MCS  0.3.3-alpha7
Socket.cc
1 // ----------------------------------------------------------------------^
2 // Copyright (C) 2004, 2005, 2006, 2007, 2008 Giorgio Calderone
3 // (mailto: <gcalderone@ifc.inaf.it>)
4 //
5 // This file is part of MCS.
6 //
7 // MCS is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
11 //
12 // MCS is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with MCS; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21 // ----------------------------------------------------------------------$
22 
23 
24 #include "mcs.hh"
25 using namespace mcs;
26 
27 #include "fcntl.h"
28 
29 
30 #define MCS_SOCKET_START "DATA-START %d (%d)"
31 #define MCS_SOCKET_SENDING "DATA-CHUNK %d"
32 #define MCS_SOCKET_STOP "DATA-STOP"
33 
34 
35 
36 
37 //--------------------------------------------------------
39 {
40  struct if_nameindex* ni;
41  unsigned int i=0;
42  bool found = false;
43 
44  ni = if_nameindex();
45  while (ni[i].if_index) {
46  names.push_back(string(ni[i].if_name));
47  i++;
48  }
49  if_freenameindex(ni);
50 
51 
52  for (i=0; i<names.size(); i++)
53  if (name == names[i]) {
54  lindex = i;
55  found = true;
56  break;
57  }
58  if (! found)
59  throw MCS_FATAL(MSG_NET_INTERFACE_NAME_NOT_EXISTS, name.csz);
60 
61  if (! isup())
62  throw MCS_FATAL(MSG_NET_INTERFACE_NOT_ACTIVE, name.csz);
63 }
64 
65 
67 {}
68 
69 
70 string mcs::NetInterface::name(int index)
71 {
72  if (index == -1)
73  return names[lindex];
74 
75  if ((unsigned int) index >= names.size())
76  throw MCS_FATAL(MSG_NET_INTERFACE_ID_NOT_EXISTS, index, names.size());
77 
78 
79  return names[index];
80 }
81 
83 {
84  return lindex;
85 }
86 
88 {
89  return names.size();
90 }
91 
92 
93 int mcs::NetInterface::req(int ioctl_num, struct ifreq *ifr)
94 {
95  int sock, ret;
96 
97  sock = socket(AF_INET, SOCK_STREAM, 0);
98  strncpy(ifr->ifr_name, names[lindex].c_str(), IFNAMSIZ-1);
99  ifr->ifr_name[IFNAMSIZ-1] = 0;
100 
101  ret = ioctl(sock, ioctl_num, ifr);
102  close(sock);
103  if (ret == -1)
104  throw MCS_FATAL(MSG_RETRIEVING_INTERFACE_FLAGS, names[lindex].csz);
105 
106  return ret;
107 }
108 
109 
110 int mcs::NetInterface::getflags()
111 {
112  struct ifreq ifr;
113  req(SIOCGIFFLAGS, &ifr);
114  return ifr.ifr_flags;
115 }
116 
117 
118 bool mcs::NetInterface::isup()
119 {
120  return ((getflags() & IFF_UP) ? true : false);
121 }
122 
123 
124 void mcs::NetInterface::str_sockaddr(struct sockaddr* sa)
125 {
126  struct ifreq ifr;
127 
128  ifr.ifr_addr.sa_family = AF_INET;
129  req(SIOCGIFADDR, &ifr);
130 
131  sa->sa_family = ifr.ifr_addr.sa_family;
132  memcpy(sa->sa_data, ifr.ifr_addr.sa_data, 14);
133 }
134 
135 
136 void mcs::NetInterface::str_sockaddr_in(struct sockaddr_in* sin)
137 {
138  struct sockaddr sa;
139  str_sockaddr(&sa);
140  memcpy(sin, &sa, sizeof(struct sockaddr_in));
141 }
142 
143 
145 {
146  string s;
147  struct sockaddr_in sin;
148 
149  int actIndex = lindex;
150  if (index != -1 ) {
151  if ((unsigned int) index >= names.size())
152  throw MCS_FATAL(MSG_NET_INTERFACE_ID_NOT_EXISTS, index, names.size());
153 
154  lindex = index;
155  }
156 
157  s = "(not available)";
158  try {
159  str_sockaddr_in(&sin);
160  s = inet_ntoa(sin.sin_addr);
161  }
162  catch (Event e) {}
163 
164  lindex = actIndex;
165  return s;
166 }
167 
168 
169 
170 
171 
172 
173 
174 
175 
176 //--------------------------------------------------------
178 {
179  struct hostent* he;
180 
181  he = gethostbyname(host.c_str());
182  if (he == NULL)
183  throw MCS_FATAL(MSG_RETRIEVING_HOSTNAME, hstrerror(h_errno));
184 
185  host = he->h_name;
186  ipaddr = inet_ntoa(*(struct in_addr*)he->h_addr);
187  populate_sockaddr_in();
188 }
189 
190 
192 {
193  int ret;
194  socklen_t len;
195 
196  len = sizeof(sin);
197  ret = getpeername(sockfd, (struct sockaddr*)&sin, &len);
198  if (ret == -1)
199  throw MCS_FATAL(MSG_RETRIEVING_PEERNAME, strerror(errno));
200 
201  struct hostent* he;
202  he = gethostbyaddr(&(sin.sin_addr), sizeof(struct in_addr), AF_INET);
203 
204 // if (he == NULL)
205 // throw MCS_FATAL(MSG_RETRIEVING_HOST_INFO, hstrerror(errno));
206 
207  if (he != NULL) {
208  host = he->h_name;
209  ipaddr = inet_ntoa(*(struct in_addr*)he->h_addr);
210  populate_sockaddr_in();
211  }
212 }
213 
215 {}
216 
217 
218 void mcs::HostInfo::populate_sockaddr_in()
219 {
220  struct in_addr addr;
221  inet_aton(ipaddr.c_str(), &addr);
222 
223  sin.sin_family = AF_INET;
224  sin.sin_port = htons(0);
225  sin.sin_addr.s_addr = addr.s_addr;
226  memset(&(sin.sin_zero), '\0', 8);
227 }
228 
229 string mcs::HostInfo::hostname() { return host; }
230 string mcs::HostInfo::ipaddress() { return ipaddr; }
231 
232 
233 
234 
235 
236 
237 
238 
239 
240 
241 //--------------------------------------------------------
242 mcs::Socket::Socket(string host, unsigned short int port,
243  unsigned int readTimeout, unsigned int writeTimeout,
244  bool use_ssl) : HostInfo(host)
245 {
246  MCS_DEBUG_SETUP(0, "Socket");
247 
248  this->port = port;
249  this->use_ssl = use_ssl;
250 #ifdef HAVE_OPENSSL_SSL_H
251  this->ssl_ctx = NULL;
252 #endif //HAVE_OPENSSL_SSL_H
253 
254  set_struct_timeval(readTimeout , &readto);
255  set_struct_timeval(writeTimeout, &writeto);
256 
257  sockfd = socketToHost(port);
258 
259 #ifdef HAVE_OPENSSL_SSL_H
260  if (use_ssl) {
261  SSL_library_init();
262  ERR_load_crypto_strings();
263  SSL_load_error_strings();
264 
265  ssl_ctx = SSL_CTX_new(SSLv23_method());
266 
267  ssl=SSL_new(ssl_ctx);
268  sbio=BIO_new_socket(sockfd, BIO_NOCLOSE);
269  SSL_set_bio(ssl, sbio, sbio);
270 
271  int ret = SSL_connect(ssl);
272  if (ret <= 0)
273  throw MCS_ERROR( MSG_SSL_CONNECT_ERROR );
274 
275  //ret = SSL_get_error(ssl, ret);
276  //switch (ret) {
277  //case SSL_ERROR_NONE:
278  // break;
279  //case SSL_ERROR_ZERO_RETURN: cout << "qui1" << endl; break;
280  //case SSL_ERROR_WANT_READ: cout << "qui2" << endl; break;
281  //case SSL_ERROR_WANT_WRITE: cout << "qui3" << endl; break;
282  //case SSL_ERROR_WANT_CONNECT: cout << "qui4" << endl; break;
283  //case SSL_ERROR_WANT_ACCEPT: cout << "qui5" << endl; break;
284  //case SSL_ERROR_WANT_X509_LOOKUP:cout << "qui6" << endl; break;
285  //case SSL_ERROR_SYSCALL: cout << "qui7" << endl; break;
286  //case SSL_ERROR_SSL: cout << "qui8" << endl; break;
287  //}
288  //cout << ERR_error_string(ret, NULL) << endl;
289  //
290  //ERR_print_errors_fp(stderr);
291  //throw MCS_ERROR( MSG_SSL_CONNECT_ERROR );
292  }
293 #endif //HAVE_OPENSSL_SSL_H
294 }
295 
296 
298  unsigned int readTimeout,
299  unsigned int writeTimeout,
300  void* ssl_ctx) : HostInfo(sockfd)
301 {
302  MCS_DEBUG_SETUP(0, "Socket");
303 
304  this->port = 0;
305  this->use_ssl = (ssl_ctx != NULL);
306 #ifdef HAVE_OPENSSL_SSL_H
307  this->ssl_ctx = NULL;
308 #endif //HAVE_OPENSSL_SSL_H
309 
310  set_struct_timeval(readTimeout , &readto);
311  set_struct_timeval(writeTimeout, &writeto);
312 
313  this->sockfd = sockfd;
314 
315 
316 #ifdef HAVE_OPENSSL_SSL_H
317  if (use_ssl) {
318  SSL_CTX* ctx = (SSL_CTX*) ssl_ctx;
319 
320  sbio=BIO_new_socket(sockfd, BIO_NOCLOSE);
321  ssl=SSL_new(ctx);
322  SSL_set_bio(ssl, sbio, sbio);
323 
324  if(SSL_accept(ssl) <= 0)
325  throw MCS_ERROR( MSG_SSL_ACCEPT_ERROR );
326  }
327 #endif //HAVE_OPENSSL_SSL_H
328 }
329 
330 
331 
332 int mcs::Socket::socketToHost(unsigned short port)
333 {
334  int ret;
335  //int sockfd;
336  long socketflags;
337 
338  sockfd = socket(PF_INET, SOCK_STREAM, 0);
339 
340  sin.sin_port = htons(port);
341 
342  // Set non-blocking
343  socketflags = fcntl(sockfd, F_GETFL, NULL);
344  fcntl(sockfd, F_SETFL, socketflags | O_NONBLOCK);
345 
346  ret = connect(sockfd, (struct sockaddr *)&sin, sizeof(struct sockaddr));
347 
348  if (ret == -1) {
349  if (errno == EINPROGRESS)
350  chkSend(THROW);
351  else
352  throw MCS_FATAL(MSG_CANT_CONNECT_TO_HOST, strerror(errno));
353  }
354 
355  // Set to blocking mode again...
356  fcntl(sockfd, F_SETFL, socketflags);
357 
358  return sockfd;
359 }
360 
361 
363 {
364  Socket::Close();
365 }
366 
367 
369 {
370  if (sockfd) {
371 #ifdef HAVE_OPENSSL_SSL_H
372  if (use_ssl) {
373  SSL_shutdown(ssl);
374  SSL_free(ssl);
375 
376  if (ssl_ctx)
377  SSL_CTX_free (ssl_ctx);
378  }
379 #endif //HAVE_OPENSSL_SSL_H
380 
381  close(sockfd);
382  sockfd = 0;
383  }
384 }
385 
386 
388 {
389  bool b = false;
390  int ret;
391  struct timeval timeout;
392  timeout.tv_sec = writeto.tv_sec;
393  timeout.tv_usec = writeto.tv_usec;
394 
395  FD_ZERO(&fds);
396  FD_SET(sockfd, &fds);
397 
398  ret = select(sockfd+1, NULL, &fds, NULL, &timeout);
399  if (ret == -1) { //Error
400  if (throwexc)
401  throw MCS_FATAL(MSG_CALLING_SELECT, strerror(errno));
402 
403  } else if (ret == 0) { //Timeout
404  if (throwexc)
405  throw MCS_FATAL(MSG_TIME_OUT);
406  }
407 
408  else { //Should be ok
409  if (FD_ISSET(sockfd, &fds))
410  b = true;
411  else //We didn't get an error nor a timeout, but the socket is not in the list???
412  throw MCS_FATAL(MSG_UNEXPECTED);
413  }
414 
415  return b;
416 }
417 
418 
419 bool mcs::Socket::chkRecv(bool chkDataAvailable, enum ThrowExceptions throwexc)
420 {
421  bool b = false;
422  int ret;
423  struct timeval timeout;
424 
425  if (chkDataAvailable) {
426  timeout.tv_sec = 0;
427  timeout.tv_usec = 0;
428  }
429  else {
430  timeout.tv_sec = readto.tv_sec;
431  timeout.tv_usec = readto.tv_usec;
432  }
433 
434  FD_ZERO(&fds);
435  FD_SET(sockfd, &fds);
436 
437 #ifdef HAVE_OPENSSL_SSL_H
438  if (use_ssl) {
439  ret = SSL_pending(ssl);
440  if (ret > 0)
441  return true;
442  }
443 #endif //HAVE_OPENSSL_SSL_H
444 
445  ret = select(sockfd+1, &fds, NULL, NULL, &timeout);
446  if (ret == -1) { //Error
447  if (throwexc)
448  throw MCS_FATAL(MSG_CALLING_SELECT, strerror(errno));
449  }
450  else if (ret == 0) { //Timeout
451  if (throwexc)
452  throw MCS_FATAL(MSG_TIME_OUT);
453  }
454  else { //Should be ok
455  if (FD_ISSET(sockfd, &fds)) {
456  char a;
457  ret = recv(sockfd, &a, 1, MSG_PEEK);
458  if (ret == -1) { //Error
459  if (throwexc)
460  throw MCS_FATAL(MSG_CALLING_RECV, strerror(errno));
461  }
462  else if (ret == 0) { //Connection closed by peer
463  if (throwexc)
464  throw MCS_FATAL(MSG_CLOSED_BY_PEER);
465  }
466  else {
467  b = true;
468  }
469  }
470  else //We didn't get an error nor a timeout but the socket isn't in the list
471  throw MCS_FATAL(MSG_UNEXPECTED);
472  }
473 
474  return b;
475 }
476 
477 
478 void mcs::Socket::sendChunk(void* p, unsigned int size)
479 {
480  string s;
481  char buf[40];
482  unsigned int resp;
483 
484  sprintf(buf, MCS_SOCKET_SENDING, size);
485  print(buf);
486 
487  s = getline();
488  if ((sscanf(s.c_str(), "%d", &resp) == 1) && (resp == size) ) {
489  write(p, size);
490  }
491  else
492  throw MCS_WARN(MSG_SEND_ABORT_BY_RECEIVER);
493 }
494 
495 
496 unsigned int mcs::Socket::recvChunk(void* p, unsigned int maxsize)
497 {
498  string s;
499  char buf[60];
500  unsigned int chunksize;
501 
502  s = getline();
503  if (s == MCS_SOCKET_STOP)
504  return 0;
505 
506  if (sscanf(s.c_str(), MCS_SOCKET_SENDING, &chunksize) != 1)
507  throw MCS_FATAL(MSG_PROTOCOL, s.c_str());
508 
509  if (chunksize > maxsize)
510  throw MCS_FATAL(MSG_NOT_ENOUGH_SPACE, chunksize, maxsize);
511 
512  sprintf(buf, "%d", chunksize);
513  print(buf);
514 
515  read(p, chunksize);
516  return chunksize;
517 }
518 
519 
520 unsigned int mcs::Socket::recvChunk(Buffer* abuf)
521 {
522  string s;
523  char buf[60];
524  unsigned int chunksize;
525 
526  s = getline();
527  if (s == MCS_SOCKET_STOP)
528  return 0;
529 
530  if (sscanf(s.c_str(), MCS_SOCKET_SENDING, &chunksize) != 1)
531  throw MCS_FATAL(MSG_PROTOCOL, s.c_str());
532 
533  abuf->resize(chunksize);
534  char* p = (*abuf)[0];
535 
536  sprintf(buf, "%d", chunksize);
537  print(buf);
538 
539  read(p, chunksize);
540  return chunksize;
541 }
542 
543 
544 
545 
546 unsigned int mcs::Socket::read(void* buf, unsigned int count)
547 {
548  unsigned int ret, lcount;
549  char* p = (char*) buf;
550  chkRecv();
551 
552  lcount = 0;
553  while (count>0) {
554 
555 #ifdef HAVE_OPENSSL_SSL_H
556  if (use_ssl) {
557  ret = SSL_read(ssl, p ,count);
558  switch(SSL_get_error(ssl, ret)) {
559  case SSL_ERROR_NONE:
560  break;
561  //case SSL_ERROR_ZERO_RETURN:
562  // goto shutdown;
563  //case SSL_ERROR_SYSCALL:
564  // fprintf(stderr,
565  // "SSL Error: Premature close\n");
566  // goto done;
567  default:
568  throw MCS_FATAL(MSG_CLOSED_BY_PEER);
569  //berr_exit("SSL read problem");
570  }
571  }
572  else
573 #endif //HAVE_OPENSSL_SSL_H
574  ret = recv(sockfd, (void*) p, count, 0);
575 
576  if (ret == 0)
577  throw MCS_FATAL(MSG_CLOSED_BY_PEER);
578 
579  count -= ret;
580  p += ret;
581  lcount += ret;
582  }
583 
584  return lcount;
585 }
586 
587 
588 unsigned int mcs::Socket::write(void* buf, unsigned int count)
589 {
590  unsigned int ret;
591 
592  chkSend();
593 
594 #ifdef HAVE_OPENSSL_SSL_H
595  if (use_ssl) {
596  ret = SSL_write(ssl, buf, count);
597  switch(SSL_get_error(ssl, ret)) {
598  case SSL_ERROR_NONE:
599  break;
600  default:
601  throw MCS_FATAL(MSG_CALLING_SEND, "SSL write problem");
602  }
603  }
604  else
605 #endif //HAVE_OPENSSL_SSL_H
606  ret = send(sockfd, buf, count, 0);
607 
608  if (ret != count)
609  throw MCS_FATAL(MSG_CALLING_SEND, strerror(errno));
610 
611  return ret;
612 }
613 
614 
616 {
617  char p = 0;
618  string s = "";
619 
620  while (p != '\n') {
621  read(&p, 1);
622  s += p;
623  }
624 
625  remTrailing(s, "\n");
626  return s;
627 }
628 
629 
630 void mcs::Socket::print(string s)
631 {
632  s += "\n";
633  write((void*) s.c_str(), s.length());
634 }
635 
636 
638 {
639  void* p;
640  char buf[40];
641  unsigned int chunksize;
642 
643  MCS_DEBUG_ENTER(NOARGS);
644 
645  if (from->knowSize())
646  sprintf(buf, MCS_SOCKET_START, from->size(), from->maxChunkSize());
647  else
648  sprintf(buf, MCS_SOCKET_START, 0, from->maxChunkSize());
649  print(buf);
650 
651  while ((p = from->nextChunk(chunksize))) {
652  if (chunksize > 0)
653  sendChunk(p, chunksize);
654  }
655 
656  sprintf(buf, MCS_SOCKET_STOP);
657  print(buf);
658  MCS_DEBUG_LEAVE(NOARGS);
659 }
660 
661 
662 unsigned int mcs::Socket::recvData(char** buffer, unsigned int maxsize)
663 {
664  unsigned int size, chunksize, accum, tmp;
665  string s;
666 
667  s = getline();
668  if (sscanf(s.c_str(), MCS_SOCKET_START, &size, &chunksize) != 2)
669  throw MCS_FATAL(MSG_PROTOCOL, s.c_str());
670 
671  Buffer* abuf;
672  if (*buffer)
673  abuf = new Buffer(*buffer, maxsize);
674  else
675  abuf = new Buffer(DONT_FREE);
676 
677  accum = 0;
678  while ((tmp = recvChunk(abuf)))
679  accum += tmp;
680 
681  if (! (*buffer))
682  *buffer = (*abuf)[0];
683 
684  return accum;
685 
686 // unsigned int size, chunksize, accum, tmp;
687 // char* p;
688 // string s;
689 //
690 // s = getline();
691 // if (sscanf(s.c_str(), MCS_SOCKET_START, &size, &chunksize) != 2)
692 // throw MCS_FATAL(MSG_PROTOCOL, s.c_str());
693 //
694 // if (! (*buffer)) {
695 // if (size > 0) {
696 // *buffer = (char*) malloc(size);
697 // maxsize = size;
698 // }
699 // else {
700 // *buffer = (char*) malloc(chunksize);
701 // maxsize = chunksize;
702 // }
703 // }
704 // else {
705 // if (chunksize > maxsize)
706 // throw MCS_FATAL(MSG_NOT_ENOUGH_SPACE, chunksize, maxsize);
707 // }
708 //
709 // accum = 0;
710 // p = *buffer;
711 // while ((tmp = recvChunk(p, maxsize))) {
712 // p += tmp;
713 // accum += tmp;
714 // if (accum > maxsize)
715 // *buffer = (char*) realloc(*buffer, maxsize + chunksize);
716 // }
717 //
718 // return accum;
719 }
720 
721 
722 
723 unsigned int mcs::Socket::recvData(string filename)
724 {
725  ofstream out(filename.c_str(), ios::binary);
726  if (! out.is_open())
727  throw MCS_ERROR(MSG_CANT_OPEN_FILE, filename.c_str());
728 
729  return recvData(out);
730 }
731 
732 
733 unsigned int mcs::Socket::recvData(ofstream& out)
734 {
735  unsigned int size, chunksize, accum, tmp;
736  char* p;
737  string s;
738 
739  s = getline();
740  if (sscanf(s.c_str(), MCS_SOCKET_START, &size, &chunksize) != 2)
741  throw MCS_FATAL(MSG_PROTOCOL, s.c_str());
742 
743  p = (char*) malloc (chunksize);
744  accum = 0;
745  while ((tmp = recvChunk(p, chunksize))) {
746  out.write(p, tmp);
747  accum += tmp;
748  }
749 
750  free(p);
751 
752  return accum;
753 }
754 
755 
756 
757 unsigned int mcs::Socket::recvData(int filedes)
758 {
759  unsigned int size, chunksize, accum, tmp;
760  char* p;
761  string s;
762 
763  s = getline();
764  if (sscanf(s.c_str(), MCS_SOCKET_START, &size, &chunksize) != 2)
765  throw MCS_FATAL(MSG_PROTOCOL, s.c_str());
766 
767  p = (char*) malloc (chunksize);
768  accum = 0;
769  while ((tmp = recvChunk(p, chunksize))) {
770  ::write(filedes, p, tmp);
771  accum += tmp;
772  }
773 
774  free(p);
775 
776  return accum;
777 }
778 
779 
780 
781 
782 void mcs::Socket::set_struct_timeval(unsigned int millisec, struct timeval* time)
783 {
784  float fsec = ((float) millisec) / 1000.0;
785  int isec = (int) rintf(fsec);
786  time->tv_sec = isec;
787  time->tv_usec = 0;
788 }
789 
790 
791 
792 
793 
794 
795 
796 
797 
798 //--------------------------------------------------------
799 mcs::ServerSocket::ServerSocket(string interface, unsigned short int port,
800  bool use_ssl, string sslcert, string sslpriv) :
801  NetInterface(interface)
802 {
803  int ret;
804  struct sockaddr_in sin;
805 
806  this->use_ssl = use_ssl;
807 
808  sockfd = socket(PF_INET, SOCK_STREAM, 0);
809  str_sockaddr_in(&sin);
810  sin.sin_port = htons(port);
811 
812  ret = 1;
813  ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &ret, sizeof(int));
814  ret = bind(sockfd, (struct sockaddr *)&sin, sizeof(struct sockaddr));
815 
816  if (ret == -1)
817  throw MCS_FATAL(MSG_CALLING_BIND, strerror(errno));
818 
819  ret = listen(sockfd, 10);
820  if (ret == -1)
821  throw MCS_FATAL(MSG_CALLING_LISTEN, strerror(errno));
822 
823 
824  //Eventually initialize the SSL library and a SSL context object
825 #ifdef HAVE_OPENSSL_SSL_H
826  ssl_ctx = NULL;
827 
828  if (use_ssl) {
829  SSL_library_init();
830  SSL_load_error_strings();
831  ERR_load_crypto_strings();
832 
833  ssl_ctx=SSL_CTX_new(SSLv23_server_method());
834 
835 
836  if (! SSL_CTX_use_certificate_file(ssl_ctx, sslcert.c_str(),
837  SSL_FILETYPE_PEM))
838  throw MCS_FATAL ( MSG_UNEXPECTED );
839 
840  if (! SSL_CTX_use_PrivateKey_file(ssl_ctx, sslpriv.c_str(),
841  SSL_FILETYPE_PEM))
842  throw MCS_FATAL ( MSG_UNEXPECTED );
843 
844  if (! SSL_CTX_check_private_key(ssl_ctx))
845  throw MCS_FATAL ( MSG_UNEXPECTED );
846  }
847 #endif //HAVE_OPENSSL_SSL_H
848 }
849 
850 
852 {
853  close(sockfd);
854 
855 #ifdef HAVE_OPENSSL_SSL_H
856  if (use_ssl)
857  if (ssl_ctx)
858  SSL_CTX_free (ssl_ctx);
859 #endif //HAVE_OPENSSL_SSL_H
860 }
861 
862 
863 
864 void* mcs::ServerSocket::getSSLContext()
865 {
866 #ifdef HAVE_OPENSSL_SSL_H
867  if (use_ssl)
868  return ssl_ctx;
869  else
870  return NULL;
871 #else
872  return NULL;
873 #endif //HAVE_OPENSSL_SSL_H
874 }
875 
876 
877 
878 bool mcs::ServerSocket::acceptConnection(int& newsock, unsigned int millisec)
879 {
880  struct sockaddr_in sin;
881  socklen_t sin_size = sizeof(struct sockaddr_in);
882 
883  fd_set fds;
884  FD_ZERO(&fds);
885  FD_SET(sockfd, &fds);
886 
887  struct timeval timeout;
888  Socket::set_struct_timeval(millisec, &timeout);
889 
890  int ret = select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
891  if (ret == -1) { //Error
892  throw MCS_FATAL(MSG_CALLING_SELECT, strerror(errno));
893  }
894  else if (ret == 0) { //Timeout
895  return false;
896  }
897  else { //Should be ok
898  if (FD_ISSET(sockfd, &fds))
899  newsock = accept(sockfd, (struct sockaddr *)&sin, &sin_size);
900  else //We didn't get an error nor a timeout but the socket isn't in the list
901  throw MCS_FATAL(MSG_UNEXPECTED);
902  }
903 
904  return true;
905 }
~HostInfo()
Destructor.
Definition: Socket.cc:214
Retrieve informations about network interfaces.
Definition: mcs.hh:1487
string ipaddress()
Return the host IP address.
Definition: Socket.cc:230
~ServerSocket()
Destructor.
Definition: Socket.cc:851
Serialize memory buffers or files into chunks.
Definition: mcs.hh:1290
Socket(const Socket &)
Declared to avoid using of default copy constructor.
~Socket()
Destructor.
Definition: Socket.cc:362
ServerSocket(const ServerSocket &)
Declared to avoid using of default copy constructor.
Hold informations about an event.
Definition: mcs.hh:814
#define csz
Macro to extract a C-style, null terminated string from a string object.
Definition: mcs.hh:486
void print(string s)
Writes a string in the socket adding a newline.
Definition: Socket.cc:630
bool acceptConnection(int &newsock, unsigned int millisec)
Wait for an incoming connection.
Definition: Socket.cc:878
unsigned int write(void *buf, unsigned int count)
Reads data from a buffer and write in the socket.
Definition: Socket.cc:588
int sockfd
C socket file descriptor.
Definition: mcs.hh:1668
unsigned int count()
Return how many network interfaces are present in the system.
Definition: Socket.cc:87
#define MCS_ERROR(A, rest...)
Facility to easily pass all necessary parameter to an Event constructor.
Definition: mcs.hh:964
bool use_ssl
True if the connection should be encrypted.
Definition: mcs.hh:2022
bool knowSize()
Reinitialize internal data.
unsigned int size()
If knowSize() is true, return the size of the entire block of data.
string remTrailing(string &s, const char *p)
Remove any trailing character "p".
Definition: Utils.cc:185
int socketToHost(unsigned short port)
Connect to the host.
Definition: Socket.cc:332
High level buffer.
Definition: mcs.hh:1095
void resize(unsigned int size)
Check size, and eventually enlarge allocated memory.
Definition: Record.cc:81
bool use_ssl
True if the connection should be encrypted.
Definition: mcs.hh:1690
unsigned int read(void *buf, unsigned int count)
Reads data from the socket and write in a buffer.
Definition: Socket.cc:546
string ipaddress(int index=-1)
Return the IP address of an interface.
Definition: Socket.cc:144
unsigned int index()
Return the index of the actual interface.
Definition: Socket.cc:82
HostInfo(const HostInfo &)
Declared to avoid using of default copy constructor.
void * nextChunk(unsigned int &chunksize)
Fills a buffer with next chunk to be sent.
void sendChunk(void *buf, unsigned int size)
Send a chunk of binary data through the socket.
Definition: Socket.cc:478
Main include file for all MCS based applications.
void sendData(Serializable *from)
Send a block of data through the socket.
Definition: Socket.cc:637
bool chkRecv(bool chkDataAvailable=false, enum ThrowExceptions throwexc=THROW)
Check if you can read data from this socket.
Definition: Socket.cc:419
#define MCS_WARN(A, rest...)
Facility to easily pass all necessary parameter to an Event constructor.
Definition: mcs.hh:961
unsigned short int port
Port on which this socket will connect.
Definition: mcs.hh:1687
ThrowExceptions
Values to be used with throwexc parameters.
Definition: mcs.hh:257
bool chkSend(enum ThrowExceptions throwexc=THROW)
Check if you can send data through this socket.
Definition: Socket.cc:387
static void set_struct_timeval(unsigned int millisec, struct timeval *time)
Fill a "struct timeval" with the given interval.
Definition: Socket.cc:782
struct timeval readto
Timeout interval for read operations.
Definition: mcs.hh:1693
NetInterface(string name="lo")
Constructor.
Definition: Socket.cc:38
void Close()
Close the socket.
Definition: Socket.cc:368
unsigned int maxChunkSize()
Return the max size allowed for a chunk.
#define MCS_FATAL(A, rest...)
Facility to easily pass all necessary parameter to an Event constructor.
Definition: mcs.hh:967
unsigned int recvData(char **buffer, unsigned int maxsize)
Receive data and store in a buffer.
Definition: Socket.cc:662
int sockfd
Server socket descriptor.
Definition: mcs.hh:2019
string name(int index=-1)
Return the name of an interface.
Definition: Socket.cc:70
string getline()
Reads from a socket until a newline is encountered.
Definition: Socket.cc:615
~NetInterface()
Destructor.
Definition: Socket.cc:66
fd_set fds
Set of socket file descriptors, used with select().
Definition: mcs.hh:1671
Retrieve informations about a network host.
Definition: mcs.hh:1588
string hostname()
Return the host name.
Definition: Socket.cc:229
struct timeval writeto
Timeout interval fro write operations.
Definition: mcs.hh:1696
unsigned int recvChunk(void *buf, unsigned int size)
Receive a chunk of binary data from the socket.
Definition: Socket.cc:496
Namespace for MCS library.

mcslogo

MCS (My Customizable Server) ver. 0.3.3-alpha7
Documentation generated on Mon May 28 07:39:41 UTC 2018