00001
00002
00003
00004
00005
00006
00007
00008
00009 static const char rcsid[] __attribute__((used)) = "$Id: Port.cpp 1197 2014-10-14 22:26:11Z sella $";
00010
00011 #include "Port.h"
00012 #include "PortException.h"
00013
00014 #include <sys/socket.h>
00015 #include <string.h>
00016 #include <stdint.h>
00017 #include <stdlib.h>
00018 #include <netdb.h>
00019
00020 #define HASH_ALGO_INT1
00021
00022 union __sockaddr_union {
00023 struct sockaddr_storage *ss;
00024 struct sockaddr *sa;
00025 struct sockaddr_in *sa_in;
00026 struct sockaddr_in6 *sa_in6;
00027 };
00028
00029 using namespace sella::net;
00030
00031 Port::Port(const std::string &service, int protocol) throw (PortException) :
00032 port(0),
00033 protocol(0),
00034 hcache(0)
00035 {
00036 switch (protocol) {
00037 case UDPPreferred:
00038 if (this->parseUDPPreferred(this->port, this->protocol, service) == false) {
00039 THROW(PortException, "unable to parse port: '%s' does not represent valid UDP or TCP port", service.c_str());
00040 }
00041 break;
00042
00043 case UDPRequired:
00044 if (this->parseUDPRequired(this->port, this->protocol, service) == false) {
00045 THROW(PortException, "unable to parse port: '%s' does not represent valid UDP port", service.c_str());
00046 }
00047 break;
00048
00049 case TCPPreferred:
00050 if (this->parseTCPPreferred(this->port, this->protocol, service) == false) {
00051 THROW(PortException, "unable to parse port: '%s' does not represent valid TCP or UDP port", service.c_str());
00052 }
00053 break;
00054
00055 case TCPRequired:
00056 if (this->parseTCPRequired(this->port, this->protocol, service) == false) {
00057 THROW(PortException, "unable to parse port: '%s' does not represent valid TCP port", service.c_str());
00058 }
00059 break;
00060
00061 default:
00062 THROW(PortException, "unable to parse port: unknown protocol supplied for port '%s'", service.c_str());
00063 }
00064 }
00065
00066 Port::Port(uint16_t port, int protocol) throw (PortException) :
00067 port(port),
00068 protocol(0)
00069 {
00070 switch (protocol) {
00071 case UDPPreferred:
00072 case UDPRequired:
00073 this->protocol = UDPProtocol;
00074 break;
00075
00076 case TCPPreferred:
00077 case TCPRequired:
00078 this->protocol = TCPProtocol;
00079 break;
00080
00081 default:
00082 THROW(PortException, "unable to parse port: unknown protocol supplied for port '%d'", protocol);
00083 }
00084 }
00085
00086 Port::Port(const struct sockaddr_storage *ss, int protocol) throw (PortException) :
00087 protocol(0),
00088 hcache(0)
00089 {
00090 union __sockaddr_union u;
00091 u.ss = (struct sockaddr_storage*) ss;
00092
00093 if (ss == NULL) {
00094 THROW(PortException, "passed sockaddr_storage is null");
00095 }
00096
00097 port = ntohs(u.sa_in->sin_port);
00098
00099 switch (protocol) {
00100 case UDPPreferred:
00101 case UDPRequired:
00102 this->protocol = UDPProtocol;
00103 break;
00104
00105 case TCPPreferred:
00106 case TCPRequired:
00107 this->protocol = TCPProtocol;
00108 break;
00109
00110 default:
00111 THROW(PortException, "unable to parse port: unknown protocol supplied for port '%d'", protocol);
00112 }
00113 }
00114
00115 Port::Port(const struct sockaddr *sa, int protocol) throw (PortException) :
00116 protocol(0),
00117 hcache(0)
00118 {
00119 union __sockaddr_union u;
00120 u.sa = (struct sockaddr*) sa;
00121
00122 if (sa == NULL) {
00123 THROW(PortException, "passed sockaddr is null");
00124 }
00125
00126 port = ntohs(u.sa_in->sin_port);
00127
00128 switch (protocol) {
00129 case UDPPreferred:
00130 case UDPRequired:
00131 this->protocol = UDPProtocol;
00132 break;
00133
00134 case TCPPreferred:
00135 case TCPRequired:
00136 this->protocol = TCPProtocol;
00137 break;
00138
00139 default:
00140 THROW(PortException, "unable to parse port: unknown protocol supplied for port '%d'", protocol);
00141 }
00142 }
00143
00144 Port::Port(const Port &other) throw () :
00145 port(other.port),
00146 protocol(other.protocol),
00147 scache(other.scache),
00148 hcache(other.hcache)
00149 { }
00150
00151 Port::Port(const Port &&other) throw () :
00152 port(other.port),
00153 protocol(other.protocol),
00154 scache(std::move(other.scache)),
00155 hcache(other.hcache)
00156 { }
00157
00158 Port::~Port() throw () { }
00159
00160 Port& Port::operator=(const Port &other) throw () {
00161 if (this != &other) {
00162 this->port = other.port;
00163 this->protocol = other.protocol;
00164 this->scache= other.scache;
00165 this->hcache = other.hcache;
00166 }
00167
00168 return *this;
00169 }
00170
00171 Port& Port::operator=(const Port &&other) throw () {
00172 if (this != &other) {
00173 this->port = other.port;
00174 this->protocol = other.protocol;
00175 this->scache= std::move(other.scache);
00176 this->hcache = other.hcache;
00177 }
00178
00179 return *this;
00180 }
00181
00182 bool Port::operator == (const Port &other) const throw () {
00183 return (this->port == other.port) ? ((this->protocol == other.protocol) ? true : false) : false;
00184 }
00185
00186 bool Port::operator != (const Port &other) const throw () {
00187 return !(*this == other);
00188 }
00189
00190 bool Port::operator >= (const Port &other) const throw () {
00191 return (this->port < other.port) ? false : ((this->port > other.port) ? true : (this->protocol >= other.protocol) ? true : false);
00192 }
00193
00194 bool Port::operator <= (const Port &other) const throw () {
00195 return (this->port > other.port) ? false : ((this->port < other.port) ? true : (this->protocol <= other.protocol) ? true : false);
00196 }
00197
00198 bool Port::operator > (const Port &other) const throw () {
00199 return (this->port > other.port) ? true : ((this->port < other.port) ? false : (this->protocol > other.protocol) ? true : false);
00200 }
00201
00202 bool Port::operator < (const Port &other) const throw () {
00203 return (this->port < other.port) ? true : ((this->port > other.port) ? false : (this->protocol < other.protocol) ? true : false);
00204 }
00205
00206 uint16_t Port::get(void) const throw () {
00207 return this->port;
00208 }
00209
00210 uint16_t Port::getPort(void) const throw () {
00211 return this->port;
00212 }
00213
00214 int Port::getProtocol(void) const throw () {
00215 return this->protocol;
00216 }
00217
00218 const std::string& Port::str(void) const throw () {
00219 char buf[31];
00220
00221 if (scache.empty()) {
00222 snprintf(buf, sizeof(buf), "%u", this->port);
00223 scache = buf;
00224 }
00225
00226 return scache;
00227 }
00228
00229 const char* Port::c_str(void) const throw () {
00230 return str().c_str();
00231 }
00232
00233 uint32_t Port::getU32(void) const throw () {
00234 return (port | (port << 16)) ^ 0xB4B4D2D2;
00235 }
00236
00237 uint32_t Port::getHash(void) const throw () {
00238 if (hcache != 0) {
00239 return hcache;
00240 }
00241
00242 #if defined HASH_ALGO_INT1
00243 uint32_t k = getU32();
00244
00245 hcache = ((k & 0xF0F0F0F0) >> 4) | ((k & 0x0F0F0F0F) << 4);
00246 #elif defined HASH_ALGO_INT2
00247 uint32_t k = getU32();
00248
00249 hcache = (k<<16)^(k>>16)^k;
00250 #elif defined HASH_ALGO_INT3
00251 hcache = getU32();
00252 #else
00253 #error No hash algo selected.
00254 #endif
00255
00256 return hcache;
00257 }
00258
00259 bool Port::empty(void) const throw () {
00260 return (port == 0);
00261 }
00262
00263 void Port::clear(void) throw () {
00264 port = 0;
00265 protocol = 0;
00266 scache.clear();
00267 hcache = 0;
00268 }
00269
00270 const Port::shared Port::shared_ptr(const std::string &service, int protocol) throw (PortException) {
00271 return std::make_shared<Port>(service, protocol);
00272 }
00273
00274 const Port::shared Port::shared_ptr(uint16_t port, int protocol) throw (PortException) {
00275 return std::make_shared<Port>(port, protocol);
00276 }
00277
00278 const Port::shared Port::shared_ptr(const struct sockaddr_storage *ss, int protocol) throw (PortException) {
00279 return std::make_shared<Port>(ss, protocol);
00280 }
00281
00282 const Port::shared Port::shared_ptr(const struct sockaddr *sa, int protocol) throw (PortException) {
00283 return std::make_shared<Port>(sa, protocol);
00284 }
00285
00286 bool Port::parseUDPRequired(uint16_t &port, int &protocol, const std::string &service) throw () {
00287 struct servent entry_buf, *entry;
00288 char buf[4096], *end;
00289
00290 port = strtol(service.c_str(), &end, 10);
00291
00292 if ((*end) != '\0') {
00293 if (getservbyname_r(service.c_str(), "udp", &entry_buf, buf, sizeof(buf), &entry) == 0) {
00294 protocol = UDPProtocol;
00295 port = entry->s_port;
00296 } else {
00297 return false;
00298 }
00299 }
00300 return true;
00301 }
00302
00303 bool Port::parseTCPRequired(uint16_t &port, int &protocol, const std::string &service) throw () {
00304 struct servent entry_buf, *entry;
00305 char buf[4096], *end;
00306
00307 port = strtol(service.c_str(), &end, 10);
00308
00309 if ((*end) != '\0') {
00310 if (getservbyname_r(service.c_str(), "tcp", &entry_buf, buf, sizeof(buf), &entry) == 0) {
00311 protocol = UDPProtocol;
00312 port = entry->s_port;
00313 } else {
00314 return false;
00315 }
00316 }
00317 return true;
00318 }
00319
00320 bool Port::parseUDPPreferred(uint16_t &port, int &protocol, const std::string &service) throw () {
00321 if (this->parseUDPRequired(port, protocol, service) == false) {
00322 return this->parseTCPRequired(port, protocol, service);
00323 }
00324 return true;
00325 }
00326
00327 bool Port::parseTCPPreferred(uint16_t &port, int &protocol, const std::string &service) throw () {
00328 if (this->parseTCPRequired(port, protocol, service) == false) {
00329 return this->parseUDPRequired(port, protocol, service);
00330 }
00331 return true;
00332 }
00333
00334
00335
00336