/* $Id$ */ /* * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __PJPP_SOCK_HPP__ #define __PJPP_SOCK_HPP__ #include #include class Pj_Event_Handler; // // Base class for address. // class Pj_Addr { }; // // Internet address. // class Pj_Inet_Addr : public pj_sockaddr_in, public Pj_Addr { public: // // Get port number. // pj_uint16_t get_port_number() const { return pj_sockaddr_in_get_port(this); } // // Set port number. // void set_port_number(pj_uint16_t port) { sin_family = PJ_AF_INET; pj_sockaddr_in_set_port(this, port); } // // Get IP address. // pj_uint32_t get_ip_address() const { return pj_sockaddr_in_get_addr(this).s_addr; } // // Get address string. // const char *get_address() const { return pj_inet_ntoa(sin_addr); } // // Set IP address. // void set_ip_address(pj_uint32_t addr) { sin_family = PJ_AF_INET; pj_sockaddr_in_set_addr(this, addr); } // // Set address. // pj_status_t set_address(const pj_str_t *addr) { return pj_sockaddr_in_set_str_addr(this, addr); } // // Set address. // pj_status_t set_address(const char *addr) { pj_str_t s; return pj_sockaddr_in_set_str_addr(this, pj_cstr(&s, addr)); } // // Compare for equality. // bool operator==(const Pj_Inet_Addr &rhs) const { return sin_family == rhs.sin_family && sin_addr.s_addr == rhs.sin_addr.s_addr && sin_port == rhs.sin_port; } private: // // Dummy length used in pj_ioqueue_recvfrom() etc // friend class Pj_Event_Handler; friend class Pj_Socket; friend class Pj_Sock_Stream; friend class Pj_Sock_Dgram; int addrlen_; }; // // Socket base class. // // Note: // socket will not automatically be closed on destructor. // class Pj_Socket { public: // // Default constructor. // Pj_Socket() : sock_(PJ_INVALID_SOCKET) { } // // Initialize from a socket handle. // explicit Pj_Socket(pj_sock_t sock) : sock_(sock) { } // // Copy constructor. // Pj_Socket(const Pj_Socket &rhs) : sock_(rhs.sock_) { } // // Destructor will not close the socket. // You must call close() explicitly. // ~Pj_Socket() { } // // Set socket handle. // void set_handle(pj_sock_t sock) { sock_ = sock; } // // Get socket handle. // pj_sock_t get_handle() const { return sock_; } // // Get socket handle. // pj_sock_t& get_handle() { return sock_; } // // See if the socket is valid. // bool is_valid() const { return sock_ != PJ_INVALID_SOCKET; } // // Create the socket. // pj_status_t create(int af, int type, int proto) { return pj_sock_socket(af, type, proto, &sock_); } // // Bind socket. // pj_status_t bind(const Pj_Inet_Addr &addr) { return pj_sock_bind(sock_, &addr, sizeof(Pj_Inet_Addr)); } // // Close socket. // pj_status_t close() { pj_sock_close(sock_); } // // Get peer socket name. // pj_status_t getpeername(Pj_Inet_Addr *addr) { return pj_sock_getpeername(sock_, addr, &addr->addrlen_); } // // getsockname // pj_status_t getsockname(Pj_Inet_Addr *addr) { return pj_sock_getsockname(sock_, addr, &addr->addrlen_); } // // getsockopt. // pj_status_t getsockopt(pj_uint16_t level, pj_uint16_t optname, void *optval, int *optlen) { return pj_sock_getsockopt(sock_, level, optname, optval, optlen); } // // setsockopt // pj_status_t setsockopt(pj_uint16_t level, pj_uint16_t optname, const void *optval, int optlen) { return pj_sock_setsockopt(sock_, level, optname, optval, optlen); } // // receive data. // pj_ssize_t recv(void *buf, pj_size_t len, int flag = 0) { pj_ssize_t bytes = len; if (pj_sock_recv(sock_, buf, &bytes, flag) != PJ_SUCCESS) return -1; return bytes; } // // send data. // pj_ssize_t send(const void *buf, pj_ssize_t len, int flag = 0) { pj_ssize_t bytes = len; if (pj_sock_send(sock_, buf, &bytes, flag) != PJ_SUCCESS) return -1; return bytes; } // // connect. // pj_status_t connect(const Pj_Inet_Addr &addr) { return pj_sock_connect(sock_, &addr, sizeof(Pj_Inet_Addr)); } // // assignment. // Pj_Socket &operator=(const Pj_Socket &rhs) { sock_ = rhs.sock_; return *this; } protected: friend class Pj_Event_Handler; pj_sock_t sock_; }; #if PJ_HAS_TCP // // Stream socket. // class Pj_Sock_Stream : public Pj_Socket { public: // // Default constructor. // Pj_Sock_Stream() { } // // Initialize from a socket handle. // explicit Pj_Sock_Stream(pj_sock_t sock) : Pj_Socket(sock) { } // // Copy constructor. // Pj_Sock_Stream(const Pj_Sock_Stream &rhs) : Pj_Socket(rhs) { } // // Assignment. // Pj_Sock_Stream &operator=(const Pj_Sock_Stream &rhs) { sock_ = rhs.sock_; return *this; } // // listen() // pj_status_t listen(int backlog = 5) { return pj_sock_listen(sock_, backlog); } // // blocking accept() // Pj_Sock_Stream accept(Pj_Inet_Addr *remote_addr = NULL) { pj_sock_t newsock; int *addrlen = remote_addr ? &remote_addr->addrlen_ : NULL; pj_status_t status; status = pj_sock_accept(sock_, &newsock, remote_addr, addrlen); if (status != PJ_SUCCESS) return Pj_Sock_Stream(-1); return Pj_Sock_Stream(newsock); } // // shutdown() // pj_status_t shutdown(int how = PJ_SHUT_RDWR) { return pj_sock_shutdown(sock_, how); } }; #endif // // Datagram socket. // class Pj_Sock_Dgram : public Pj_Socket { public: // // Default constructor. // Pj_Sock_Dgram() { } // // Initialize from a socket handle. // explicit Pj_Sock_Dgram(pj_sock_t sock) : Pj_Socket(sock) { } // // Copy constructor. // Pj_Sock_Dgram(const Pj_Sock_Dgram &rhs) : Pj_Socket(rhs) { } // // Assignment. // Pj_Sock_Dgram &operator=(const Pj_Sock_Dgram &rhs) { Pj_Socket::operator =(rhs); return *this; } // // recvfrom() // pj_ssize_t recvfrom( void *buf, pj_size_t len, int flag = 0, Pj_Inet_Addr *fromaddr = NULL) { pj_ssize_t bytes = len; int *addrlen = fromaddr ? &fromaddr->addrlen_ : NULL; if (pj_sock_recvfrom( sock_, buf, &bytes, flag, fromaddr, addrlen) != PJ_SUCCESS) { return -1; } return bytes; } // // sendto() // pj_ssize_t sendto( const void *buf, pj_size_t len, int flag, const Pj_Inet_Addr &addr) { pj_ssize_t bytes = len; if (pj_sock_sendto( sock_, buf, &bytes, flag, &addr, sizeof(pj_sockaddr_in)) != PJ_SUCCESS) { return -1; } return bytes; } }; #endif /* __PJPP_SOCK_HPP__ */