-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy paththread.c
More file actions
133 lines (111 loc) · 4.47 KB
/
thread.c
File metadata and controls
133 lines (111 loc) · 4.47 KB
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
#include "thread.h"
//handle thread close
void exit_thread(handler_args_t* args, char username[]) {
if (strlen(username) == 0) {
printf("CLIENT - UKNOWN USER FAILED TO CONNECT\n");
}else{
printf("CLIENT = %s - HAS JUST DISCONNECTED\n", username);
}
// close client socket
int ret = close(args->socket_desc);
if (ret == -1) printf("Error closing %s's client socket\n", username);
// free thread's memory
free(args->client_addr);
free(args);
pthread_exit(NULL);
}
//function to handle a single connection with a client
void* client_handler(void* arg) {
handler_args_t* args = (handler_args_t*)arg;
//initialize socket and other structure
int socket_desc = args->socket_desc;
struct sockaddr_in* client_addr = args->client_addr;
int ret, recv_bytes;
char username[30];
char buf[4096];
size_t buf_len = sizeof(buf);
size_t msg_len;
//possible commands
char* quit_command = SERVER_QUIT_COMMAND;
size_t quit_command_len = strlen(quit_command);
char* new_command = SERVER_NEW_COMMAND;
size_t new_command_len = strlen(new_command);
char* delete_command = SERVER_DELETE_COMMAND;
size_t delete_command_len = strlen(delete_command);
char* show_command = SERVER_SHOW_COMMAND;
size_t show_command_len = strlen(show_command);
//set socket timeout
struct timeval timeout;
timeout.tv_sec = 600; //10 minutes
timeout.tv_usec = 0;
ret = setsockopt (socket_desc, SOL_SOCKET, SO_RCVTIMEO, (void *)&timeout, sizeof(timeout));
if (ret<0) exit_thread(args, "");
ret = setsockopt (socket_desc, SOL_SOCKET, SO_SNDTIMEO, (void *)&timeout, sizeof(timeout));
if (ret<0) exit_thread(args, "");
// parse client IP address and port
char client_ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(client_addr->sin_addr), client_ip, INET_ADDRSTRLEN);
// send welcome message
sprintf(buf, "Hi! This is a showcase server. Please insert your username (max 15 chars): ");
msg_len = strlen(buf);
while ( (ret = send(socket_desc, buf, msg_len, 0)) < 0 ) {
if (errno == EINTR) continue;
if (errno == EAGAIN) break;
}
if (sock_error(ret)) exit_thread(args, "");
// read username from client
while ( (recv_bytes = recv(socket_desc, username, buf_len, 0)) < 0 ) {
if (errno == EINTR) continue;
if (errno == EAGAIN) break;
}
if (sock_error(recv_bytes)) exit_thread(args, "");
username[recv_bytes] = '\0';
printf("CLIENT = %s - HAS JUST CONNECTED\n", username);
//send instructions to client
sprintf(buf, "Hi %s! Here it is the showcase:\n",username);
msg_len = strlen(buf);
while ( (ret = send(socket_desc, buf, msg_len, 0)) < 0 ) {
if (errno == EINTR) continue;
if (errno == EAGAIN) break;
}
if (sock_error(ret)) exit_thread(args, username);
//send first showcase
if (! send_showcase(socket_desc)) exit_thread(args, username);
// echo loop
while (1) {
// read message from client
while ( (recv_bytes = recv(socket_desc, buf, buf_len, 0)) < 0 ) {
if (errno == EINTR) continue;
if (errno == EAGAIN) break;
}
if (sock_error(recv_bytes)) break;
// check whether I have been ask for the showcase
if (recv_bytes == show_command_len && !memcmp(buf, show_command, show_command_len)) {
if (! send_showcase(socket_desc)) break;
}
// check whether I have been ask for the showcase
else if (recv_bytes == new_command_len && !memcmp(buf, new_command, new_command_len)) {
if (! recv_post(socket_desc, username) ) break;
}
// check whether I have been ask for the showcase
else if (recv_bytes == delete_command_len && !memcmp(buf, delete_command, delete_command_len)) {
if (! recv_delete(socket_desc, username) ) break;
}
// check whether I have just been told to quit...
else if (recv_bytes == quit_command_len && !memcmp(buf, quit_command, quit_command_len)) {
break;
}
//error: command not found
else {
strcpy(buf, "COMMAND NOT FOUND\0");
msg_len = strlen(buf);
while ( (ret = send(socket_desc, buf, msg_len+1, 0)) < 0 ) {
if (errno == EINTR) continue;
if (errno == EAGAIN) break;
}
if (sock_error(ret)) break;
}
}
exit_thread(args, username);
pthread_exit(NULL);
}