Implemented game profiles
[rlserver.git] / server.c
bloba96df51d74ee171aa3d04473574106c62dab3073
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <errno.h>
5 #include <string.h>
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <netinet/in.h>
9 #include <arpa/inet.h>
10 #include <sys/wait.h>
11 #include <signal.h>
12 #include <pthread.h>
13 #include "telnet.h"
14 #include "sessions.h"
15 #include "server.h"
17 // XXX move to config file
18 #define MYPORT 3456
19 #define BACKLOG 3 // how many pending connections queue will hold
23 static void sigchld_handler (int s)
25 while (waitpid(-1, NULL, WNOHANG) > 0);
30 static void init_signals (void)
32 struct sigaction sa;
34 sa.sa_handler = sigchld_handler; // reap all dead processes
35 sigemptyset (&sa.sa_mask);
36 sa.sa_flags = SA_RESTART;
37 if (sigaction(SIGCHLD, &sa, NULL) == -1)
39 perror ("sigaction");
40 exit (1);
46 static int open_socket (int port)
48 int sockfd; // listen on sock_fd
49 struct sockaddr_in my_addr; // my address information
50 int yes = 1;
52 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
54 perror ("socket");
55 return -1;
58 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
60 perror ("setsockopt");
61 close (sockfd);
62 return -1;
65 my_addr.sin_family = AF_INET; // host byte order
66 my_addr.sin_port = htons(port); // short, network byte order
67 my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
68 memset (&(my_addr.sin_zero), 0, 8); // zero the rest of the struct
70 if (bind(sockfd, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) == -1)
72 perror ("bind");
73 close (sockfd);
74 return -1;
77 if (listen(sockfd, BACKLOG) == -1)
79 perror ("listen");
80 close (sockfd);
81 return -1;
84 return sockfd;
89 typedef struct
91 int sock;
92 } thread_data;
97 * Handle newly connected client in a thread
99 static void* connection_thread (void *data)
101 session_info *sess;
102 int r;
103 int sock = ((thread_data*)data)->sock;
104 free (data);
106 send_telnet_init (sock);
108 sess = add_session(sock);
110 r = main_menu(sess);
112 remove_session (sess);
113 close (sock);
114 return NULL;
119 static void handle_connect (int new_fd)
121 pthread_attr_t thread_attr;
122 thread_data *data;
123 pthread_t th; // XXX
125 if ((data = malloc(sizeof(thread_data))) == NULL)
127 close (new_fd);
128 // XXX
129 return;
132 data->sock = new_fd;
134 // init thread data
135 pthread_attr_init (&thread_attr);
136 pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_DETACHED);
137 pthread_attr_setscope (&thread_attr, PTHREAD_SCOPE_PROCESS);
139 // handle new connection in a thread
140 if (pthread_create(&th, &thread_attr, connection_thread, data) != 0)
142 free (data);
143 close (new_fd);
148 // socket used to listen for new connections
149 int server_socket = -1;
151 int main (void)
153 init_signals ();
155 server_socket = open_socket(MYPORT);
156 if (server_socket == -1) return 1;
158 while (1)
160 struct sockaddr_in their_addr; // connector's address information
161 socklen_t sin_size = sizeof(struct sockaddr_in);
162 int new_fd;
164 // got a new connection
165 if ((new_fd = accept(server_socket, (struct sockaddr*)&their_addr, &sin_size)) == -1)
167 perror ("accept");
168 continue;
171 printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));
172 handle_connect (new_fd);
175 close (server_socket);
177 extern pthread_mutex_t sessionlist_mutex;
178 pthread_mutex_destroy (&sessionlist_mutex);
180 release_sessions ();
182 return 0;