/*******************************************************************************
 *	BSocket.h	BSocket Access Classes
 *			T.Barnaby,	BEAM Ltd,	1/4/05
 *	updated by	D.Korchagin,	CERN AB-BI-SW,	2007-08-31
 *******************************************************************************
 */
#ifndef BSOCKET_H
#define BSOCKET_H	1

#include <BString.h>
#include <BError.h>
#include <BTypes.h>
#include <stdint.h>

#include <sys/types.h>

#ifndef __Lynx__
#include <sys/prctl.h>
#else
#include <netinet/in.h>
#define SOL_IP	0
#define SO_PRIORITY	12
#define MSG_NOSIGNAL 0
#endif

/// Socket Address
class BSocketAddress {
public:
	typedef struct sockaddr SockAddr;
	
			BSocketAddress();
			BSocketAddress(const BSocketAddress& add);
			BSocketAddress(SockAddr* address, int len);
			~BSocketAddress();
			
	BError		set(SockAddr* address, int len);

	const SockAddr*	raw() const;
	int		len() const;
	
			// Operator functions
	BSocketAddress&	operator=(const BSocketAddress& add);
	 		operator const SockAddr*() const { return raw(); }
	int		operator==(const BSocketAddress& add) const;
	int		operator!=(const BSocketAddress& add) const;
private:
	int		olen;
	SockAddr*	oaddress;
};

/// IP aware socket address
class BSocketAddressINET : public BSocketAddress {
public:
	typedef struct sockaddr_in SockAddrIP;

	BError		set(BString hostName, uint32_t port);
	BError		set(uint32_t address, uint32_t port);
	BError		set(BString hostName, BString service, BString type);

	void		setPort(uint32_t port);
	uint32_t	address();				///< Returns socket ip address
	uint32_t	port();					///< Returns socket port
	
	BString		getString();				///< Return string version of address <ip>:<port>
	
	// Some useful generic system functions
	static BString		getHostName();			///< Get this hosts network name
	static BList<uint32_t>	getIpAddresses();		///< Get a list of all the IP addresses of this host
	static BList<BString>	getIpAddressList();		///< Get a list of all the IP addresses of this host under hostname
	static BList<BString>	getIpAddressListAll();		///< Get a list of all the IP addresses of this host looking at physical interfaces
};

class BSocket {
public:
	enum NType	{ STREAM, DGRAM };
	enum Priority	{ PriorityLow, PriorityNormal, PriorityHigh };

			BSocket();
			BSocket(int fd);
			BSocket(NType type);
			~BSocket();

	BError		init(NType type);
	int		getFd();

			// Main functions	
	BError		bind(const BSocketAddress& add);
	BError		connect(const BSocketAddress& add);
	BError		shutdown(int how);
	BError		close();
	BError		listen(int backlog = 5);
	BError		accept(int& fd);
	BError		accept(int& fd, BSocketAddress& address);
		
			// Main data transfer functions
	BError		send(const void* buf, BSize nbytes, BSize& nbytesSent, int flags = 0);
	BError		sendTo(const BSocketAddress& address, const void* buf, BSize nbytes, BSize& nbytesSent, int flags = 0);
	BError		recv(void* buf, BSize maxbytes, BSize& nbytesRecv, int flags = 0);
	BError		recvFrom(BSocketAddress& address, void* buf, BSize maxbytes, BSize& nbytesRecv, int flags = 0);
	BError		recvWithTimeout(void* buf, BSize maxbytes, BSize& nbytesRecv, int timeout, int flags = 0);
	BError		recvFromWithTimeout(BSocketAddress& address, void* buf, BSize maxbytes, BSize& nbytesRecv, int timeout, int flags = 0);

			// Configuration functions
	BError		setSockOpt(int level, int optname, void* optval, unsigned int optlen);
	BError		getSockOpt(int level, int optname, void* optval, unsigned int* optlen);
	BError		setReuseAddress(int on);
	BError		setBroadCast(int on);
	BError		setPriority(Priority priority);
	
	BError		getMTU(uint32_t& mtu);
	BError		getAddress(BSocketAddress& address);

private:
	int		osocket;
};
#endif
