changeset 168:a89ff602b30f

Initial import of nsock.c nsock.h
author David Demelier <markand@malikania.fr>
date Thu, 22 Aug 2013 17:40:54 +0200
parents 1167cd06b475
children 29531c2f8213
files nsock.c nsock.h
diffstat 2 files changed, 796 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nsock.c	Thu Aug 22 17:40:54 2013 +0200
@@ -0,0 +1,627 @@
+/*
+ * nsock.c -- portable BSD sockets wrapper
+ *
+ * Copyright (c) 2013 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#  include <stdio.h>
+#  include <stdlib.h>
+
+#if !defined(_WIN32)
+#  include <errno.h>
+#  include <string.h>
+#endif
+
+#include "nsock.h"
+
+#define	TAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *tqh_first;	/* first element */			\
+	struct type **tqh_last;	/* addr of last next element */		\
+	size_t noclients;						\
+}
+
+#define	TAILQ_ENTRY(type)						\
+struct {								\
+	struct type *tqe_next;	/* next element */			\
+	struct type **tqe_prev;	/* address of previous next element */	\
+}
+
+#define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
+
+#define	TAILQ_FIRST(head)	((head)->tqh_first)
+
+#define	TAILQ_FOREACH(var, head, field)					\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var);							\
+	    (var) = TAILQ_NEXT((var), field))
+
+#define	TAILQ_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	TAILQ_INIT(head) do {						\
+	TAILQ_FIRST((head)) = NULL;					\
+	(head)->tqh_last = &TAILQ_FIRST((head));			\
+} while (0)
+
+#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
+		TAILQ_FIRST((head))->field.tqe_prev =			\
+		    &TAILQ_NEXT((elm), field);				\
+	else								\
+		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
+	TAILQ_FIRST((head)) = (elm);					\
+	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
+	(head)->noclients ++;						\
+} while (0)
+
+#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	TAILQ_NEXT((elm), field) = NULL;				\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
+	(head)->noclients ++;						\
+} while (0)
+
+#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define	TAILQ_REMOVE(head, elm, field) do {				\
+	if ((TAILQ_NEXT((elm), field)) != NULL)				\
+		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
+		    (elm)->field.tqe_prev;				\
+	else {								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+	}								\
+	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
+	(head)->noclients --;						\
+} while (0)
+
+struct nsock {
+	nsock_socket_t		fd;
+	char			error[128];
+};
+
+struct nsock_ep {
+	struct sockaddr_storage	addr;
+	socklen_t		addrlen;
+	char			error[128];
+};
+
+struct nsock_listener {
+	const struct nsock	*sock;
+	char			error[128];
+	TAILQ_HEAD(, nsock_clt)	head;
+};
+
+struct nsock_clt {
+	const struct nsock	*sock;
+	TAILQ_ENTRY(nsock_clt)	link;
+};
+
+/* --------------------------------------------------------
+ * Private helpers
+ * -------------------------------------------------------- */
+
+static void
+nsock_set_error(char *buffer, size_t bufsize)
+{
+	memset(buffer, 0, bufsize);
+
+#if defined(_WIN32)
+	LPSTR str;
+
+	FormatMessageA(
+		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+		NULL,
+		WSAGetLastError(),
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		(LPSTR)&str, 0, NULL);
+
+	if (str) {
+		strncpy(buffer, str, bufsize);
+		LocalFree(str);
+	}
+#else
+	strncpy(buffer, strerror(errno), bufsize);
+#endif
+}
+
+static void
+nsock_set_errno(char *buffer, size_t bufsize, int no)
+{
+	memset(buffer, 0, bufsize);
+	strncpy(buffer, strerror(no), bufsize - 1);
+}
+
+static struct nsock_clt *
+nsock_clt_new(const struct nsock *ns)
+{
+	struct nsock_clt *clt;
+
+	if ((clt = malloc(sizeof (struct nsock_clt))) == NULL)
+		return NULL;
+
+	clt->sock = ns;
+
+	return clt;
+}
+
+/* --------------------------------------------------------
+ * Sockets functions
+ * -------------------------------------------------------- */
+
+void
+nsock_init(void)
+{
+#if defined(_WIN32)
+	WSADATA wsa;
+	WSAStartup(MAKEWORD(2, 2), &wsa);
+#endif
+}
+
+struct nsock *
+nsock_create(int domain, int type, int protocol)
+{
+	struct nsock *ns;
+
+	if ((ns = malloc(sizeof (struct nsock))) == NULL)
+		return NULL;
+
+	ns->fd = socket(domain, type, protocol);
+
+	if (ns->fd == INVALID_SOCKET)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return ns;
+}
+
+const char *
+nsock_error(struct nsock *ns)
+{
+	if (ns == NULL)
+		return strerror(ENOMEM);
+
+	return ns->error;
+}
+
+int
+nsock_bind(struct nsock *ns, const struct nsock_ep *ep)
+{
+	int ret;
+
+	ret = bind(ns->fd, (const struct sockaddr *)&ep->addr, ep->addrlen);
+
+	if (ret == SOCKET_ERROR)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return ret == SOCKET_ERROR ? -1 : 0;
+}
+
+int
+nsock_listen(struct nsock *ns, int max)
+{
+	int ret;
+
+	ret = listen(ns->fd, max);
+
+	if (ret == SOCKET_ERROR)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return ret == SOCKET_ERROR ? -1 : 0;
+}
+
+int
+nsock_accept(struct nsock *ns, struct nsock **client, struct nsock_ep **clientinfo)
+{
+	struct sockaddr_storage *st = NULL;
+	socklen_t *len = NULL;
+	int ret;
+
+	if ((*client = malloc(sizeof (struct nsock))) == NULL) {
+		nsock_set_errno(ns->error, sizeof (ns->error), ENOMEM);
+		return -1;
+	}
+
+	if (clientinfo != NULL) {
+		if ((*clientinfo = malloc(sizeof (struct nsock_ep))) == NULL) {
+			free(client);
+			nsock_set_errno(ns->error, sizeof (ns->error), ENOMEM);
+			return -1;
+		}
+
+		st = &(*clientinfo)->addr;
+		len = &(*clientinfo)->addrlen;
+
+		/* Set the addrlen to sockaddr_storage first */
+		*len = sizeof (struct sockaddr_storage);
+	}
+
+	/* Prepare client */
+	memset((*client)->error, 0, sizeof ((*client)->error));
+	(*client)->fd = accept(ns->fd, (struct sockaddr *)st, len);
+
+	if ((*client)->fd == INVALID_SOCKET) {
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+		/* free clients and set to NULL so user will not use it */
+		free(*client);
+		*client = NULL;
+
+		if (clientinfo != NULL) {
+			free(*clientinfo);
+			*clientinfo = NULL;
+		}
+
+		ret = -1;
+	} else
+		ret = 0;
+
+	return ret;
+}
+
+int
+nsock_connect(struct nsock *ns, const struct nsock_ep *ep)
+{
+	int ret;
+
+	ret = connect(ns->fd, (const struct sockaddr *)&ep->addr, ep->addrlen);
+
+	if (ret == SOCKET_ERROR)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return ret == SOCKET_ERROR ? -1 : 0;
+}
+
+int
+nsock_set(struct nsock *ns, int level, int name, const void *arg, unsigned arglen)
+{
+	int ret;
+
+	ret = setsockopt(ns->fd, level, name, (nsock_carg_t)arg, arglen);
+
+	if (ret == SOCKET_ERROR)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return ret == SOCKET_ERROR ? -1 : 0;
+}
+
+long
+nsock_recv(struct nsock *ns, void *data, size_t datasz, int flags)
+{
+	long nbread;
+
+	nbread = recv(ns->fd, data, datasz, flags);
+
+	if (nbread == -1)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return nbread;
+}
+
+long
+nsock_recvfrom(struct nsock *ns, struct nsock_ep *ep, void *data, size_t datasz, int flags)
+{
+	struct sockaddr_storage *st = NULL;
+	socklen_t *len = NULL;
+	long nbread;
+
+	if (ep != NULL) {
+		st = &ep->addr;
+		len = &ep->addrlen;
+
+		/* Set the addrlen to sockaddr_storage first */
+		*len = sizeof (struct sockaddr_storage);
+	}
+
+	nbread = recvfrom(ns->fd, data, datasz, flags,
+	    (struct sockaddr *)st, len);
+
+	if (nbread == SOCKET_ERROR)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return nbread;
+}
+
+long
+nsock_send(struct nsock *ns, const void *data, size_t datasz, int flags)
+{
+	long nbsent;
+
+	nbsent = send(ns->fd, data, datasz, flags);
+
+	if (nbsent == -1)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return nbsent;
+}
+
+long
+nsock_sendto(struct nsock *ns, const struct nsock_ep *ep, const void *data, size_t datasz, int flags)
+{
+	long nbsent;
+
+	nbsent = sendto(ns->fd, data, datasz, flags,
+	    (const struct sockaddr *)&ep->addr, ep->addrlen);
+
+	if (nbsent == SOCKET_ERROR)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return nbsent;
+}
+
+void
+nsock_close(struct nsock *ns)
+{
+	closesocket(ns->fd);
+}
+
+void
+nsock_free(struct nsock *ns)
+{
+	free(ns);
+}
+
+void
+nsock_finish(void)
+{
+#if defined(_WIN32)
+	WSACleanup();
+#endif
+}
+
+/* --------------------------------------------------------
+ * End point functions
+ * -------------------------------------------------------- */
+
+struct nsock_ep *
+nsock_ep_create(void)
+{
+	struct nsock_ep *ep;
+
+	if ((ep = calloc(1, sizeof (struct nsock_ep))) == NULL)
+		return NULL;
+
+	return ep;
+}
+
+const char *
+nsock_ep_error(struct nsock_ep *ep)
+{
+	if (ep == NULL)
+		return strerror(ENOMEM);
+
+	return ep->error;
+}
+
+int
+nsock_ep_bind_ip(struct nsock_ep *ep, const char *iface, unsigned port, int family)
+{
+	if (family == AF_INET6) {
+		struct sockaddr_in6 *ptr = (struct sockaddr_in6 *)&ep->addr;
+
+		memset(ptr, 0, sizeof (struct sockaddr_in6));
+		ptr->sin6_family = AF_INET6;
+		ptr->sin6_port = htons(port);
+
+		if (iface == NULL || strcmp(iface, "*") == 0)
+			ptr->sin6_addr = in6addr_any;
+		else if (inet_pton(AF_INET6, iface, &ptr->sin6_addr) <= 0) {
+			nsock_set_error(ep->error, sizeof (ep->error));
+			return -1;
+		}
+
+		ep->addrlen = sizeof (struct sockaddr_in6);
+	} else {
+		struct sockaddr_in *ptr = (struct sockaddr_in *)&ep->addr;
+
+		memset(ptr, 0, sizeof (struct sockaddr_in));
+		ptr->sin_family = AF_INET;
+		ptr->sin_port = htons(port);
+
+		if (iface == NULL || strcmp(iface, "*") == 0)
+			ptr->sin_addr.s_addr = INADDR_ANY;
+		else if (inet_pton(AF_INET, iface, &ptr->sin_addr) <= 0) {
+			nsock_set_error(ep->error, sizeof (ep->error));
+			return -1;
+		}
+
+		ep->addrlen = sizeof (struct sockaddr_in);
+	}
+	
+	return 0;
+}
+
+int
+nsock_ep_connect_ip(struct nsock_ep *ep, const char *host, unsigned port, int family)
+{
+	struct addrinfo hints, *res;
+	char portstr[32];
+	int error;
+
+	memset(&hints, 0, sizeof (hints));
+	hints.ai_family = family;
+	hints.ai_socktype = SOCK_STREAM;
+
+	memset(portstr, 0, sizeof (portstr));
+	sprintf(portstr, "%u", port);
+
+	error = getaddrinfo(host, portstr, &hints, &res);
+	if (error) {
+		memset(ep->error, 0, sizeof (ep->error));
+		strncpy(ep->error, gai_strerrorA(error), sizeof (ep->error) - 1);
+		return -1;
+	}
+
+	memcpy(&ep->addr, res->ai_addr, res->ai_addrlen);
+	ep->addrlen = res->ai_addrlen;
+
+	freeaddrinfo(res);
+
+	return 0;
+}
+
+#if !defined(_WIN32)
+
+void
+nsock_ep_unix(struct nsock_ep *ep, const char *path)
+{
+	struct sockaddr_un *ptr= (struct sockaddr_un *)&ep->addr;
+
+	/* Path */
+	memset(ptr, 0, sizeof (struct sockaddr_un));
+	strncpy(ptr->sun_path, path, sizeof (ptr->sun_path) - 1);
+	ptr->sun_family = AF_UNIX;
+
+	/* Len is computed with SUN_LEN */
+	ep->addrlen = SUN_LEN(ptr);
+}
+
+#endif
+
+struct sockaddr *
+nsock_ep_getaddr(struct nsock_ep *ep)
+{
+	return (struct sockaddr *)&ep->addr;
+}
+
+socklen_t
+nsock_ep_getaddrlen(const struct nsock_ep *ep)
+{
+	return ep->addrlen;
+}
+
+void
+nsock_ep_free(struct nsock_ep *ep)
+{
+	free(ep);
+}
+
+/* --------------------------------------------------------
+ * listener functions
+ * -------------------------------------------------------- */
+
+struct nsock_listener *
+nsock_lst_create(const struct nsock *ns)
+{
+	struct nsock_listener *ls;	
+
+	if ((ls = malloc(sizeof (struct nsock_listener))) == NULL)
+		return NULL;
+
+	ls->sock = ns;	
+	TAILQ_INIT(&ls->head);
+
+	return ls;
+}
+
+const char *
+nsock_lst_error(struct nsock_listener *ls)
+{
+	if (ls == NULL)
+		return strerror(ENOMEM);
+
+	return ls->error;
+}
+
+int
+nsock_lst_push(struct nsock_listener *ls, struct nsock *ns)
+{
+	struct nsock_clt *clt;
+
+	if ((clt = nsock_clt_new(ns)) == NULL)
+		return -1;
+
+	TAILQ_INSERT_HEAD(&ls->head, clt, link);
+
+	return 0;
+}
+
+int
+nsock_lst_append(struct nsock_listener *ls, struct nsock *ns)
+{
+	struct nsock_clt *clt;
+
+	if ((clt = nsock_clt_new(ns)) == NULL)
+		return -1;
+
+	TAILQ_INSERT_TAIL(&ls->head, clt, link);
+
+	return 0;
+}
+
+size_t
+nsock_lst_count(const struct nsock_listener *ls)
+{
+	return ls->head.noclients;
+}
+
+void
+nsock_lst_remove(struct nsock_listener *ls, const struct nsock *ns)
+{
+	struct nsock_clt *clt, *tmp;
+
+	TAILQ_FOREACH_SAFE(clt, &ls->head, link, tmp) {
+		if (clt->sock == ns) {
+			TAILQ_REMOVE(&ls->head, clt, link);
+			free(clt);
+			break;
+		}
+	}
+}
+
+struct nsock *
+nsock_lst_select(struct nsock_listener *ls, long sec, long usec)
+{
+	fd_set fds;
+	struct timeval maxwait, *towait;
+	int error;
+	int fdmax;
+	struct nsock_clt *clt;
+
+	fdmax = TAILQ_FIRST(&ls->head)->sock->fd;
+
+	FD_ZERO(&fds);
+	TAILQ_FOREACH(clt, &ls->head, link) {
+		FD_SET(clt->sock->fd, &fds);
+		if ((int)clt->sock->fd > fdmax)
+			fdmax = clt->sock->fd;
+	}
+
+	maxwait.tv_sec = sec;
+	maxwait.tv_usec = usec;
+
+        // Set to NULL for infinite timeout.
+	towait = (sec == 0 && usec == 0) ? NULL : &maxwait;
+	error = select(fdmax + 1, &fds, NULL, NULL, towait);
+
+	TAILQ_FOREACH(clt, &ls->head, link)
+		if (FD_ISSET(clt->sock->fd, &fds))
+			return (struct nsock *)clt->sock;
+
+	return NULL;
+}
+
+void
+nsock_lst_free(struct nsock_listener *ls)
+{
+	struct nsock_clt *clt, *tmp;
+
+	TAILQ_FOREACH_SAFE(clt, &ls->head, link, tmp)
+		free(clt);
+
+	free(ls);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nsock.h	Thu Aug 22 17:40:54 2013 +0200
@@ -0,0 +1,169 @@
+/*
+ * nsock.h -- portable BSD sockets wrapper
+ *
+ * Copyright (c) 2013 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _NSOCK_H_
+#define _NSOCK_H_
+
+#if defined(_WIN32)
+#  include <WinSock2.h>
+#  include <WS2tcpip.h>
+
+typedef SOCKET			nsock_socket_t;
+typedef const char *		nsock_carg_t;
+typedef char *			nsock_arg_t;
+
+#else
+#  include <sys/types.h>
+#  include <sys/socket.h>
+#  include <sys/un.h>
+
+#  include <arpa/inet.h>
+
+#  include <netinet/in.h>
+
+#  include <netdb.h>
+#  include <unistd.h>
+
+#  define ioctlsocket(s)	ioctl(s)
+#  define closesocket(s)	close(s)
+
+#  define gai_strerrorA		gai_strerror
+
+#  define INVALID_SOCKET	-1
+#  define SOCKET_ERROR		-1
+
+typedef int			nsock_socket_t;
+typedef const void *		nsock_carg_t;
+typedef void *			nsock_arg_t;
+
+#endif
+
+struct nsock;
+struct nsock_ep;
+struct nsock_listener;
+
+/* --------------------------------------------------------
+ * Sockets functions
+ * -------------------------------------------------------- */
+
+void
+nsock_init(void);
+
+struct nsock *
+nsock_create(int, int, int);
+
+const char *
+nsock_error(struct nsock *);
+
+int
+nsock_bind(struct nsock *, const struct nsock_ep *);
+
+int
+nsock_listen(struct nsock *, int);
+
+int
+nsock_accept(struct nsock *, struct nsock **, struct nsock_ep **);
+
+int
+nsock_connect(struct nsock *, const struct nsock_ep *);
+
+int
+nsock_set(struct nsock *, int, int, const void *, unsigned);
+
+long
+nsock_recv(struct nsock *, void *, size_t, int);
+
+long
+nsock_recvfrom(struct nsock *, struct nsock_ep *, void *, size_t, int);
+
+long
+nsock_send(struct nsock *, const void *, size_t, int);
+
+long
+nsock_sendto(struct nsock *, const struct nsock_ep *, const void *, size_t, int);
+
+void
+nsock_close(struct nsock *);
+
+void
+nsock_free(struct nsock *);
+
+void
+nsock_finish(void);
+
+/* --------------------------------------------------------
+ * End point functions
+ * -------------------------------------------------------- */
+
+struct nsock_ep *
+nsock_ep_create(void);
+
+const char *
+nsock_ep_error(struct nsock_ep *);
+
+int
+nsock_ep_bind_ip(struct nsock_ep *, const char *, unsigned, int);
+
+int
+nsock_ep_connect_ip(struct nsock_ep *, const char *, unsigned, int);
+
+#if !defined(_WIN32)
+
+void
+nsock_ep_unix(struct nsock_ep *, const char *);
+
+#endif
+
+struct sockaddr *
+nsock_ep_getaddr(struct nsock_ep *);
+
+socklen_t
+nsock_ep_getaddrlen(const struct nsock_ep *);
+
+void
+nsock_ep_free(struct nsock_ep *);
+
+/* --------------------------------------------------------
+ * listener functions
+ * -------------------------------------------------------- */
+
+struct nsock_listener *
+nsock_lst_create(const struct nsock *);
+
+const char *
+nsock_lst_error(struct nsock_listener *);
+
+int
+nsock_lst_push(struct nsock_listener *, struct nsock *);
+
+int
+nsock_lst_append(struct nsock_listener *, struct nsock *);
+
+size_t
+nsock_lst_count(const struct nsock_listener *);
+
+void
+nsock_lst_remove(struct nsock_listener *, const struct nsock *);
+
+struct nsock *
+nsock_lst_select(struct nsock_listener *, long, long);
+
+void
+nsock_lst_free(struct nsock_listener *);
+
+#endif /* !_NSOCK_H_ */