diff options
author | Determinant <ted.sybil@gmail.com> | 2018-06-26 12:58:54 -0400 |
---|---|---|
committer | Determinant <ted.sybil@gmail.com> | 2018-06-26 12:58:54 -0400 |
commit | 5c3b39340d365f5ff37a79424956591e87b44816 (patch) | |
tree | 45fc59c19ed95c44bacbbe59396d8bc1b25872dd /include/salticidae/netaddr.h |
init
Diffstat (limited to 'include/salticidae/netaddr.h')
-rw-r--r-- | include/salticidae/netaddr.h | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/include/salticidae/netaddr.h b/include/salticidae/netaddr.h new file mode 100644 index 0000000..c166c3a --- /dev/null +++ b/include/salticidae/netaddr.h @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2018 Cornell University. + * + * Author: Ted Yin <tederminant@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _SALTICIDAE_NETADDR_H +#define _SALTICIDAE_NETADDR_H + +#include <string> +#include <cstring> +#include <cstdint> +#include <arpa/inet.h> + +#include "salticidae/util.h" + +namespace salticidae { + +/* TODO: IPv6 support */ + +struct NetAddr { + uint32_t ip; + uint16_t port; + /* construct from human-readable format */ + NetAddr(): ip(0), port(0) {} + + NetAddr(uint32_t ip, uint16_t port): ip(ip), port(port) {} + + NetAddr(const std::string &_addr, uint16_t _port) { + set_by_ip_port(_addr, _port); + } + + void set_by_ip_port(const std::string &_addr, uint16_t _port) { + struct hostent *h; + if ((h = gethostbyname(_addr.c_str())) == nullptr) + throw SalticidaeError("gethostbyname failed"); + memmove(&ip, h->h_addr_list[0], sizeof(in_addr_t)); + port = htons(_port); + } + + NetAddr(const std::string &ip_port_addr) { + size_t pos = ip_port_addr.find(":"); + if (pos == std::string::npos) + throw SalticidaeError("invalid port format"); + std::string ip_str = ip_port_addr.substr(0, pos); + std::string port_str = ip_port_addr.substr(pos + 1); + long port; + try { + port = std::stol(port_str.c_str()); + } catch (std::logic_error) { + throw SalticidaeError("invalid port format"); + } + if (port < 0) + throw SalticidaeError("negative port number"); + if (port > 0xffff) + throw SalticidaeError("port number greater than 0xffff"); + set_by_ip_port(ip_str, (uint16_t)port); + } + /* construct from unix socket format */ + NetAddr(const struct sockaddr_in *addr_sock) { + ip = addr_sock->sin_addr.s_addr; + port = addr_sock->sin_port; + } + + bool operator==(const NetAddr &other) const { + return ip == other.ip && port == other.port; + } + + operator std::string() const { + struct in_addr in; + in.s_addr = ip; + return "<NetAddr " + std::string(inet_ntoa(in)) + + ":" + std::to_string(ntohs(port)) + ">"; + } + + bool is_null() const { return ip == 0 && port == 0; } +}; + +} + +namespace std { + template <> + struct hash<salticidae::NetAddr> { + size_t operator()(const salticidae::NetAddr &k) const { + return k.ip ^ k.port; + } + }; + + template <> + struct hash<const salticidae::NetAddr> { + size_t operator()(const salticidae::NetAddr &k) const { + return k.ip ^ k.port; + } + }; +} + +#endif |