-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathServer.cpp
321 lines (287 loc) · 8.09 KB
/
Server.cpp
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
/*
* File: Server.cpp
* Author: atghosh
*
* Created on 19 July, 2013, 12:36 PM
*/
#include "Server.h"
/* Global variables required by the server */
std::map<int, std::pair<std::string, std::string> > client_details; /* Store all client details */
pthread_mutex_t lock_parse = PTHREAD_MUTEX_INITIALIZER; /* Thread to lock parser access */
bool ABORT = 0; /* Is server aborted? */
int serv_port = -1; /* Port number to run the server on */
/* Three LinkedLists */
LinkedList<std::string> stringlist;
LinkedList<int> intlist;
LinkedList<float> floatlist;
Server::Server(int port)
{
printf("Starting the Server With Port(%d)\nCtrl+C to quit\n", port);
/* create a listening socket */
serv_port = s.create();
/* bind our socket address to the listening socket */
s.bind(port);
}
Server::~Server()
{
}
/*
Unpack the struct.
Insert into LinkedList.
Write confirmation message into the string.
@param parm structured containing parsed query
@param msg to store the message
*/
void Server::insert_operation(struct parsed_vals * parm, std::string &msg)
{
std::stringstream msg_stream;
bool success = false;
switch (parm->type) {
case INT_TYPE:
if (intlist.addNode((parm->data).int_data))
{
msg_stream << (parm->data).int_data << " successfully inserted into the list\n";
success = true;
}
break;
case FLOAT_TYPE:
if (floatlist.addNode((parm->data).float_data))
{
msg_stream << (parm->data).float_data << " successfully inserted into the list\n";
success = true;
}
break;
case STRING_TYPE:
if (stringlist.addNode((parm->data).str_data))
{
msg_stream << (parm->data).str_data << " successfully inserted into the list\n";
success = true;
}
break;
}
if (!success)
msg_stream << "Insertion failed due to a reason I couldn't figure out.\
Would you mind trying again?\n";
msg = msg_stream.str();
}
/*
Unpack the struct.
Delete value from LinkedList.
Write confirmation message into the string.
@param parm structured containing parsed query
@param msg to store the message
*/
void Server::delete_operation(struct parsed_vals * parm, std::string &msg)
{
std::stringstream msg_stream;
bool success = false;
switch (parm->type) {
case INT_TYPE:
if (intlist.deleteNode((parm->data).int_data))
{
msg_stream << (parm->data).int_data << " successfully deleted\n";
success = true;
}
break;
case FLOAT_TYPE:
if (floatlist.deleteNode((parm->data).float_data))
{
msg_stream << (parm->data).float_data << " successfully deleted\n";
success = true;
}
break;
case STRING_TYPE:
if (stringlist.deleteNode((parm->data).str_data))
{
msg_stream << (parm->data).str_data << " successfully deleted\n";
success = true;
}
break;
}
if (!success)
msg_stream << "Deletion failed as the element was not found in the list.\
Why don't you try inserting it?\n";
msg = msg_stream.str();
}
/*
Unpack the struct.
Check if value exists in LinkedList.
Write confirmation message into the string.
@param parm structured containing parsed query
@param msg to store the message
*/
void Server::find_operation(struct parsed_vals * parm, std::string &msg)
{
std::stringstream msg_stream;
bool success = false;
switch (parm->type) {
case INT_TYPE:
if (intlist.check_if_exists((parm->data).int_data))
{
msg_stream << (parm->data).int_data << " found in the list\n";
success = true;
}
break;
case FLOAT_TYPE:
if (floatlist.check_if_exists((parm->data).float_data))
{
msg_stream << (parm->data).float_data << " found in the list\n";
success = true;
}
break;
case STRING_TYPE:
if (stringlist.check_if_exists((parm->data).str_data))
{
msg_stream << (parm->data).str_data << " found in the list\n";
success = true;
}
break;
}
if (!success)
msg_stream << "This value wasn't found in the list! Why don't you try inserting it?\n";
msg = msg_stream.str();
}
void Server::delete_all_operation()
{
intlist.destroyList();
floatlist.destroyList();
stringlist.destroyList();
}
/*
serves each client request
@parm cli_id client id --> return value from accept
*/
void * process_request(void *cli_id)
{
int tmp = *((int *) cli_id);
free(cli_id);
pthread_detach(pthread_self());
int clientsocket = tmp;
char buffer[MAXLINE];
std::string mssg;
while (!ABORT)
{
if (Helper::readline(clientsocket, buffer, MAXLINE - 1) <= 0)
{
break;
}
/* check if the command is exit.is yes, close this thread */
if (strncmp(buffer, "EXIT", 4) == 0 || strncmp(buffer, "exit", 4) == 0)
{
Helper::writeline(clientsocket, buffer, sizeof buffer);
break;
}
/* lock the parsing operation */
struct parsed_vals tokens;
pthread_mutex_lock(&lock_parse);
YY_BUFFER_STATE bp = yy_scan_string(buffer);
yy_switch_to_buffer(bp);
int ret_val = yyparse((void *) &tokens);
yy_delete_buffer(bp);
pthread_mutex_unlock(&lock_parse);
/* call required function based on the 'cmd; field of struct (here tokens)*/
if (ret_val == 0)
{
switch (tokens.cmd) {
case INSERT_CMD:
Server::insert_operation(&tokens, mssg);
break;
case FIND_CMD:
Server::find_operation(&tokens, mssg);
break;
case DELETE_CMD:
Server::delete_operation(&tokens, mssg);
break;
case DELALL_CMD:
Server::delete_all_operation();
mssg = "All items successfully deleted\n";
break;
case SHOW_CMD:
std::stringstream msg;
msg << intlist.size << " integers\t" << floatlist.size << " \
floats\t" << stringlist.size << " strings\n";
mssg = msg.str();
break;
}
} else
{
mssg = "Invalid command issued!!!\n";
}
if (Helper::writeline(clientsocket, (char *) (mssg.c_str()), mssg.length()) < 0)
{
break;
}
memset(buffer, 0, sizeof buffer);
}
client_details.erase(clientsocket);
if (::close(clientsocket) < 0)
{
std::cerr << "Error in calling close\n";
}
pthread_exit(NULL);
}
void* wait_stdin(void *arg)
{
pthread_detach(pthread_self());
std::string text;
while (1)
{
std::getline(std::cin, text);
if (0 == text.compare("show client details") || 0 == text.compare("SHOW CLIENT DETAILS"))
{
std::map<int, std::pair<std::string, std::string> >::iterator iter = client_details.begin();
bool atleast_one=false;
for (iter = client_details.begin(); iter != client_details.end(); ++iter)
{
std::cout << (iter->second).first << ":" << (iter->second).second << '\n';
atleast_one = true;
}
if (!atleast_one)
std::cout << "No clients connected\n";
} else if (0 == text.compare("shut") || 0 == text.compare("SHUT"))
{
raise(SIGINT);
} else
{
std::cout << "Invalid Command Issued\nTry \"show client details\" or \"shut\"\n";
}
}
pthread_exit(NULL);
}
void Server::start_listening()
{
s.listen();
if ((pthread_create(&stdin_thread, NULL, &wait_stdin, NULL)) != 0) /* create new thread for server stdin input */
{
std::cerr << ("SERVER:Error Creating A thread for stdin\n");
exit(EXIT_FAILURE);
}
std::string cli_name;
while (1)
{
int *conn_s;
std::string time_accept;
conn_s = (int *) malloc(sizeof (int));
cli_name = s.accept(conn_s);
/* Insert into map details of all clients */
time(&rawtime);
time_accept = ctime(&rawtime);
client_details.insert(std::make_pair(*conn_s, std::make_pair(cli_name, time_accept)));
if ((pthread_create(&process_thread, NULL, &process_request, conn_s)) != 0) /* new thread for each client */
{
std::cerr << ("SERVER:Error Creating A thread for Socket(%d)\n",
*conn_s);
exit(EXIT_FAILURE);
}
}
}
/*
Populate the list on server startup.
Data persistency.
*/
void Server::populate_lists()
{
intlist.fillList(INT_FILE_PATH);
floatlist.fillList(FLOAT_FILE_PATH);
stringlist.fillList(STRING_FILE_PATH);
}