// Establish a connection using an SSL layer void ssl_connect(mongo_link* link, SV *client) { tcp_setup(link); SV *ca_file_sv, *ca_path_sv; char *ca_file, *ca_path; if (link->master->socket){ // Register the error strings for libcrypto & libssl SSL_load_error_strings(); // Register the available ciphers and digests SSL_library_init(); // New context saying we are a client, and using SSL 2 or 3 link->ssl_context = SSL_CTX_new(SSLv23_client_method()); if(link->ssl_context == NULL){ ERR_print_errors_fp(stderr); } ca_file_sv = perl_mongo_call_method( client, "ssl_ca_file", 0, 0 ); ca_path_sv = perl_mongo_call_method( client, "ssl_ca_path", 0, 0 ); if ( SvPOK( ca_file_sv ) && SvPOK( ca_path_sv ) ) { ca_file = SvPV_nolen( ca_file_sv ); ca_path = SvPV_nolen( ca_path_sv ); SSL_CTX_load_verify_locations( link->ssl_context, ca_file, ca_path ); } // Create an SSL struct for the connection link->ssl_handle = SSL_new(link->ssl_context); if(link->ssl_handle == NULL){ ERR_print_errors_fp(stderr); } // Connect the SSL struct to our connection if(!SSL_set_fd(link->ssl_handle, link->master->socket)){ ERR_print_errors_fp(stderr); } // Initiate SSL handshake if(SSL_connect (link->ssl_handle) != 1){ ERR_print_errors_fp(stderr); } SSL_CTX_set_timeout(link->ssl_context, (long)link->timeout); link->master->connected = 1; } }
// Establish a connection using an SSL layer void ssl_connect(mongo_link* link) { tcp_setup(link); if (link->master->socket){ // Register the error strings for libcrypto & libssl SSL_load_error_strings(); // Register the available ciphers and digests SSL_library_init(); // New context saying we are a client, and using SSL 2 or 3 link->ssl_context = SSL_CTX_new(SSLv23_client_method()); if(link->ssl_context == NULL){ ERR_print_errors_fp(stderr); } // Create an SSL struct for the connection link->ssl_handle = SSL_new(link->ssl_context); if(link->ssl_handle == NULL){ ERR_print_errors_fp(stderr); } // Connect the SSL struct to our connection if(!SSL_set_fd(link->ssl_handle, link->master->socket)){ ERR_print_errors_fp(stderr); } // Initiate SSL handshake if(SSL_connect (link->ssl_handle) != 1){ ERR_print_errors_fp(stderr); } SSL_CTX_set_timeout(link->ssl_context, (long)link->timeout); link->master->connected = 1; } }
int main(int argc, char **argv) { int udp_socket; int tcp_socket; int tcp_port; int client_socket; struct sockaddr_in addr; int addr_size; char buffer[1025]; struct client *clients; int num_clients; int max_clients; int i, j; int len; char* temp_str; fd_set read_fds_master; fd_set read_fds_copy; int fd_max; FD_ZERO(&read_fds_master); FD_ZERO(&read_fds_copy); clients = malloc(BACKLOG * sizeof(struct client)); num_clients = 0; max_clients = BACKLOG; /* signal(SIGINT, handle_sigint); */ if ((udp_socket = udp_setup(UDP_PORT)) == -1) exit(1); /* make udp socket "select()able" */ FD_SET(udp_socket, &read_fds_master); fd_max = udp_socket; if((tcp_socket = tcp_setup(&tcp_port)) == -1) exit(1); printf("Listening on tcp port: %d\n", tcp_port); /* make tcp socket "select()able" */ FD_SET(tcp_socket, &read_fds_master); fd_max = tcp_socket; /* main loop */ for (;;) { /* handle readable sockets */ read_fds_copy = read_fds_master; // make a copy that select() can modify if (select(fd_max + 1, &read_fds_copy, NULL, NULL, NULL) == -1) { fprintf(stderr, "Error during select().\n"); close(udp_socket); exit(1); } for (i = 0; i <= fd_max; i++) { if (FD_ISSET(i, &read_fds_copy)) { if (i == udp_socket) { /* answer a multicast message */ memset(buffer, 0, sizeof(buffer)); addr_size = sizeof(addr); if (recvfrom(udp_socket, buffer, sizeof(buffer), 0, (struct sockaddr*)&addr, &addr_size) == -1) { fprintf(stderr, "Error receiving multicast message.\n"); close(udp_socket); exit(1); } if (strncmp(buffer, "server_discovery", 16) == 0) { printf("%s:%d - discovery request\n", inet_ntoa(addr.sin_addr.s_addr), ntohs(addr.sin_port)); len = sprintf(buffer, "discovery_reply %d\n", tcp_port); addr_size = sizeof(addr); if (sendto(udp_socket, buffer, len, 0, (struct sockaddr*)&addr, addr_size) == -1) { perror("Error answering multicast message.\n"); close(udp_socket); exit(1); } } } if (i == tcp_socket) { for (j = 0; j < num_clients; j++) { if (clients[j].status == 'd') break; /* the value of j at this point is used as a side effect later */ } /* j is now ALWAYS the first unused index of the clients array */ if (j == num_clients) num_clients++; if (num_clients > max_clients) { max_clients = max_clients + BACKLOG; clients = realloc(clients, max_clients * sizeof(struct client)); } addr_size = sizeof(addr); clients[j].socket = accept(tcp_socket, (struct sockaddr*)&addr, &addr_size); clients[j].status = 'c'; /* save source as string for logging and debugging */ strncpy(clients[j].socket_addr, (const char*)inet_ntoa(addr.sin_addr.s_addr), 15); clients[j].socket_port = ntohs(addr.sin_port); printf("%s:%d - new connection.\n", clients[j].socket_addr, clients[j].socket_port); FD_SET(clients[j].socket, &read_fds_master); if (clients[j].socket > fd_max) fd_max = clients[j].socket; } for (j = 0; j < num_clients; j++) { if (i == clients[j].socket) { memset(buffer, 0, sizeof(buffer)); len = recv(clients[j].socket, buffer, sizeof(buffer) - 1 - strlen(clients[j].line_buffer), 0); switch (len) { case 0: printf("%s:%d - disconnected.\n", clients[j].socket_addr, clients[j].socket_port); FD_CLR(clients[j].socket, &read_fds_master); clients[j].status = 'd'; push_global_filelist(clients, num_clients); break; case -1: /* TODO: handle gracefully. this is usually a "connection reset by peer" */ perror("recv"); break; default: strncat(clients[j].line_buffer, buffer, len); while (strchr(clients[j].line_buffer, '\n') != NULL) { switch (clients[j].status) { case 'c': //printf("status: connected\n"); if (sscanf(clients[j].line_buffer, "register %d", &(clients[j].download_port)) == 1) { printf("%s:%d - registered port %d for downloads.\n", clients[j].socket_addr, clients[j].socket_port, clients[j].download_port); clients[j].status = 'r'; break; } printf("%s:%d - sent %d unrecognized bytes: %s\n", clients[j].socket_addr, clients[j].socket_port, strlen(clients[j].line_buffer), clients[j].line_buffer); break; case 'r': //printf("status: registered\n"); //printf("buffer: %s", clients[j].line_buffer); if (sscanf(clients[j].line_buffer, "send_filelist %d\n", &(clients[j].filelist_size)) == 1) { if (clients[j].filelist_size > 0) { printf("%s:%d - will send %d file list entries next.\n", clients[j].socket_addr, clients[j].socket_port, clients[j].filelist_size); if (clients[j].file_list != NULL) free(clients[j].file_list); clients[j].file_list = malloc(clients[j].filelist_size * sizeof(struct filelist_entry)); } clients[j].status = 's'; clients[j].filelist_len = 0; break; } if (strncmp(clients[j].line_buffer, "unregister", 10) == 0) { printf("%s:%d - unregistered download port.\n", clients[j].socket_addr, clients[j].socket_port); clients[j].status = 'c'; break; } printf("%s:%d - sent %d unrecognized bytes: %s\n", clients[j].socket_addr, clients[j].socket_port, strlen(clients[j].line_buffer), clients[j].line_buffer); break; case 's': //printf("status: sending file list\n"); if (clients[j].filelist_len < clients[j].filelist_size) { len = clients[j].filelist_len; if (sscanf(clients[j].line_buffer , "%d %1000s", &(clients[j].file_list[len].size), clients[j].file_list[len].name) == 2) { clients[j].filelist_len = clients[j].filelist_len + 1; printf("%s:%d - sent a file list entry: %s (%d bytes)\n", clients[j].socket_addr, clients[j].socket_port, clients[j].file_list[len].name, clients[j].file_list[len].size); } else { printf("%s:%d - sent %d unrecognized bytes: %s\n", clients[j].socket_addr, clients[j].socket_port, strlen(clients[j].line_buffer), clients[j].line_buffer); } } if (clients[j].filelist_len == clients[j].filelist_size) { clients[j].status = 'r'; push_global_filelist(clients, num_clients); } break; default: break; } /* consume part of buffer */ temp_str = strchr(clients[j].line_buffer, '\n'); //printf("bytes left: %d\n", strlen(temp_str)); if (strlen(temp_str) > 1) { memset(buffer, 0, sizeof(buffer)); strncpy(buffer, temp_str + 1, strlen(temp_str) - 1); //printf("bytes left: %d\n", strlen(buffer)); memset(clients[j].line_buffer, 0, sizeof(clients[j].line_buffer)); strncpy(clients[j].line_buffer, buffer, strlen(buffer)); //printf("line buffer: %s", clients[j].line_buffer); } else { memset(clients[j].line_buffer, 0, sizeof(clients[j].line_buffer)); } } } } } } } } }
int main(int argc, char *argv[]) { char *dummy; int sock[2]; long port; if (argc != 2) usage(); port = strtol(argv[1], &dummy, 10); if (port < 0 || port > 65535 || *dummy != '\0') usage(); #ifndef SO_NOSIGPIPE warnx("sigpipe: SO_NOSIGPIPE not defined, skipping some tests"); #endif /* * UNIX domain socketpair(). */ if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sock) < 0) err(-1, "socketpair(PF_LOCAL, SOCK_STREAM)"); test_send_wantsignal("test_send_wantsignal(PF_LOCAL)", sock[0], sock[1]); #ifdef SO_NOSIGPIPE if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sock) < 0) err(-1, "socketpair(PF_LOCAL, SOCK_STREAM)"); test_send_dontsignal("test_send_dontsignal(PF_LOCAL)", sock[0], sock[1]); #endif if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sock) < 0) err(-1, "socketpair(PF_LOCAL, SOCK_STREAM)"); test_write_wantsignal("test_write_wantsignal(PF_LOCAL)", sock[0], sock[1]); #ifdef SO_NOSIGPIPE if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sock) < 0) err(-1, "socketpair(PF_LOCAL, SOCK_STREAM)"); test_write_dontsignal("test_write_dontsignal(PF_LOCAL)", sock[0], sock[1]); #endif /* * TCP. */ tcp_setup(port); tcp_pair(port, sock); test_send_wantsignal("test_send_wantsignal(PF_INET)", sock[0], sock[1]); #ifdef SO_NOSIGPIPE tcp_pair(port, sock); test_send_dontsignal("test_send_dontsignal(PF_INET)", sock[0], sock[1]); #endif tcp_pair(port, sock); test_write_wantsignal("test_write_wantsignal(PF_INET)", sock[0], sock[1]); #ifdef SO_NOSIGPIPE tcp_pair(port, sock); test_write_dontsignal("test_write_dontsignal(PF_INET)", sock[0], sock[1]); #endif tcp_teardown(); fprintf(stderr, "PASS\n"); return (0); }
static void setup(void) { char *fname = NULL; uint64_t intvl; if (atexit(teardown) != 0) { log_stderr("cannot register teardown procedure with atexit()"); exit(EX_OSERR); /* only failure comes from NOMEM */ } /* Setup logging first */ log_setup(&stats.log); if (debug_setup(&setting.debug) != CC_OK) { log_stderr("debug log setup failed"); exit(EX_CONFIG); } /* setup top-level application options */ if (option_bool(&setting.ds.daemonize)) { daemonize(); } fname = option_str(&setting.ds.pid_filename); if (fname != NULL) { /* to get the correct pid, call create_pidfile after daemonize */ create_pidfile(fname); } /* setup library modules */ buf_setup(&setting.buf, &stats.buf); dbuf_setup(&setting.dbuf, &stats.dbuf); event_setup(&stats.event); sockio_setup(&setting.sockio, &stats.sockio); tcp_setup(&setting.tcp, &stats.tcp); timing_wheel_setup(&stats.timing_wheel); /* setup pelikan modules */ time_setup(&setting.time); procinfo_setup(&stats.procinfo); request_setup(&setting.request, &stats.request); response_setup(&setting.response, &stats.response); parse_setup(&stats.parse_req, NULL); compose_setup(NULL, &stats.compose_rsp); slab_setup(&setting.slab, &stats.slab); process_setup(&setting.process, &stats.process); admin_process_setup(); core_admin_setup(&setting.admin); core_server_setup(&setting.server, &stats.server); core_worker_setup(&setting.worker, &stats.worker); /* adding recurring events to maintenance/admin thread */ intvl = option_uint(&setting.ds.dlog_intvl); if (core_admin_register(intvl, debug_log_flush, NULL) == NULL) { log_stderr("Could not register timed event to flush debug log"); goto error; } return; error: if (fname != NULL) { remove_pidfile(fname); } /* since we registered teardown with atexit, it'll be called upon exit */ exit(EX_CONFIG); }