diff options
author | LAN-TW <lantw44@gmail.com> | 2013-10-20 01:35:03 +0800 |
---|---|---|
committer | LAN-TW <lantw44@gmail.com> | 2013-10-20 01:35:03 +0800 |
commit | 9037b4d00d70856c08588cc23ce210721175b593 (patch) | |
tree | f71953afd456cb8ae7291af708a005f2c42416ec | |
parent | 52e738da9c1626ce9f2c29a43057bc4a8cf7a4aa (diff) | |
download | cn2013-9037b4d00d70856c08588cc23ce210721175b593.tar.gz cn2013-9037b4d00d70856c08588cc23ce210721175b593.tar.zst cn2013-9037b4d00d70856c08588cc23ce210721175b593.zip |
HW1: 簡單的接受連線的功能
-rw-r--r-- | hw1/Makefile.am | 5 | ||||
-rw-r--r-- | hw1/server-main.c | 99 | ||||
-rw-r--r-- | hw1/server.c | 51 | ||||
-rw-r--r-- | hw1/server.h | 2 | ||||
-rw-r--r-- | hw1/socktool.c | 44 | ||||
-rw-r--r-- | hw1/socktool.h | 11 |
6 files changed, 167 insertions, 45 deletions
diff --git a/hw1/Makefile.am b/hw1/Makefile.am index fa37db3..ab32312 100644 --- a/hw1/Makefile.am +++ b/hw1/Makefile.am @@ -1,6 +1,7 @@ EXTRA_DIST = autogen.sh bin_PROGRAMS = ras-server -noinst_LIBRARIES = libbasic.a +noinst_LIBRARIES = libbasic.a libras.a libbasic_a_SOURCES = xwrap.c xwrap.h basic-list.c basic-list.h +libras_a_SOURCES = socktool.c socktool.h ras_server_SOURCES = server-main.c server.c -ras_server_LDADD = $(top_builddir)/libbasic.a +ras_server_LDADD = $(top_builddir)/libbasic.a $(top_builddir)/libras.a diff --git a/hw1/server-main.c b/hw1/server-main.c index b4b4d84..e6d5f5a 100644 --- a/hw1/server-main.c +++ b/hw1/server-main.c @@ -3,15 +3,51 @@ #endif #include "server.h" +#include "socktool.h" #include "basic-list.h" #include <locale.h> #include <time.h> +#include <signal.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <sys/types.h> +#include <sys/select.h> #include <sys/socket.h> +static volatile sig_atomic_t quit_request = false; +static void quit_request_setter (int signo) { + quit_request = true; +} + +static void svrlist_fill_rset (List* svrlist, fd_set* rset, int* maxfd) { + ListNode* iter; + + for (iter = list_node_front (svrlist); iter != NULL; iter = list_next (iter)) { + RasServer* server = RAS_SERVER (list_data (iter)); + if (server->fd_is_set) { + FD_SET (server->fd, rset); + *maxfd = xmax (*maxfd, server->fd) + 1; + } + } +} + +static RasServer* svrlist_find_server (List* svrlist, int fd) { + ListNode* iter; + + for (iter = list_node_front (svrlist); iter != NULL; iter = list_next (iter)) { + RasServer* server = RAS_SERVER (list_data (iter)); + if (server->fd_is_set && server->fd == fd) { + return server; + } + } + + return NULL; +} + + int main (int argc, char* argv[]) { setlocale (LC_ALL, ""); tzset (); @@ -21,35 +57,78 @@ int main (int argc, char* argv[]) { return 1; } + struct sigaction action = { + .sa_handler = SIG_IGN, + .sa_flags = 0 + }; + sigemptyset (&action.sa_mask); + sigaction (SIGPIPE, &action, NULL); + action.sa_handler = quit_request_setter; + sigaction (SIGINT, &action, NULL); + sigaction (SIGQUIT, &action, NULL); + sigaction (SIGTERM, &action, NULL); + List* svrlist = list_create (); + RasServer svr; int sid; - RasServer server; - ras_server_init (&server, + ras_server_init (&svr, AF_LOCAL, RAS_SERVER_PERM_ADMIN, argv[0], NULL, &sid); - if (ras_server_listen (&server, "/tmp/ras-server.sock", 0) < 0) { + if (ras_server_listen (&svr, "/tmp/ras-server.sock", 0) < 0) { return 1; } else { - list_pushback (svrlist, &server, sizeof (RasServer)); + list_pushback (svrlist, &svr, sizeof (RasServer)); } - ras_server_init (&server, + ras_server_init (&svr, AF_INET, RAS_SERVER_PERM_RESTRICTED, argv[0], NULL, &sid); - if (ras_server_listen (&server, NULL, atoi (argv[1])) < 0) { + if (ras_server_listen (&svr, NULL, atoi (argv[1])) < 0) { return 1; } else { - list_pushback (svrlist, &server, sizeof (RasServer)); + list_pushback (svrlist, &svr, sizeof (RasServer)); } - ras_server_init (&server, + ras_server_init (&svr, AF_INET6, RAS_SERVER_PERM_RESTRICTED, argv[0], NULL, &sid); - if (ras_server_listen (&server, NULL, atoi (argv[1])) < 0) { + if (ras_server_listen (&svr, NULL, atoi (argv[1])) < 0) { return 1; } else { - list_pushback (svrlist, &server, sizeof (RasServer)); + list_pushback (svrlist, &svr, sizeof (RasServer)); } + int maxfd; + fd_set rset, wset; + + while (!quit_request) { + int rval; + + maxfd = 0; + FD_ZERO (&rset); + FD_ZERO (&wset); + svrlist_fill_rset (svrlist, &rset, &maxfd); + + rval = select (maxfd, &rset, &wset, NULL, NULL); + if (rval < 0) { + continue; + } + for (int i = 0; i < maxfd; i++) { + if (FD_ISSET (i, &rset)) { + RasServer* server = svrlist_find_server (svrlist, i); + if (server == NULL) { + continue; + } + + int session_fd = accept (i, NULL, NULL); + char* peername = ras_socktool_get_peername (session_fd); + ras_server_log (server, "client X from %s is accepted", peername); + free (peername); + + } + } + + + } puts ("Shutting down all servers ..."); diff --git a/hw1/server.c b/hw1/server.c index 357e2f8..118fd31 100644 --- a/hw1/server.c +++ b/hw1/server.c @@ -4,6 +4,7 @@ #include "server.h" #include "xwrap.h" +#include "socktool.h" #include <arpa/inet.h> #include <fcntl.h> @@ -22,10 +23,6 @@ #include <time.h> #include <unistd.h> -#define SOCKADDR_UN(x) ((struct sockaddr_un*)(x)) -#define SOCKADDR_IN(x) ((struct sockaddr_in*)(x)) -#define SOCKADDR_IN6(x) ((struct sockaddr_in6*)(x)) - int ras_server_init ( RasServer* server, int domain, RasServerPerm perm, const char* name, const char* log_file, int* id) { @@ -83,7 +80,7 @@ void ras_server_close (RasServer* server) { shutdown (server->fd, SHUT_RDWR); close (server->fd); if (server->domain == AF_LOCAL) { - unlink (SOCKADDR_UN (server->addr)->sun_path); + unlink (SOCKADDR_UN (&server->addr)->sun_path); } } if (server->log_is_set) { @@ -91,55 +88,47 @@ void ras_server_close (RasServer* server) { } free (server->log_file); free (server->name); - free (server->addr); } int ras_server_listen (RasServer* server, const char* addr, uint16_t port) { int len, fd; + struct sockaddr_storage sock; socklen_t socklen; - struct sockaddr* sock; + memset (&sock, 0, sizeof (sock)); switch (server->domain) { case AF_LOCAL: - len = strlen (addr) + 1; - socklen = xmax ( - offsetof (struct sockaddr_un, sun_path) + len, - sizeof (struct sockaddr_un)); - sock = xmalloc (socklen); - SOCKADDR_UN (sock)->sun_family = AF_LOCAL; - strncpy (SOCKADDR_UN (sock)->sun_path, addr, len); + socklen = sizeof (struct sockaddr_un); + len = socklen - offsetof (struct sockaddr_un, sun_path) - 1; + SOCKADDR_UN (&sock)->sun_family = AF_LOCAL; + strncpy (SOCKADDR_UN (&sock)->sun_path, addr, len); ras_server_log (server, "addr = %s", addr); break; case AF_INET: socklen = sizeof (struct sockaddr_in); - sock = xmalloc (socklen); - memset (sock, 0, socklen); - SOCKADDR_IN (sock)->sin_family = AF_INET; - SOCKADDR_IN (sock)->sin_port = htons (port); + SOCKADDR_IN (&sock)->sin_family = AF_INET; + SOCKADDR_IN (&sock)->sin_port = htons (port); if (addr == NULL) { - SOCKADDR_IN (sock)->sin_addr.s_addr = htonl (INADDR_ANY); + SOCKADDR_IN (&sock)->sin_addr.s_addr = htonl (INADDR_ANY); addr = "any"; } else { - if (inet_pton (AF_INET, addr, &(SOCKADDR_IN (sock)->sin_addr)) <= 0) { + if (inet_pton (AF_INET, addr, &(SOCKADDR_IN (&sock)->sin_addr)) <= 0) { ras_server_log (server, "unknown IPv4 address: %s", addr); - free (sock); - goto sock_allocated; + return -1; } } ras_server_log (server, "addr = %s, port = %" PRIu16, addr, port); break; case AF_INET6: socklen = sizeof (struct sockaddr_in6); - sock = xmalloc (socklen); - memset (sock, 0, socklen); - SOCKADDR_IN6 (sock)->sin6_family = AF_INET6; - SOCKADDR_IN6 (sock)->sin6_port = htons (port); + SOCKADDR_IN6 (&sock)->sin6_family = AF_INET6; + SOCKADDR_IN6 (&sock)->sin6_port = htons (port); if (addr == NULL) { - SOCKADDR_IN6 (sock)->sin6_addr = in6addr_any; + SOCKADDR_IN6 (&sock)->sin6_addr = in6addr_any; addr = "any"; } else { - if (inet_pton (AF_INET6, addr, &(SOCKADDR_IN6 (sock)->sin6_addr)) <= 0) { + if (inet_pton (AF_INET6, addr, &(SOCKADDR_IN6 (&sock)->sin6_addr)) <= 0) { ras_server_log (server, "unknown IPv6 address: %s", addr); - goto sock_allocated; + return -1; } } ras_server_log (server, "addr = %s, port = %" PRIu16, addr, port); @@ -158,7 +147,7 @@ int ras_server_listen (RasServer* server, const char* addr, uint16_t port) { setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof (yes)); } - if (bind (fd, sock, socklen)) { + if (bind (fd, SOCKADDR (&sock), socklen)) { ras_server_log (server, "bind: %s", strerror (errno)); goto fd_opened; } @@ -175,8 +164,6 @@ int ras_server_listen (RasServer* server, const char* addr, uint16_t port) { return 0; -sock_allocated: - free (sock); fd_opened: close (fd); diff --git a/hw1/server.h b/hw1/server.h index 7919348..359b384 100644 --- a/hw1/server.h +++ b/hw1/server.h @@ -23,7 +23,7 @@ typedef struct { char* log_file; int log_fd; int domain; - struct sockaddr* addr; + struct sockaddr_storage addr; socklen_t addrlen; int log_is_set : 1; int fd_is_set : 1; diff --git a/hw1/socktool.c b/hw1/socktool.c new file mode 100644 index 0000000..b07c6cb --- /dev/null +++ b/hw1/socktool.c @@ -0,0 +1,44 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "socktool.h" +#include "xwrap.h" + +#include <arpa/inet.h> +#include <sys/socket.h> +#include <sys/un.h> + +char* ras_socktool_get_peername (int sockfd) { + struct sockaddr_storage sock; + socklen_t socklen = sizeof (sock); + + memset (&sock, 0, socklen); + if (getpeername (sockfd, SOCKADDR (&sock), &socklen) < 0) { + return xstrdup ("invalid socket"); + } + + int domain = sock.ss_family; + if (domain == AF_LOCAL) { + return xstrdup ("local process"); + } + + socklen_t ipstrlen; + void* ipnet; + char* ipstr; + if (domain == AF_INET) { + ipstrlen = INET_ADDRSTRLEN; + ipnet = &(SOCKADDR_IN (&sock)->sin_addr); + } else { + ipstrlen = INET6_ADDRSTRLEN; + ipnet = &(SOCKADDR_IN6 (&sock)->sin6_addr); + } + + ipstr = xmalloc (ipstrlen); + if (inet_ntop (domain, ipnet, ipstr, ipstrlen) == NULL) { + free (ipstr); + return xstrdup ("unknown address"); + } + + return ipstr; +} diff --git a/hw1/socktool.h b/hw1/socktool.h new file mode 100644 index 0000000..13a60b6 --- /dev/null +++ b/hw1/socktool.h @@ -0,0 +1,11 @@ +#ifndef RAS_SOCKTOOL_H +#define RAS_SOCKTOOL_H + +#define SOCKADDR(x) ((struct sockaddr*)(x)) +#define SOCKADDR_UN(x) ((struct sockaddr_un*)(x)) +#define SOCKADDR_IN(x) ((struct sockaddr_in*)(x)) +#define SOCKADDR_IN6(x) ((struct sockaddr_in6*)(x)) + +char* ras_socktool_get_peername (int sockfd); + +#endif /* RAS_SOCKTOOL_H */ |