AC_CHECK_LIB([sodium],[crypto_hash_sha256_init])
# Checks for header files.
-AC_CHECK_HEADERS([stdlib.h string.h])
+AC_CHECK_HEADERS([fcntl.h inttypes.h netdb.h stddef.h stdint.h stdlib.h string.h sys/socket.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_TYPE_UINT64_T
+AC_TYPE_UINT8_T
# Checks for library functions.
AC_FUNC_MALLOC
-AC_CHECK_FUNCS([atexit])
+AC_FUNC_MKTIME
+AC_CHECK_FUNCS([atexit memmove memset mkdir setenv socket strchr strdup strndup strpbrk strrchr strstr strtoul strtoull])
AC_CONFIG_FILES([Makefile
bench/Makefile
#include<sys/socket.h>
#include<unistd.h>
-int start();
+struct net_info {
+ int tcp;
+ int udp;
+};
+
+#define NET_MESSAGE_SHUTDOWN_FAILED "net thread shutdown failed\n"
+
+#define HINTS_INIT(hints,socktype) { \
+ memset(&hints,0,sizeof(struct addrinfo)); \
+\
+ hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ \
+ hints.ai_socktype = socktype; /* */ \
+ hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ \
+ hints.ai_protocol = 0; \
+ hints.ai_canonname = NULL; \
+ hints.ai_addr = NULL; \
+ hints.ai_next = NULL; \
+}
+
+int net_listen_sock();
+void net_loop();
+int net_start();
+int net_tcp();
+int net_udp();
#endif
--- /dev/null
+#include<net.h>
+
+int net_listen_sock(struct addrinfo *hints) {
+ struct addrinfo *p, *res;
+ int sock_fd;
+
+ if(getaddrinfo(NULL,global_options.port,hints,&res)!=0) {
+ perror("getaddrinfo");
+ return -1;
+ }
+
+ for(p=res;p!=NULL;p=p->ai_next) {
+ sock_fd = socket(p->ai_family,p->ai_socktype,p->ai_protocol);
+ if(sock_fd<0) { continue; }
+
+ if(bind(sock_fd,p->ai_addr,p->ai_addrlen)==0) { break; /* Success */ }
+
+ close(sock_fd);
+ }
+
+ free(res);
+
+ if(p==NULL) { return -1; }
+
+ return sock_fd;
+}
#include<net.h>
-#define MAX_BACKLOG 10
-
-static int listen_sock();
-static int tcp();
-static int udp();
-
-#define HINTS_INIT(hints,socktype) { \
- memset(&hints,0,sizeof(struct addrinfo)); \
-\
- hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ \
- hints.ai_socktype = socktype; /* */ \
- hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ \
- hints.ai_protocol = 0; \
- hints.ai_canonname = NULL; \
- hints.ai_addr = NULL; \
- hints.ai_next = NULL; \
-}
+static pthread_t *net_threads;
-static int tcp() {
- struct addrinfo hints;
- int sock_fd;
+static void net_shutdown();
+static void *net_spawn(void*);
+static void net_stop();
- HINTS_INIT(hints,SOCK_STREAM);
- sock_fd = listen_sock(&hints);
- if(sock_fd<0) { return -1; }
+static void net_shutdown(void *p) {
+ struct net_info *info = (struct net_info*)p;
- if(listen(sock_fd,MAX_BACKLOG)!=0) {
- perror("listen");
- return -1;
- }
+ close(info->tcp);
+ close(info->udp);
- return 1;
+ return;
}
-static int udp() {
- struct addrinfo hints;
- int sock_fd;
+static void *net_spawn(void *p) {
+ struct net_info info;
- HINTS_INIT(hints,SOCK_DGRAM);
- sock_fd = listen_sock(&hints);
- if(sock_fd<0) { return -1; }
+ if((info.tcp = net_tcp())<0) { return NULL; }
+ if((info.udp = net_udp())<0) { return NULL; }
- return 1;
-}
+ pthread_cleanup_push(&net_shutdown,&info);
+ while(1) {
+ pthread_testcancel();
+ net_loop();
+ }
-int start() {
- if(tcp()<0) { return -1; }
- if(udp()<0) { return -1; }
+ pthread_cleanup_pop(1);
- return 1;
+ return NULL;
}
-static int listen_sock(struct addrinfo *hints) {
- struct addrinfo *p, *res;
- int sock_fd;
+int net_start() {
+ global_options.worker_threads = 1;
+ net_threads = calloc(sizeof(pthread_t),global_options.worker_threads);
+ for(size_t i=0;i<global_options.worker_threads;i++) {
+ if(pthread_create(&(net_threads[i]),NULL,&net_spawn,NULL)!=0) {
+ perror("pthread_create");
+ return -1;
+ }
+ }
- if(getaddrinfo(NULL,global_options.port,hints,&res)!=0) {
- perror("getaddrinfo");
+ if(0!=atexit(&net_stop)) {
+ perror("atexit");
return -1;
}
- for(p=res;p!=NULL;p=p->ai_next) {
- sock_fd = socket(p->ai_family,p->ai_socktype,p->ai_protocol);
- if(sock_fd<0) { continue; }
-
- if(bind(sock_fd,p->ai_addr,p->ai_addrlen)==0) { break; /* Success */ }
+ return 1;
+}
- close(sock_fd);
+static void net_stop() {
+ for(size_t i=0;i<global_options.worker_threads;i++) {
+ pthread_cancel(net_threads[i]);
}
- free(res);
-
- if(p==NULL) { return -1; }
-
- return sock_fd;
+ for(size_t i=0;i<global_options.worker_threads;i++) {
+ if(pthread_join(net_threads[i],NULL)!=0) {
+ log_err(NET_MESSAGE_SHUTDOWN_FAILED);
+ }
+ }
}
+