summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/network/README5
-rw-r--r--tests/GNUmakefile2
-rw-r--r--tests/Makefile.W322
-rw-r--r--tests/network/test2.c122
4 files changed, 83 insertions, 48 deletions
diff --git a/docs/network/README b/docs/network/README
index d2829e5..9bf3cc4 100644
--- a/docs/network/README
+++ b/docs/network/README
@@ -14,6 +14,11 @@ Goals:
- reach the 100MBit/s sustained transfer rate (yes I know, there are
Gigabits/s NICs out there, but their speed is almost impossible to
reach)
+- low-level abstraction should try not to hide the BSD-API, but try to
+ nivelate things in the direction of POSIX. So we are later able to
+ add specific Unix or Windows code where we want. An abstraction as
+ in Poco hinders us doing this because we have to think about everything
+ from the beginning!
Links:
- Boost ASIO: on design
diff --git a/tests/GNUmakefile b/tests/GNUmakefile
index 405e207..b5a23cc 100644
--- a/tests/GNUmakefile
+++ b/tests/GNUmakefile
@@ -1,6 +1,6 @@
TOPDIR = ..
-SUBDIRS = threads port log gettext daemon service network
+SUBDIRS = threads port log gettext network daemon service
-include $(TOPDIR)/makefiles/gmake/sub.mk
diff --git a/tests/Makefile.W32 b/tests/Makefile.W32
index f76c295..2b592c9 100644
--- a/tests/Makefile.W32
+++ b/tests/Makefile.W32
@@ -1,6 +1,6 @@
TOPDIR = ..
-SUBDIRS = threads port log service network
+SUBDIRS = threads port log network service
!INCLUDE $(TOPDIR)\makefiles\nmake\sub.mk
diff --git a/tests/network/test2.c b/tests/network/test2.c
index 9b30a9d..f0e711a 100644
--- a/tests/network/test2.c
+++ b/tests/network/test2.c
@@ -20,6 +20,8 @@
#define DEBUG 0
+#define ACCEPT_TIMEOUT 5
+
static bool wolf_network_sock_nonblocking( int fd ) {
int flags;
@@ -41,6 +43,11 @@ int main( int argc, char* argv[] ) {
struct addrinfo *result;
wolf_network_sockaddr_union_t client_addr;
socklen_t client_addr_len;
+ fd_set read_set;
+ struct timeval timeout;
+ char client_hostname[NI_MAXHOST] = "";
+ char client_service[NI_MAXSERV] = "";
+ int on;
if( argc != 3 ) {
fprintf( stderr, "usage: test2 <host> <port>\n" );
@@ -77,7 +84,17 @@ int main( int argc, char* argv[] ) {
goto FAIL;
}
- /* setsockopt SO_REUSEADDR */
+ /* setsockopt SO_REUSEADDR, this is handy while testing or deployment, in
+ * production in can lead to a certain type of rerouting packets to wrong
+ * servers
+ */
+ on = 1;
+ res = setsockopt( serv_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof( on ) );
+ if( res < 0 ) {
+ (void)close( serv_fd );
+ fprintf( stderr, "setsockopt(SO_REUSEADDR) failed: %s (%d)\n", strerror( errno ), errno );
+ goto FAIL;
+ }
/* bind server socket */
res = bind( serv_fd, result->ai_addr, result->ai_addrlen );
@@ -105,6 +122,7 @@ int main( int argc, char* argv[] ) {
/* accept the connection in the kernel, select ready for ready tells us there
* is a connection ready. Then we have to call accept again and check the result
*/
+FIRST_ACCEPT_AGAIN:
client_addr_len = sizeof( client_addr );
res = accept( serv_fd, &client_addr.addr, &client_addr_len );
if( res < 0 ) {
@@ -117,33 +135,74 @@ int main( int argc, char* argv[] ) {
}
}
-#if 0
+ /* go into a select and wait till we are ready for read (this indicates a
+ * possibly new connection)
+ */
+ACCEPT_SELECT_AGAIN:
FD_ZERO( &read_set );
- FD_ZERO( &write_set );
- FD_SET( fd, &read_set );
- FD_SET( fd, &write_set );
- timeout.tv_sec = CONNECT_TIMEOUT;
+ FD_SET( serv_fd, &read_set );
+ timeout.tv_sec = ACCEPT_TIMEOUT;
timeout.tv_usec = 0;
- res = select( fd + 1, &read_set, &write_set, NULL, &timeout );
+
+ res = select( serv_fd + 1, &read_set, NULL, NULL, &timeout );
if( res < 0 ) {
if( errno == EINTR || errno == EAGAIN ) {
- goto CONNECT_SELECT_AGAIN;
+ goto ACCEPT_SELECT_AGAIN;
} else {
/* fatal errors */
- fprintf( stderr, "select failed: %s (%d)\n",
+ fprintf( stderr, "accept/select failed: %s (%d)\n",
strerror( errno ), errno );
- (void)close( fd );
+ (void)close( serv_fd );
goto FAIL;
}
} else if( res == 0 ) {
- /* connect timeout */
- fprintf( stderr, "Connect timeout..terminating\n" );
- goto FAIL;
+ /* accept timeout, here we could to periodic stuff, also if we
+ * get blocked somewhere above we could recover..
+ */
+ fprintf( stderr, "Idle. No new connections..\n" );
+ goto ACCEPT_SELECT_AGAIN;
} else {
- if( FD_ISSET( fd, &read_set ) || FD_ISSET( fd, &write_set ) ) {
- socklen_t sock_error_len;
- int sock_error;
-#endif
+ if( FD_ISSET( serv_fd, &read_set ) ) {
+ /* this is a new connection */
+ } else {
+ /* can't happen! */
+ assert( false );
+ }
+ }
+
+ /* second accept, now we have to check for possible "short-and-run-away"
+ * connects.
+ */
+ACCEPT_AGAIN:
+ client_addr_len = sizeof( client_addr );
+ res = accept( serv_fd, &client_addr.addr, &client_addr_len );
+ if( res < 0 ) {
+ if( errno == EINTR ) {
+ /* interrupted, again */
+ goto ACCEPT_AGAIN;
+ } else if( errno == ECONNABORTED || errno == EPROTO ) {
+ /* connection run away */
+ goto FIRST_ACCEPT_AGAIN;
+ } else {
+ (void)close( serv_fd );
+ fprintf( stderr, "second non-blocking accept failed: %s (%d)\n", strerror( errno ), errno );
+ goto FAIL;
+ }
+ }
+
+ /* determine where the request came from */
+ res = getnameinfo( &client_addr.addr, client_addr_len,
+ client_hostname, NI_MAXHOST,
+ client_service, NI_MAXSERV,
+ NI_NUMERICSERV | NI_NUMERICHOST );
+ if( res < 0 ) {
+ (void)close( serv_fd );
+ fprintf( stderr, "getnameinfo failed: %s (%d)\n",
+ gai_strerror( error ), error );
+ goto FAIL;
+ }
+
+ fprintf( stderr, "New connection from %s, port %s\n", client_hostname, client_service );
goto OK;
@@ -221,14 +280,6 @@ int main( int argc, char *argv[] ) {
bool stdin_eof;
bool fd_write_closed;
bool fd_eof;
- int max_fd;
- fd_set read_set;
- fd_set write_set;
- struct timeval timeout;
- socklen_t peer_addr_len;
- union sockaddr_union peer_addr;
- char peer_hostname[NI_MAXHOST] = "";
- char peer_service[NI_MAXSERV] = "";
CONNECT_SELECT_AGAIN:
sock_error_len = sizeof( int );
@@ -256,27 +307,6 @@ CONNECT_SELECT_AGAIN:
}
CONNECTED:
- /* determine the address of the other end of the connection */
- peer_addr_len = sizeof( peer_addr );
- res = getsockname( fd, &peer_addr.addr, &peer_addr_len );
- if( res < 0 ) {
- (void)close( fd );
- fprintf( stderr, "getsockname failed: %s (%d)\n", strerror( errno ), errno );
- goto FAIL;
- }
- res = getnameinfo( &peer_addr.addr, peer_addr_len,
- peer_hostname, NI_MAXHOST,
- peer_service, NI_MAXSERV,
- NI_NUMERICSERV | NI_NUMERICHOST );
- if( res < 0 ) {
- (void)close( fd );
- fprintf( stderr, "getnameinfo failed: %s (%d)\n",
- gai_strerror( error ), error );
- goto FAIL;
- }
-
- fprintf( stderr, "Connected to %s, port %s (peer: %s, %s)\n", host, service,
- peer_hostname, peer_service );
idle_secs = 0;
count = 0;