summaryrefslogtreecommitdiffstats
path: root/src/shared/sockhelper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/sockhelper.c')
-rw-r--r--src/shared/sockhelper.c42
1 files changed, 26 insertions, 16 deletions
diff --git a/src/shared/sockhelper.c b/src/shared/sockhelper.c
index ab34aa1..5096320 100644
--- a/src/shared/sockhelper.c
+++ b/src/shared/sockhelper.c
@@ -1,6 +1,8 @@
-#include "sockhelper.h"
-#include "log.h"
+#include <dnbd3/shared/sockhelper.h>
+#include <dnbd3/shared/log.h>
+#include <dnbd3/types.h>
#include <arpa/inet.h> // inet_ntop
+#include <netinet/tcp.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
@@ -19,8 +21,7 @@ struct _poll_list {
int sock_connect(const dnbd3_host_t * const addr, const int connect_ms, const int rw_ms)
{
// TODO: Move out of here, this unit should contain general socket functions
- // TODO: Abstract away from sockaddr_in* like the rest of the functions here do,
- // so WITH_IPV6 can finally be removed as everything is transparent. b- but how?
+ // TODO: Abstract away from sockaddr_in* like the rest of the functions here
struct sockaddr_storage ss;
int proto, addrlen;
memset( &ss, 0, sizeof ss );
@@ -32,9 +33,7 @@ int sock_connect(const dnbd3_host_t * const addr, const int connect_ms, const in
addr4->sin_port = addr->port;
proto = PF_INET;
addrlen = sizeof *addr4;
- }
-#ifdef WITH_IPV6
- else if ( addr->type == HOST_IP6 ) {
+ } else if ( addr->type == HOST_IP6 ) {
// Set host (IPv6)
struct sockaddr_in6 *addr6 = (struct sockaddr_in6*)&ss;
addr6->sin6_family = AF_INET6;
@@ -42,10 +41,9 @@ int sock_connect(const dnbd3_host_t * const addr, const int connect_ms, const in
addr6->sin6_port = addr->port;
proto = PF_INET6;
addrlen = sizeof *addr6;
- }
-#endif
- else {
+ } else {
logadd( LOG_DEBUG1, "Unsupported address type: %d\n", (int)addr->type );
+ errno = EAFNOSUPPORT;
return -1;
}
int client_sock = socket( proto, SOCK_STREAM, IPPROTO_TCP );
@@ -56,9 +54,13 @@ int sock_connect(const dnbd3_host_t * const addr, const int connect_ms, const in
} else {
sock_setTimeout( client_sock, connect_ms );
}
+ // NODELAY makes sense for the client side, which should be all users in this code base
+ int e2 = 1;
+ setsockopt( client_sock, IPPROTO_TCP, TCP_NODELAY, (void *)&e2, sizeof(e2) );
for ( int i = 0; i < 5; ++i ) {
int ret = connect( client_sock, (struct sockaddr *)&ss, addrlen );
- if ( ret != -1 || errno == EINPROGRESS || errno == EISCONN ) break;
+ e2 = errno;
+ if ( ret != -1 || ( connect_ms == -1 && errno == EINPROGRESS ) || errno == EISCONN ) break;
if ( errno == EINTR ) {
// http://www.madore.org/~david/computers/connect-intr.html
#ifdef __linux__
@@ -67,21 +69,26 @@ int sock_connect(const dnbd3_host_t * const addr, const int connect_ms, const in
struct pollfd unix_really_sucks = { .fd = client_sock, .events = POLLOUT | POLLIN };
while ( i-- > 0 ) {
int pr = poll( &unix_really_sucks, 1, connect_ms == 0 ? -1 : connect_ms );
+ e2 = errno;
if ( pr == 1 && ( unix_really_sucks.revents & POLLOUT ) ) break;
if ( pr == -1 && errno == EINTR ) continue;
close( client_sock );
+ errno = e2;
return -1;
}
- sockaddr_storage junk;
+ struct sockaddr_storage junk;
socklen_t more_junk = sizeof(junk);
if ( getpeername( client_sock, (struct sockaddr*)&junk, &more_junk ) == -1 ) {
+ e2 = errno;
close( client_sock );
+ errno = e2;
return -1;
}
break;
#endif
} // EINTR
close( client_sock );
+ errno = e2;
return -1;
}
if ( connect_ms != -1 && connect_ms != rw_ms ) {
@@ -157,7 +164,7 @@ bool sock_sockaddrToDnbd3(struct sockaddr* sa, dnbd3_host_t *host)
memcpy( host->addr, &addr4->sin_addr, 4 );
return true;
}
-#ifdef WITH_IPV6
+
if ( sa->sa_family == AF_INET6 ) {
// Set host (IPv6)
struct sockaddr_in6 *addr6 = (struct sockaddr_in6*)sa;
@@ -166,7 +173,7 @@ bool sock_sockaddrToDnbd3(struct sockaddr* sa, dnbd3_host_t *host)
memcpy( host->addr, &addr6->sin6_addr, 16 );
return true;
}
-#endif
+
return false;
}
@@ -234,7 +241,10 @@ size_t sock_printable(const struct sockaddr * const addr, const socklen_t addrLe
outlen = snprintf( output, len, "[%s]:%s", host, port );
}
}
- if ( outlen <= 0 ) return 0;
+ if ( outlen <= 0 ) {
+ output[0] = '\0';
+ return 0;
+ }
return MIN( (size_t)outlen, len-1 );
}
@@ -338,7 +348,7 @@ int sock_multiConnect(poll_list_t* list, const dnbd3_host_t* host, int connect_m
if ( i != list->count ) list->entry[i] = list->entry[list->count];
if ( fd != -1 ) {
sock_set_block( fd );
- if ( rw_ms != -1 && rw_ms != connect_ms ) {
+ if ( rw_ms != -1 ) {
sock_setTimeout( fd, rw_ms );
}
return fd;