summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLAN-TW <lantw44@gmail.com>2013-10-20 01:35:03 +0800
committerLAN-TW <lantw44@gmail.com>2013-10-20 01:35:03 +0800
commit9037b4d00d70856c08588cc23ce210721175b593 (patch)
treef71953afd456cb8ae7291af708a005f2c42416ec
parent52e738da9c1626ce9f2c29a43057bc4a8cf7a4aa (diff)
downloadcn2013-9037b4d00d70856c08588cc23ce210721175b593.tar.gz
cn2013-9037b4d00d70856c08588cc23ce210721175b593.tar.zst
cn2013-9037b4d00d70856c08588cc23ce210721175b593.zip
HW1: 簡單的接受連線的功能
-rw-r--r--hw1/Makefile.am5
-rw-r--r--hw1/server-main.c99
-rw-r--r--hw1/server.c51
-rw-r--r--hw1/server.h2
-rw-r--r--hw1/socktool.c44
-rw-r--r--hw1/socktool.h11
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 */