X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=lib%2Fsocket.c;h=055109a73c9f7b4be1f69d73f0552feb5c2d51ff;hb=c8f0bac1bbe9b0e70607979d51b74e59304fcc41;hp=1dbbdeae5eb5c21758f5e1c7789765f706706d71;hpb=d7c6e9aaa9df593e951e2f19106dcc71102e74f1;p=deb_libnfs.git diff --git a/lib/socket.c b/lib/socket.c index 1dbbdea..055109a 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -14,16 +14,6 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, see . */ -#ifdef WIN32 -#include "win32_compat.h" -#else -#include -#include -#include -#include -#include -#endif/*WIN32*/ - #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -32,22 +22,52 @@ #include "aros_compat.h" #endif +#ifdef WIN32 +#include "win32_compat.h" +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + #ifdef HAVE_POLL_H #include #endif -#include -#include -#include -#include -#include -#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_TCP_H +#include +#endif + +#ifdef HAVE_NETDB_H +#include +#endif + #ifdef HAVE_SYS_FILIO_H #include #endif + #ifdef HAVE_SYS_SOCKIO_H #include #endif + +#include +#include +#include +#include +#include +#include #include #include "libnfs-zdr.h" #include "libnfs.h" @@ -69,13 +89,33 @@ 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); #endif //FIXME } +#ifdef HAVE_NETINET_TCP_H +int set_tcp_sockopt(int sockfd, int optname, int value) +{ + int level; + + #if defined(__FreeBSD__) || defined(__sun) || (defined(__APPLE__) && defined(__MACH__)) + struct protoent *buf; + + if ((buf = getprotobyname("tcp")) != NULL) + level = buf->p_proto; + else + return -1; + #else + level = SOL_TCP; + #endif + + return setsockopt(sockfd, level, optname, (char *)&value, sizeof(value)); +} +#endif + int rpc_get_fd(struct rpc_context *rpc) { assert(rpc->magic == RPC_CONTEXT_MAGIC); @@ -118,11 +158,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; @@ -151,13 +187,7 @@ static int rpc_read_from_socket(struct rpc_context *rpc) 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; } @@ -180,6 +210,7 @@ static int rpc_read_from_socket(struct rpc_context *rpc) if (count < 0) { rpc_set_error(rpc, "Failed recvfrom: %s", strerror(errno)); free(buf); + return -1; } if (rpc_process_pdu(rpc, buf, count) != 0) { rpc_set_error(rpc, "Invalid/garbage pdu received from server. Ignoring PDU"); @@ -202,11 +233,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,7 +252,7 @@ static int rpc_read_from_socket(struct rpc_context *rpc) pdu_size = rpc_get_pdu_size(rpc->inbuf); if (rpc->insize < pdu_size) { unsigned char *buf; - + buf = malloc(pdu_size); if (buf == NULL) { rpc_set_error(rpc, "Failed to allocate buffer of %d bytes for pdu, errno:%d. Closing socket.", pdu_size, errno); @@ -242,11 +269,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,14 +281,17 @@ static int rpc_read_from_socket(struct rpc_context *rpc) rpc->inpos += count; if (rpc->inpos == rpc->insize) { - if (rpc_process_pdu(rpc, rpc->inbuf, pdu_size) != 0) { - rpc_set_error(rpc, "Invalid/garbage pdu received from server. Closing socket"); - return -1; - } - free(rpc->inbuf); + char *buf = rpc->inbuf; + rpc->inbuf = NULL; rpc->insize = 0; rpc->inpos = 0; + + if (rpc_process_pdu(rpc, buf, pdu_size) != 0) { + rpc_set_error(rpc, "Invalid/garbage pdu received from server. Closing socket"); + return -1; + } + free(buf); } return 0; @@ -367,6 +393,17 @@ void rpc_unset_autoreconnect(struct rpc_context *rpc) rpc->auto_reconnect = 0; } +void rpc_set_tcp_syncnt(struct rpc_context *rpc, int v) +{ + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + rpc->tcp_syncnt = v; +} + +#ifndef TCP_SYNCNT +#define TCP_SYNCNT 7 +#endif + static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_storage *s) { int socksize; @@ -377,6 +414,11 @@ static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_s case AF_INET: socksize = sizeof(struct sockaddr_in); rpc->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); +#ifdef HAVE_NETINET_TCP_H + if (rpc->tcp_syncnt != RPC_PARAM_UNDEFINED) { + set_tcp_sockopt(rpc->fd, TCP_SYNCNT, rpc->tcp_syncnt); + } +#endif break; default: rpc_set_error(rpc, "Can not handle AF_FAMILY:%d", s->ss_family); @@ -411,8 +453,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); @@ -440,10 +486,10 @@ static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_s 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; - } + } return 0; -} +} int rpc_connect_async(struct rpc_context *rpc, const char *server, int port, rpc_cb cb, void *private_data) { @@ -487,7 +533,7 @@ int rpc_connect_async(struct rpc_context *rpc, const char *server, int port, rpc } return 0; -} +} int rpc_disconnect(struct rpc_context *rpc, char *error) { @@ -496,11 +542,7 @@ int rpc_disconnect(struct rpc_context *rpc, char *error) rpc_unset_autoreconnect(rpc); if (rpc->fd != -1) { -#if defined(WIN32) - closesocket(rpc->fd); -#else close(rpc->fd); -#endif } rpc->fd = -1; @@ -532,11 +574,7 @@ static int rpc_reconnect_requeue(struct rpc_context *rpc) assert(rpc->magic == RPC_CONTEXT_MAGIC); if (rpc->fd != -1) { -#if defined(WIN32) - closesocket(rpc->fd); -#else close(rpc->fd); -#endif } rpc->fd = -1; @@ -580,7 +618,7 @@ int rpc_bind_udp(struct rpc_context *rpc, char *addr, int port) sprintf(service, "%d", port); if (getaddrinfo(addr, service, NULL, &ai) != 0) { rpc_set_error(rpc, "Invalid address:%s. " - "Can not resolv into IPv4/v6 structure."); + "Can not resolv into IPv4/v6 structure.", addr); return -1; } @@ -588,13 +626,13 @@ int rpc_bind_udp(struct rpc_context *rpc, char *addr, int port) case AF_INET: rpc->fd = socket(ai->ai_family, SOCK_DGRAM, 0); if (rpc->fd == -1) { - rpc_set_error(rpc, "Failed to create UDP socket: %s", strerror(errno)); + rpc_set_error(rpc, "Failed to create UDP socket: %s", strerror(errno)); freeaddrinfo(ai); return -1; } if (bind(rpc->fd, (struct sockaddr *)ai->ai_addr, sizeof(struct sockaddr_in)) != 0) { - rpc_set_error(rpc, "Failed to bind to UDP socket: %s",strerror(errno)); + rpc_set_error(rpc, "Failed to bind to UDP socket: %s",strerror(errno)); freeaddrinfo(ai); return -1; } @@ -625,7 +663,7 @@ int rpc_set_udp_destination(struct rpc_context *rpc, char *addr, int port, int i sprintf(service, "%d", port); if (getaddrinfo(addr, service, NULL, &ai) != 0) { rpc_set_error(rpc, "Invalid address:%s. " - "Can not resolv into IPv4/v6 structure."); + "Can not resolv into IPv4/v6 structure.", addr); return -1; } @@ -670,3 +708,10 @@ int rpc_queue_length(struct rpc_context *rpc) } return i; } + +void rpc_set_fd(struct rpc_context *rpc, int fd) +{ + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + rpc->fd = fd; +}