forked from DSUOSS/unix-chat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.c
128 lines (108 loc) · 2.45 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
123
124
125
126
127
128
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/select.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define CHAT_SOCKET "/tmp/chat_socket"
typedef unsigned int uint;
typedef struct{
uint sockets[100];
uint count;
}sock_container;
void add_client(sock_container* c, uint s){
c->sockets[c->count] = s;
c->count++;
}
void remove_client(sock_container* c, uint s){
uint i, loc = 0;
for (i = 0; i < c->count; ++i){
if (s == c->sockets[i]){
loc = i;
break;
}
}
--c->count;
for (i = loc; i < c->count; ++i){
c->sockets[i] = c->sockets[i+1];
}
}
uint build_fd_set(sock_container* c, uint server, fd_set* s){
uint i, highest, sock;
FD_ZERO(s);
FD_SET(server, s);
highest = server;
for (i=0; i < c->count; ++i){
sock = c->sockets[i];
FD_SET(sock, s);
if (sock > highest)
highest = sock;
}
return highest;
}
uint init_socket(){
uint s;
struct sockaddr_un local;
uint len;
s= socket(AF_UNIX, SOCK_STREAM, 0);
if (!s){
perror("Failed to create socket");
exit(-1);
}
local.sun_family = AF_UNIX;
strcpy(local.sun_path, CHAT_SOCKET);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if(bind(s, (struct sockaddr *)&local, len) == -1){
perror("Failed to bind");
exit(-2);
}
if(listen(s, 100) == -1){
perror("Failed to listen");
exit(-3);
}
fcntl(s, F_SETFL, O_NONBLOCK);
chmod(CHAT_SOCKET, S_IRWXU|S_IRWXG|S_IRWXO);
return s;
}
int main(int argc, char** argv){
uint server, client, i, j, len, highest;
fd_set fds;
sock_container clients = {};
char buffer[1024];
server = init_socket();
while(1){
//places clients and server in fds
//this is required every loop because select modifys fds
highest = build_fd_set(&clients, server, &fds);
select(highest + 1, &fds, NULL, NULL, NULL);
//accept any new clients
if (FD_ISSET(server, &fds)){
client= accept(server, NULL, NULL);
add_client(&clients, client);
}
//read data from clients
for(i = 0; i<clients.count; ++i){
uint socket = clients.sockets[i];
if(FD_ISSET(socket, &fds)){
bzero(buffer, sizeof(buffer));
len = read(socket, &buffer, 1024);
if (len>0){
//write data to all clients
for (j = 0; j<clients.count; ++j){
write(clients.sockets[j], buffer, len);
}
}
//client closed connection
else{
close(socket);
remove_client(&clients, socket);
}
}
}
}
return 0;
}