source: Main/trunk/Server/server.c@ 11

Last change on this file since 11 was 11, checked in by Nishi, on Sep 13, 2024 at 9:47:34 PM

multi-client

  • Property svn:keywords set to Id
File size: 3.6 KB
Line 
1/* $Id: server.c 11 2024-09-13 12:47:34Z nishi $ */
2
3#include "tw_server.h"
4
5#include "tw_config.h"
6
7#include <unistd.h>
8#include <string.h>
9#include <stdbool.h>
10
11#include <cm_log.h>
12
13#ifdef __MINGW32__
14#include <winsock2.h>
15#include <process.h>
16#define NO_IPV6
17#else
18#include <sys/select.h>
19#include <sys/socket.h>
20#include <arpa/inet.h>
21#include <netinet/in.h>
22#include <netinet/tcp.h>
23#endif
24
25extern struct tw_config config;
26
27fd_set fdset;
28int sockcount = 0;
29
30#ifdef NO_IPV6
31#define SOCKADDR struct sockaddr_in
32#else
33#define SOCKADDR struct sockaddr_in6
34#endif
35SOCKADDR addresses[MAX_PORTS];
36int sockets[MAX_PORTS];
37
38void close_socket(int sock) {
39#ifdef __MINGW32__
40 closesocket(sock);
41#else
42 close(sock);
43#endif
44}
45
46int tw_server_init(void) {
47 int i;
48#ifdef __MINGW32__
49 WSADATA wsa;
50 WSAStartup(MAKEWORD(2, 0), &wsa);
51#endif
52 for(i = 0; config.ports[i] != -1; i++)
53 ;
54 sockcount = i;
55 for(i = 0; config.ports[i] != -1; i++) {
56#ifdef NO_IPV6
57 int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
58#else
59 int sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
60#endif
61#ifdef __MINGW32__
62 if(sock == INVALID_SOCKET)
63#else
64 if(sock < 0)
65#endif
66 {
67 cm_log("Server", "Socket creation failure");
68 return 1;
69 }
70 int yes = 1;
71 if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(yes)) < 0) {
72 close_socket(sock);
73 cm_log("Server", "setsockopt failure (reuseaddr)");
74 return 1;
75 }
76 if(setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&yes, sizeof(yes)) < 0) {
77 close_socket(sock);
78 cm_log("Server", "setsockopt failure (nodelay)");
79 return 1;
80 }
81#ifndef NO_IPV6
82 int no = 0;
83 if(setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&no, sizeof(no)) < 0) {
84 close_socket(sock);
85 cm_log("Server", "setsockopt failure (IPv6)");
86 return 1;
87 }
88#endif
89 memset(&addresses[i], 0, sizeof(addresses[i]));
90#ifdef NO_IPV6
91 addresses[i].sin_family = AF_INET;
92 addresses[i].sin_addr.s_addr = INADDR_ANY;
93 addresses[i].sin_port = htons(config.ports[i]);
94#else
95 addresses[i].sin6_family = AF_INET6;
96 addresses[i].sin6_addr = in6addr_any;
97 addresses[i].sin6_port = htons(config.ports[i]);
98#endif
99 if(bind(sock, (struct sockaddr*)&addresses[i], sizeof(addresses[i])) < 0) {
100 close_socket(sock);
101 cm_log("Server", "Bind failure");
102 return 1;
103 }
104 if(listen(sock, 128) < 0) {
105 close_socket(sock);
106 cm_log("Server", "Listen failure");
107 return 1;
108 }
109 sockets[i] = sock;
110 }
111 return 0;
112}
113
114#ifdef __MINGW32__
115struct pass_entry {
116 int sock;
117 bool ssl;
118};
119
120unsigned int WINAPI tw_server_pass(void* ptr) {
121 int sock = ((struct pass_entry*)ptr)->sock;
122 bool ssl = ((struct pass_entry*)ptr)->ssl;
123#else
124void tw_server_pass(int sock, bool ssl) {
125#endif
126 close_socket(sock);
127#ifdef __MINGW32__
128 _endthreadex(0);
129#endif
130}
131
132void tw_server_loop(void) {
133 struct timeval tv;
134 while(1) {
135 FD_ZERO(&fdset);
136 int i;
137 for(i = 0; i < sockcount; i++) {
138 FD_SET(sockets[i], &fdset);
139 }
140 tv.tv_sec = 1;
141 tv.tv_usec = 0;
142 int ret = select(FD_SETSIZE, &fdset, NULL, NULL, &tv);
143 if(ret == -1) {
144 break;
145 } else if(ret > 0) {
146 /* connection */
147 int i;
148 for(i = 0; i < sockcount; i++) {
149 if(FD_ISSET(sockets[i], &fdset)) {
150 SOCKADDR claddr;
151 int clen = sizeof(claddr);
152 int sock = accept(sockets[i], (struct sockaddr*)&claddr, &clen);
153#ifdef __MINGW32__
154 HANDLE thread;
155 struct pass_entry* e = malloc(sizeof(*e));
156 e->sock = sock;
157 e->ssl = config.ports[i] & (1ULL << 32);
158 thread = (HANDLE)_beginthreadex(NULL, 0, tw_server_pass, e, 0, NULL);
159#else
160 pid_t pid = fork();
161 if(pid == 0) {
162 tw_server_pass(sock, config.ports[i] & (1ULL << 32));
163 _exit(0);
164 } else {
165 close_socket(sock);
166 }
167#endif
168 }
169 }
170 }
171 }
172}
Note: See TracBrowser for help on using the repository browser.