ffead.server.doc
Server.cpp
1 /*
2  Copyright 2009-2012, Sumeet Chhetri
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16 /*
17  * Server.cpp
18  *
19  * Created on: Jan 2, 2010
20  * Author: sumeet
21  */
22 
23 #include "Server.h"
24 
25 
26 void sigchld_handler(int s)
27 {
28  while(waitpid(-1, NULL, WNOHANG) > 0);
29 }
30 
31 Server::Server()
32 {
33  runn = false;
34 }
35 
36 Server::Server(string port,int waiting,Service serv)
37 {
38  runn = true;
39  service = serv;
40  logger = Logger::getLogger("Server");
41  struct addrinfo hints, *servinfo, *p;
42  struct sigaction sa;
43  int yes=1;
44  int rv;
45 
46  memset(&hints, 0, sizeof hints);
47  hints.ai_family = AF_UNSPEC;
48  hints.ai_socktype = SOCK_STREAM;
49  hints.ai_flags = AI_PASSIVE; // use my IP
50  if ((rv = getaddrinfo(NULL, port.c_str(), &hints, &servinfo)) != 0) {
51  fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
52  exit(0);
53  }
54  // loop through all the results and bind to the first we can
55  for(p = servinfo; p != NULL; p = p->ai_next)
56  {
57  if ((this->sock = socket(p->ai_family, p->ai_socktype,p->ai_protocol)) == -1)
58  {
59  perror("server: socket");
60  continue;
61  }
62  if (setsockopt(this->sock, SOL_SOCKET, SO_REUSEADDR, &yes,
63  sizeof(int)) == -1) {
64  perror("setsockopt");
65  exit(1);
66  }
67  if (bind(this->sock, p->ai_addr, p->ai_addrlen) == -1) {
68  close(this->sock);
69  perror("server: bind");
70  continue;
71  }
72  break;
73  }
74 
75  if (p == NULL)
76  {
77  fprintf(stderr, "server: failed to bind\n");
78  exit(0);
79  }
80  freeaddrinfo(servinfo); // all done with this structure
81  if (listen(this->sock, BACKLOGM) == -1)
82  {
83  perror("listen");
84  exit(1);
85  }
86  sa.sa_handler = sigchld_handler; // reap all dead processes
87  sigemptyset(&sa.sa_mask);
88  sa.sa_flags = SA_RESTART;
89  if (sigaction(SIGCHLD, &sa, NULL) == -1)
90  {
91  perror("sigaction");
92  exit(1);
93  }
94  logger << ("waiting for connections on " + port + ".....") << endl;
95 
96  if(fork()==0)
97  {
98  fd_set master; // master file descriptor list
99  fd_set read_fds; // temp file descriptor list for select()
100  int fdmax; // maximum file descriptor number
101 
102  FD_ZERO(&master); // clear the master and temp sets
103  FD_ZERO(&read_fds);
104 
105  FD_SET(this->sock, &master);
106  // keep track of the biggest file descriptor
107  fdmax = this->sock; // so far, it's this on
108 
109  while(runn)
110  {
111  read_fds = master; // copy it
112  int nfds = select(fdmax+1, &read_fds, NULL, NULL, NULL);
113  if (nfds == -1)
114  {
115  perror("epoll_wait");
116  break;
117  }
118  for(int n=0;n<=fdmax;n++)
119  {
120  if (FD_ISSET(n, &read_fds))
121  {
122  if (n == this->sock)
123  {
124  int new_fd = this->Accept();
125  if (new_fd == -1)
126  {
127  perror("accept");
128  continue;
129  }
130  else
131  {
132  fcntl(new_fd, F_SETFL, fcntl(new_fd, F_GETFD, 0) | O_NONBLOCK);
133  FD_SET(new_fd, &master); // add to master set
134  if (new_fd > fdmax) { // keep track of the max
135  fdmax = new_fd;
136  }
137  }
138  }
139  else
140  {
141  //Thread pthread(serv, &new_fd);
142  //pthread.execute();
143  }
144  }
145  }
146  }
147  }
148 
149 }
150 
151 Server::Server(string port,bool block,int waiting,Service serv,int mode)
152 {
153  runn = true;
154 
155  logger = Logger::getLogger("Server");
156 
157  service = serv;
158  struct addrinfo hints, *servinfo, *p;
159  struct sigaction sa;
160  int yes=1;
161  int rv;
162 
163  if(mode<1 || mode >3)
164  mode = 3;
165 
166  memset(&hints, 0, sizeof hints);
167  hints.ai_family = AF_UNSPEC;
168  hints.ai_socktype = SOCK_STREAM;
169  hints.ai_flags = AI_PASSIVE; // use my IP
170  if ((rv = getaddrinfo(NULL, port.c_str(), &hints, &servinfo)) != 0) {
171  fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
172  exit(0);
173  }
174  // loop through all the results and bind to the first we can
175  for(p = servinfo; p != NULL; p = p->ai_next)
176  {
177  if ((this->sock = socket(p->ai_family, p->ai_socktype,p->ai_protocol)) == -1)
178  {
179  perror("server: socket");
180  continue;
181  }
182  if (setsockopt(this->sock, SOL_SOCKET, SO_REUSEADDR, &yes,
183  sizeof(int)) == -1) {
184  perror("setsockopt");
185  exit(1);
186  }
187  if (bind(this->sock, p->ai_addr, p->ai_addrlen) == -1) {
188  close(this->sock);
189  perror("server: bind");
190  continue;
191  }
192  break;
193  }
194  //int blockMode = 1;
195  //ioctl(this->sock, FIONBIO, &blockMode);
196  //fcntl(this->sock, F_SETFL, O_NONBLOCK);
197  //fcntl (this->sock, F_SETFL, fcntl(this->sock, F_GETFD, 0) | O_NONBLOCK);
198  if (p == NULL)
199  {
200  fprintf(stderr, "server: failed to bind\n");
201  exit(0);
202  }
203  freeaddrinfo(servinfo); // all done with this structure
204  if (listen(this->sock, BACKLOGM) == -1)
205  {
206  perror("listen");
207  exit(1);
208  }
209  sa.sa_handler = sigchld_handler; // reap all dead processes
210  sigemptyset(&sa.sa_mask);
211  sa.sa_flags = SA_RESTART;
212  if (sigaction(SIGCHLD, &sa, NULL) == -1)
213  {
214  perror("sigaction");
215  exit(1);
216  }
217  logger << ("waiting for connections on " + port + ".....") << endl;
218  if(mode==1)
219  {
220  if(fork()==0)
221  {
222  servicing(this);
223  }
224  }
225  else if(mode==2)
226  {
227  Thread servicing_thread(&servicing, this);
228  servicing_thread.execute();
229  }
230  else if(mode==3)
231  servicing(this);
232 }
233 
234 Server::~Server() {
235  // TODO Auto-generated destructor stub
236 }
237 
238 void* Server::servicing(void* arg)
239 {
240  Server* server = (Server*)arg;
241  Service serv = server->service;
242  while(server->runn)
243  {
244  int new_fd = server->Accept();
245  if (new_fd == -1)
246  {
247  perror("accept");
248  continue;
249  }
250  else
251  {
252  Thread pthread(serv, &new_fd);
253  pthread.execute();
254  }
255  }
256  return NULL;
257 }
258 
259 int Server::Accept()
260 {
261  socklen_t sin_size = sizeof their_addr;
262  int new_fd = accept(this->sock, (struct sockaddr *)&(this->their_addr), &sin_size);
263  return new_fd;
264 }
265 int Server::Send(int fd,string data)
266 {
267  int bytes = send(fd,data.c_str(),data.length(),0);
268  if(bytes == -1)
269  {
270  logger << "send failed" << endl;
271  }
272  return bytes;
273 }
274 int Server::Send(int fd,vector<char> data)
275 {
276  int bytes = send(fd,&data[0],data.size(),0);
277  if(bytes == -1)
278  {
279  logger << "send failed" << endl;
280  }
281  return bytes;
282 }
283 int Server::Send(int fd,vector<unsigned char> data)
284 {
285  int bytes = send(fd,&data[0],data.size(),0);
286  if(bytes == -1)
287  {
288  logger << "send failed" << endl;
289  }
290  return bytes;
291 }
292 int Server::Send(int fd,char *data)
293 {
294  int bytes = send(fd,data,sizeof data,0);
295  if(bytes == -1)
296  {
297  logger << "send failed" << endl;
298  }
299  return bytes;
300 }
301 int Server::Send(int fd,unsigned char *data)
302 {
303  int bytes = send(fd,data,sizeof data,0);
304  if(bytes == -1)
305  {
306  logger << "send failed" << endl;
307  }
308  return bytes;
309 }
310 
311 int Server::Receive(int fd,string &data,int bytes)
312 {
313  if(bytes==0)
314  return -1;
315  char buf[bytes];
316  int bytesr = recv(fd, buf, bytes, 0);
317  /*string temp;
318  stringstream ss;
319  ss << buf;
320  while(getline(ss,temp,'\r'))
321  {
322  data.append(temp);
323  }*/
324  string temp(buf,buf+bytesr);
325  data = temp;
326  memset(&buf[0], 0, sizeof(buf));
327  return bytesr;
328 }
329 int Server::Receive(int fd,vector<char> &data,int bytes)
330 {
331  if(bytes==0)
332  return -1;
333  char te[bytes];
334  int bytesr = Receive(fd,te,bytes);
335  data.resize(bytes);
336  copy(te,te+bytes,data.begin());
337  return bytesr;
338 }
339 int Server::Receive(int fd,vector<unsigned char>& data,int bytes)
340 {
341  if(bytes==0)
342  return -1;
343  char te[bytes];
344  int bytesr = Receive(fd,te,bytes);
345  data.resize(bytes);
346  copy(te,te+bytes,data.begin());
347  return bytesr;
348 }
349 int Server::Receive(int fd,char data[],int bytes)
350 {
351  if(bytes==0)
352  return -1;
353  int bytesr = recv(fd, data, bytes, 0);
354  return bytesr;
355 }
356 int Server::Receive(int fd,unsigned char data[],int bytes)
357 {
358  if(bytes==0)
359  return -1;
360  int bytesr = recv(fd, data, bytes, 0);
361  return bytesr;
362 }
363 int Server::Receive(int fd,vector<string>& data,int bytes)
364 {
365  if(bytes==0)
366  return -1;
367  char te[bytes];
368  string temp;
369  int bytesr = Receive(fd,te,bytes);
370  stringstream ss;
371  ss << te;
372  while(getline(ss,temp,'\n'))
373  {
374  data.push_back(temp);
375  //logger << temp << endl;
376  }
377  memset(&te[0], 0, sizeof(te));
378  return bytesr;
379 }
380 
381 int Server::createListener(string port,bool block)
382 {
383  int sockfd;
384  struct addrinfo hints, *servinfo, *p;
385  struct sigaction sa;
386  int yes=1;
387  int rv;
388 
389  memset(&hints, 0, sizeof hints);
390  hints.ai_family = AF_UNSPEC;
391  hints.ai_socktype = SOCK_STREAM;
392  hints.ai_flags = AI_PASSIVE; // use my IP
393  if ((rv = getaddrinfo(NULL, port.c_str(), &hints, &servinfo)) != 0) {
394  fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
395  exit(0);
396  }
397  // loop through all the results and bind to the first we can
398  for(p = servinfo; p != NULL; p = p->ai_next)
399  {
400  if ((sockfd = socket(p->ai_family, p->ai_socktype,p->ai_protocol)) == -1)
401  {
402  perror("server: socket");
403  continue;
404  }
405  if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
406  sizeof(int)) == -1) {
407  perror("setsockopt");
408  exit(1);
409  }
410  if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
411  close(sockfd);
412  perror("server: bind");
413  continue;
414  }
415  break;
416  }
417  if (p == NULL)
418  {
419  fprintf(stderr, "server: failed to bind\n");
420  exit(0);
421  }
422  freeaddrinfo(servinfo); // all done with this structure
423  if (listen(sockfd, BACKLOGM) == -1)
424  {
425  perror("listen");
426  exit(1);
427  }
428  sa.sa_handler = sigchld_handler; // reap all dead processes
429  sigemptyset(&sa.sa_mask);
430  sa.sa_flags = SA_RESTART;
431  if (sigaction(SIGCHLD, &sa, NULL) == -1)
432  {
433  perror("sigaction");
434  exit(1);
435  }
436 
437  if(!block)
438  {
439  fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0) | O_NONBLOCK);
440  }
441  return sockfd;
442 }
443 
444 int Server::createListener(string ipAddress,string port,bool block)
445 {
446  int sockfd;
447  struct addrinfo hints, *servinfo, *p;
448  struct sigaction sa;
449  int yes=1;
450  int rv;
451 
452  memset(&hints, 0, sizeof hints);
453  hints.ai_family = AF_UNSPEC;
454  hints.ai_socktype = SOCK_STREAM;
455  hints.ai_flags = AI_PASSIVE; // use my IP
456 
457  const char *ip_addr = NULL;
458  if(ipAddress!="")
459  ip_addr = ipAddress.c_str();
460 
461  if ((rv = getaddrinfo(ip_addr, port.c_str(), &hints, &servinfo)) != 0) {
462  fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
463  exit(0);
464  }
465  // loop through all the results and bind to the first we can
466  for(p = servinfo; p != NULL; p = p->ai_next)
467  {
468  if ((sockfd = socket(p->ai_family, p->ai_socktype,p->ai_protocol)) == -1)
469  {
470  perror("server: socket");
471  continue;
472  }
473  if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
474  sizeof(int)) == -1) {
475  perror("setsockopt");
476  exit(1);
477  }
478  if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
479  close(sockfd);
480  perror("server: bind");
481  continue;
482  }
483  break;
484  }
485  if (p == NULL)
486  {
487  fprintf(stderr, "server: failed to bind\n");
488  exit(0);
489  }
490  freeaddrinfo(servinfo); // all done with this structure
491  if (listen(sockfd, BACKLOGM) == -1)
492  {
493  perror("listen");
494  exit(1);
495  }
496  sa.sa_handler = sigchld_handler; // reap all dead processes
497  sigemptyset(&sa.sa_mask);
498  sa.sa_flags = SA_RESTART;
499  if (sigaction(SIGCHLD, &sa, NULL) == -1)
500  {
501  perror("sigaction");
502  exit(1);
503  }
504 
505  if(!block)
506  {
507  fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0) | O_NONBLOCK);
508  }
509  return sockfd;
510 }