ed7386ce5e
xtris is a version of an classical popular game, for any number of players, for the X Window system. xtris is a true client/server game (as opposed to a centralized game managing multiple displays), which makes it particularily responsive and bandwith-effective. Submitted by Oliver Paulzen <opp@muffin.org> in private mail.
203 lines
4.7 KiB
Text
203 lines
4.7 KiB
Text
$NetBSD: patch-ae,v 1.1.1.1 2002/01/25 17:47:18 hubertf Exp $
|
|
|
|
--- xtserv.c.orig Wed Apr 9 20:01:58 1997
|
|
+++ xtserv.c
|
|
@@ -95,7 +95,13 @@
|
|
#define NEXT(u) ((u)->next ? (u)->next : user0)
|
|
|
|
int port = DEFAULTPORT;
|
|
+#ifdef INET6
|
|
+# define MAX_LISTEN_SOCKS 16
|
|
+struct sockaddr_storage saddr;
|
|
+#else
|
|
struct sockaddr_in saddr;
|
|
+#endif
|
|
+int saddr_len;
|
|
int lfd;
|
|
unsigned char realbuf[512], *buf = realbuf + 4;
|
|
|
|
@@ -235,6 +241,9 @@
|
|
void new_connect(int fd) {
|
|
struct user *u, *v;
|
|
unsigned char nxn;
|
|
+#ifdef INET6
|
|
+ char ipaddr_buf[INET6_ADDRSTRLEN];
|
|
+#endif
|
|
|
|
u = malloc(sizeof (struct user));
|
|
if (!u)
|
|
@@ -263,8 +272,20 @@
|
|
v = v->next;
|
|
}
|
|
u->number = nxn;
|
|
+#ifdef INET6
|
|
+ if (verbose){
|
|
+ ipaddr_buf[0] = '\0';
|
|
+ getnameinfo((struct sockaddr *)&saddr, saddr_len,
|
|
+ ipaddr_buf, sizeof(ipaddr_buf),
|
|
+ NULL, 0, NI_NUMERICHOST);
|
|
+ ipaddr_buf[sizeof(ipaddr_buf)-1] = '\0';
|
|
+ printf("client %d connecting from %s\n",
|
|
+ nxn, ((ipaddr_buf[0] != '\0') ? ipaddr_buf : "(unknown)"));
|
|
+ }
|
|
+#else
|
|
if (verbose)
|
|
printf("client %d connecting from %s\n", nxn, inet_ntoa(saddr.sin_addr));
|
|
+#endif
|
|
clients++;
|
|
buf[1] = OP_YOUARE;
|
|
buf[0] = u->number;
|
|
@@ -280,6 +301,15 @@
|
|
char *opt;
|
|
struct protoent *tcpproto;
|
|
struct timeval tv;
|
|
+#ifdef INET6
|
|
+ struct addrinfo hints, *res0, *res;
|
|
+ char serv_buf[NI_MAXSERV];
|
|
+ int socklistListen[MAX_LISTEN_SOCKS];
|
|
+ int countSock, maxSock;
|
|
+ char str_buff[512];
|
|
+ int j, sel, gai;
|
|
+ int sockListen;
|
|
+#endif
|
|
|
|
#ifndef NeXT
|
|
struct sigaction sact;
|
|
@@ -343,6 +373,46 @@
|
|
} else fatal("Unrecognized option, try -h for help");
|
|
}
|
|
|
|
+#ifdef INET6
|
|
+ memset(&hints, 0, sizeof(hints));
|
|
+ hints.ai_family = PF_UNSPEC;
|
|
+ hints.ai_socktype = SOCK_STREAM;
|
|
+ hints.ai_flags = AI_PASSIVE;
|
|
+ snprintf(serv_buf, sizeof(serv_buf), "%d", port);
|
|
+ serv_buf[sizeof(serv_buf)-1] = '\0';
|
|
+ gai = getaddrinfo(NULL, serv_buf, &hints, &res0);
|
|
+ if (gai){
|
|
+ snprintf(str_buff, sizeof(str_buff)-1,
|
|
+ "getaddrinfo(): %s", gai_strerror(gai));
|
|
+ str_buff[sizeof(str_buff)-1] = '\0';
|
|
+ fatal(str_buff);
|
|
+ }
|
|
+ countSock = 0;
|
|
+ maxSock = -1;
|
|
+ for (res=res0; res && (countSock < MAX_LISTEN_SOCKS); res=res->ai_next){
|
|
+ sockListen = socket(res->ai_family, res->ai_socktype, 0);
|
|
+ if(sockListen < 0) continue;
|
|
+ on = 1;
|
|
+ setsockopt(sockListen, SOL_SOCKET, SO_REUSEADDR,
|
|
+ (char *)&on, sizeof(int));
|
|
+ if (bind(sockListen, res->ai_addr, res->ai_addrlen) < 0){
|
|
+ close(sockListen);
|
|
+ continue;
|
|
+ }
|
|
+ if (listen(sockListen, 5) < 0){
|
|
+ close(sockListen);
|
|
+ continue;
|
|
+ }
|
|
+ socklistListen[countSock++] = sockListen;
|
|
+ if (maxSock < sockListen) maxSock = sockListen;
|
|
+ }
|
|
+ if (!countSock){
|
|
+ snprintf(str_buff, sizeof(str_buff), "socket(),bind(),listen(): %d", countSock);
|
|
+ str_buff[sizeof(str_buff)-1] = '\0';
|
|
+ fatal(str_buff);
|
|
+ }
|
|
+ freeaddrinfo(res0);
|
|
+#else
|
|
lfd = socket(PF_INET, SOCK_STREAM, 0);
|
|
saddr.sin_family = AF_INET;
|
|
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
@@ -357,13 +427,26 @@
|
|
syserr("bind");
|
|
|
|
listen(lfd, 5);
|
|
+#endif
|
|
|
|
if (is_daemon) {
|
|
/* become a daemon, breaking all ties with the controlling terminal */
|
|
verbose = 0;
|
|
for (i=0; i<255; i++) {
|
|
+#ifdef INET6
|
|
+ lfd = -1;
|
|
+ for (j=0; j<countSock; j++){
|
|
+ if (i == socklistListen[j]){
|
|
+ lfd = socklistListen[j];
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (lfd < 0)
|
|
+ close(i);
|
|
+#else
|
|
if (i != lfd)
|
|
close(i);
|
|
+#endif
|
|
}
|
|
if (fork())
|
|
exit(0);
|
|
@@ -395,7 +478,11 @@
|
|
flushuser(u);
|
|
|
|
FD_ZERO(&fds);
|
|
+#ifdef INET6
|
|
+ mfd = -1;
|
|
+#else
|
|
mfd = lfd;
|
|
+#endif
|
|
u = user0;
|
|
while (u) {
|
|
FD_SET(u->fd, &fds);
|
|
@@ -403,7 +490,15 @@
|
|
mfd = u->fd;
|
|
u = u->next;
|
|
}
|
|
+#ifdef INET6
|
|
+ for (i=0; i<countSock; i++){
|
|
+ FD_SET(socklistListen[i], &fds);
|
|
+ if (socklistListen[i] > mfd)
|
|
+ mfd = socklistListen[i];
|
|
+ }
|
|
+#else
|
|
FD_SET(lfd, &fds);
|
|
+#endif
|
|
tv.tv_sec = 0;
|
|
tv.tv_usec = 500000;
|
|
if ((sl = select(mfd + 1, &fds, NULL, NULL, &tv)) < 0)
|
|
@@ -425,11 +520,15 @@
|
|
if (sl == 0)
|
|
continue;
|
|
|
|
- if (FD_ISSET(lfd, &fds)) {
|
|
- int newfd, slen;
|
|
+#ifdef INET6
|
|
+ for (i=0; i<countSock; i++){
|
|
+ lfd = socklistListen[i];
|
|
+#endif
|
|
+ if (FD_ISSET(lfd, &fds)) {
|
|
+ int newfd;
|
|
|
|
- slen = sizeof(saddr);
|
|
- newfd = accept(lfd, (struct sockaddr *)&saddr, &slen);
|
|
+ saddr_len = sizeof(saddr);
|
|
+ newfd = accept(lfd, (struct sockaddr *)&saddr, &saddr_len);
|
|
if (newfd < 0) {
|
|
if (errno != EINTR)
|
|
syserr("accept");
|
|
@@ -440,8 +539,15 @@
|
|
}
|
|
new_connect(newfd);
|
|
}
|
|
+#ifdef INET6
|
|
+ break;
|
|
+#else
|
|
continue;
|
|
+#endif
|
|
+ }
|
|
+#ifdef INET6
|
|
}
|
|
+#endif
|
|
|
|
u = user0;
|
|
do {
|