7 #include <sys/socket.h>
8 #include <netinet/in.h>
20 #define BACKLOG 3 // how many pending connections queue will hold
23 play_info
*playlist
= NULL
;
25 pthread_mutex_t playlist_mutex
= PTHREAD_MUTEX_INITIALIZER
;
28 play_info
* add_play_session (const char *user_name
, int game_id
, int pty_master
)
30 play_info
*ps
= (play_info
*)malloc(sizeof(play_info
));
31 if (ps
== NULL
) return NULL
;
36 strcpy (ps
->user_name
, user_name
);
37 ps
->game_id
= game_id
;
40 ps
->pty_master
= pty_master
;
41 ps
->observer_count
= 0;
43 pthread_mutex_init (&ps
->mutex
, NULL
);
44 ps
->last_activity
= time(NULL
);
47 pthread_mutex_lock (&playlist_mutex
);
56 play_info
*p
= playlist
;
57 while (p
->next
!= NULL
) p
= p
->next
;
63 pthread_mutex_unlock (&playlist_mutex
);
70 void remove_play_session (play_info
*ps
)
74 pthread_mutex_lock (&playlist_mutex
);
76 for (p
= playlist
; p
!= NULL
; p
= p
->next
)
78 if (p
!= ps
) continue;
80 if (p
->next
) p
->next
->prev
= p
->prev
;
81 if (p
->prev
) p
->prev
->next
= p
->next
;
83 if (playlist
== ps
) playlist
= ps
->next
;
91 pthread_mutex_unlock (&playlist_mutex
);
95 static void sigchld_handler (int s
)
97 while (waitpid(-1, NULL
, WNOHANG
) > 0);
102 static void init_signals (void)
106 sa
.sa_handler
= sigchld_handler
; // reap all dead processes
107 sigemptyset (&sa
.sa_mask
);
108 sa
.sa_flags
= SA_RESTART
;
109 if (sigaction(SIGCHLD
, &sa
, NULL
) == -1)
111 perror ("sigaction");
118 static int open_socket (int port
)
120 int sockfd
; // listen on sock_fd
121 struct sockaddr_in my_addr
; // my address information
124 if ((sockfd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
130 if (setsockopt(sockfd
, SOL_SOCKET
, SO_REUSEADDR
, &yes
, sizeof(int)) == -1)
132 perror ("setsockopt");
137 my_addr
.sin_family
= AF_INET
; // host byte order
138 my_addr
.sin_port
= htons(port
); // short, network byte order
139 my_addr
.sin_addr
.s_addr
= INADDR_ANY
; // automatically fill with my IP
140 memset (&(my_addr
.sin_zero
), 0, 8); // zero the rest of the struct
142 if (bind(sockfd
, (struct sockaddr
*)&my_addr
, sizeof(struct sockaddr
)) == -1)
149 if (listen(sockfd
, BACKLOG
) == -1)
169 * Handle newly connected client in a thread
171 static void* connection_thread (void *data
)
174 int sock
= ((thread_data
*)data
)->sock
;
177 send_telnet_init (sock
);
180 printf("menu %d\n", r
);
181 if (r
== 1) run_game (sock
);
189 static void handle_connect (int new_fd
)
191 pthread_attr_t thread_attr
;
195 if ((data
= malloc(sizeof(thread_data
))) == NULL
)
205 pthread_attr_init (&thread_attr
);
206 pthread_attr_setdetachstate (&thread_attr
, PTHREAD_CREATE_DETACHED
);
207 pthread_attr_setscope (&thread_attr
, PTHREAD_SCOPE_PROCESS
);
209 // handle new connection in a thread
210 if (pthread_create(&th
, &thread_attr
, connection_thread
, data
) != 0)
218 // socket used to listen for new connections
219 int server_socket
= -1;
225 server_socket
= open_socket(MYPORT
);
226 if (server_socket
== -1) return 1;
230 struct sockaddr_in their_addr
; // connector's address information
231 socklen_t sin_size
= sizeof(struct sockaddr_in
);
234 // got a new connection
235 if ((new_fd
= accept(server_socket
, (struct sockaddr
*)&their_addr
, &sin_size
)) == -1)
241 printf("server: got connection from %s\n",inet_ntoa(their_addr
.sin_addr
));
242 handle_connect (new_fd
);
245 close (server_socket
);
246 pthread_mutex_destroy (&playlist_mutex
);