00001 // ----------------------------------------------------------------------^ 00002 // Copyright (C) 2004, 2005, 2006, 2007, 2008 Giorgio Calderone 00003 // (mailto: <gcalderone@ifc.inaf.it>) 00004 // 00005 // This file is part of MCS. 00006 // 00007 // MCS is free software; you can redistribute it and/or modify 00008 // it under the terms of the GNU General Public License as published by 00009 // the Free Software Foundation; either version 2 of the License, or 00010 // (at your option) any later version. 00011 // 00012 // MCS is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU General Public License 00018 // along with MCS; if not, write to the Free Software 00019 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00020 // 00021 // ----------------------------------------------------------------------$ 00022 00023 00024 #include "mcs.hh" 00025 using namespace mcs; 00026 00027 #include "fcntl.h" 00028 00029 00030 #define MCS_SOCKET_START "DATA-START %d (%d)" 00031 #define MCS_SOCKET_SENDING "DATA-CHUNK %d" 00032 #define MCS_SOCKET_STOP "DATA-STOP" 00033 00034 00035 00036 00037 //-------------------------------------------------------- 00038 mcs::NetInterface::NetInterface(string name) 00039 { 00040 struct if_nameindex* ni; 00041 unsigned int i=0; 00042 bool found = false; 00043 00044 ni = if_nameindex(); 00045 while (ni[i].if_index) { 00046 names.push_back(string(ni[i].if_name)); 00047 i++; 00048 } 00049 if_freenameindex(ni); 00050 00051 00052 for (i=0; i<names.size(); i++) 00053 if (name == names[i]) { 00054 lindex = i; 00055 found = true; 00056 break; 00057 } 00058 if (! found) 00059 throw MCS_FATAL(MSG_NET_INTERFACE_NAME_NOT_EXISTS, name.csz); 00060 00061 if (! isup()) 00062 throw MCS_FATAL(MSG_NET_INTERFACE_NOT_ACTIVE, name.csz); 00063 } 00064 00065 00066 mcs::NetInterface::~NetInterface() 00067 {} 00068 00069 00070 string mcs::NetInterface::name(int index) 00071 { 00072 if (index == -1) 00073 return names[lindex]; 00074 00075 if ((unsigned int) index >= names.size()) 00076 throw MCS_FATAL(MSG_NET_INTERFACE_ID_NOT_EXISTS, index, names.size()); 00077 00078 00079 return names[index]; 00080 } 00081 00082 unsigned int mcs::NetInterface::index() 00083 { 00084 return lindex; 00085 } 00086 00087 unsigned int mcs::NetInterface::count() 00088 { 00089 return names.size(); 00090 } 00091 00092 00093 int mcs::NetInterface::req(int ioctl_num, struct ifreq *ifr) 00094 { 00095 int sock, ret; 00096 00097 sock = socket(AF_INET, SOCK_STREAM, 0); 00098 strncpy(ifr->ifr_name, names[lindex].c_str(), IFNAMSIZ-1); 00099 ifr->ifr_name[IFNAMSIZ-1] = 0; 00100 00101 ret = ioctl(sock, ioctl_num, ifr); 00102 close(sock); 00103 if (ret == -1) 00104 throw MCS_FATAL(MSG_RETRIEVING_INTERFACE_FLAGS, names[lindex].csz); 00105 00106 return ret; 00107 } 00108 00109 00110 int mcs::NetInterface::getflags() 00111 { 00112 struct ifreq ifr; 00113 req(SIOCGIFFLAGS, &ifr); 00114 return ifr.ifr_flags; 00115 } 00116 00117 00118 bool mcs::NetInterface::isup() 00119 { 00120 return ((getflags() & IFF_UP) ? true : false); 00121 } 00122 00123 00124 void mcs::NetInterface::str_sockaddr(struct sockaddr* sa) 00125 { 00126 struct ifreq ifr; 00127 00128 ifr.ifr_addr.sa_family = AF_INET; 00129 req(SIOCGIFADDR, &ifr); 00130 00131 sa->sa_family = ifr.ifr_addr.sa_family; 00132 memcpy(sa->sa_data, ifr.ifr_addr.sa_data, 14); 00133 } 00134 00135 00136 void mcs::NetInterface::str_sockaddr_in(struct sockaddr_in* sin) 00137 { 00138 struct sockaddr sa; 00139 str_sockaddr(&sa); 00140 memcpy(sin, &sa, sizeof(struct sockaddr_in)); 00141 } 00142 00143 00144 string mcs::NetInterface::ipaddress(int index) 00145 { 00146 string s; 00147 struct sockaddr_in sin; 00148 00149 int actIndex = lindex; 00150 if (index != -1 ) { 00151 if ((unsigned int) index >= names.size()) 00152 throw MCS_FATAL(MSG_NET_INTERFACE_ID_NOT_EXISTS, index, names.size()); 00153 00154 lindex = index; 00155 } 00156 00157 s = "(not available)"; 00158 try { 00159 str_sockaddr_in(&sin); 00160 s = inet_ntoa(sin.sin_addr); 00161 } 00162 catch (Event e) {} 00163 00164 lindex = actIndex; 00165 return s; 00166 } 00167 00168 00169 00170 00171 00172 00173 00174 00175 00176 //-------------------------------------------------------- 00177 mcs::HostInfo::HostInfo(string host) 00178 { 00179 struct hostent* he; 00180 00181 he = gethostbyname(host.c_str()); 00182 if (he == NULL) 00183 throw MCS_FATAL(MSG_RETRIEVING_HOSTNAME, hstrerror(h_errno)); 00184 00185 host = he->h_name; 00186 ipaddr = inet_ntoa(*(struct in_addr*)he->h_addr); 00187 populate_sockaddr_in(); 00188 } 00189 00190 00191 mcs::HostInfo::HostInfo(int sockfd) 00192 { 00193 int ret; 00194 socklen_t len; 00195 00196 len = sizeof(sin); 00197 ret = getpeername(sockfd, (struct sockaddr*)&sin, &len); 00198 if (ret == -1) 00199 throw MCS_FATAL(MSG_RETRIEVING_PEERNAME, strerror(errno)); 00200 00201 struct hostent* he; 00202 he = gethostbyaddr(&(sin.sin_addr), sizeof(struct in_addr), AF_INET); 00203 00204 // if (he == NULL) 00205 // throw MCS_FATAL(MSG_RETRIEVING_HOST_INFO, hstrerror(errno)); 00206 00207 if (he != NULL) { 00208 host = he->h_name; 00209 ipaddr = inet_ntoa(*(struct in_addr*)he->h_addr); 00210 populate_sockaddr_in(); 00211 } 00212 } 00213 00214 mcs::HostInfo::~HostInfo() 00215 {} 00216 00217 00218 void mcs::HostInfo::populate_sockaddr_in() 00219 { 00220 struct in_addr addr; 00221 inet_aton(ipaddr.c_str(), &addr); 00222 00223 sin.sin_family = AF_INET; 00224 sin.sin_port = htons(0); 00225 sin.sin_addr.s_addr = addr.s_addr; 00226 memset(&(sin.sin_zero), '\0', 8); 00227 } 00228 00229 string mcs::HostInfo::hostname() { return host; } 00230 string mcs::HostInfo::ipaddress() { return ipaddr; } 00231 00232 00233 00234 00235 00236 00237 00238 00239 00240 00241 //-------------------------------------------------------- 00242 mcs::Socket::Socket(string host, unsigned short int port, 00243 unsigned int readTimeout, unsigned int writeTimeout, 00244 bool use_ssl) : HostInfo(host) 00245 { 00246 MCS_DEBUG_SETUP(0, "Socket"); 00247 00248 this->port = port; 00249 this->use_ssl = use_ssl; 00250 #ifdef HAVE_OPENSSL_SSL_H 00251 this->ssl_ctx = NULL; 00252 #endif //HAVE_OPENSSL_SSL_H 00253 00254 set_struct_timeval(readTimeout , &readto); 00255 set_struct_timeval(writeTimeout, &writeto); 00256 00257 sockfd = socketToHost(port); 00258 00259 #ifdef HAVE_OPENSSL_SSL_H 00260 if (use_ssl) { 00261 SSL_library_init(); 00262 ERR_load_crypto_strings(); 00263 SSL_load_error_strings(); 00264 00265 ssl_ctx = SSL_CTX_new(SSLv23_method()); 00266 00267 ssl=SSL_new(ssl_ctx); 00268 sbio=BIO_new_socket(sockfd, BIO_NOCLOSE); 00269 SSL_set_bio(ssl, sbio, sbio); 00270 00271 int ret = SSL_connect(ssl); 00272 if (ret <= 0) 00273 throw MCS_ERROR( MSG_SSL_CONNECT_ERROR ); 00274 00275 //ret = SSL_get_error(ssl, ret); 00276 //switch (ret) { 00277 //case SSL_ERROR_NONE: 00278 // break; 00279 //case SSL_ERROR_ZERO_RETURN: cout << "qui1" << endl; break; 00280 //case SSL_ERROR_WANT_READ: cout << "qui2" << endl; break; 00281 //case SSL_ERROR_WANT_WRITE: cout << "qui3" << endl; break; 00282 //case SSL_ERROR_WANT_CONNECT: cout << "qui4" << endl; break; 00283 //case SSL_ERROR_WANT_ACCEPT: cout << "qui5" << endl; break; 00284 //case SSL_ERROR_WANT_X509_LOOKUP:cout << "qui6" << endl; break; 00285 //case SSL_ERROR_SYSCALL: cout << "qui7" << endl; break; 00286 //case SSL_ERROR_SSL: cout << "qui8" << endl; break; 00287 //} 00288 //cout << ERR_error_string(ret, NULL) << endl; 00289 // 00290 //ERR_print_errors_fp(stderr); 00291 //throw MCS_ERROR( MSG_SSL_CONNECT_ERROR ); 00292 } 00293 #endif //HAVE_OPENSSL_SSL_H 00294 } 00295 00296 00297 mcs::Socket::Socket(int sockfd, 00298 unsigned int readTimeout, 00299 unsigned int writeTimeout, 00300 void* ssl_ctx) : HostInfo(sockfd) 00301 { 00302 MCS_DEBUG_SETUP(0, "Socket"); 00303 00304 this->port = 0; 00305 this->use_ssl = (ssl_ctx != NULL); 00306 #ifdef HAVE_OPENSSL_SSL_H 00307 this->ssl_ctx = NULL; 00308 #endif //HAVE_OPENSSL_SSL_H 00309 00310 set_struct_timeval(readTimeout , &readto); 00311 set_struct_timeval(writeTimeout, &writeto); 00312 00313 this->sockfd = sockfd; 00314 00315 00316 #ifdef HAVE_OPENSSL_SSL_H 00317 if (use_ssl) { 00318 SSL_CTX* ctx = (SSL_CTX*) ssl_ctx; 00319 00320 sbio=BIO_new_socket(sockfd, BIO_NOCLOSE); 00321 ssl=SSL_new(ctx); 00322 SSL_set_bio(ssl, sbio, sbio); 00323 00324 if(SSL_accept(ssl) <= 0) 00325 throw MCS_ERROR( MSG_SSL_ACCEPT_ERROR ); 00326 } 00327 #endif //HAVE_OPENSSL_SSL_H 00328 } 00329 00330 00331 00332 int mcs::Socket::socketToHost(unsigned short port) 00333 { 00334 int ret; 00335 //int sockfd; 00336 long socketflags; 00337 00338 sockfd = socket(PF_INET, SOCK_STREAM, 0); 00339 00340 sin.sin_port = htons(port); 00341 00342 // Set non-blocking 00343 socketflags = fcntl(sockfd, F_GETFL, NULL); 00344 fcntl(sockfd, F_SETFL, socketflags | O_NONBLOCK); 00345 00346 ret = connect(sockfd, (struct sockaddr *)&sin, sizeof(struct sockaddr)); 00347 00348 if (ret == -1) { 00349 if (errno == EINPROGRESS) 00350 chkSend(THROW); 00351 else 00352 throw MCS_FATAL(MSG_CANT_CONNECT_TO_HOST, strerror(errno)); 00353 } 00354 00355 // Set to blocking mode again... 00356 fcntl(sockfd, F_SETFL, socketflags); 00357 00358 return sockfd; 00359 } 00360 00361 00362 mcs::Socket::~Socket() 00363 { 00364 Socket::Close(); 00365 } 00366 00367 00368 void mcs::Socket::Close() 00369 { 00370 if (sockfd) { 00371 #ifdef HAVE_OPENSSL_SSL_H 00372 if (use_ssl) { 00373 SSL_shutdown(ssl); 00374 SSL_free(ssl); 00375 00376 if (ssl_ctx) 00377 SSL_CTX_free (ssl_ctx); 00378 } 00379 #endif //HAVE_OPENSSL_SSL_H 00380 00381 close(sockfd); 00382 sockfd = 0; 00383 } 00384 } 00385 00386 00387 bool mcs::Socket::chkSend(enum ThrowExceptions throwexc) 00388 { 00389 bool b = false; 00390 int ret; 00391 struct timeval timeout; 00392 timeout.tv_sec = writeto.tv_sec; 00393 timeout.tv_usec = writeto.tv_usec; 00394 00395 FD_ZERO(&fds); 00396 FD_SET(sockfd, &fds); 00397 00398 ret = select(sockfd+1, NULL, &fds, NULL, &timeout); 00399 if (ret == -1) //Error 00400 if (throwexc) 00401 throw MCS_FATAL(MSG_CALLING_SELECT, strerror(errno)); 00402 00403 else if (ret == 0) //Timeout 00404 if (throwexc) 00405 throw MCS_FATAL(MSG_TIME_OUT); 00406 00407 else { //Should be ok 00408 if (FD_ISSET(sockfd, &fds)) 00409 b = true; 00410 else //We didn't get an error nor a timeout, but the socket is not in the list??? 00411 throw MCS_FATAL(MSG_UNEXPECTED); 00412 } 00413 00414 return b; 00415 } 00416 00417 00418 bool mcs::Socket::chkRecv(bool chkDataAvailable, enum ThrowExceptions throwexc) 00419 { 00420 bool b = false; 00421 int ret; 00422 struct timeval timeout; 00423 00424 if (chkDataAvailable) { 00425 timeout.tv_sec = 0; 00426 timeout.tv_usec = 0; 00427 } 00428 else { 00429 timeout.tv_sec = readto.tv_sec; 00430 timeout.tv_usec = readto.tv_usec; 00431 } 00432 00433 FD_ZERO(&fds); 00434 FD_SET(sockfd, &fds); 00435 00436 #ifdef HAVE_OPENSSL_SSL_H 00437 if (use_ssl) { 00438 ret = SSL_pending(ssl); 00439 if (ret > 0) 00440 return true; 00441 } 00442 #endif //HAVE_OPENSSL_SSL_H 00443 00444 ret = select(sockfd+1, &fds, NULL, NULL, &timeout); 00445 if (ret == -1) { //Error 00446 if (throwexc) 00447 throw MCS_FATAL(MSG_CALLING_SELECT, strerror(errno)); 00448 } 00449 else if (ret == 0) { //Timeout 00450 if (throwexc) 00451 throw MCS_FATAL(MSG_TIME_OUT); 00452 } 00453 else { //Should be ok 00454 if (FD_ISSET(sockfd, &fds)) { 00455 char a; 00456 ret = recv(sockfd, &a, 1, MSG_PEEK); 00457 if (ret == -1) { //Error 00458 if (throwexc) 00459 throw MCS_FATAL(MSG_CALLING_RECV, strerror(errno)); 00460 } 00461 else if (ret == 0) { //Connection closed by peer 00462 if (throwexc) 00463 throw MCS_FATAL(MSG_CLOSED_BY_PEER); 00464 } 00465 else { 00466 b = true; 00467 } 00468 } 00469 else //We didn't get an error nor a timeout but the socket isn't in the list 00470 throw MCS_FATAL(MSG_UNEXPECTED); 00471 } 00472 00473 return b; 00474 } 00475 00476 00477 void mcs::Socket::sendChunk(void* p, unsigned int size) 00478 { 00479 string s; 00480 char buf[40]; 00481 unsigned int resp; 00482 00483 sprintf(buf, MCS_SOCKET_SENDING, size); 00484 print(buf); 00485 00486 s = getline(); 00487 if ((sscanf(s.c_str(), "%d", &resp) == 1) && (resp == size) ) { 00488 write(p, size); 00489 } 00490 else 00491 throw MCS_WARN(MSG_SEND_ABORT_BY_RECEIVER); 00492 } 00493 00494 00495 unsigned int mcs::Socket::recvChunk(void* p, unsigned int maxsize) 00496 { 00497 string s; 00498 char buf[60]; 00499 unsigned int chunksize; 00500 00501 s = getline(); 00502 if (s == MCS_SOCKET_STOP) 00503 return 0; 00504 00505 if (sscanf(s.c_str(), MCS_SOCKET_SENDING, &chunksize) != 1) 00506 throw MCS_FATAL(MSG_PROTOCOL, s.c_str()); 00507 00508 if (chunksize > maxsize) 00509 throw MCS_FATAL(MSG_NOT_ENOUGH_SPACE, chunksize, maxsize); 00510 00511 sprintf(buf, "%d", chunksize); 00512 print(buf); 00513 00514 read(p, chunksize); 00515 return chunksize; 00516 } 00517 00518 00519 unsigned int mcs::Socket::recvChunk(Buffer* abuf) 00520 { 00521 string s; 00522 char buf[60]; 00523 unsigned int chunksize; 00524 00525 s = getline(); 00526 if (s == MCS_SOCKET_STOP) 00527 return 0; 00528 00529 if (sscanf(s.c_str(), MCS_SOCKET_SENDING, &chunksize) != 1) 00530 throw MCS_FATAL(MSG_PROTOCOL, s.c_str()); 00531 00532 abuf->resize(chunksize); 00533 char* p = (*abuf)[0]; 00534 00535 sprintf(buf, "%d", chunksize); 00536 print(buf); 00537 00538 read(p, chunksize); 00539 return chunksize; 00540 } 00541 00542 00543 00544 00545 unsigned int mcs::Socket::read(void* buf, unsigned int count) 00546 { 00547 unsigned int ret, lcount; 00548 char* p = (char*) buf; 00549 chkRecv(); 00550 00551 lcount = 0; 00552 while (count>0) { 00553 00554 #ifdef HAVE_OPENSSL_SSL_H 00555 if (use_ssl) { 00556 ret = SSL_read(ssl, p ,count); 00557 switch(SSL_get_error(ssl, ret)) { 00558 case SSL_ERROR_NONE: 00559 break; 00560 //case SSL_ERROR_ZERO_RETURN: 00561 // goto shutdown; 00562 //case SSL_ERROR_SYSCALL: 00563 // fprintf(stderr, 00564 // "SSL Error: Premature close\n"); 00565 // goto done; 00566 default: 00567 throw MCS_FATAL(MSG_CLOSED_BY_PEER); 00568 //berr_exit("SSL read problem"); 00569 } 00570 } 00571 else 00572 #endif //HAVE_OPENSSL_SSL_H 00573 ret = recv(sockfd, (void*) p, count, 0); 00574 00575 if (ret == 0) 00576 throw MCS_FATAL(MSG_CLOSED_BY_PEER); 00577 00578 count -= ret; 00579 p += ret; 00580 lcount += ret; 00581 } 00582 00583 return lcount; 00584 } 00585 00586 00587 unsigned int mcs::Socket::write(void* buf, unsigned int count) 00588 { 00589 unsigned int ret; 00590 00591 chkSend(); 00592 00593 #ifdef HAVE_OPENSSL_SSL_H 00594 if (use_ssl) { 00595 ret = SSL_write(ssl, buf, count); 00596 switch(SSL_get_error(ssl, ret)) { 00597 case SSL_ERROR_NONE: 00598 break; 00599 default: 00600 throw MCS_FATAL(MSG_CALLING_SEND, "SSL write problem"); 00601 } 00602 } 00603 else 00604 #endif //HAVE_OPENSSL_SSL_H 00605 ret = send(sockfd, buf, count, 0); 00606 00607 if (ret != count) 00608 throw MCS_FATAL(MSG_CALLING_SEND, strerror(errno)); 00609 00610 return ret; 00611 } 00612 00613 00614 string mcs::Socket::getline() 00615 { 00616 char p = 0; 00617 string s = ""; 00618 00619 while (p != '\n') { 00620 read(&p, 1); 00621 s += p; 00622 } 00623 00624 remTrailing(s, "\n"); 00625 return s; 00626 } 00627 00628 00629 void mcs::Socket::print(string s) 00630 { 00631 s += "\n"; 00632 write((void*) s.c_str(), s.length()); 00633 } 00634 00635 00636 void mcs::Socket::sendData(Serializable* from) 00637 { 00638 void* p; 00639 char buf[40]; 00640 unsigned int chunksize; 00641 00642 MCS_DEBUG_ENTER(NOARGS); 00643 00644 if (from->knowSize()) 00645 sprintf(buf, MCS_SOCKET_START, from->size(), from->maxChunkSize()); 00646 else 00647 sprintf(buf, MCS_SOCKET_START, 0, from->maxChunkSize()); 00648 print(buf); 00649 00650 while ((p = from->nextChunk(chunksize))) { 00651 if (chunksize > 0) 00652 sendChunk(p, chunksize); 00653 } 00654 00655 sprintf(buf, MCS_SOCKET_STOP); 00656 print(buf); 00657 MCS_DEBUG_LEAVE(NOARGS); 00658 } 00659 00660 00661 unsigned int mcs::Socket::recvData(char** buffer, unsigned int maxsize) 00662 { 00663 unsigned int size, chunksize, accum, tmp; 00664 string s; 00665 00666 s = getline(); 00667 if (sscanf(s.c_str(), MCS_SOCKET_START, &size, &chunksize) != 2) 00668 throw MCS_FATAL(MSG_PROTOCOL, s.c_str()); 00669 00670 Buffer* abuf; 00671 if (*buffer) 00672 abuf = new Buffer(*buffer, maxsize); 00673 else 00674 abuf = new Buffer(DONT_FREE); 00675 00676 accum = 0; 00677 while ((tmp = recvChunk(abuf))) 00678 accum += tmp; 00679 00680 if (! (*buffer)) 00681 *buffer = (*abuf)[0]; 00682 00683 return accum; 00684 00685 // unsigned int size, chunksize, accum, tmp; 00686 // char* p; 00687 // string s; 00688 // 00689 // s = getline(); 00690 // if (sscanf(s.c_str(), MCS_SOCKET_START, &size, &chunksize) != 2) 00691 // throw MCS_FATAL(MSG_PROTOCOL, s.c_str()); 00692 // 00693 // if (! (*buffer)) { 00694 // if (size > 0) { 00695 // *buffer = (char*) malloc(size); 00696 // maxsize = size; 00697 // } 00698 // else { 00699 // *buffer = (char*) malloc(chunksize); 00700 // maxsize = chunksize; 00701 // } 00702 // } 00703 // else { 00704 // if (chunksize > maxsize) 00705 // throw MCS_FATAL(MSG_NOT_ENOUGH_SPACE, chunksize, maxsize); 00706 // } 00707 // 00708 // accum = 0; 00709 // p = *buffer; 00710 // while ((tmp = recvChunk(p, maxsize))) { 00711 // p += tmp; 00712 // accum += tmp; 00713 // if (accum > maxsize) 00714 // *buffer = (char*) realloc(*buffer, maxsize + chunksize); 00715 // } 00716 // 00717 // return accum; 00718 } 00719 00720 00721 00722 unsigned int mcs::Socket::recvData(string filename) 00723 { 00724 ofstream out(filename.c_str(), ios::binary); 00725 if (! out.is_open()) 00726 throw MCS_ERROR(MSG_CANT_OPEN_FILE, filename.c_str()); 00727 00728 return recvData(out); 00729 } 00730 00731 00732 unsigned int mcs::Socket::recvData(ofstream& out) 00733 { 00734 unsigned int size, chunksize, accum, tmp; 00735 char* p; 00736 string s; 00737 00738 s = getline(); 00739 if (sscanf(s.c_str(), MCS_SOCKET_START, &size, &chunksize) != 2) 00740 throw MCS_FATAL(MSG_PROTOCOL, s.c_str()); 00741 00742 p = (char*) malloc (chunksize); 00743 accum = 0; 00744 while ((tmp = recvChunk(p, chunksize))) { 00745 out.write(p, tmp); 00746 accum += tmp; 00747 } 00748 00749 free(p); 00750 00751 return accum; 00752 } 00753 00754 00755 00756 unsigned int mcs::Socket::recvData(int filedes) 00757 { 00758 unsigned int size, chunksize, accum, tmp; 00759 char* p; 00760 string s; 00761 00762 s = getline(); 00763 if (sscanf(s.c_str(), MCS_SOCKET_START, &size, &chunksize) != 2) 00764 throw MCS_FATAL(MSG_PROTOCOL, s.c_str()); 00765 00766 p = (char*) malloc (chunksize); 00767 accum = 0; 00768 while ((tmp = recvChunk(p, chunksize))) { 00769 ::write(filedes, p, tmp); 00770 accum += tmp; 00771 } 00772 00773 free(p); 00774 00775 return accum; 00776 } 00777 00778 00779 00780 00781 void mcs::Socket::set_struct_timeval(unsigned int millisec, struct timeval* time) 00782 { 00783 float fsec = ((float) millisec) / 1000.0; 00784 int isec = (int) rintf(fsec); 00785 time->tv_sec = isec; 00786 time->tv_usec = 0; 00787 } 00788 00789 00790 00791 00792 00793 00794 00795 00796 00797 //-------------------------------------------------------- 00798 mcs::ServerSocket::ServerSocket(string interface, unsigned short int port, 00799 bool use_ssl, string sslcert, string sslpriv) : 00800 NetInterface(interface) 00801 { 00802 int ret; 00803 struct sockaddr_in sin; 00804 00805 this->use_ssl = use_ssl; 00806 00807 sockfd = socket(PF_INET, SOCK_STREAM, 0); 00808 str_sockaddr_in(&sin); 00809 sin.sin_port = htons(port); 00810 00811 ret = 1; 00812 ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &ret, sizeof(int)); 00813 ret = bind(sockfd, (struct sockaddr *)&sin, sizeof(struct sockaddr)); 00814 00815 if (ret == -1) 00816 throw MCS_FATAL(MSG_CALLING_BIND, strerror(errno)); 00817 00818 ret = listen(sockfd, 10); 00819 if (ret == -1) 00820 throw MCS_FATAL(MSG_CALLING_LISTEN, strerror(errno)); 00821 00822 00823 //Eventually initialize the SSL library and a SSL context object 00824 #ifdef HAVE_OPENSSL_SSL_H 00825 ssl_ctx = NULL; 00826 00827 if (use_ssl) { 00828 SSL_library_init(); 00829 SSL_load_error_strings(); 00830 ERR_load_crypto_strings(); 00831 00832 ssl_ctx=SSL_CTX_new(SSLv23_server_method()); 00833 00834 00835 if (! SSL_CTX_use_certificate_file(ssl_ctx, sslcert.c_str(), 00836 SSL_FILETYPE_PEM)) 00837 throw MCS_FATAL ( MSG_UNEXPECTED ); 00838 00839 if (! SSL_CTX_use_PrivateKey_file(ssl_ctx, sslpriv.c_str(), 00840 SSL_FILETYPE_PEM)) 00841 throw MCS_FATAL ( MSG_UNEXPECTED ); 00842 00843 if (! SSL_CTX_check_private_key(ssl_ctx)) 00844 throw MCS_FATAL ( MSG_UNEXPECTED ); 00845 } 00846 #endif //HAVE_OPENSSL_SSL_H 00847 } 00848 00849 00850 mcs::ServerSocket::~ServerSocket() 00851 { 00852 close(sockfd); 00853 00854 #ifdef HAVE_OPENSSL_SSL_H 00855 if (use_ssl) 00856 if (ssl_ctx) 00857 SSL_CTX_free (ssl_ctx); 00858 #endif //HAVE_OPENSSL_SSL_H 00859 } 00860 00861 00862 00863 void* mcs::ServerSocket::getSSLContext() 00864 { 00865 #ifdef HAVE_OPENSSL_SSL_H 00866 if (use_ssl) 00867 return ssl_ctx; 00868 else 00869 return NULL; 00870 #else 00871 return NULL; 00872 #endif //HAVE_OPENSSL_SSL_H 00873 } 00874 00875 00876 00877 bool mcs::ServerSocket::acceptConnection(int& newsock, unsigned int millisec) 00878 { 00879 struct sockaddr_in sin; 00880 socklen_t sin_size = sizeof(struct sockaddr_in); 00881 00882 fd_set fds; 00883 FD_ZERO(&fds); 00884 FD_SET(sockfd, &fds); 00885 00886 struct timeval timeout; 00887 Socket::set_struct_timeval(millisec, &timeout); 00888 00889 int ret = select(FD_SETSIZE, &fds, NULL, NULL, &timeout); 00890 if (ret == -1) { //Error 00891 throw MCS_FATAL(MSG_CALLING_SELECT, strerror(errno)); 00892 } 00893 else if (ret == 0) { //Timeout 00894 return false; 00895 } 00896 else { //Should be ok 00897 if (FD_ISSET(sockfd, &fds)) 00898 newsock = accept(sockfd, (struct sockaddr *)&sin, &sin_size); 00899 else //We didn't get an error nor a timeout but the socket isn't in the list 00900 throw MCS_FATAL(MSG_UNEXPECTED); 00901 } 00902 00903 return true; 00904 }
![]() |
MCS (My Customizable Server) ver. 0.3.3-alpha3
|