-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathserver.c
123 lines (101 loc) · 3.04 KB
/
server.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <libsocket.h>
#include <regex.h>
#include "chat.h"
int main(int argc, char *argv[])
{
int listenfd, connfd, nready, maxfd;
struct sockaddr_in serveraddr, clientaddr;
socklen_t clientlen;
fd_set rset, allset;
struct clients clients = {0};
struct channels channels = {0};
struct collection collection = {0};
collection.clients = &clients;
collection.channels = &channels;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVER_PORT);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
Bind(listenfd, (struct sockaddr *) &serveraddr, sizeof(struct sockaddr));
Listen(listenfd, LISTENQ);
// Setup read set for select
maxfd = listenfd;
FD_ZERO(&allset);
FD_SET(listenfd, &allset);
puts("Server running...");
for (; ;) {
clientlen = sizeof(clientaddr);
// Wait for rset to be ready
rset = allset;
nready = select(maxfd + 1, &rset, NULL, NULL, NULL);
/* If New connection arrived handle it */
if (FD_ISSET(listenfd, &rset)) {
puts("New connection initiated...");
if ((connfd = accept(listenfd, (struct sockaddr *) &clientaddr, &clientlen)) == -1) {
perror("accept error");
}
/* If client limit reached then don't accept the new connection */
if (clients.nclient + 1 == FD_SETSIZE) {
fprintf(stderr, "Warning: Client limit exceeded, rejecting new connection.");
/* TODO Need to tell client, your connection request rejected */
}
/* Save new client details in first empty space */
for (int i = 0; i < FD_SETSIZE; i++) {
if (clients.clients[i] == NULL) {
if (server_new_client(&clients, connfd) == -1)
break;
FD_SET(connfd, &allset);
break;
}
}
// Increment maxfd if required
if (connfd > maxfd)
maxfd = connfd;
/* If only new connection arrived then skip iteration on
* clients below */
if (--nready == 0)
continue;
}
struct client *tmp;
/* Find ready socket and handle the client request */
for (int i = 0; i < clients.clients_i && nready; i++) {
tmp = clients.clients[i];
if (tmp == NULL)
continue;
/* If client's socket is ready then process it */
if (FD_ISSET(tmp->fd, &rset)) {
/* If client terminated then clean client details */
puts("handle_client_request called..");
collection.index = i;
chat_request_handle(&collection, &allset);
nready--;
}
}
}
}
int server_new_client(struct clients *clients, int sockfd)
{
struct client *client;
if ((client = malloc(sizeof(struct client))) == NULL) {
perror("server_new_client: malloc error");
return -1;
}
/* Set default values */
client->fd = sockfd;
client->pair_fd = -1;
client->nick[0] = 0;
client->is_username_set = false;
client->is_assoc = false;
clients->clients[clients->nclient++] = client;
clients->clients_i++;
return 0;
}
int server_del_client(struct clients *clients, int index)
{
if (clients->clients[index] == NULL)
return -1;
free(clients->clients[index]);
clients->clients[index] = NULL;
return 0;
}