Add configure test for arpa/inet.h
[deb_libnfs.git] / lib / socket.c
index c746c76affeb2efe123aa3ec752040eec281be34..8dc3ed2d6b0d5a9fc1a5d731f2cd96bd3ad0d48c 100644 (file)
    You should have received a copy of the GNU Lesser General Public License
    along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef AROS
+#include "aros_compat.h"
+#endif
+
 #ifdef WIN32
 #include "win32_compat.h"
-#else
-#include <unistd.h>
-#include <poll.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
 #include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
-#include <netdb.h>
-#endif/*WIN32*/
+#endif
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
 #endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <rpc/rpc.h>
-#include <rpc/xdr.h>
+
 #ifdef HAVE_SYS_FILIO_H
 #include <sys/filio.h>
 #endif
+
 #ifdef HAVE_SYS_SOCKIO_H
 #include <sys/sockio.h>
 #endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
 #include <sys/types.h>
+#include "libnfs-zdr.h"
 #include "libnfs.h"
 #include "libnfs-raw.h"
 #include "libnfs-private.h"
@@ -61,7 +85,7 @@ static void set_nonblocking(int fd)
        int v = 0;
 #if defined(WIN32)
        long nonblocking=1;
-       v = ioctlsocket(fd, FIONBIO,&nonblocking);
+       v = ioctl(fd, FIONBIO, &nonblocking);
 #else
        v = fcntl(fd, F_GETFL, 0);
         fcntl(fd, F_SETFL, v | O_NONBLOCK);
@@ -70,12 +94,18 @@ static void set_nonblocking(int fd)
 
 int rpc_get_fd(struct rpc_context *rpc)
 {
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
        return rpc->fd;
 }
 
 int rpc_which_events(struct rpc_context *rpc)
 {
-       int events = rpc->is_connected ? POLLIN : POLLOUT;
+       int events;
+
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
+       events = rpc->is_connected ? POLLIN : POLLOUT;
 
        if (rpc->is_udp != 0) {
                /* for udp sockets we only wait for pollin */
@@ -90,11 +120,10 @@ int rpc_which_events(struct rpc_context *rpc)
 
 static int rpc_write_to_socket(struct rpc_context *rpc)
 {
-       int64_t count;
+       int32_t count;
+
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
 
-       if (rpc == NULL) {
-               return -1;
-       }
        if (rpc->fd == -1) {
                rpc_set_error(rpc, "trying to write but not connected");
                return -1;
@@ -105,11 +134,7 @@ static int rpc_write_to_socket(struct rpc_context *rpc)
 
                total = rpc->outqueue->outdata.size;
 
-#if defined(WIN32)
                count = send(rpc->fd, rpc->outqueue->outdata.data + rpc->outqueue->written, total - rpc->outqueue->written, 0);
-#else
-               count = write(rpc->fd, rpc->outqueue->outdata.data + rpc->outqueue->written, total - rpc->outqueue->written);
-#endif
                if (count == -1) {
                        if (errno == EAGAIN || errno == EWOULDBLOCK) {
                                return 0;
@@ -134,13 +159,13 @@ static int rpc_read_from_socket(struct rpc_context *rpc)
        int available;
        int size;
        int pdu_size;
-       int64_t count;
+       int32_t count;
+
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
 
-#if defined(WIN32)
-       if (ioctlsocket(rpc->fd, FIONREAD, &available) != 0) {
-#else
        if (ioctl(rpc->fd, FIONREAD, &available) != 0) {
-#endif
                rpc_set_error(rpc, "Ioctl FIONREAD returned error : %d. Closing socket.", errno);
                return -1;
        }
@@ -185,11 +210,7 @@ static int rpc_read_from_socket(struct rpc_context *rpc)
        if (rpc->inpos < 4) {
                size = 4 - rpc->inpos;
 
-#if defined(WIN32)
                count = recv(rpc->fd, rpc->inbuf + rpc->inpos, size, 0);
-#else
-               count = read(rpc->fd, rpc->inbuf + rpc->inpos, size);
-#endif
                if (count == -1) {
                        if (errno == EINTR) {
                                return 0;
@@ -225,11 +246,7 @@ static int rpc_read_from_socket(struct rpc_context *rpc)
                size = rpc->insize - rpc->inpos;
        }
 
-#if defined(WIN32)
        count = recv(rpc->fd, rpc->inbuf + rpc->inpos, size, 0);
-#else
-       count = read(rpc->fd, rpc->inbuf + rpc->inpos, size);
-#endif
        if (count == -1) {
                if (errno == EINTR) {
                        return 0;
@@ -258,6 +275,8 @@ static int rpc_read_from_socket(struct rpc_context *rpc)
 
 int rpc_service(struct rpc_context *rpc, int revents)
 {
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
        if (revents & POLLERR) {
 #ifdef WIN32
                char err = 0;
@@ -336,11 +355,15 @@ int rpc_service(struct rpc_context *rpc, int revents)
 
 void rpc_set_autoreconnect(struct rpc_context *rpc)
 {
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
        rpc->auto_reconnect = 1;
 }
 
 void rpc_unset_autoreconnect(struct rpc_context *rpc)
 {
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
        rpc->auto_reconnect = 0;
 }
 
@@ -348,6 +371,8 @@ static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_s
 {
        int socksize;
 
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
        switch (s->ss_family) {
        case AF_INET:
                socksize = sizeof(struct sockaddr_in);
@@ -386,8 +411,12 @@ static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_s
                static int portOfs = 0;
                const int firstPort = 512;      /* >= 512 according to Sun docs */
                const int portCount = IPPORT_RESERVED - firstPort;
-               int startOfs = portOfs, port, rc;
+               int startOfs, port, rc;
 
+               if (portOfs == 0) {
+                       portOfs = time(NULL) % 400;
+               }
+               startOfs = portOfs;
                do {
                        rc = -1;
                        port = htons(firstPort + portOfs);
@@ -412,13 +441,8 @@ static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_s
 
        set_nonblocking(rpc->fd);
 
-#if defined(WIN32)
-       if (connect(rpc->fd, (struct sockaddr *)s, socksize) == 0 && errno != EINPROGRESS   )
-#else
-       if (connect(rpc->fd, (struct sockaddr *)s, socksize) != 0 && errno != EINPROGRESS) 
-#endif
-       {
-         rpc_set_error(rpc, "connect() to server failed. %s(%d)", strerror(errno), errno);
+       if (connect(rpc->fd, (struct sockaddr *)s, socksize) != 0 && errno != EINPROGRESS) {
+               rpc_set_error(rpc, "connect() to server failed. %s(%d)", strerror(errno), errno);
                return -1;
        }               
 
@@ -429,6 +453,8 @@ int rpc_connect_async(struct rpc_context *rpc, const char *server, int port, rpc
 {
        struct sockaddr_in *sin = (struct sockaddr_in *)&rpc->s;
 
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
        if (rpc->fd != -1) {
                rpc_set_error(rpc, "Trying to connect while already connected");
                return -1;
@@ -469,14 +495,12 @@ int rpc_connect_async(struct rpc_context *rpc, const char *server, int port, rpc
 
 int rpc_disconnect(struct rpc_context *rpc, char *error)
 {
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
        rpc_unset_autoreconnect(rpc);
 
        if (rpc->fd != -1) {
-#if defined(WIN32)
-               closesocket(rpc->fd);
-#else
                close(rpc->fd);
-#endif
        }
        rpc->fd  = -1;
 
@@ -489,6 +513,8 @@ int rpc_disconnect(struct rpc_context *rpc, char *error)
 
 static void reconnect_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data)
 {
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
        if (status != RPC_STATUS_SUCCESS) {
                rpc_error_all_pdus(rpc, "RPC ERROR: Failed to reconnect async");
                return;
@@ -503,12 +529,10 @@ static int rpc_reconnect_requeue(struct rpc_context *rpc)
 {
        struct rpc_pdu *pdu;
 
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
        if (rpc->fd != -1) {
-#if defined(WIN32)
-               closesocket(rpc->fd);
-#else
                close(rpc->fd);
-#endif
        }
        rpc->fd  = -1;
 
@@ -542,6 +566,8 @@ int rpc_bind_udp(struct rpc_context *rpc, char *addr, int port)
        struct addrinfo *ai = NULL;
        char service[6];
 
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
        if (rpc->is_udp == 0) {
                rpc_set_error(rpc, "Cant not bind UDP. Not UDP context");
                return -1;
@@ -585,6 +611,8 @@ int rpc_set_udp_destination(struct rpc_context *rpc, char *addr, int port, int i
        struct addrinfo *ai = NULL;
        char service[6];
 
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
        if (rpc->is_udp == 0) {
                rpc_set_error(rpc, "Can not set destination sockaddr. Not UDP context");
                return -1;
@@ -604,6 +632,7 @@ int rpc_set_udp_destination(struct rpc_context *rpc, char *addr, int port, int i
        rpc->udp_dest = malloc(ai->ai_addrlen);
        if (rpc->udp_dest == NULL) {
                rpc_set_error(rpc, "Out of memory. Failed to allocate sockaddr structure");
+               freeaddrinfo(ai);
                return -1;
        }
        memcpy(rpc->udp_dest, ai->ai_addr, ai->ai_addrlen);
@@ -617,6 +646,8 @@ int rpc_set_udp_destination(struct rpc_context *rpc, char *addr, int port, int i
 
 struct sockaddr *rpc_get_recv_sockaddr(struct rpc_context *rpc)
 {
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
        return (struct sockaddr *)&rpc->udp_src;
 }
 
@@ -625,6 +656,8 @@ int rpc_queue_length(struct rpc_context *rpc)
        int i=0;
        struct rpc_pdu *pdu;
 
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
        for(pdu = rpc->outqueue; pdu; pdu = pdu->next) {
                i++;
        }