blob: c128d37ca22dd7a94856424a6abd0a9e81912d26 [file] [log] [blame]
Junxiao Shi77dcadd2014-10-05 14:40:54 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyevaf99f462015-01-19 21:43:09 -08003 * Copyright (c) 2013-2015 Regents of the University of California.
Junxiao Shi77dcadd2014-10-05 14:40:54 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "ethernet.hpp"
23
Davide Pesaventodfb8a612014-11-25 19:14:11 +010024#include <boost/functional/hash.hpp>
25
Alexander Afanasyev52ec6672015-01-22 12:29:02 -080026#include <stdio.h>
Davide Pesaventodfe9c6b2014-08-25 21:17:10 +020027#include <ostream>
Junxiao Shi77dcadd2014-10-05 14:40:54 -070028
29namespace ndn {
30namespace util {
31namespace ethernet {
32
Junxiao Shi77dcadd2014-10-05 14:40:54 -070033Address::Address()
34{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010035 fill(0);
Junxiao Shi77dcadd2014-10-05 14:40:54 -070036}
37
38Address::Address(uint8_t a1, uint8_t a2, uint8_t a3, uint8_t a4, uint8_t a5, uint8_t a6)
39{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010040 data()[0] = a1;
41 data()[1] = a2;
42 data()[2] = a3;
43 data()[3] = a4;
44 data()[4] = a5;
45 data()[5] = a6;
Junxiao Shi77dcadd2014-10-05 14:40:54 -070046}
47
48Address::Address(const uint8_t octets[])
49{
50 std::copy(octets, octets + size(), begin());
51}
52
Junxiao Shi77dcadd2014-10-05 14:40:54 -070053bool
54Address::isBroadcast() const
55{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010056 return *this == getBroadcastAddress();
Junxiao Shi77dcadd2014-10-05 14:40:54 -070057}
58
59bool
60Address::isMulticast() const
61{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010062 return (at(0) & 1) != 0;
Junxiao Shi77dcadd2014-10-05 14:40:54 -070063}
64
65bool
66Address::isNull() const
67{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010068 return *this == Address();
Junxiao Shi77dcadd2014-10-05 14:40:54 -070069}
70
71std::string
72Address::toString(char sep) const
73{
74 char s[18]; // 12 digits + 5 separators + null terminator
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010075
Alexander Afanasyev52ec6672015-01-22 12:29:02 -080076 // - apparently gcc-4.6 does not support the 'hh' type modifier
77 // - std::snprintf not found in some environments
78 // http://redmine.named-data.net/issues/2299 for more information
79 snprintf(s, sizeof(s), "%02x%c%02x%c%02x%c%02x%c%02x%c%02x",
80 at(0), sep, at(1), sep, at(2), sep, at(3), sep, at(4), sep, at(5));
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010081
Junxiao Shi77dcadd2014-10-05 14:40:54 -070082 return std::string(s);
83}
84
85Address
86Address::fromString(const std::string& str)
87{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010088 Address a;
89 unsigned short temp[a.size()];
Junxiao Shi77dcadd2014-10-05 14:40:54 -070090 char sep[5][2]; // 5 * (1 separator char + 1 null terminator)
91 int n = 0; // num of chars read from the input string
92
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010093 // apparently gcc-4.6 does not support the 'hh' type modifier
94 int ret = std::sscanf(str.c_str(), "%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%n",
95 &temp[0], &sep[0][0], &temp[1], &sep[1][0], &temp[2], &sep[2][0],
96 &temp[3], &sep[3][0], &temp[4], &sep[4][0], &temp[5], &n);
Junxiao Shi77dcadd2014-10-05 14:40:54 -070097
98 if (ret < 11 || static_cast<size_t>(n) != str.length())
99 return Address();
100
Davide Pesavento51dc2ef2014-11-04 20:04:19 +0100101 for (size_t i = 0; i < a.size(); ++i)
Junxiao Shi77dcadd2014-10-05 14:40:54 -0700102 {
103 // check that all separators are actually the same char (: or -)
104 if (i < 5 && sep[i][0] != sep[0][0])
105 return Address();
106
107 // check that each value fits into a uint8_t
108 if (temp[i] > 0xFF)
109 return Address();
110
111 a[i] = static_cast<uint8_t>(temp[i]);
112 }
113
114 return a;
115}
116
Davide Pesavento51dc2ef2014-11-04 20:04:19 +0100117Address
118getBroadcastAddress()
119{
120 return { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
121}
122
123Address
124getDefaultMulticastAddress()
125{
126 return { 0x01, 0x00, 0x5E, 0x00, 0x17, 0xAA };
127}
128
Junxiao Shi77dcadd2014-10-05 14:40:54 -0700129std::ostream&
130operator<<(std::ostream& o, const Address& a)
131{
132 return o << a.toString();
133}
134
135} // namespace ethernet
136} // namespace util
137} // namespace ndn
Davide Pesaventodfb8a612014-11-25 19:14:11 +0100138
139
140using ndn::util::ethernet::Address;
141
142std::size_t
143std::hash<Address>::operator()(const Address& a) const noexcept
144{
145 return boost::hash_range(a.cbegin(), a.cend());
146}