blob: cc99b04399f6f05a49ecddf0e7ee39e2bb5f61b6 [file] [log] [blame]
// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
//
// This file is part of GNU uCommon C++.
//
// GNU uCommon C++ is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU uCommon C++ 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
/**
* Common socket class and address manipulation.
* This offers a common socket base class that exposes socket functionality
* based on what the target platform supports. Support for multicast, IPV6
* addressing, and manipulation of cidr policies are all supported here.
* @file ucommon/socket.h
*/
#ifndef _UCOMMON_SOCKET_H_
#define _UCOMMON_SOCKET_H_
#ifndef _UCOMMON_TIMERS_H_
#include <ucommon/timers.h>
#endif
#ifndef _UCOMMON_LINKED_H_
#include <ucommon/linked.h>
#endif
#ifndef _UCOMMON_STRING_H_
#include <ucommon/string.h>
#endif
extern "C" {
struct addrinfo;
}
#ifdef _MSWINDOWS_
#define SHUT_RDWR SD_BOTH
#define SHUT_WR SD_SEND
#define SHUT_RD SD_RECV
#else
#include <unistd.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netdb.h>
#endif
#include <errno.h>
#include <stdio.h>
#ifndef IPTOS_LOWDELAY
#define IPTOS_LOWDELAY 0x10
#define IPTOS_THROUGHPUT 0x08
#define IPTOS_RELIABILITY 0x04
#define IPTOS_MINCOST 0x02
#endif
#ifdef AF_UNSPEC
#define DEFAULT_FAMILY AF_UNSPEC
#else
#define DEFAULT_FAMILY AF_INET
#endif
struct sockaddr_internet;
typedef struct sockaddr *sockaddr_t;
typedef struct sockaddr sockaddr_struct; // older gcc needs...?
/**
* An object that holds ipv4 or ipv6 binary encoded host addresses.
*/
typedef struct hostaddr_internet
{
union
{
struct in_addr ipv4;
#ifdef AF_INET6
struct in6_addr ipv6;
#endif
};
} inethostaddr_t;
#if defined(AF_INET6) || defined(__CYGWIN__)
/**
* An object that can hold a ipv4 or ipv6 socket address. This would be
* used for tcpip socket connections. We do not use sockaddr_storage
* because it is not present in pre ipv6 stacks, and because the storage
* size also includes the size of the path of a unix domain socket on
* posix systems.
*/
typedef struct sockaddr_internet
{
union {
#ifdef AF_INET6
struct sockaddr_in6 ipv6;
#endif
struct sockaddr_in ipv4;
struct sockaddr address;
};
} inetsockaddr_t;
#else
typedef struct sockaddr_internet
{
union {
struct sockaddr_in ipv4;
struct sockaddr address;
};
} inetsockaddr_t;
struct sockaddr_storage
{
#ifdef AF_UNIX
char sa_data[128];
#else
char sa_data[sizeof(struct sockaddr_in)];
#endif
};
#endif
#ifndef SOCK_DCCP
#define SOCK_DCCP 6
#endif
#ifndef IPPROTO_DCCP
#define IPPROTO_DCCP 23
#endif
#ifndef SOL_DCCP
#define SOL_DCCP 269
#endif
#define DCCP_SOCKOPT_AVAILABLE_CCIDS 12
#define DCCP_SOCKOPT_CCID 13
#define DCCP_SOCKOPT_TX_CCID 14
#define DCCP_SOCKOPT_RX_CCID 15
NAMESPACE_UCOMMON
/**
* A class to hold internet segment routing rules. This class can be used
* to provide a stand-alone representation of a cidr block of internet
* addresses or chained together into some form of access control list. The
* cidr class can hold segments for both IPV4 and IPV6 addresses. The class
* accepts cidr's defined as C strings, typically in the form of address/bits
* or address/submask. These routines auto-detect ipv4 and ipv6 addresses.
* @author David Sugar <dyfet@gnutelephony.org>
*/
class __EXPORT cidr : public LinkedObject
{
protected:
int Family;
inethostaddr_t Netmask, Network;
char Name[16];
unsigned mask(const char *cp) const;
inethostaddr_t broadcast(void) const;
unsigned mask(void) const;
public:
/**
* A convenience type for using a pointer to a linked list as a policy chain.
*/
typedef LinkedObject policy;
/**
* Create an uninitialized cidr.
*/
cidr();
/**
* Create an unlinked cidr from a string. The string is typically in
* the form base-host-address/range, where range might be a bit count
* or a network mask.
* @param string for cidr block.
*/
cidr(const char *string);
/**
* Create an unnamed cidr entry on a specified policy chain.
* @param policy chain to link cidr to.
* @param string for cidr block.
*/
cidr(policy **policy, const char *string);
/**
* Create a named cidr entry on a specified policy chain.
* @param policy chain to link cidr to.
* @param string for cidr block.
* @param name of this policy object.
*/
cidr(policy **policy, const char *string, const char *name);
/**
* Construct a copy of an existing cidr.
* @param existing cidr we copy from.
*/
cidr(const cidr& existing);
/**
* Find the smallest cidr entry in a list that matches the socket address.
* @param policy chain to search.
* @param address to search for.
* @return smallest cidr or NULL if none match.
*/
static const cidr *find(const policy *policy, const struct sockaddr *address);
/**
* Get the largest container cidr entry in a list that matches the
* socket address.
* @param policy chain to search.
* @param address to search for.
* @return largest cidr or NULL if none match.
*/
static const cidr *container(const policy *policy, const struct sockaddr *address);
/**
* Get the saved name of our cidr. This is typically used with find
* when the same policy name might be associated with multiple non-
* overlapping cidr blocks. A typical use might to have a cidr
* block like 127/8 named "localdomain", as well as the ipv6 "::1".
* @return name of cidr.
*/
inline const char *getName(void) const
{return Name;};
/**
* Get the address family of our cidr block object.
* @return family of our cidr.
*/
inline int getFamily(void) const
{return Family;};
/**
* Get the network host base address of our cidr block.
* @return binary network host address.
*/
inline inethostaddr_t getNetwork(void) const
{return Network;};
/**
* Get the effective network mask for our cidr block.
* @return binary network mask for our cidr.
*/
inline inethostaddr_t getNetmask(void) const
{return Netmask;};
/**
* Get the broadcast host address represented by our cidr.
* @return binary broadcast host address.
*/
inline inethostaddr_t getBroadcast(void) const
{return broadcast();}
/**
* Get the number of bits in the cidr bitmask.
* @return bit mask of cidr.
*/
inline unsigned getMask(void) const
{return mask();}
/**
* Set our cidr to a string address. Replaces prior value.
* @param string to set for cidr.
*/
void set(const char *string);
/**
* Test if a given socket address falls within this cidr.
* @param address of socket to test.
* @return true if address is within cidr.
*/
bool is_member(const struct sockaddr *address) const;
/**
* Test if a given socket address falls within this cidr.
* @param address of socket to test.
* @return true if address is within cidr.
*/
inline bool operator==(const struct sockaddr *address) const
{return is_member(address);};
/**
* Test if a given socket address falls outside this cidr.
* @param address of socket to test.
* @return true if address is outside cidr.
*/
inline bool operator!=(const struct sockaddr *address) const
{return !is_member(address);};
};
/**
* A generic socket base class. This class can be used directly or as a
* base class for building network protocol stacks. This common base tries
* to handle UDP and TCP sockets, as well as support multicast, IPV4/IPV6
* addressing, and additional addressing domains (such as Unix domain sockets).
* @author David Sugar <dyfet@gnutelephony.org>
*/
class __EXPORT Socket
{
protected:
socket_t so;
int ioerr;
timeout_t iowait;
public:
/**
* Get an address list directly. This is used internally by some derived
* socket types when generic address lists would be invalid.
* @param host name in the form address or "address:port"
* @param service id or port to use if not specified in host string.
* @param type of service to get.
* @param protocol of service to get.
*/
static struct addrinfo *query(const char *host, const char *service, int type = SOCK_STREAM, int protocol = 0);
/**
* Release an address list directly. This is used internally by some
* derived socket types which do not use generic address lists.
* @param list of addresses.
*/
static void release(struct addrinfo *list);
/**
* A generic socket address class. This class uses the addrinfo list
* to store socket multiple addresses in a protocol and family
* independent manner. Hence, this address class can be used for ipv4
* and ipv6 sockets, for assigning connections to multiple hosts, etc.
* The address class will call the resolver when passed host names.
* @author David Sugar <dyfet@gnutelephony.org>
*/
class __EXPORT address
{
protected:
struct addrinfo *list;
public:
/**
* Construct a socket address. This is used to get an address to
* bind a socket interface to. The address can be specified as the
* ip address of the interface or as a "hostname". If a hostname
* is used, then family should be specified for clarity.
* @param family of socket address. Needed when host names are used.
* @param address or hostname.
* @param type of socket (stream, dgram, etc).
* @param protocol number of socket.
*/
address(int family, const char *address, int type = SOCK_STREAM, int protocol = 0);
/**
* Construct a socket address for an existing socket. This can be the
* name of a host or to perform a lookup in a domain for a service.
* Family can be used to restrict the set of results returned, however
* since things like connecto() already filter by family and create
* will use family from the addrinfo, in most cases AF_UNSPEC can be
* used. This may be depreciated in favor of the constructor that
* matches a set() method.
* @param family of hosts to filter by or AF_UNSPEC.
* @param hostname or ip address. The socket family is used for hostnames.
* @param service port or name we are referencing or NULL.
*/
address(int family, const char *hostname, const char *service = NULL);
/**
* Construct a socket address list for a service.
* @param host address for service.
* @param service name or port number.
* @param type of service, stream, dgram, etc.
*/
address(const char *host, const char *service, int type = SOCK_STREAM);
/**
* Construct a socket address from host and service. This is primarily
* used to construct a list of potential service connections by pure
* port numbers or for host lookup only.
* @param hostname or address to use.
* @param service port or 0.
*/
address(const char *hostname, unsigned service = 0);
/**
* Construct an empty address.
*/
address();
/**
* Copy constructor.
* @param reference to object to copy from.
*/
address(const address& reference);
/**
* Destroy address. Deallocate addrinfo structure.
*/
~address();
/**
* Get the first socket address in our address list.
* @return first socket address or NULL if none.
*/
struct sockaddr *get(void) const;
inline struct sockaddr *getAddr(void) const
{return get();}
inline struct sockaddr *operator()(void) const
{return get();}
/**
* Get the first socket address by casted reference.
* @return first socket address we resolved or NULL if none.
*/
inline operator struct sockaddr *() const
{return get();};
/**
* Get the first socket address of specified family from our list.
* @param family to seek.
* @return first socket address of family or NULL if none.
*/
struct sockaddr *get(int family) const;
inline struct sockaddr *operator()(int family) const
{return get(family);}
inline operator struct sockaddr_in *() const
{return (struct sockaddr_in *)get(AF_INET);}
#ifdef AF_INET6
inline operator struct sockaddr_in6 *() const
{return (struct sockaddr_in6 *)get(AF_INET6);}
#endif
/**
* Get the family of the first member in a list of services.
* @return family of first socket address or 0 if none.
*/
int family(void) const;
/**
* Find a specific socket address in our address list.
* @return matching address from list or NULL if not found.
*/
struct sockaddr *find(const struct sockaddr *addr) const;
/**
* Get the full socket address list from the object.
* @return addrinfo list we resolved or NULL if none.
*/
inline struct addrinfo *getList(void) const
{return list;};
/**
* Get the full socket address list by casted reference.
* @return addrinfo list we resolved or NULL if none.
*/
inline operator struct addrinfo *() const
{return list;};
/**
* Return the full socket address list by pointer reference.
* @return addrinfo list we resolved or NULL if none.
*/
inline struct addrinfo *operator*() const
{return list;};
/**
* Test if the address list is valid.
* @return true if we have an address list.
*/
inline operator bool() const
{return list != NULL;};
/**
* Test if we have no address list.
* @return true if we have no address list.
*/
inline bool operator!() const
{return list == NULL;};
/**
* Clear current object.
*/
void clear(void);
/**
* Set the host addresses to form a new list.
* @param hostname or address to resolve.
* @param service name or port number, or NULL if not used.
* @param type of socket (stream or dgram) to filter list by.
*/
void set(const char *hostname, const char *service = NULL, int type = SOCK_STREAM);
/**
* Append additional host addresses to our list.
* @param hostname or address to resolve.
* @param service name or port number, or NULL if not used.
* @param type of socket (stream or dgram).
*/
void add(const char *hostname, const char *service = NULL, int type = SOCK_STREAM);
/**
* Set an entry for host binding.
* @param family of socket address. Needed when hostnames are used.
* @param address or hostname.
* @param type of socket (stream, dgram, etc).
* @param protocol number of socket.
*/
void set(int family, const char *address, int type = SOCK_STREAM, int protocol = 0);
/**
* Add an individual socket address to our address list.
* @param address to add.
*/
void add(sockaddr *address);
/**
* Insert unique members from another socket address list to ours.
* @param address list to insert into list.
* @return count of addresses added.
*/
unsigned insert(struct addrinfo *address);
/**
* Remove members from another socket address list from ours.
* @param address list to remove from list.
* @return count of addresses removed.
*/
unsigned remove(struct addrinfo *address);
/**
* Remove an individual socket address from our address list.
* @param address to remove.
* @return true if found and removed, false if not found.
*/
bool remove(struct sockaddr *address);
/**
* Insert an individual socket address to our address list only if
* unique.
* @param address to insert into list.
* @return true if inserted, false if duplicate.
*/
bool insert(struct sockaddr *address);
/**
* Copy an existing addrinfo into our object. This is also used
* to support the copy constructor.
* @param address list to copy from.
*/
void copy(const struct addrinfo *address);
/**
* Set an individual socket address for our address list.
* @param address to add.
*/
void set(struct sockaddr *address);
/**
* Set a socket address from host and service.
* @param hostname or address to use.
* @param service port or 0.
*/
void set(const char *hostname, unsigned service = 0);
/**
* Duplicate a socket address.
* @param address to duplicate.
* @return duplicate address object.
*/
static struct sockaddr *dup(struct sockaddr *address);
/**
* Convert address object into ipv4 address.
* @param address to convert.
* @return new ipv4 address or NULL if not ipv4.
*/
static struct sockaddr_in *ipv4(struct sockaddr *address);
#ifdef AF_INET6
/**
* Convert address object into ipv6 address.
* @param address to convert.
* @return new ipv6 address or NULL if not ipv6.
*/
static struct sockaddr_in6 *ipv6(struct sockaddr *address);
#endif
};
friend class address;
/**
* Create a socket object for use.
*/
Socket();
/**
* Create socket as duped handle of existing socket.
* @param existing socket to dup.
*/
Socket(const Socket& existing);
/**
* Create socket from existing socket descriptor.
* @param socket descriptor to use.
*/
Socket(socket_t socket);
/**
* Create and connect a socket to an address from an address list. The
* type of socket created is based on the type we are connecting to.
* @param address list to connect with.
*/
Socket(struct addrinfo *address);
/**
* Create an unbound socket of a specific type.
* @param family of our new socket.
* @param type (stream, udp, etc) of our new socket.
* @param protocol number of our new socket.'
*/
Socket(int family, int type, int protocol = 0);
/**
* Create a bound socket. If one wishes to listen for connections on
* a protocol, then ListenSocket should be used instead.
* @param address to bind or "*" for all.
* @param port number of service to bind.
* @param family to bind as.
* @param type of socket to bind (stream, udp, etc).
* @param protocol of socket to bind.
*/
Socket(const char *address, const char *port, int family = AF_UNSPEC, int type = 0, int protocol = 0);
/**
* Shutdown, close, and destroy socket.
*/
virtual ~Socket();
/**
* Cancel pending i/o by shutting down the socket.
*/
void cancel(void);
/**
* Cancel pending i/o by shutting down the socket.
* @param socket to shutdown.
*/
static void cancel(socket_t socket);
/**
* Shutdown and close the socket.
*/
void release(void);
/**
* Get error code.
*/
inline int err(void) const
{return ioerr;}
/**
* See the number of bytes in the receive queue.
* @param value to test for.
* @return true if at least that many bytes waiting in receive queue.
*/
bool is_pending(unsigned value) const;
/**
* Test if socket is connected.
* @return true if connected.
*/
bool connected(void) const;
/**
* Test for pending input data. This function can wait up to a specified
* timeout for data to appear.
* @param timeout or 0 if none.
* @return true if input data waiting.
*/
bool wait(timeout_t timeout = 0) const;
/**
* Set nodelay option for tcp socket.
* @return 0 if successful, -1 on error.
*/
inline int nodelay(void) const
{return nodelay(so);};
/**
* Test for pending input data. This function can wait up to a specified
* timeout for data to appear.
* @param socket to test.
* @param timeout or 0 if none.
* @return true if input data waiting.
*/
static bool wait(socket_t socket, timeout_t timeout = 0);
/**
* Test for output data sent. This function can wait up to a specified
* timeout for data to appear sent.
* @param timeout or 0 if none.
* @return false if cannot send more output/out of buffer space.
*/
bool waitSending(timeout_t timeout = 0) const;
/**
* Get the number of bytes of data in the socket receive buffer.
* @return bytes pending.
*/
inline unsigned pending(void) const
{return pending(so);};
/**
* Set socket for unicast mode broadcasts.
* @param enable broadcasting if true.
* @return 0 on success, -1 if error.
*/
inline int broadcast(bool enable)
{return broadcast(so, enable);};
/**
* Set socket for keepalive packets.
* @param enable keep-alive if true.
* @return 0 on success, -1 if error.
*/
inline int keepalive(bool enable)
{return keepalive(so, enable);};
/**
* Set socket blocking I/O mode.
* @param enable true for blocking I/O.
* @return 0 on success, -1 if error.
*/
inline int blocking(bool enable)
{return blocking(so, enable);};
/**
* Set multicast mode and multicast broadcast range.
* @param ttl to set for multicast socket or 0 to disable multicast.
* @return 0 on success, -1 if error.
*/
inline int multicast(unsigned ttl = 1)
{return multicast(so, ttl);};
/**
* Set loopback to read multicast packets we broadcast.
* @param enable true to loopback, false to ignore.
* @return 0 on success, -1 if error.
*/
inline int loopback(bool enable)
{return loopback(so, enable);};
/**
* Get socket error code.
* @return socket error code.
*/
inline int getError(void)
{return error(so);};
/**
* Set the time to live before packets expire.
* @param time to live to set.
* @return 0 on success, -1 on error.
*/
inline int ttl(unsigned char time)
{return ttl(so, time);};
/**
* Set the size of the socket send buffer.
* @param size of send buffer to set.
* @return 0 on success, -1 on error.
*/
inline int sendsize(unsigned size)
{return sendsize(so, size);};
/**
* Set the size to wait before sending.
* @param size of send wait buffer to set.
* @return 0 on success, -1 on error.
*/
inline int sendwait(unsigned size)
{return sendwait(so, size);};
/**
* Set the size of the socket receive buffer.
* @param size of recv buffer to set.
* @return 0 on success, -1 on error.
*/
inline int recvsize(unsigned size)
{return recvsize(so, size);};
/**
* Get the type of a socket.
* @param socket descriptor.
* @return socket type.
*/
static int type(socket_t socket);
/**
* Set segment size and get MTU.
* @param socket to modify.
* @param size of segment or zero to not set.
* @return mtu size of socket.
*/
static unsigned segsize(socket_t socket, unsigned size = 0);
/**
* Set congestion control id.
* @param socket to modify.
* @param ccid value to set.
* @return true if success, false if not dccp or not supported ccid used.
*/
static bool ccid(socket_t socket, uint8_t id);
/**
* Get the type of a socket.
* @return socket type.
*/
inline int type(void)
{return type(so);};
/**
* Set segment size and get mtu of a socket.
* @param size of segment or 0 to leave unchanged.
* @return mtu size.
*/
inline unsigned segsize(unsigned size)
{return segsize(so, size);};
/**
* Set ccid of dccp socket.
* @param ccid to set.
* @return true if success, false if not dccp or not supported ccid used.
*/
inline bool ccid(uint8_t id)
{return ccid(so, id);};
/**
* Set the type of service field of outgoing packets. Some useful
* values include IPTOS_LOWDELAY to minimize delay for interactive
* traffic, IPTOS_THROUGHPUT to optimize throughput, OPTOS_RELIABILITY
* to optimize for reliability, and IPTOS_MINCOST for low speed use.
* @param type of service value.
* @return 0 on success or -1 on error.
*/
inline int tos(int type)
{return tos(so, type);};
/**
* Set packet priority, 0 to 6 unless privileged. Should be set before
* type-of-service.
* @param scheduling priority for packet scheduling.
* @return 0 on success, -1 on error.
*/
inline int priority(int scheduling)
{return priority(so, scheduling);};
/**
* Shutdown the socket communication channel.
*/
inline void shutdown(void)
{::shutdown(so, SHUT_RDWR);};
/**
* Connect our socket to a remote host from an address list.
* For TCP (and DCCP) sockets, the entire list may be tried. For UDP,
* connect is only a state and the first valid entry in the list is used.
* @param list of addresses to connect to.
* @return 0 on success or error.
*/
int connectto(struct addrinfo *list);
/**
* Disconnect a connected socket. Depending on the implementation, this
* might be done by connecting to AF_UNSPEC, connecting to a 0 address,
* or connecting to self.
* @return 0 on success or error.
*/
int disconnect(void);
/**
* Join socket to multicast group.
* @param list of groups to join.
* @return 0 on success, -1 on error.
*/
int join(const struct addrinfo *list);
/**
* Drop socket from multicast group.
* @param list of groups to drop.
* @return 0 on success, -1 on error.
*/
int drop(const struct addrinfo *list);
/**
* Socket i/o timer setting.
* @param timeout to wait, inf for blocking, 0 pure non-blocking.
* @return 0 on success or error code.
*/
int wait(timeout_t timeout = Timer::inf);
/**
* Peek at data waiting in the socket receive buffer.
* @param data pointer to save data in.
* @param number of bytes to peek.
* @return number of bytes actually read, or 0 if no data waiting.
*/
size_t peek(void *data, size_t number) const;
/**
* Read data from the socket receive buffer. This will be used in abi 4.
* @param data pointer to save data in.
* @param number of bytes to read.
* @param address of peer data was received from.
* @return number of bytes actually read, 0 if none, -1 if error.
*/
size_t readfrom(void *data, size_t number, struct sockaddr_storage *address = NULL);
/**
* Write data to the socket send buffer. This will be used in abi 4.
* @param data pointer to write data from.
* @param number of bytes to write.
* @param address of peer to send data to if not connected.
* @return number of bytes actually sent, 0 if none, -1 if error.
*/
size_t writeto(const void *data, size_t number, const struct sockaddr *address = NULL);
/**
* Read a newline of text data from the socket and save in NULL terminated
* string. This uses an optimized I/O method that takes advantage of
* socket peeking. This presumes a connected socket on a streamble
* protocol. Because the trailing newline is dropped, the return size
* may be greater than the string length. If there was no data read
* because of eof of data, an error has occured, or timeout without
* input, then 0 will be returned.
* @param data to save input line.
* @param size of input line buffer.
* @return number of bytes read, 0 if none, err() has error.
*/
size_t readline(char *data, size_t size);
/**
* Print formatted string to socket.
* @param format string.
* @return number of bytes sent.
*/
size_t printf(const char *format, ...) __PRINTF(2,3);
/**
* Read a string of input from the socket and strip trailing newline.
* This uses an optimized I/O method that takes advantage of
* socket peeking. This presumes a connected socket on a streamble
* protocol. Because the trailing newline is dropped, the return size
* may be greater than the string length. If there was no data read
* because of eof of data, an error has occured, or timeout without
* input, then 0 will be returned.
* @param buffer to save input line.
* @return number of bytes read, 0 if none, err() has error.
*/
size_t readline(String& buffer);
/**
* Read a newline of text data from the socket and save in NULL terminated
* string. This uses an optimized I/O method that takes advantage of
* socket peeking. As such, it has to be rewritten to be used in a ssl
* layer socket.
* @param socket to read from.
* @param data to save input line.
* @param size of input line buffer.
* @param timeout to wait for a complete input line.
* @return number of bytes read, 0 if none, -1 if error.
*/
static ssize_t readline(socket_t socket, char *data, size_t size, timeout_t timeout = Timer::inf);
/**
* Print formatted string to socket.
* @param socket to write to.
* @param format string.
* @return number of bytes sent, -1 if error.
*/
static ssize_t printf(socket_t socket, const char *format, ...) __PRINTF(2,3);
/**
* Write a null terminated string to the socket. This exists because
* we messed up consistency with the original puts() method. In the
* future there will be a single puts() that has a NULL default.
* @param string to write.
* @return number of bytes sent, 0 if none, -1 if error.
*/
size_t writes(const char *string);
/**
* Test if socket is valid.
* @return true if valid socket.
*/
operator bool();
/**
* Test if socket is invalid.
* @return true if socket is invalid.
*/
bool operator!() const;
/**
* Assign socket from a socket descriptor. Release existing socket if
* one present.
* @param socket descriptor to assign to object.
*/
Socket& operator=(socket_t socket);
/**
* Get the socket descriptor by casting.
* @return socket descriptor of object.
*/
inline operator socket_t() const
{return so;};
/**
* Get the socket descriptor by pointer reference.
* @return socket descriptor of object.
*/
inline socket_t operator*() const
{return so;};
/**
* Get the number of bytes pending in the receive buffer of a socket
* descriptor.
* @param socket descriptor.
* @return number of pending bytes.
*/
static unsigned pending(socket_t socket);
/**
* Set the send size of a socket descriptor.
* @param socket descriptor.
* @param size of send buffer to set.
* @return 0 on success, -1 on error.
*/
static int sendsize(socket_t socket, unsigned size);
/**
* Set the size to wait before sending.
* @param socket descriptor.
* @param size of send wait buffer to set.
* @return 0 on success, -1 on error.
*/
static int sendwait(socket_t socket, unsigned size);
/**
* Set the receive size of a socket descriptor.
* @param socket descriptor.
* @param size of receive buffer to set.
* @return 0 on success, -1 on error.
*/
static int recvsize(socket_t socket, unsigned size);
/**
* Connect socket descriptor to a remote host from an address list.
* For TCP (and DCCP) sockets, the entire list may be tried. For UDP,
* connect is only a state and the first valid entry in the list is used.
* @param socket descriptor.
* @param list of addresses to connect to.
* @return 0 on success, -1 on error.
*/
static int connectto(socket_t socket, struct addrinfo *list);
/**
* Disconnect a connected socket descriptor.
* @param socket descriptor.
* @return 0 on success, -1 on error.
*/
static int disconnect(socket_t socket);
/**
* Drop socket descriptor from multicast group.
* @param socket descriptor.
* @param list of groups to drop.
* @return 0 on success, -1 on error.
*/
static int drop(socket_t socket, const struct addrinfo *list);
/**
* Join socket descriptor to multicast group.
* @param socket descriptor.
* @param list of groups to join.
* @return 0 on success, -1 on error.
*/
static int join(socket_t socket, const struct addrinfo *list);
/**
* Get socket error code of socket descriptor.
* @param socket descriptor.
* @return socket error code.
*/
static int error(socket_t socket);
/**
* Set multicast mode and multicast broadcast range for socket descriptor.
* @param socket descriptor.
* @param ttl to set for multicast socket or 0 to disable multicast.
* @return 0 if success, -1 if error.
*/
static int multicast(socket_t socket, unsigned ttl = 1);
/**
* Set loopback to read multicast packets socket descriptor broadcasts.
* @param socket descriptor.
* @param enable true to loopback, false to ignore.
* @return 0 if success, -1 if error.
*/
static int loopback(socket_t socket, bool enable);
/**
* Set socket blocking I/O mode of socket descriptor.
* @param socket descriptor.
* @param enable true for blocking I/O.
* @return 0 if success, -1 if error.
*/
static int blocking(socket_t socket, bool enable);
/**
* Set socket for keepalive packets for socket descriptor.
* @param socket descriptor.
* @param enable keep-alive if true.
* @return 0 if success, -1 if error.
*/
static int keepalive(socket_t socket, bool enable);
/**
* Set socket for unicast mode broadcasts on socket descriptor.
* @param socket descriptor.
* @param enable broadcasting if true.
* @return 0 if success, -1 if error.
*/
static int broadcast(socket_t socket, bool enable);
/**
* Set tcp nodelay option on socket descriptor.
* @param socket descriptor.
* @return 0 if success, -1 if error.
*/
static int nodelay(socket_t socket);
/**
* Set packet priority of socket descriptor.
* @param socket descriptor.
* @param scheduling priority for packet scheduling.
* @return 0 on success, -1 on error.
*/
static int priority(socket_t socket, int scheduling);
/**
* Set type of service of socket descriptor.
* @param socket descriptor.
* @param type of service.
* @return 0 on success, -1 on error.
*/
static int tos(socket_t socket, int type);
/**
* Set the time to live for the socket descriptor.
* @param socket descriptor.
* @param time to live to set.
* @return 0 on success, -1 on error.
*/
static int ttl(socket_t socket, unsigned char time);
/**
* Get the address family of the socket descriptor.
* @return address family.
*/
static int family(socket_t socket);
/**
* Get the address family of a socket address object.
* @param address to examine.
* @return address family.
*/
inline static int family(const struct sockaddr_storage& address)
{return ((const struct sockaddr *)&address)->sa_family;};
/**
* Get the address family of an internet socket address object.
* @param address to examine.
* @return address family.
*/
inline static int family(const struct sockaddr_internet& address)
{return address.address.sa_family;};
/**
* Get data waiting in receive queue.
* @param socket to get from.
* @param buffer to save.
* @param size of data buffer to request.
* @param flags for i/o operation (MSG_OOB, MSG_PEEK, etc).
* @param address of source.
* @return number of bytes received, -1 if error.
*/
static ssize_t recvfrom(socket_t socket, void *buffer, size_t size, int flags = 0, struct sockaddr_storage *address = NULL);
/**
* Send data on socket.
* @param socket to send to.
* @param buffer to send.
* @param size of data buffer to send.
* @param flags for i/o operation (MSG_OOB, MSG_PEEK, etc).
* @param address of destination, NULL if connected.
* @return number of bytes sent, -1 if error.
*/
static ssize_t sendto(socket_t socket, const void *buffer, size_t size, int flags = 0, const struct sockaddr *address = NULL);
/**
* Send reply on socket. Used to reply to a recvfrom message.
* @param socket to send to.
* @param buffer to send.
* @param size of data buffer to send.
* @param flags for i/o operation (MSG_OOB, MSG_PEEK, etc).
* @param address to reply to.
* @return number of bytes sent, -1 if error.
*/
inline static ssize_t replyto(socket_t socket, const void *buffer, size_t size, int flags, const struct sockaddr_storage *address)
{return sendto(socket, buffer, size, flags, (const struct sockaddr *)address);};
/**
* Send to internet socket.
* @param socket to send to.
* @param buffer to send.
* @param size of data buffer to send.
* @param flags for i/o operation (MSG_OOB, MSG_PEEK, etc).
* @param address to send to.
* @return number of bytes sent, -1 if error.
*/
inline static ssize_t sendinet(socket_t socket, const void *buffer, size_t size, int flags, const struct sockaddr_internet *address)
{return sendto(socket, buffer, size, flags, (const struct sockaddr *)address);};
/**
* Get internet data waiting in receive queue.
* @param socket to get from.
* @param buffer to save.
* @param size of data buffer to request.
* @param flags for i/o operation (MSG_OOB, MSG_PEEK, etc).
* @param address of source.
* @return number of bytes received, -1 if error.
*/
static ssize_t recvinet(socket_t socket, void *buffer, size_t size, int flags = 0, struct sockaddr_internet *address = NULL);
/**
* Bind the socket descriptor to a known interface and service port.
* @param socket descriptor to bind.
* @param address to bind to or "*" for all.
* @param service port to bind.
* @param protocol to use or 0 if default.
* @return 0 on success, -1 if error.
*/
static int bindto(socket_t socket, const char *address, const char *service, int protocol = 0);
/**
* Bind the socket descriptor to a known interface listen on service port.
* @param socket descriptor to bind.
* @param address of interface to bind to.
* @param backlog for service.
* @return 0 on success, -1 if error.
*/
static int listento(socket_t socket, const struct sockaddr *address, int backlog = 5);
/**
* Bind the socket descriptor to a known interface.
* @param socket descriptor to bind.
* @param address of interface to bind to.
* @return 0 on success, -1 if error.
*/
static int bindto(socket_t socket, const struct sockaddr *address);
/**
* Accept a socket connection from a remote host.
* @param socket descriptor to accept from.
* @param address of socket accepting.
* @return new socket accepted.
*/
static socket_t acceptfrom(socket_t socket, struct sockaddr_storage *address = NULL);
/**
* Create a socket object unbound.
* @param family of socket.
* @param type of socket.
* @param protocol of socket.
* @return socket descriptor created or INVALID_SOCKET.
*/
static socket_t create(int family, int type, int protocol);
/**
* Create a connected socket.
* @param address list to connect to.
* @param type of socket to create.
* @param protocol of socket.
* @return socket descriptor created or INVALID_SOCKET.
*/
static socket_t create(const struct addrinfo *address, int type, int protocol);
/**
* Create a bound socket for a service.
* @param iface to bind.
* @param service port to bind.
* @param family to select or AF_UNSPEC
* @param type of socket to create.
* @param protocol of socket to create.
* @return socket descriptor created or INVALID_SOCKET.
*/
static socket_t create(const char *iface, const char *service, int family = AF_UNSPEC, int type = 0, int protocol = 0);
/**
* Create a connected socket for a service.
* @param address of service for connect.
* @return socket descriptor.
*/
static socket_t create(const Socket::address &address);
/**
* Release (close) a socket.
* @param socket to close.
*/
static void release(socket_t socket);
/**
* Lookup and return the host name associated with a socket address.
* @param address to lookup.
* @param buffer to save hostname into.
* @param size of buffer to save hostname into.
* @return buffer or NULL if lookup fails.
*/
static char *hostname(const struct sockaddr *address, char *buffer, size_t size);
/**
* Create an address info lookup hint based on the family and type
* properties of a socket descriptor.
* @param socket descriptor.
* @param hint buffer.
* @return hint buffer.
*/
static struct addrinfo *hinting(socket_t socket, struct addrinfo *hint);
/**
* Lookup a host name and service address based on the addressing family
* and socket type of a socket descriptor. Store the result in a socket
* address structure.
* @param socket descriptor.
* @param address that is resolved.
* @param hostname to resolve.
* @param service port.
* @return socket address size.
*/
static socklen_t query(socket_t socket, struct sockaddr_storage *address, const char *hostname, const char *service);
/**
* Get the size of a socket address.
* @param address of socket.
* @return size to use for this socket address object.
*/
static socklen_t len(const struct sockaddr *address);
/**
* Compare socket addresses. Test if the address and service matches
* or if there is no service, then just the host address values.
* @param address1 to compare.
* @param address2 to compare.
* @return true if same family and equal.
*/
static bool equal(const struct sockaddr *address1, const struct sockaddr *address2);
/**
* Copy a socket address.
* @param target address pointer to copy into.
* @param origin address pointer to copy from.
* @return number of bytes copied, 0 if invalid.
*/
static unsigned copy(struct sockaddr *target, const struct sockaddr *origin);
/**
* Store an address into an address object.
* @param storage for address.
* @param address to store.
* @return number of bytes stored.
*/
inline static unsigned store(struct sockaddr_storage *storage, const struct sockaddr *address)
{return copy((struct sockaddr*)storage, address);};
/**
* Store an address into an internet address object.
* @param storage for address.
* @param address to store.
* @return number of bytes stored.
*/
static unsigned store(struct sockaddr_internet *storage, const struct sockaddr *address);
/**
* Compare socket host addresses. Test if the host address matches
* or if there is no service, then just the host address values.
* @param address1 to compare.
* @param address2 to compare.
* @return true if same family and equal.
*/
static bool eq_host(const struct sockaddr *address1, const struct sockaddr *address2);
/**
* Compare socket addresses. Test if the stored addresses received match.
* or if there is no service, then just the host address values.
* @param address1 to compare.
* @param address2 to compare.
* @return true if same family and equal.
*/
inline static bool eq_from(const struct sockaddr_storage *address1, const struct sockaddr_storage *address2)
{return equal((const struct sockaddr *)address1, (const struct sockaddr *)address2);};
/**
* Compare socket addresses. Test if the internet addresses received match.
* or if there is no service, then just the host address values.
* @param address1 to compare.
* @param address2 to compare.
* @return true if same family and equal.
*/
inline static bool eq_inet(const struct sockaddr_internet *address1, const struct sockaddr_internet *address2)
{return equal((const struct sockaddr *)address1, (const struct sockaddr *)address2);};
/**
* See if both addresses are in the same subnet. This is only relevant
* to IPV4 and class domain routing.
* @param address1 to test.
* @param address2 to test.
* @return true if in same subnet.
*/
static bool eq_subnet(const struct sockaddr *address1, const struct sockaddr *address2);
/**
* Get the socket address of the interface needed to reach a destination
* address.
* @param address of interface found.
* @param destination address.
* @return 0 on success, -1 on error.
*/
static int via(struct sockaddr *address, const struct sockaddr *destination);
/**
* Get the hostname of a socket address.
* @param address to lookup.
* @param buffer to save hostname in.
* @param size of hostname buffer.
* @return buffer if found or NULL if not.
*/
static char *query(const struct sockaddr *address, char *buffer, socklen_t size);
/**
* Get the service port of a socket.
* @param address of socket to examine.
* @return service port number.
*/
static short service(const struct sockaddr *address);
/**
* Get the service port of an inet socket.
* @param address of internet socket to examine.
* @return service port number.
*/
inline static short service(const struct sockaddr_internet *address)
{return service((const struct sockaddr *)address);};
/**
* Convert a socket address and service into a hash map index.
* @param address to convert.
* @param size of map index.
* @return key index path.
*/
static unsigned keyindex(const struct sockaddr *address, unsigned size);
/**
* Convert a socket host address into a hash map index.
* @param address to convert.
* @param size of map index.
* @return key index path.
*/
static unsigned keyhost(const struct sockaddr *address, unsigned size);
/**
* Initialize socket subsystem.
*/
static void init(void);
/**
* Initialize with program name. Used by socks, for example.
* @param program name.
*/
static void init(const char *program);
/**
* Set default socket family preference for query options when the
* socket type is otherwise not specified.
* @param family to select.
*/
static void query(int family);
/**
* Set the default socket behavior for v6-v4 mapping. This also
* effects v6 address lookup as to whether v4 remapped addresses
* can be used if no v6 address is found.
* @param enable true to set mapping. This is default.
*/
static void v4mapping(bool enable);
/**
* Return error code of last socket operation,
* @return errno style error code.
*/
static int error(void);
/**
* Simple function to validate that a given IP address string is a "zero"
* address. Such address strings are used for example in SIP to indicate
* "hold" by re-inviting peers to a null address. Supports IPV4 and
* IPV6 addresses.
* @param string address to check.
* @return true if zero/null address.
*/
static bool is_null(const char *string);
/**
* Simple function to validate that a given IP address string is a numeric
* address. This can be used to verify an address is not a "host" name.
* Supports IPV4 and IPV6 address strings.
* @param string address to check.
* @return true if zero/null address.
*/
static bool is_numeric(const char *string);
/**
* Get local address to which the socket is bound. This is defined here
* because we may re-define the backend linkage for the socks proxy in
* the future.
* @param socket descriptor to examine.
* @param address storage for local address.
* @return 0 on success, -1 on failure.
*/
static int local(socket_t socket, struct sockaddr_storage *address);
/**
* Get remote address to which the socket is connected. This is defined
* here because we may re-define the backend linkage for the socks proxy in
* the future.
* @param socket descriptor to examine.
* @param address storage for remote address.
* @return 0 on success, -1 on failure.
*/
static int remote(socket_t socket, struct sockaddr_storage *address);
};
/**
* A bound socket used to listen for inbound socket connections. This class
* is commonly used for TCP and DCCP listener sockets.
* @author David Sugar <dyfet@gnutelephony.org>
*/
class __EXPORT ListenSocket : protected Socket
{
public:
/**
* Create and bind a listener socket.
* @param address to bind on or "*" for all.
* @param service port to bind listener.
* @param backlog size for buffering pending connections.
* @param family of socket.
* @param type of socket.
* @param protocol for socket if not TCPIP.
*/
ListenSocket(const char *address, const char *service, unsigned backlog = 5, int family = AF_UNSPEC, int type = 0, int protocol = 0);
/**
* Create a listen socket directly.
* @param address to bind on or "*" for all.
* @param service port to bind listener.
* @param backlog size for buffering pending connections.
* @param family of socket.
* @param type of socket.
* @param protocol for socket if not TCPIP.
* @return bound and listened to socket.
*/
static socket_t create(const char *address, const char *service, unsigned backlog = 5, int family = AF_UNSPEC, int type = 0, int protocol = 0);
/**
* Accept a socket connection.
* @param address to save peer connecting.
* @return socket descriptor of connected socket.
*/
socket_t accept(struct sockaddr_storage *address = NULL) const;
/**
* Wait for a pending connection.
* @param timeout to wait.
* @return true when acceptable connection is pending.
*/
inline bool wait(timeout_t timeout = Timer::inf) const
{return Socket::wait(timeout);};
/**
* Get the socket descriptor of the listener.
* @return socket descriptor.
*/
inline operator socket_t() const
{return so;}
/**
* Get the socket descriptor of the listener by pointer reference.
* @return socket descriptor.
*/
inline socket_t operator*() const
{return so;}
/**
* Get the socket descriptor of the listener.
* @return socket descriptor.
*/
inline socket_t getsocket(void) const
{return so;}
inline socket_t handle(void) const
{return so;}
};
/**
* A generic tcp server class. This saves the service id tag so that it
* can be propagated.
* @author David Sugar <dyfet@gnutelephony.org>
*/
class __EXPORT TCPServer : public ListenSocket
{
public:
/**
* Create and bind a tcp server. This mostly is used to preserve the
* service tag for TCP Socket when derived from a server instance.
* @param service tag to use.
* @param address of interface to bind or "*" for all.
* @param backlog size for pending connections.
*/
TCPServer(const char *address, const char *service, unsigned backlog = 5);
};
/**
* Helper function for linked_pointer<struct sockaddr>.
*/
__EXPORT struct addrinfo *_nextaddrinfo(struct addrinfo *addrinfo);
/**
* Helper function for linked_pointer<struct sockaddr>.
*/
__EXPORT struct sockaddr *_getaddrinfo(struct addrinfo *addrinfo);
/**
* Helper function for linked_pointer<struct sockaddr>.
*/
__EXPORT socket_t _getaddrsock(struct addrinfo *addrinfo);
/**
* Linked pointer for address lists. This can be used to iterate through
* the list of a Socket::address object using the linked_pointer method.
* @author David Sugar <dyfet@gnutelephony.org>
*/
template <>
class linked_pointer<sockaddr_struct>
{
private:
struct addrinfo *ptr;
public:
inline linked_pointer(struct addrinfo *list)
{ptr = list;}
inline linked_pointer()
{ptr = NULL;}
inline linked_pointer(Socket::address& list)
{ptr = list.getList();};
/**
* Get the full socket address list by casted reference.
* @return addrinfo list we resolved or NULL if none.
*/
inline operator struct sockaddr *() const
{return _getaddrinfo(ptr);};
/**
* Return the full socket address list by pointer reference.
* @return addrinfo list we resolved or NULL if none.
*/
inline struct sockaddr *operator*() const
{return _getaddrinfo(ptr);};
inline operator struct sockaddr_in *() const
{return (struct sockaddr_in *)_getaddrinfo(ptr);};
inline struct sockaddr_in *in(void) const
{return (struct sockaddr_in *)_getaddrinfo(ptr);};
#ifdef AF_INET6
inline operator struct sockaddr_in6 *() const
{return (struct sockaddr_in6 *)_getaddrinfo(ptr);};
inline struct sockaddr_in6 *in6(void) const
{return (struct sockaddr_in6 *)_getaddrinfo(ptr);};
#endif
/**
* Get socket as expression operator.
*/
inline socket_t operator()(void) const
{return _getaddrsock(ptr);};
/**
* Test if the address list is valid.
* @return true if we have an address list.
*/
inline operator bool() const
{return ptr != NULL;};
/**
* Assign our pointer from an address list.
* @param pointer of linked list.
*/
inline void operator=(struct addrinfo *list)
{ptr = list;};
/**
* Assign our pointer from an address list.
* @param pointer of linked list.
*/
inline void operator=(Socket::address& list)
{ptr = list.getList();};
/**
* Assign our pointer from an address list.
* @param pointer of linked list.
*/
inline void set(struct addrinfo *list)
{ptr = list;};
/**
* Assign our pointer from an address list.
* @param pointer of linked list.
*/
inline void set(Socket::address& list)
{ptr = list.getList();};
/**
* Return member from typed object our pointer references.
* @return evaluated member of object we point to.
*/
inline struct sockaddr* operator->() const
{return _getaddrinfo(ptr);};
/**
* Test if we have no address list.
* @return true if we have no address list.
*/
inline bool operator!() const
{return ptr == NULL;};
inline void next(void)
{ptr = _nextaddrinfo(ptr);};
};
/**
* A convenience function to convert a socket address list into an addrinfo.
* @param address list object.
* @return addrinfo list or NULL if empty.
*/
inline struct addrinfo *addrinfo(Socket::address& address)
{return address.getList();}
/**
* A convenience function to convert a socket address list into a socket
* address.
* @param address list object.
* @return first socket address in list or NULL if empty.
*/
inline struct sockaddr *addr(Socket::address& address)
{return address.get();}
/**
* Compare two socket addresses to see if equal. If the port is zero
* then this is the same as comparing host address alone.
* @param s1 socket address to compare.
* @param s2 socket address to compare.
* @return true if addresses same.
*/
inline bool eq(const struct sockaddr *s1, const struct sockaddr *s2)
{return Socket::equal(s1, s2);}
/**
* Compare two stored socket addresses to see if equal. If the port is zero
* then this is the same as comparing host address alone.
* @param s1 stored socket address to compare.
* @param s2 stored socket address to compare.
* @return true if addresses same.
*/
inline bool eq(const struct sockaddr_storage *s1, const struct sockaddr_storage *s2)
{return Socket::equal((const struct sockaddr *)s1, (const struct sockaddr *)s2);}
/**
* Compare two host addresses to see if equal. The port numbers are
* ignored.
* @param s1 socket address to compare.
* @param s2 socket address to compare.
* @return true if addresses same.
*/
inline bool eq_host(const struct sockaddr *s1, const struct sockaddr *s2)
{return Socket::eq_host(s1, s2);}
inline bool eq_subnet(const struct sockaddr *s1, const struct sockaddr *s2)
{return Socket::eq_subnet(s1, s2);}
String str(Socket& so, strsize_t size);
typedef TCPServer tcpserv_t;
END_NAMESPACE
#endif