%% options copyright owner = Dirk Krause copyright year = 2015-xxxx license = bsd %% module #include "dk4sock.h" #include "dk4mem.h" $!trace-include dk4_socket_set_t * dk4socket_set_server_directly( unsigned short portno, int backlog, int local, dk4_er_t *erp ) { #if DK4_HAVE_STRUCT_SOCKADDR_IN6 struct sockaddr_in6 soin6; #endif struct sockaddr_in soin4; dk4_socket_set_t *back = NULL; size_t max; int res; #if DK4_HAVE_SETSOCKOPT && (defined(SO_REUSEPORT) || defined(SO_REUSEADDR)) int opt; #endif if (0 < portno) { max = 1; #if DK4_HAVE_STRUCT_SOCKADDR_IN6 max++; #endif back = dk4socket_set_new(max, erp); if (NULL != back) { /* IPv4 address */ DK4_MEMRES(&soin4, sizeof(soin4)); soin4.sin_family = AF_INET; soin4.sin_port = dk4socket_htons(portno); if (0 != local) { soin4.sin_addr.s_addr = dk4socket_htonl(INADDR_LOOPBACK); } else { soin4.sin_addr.s_addr = dk4socket_htonl(INADDR_ANY); } (back->pSockets)[back->szUsed] = dk4socket_open( AF_INET, SOCK_STREAM, 0, erp ); if (INVALID_SOCKET != (back->pSockets)[back->szUsed]) { #if DK4_HAVE_SETSOCKOPT && defined(SO_REUSEPORT) dk4socket_set_one_bytes(&opt, sizeof(opt)); res = setsockopt( (back->pSockets)[back->szUsed], SOL_SOCKET, SO_REUSEPORT, (void *)(&opt), sizeof(opt) ); if (0 != res) { $? "! failed to reuse port number" } #else #if DK4_HAVE_SETSOCKOPT && defined(SO_REUSEADDR) $? ". SO_REUSEADDR" dk4socket_set_one_bytes(&opt, sizeof(opt)); res = setsockopt( (back->pSockets)[back->szUsed], SOL_SOCKET, SO_REUSEADDR, (void *)(&opt), sizeof(opt) ); if (0 != res) { $? "! failed to reuse address" } #else $? ". neither SO_REUSEPORT nor SO_REUSEADDR" #endif #endif res = dk4socket_bind( (back->pSockets)[back->szUsed], (struct sockaddr *)(&soin4), sizeof(soin4), erp ); if (DK4_SOCKET_RESULT_SUCCESS == res) { res = dk4socket_listen( (back->pSockets)[back->szUsed], backlog, erp ); if (DK4_SOCKET_RESULT_SUCCESS == res) { back->szUsed += 1; } else { (void)dk4socket_close((back->pSockets)[back->szUsed], NULL); (back->pSockets)[back->szUsed] = INVALID_SOCKET; } } else { (void)dk4socket_close((back->pSockets)[back->szUsed], NULL); (back->pSockets)[back->szUsed] = INVALID_SOCKET; } } /* IPv6 address if available */ #if DK4_HAVE_STRUCT_SOCKADDR_IN6 DK4_MEMRES(&soin6, sizeof(soin6)); soin6.sin6_family = AF_INET6; if (0 != local) { soin6.sin6_addr.s6_addr[15] = 0x01; } soin6.sin6_port = dk4socket_htons(portno); (back->pSockets)[back->szUsed] = dk4socket_open( AF_INET6, SOCK_STREAM, 0, erp ); if (INVALID_SOCKET != (back->pSockets)[back->szUsed]) { #if DK4_HAVE_SETSOCKOPT && defined(SO_REUSEPORT) dk4socket_set_one_bytes(&opt, sizeof(opt)); res = setsockopt( (back->pSockets)[back->szUsed], SOL_SOCKET, SO_REUSEPORT, (void *)(&opt), sizeof(opt) ); if (0 != res) { $? "! failed to reuse port number" } #else #if DK4_HAVE_SETSOCKOPT && defined(SO_REUSEADDR) $? ". SO_REUSEADDR" dk4socket_set_one_bytes(&opt, sizeof(opt)); res = setsockopt( (back->pSockets)[back->szUsed], SOL_SOCKET, SO_REUSEADDR, (void *)(&opt), sizeof(opt) ); if (0 != res) { $? "! failed to reuse address" } #else $? ". neither SO_REUSEPORT nor SO_REUSEADDR" #endif #endif res = dk4socket_bind( (back->pSockets)[back->szUsed], (struct sockaddr *)(&soin6), sizeof(soin6), erp ); if (DK4_SOCKET_RESULT_SUCCESS == res) { res = dk4socket_listen( (back->pSockets)[back->szUsed], backlog, erp ); if (DK4_SOCKET_RESULT_SUCCESS == res) { back->szUsed += 1; } else { (void)dk4socket_close((back->pSockets)[back->szUsed], NULL); (back->pSockets)[back->szUsed] = INVALID_SOCKET; } } else { (void)dk4socket_close((back->pSockets)[back->szUsed], NULL); (back->pSockets)[back->szUsed] = INVALID_SOCKET; } } #endif if (0 == back->szUsed) { dk4socket_set_delete(back, NULL); back = NULL; } } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; }