9 static const char rcsid[] __attribute__((used)) =
"$Id: Port.cpp 1901 2017-06-24 20:03:54Z sella $";
12 #include "PortException.h"
13 #include "../util/String.h"
15 #include <sys/socket.h>
21 #define HASH_ALGO_INT1
24 struct sockaddr_storage *ss;
26 struct sockaddr_in *sa_in;
27 struct sockaddr_in6 *sa_in6;
30 using namespace sella::net;
31 using namespace sella::util;
33 Port::Port(
const std::string &service,
int protocol)
throw (PortException) :
40 if (this->parseUDPPreferred(this->port, this->protocol, service) ==
false) {
41 THROW(PortException,
"unable to parse port: '%s' does not represent valid UDP or TCP port", service.c_str());
46 if (this->parseUDPRequired(this->port, this->protocol, service) ==
false) {
47 THROW(PortException,
"unable to parse port: '%s' does not represent valid UDP port", service.c_str());
52 if (this->parseTCPPreferred(this->port, this->protocol, service) ==
false) {
53 THROW(PortException,
"unable to parse port: '%s' does not represent valid TCP or UDP port", service.c_str());
58 if (this->parseTCPRequired(this->port, this->protocol, service) ==
false) {
59 THROW(PortException,
"unable to parse port: '%s' does not represent valid TCP port", service.c_str());
64 THROW(PortException,
"unable to parse port: unknown protocol supplied for port '%s'", service.c_str());
68 Port::Port(uint16_t port,
int protocol)
throw (PortException) :
75 this->protocol = UDPProtocol;
80 this->protocol = TCPProtocol;
84 THROW(PortException,
"unable to parse port: unknown protocol supplied for port '%d'", protocol);
88 Port::Port(
const struct sockaddr_storage *ss,
int protocol)
throw (PortException) :
93 u.ss = (
struct sockaddr_storage*) ss;
96 THROW(PortException,
"passed sockaddr_storage is null");
99 port = ntohs(u.sa_in->sin_port);
104 this->protocol = UDPProtocol;
109 this->protocol = TCPProtocol;
113 THROW(PortException,
"unable to parse port: unknown protocol supplied for port '%d'", protocol);
117 Port::Port(
const struct sockaddr *sa,
int protocol)
throw (PortException) :
122 u.sa = (
struct sockaddr*) sa;
125 THROW(PortException,
"passed sockaddr is null");
128 port = ntohs(u.sa_in->sin_port);
133 this->protocol = UDPProtocol;
138 this->protocol = TCPProtocol;
142 THROW(PortException,
"unable to parse port: unknown protocol supplied for port '%d'", protocol);
146 Port::Port(
const Port &other)
throw () :
148 protocol(other.protocol),
149 scache(other.scache),
153 Port::Port(
const Port &&other) throw () :
155 protocol(other.protocol),
156 scache(std::move(other.scache)),
160 Port::~Port() throw () { }
162 Port& Port::operator=(
const Port &other)
throw () {
163 if (
this != &other) {
164 this->port = other.port;
165 this->protocol = other.protocol;
166 this->scache= other.scache;
167 this->hcache = other.hcache;
173 Port& Port::operator=(
const Port &&other) throw () {
174 if (
this != &other) {
175 this->port = other.port;
176 this->protocol = other.protocol;
177 this->scache= std::move(other.scache);
178 this->hcache = other.hcache;
184 bool Port::operator == (
const Port &other)
const throw () {
185 return (this->port == other.port) ? ((this->protocol == other.protocol) ?
true :
false) :
false;
188 bool Port::operator != (
const Port &other)
const throw () {
189 return !(*
this == other);
192 bool Port::operator >= (
const Port &other)
const throw () {
193 return (this->port < other.port) ?
false : ((this->port > other.port) ?
true : (this->protocol >= other.protocol) ?
true :
false);
196 bool Port::operator <= (
const Port &other)
const throw () {
197 return (this->port > other.port) ?
false : ((this->port < other.port) ?
true : (this->protocol <= other.protocol) ?
true :
false);
200 bool Port::operator > (
const Port &other)
const throw () {
201 return (this->port > other.port) ?
true : ((this->port < other.port) ?
false : (this->protocol > other.protocol) ?
true :
false);
204 bool Port::operator < (
const Port &other)
const throw () {
205 return (this->port < other.port) ?
true : ((this->port > other.port) ?
false : (this->protocol < other.protocol) ?
true :
false);
208 uint16_t Port::get(
void)
const throw () {
212 uint16_t Port::getPort(
void)
const throw () {
216 int Port::getProtocol(
void)
const throw () {
217 return this->protocol;
220 const std::string& Port::str(
void)
const throw () {
221 if (scache.empty()) {
222 scache = String::itoa(this->port);
228 const char* Port::c_str(
void)
const throw () {
229 return str().c_str();
232 uint32_t Port::getU32(
void)
const throw () {
233 return (port | (port << 16)) ^ 0xB4B4D2D2;
236 uint32_t Port::getHash(
void)
const throw () {
241 #if defined HASH_ALGO_INT1
242 uint32_t k = getU32();
244 hcache = ((k & 0xF0F0F0F0) >> 4) | ((k & 0x0F0F0F0F) << 4);
245 #elif defined HASH_ALGO_INT2
246 uint32_t k = getU32();
248 hcache = (k<<16)^(k>>16)^k;
249 #elif defined HASH_ALGO_INT3
252 #error No hash algo selected.
258 bool Port::empty(
void)
const throw () {
262 void Port::clear(
void) throw () {
269 const Port::shared Port::shared_ptr(
const std::string &service,
int protocol)
throw (PortException) {
270 return std::make_shared<Port>(service, protocol);
273 const Port::shared Port::shared_ptr(uint16_t port,
int protocol)
throw (PortException) {
274 return std::make_shared<Port>(port, protocol);
277 const Port::shared Port::shared_ptr(
const struct sockaddr_storage *ss,
int protocol)
throw (PortException) {
278 return std::make_shared<Port>(ss, protocol);
281 const Port::shared Port::shared_ptr(
const struct sockaddr *sa,
int protocol)
throw (PortException) {
282 return std::make_shared<Port>(sa, protocol);
285 bool Port::parseUDPRequired(uint16_t &port,
int &protocol,
const std::string &service)
throw () {
286 struct servent entry_buf, *entry;
287 char buf[4096], *end;
289 port = strtol(service.c_str(), &end, 10);
291 if ((*end) !=
'\0') {
292 if (getservbyname_r(service.c_str(),
"udp", &entry_buf, buf,
sizeof(buf), &entry) == 0) {
293 protocol = UDPProtocol;
294 port = entry->s_port;
302 bool Port::parseTCPRequired(uint16_t &port,
int &protocol,
const std::string &service)
throw () {
303 struct servent entry_buf, *entry;
304 char buf[4096], *end;
306 port = strtol(service.c_str(), &end, 10);
308 if ((*end) !=
'\0') {
309 if (getservbyname_r(service.c_str(),
"tcp", &entry_buf, buf,
sizeof(buf), &entry) == 0) {
310 protocol = UDPProtocol;
311 port = entry->s_port;
319 bool Port::parseUDPPreferred(uint16_t &port,
int &protocol,
const std::string &service)
throw () {
320 if (this->parseUDPRequired(port, protocol, service) ==
false) {
321 return this->parseTCPRequired(port, protocol, service);
326 bool Port::parseTCPPreferred(uint16_t &port,
int &protocol,
const std::string &service)
throw () {
327 if (this->parseTCPRequired(port, protocol, service) ==
false) {
328 return this->parseUDPRequired(port, protocol, service);