00001 #include "common.h"
00002
00003 #ifdef _WINDOWS
00004 #include <Winsock2.h>
00005 #endif
00006
00007 #include "log.h"
00008 #include "util.h"
00009
00010 #include "hashtable.h"
00011 #include "vector.h"
00012 #include "thread.h"
00013
00014 #include "socket.h"
00015
00016 #include <stdio.h>
00017 #include <string.h>
00018 #include <stdlib.h>
00019 #include <signal.h>
00020 #include <fcntl.h>
00021 #include <errno.h>
00022
00023 #if defined(unix) || defined(__unix__) || defined(__MACH__)
00024 #include <unistd.h>
00025 #include <sys/time.h>
00026 #include <sys/socket.h>
00027 #include <netinet/in.h>
00028 #include <arpa/inet.h>
00029 #endif
00030
00041 #ifdef CP_USE_SSL
00042 #include <openssl/ssl.h>
00043 #include <openssl/err.h>
00044
00045 #ifdef _WINDOWS
00046 #include <wincrypt.h>
00047 #endif
00048
00049 static cp_hashtable *ssl_ctx_table = NULL;
00050
00051 volatile int ssl_initialized = 0;
00052
00053 void cp_socket_ssl_init()
00054 {
00055 if (ssl_initialized) return;
00056 ssl_initialized = 1;
00057
00058 SSL_library_init();
00059 SSL_load_error_strings();
00060 OpenSSL_add_all_algorithms();
00061
00062 ssl_ctx_table = cp_hashtable_create(1, cp_hash_string, cp_hash_compare_string);
00063 }
00064
00065 void cp_socket_ssl_shutdown()
00066 {
00067 if (ssl_initialized)
00068 {
00069 ssl_initialized = 0;
00070 if (ssl_ctx_table)
00071 cp_hashtable_destroy_custom(ssl_ctx_table, free,
00072 (cp_destructor_fn) SSL_CTX_free);
00073 ssl_ctx_table = NULL;
00074
00075 EVP_cleanup();
00076 ERR_free_strings();
00077 }
00078 }
00079
00080 SSL_CTX *get_ssl_ctx(char *certificate_file, char *key_file)
00081 {
00082 int len;
00083 char *ck;
00084 SSL_CTX *ctx;
00085 if (ssl_ctx_table == NULL) cp_socket_ssl_init();
00086
00087 len = strlen(certificate_file) + strlen(key_file) + 2;
00088 ck = malloc(len * sizeof(char));
00089 #ifdef CP_HAS_SNPRINTF
00090 snprintf(ck, len, "%s*%s", certificate_file, key_file);
00091 #else
00092 sprintf(ck, "%s*%s", certificate_file, key_file);
00093 #endif
00094
00095 ctx = cp_hashtable_get(ssl_ctx_table, ck);
00096 if (ctx == NULL)
00097 {
00098 int rc = 0;
00099 SSL_METHOD *method = SSLv23_server_method();
00100 ctx = SSL_CTX_new(method);
00101 if (ctx == NULL)
00102 {
00103 rc = ERR_get_error();
00104 cp_error(CP_SSL_CTX_INITIALIZATION_ERROR,
00105 "can\'t create SSL context: %s",
00106 ERR_reason_error_string(rc));
00107 goto CTX_ERROR;
00108 }
00109
00110 if (SSL_CTX_use_certificate_file(ctx, certificate_file,
00111 SSL_FILETYPE_PEM) != 1)
00112 {
00113 rc = ERR_get_error();
00114 cp_error(CP_SSL_CTX_INITIALIZATION_ERROR,
00115 "certificate file: %s", ERR_reason_error_string(rc));
00116 goto CTX_ERROR;
00117 }
00118
00119 if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) != 1)
00120 {
00121 rc = ERR_get_error();
00122 cp_error(CP_SSL_CTX_INITIALIZATION_ERROR,
00123 "private key file: %s\n", ERR_reason_error_string(rc));
00124 goto CTX_ERROR;
00125 }
00126
00127 if (!(SSL_CTX_check_private_key(ctx)))
00128 {
00129 rc = ERR_get_error();
00130 cp_error(CP_SSL_CTX_INITIALIZATION_ERROR,
00131 "checking private key: %s", ERR_reason_error_string(rc));
00132 goto CTX_ERROR;
00133 }
00134
00135 cp_hashtable_put(ssl_ctx_table, ck, ctx);
00136 }
00137
00138 return ctx;
00139
00140 CTX_ERROR:
00141 if (ctx)
00142 SSL_CTX_free(ctx);
00143
00144 return NULL;
00145 }
00146
00147 SSL_CTX *get_client_ssl_ctx(char *CA_file, char *CA_path)
00148 {
00149 SSL_CTX *ctx;
00150 cp_string *ckwrap = cp_string_create_empty(80);
00151 char *ck;
00152
00153 if (ssl_ctx_table == NULL) cp_socket_ssl_init();
00154
00155 if (CA_file) cp_string_cstrcat(ckwrap, CA_file);
00156 cp_string_cstrcat(ckwrap, "*");
00157 if (CA_path) cp_string_cstrcat(ckwrap, CA_path);
00158 ck = cp_string_tocstr(ckwrap);
00159 free(ckwrap);
00160
00161 ctx = cp_hashtable_get(ssl_ctx_table, ck);
00162 if (ctx == NULL)
00163 {
00164 int rc;
00165 SSL_METHOD *method = SSLv23_client_method();
00166 ctx = SSL_CTX_new(method);
00167
00168 rc = SSL_CTX_load_verify_locations(ctx, CA_file, CA_path);
00169 if (rc == 0)
00170 {
00171 rc = ERR_get_error();
00172 cp_error(CP_SSL_CTX_INITIALIZATION_ERROR,
00173 "loading CA certificate: %s", ERR_reason_error_string(rc));
00174 SSL_CTX_free(ctx);
00175 return NULL;
00176 }
00177
00178 cp_hashtable_put(ssl_ctx_table, ck, ctx);
00179 }
00180 else
00181 free(ck);
00182
00183 return ctx;
00184 }
00185
00186 #endif
00187
00188 static volatile int socket_reg_id = 0;
00189 static cp_hashlist *socket_registry;
00190 static cp_vector *shutdown_hook = NULL;
00191 static volatile int initialized = 0;
00192 static volatile int shutting = 0;
00193
00194 #if defined(unix) || defined(__unix__) || defined(__MACH__)
00195 void cp_socket_signal_handler(int sig);
00196 #endif
00197
00198 void cp_socket_init()
00199 {
00200 #if defined(unix) || defined(__unix__) || defined(__MACH__)
00201 struct sigaction act;
00202 #endif
00203
00204 #ifdef _WINDOWS
00205 WSADATA wsaData;
00206 WORD version;
00207 int error;
00208 #endif
00209
00210 if (initialized) return;
00211 initialized = 1;
00212
00213 #ifdef _WINDOWS
00214 version = MAKEWORD( 2, 0 );
00215 error = WSAStartup( version, &wsaData );
00216
00217
00218 if ( error != 0 )
00219 {
00220
00221 initialized = 0;
00222 return;
00223 }
00224
00225
00226 if ( LOBYTE( wsaData.wVersion ) != 2 ||
00227 HIBYTE( wsaData.wVersion ) != 0 )
00228 {
00229
00230 initialized = 0;
00231 WSACleanup();
00232 return;
00233 }
00234 #endif
00235
00236 socket_registry =
00237 cp_hashlist_create_by_mode(1, COLLECTION_MODE_DEEP,
00238 cp_hash_int, cp_hash_compare_int);
00239 #if defined(unix) || defined(__unix__) || defined(__MACH__)
00240 act.sa_handler = cp_socket_signal_handler;
00241 sigemptyset(&act.sa_mask);
00242 act.sa_flags = 0;
00243 sigaction(SIGPIPE, &act, NULL);
00244 #endif
00245 }
00246
00247 void cp_socket_stop(cp_socket *sock)
00248 {
00249 #ifdef __TRACE__
00250 DEBUGMSG("stopping socket %lX", sock);
00251 #endif
00252 sock->closing = 1;
00253
00254 shutdown(sock->fd, SHUT_RD);
00255 }
00256
00257 void cp_tcp_add_shutdown_callback(void (*cb)(void *), void *prm)
00258 {
00259 cp_wrap *wrap;
00260
00261 if (shutdown_hook == NULL)
00262 shutdown_hook = cp_vector_create(1);
00263
00264 wrap = cp_wrap_new(prm, cb);
00265
00266 cp_vector_add_element(shutdown_hook, wrap);
00267 }
00268
00269 volatile int stopping_all = 0;
00270
00271 void cp_socket_stop_all()
00272 {
00273 if (stopping_all) return;
00274 stopping_all = 1;
00275
00276 if (socket_registry)
00277 {
00278 cp_socket *sock;
00279 cp_hashlist_iterator i;
00280 cp_hashlist_iterator_init(&i, socket_registry, COLLECTION_LOCK_READ);
00281 while ((sock = cp_hashlist_iterator_next_value(&i)))
00282 cp_socket_stop(sock);
00283 cp_hashlist_iterator_release(&i);
00284 }
00285 }
00286
00287 void cp_socket_shutdown()
00288 {
00289 if (shutting) return;
00290
00291 shutting = 1;
00292
00293 #ifdef __TRACE__
00294 DEBUGMSG("shutting down socket layer");
00295 #endif
00296
00297 if (shutdown_hook)
00298 {
00299 cp_vector_destroy_custom(shutdown_hook,
00300 (cp_destructor_fn) cp_wrap_delete);
00301 shutdown_hook = NULL;
00302 }
00303
00304 cp_socket_stop_all();
00305 if (socket_registry)
00306 {
00307 cp_hashlist_destroy(socket_registry);
00308 socket_registry = NULL;
00309 }
00310
00311 #ifdef CP_USE_SSL
00312 cp_socket_ssl_shutdown();
00313 #endif
00314
00315 #ifdef _WINDOWS
00316 WSACleanup();
00317 #endif
00318 }
00319
00320 #if defined(unix) || defined(__unix__) || defined(__MACH__)
00321 void cp_socket_signal_handler(int sig)
00322 {
00323 switch (sig)
00324 {
00325 case SIGPIPE:
00326 #ifdef __TRACE__
00327 DEBUGMSG("SIGPIPE - ignoring\n");
00328 #endif
00329 break;
00330 }
00331 }
00332 #endif
00333
00334 #if defined(unix) || defined(__unix__) || defined(__MACH__)
00335 int setnonblocking(int sock)
00336 {
00337 int opts;
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 opts = fcntl(sock, F_GETFL);
00367 if (opts < 0)
00368 {
00369 perror("fcntl(F_GETFL)");
00370 return -1;
00371 }
00372
00373 opts |= O_NONBLOCK;
00374
00375 if (fcntl(sock, F_SETFL, opts) < 0)
00376 {
00377 perror("fcntl(F_SETFL)");
00378 return -1;
00379 }
00380
00381 return opts;
00382 }
00383 #else
00384 int setnonblocking(int sock)
00385 {
00386 DWORD ul=1;
00387 return ioctlsocket(sock, FIONBIO, &ul);
00388 }
00389 #endif
00390
00391 cp_connection_descriptor *cp_connection_descriptor_create(cp_socket *sock,
00392 struct sockaddr_in *addr,
00393 int fd)
00394 {
00395 cp_connection_descriptor *conn_desc =
00396 (cp_connection_descriptor *) calloc(1, sizeof(cp_connection_descriptor));
00397
00398 if (conn_desc == NULL)
00399 {
00400 cp_error(CP_MEMORY_ALLOCATION_FAILURE,
00401 "can\'t allocate cp_connection_descriptor (%d bytes)",
00402 sizeof(cp_connection_descriptor));
00403 return NULL;
00404 }
00405
00406 conn_desc->sock = sock;
00407 conn_desc->addr = addr;
00408 conn_desc->fd = fd;
00409
00410 return conn_desc;
00411 }
00412
00413 #ifdef CP_USE_SSL
00414 cp_connection_descriptor *cp_connection_descriptor_create_ssl(cp_socket *sock,
00415 struct sockaddr_in *addr,
00416 int fd,
00417 SSL *ssl)
00418 {
00419 cp_connection_descriptor *conn_desc =
00420 cp_connection_descriptor_create(sock, addr, fd);
00421
00422 if (conn_desc) conn_desc->ssl = ssl;
00423
00424 return conn_desc;
00425 }
00426 #endif
00427
00428 void cp_connection_descriptor_destroy(cp_connection_descriptor *conn_desc)
00429 {
00430 if (conn_desc)
00431 {
00432 #ifdef CP_USE_SSL
00433 if (conn_desc->ssl)
00434 cp_socket_ssl_connection_close(conn_desc->sock, conn_desc->ssl);
00435 else
00436 #endif
00437 cp_socket_connection_close(conn_desc->sock, conn_desc->fd);
00438 free(conn_desc);
00439 }
00440 }
00441
00442
00443 cp_socket *cp_socket_create(int port, cp_socket_strategy strategy, void *fn)
00444 {
00445 cp_socket *sock;
00446
00447 cp_socket_init();
00448
00449 sock = calloc(1, sizeof(cp_socket));
00450 if (sock == NULL)
00451 {
00452 cp_error(CP_MEMORY_ALLOCATION_FAILURE, "can\'t allocate cp_socket (%d bytes)", sizeof(cp_socket));
00453 return NULL;
00454 }
00455
00456 sock->port = port;
00457 sock->backlog = CPSOCKET_DEFAULT_BACKLOG;
00458 sock->delay.tv_sec = CPSOCKET_DEFAULT_DELAY_SEC;
00459 sock->delay.tv_usec = CPSOCKET_DEFAULT_DELAY_USEC;
00460 sock->strategy = strategy;
00461 sock->fds =
00462 cp_hashlist_create_by_option(COLLECTION_MODE_DEEP, 10, cp_hash_int,
00463 cp_hash_compare_int, NULL, free, NULL, free);
00464 if (sock->fds == NULL)
00465 {
00466 cp_error(CP_MEMORY_ALLOCATION_FAILURE,
00467 "can\'t allocate cp_socket fd list");
00468 free(sock);
00469 return NULL;
00470 }
00471
00472 switch (strategy)
00473 {
00474 case CPSOCKET_STRATEGY_CALLBACK:
00475 sock->action.callback = (cp_socket_callback) fn;
00476
00477 break;
00478
00479 case CPSOCKET_STRATEGY_THREADPOOL:
00480 sock->poolsize_min = CPSOCKET_THREADPOOL_DEFAULT_SIZE_MIN;
00481 sock->poolsize_max = CPSOCKET_THREADPOOL_DEFAULT_SIZE_MAX;
00482 sock->action.thread_fn = (cp_socket_thread_function) fn;
00483 break;
00484 }
00485
00486 sock->id = socket_reg_id++;
00487 cp_hashlist_append(socket_registry, &sock->id, sock);
00488
00489 return sock;
00490 }
00491
00492 #ifdef CP_USE_SSL
00493 cp_socket *cp_socket_create_ssl(int port,
00494 cp_socket_strategy strategy,
00495 void *fn,
00496 char *certificate_file,
00497 char *key_file,
00498 int verification_mode)
00499 {
00500 cp_socket *socket = cp_socket_create(port, strategy, fn);
00501 if (socket)
00502 {
00503 socket->ctx = get_ssl_ctx(certificate_file, key_file);
00504 if (socket->ctx == NULL)
00505 {
00506 cp_socket_delete(socket);
00507 return NULL;
00508 }
00509
00510 socket->use_ssl = 1;
00511 SSL_CTX_set_verify(socket->ctx, verification_mode, NULL);
00512 }
00513 return socket;
00514 }
00515 #endif
00516
00517 void cp_socket_set_backlog(cp_socket *socket, int backlog)
00518 {
00519 socket->backlog = backlog;
00520 }
00521
00522 void cp_socket_set_delay(cp_socket *socket, struct timeval delay)
00523 {
00524 socket->delay = delay;
00525 }
00526
00527 void cp_socket_set_delay_sec(cp_socket *socket, long sec)
00528 {
00529 socket->delay.tv_sec = sec;
00530 }
00531
00532 void cp_socket_set_delay_usec(cp_socket *socket, long usec)
00533 {
00534 socket->delay.tv_usec = usec;
00535 }
00536
00537 void cp_socket_set_poolsize_min(cp_socket *socket, int min)
00538 {
00539 socket->poolsize_min = min;
00540 }
00541
00542 void cp_socket_set_poolsize_max(cp_socket *socket, int max)
00543 {
00544 socket->poolsize_max = max;
00545 }
00546
00547 void cp_socket_set_owner(cp_socket *socket, void *owner)
00548 {
00549 socket->owner = owner;
00550 }
00551
00552 void *cp_socket_add_shutdown_callback(cp_socket *sock,
00553 void (*cb)(void *),
00554 void *prm)
00555 {
00556 cp_wrap *wrap = cp_wrap_new(prm, (cp_destructor_fn) cb);
00557
00558 if (sock->shutdown_callback == NULL)
00559 sock->shutdown_callback = cp_vector_create(1);
00560
00561 return cp_vector_add_element(sock->shutdown_callback, wrap);
00562 }
00563
00564 void cp_socket_delete(cp_socket *sock)
00565 {
00566 if (sock)
00567 {
00568 sock->closing = 1;
00569 switch(sock->strategy)
00570 {
00571 case CPSOCKET_STRATEGY_THREADPOOL:
00572 cp_thread_pool_stop(sock->tpool);
00573 cp_thread_pool_destroy(sock->tpool);
00574 break;
00575
00576 case CPSOCKET_STRATEGY_CALLBACK:
00577 {
00578 cp_hashlist_iterator *itr;
00579 cp_hashlist_entry *entry;
00580 int *pfd;
00581
00582 itr = cp_hashlist_create_iterator(sock->fds, COLLECTION_LOCK_NONE);
00583
00584 while ((entry = cp_hashlist_iterator_next(itr)))
00585 {
00586 pfd = (int *) cp_hashlist_entry_get_key(entry);
00587 cp_socket_connection_close(sock, *pfd);
00588 }
00589
00590 cp_hashlist_iterator_destroy(itr);
00591 }
00592 break;
00593 }
00594
00595
00596
00597
00598
00599
00600 if (sock->shutdown_callback)
00601 cp_vector_destroy_custom(sock->shutdown_callback,
00602 (cp_destructor_fn) cp_wrap_delete);
00603
00604 if (socket_registry)
00605 cp_hashlist_remove(socket_registry, &sock->id);
00606 cp_hashlist_destroy_custom(sock->fds, free, free);
00607 free(sock);
00608 }
00609 }
00610
00616 int cp_socket_listen(cp_socket *sock)
00617 {
00618 struct sockaddr_in insock;
00619 char *errmsg;
00620 int yes = 1;
00621 int fd;
00622 int rc = -1;
00623
00624 if (sock->strategy == CPSOCKET_STRATEGY_THREADPOOL)
00625 {
00626 sock->tpool = cp_thread_pool_create(sock->poolsize_min,
00627 sock->poolsize_max);
00628
00629 if (sock->tpool == NULL)
00630 {
00631 errmsg = "can\'t create cp_thread pool";
00632 goto LISTEN_ERROR;
00633 }
00634 }
00635
00636 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
00637 {
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 rc = errno;
00652 errmsg = "socket";
00653 goto LISTEN_ERROR;
00654 }
00655
00656
00657 #ifdef TRACE
00658 DEBUGMSG("got socket: fd %d\n", fd);
00659 #endif
00660 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
00661 (char *) &yes, sizeof(int)) < 0)
00662 {
00663 errmsg = "setsockopt";
00664 goto LISTEN_ERROR;
00665 }
00666
00667 sock->fd = fd;
00668
00669 memset(&insock, 0, sizeof(struct sockaddr_in));
00670 insock.sin_port = htons((unsigned short) sock->port);
00671 insock.sin_family = AF_INET;
00672
00673 if (bind(sock->fd, (struct sockaddr *) &insock,
00674 sizeof(struct sockaddr_in)) < 0)
00675 {
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692 rc = errno;
00693 errmsg = "cp_socket_listen: bind";
00694 goto LISTEN_ERROR;
00695 }
00696
00697 if (listen(sock->fd, sock->backlog) < 0)
00698 {
00699
00700
00701
00702
00703
00704
00705
00706 rc = errno;
00707 errmsg = "listen";
00708 goto LISTEN_ERROR;
00709 }
00710 gettimeofday(&sock->created, NULL);
00711 sock->connections_served = 0;
00712 #ifdef DEBUG
00713 DEBUGMSG("listening on port %d (fd %d)\n", sock->port, sock->fd);
00714 #endif
00715
00716 return 0;
00717
00718 LISTEN_ERROR:
00719 cp_perror(CP_IO_ERROR, rc, "cp_socket_listen: failed on %s", errmsg);
00720 return rc;
00721 }
00722
00723
00724 int cp_socket_select_callback_impl(cp_socket *sock)
00725 {
00726 fd_set fds;
00727 unsigned int *pfd;
00728 cp_hashlist_iterator *itr;
00729 cp_hashlist_entry *entry;
00730 int rc = -1;
00731 #ifdef CP_USE_SSL
00732 cp_hashtable *ssl_entry = NULL;
00733
00734 if (sock->use_ssl)
00735 ssl_entry = cp_hashtable_create(10, cp_hash_int, cp_hash_compare_int);
00736 #endif
00737
00738 itr = cp_hashlist_create_iterator(sock->fds, COLLECTION_LOCK_NONE);
00739
00740 while (!sock->closing)
00741 {
00742 FD_ZERO(&fds);
00743
00744 sock->fdn = sock->fd;
00745
00746 FD_SET(sock->fd, &fds);
00747
00748 cp_hashlist_iterator_head(itr);
00749 while ((entry = cp_hashlist_iterator_next(itr)))
00750 {
00751 pfd = (unsigned int *) cp_hashlist_entry_get_key(entry);
00752 FD_SET(*pfd, &fds);
00753 if (sock->fdn < *pfd) sock->fdn = *pfd;
00754 }
00755
00756 if ((rc = select(sock->fdn + 1, &fds, NULL, NULL, &sock->delay)) < 0)
00757 {
00758 cp_perror(CP_IO_ERROR, errno,
00759 "cp_socket_select_callback_impl: select failed");
00760
00761 sock->closing = 1;
00762 break;
00763 }
00764
00765 if (rc == 0) continue;
00766
00767 if (FD_ISSET(sock->fd, &fds))
00768 {
00769 int newconn;
00770 unsigned int l;
00771 struct sockaddr_in *insock = calloc(1, sizeof(struct sockaddr_in));
00772
00773 newconn = accept(sock->fd, (struct sockaddr *) insock, &l);
00774 if (newconn < 0)
00775 {
00776 cp_perror(CP_IO_ERROR, errno,
00777 "cp_socket_select_callback_impl: accept failed");
00778 free(insock);
00779 if (newconn == EBADF ||
00780 #ifdef ENOTSOCK
00781 newconn == ENOTSOCK ||
00782 #endif
00783 #ifdef EOPNOTSUPP
00784 newconn == EOPNOTSUPP ||
00785 #endif
00786 newconn == EINVAL ||
00787 newconn == EFAULT || newconn == EPERM)
00788 break;
00789
00790
00791
00792
00793
00794 continue;
00795 }
00796
00797 #ifdef CP_USE_SSL
00798 if (sock->use_ssl)
00799 {
00800 SSL *ssl = SSL_new(sock->ctx);
00801 SSL_set_fd(ssl, newconn);
00802 rc = SSL_accept(ssl);
00803 if (rc <= 0)
00804 {
00805 int err = SSL_get_error(ssl, rc);
00806 cp_error(CP_SSL_HANDSHAKE_FAILED, "cp_socket_select_callback_impl: %s", ERR_reason_error_string(err));
00807 SSL_free(ssl);
00808 free(insock);
00809 continue;
00810 }
00811 cp_hashtable_put(ssl_entry, &newconn, ssl);
00812 }
00813 #endif
00814
00815 cp_hashlist_append(sock->fds, &newconn, insock);
00816 }
00817
00818 cp_hashlist_iterator_head(itr);
00819 while ((entry = cp_hashlist_iterator_next(itr)))
00820 {
00821 pfd = (unsigned int *) cp_hashlist_entry_get_key(entry);
00822 if (FD_ISSET(*pfd, &fds))
00823 {
00824 #ifdef CP_USE_SSL
00825 if (sock->use_ssl)
00826 {
00827 SSL *ssl = cp_hashtable_get(ssl_entry, pfd);
00828 (*sock->action.ssl_callback)(sock, ssl);
00829 }
00830 else
00831 #endif
00832 (*sock->action.callback)(sock, *pfd);
00833 }
00834 }
00835 }
00836
00837 cp_hashlist_iterator_destroy(itr);
00838
00839 #ifdef CP_USE_SSL
00840 if (sock->use_ssl)
00841 cp_hashtable_destroy_custom(ssl_entry, NULL,
00842 (cp_destructor_fn)SSL_free);
00843 #endif
00844
00845 return 0;
00846 }
00847
00848 int cp_socket_select_threadpool_impl(cp_socket *sock)
00849 {
00850 fd_set fds;
00851 int rc;
00852 struct timeval delay;
00853
00854 while (!sock->closing)
00855 {
00856 FD_ZERO(&fds);
00857
00858 sock->fdn = sock->fd;
00859
00860 FD_SET(sock->fd, &fds);
00861
00862 delay = sock->delay;
00863
00864 rc = select(sock->fdn + 1, &fds, NULL, NULL, &delay);
00865 if (rc < 0)
00866 {
00867
00868
00869
00870
00871
00872
00873
00874 rc = errno;
00875
00876 if (rc == EINTR || rc == EAGAIN)
00877 {
00878 if (stopping_all)
00879 {
00880 sock->closing = 1;
00881 break;
00882 }
00883 else
00884 continue;
00885 }
00886
00887 cp_perror(CP_IO_ERROR, rc,
00888 "cp_socket_select_threadpool_impl: select failed");
00889 sock->closing = 1;
00890 break;
00891 }
00892
00893 if (rc == 0) continue;
00894
00895 if (FD_ISSET(sock->fd, &fds))
00896 {
00897 int *newconn = malloc(sizeof(int));
00898 cp_connection_descriptor *conn_desc;
00899 unsigned int l;
00900 struct sockaddr_in *insock = calloc(1, sizeof(struct sockaddr_in));
00901 l = sizeof(struct sockaddr_in);
00902
00903 *newconn = accept(sock->fd, (struct sockaddr *) insock, &l);
00904 if (*newconn < 0)
00905 {
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928 rc = errno;
00929 if (!(sock->closing
00930 #ifdef ECONNABORTED
00931 && rc == ECONNABORTED
00932 #endif
00933 ))
00934 cp_perror(CP_IO_ERROR, rc,
00935 "cp_socket_select_threadpool_impl: accept failed");
00936 free(insock);
00937 free(newconn);
00938 if (rc == EBADF ||
00939 #ifdef ENOTSOCK
00940 rc == ENOTSOCK ||
00941 #endif
00942 #ifdef EOPNOTSUPP
00943 rc == EOPNOTSUPP ||
00944 #endif
00945 rc == EINVAL || rc == EFAULT || rc == EPERM)
00946 break;
00947
00948
00949
00950
00951 continue;
00952 }
00953
00954 sock->connections_served++;
00955 #ifdef __TRACE__
00956 DEBUGMSG("adding connection on fd %d (%lX)", *newconn, (long) insock);
00957 DEBUGMSG("connection from %s", inet_ntoa(insock->sin_addr));
00958 #endif
00959
00960 #ifdef CP_USE_SSL
00961 if (sock->use_ssl)
00962 {
00963 SSL *ssl = SSL_new(sock->ctx);
00964 SSL_set_fd(ssl, *newconn);
00965 rc = SSL_accept(ssl);
00966 if (rc <= 0)
00967 {
00968 int err = SSL_get_error(ssl, rc);
00969 cp_error(CP_SSL_HANDSHAKE_FAILED, "cp_socket_select_callback_impl: %s", ERR_reason_error_string(err));
00970 SSL_free(ssl);
00971 free(insock);
00972 continue;
00973 }
00974
00975 conn_desc = cp_connection_descriptor_create_ssl(sock, insock,
00976 *newconn, ssl);
00977 }
00978 else
00979 #endif
00980 conn_desc = cp_connection_descriptor_create(sock, insock, *newconn);
00981 gettimeofday(&conn_desc->created, NULL);
00982 cp_hashlist_append(sock->fds, newconn, insock);
00983 #ifdef __TRACE__
00984 cp_info("added: %lX (table: %lX)", (long) cp_hashlist_get(sock->fds, newconn), (long) sock->fds);
00985 #endif
00986 cp_thread_pool_get(sock->tpool, sock->action.thread_fn, conn_desc);
00987
00988 #ifdef __TRACE__
00989 cp_info("dispatched; addr: %lX (table: %lX)", (long) cp_hashlist_get(sock->fds, newconn), (long) sock->fds);
00990 #endif
00991 }
00992 }
00993
00994 return 0;
00995 }
00996
00997 int cp_socket_select(cp_socket *sock)
00998 {
00999 int rc = 0;
01000
01001 switch (sock->strategy)
01002 {
01003 case CPSOCKET_STRATEGY_CALLBACK:
01004 rc = cp_socket_select_callback_impl(sock);
01005 break;
01006
01007 case CPSOCKET_STRATEGY_THREADPOOL:
01008 rc = cp_socket_select_threadpool_impl(sock);
01009 break;
01010 }
01011
01012 return rc;
01013 }
01014
01015 #ifdef CP_USE_SSL
01016 int cp_socket_ssl_connection_close(cp_socket *sock, SSL *ssl)
01017 {
01018 int rc = 0;
01019 int fd;
01020 struct sockaddr_in *insock;
01021
01022 fd = SSL_get_fd(ssl);
01023 setnonblocking(fd);
01024 insock = (struct sockaddr_in *) cp_hashlist_get(sock->fds, &fd);
01025 if (insock)
01026 {
01027 rc = SSL_shutdown(ssl);
01028 if (rc == 0)
01029 rc = SSL_shutdown(ssl);
01030
01031 if (shutdown(fd, SHUT_WR) < 0)
01032 {
01033
01034
01035
01036
01037
01038 cp_perror(CP_IO_ERROR, errno,
01039 "shutdown error on connection from %s",
01040 inet_ntoa(insock->sin_addr));
01041 }
01042
01043 SSL_free(ssl);
01044 if (close(fd) < 0)
01045 {
01046
01047
01048
01049
01050
01051 struct sockaddr_in *insock;
01052 rc = errno;
01053 insock = (struct sockaddr_in *) cp_hashlist_get(sock->fds, &fd);
01054 cp_perror(CP_IO_ERROR, rc, "error closing connection to %s",
01055 inet_ntoa(insock->sin_addr));
01056 }
01057
01058 cp_hashlist_remove_deep(sock->fds, &fd);
01059 }
01060
01061 return rc;
01062 }
01063 #endif
01064
01065 int cp_socket_connection_close(cp_socket *sock, int fd)
01066 {
01067 struct sockaddr_in *insock;
01068 int rc = 0;
01069
01070 #ifdef __TRACE__
01071 DEBUGMSG("closing fd %d (table: %lX)", fd, (long) sock->fds);
01072 #endif
01073 insock = (struct sockaddr_in *) cp_hashlist_get(sock->fds, &fd);
01074 if (insock)
01075 {
01076 #ifdef __TRACE__
01077 DEBUGMSG("closing connection to %s", inet_ntoa(insock->sin_addr));
01078 #endif
01079 if (shutdown(fd, SHUT_RDWR) < 0)
01080 cp_perror(CP_IO_ERROR, errno, "shutdown error on connection to %s",
01081 inet_ntoa(insock->sin_addr));
01082
01083 if ((rc = close(fd)) < 0)
01084 cp_perror(CP_IO_ERROR, rc, "error closing connection to %s",
01085 inet_ntoa(insock->sin_addr));
01086
01087 cp_hashlist_remove_deep(sock->fds, &fd);
01088 }
01089
01090 return rc;
01091 }
01092
01093 int cp_connection_descrpitor_read(cp_connection_descriptor *desc,
01094 char *buf, int len)
01095 {
01096 int rc;
01097
01098 #ifdef CP_USE_SSL
01099 if (desc->sock->use_ssl)
01100 {
01101 rc = SSL_read(desc->ssl, buf, len);
01102 if (rc <= 0)
01103 {
01104 int err = SSL_get_error(desc->ssl, rc);
01105 const char *reason = ERR_reason_error_string(err);
01106 cp_error(CP_IO_ERROR, "write failed: %s", reason ? reason : ssl_err_inf(err));
01107 }
01108 }
01109 else
01110 #endif
01111 rc = read(desc->fd, buf, len);
01112
01113 if (rc > 0) desc->bytes_read += rc;
01114
01115 return rc;
01116 }
01117
01118 int cp_connection_descriptor_write(cp_connection_descriptor *desc,
01119 char *buf, int len)
01120 {
01121 int rc;
01122 #ifdef CP_USE_SSL
01123 if (desc->sock->use_ssl)
01124 {
01125 rc = SSL_write(desc->ssl, buf, len);
01126 if (rc <= 0)
01127 {
01128 int err = SSL_get_error(desc->ssl, rc);
01129 const char *reason = ERR_reason_error_string(err);
01130 cp_error(CP_IO_ERROR, "write failed: %s", reason ? reason : ssl_err_inf(err));
01131 }
01132 }
01133 else
01134 #endif
01135 rc = send(desc->fd, buf, len, 0);
01136
01137 if (rc > 0) desc->bytes_sent += rc;
01138
01139 return rc;
01140 }
01141