-
Notifications
You must be signed in to change notification settings - Fork 1
/
chats.c
183 lines (165 loc) · 4.56 KB
/
chats.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*
* C socket server
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<pthread.h>
#include "chat.h"
#define CLIENTS_MAX 10
typedef struct clientStruct {
in_port_t m_port;
char m_name[C_NAME_LEN + 1];
} client;
//the thread function
void *connection_handler(void *);
client clients[CLIENTS_MAX];
int client_index=0;//current index of the client in clients.
int main(int argc , char *argv[])
{
int server_socket_desc , client_sock, *new_sock;
struct sockaddr_in server;
//Create socket
server_socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (server_socket_desc == -1)
{
printf("Could not create socket");
}
puts("Socket created");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( C_SRV_PORT );
//Bind
if( bind(server_socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
perror("bind failed. Error");
return 1;
}
puts("bind done");
//Listen
listen(server_socket_desc , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
while( (client_sock = accept(server_socket_desc, (struct sockaddr *)0, (socklen_t*)0)) )
{
puts("Connection accepted");
pthread_t thread;
new_sock = malloc(1);
*new_sock = client_sock;
if( pthread_create( &thread , NULL , connection_handler , (void*) new_sock) < 0)
{
perror("could not create thread");
close(*new_sock);
return 1;
}
//pthread_join( thread , NULL);
puts(" thread finished");
}
if (client_sock < 0)
{
perror("accept failed");
}
close(server_socket_desc);
printf("Returning 0\n");
return 0;
}
/*
* handle connection for each client
* */
void *connection_handler(void *server_socket_desc)
{
printf("entered connection_handler thread\n");
int sock = *(int*)server_socket_desc,read_size,i;
msg_up_t msgUP;
msg_down_t msgDOWN;
msg_type_t ID;
msg_hdr_t msgHEADER;
msg_peer_t msgPEER;
while((read_size = recv(sock ,&ID , sizeof(msg_type_t) , MSG_PEEK)) > 0) {
switch(ID) {
case MSG_DOWN:
read_size = recv(sock,&msgDOWN,sizeof(msgDOWN),0);
if(read_size<=0){printf("recv for msgDOWN failed"); continue; }
int deleteIndex=-1;
for(i=0;i<client_index;i++){
if(msgDOWN.m_port == clients[i].m_port){
deleteIndex=i;
break;
}
}
if(client_index == -1) {
printf("something gone wrong, can't remove client\n");
break;
}
client temp;
for(i=deleteIndex;i<client_index-1;i++) {
temp= clients[i];
clients[i] = clients[i+1];
clients[i+1] = temp;
}
client_index--;
printf("msgDOWN: server: client deleted\n");
break;
case MSG_UP:
read_size = recv(sock , &msgUP , sizeof(msgUP) , 0);
if(read_size<=0){ printf("recv for msgUP failed"); continue; }
//if reached the max clients, then do not register
if(client_index == CLIENTS_MAX ) {
printf("maximum number of clients reached \n");
msg_nack_t msgNACK;
msgNACK.m_type = MSG_NACK;
write(sock , &msgNACK , sizeof(msgNACK));
continue;
}
int continue_outer_loop =0;//flag to determine wether to continue to outer loop
//check if client name already exists
for(i=0;i<client_index;i++) {
if(strcmp(clients[i].m_name,msgUP.m_name) ==0) {
printf("client with the name of %s already exist, exiting...\n", msgUP.m_name);
msg_nack_t msgNACK;
msgNACK.m_type = MSG_NACK;
write(sock , &msgNACK , sizeof(msgNACK));
continue_outer_loop=1;
}
}
if(continue_outer_loop ==0) {
//register, add the client to the clients list
clients[client_index].m_port = C_SRV_PORT+client_index+1;
strcpy(clients[client_index].m_name, msgUP.m_name);
msg_ack_t msgACK;
msgACK.m_type = MSG_ACK;
msgACK.m_port = clients[client_index++].m_port;
write(sock , &msgACK , sizeof(msgACK));
}
break;
case MSG_WHO:
printf("entered msg_who\n");
msgHEADER.m_type = MSG_HDR;
msgHEADER.m_count = client_index;
write(sock,&msgHEADER,sizeof(msgHEADER));
for(i=0;i<client_index;i++) {
msgPEER.m_type = MSG_PEER;
// msgPEER.m_addr = clients[i].m_addr;
msgPEER.m_port = clients[i].m_port;
strcpy(msgPEER.m_name,clients[i].m_name);
write(sock,&msgPEER,sizeof(msgPEER));
}
//close(sock);
return 0;
}
}
if(read_size < 0) {
printf("recv failed in connection_handler thread\n");
}
if(read_size == 0 ) {
printf(" disconncted\n");
}
printf("closing socket from thread..\n");
free(server_socket_desc);
return 0;
}