/* * Copyright (C) 2001-2004 Peter J Jones (pjones@pmade.org) * All Rights Reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name of the Author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /** @file * This file contains the implementation of the Netxx::Peer class. **/ // common header #include "common.h" // Netxx includes #include // standard includes #include #include #include #include //#################################################################### namespace { const unsigned int const_max_sockaddr_size = 128; } //########################################################################### Netxx::Peer::Peer (void) : okay_(false), port_(0), socketfd_(-1), sockaddr_(0), sockaddr_size_(0) { } //########################################################################### Netxx::Peer::Peer (const char *addr, port_type port, void *saddr, size_type saddr_size) : okay_(true), addr_(addr), port_(port), socketfd_(-1), sockaddr_size_(saddr_size) { // TODO should this be sockaddr_ = new char[saddr_size];? sockaddr_ = std::malloc(saddr_size); if (!sockaddr_) throw std::bad_alloc(); std::memcpy(sockaddr_, saddr, saddr_size); } //########################################################################### Netxx::Peer::Peer (socket_type socketfd, void *saddr, size_type saddr_size) : okay_(true), port_(0), socketfd_(socketfd), sockaddr_size_(saddr_size) { // TODO should this be sockaddr_ = new char[saddr_size];? sockaddr_ = std::malloc(saddr_size); if (!sockaddr_) throw std::bad_alloc(); std::memcpy(sockaddr_, saddr, saddr_size); sockaddr *sa = static_cast(sockaddr_); switch (sa->sa_family) { case AF_INET: { char buffer[INET_ADDRSTRLEN]; if (inet_ntop(AF_INET, &(reinterpret_cast(sa)->sin_addr), buffer, sizeof(buffer))) { addr_ = buffer; port_ = ntohs(reinterpret_cast(sa)->sin_port); } } break; # ifndef NETXX_NO_INET6 case AF_INET6: { char buffer[INET6_ADDRSTRLEN]; if (inet_ntop(AF_INET6, &(reinterpret_cast(sa)->sin6_addr), buffer, sizeof(buffer))) { addr_ = buffer; port_ = ntohs(reinterpret_cast(sa)->sin6_port); } } break; # endif # ifndef WIN32 case AF_LOCAL: addr_ = reinterpret_cast(sa)->sun_path; break; # endif } } //########################################################################### Netxx::Peer::Peer (const Peer &other) : okay_(other.okay_), addr_(other.addr_), port_(other.port_), socketfd_(other.socketfd_), sockaddr_(0), sockaddr_size_(other.sockaddr_size_) { if (other.sockaddr_) { sockaddr_ = std::malloc(sockaddr_size_); if (!sockaddr_) throw std::bad_alloc(); std::memcpy(sockaddr_, other.sockaddr_, sockaddr_size_); } } //########################################################################### Netxx::Peer& Netxx::Peer::operator= (const Peer &other) { Peer tmp(other); swap(tmp); return *this; } //########################################################################### void Netxx::Peer::swap (Peer &other) { std::swap(okay_, other.okay_); std::swap(addr_, other.addr_); std::swap(port_, other.port_); std::swap(socketfd_, other.socketfd_); std::swap(sockaddr_, other.sockaddr_); std::swap(sockaddr_size_, other.sockaddr_size_); } //########################################################################### Netxx::Peer::~Peer (void) { if (sockaddr_) std::free(sockaddr_); } //########################################################################### const char* Netxx::Peer::get_address (void) const { return addr_.c_str(); } //########################################################################### Netxx::port_type Netxx::Peer::get_port (void) const { return port_; } //########################################################################### Netxx::port_type Netxx::Peer::get_local_port (void) const { os_socklen_type sa_size = const_max_sockaddr_size; os_socklen_ptr_type sa_size_ptr = get_socklen_ptr(sa_size); union { sockaddr sa; sockaddr_in sin; # ifndef NETXX_NO_INET6 sockaddr_in6 sin6; # endif } sau; int rc; if ( (rc = getsockname(get_socketfd(), &sau.sa, sa_size_ptr))) { throw Exception(str_error(errno)); } switch (sau.sa.sa_family) { case AF_INET: return ntohs(sau.sin.sin_port); # ifndef NETXX_NO_INET6 case AF_INET6: return ntohs(sau.sin6.sin6_port); # endif default: return 0; } } //########################################################################### Netxx::socket_type Netxx::Peer::get_socketfd (void) const { return socketfd_; } //########################################################################### Netxx::Peer::operator bool (void) const { return okay_; } //########################################################################### const void* Netxx::Peer::get_sa (void) const { return sockaddr_; } //########################################################################### Netxx::size_type Netxx::Peer::get_sa_size() const { return sockaddr_size_; } //########################################################################### namespace Netxx { //########################################################################### std::ostream& operator<< (std::ostream &stream, const Peer &peer) { const sockaddr *sa = reinterpret_cast(peer.get_sa()); if (peer) { if (sa && sa->sa_family == AF_LOCAL) { if (peer.get_address()[0] == 0) stream << "domain socket"; else stream << peer.get_address(); } else { stream << peer.get_address() << ":" << peer.get_port(); } } return stream; } //########################################################################### } // end Netxx namespace