Skip to content

Feature: New Class MacAddress similar to IPAddress #9304

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0856254
Added new classes MacAddress and MacAddress8
mrengineer7777 Apr 29, 2022
0e84fad
Update MacAddress8.h
mrengineer7777 May 3, 2022
8b6fdba
Added Printable, constructor and extra operators
SuGlider May 5, 2022
2ed5805
Added construtor and Printable
SuGlider May 5, 2022
37d7e19
Fixes include Printable
SuGlider May 5, 2022
45da7ea
Update MacAddress.cpp
SuGlider May 5, 2022
d9cb093
Update MacAddress.h
SuGlider May 5, 2022
9e03911
Update MacAddress.cpp
SuGlider May 5, 2022
450c4dd
Added Printable
SuGlider May 5, 2022
dca7e22
Added Printble and some more operators
SuGlider May 5, 2022
a6330b2
Cleanup and bounds checking
mrengineer7777 May 6, 2022
d05cd87
Fixed printTo
mrengineer7777 May 6, 2022
6dbd662
Merge @mrengineer7777s changes from 'mrengineer7777:patch-2' into fea…
P-R-O-C-H-Y Feb 28, 2024
ae78e5e
feat(MAC): Rework API to support both 6+8 bytes MacAddress
P-R-O-C-H-Y Feb 28, 2024
8abadb1
feat(MAC): Remove MacAddress8.h file
P-R-O-C-H-Y Feb 28, 2024
72e39b8
fix(MAC): Remove comment + reorder lines
P-R-O-C-H-Y Feb 28, 2024
fc4a0a3
Merge branch 'master' into feature/mac-adress-refactor
P-R-O-C-H-Y Feb 28, 2024
b3fec39
Update toString function with single buf and return
P-R-O-C-H-Y Feb 29, 2024
dc78883
Merge branch 'feature/mac-adress-refactor' of https://github.com/P-R-…
P-R-O-C-H-Y Feb 29, 2024
08b6c12
Fix buffer size for toString
P-R-O-C-H-Y Feb 29, 2024
7a627f2
Merge branch 'master' into feature/mac-adress-refactor
lucasssvaz Feb 29, 2024
2b18f32
Merge branch 'master' into feature/mac-adress-refactor
P-R-O-C-H-Y Mar 4, 2024
df8c70c
Merge branch 'master' into feature/mac-adress-refactor
P-R-O-C-H-Y Mar 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ set(CORE_SRCS
cores/esp32/IPAddress.cpp
cores/esp32/libb64/cdecode.c
cores/esp32/libb64/cencode.c
cores/esp32/MacAddress.cpp
cores/esp32/main.cpp
cores/esp32/MD5Builder.cpp
cores/esp32/Print.cpp
Expand Down
229 changes: 229 additions & 0 deletions cores/esp32/MacAddress.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
#include <MacAddress.h>
#include <stdio.h>
#include <Print.h>

//Default constructor, blank mac address.
MacAddress::MacAddress() : MacAddress(MAC6){}

MacAddress::MacAddress(MACType mac_type){
_type = mac_type;
memset(_mac.bytes, 0, sizeof(_mac.bytes));
}
MacAddress::MacAddress(MACType mac_type, uint64_t mac) {
_type = mac_type;
_mac.val = mac;
}

MacAddress::MacAddress(MACType mac_type, const uint8_t *macbytearray) {
_type = mac_type;
memset(_mac.bytes, 0, sizeof(_mac.bytes));
if(_type == MAC6) {
memcpy(_mac.bytes, macbytearray, 6);
} else {
memcpy(_mac.bytes, macbytearray, 8);
}
}

MacAddress::MacAddress(const char *macstr){
fromString(macstr);
}

MacAddress::MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6) {
_type = MAC6;
memset(_mac.bytes, 0, sizeof(_mac.bytes));
_mac.bytes[0] = b1;
_mac.bytes[1] = b2;
_mac.bytes[2] = b3;
_mac.bytes[3] = b4;
_mac.bytes[4] = b5;
_mac.bytes[5] = b6;
}

MacAddress::MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6, uint8_t b7, uint8_t b8) {
_type = MAC8;
_mac.bytes[0] = b1;
_mac.bytes[1] = b2;
_mac.bytes[2] = b3;
_mac.bytes[3] = b4;
_mac.bytes[4] = b5;
_mac.bytes[5] = b6;
_mac.bytes[6] = b7;
_mac.bytes[7] = b8;
}

//Parse user entered string into MAC address
bool MacAddress::fromString(const char *buf) {
if(strlen(buf) == 17) {
return fromString6(buf);
} else if(strlen(buf) == 23) {
return fromString8(buf);
}
return false;
}

//Parse user entered string into MAC address
bool MacAddress::fromString6(const char *buf) {
char cs[18];
char *token;
char *next; //Unused but required
int i;

strncpy(cs, buf, sizeof(cs)); //strtok modifies the buffer: copy to working buffer.

for(i = 0; i < 6; i++) {
token = strtok((i==0) ? cs : NULL, ":"); //Find first or next token
if(!token) { //No more tokens found
return false;
}
_mac.bytes[i] = strtol(token, &next, 16);
}
_type = MAC6;
return true;
}

bool MacAddress::fromString8(const char *buf) {
char cs[24];
char *token;
char *next; //Unused but required
int i;

strncpy(cs, buf, sizeof(cs)); //strtok modifies the buffer: copy to working buffer.

for(i = 0; i < 8; i++) {
token = strtok((i==0) ? cs : NULL, ":"); //Find first or next token
if(!token) { //No more tokens found
return false;
}
_mac.bytes[i] = strtol(token, &next, 16);
}
_type = MAC8;
return true;
}

//Copy MAC into byte array
void MacAddress::toBytes(uint8_t *buf) {
if(_type == MAC6) {
memcpy(buf, _mac.bytes, 6);
} else {
memcpy(buf, _mac.bytes, sizeof(_mac.bytes));
}
}

//Print MAC address into a C string.
//MAC: Buffer must be at least 18 chars
int MacAddress::toString(char *buf) {
if(_type == MAC6) {
return sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
_mac.bytes[0], _mac.bytes[1], _mac.bytes[2],
_mac.bytes[3], _mac.bytes[4], _mac.bytes[5]);
} else {
return sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
_mac.bytes[0], _mac.bytes[1], _mac.bytes[2],
_mac.bytes[3], _mac.bytes[4], _mac.bytes[5],
_mac.bytes[6], _mac.bytes[7]);
}
}

String MacAddress::toString() const {
uint8_t bytes = (_type == MAC6) ? 18 : 24;
char buf[bytes];
if(_type == MAC6) {
snprintf(buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X",
_mac.bytes[0], _mac.bytes[1], _mac.bytes[2],
_mac.bytes[3], _mac.bytes[4], _mac.bytes[5]);
} else {
snprintf(buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
_mac.bytes[0], _mac.bytes[1], _mac.bytes[2],
_mac.bytes[3], _mac.bytes[4], _mac.bytes[5],
_mac.bytes[6], _mac.bytes[7]);
}
return String(buf);
}

uint64_t MacAddress::Value() {
return _mac.val;
}

//Allow getting individual octets of the address. e.g. uint8_t b0 = ma[0];
uint8_t MacAddress::operator[](int index) const {
index = EnforceIndexBounds(index);
return _mac.bytes[index];
}

//Allow setting individual octets of the address. e.g. ma[2] = 255;
uint8_t& MacAddress::operator[](int index) {
index = EnforceIndexBounds(index);
return _mac.bytes[index];
}

//Overloaded copy operator: init MacAddress object from byte array
MacAddress& MacAddress::operator=(const uint8_t *macbytearray) {
// 6-bytes MacAddress only
_type = MAC6;
memset(_mac.bytes, 0, sizeof(_mac.bytes));
memcpy(_mac.bytes, macbytearray, 6);
return *this;
}

//Overloaded copy operator: init MacAddress object from uint64_t
MacAddress& MacAddress::operator=(uint64_t macval) {
// 6-bytes MacAddress only
_type = MAC6;
_mac.val = macval;
return *this;
}

//Compare class to byte array
bool MacAddress::operator==(const uint8_t *macbytearray) const {
return !memcmp(_mac.bytes, macbytearray, 6);
}

//Allow comparing value of two classes
bool MacAddress::operator==(const MacAddress& mac2) const {
return _mac.val == mac2._mac.val;
}

//Type converter object to uint64_t [same as .Value()]
MacAddress::operator uint64_t() const {
return _mac.val;
}

//Type converter object to read only pointer to mac bytes. e.g. const uint8_t *ip_8 = ma;
MacAddress::operator const uint8_t*() const {
return _mac.bytes;
}

//Type converter object to read only pointer to mac value. e.g. const uint32_t *ip_64 = ma;
MacAddress::operator const uint64_t*() const {
return &_mac.val;
}

size_t MacAddress::printTo(Print& p) const
{
uint8_t bytes = (_type == MAC6) ? 6 : 8;
size_t n = 0;
for(int i = 0; i < bytes; i++) {
if(i){
n += p.print(':');
}
n += p.printf("%02X", _mac.bytes[i]);
}
return n;
}

//Bounds checking
int MacAddress::EnforceIndexBounds(int i) const {
if(i < 0) {
return 0;
}
if(_type == MAC6) {
if(i >= 6) {
return 5;
}
} else {
if(i >= 8) {
return 7;
}
}
return i;
}
101 changes: 101 additions & 0 deletions cores/esp32/MacAddress.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
//-----------------------------------------------------------------------------
// MacAddress.h - class to make it easier to handle BSSID and MAC addresses.
//
// Copyright 2022 David McCurley
// Modified by Espressif Systems 2024
//
// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//-----------------------------------------------------------------------------

#ifndef MacAddress_h
#define MacAddress_h

#include <stdint.h>
#include <WString.h>
#include <Printable.h>

enum MACType {
MAC6,
MAC8
};

// A class to make it easier to handle and pass around MAC addresses, supporting both 6-byte and 8-byte MAC addresses.
class MacAddress : public Printable {
private:
union {
uint8_t bytes[8];
uint64_t val;
} _mac;
MACType _type;

public:
//Default MAC6
MacAddress();

MacAddress(MACType mac_type);
MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6);
MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6, uint8_t b7, uint8_t b8);

MacAddress(MACType mac_type, uint64_t mac);
MacAddress(MACType mac_type, const uint8_t *macbytearray);

//Default MAC6
MacAddress(uint64_t mac) : MacAddress(MAC6, mac) {}
MacAddress(const uint8_t *macbytearray) : MacAddress(MAC6, macbytearray) {}

MacAddress(const char *macstr);

virtual ~MacAddress() {}

bool fromString(const char *buf);
bool fromString(const String &macstr) { return fromString(macstr.c_str()); }

void toBytes(uint8_t *buf);
int toString(char *buf);
String toString() const;
uint64_t Value();

uint8_t operator[](int index) const;
uint8_t& operator[](int index);

//MAC6 only
MacAddress& operator=(const uint8_t *macbytearray);
MacAddress& operator=(uint64_t macval);

bool operator==(const uint8_t *macbytearray) const;
bool operator==(const MacAddress& mac2) const;
operator uint64_t() const;
operator const uint8_t*() const;
operator const uint64_t*() const;

virtual size_t printTo(Print& p) const;

// future use in Arduino Networking
/*
friend class EthernetClass;
friend class UDP;
friend class Client;
friend class Server;
friend class DhcpClass;
friend class DNSClient;
*/

protected:
bool fromString6(const char *buf);
bool fromString8(const char *buf);

private:
int EnforceIndexBounds(int i) const;
};

#endif