/* ==========================================================================
 * libevnet/src/socket.h - Network server library for libevent.
 * --------------------------------------------------------------------------
 * Copyright (c) 2006  William Ahern
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to permit
 * persons to whom the Software is furnished to do so, subject to the
 * following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
 * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 * ==========================================================================
 */
#ifndef EVNET_SOCKET_H
#define EVNET_SOCKET_H

#include <string.h>		/* strerror(3) */

#include <sys/types.h>		/* mode_t socklen_t */
#include <sys/time.h>		/* struct timeval */

#ifndef _WIN32
#include <sys/socket.h>		/* struct sockaddr struct sockaddr_storage */
#include <sys/un.h>		/* struct sockaddr_un */

#include <netinet/in.h>		/* struct sockaddr_in struct sockaddr_in6 */
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#endif


#ifndef SOCKET
#define SOCKET	int
#endif

struct event_base;
struct arena_prototype;
struct tls_identity;
struct tls;
struct bufio_source;
struct bufio_sink;


#define SOCKET_SA_P(s)	((struct sockaddr *)(s))

#if !_WIN32
#if USE_IPV6
#define SOCKET_SA_LENOF(s)	\
	( (SOCKET_SA_P(s)->sa_family == AF_INET)  ? sizeof(struct sockaddr_in)	\
	: (SOCKET_SA_P(s)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6)	\
	: (SOCKET_SA_P(s)->sa_family == AF_UNIX)  ? sizeof(struct sockaddr_un)	\
	: 0 )
#else
#define SOCKET_SA_LENOF(s)	\
	( (SOCKET_SA_P(s)->sa_family == AF_INET)  ? sizeof(struct sockaddr_in)	\
	: (SOCKET_SA_P(s)->sa_family == AF_UNIX)  ? sizeof(struct sockaddr_un)	\
	: 0 )
#endif /* USE_IPV6 */
#else
#if USE_UPV6
#define SOCKET_SA_LENOF(s)	\
	( (SOCKET_SA_P(s)->sa_family == AF_INET)  ? sizeof(struct sockaddr_in)	\
	: (SOCKET_SA_P(s)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6)	\
	: 0 )
#else
#define SOCKET_SA_LENOF(s)	\
	( (SOCKET_SA_P(s)->sa_family == AF_INET)  ? sizeof(struct sockaddr_in)	\
	: 0 )
#endif /* USE_IPV6 */
#endif /* !_WIN32 */

#define SOCKET_UN_P(s)	((struct sockaddr_un *)(s))


enum socket_errno {
	SOCKET_ESUCCESS,
	SOCKET_ESYSTEM,
	SOCKET_ETIMEDOUT,
	SOCKET_ECANCELLED,
	SOCKET_ENOTFOUND,
	SOCKET_ENOTLS,
	SOCKET_ENOTCONNECTED,
}; /* enum socket_errno */

extern const char *socket_errlist[];

extern const int socket_nerr;


enum socket_mode {
	SOCKET_MODE_NONE,
	SOCKET_MODE_SERVER,
	SOCKET_MODE_CLIENT,
}; /* enum socket_mode */


struct socket_name {
	void *type;

	union {
		struct sockaddr sa;
		struct sockaddr_storage ss;

		struct sockaddr_in sin;
#if USE_IPV6
		struct sockaddr_in6 sin6;
#endif
#ifndef _WIN32
		struct sockaddr_un sun;
#endif
	} addr;

	struct {
		char name[256];

		char port[32];	/* More than enough for +/-2^64 in decimal. */

		int rtype;
		int flags;
	} host;

#ifndef _WIN32
	struct {
		char path[sizeof (((struct sockaddr_un *)0)->sun_path)];
	} local;
#endif
}; /* struct socket_name */


struct socket_info {
	struct {
		union {
			struct sockaddr_in sin;
#if USE_IPV6
			struct sockaddr_in6 sin6;
#endif
#ifndef _WIN32
			struct sockaddr_un sun;
#endif
			struct sockaddr_storage ss;
		} sa;

		socklen_t salen;
	} peer, self;

	struct tls *tls;
}; /* struct socket_info */


extern const struct socket_options {
	mode_t sun_mask;

	int sun_unlink;

#if _WIN32
	BOOL sa_reuseaddr;
#else
	int sa_reuseaddr;
#endif

	int so_type;

	int so_nonblock;

	int so_backlog;

#if _WIN32
	BOOL so_nodelay;
#else
	int so_nodelay;
#endif

	int sin_resolv;
} socket_defaults;


struct socket;

struct socket *socket_open(struct socket_name *, const struct socket_options *, struct event_base *, const struct arena_prototype *, enum socket_errno *so_errno);

void socket_cancel(struct socket *, int);

void socket_close(struct socket *);

void socket_enable_tls(struct socket *, struct tls_identity *);

void socket_start_tls(struct socket *, struct tls_identity *, void (*)(struct socket *, enum socket_errno, void *), void *, struct timeval *);

void socket_getsockinfo(struct socket *, SOCKET *, struct tls **);

void socket_discard(struct socket *, SOCKET *, struct tls **);

struct bufio_source *socket_to_source(struct socket *s);

struct bufio_sink *socket_to_sink(struct socket *s);

enum socket_errno socket_getpeername(struct socket *, struct sockaddr *, socklen_t *, const char **);

enum socket_errno socket_getsockname(struct socket *, struct sockaddr *, socklen_t *, const char **);

enum socket_errno socket_setsockstate(struct socket *, SOCKET, enum socket_mode);

enum socket_errno socket_errno(struct socket *);

const char *socket_strerror(enum socket_errno);

const char *socket_errstring(struct socket *);


#define SOCKET_SO_TYPE		so_type
#define SOCKET_SO_NONBLOCK	so_nonblock
#define SOCKET_SO_MODE		so_mode

#define so_paste(a, b)			a##b
#define socket_getoption(s, t, p)	so_paste(socket_getoption_, t)((s), (p))

void socket_getoption_so_type(struct socket *, int *);

void socket_getoption_so_nonblock(struct socket *, int *);

void socket_getoption_so_mode(struct socket *, enum socket_mode *);


typedef void (*socket_accept_cb)(struct socket *, struct socket *, enum socket_errno, void *);

void socket_accept(struct socket *, socket_accept_cb, void *, struct timeval *);

typedef void (*socket_connect_cb)(struct socket *, enum socket_errno, void *);

void socket_connect(struct socket *, socket_connect_cb, void *, struct timeval *);


struct socket_name *socket_name_init_addr(struct socket_name *dst, const struct sockaddr *src, socklen_t srclen);
struct socket_name *socket_name_init_host(struct socket_name *dst, const char *src, const char *port, int rr, int flags);
struct socket_name *socket_name_init_unix(struct socket_name *dst, const char *src);

#endif /* EVNET_SOCKET_H */


syntax highlighted by Code2HTML, v. 0.9.1