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

Last change on this file since 10 was 10, checked in by Nishi, on Sep 13, 2024 at 9:06:13 PM

select works

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