📄 conn.c
字号:
fd = conn->fd; unlock_out(conn); revents = gwthread_pollfd(fd, POLLOUT, -1.0); /* Note: Make sure we have the "out" lock when * going through the loop again, because the * loop condition needs it. */ if (revents < 0) { if (errno == EINTR) return 1; error(0, "conn_flush: poll failed on fd %d:", fd); return -1; } if (revents == 0) { /* We were woken up */ return 1; } if (revents & POLLNVAL) { error(0, "conn_flush: fd %d not open.", fd); return -1; } lock_out(conn); if (revents & (POLLOUT | POLLERR | POLLHUP)) { ret = unlocked_write(conn); if (ret < 0) { unlock_out(conn); return -1; } } } unlock_out(conn); return 0;}int conn_write(Connection *conn, Octstr *data){ int ret; lock_out(conn); octstr_append(conn->outbuf, data); ret = unlocked_try_write(conn); unlock_out(conn); return ret;}int conn_write_data(Connection *conn, unsigned char *data, long length){ int ret; lock_out(conn); octstr_append_data(conn->outbuf, data, length); ret = unlocked_try_write(conn); unlock_out(conn); return ret;}int conn_write_withlen(Connection *conn, Octstr *data){ int ret; unsigned char lengthbuf[4]; encode_network_long(lengthbuf, octstr_len(data)); lock_out(conn); octstr_append_data(conn->outbuf, lengthbuf, 4); octstr_append(conn->outbuf, data); ret = unlocked_try_write(conn); unlock_out(conn); return ret;}Octstr *conn_read_everything(Connection *conn){ Octstr *result = NULL; lock_in(conn); if (unlocked_inbuf_len(conn) == 0) { unlocked_read(conn); if (unlocked_inbuf_len(conn) == 0) { unlock_in(conn); return NULL; } } result = unlocked_get(conn, unlocked_inbuf_len(conn)); gw_claim_area(result); unlock_in(conn); return result;}Octstr *conn_read_fixed(Connection *conn, long length){ Octstr *result = NULL; /* See if the data is already available. If not, try a read(), * then see if we have enough data after that. If not, give up. */ lock_in(conn); if (unlocked_inbuf_len(conn) < length) { unlocked_read(conn); if (unlocked_inbuf_len(conn) < length) { unlock_in(conn); return NULL; } } result = unlocked_get(conn, length); gw_claim_area(result); unlock_in(conn); return result;}Octstr *conn_read_line(Connection *conn){ Octstr *result = NULL; long pos; lock_in(conn); /* 10 is the code for linefeed. We don't rely on \n because that * might be a different value on some (strange) systems, and * we are reading from a network connection. */ pos = octstr_search_char(conn->inbuf, 10, conn->inbufpos); if (pos < 0) { unlocked_read(conn); pos = octstr_search_char(conn->inbuf, 10, conn->inbufpos); if (pos < 0) { unlock_in(conn); return NULL; } } result = unlocked_get(conn, pos - conn->inbufpos); gw_claim_area(result); /* Skip the LF, which we left in the buffer */ conn->inbufpos++; /* If the line was terminated with CR LF, we have to remove * the CR from the result. */ if (octstr_len(result) > 0 && octstr_get_char(result, octstr_len(result) - 1) == 13) octstr_delete(result, octstr_len(result) - 1, 1); unlock_in(conn); return result;}Octstr *conn_read_withlen(Connection *conn){ Octstr *result = NULL; unsigned char lengthbuf[4]; long length; int try; lock_in(conn); for (try = 1; try <= 2; try++) { if (try > 1) unlocked_read(conn);retry: /* First get the length. */ if (unlocked_inbuf_len(conn) < 4) continue; octstr_get_many_chars(lengthbuf, conn->inbuf, conn->inbufpos, 4); length = decode_network_long(lengthbuf); if (length < 0) { warning(0, "conn_read_withlen: got negative length, skipping"); conn->inbufpos += 4; goto retry; } /* Then get the data. */ if (unlocked_inbuf_len(conn) - 4 < length) continue; conn->inbufpos += 4; result = unlocked_get(conn, length); gw_claim_area(result); break; } unlock_in(conn); return result;}Octstr *conn_read_packet(Connection *conn, int startmark, int endmark){ int startpos, endpos; Octstr *result = NULL; int try; lock_in(conn); for (try = 1; try <= 2; try++) { if (try > 1) unlocked_read(conn); /* Find startmark, and discard everything up to it */ startpos = octstr_search_char(conn->inbuf, startmark, conn->inbufpos); if (startpos < 0) { conn->inbufpos = octstr_len(conn->inbuf); continue; } else { conn->inbufpos = startpos; } /* Find first endmark after startmark */ endpos = octstr_search_char(conn->inbuf, endmark, conn->inbufpos); if (endpos < 0) continue; result = unlocked_get(conn, endpos - startpos + 1); gw_claim_area(result); break; } unlock_in(conn); return result;}#ifdef HAVE_LIBSSLX509 *conn_get_peer_certificate(Connection *conn) { /* Don't know if it needed to be locked , but better safe as crash */ lock_in(conn); lock_out(conn); if (conn->peer_certificate == NULL && conn->ssl != NULL) conn->peer_certificate = SSL_get_peer_certificate(conn->ssl); unlock_in(conn); unlock_out(conn); return conn->peer_certificate;}/* * XXX Alex decalred the RSA callback routine static and now we're getting * warning messages for our automatic compilation tests. So we are commenting * the function out to avoid the warnings. *static RSA *tmp_rsa_callback(SSL *ssl, int export, int key_len){ static RSA *rsa = NULL; debug("gwlib.http", 0, "SSL: Generating new RSA key (export=%d, keylen=%d)", export, key_len); if (export) { rsa = RSA_generate_key(key_len, RSA_F4, NULL, NULL); } else { debug("gwlib.http", 0, "SSL: Export not set"); } return rsa;}*/static Mutex **ssl_static_locks = NULL;/* the call-back function for the openssl crypto thread locking */static void openssl_locking_function(int mode, int n, const char *file, int line){ if (mode & CRYPTO_LOCK) mutex_lock(ssl_static_locks[n-1]); else mutex_unlock(ssl_static_locks[n-1]);}void openssl_init_locks(void){ int c, maxlocks = CRYPTO_num_locks(); gw_assert(ssl_static_locks == NULL); ssl_static_locks = gw_malloc(sizeof(Mutex *) * maxlocks); for (c = 0; c < maxlocks; c++) ssl_static_locks[c] = mutex_create(); /* after the mutexes have been created, apply the call-back to it */ CRYPTO_set_locking_callback(openssl_locking_function); CRYPTO_set_id_callback((CRYPTO_CALLBACK_PTR)gwthread_self);}void openssl_shutdown_locks(void){ int c, maxlocks = CRYPTO_num_locks(); /* remove call-back from the locks */ CRYPTO_set_locking_callback(NULL); for (c = 0; c < maxlocks; c++) mutex_destroy(ssl_static_locks[c]); gw_free(ssl_static_locks); ssl_static_locks = NULL;}void conn_init_ssl(void){ SSL_library_init(); SSL_load_error_strings(); global_ssl_context = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_mode(global_ssl_context, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);}void server_ssl_init(void) { SSLeay_add_ssl_algorithms(); SSL_load_error_strings(); global_server_ssl_context = SSL_CTX_new(SSLv23_server_method()); SSL_CTX_set_mode(global_server_ssl_context, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); if (!SSL_CTX_set_default_verify_paths(global_server_ssl_context)) { panic(0, "can not set default path for server"); }}void conn_shutdown_ssl(void){ if (global_ssl_context) SSL_CTX_free(global_ssl_context); ERR_free_strings(); EVP_cleanup();}void server_shutdown_ssl(void){ if (global_server_ssl_context) SSL_CTX_free(global_server_ssl_context); ERR_free_strings(); EVP_cleanup();}void use_global_client_certkey_file(Octstr *certkeyfile){ SSL_CTX_use_certificate_file(global_ssl_context, octstr_get_cstr(certkeyfile), SSL_FILETYPE_PEM); SSL_CTX_use_PrivateKey_file(global_ssl_context, octstr_get_cstr(certkeyfile), SSL_FILETYPE_PEM); if (SSL_CTX_check_private_key(global_ssl_context) != 1) panic(0, "reading global client certificate file `%s', the certificate " "isn't consistent with the private key (or failed reading the file)", octstr_get_cstr(certkeyfile)); info(0, "Using global SSL certificate and key from file `%s'", octstr_get_cstr(certkeyfile));}void use_global_server_certkey_file(Octstr *certfile, Octstr *keyfile) { SSL_CTX_use_certificate_file(global_server_ssl_context, octstr_get_cstr(certfile), SSL_FILETYPE_PEM); SSL_CTX_use_PrivateKey_file(global_server_ssl_context, octstr_get_cstr(keyfile), SSL_FILETYPE_PEM); if (SSL_CTX_check_private_key(global_server_ssl_context) != 1) { error(0, "SSL: %s", ERR_error_string(ERR_get_error(), NULL)); panic(0, "reading global server certificate file %s, the certificate \ isn't consistent with the private key in file %s \ (or failed reading the file)", octstr_get_cstr(certfile), octstr_get_cstr(keyfile)); } info(0, "Using global server SSL certificate from file `%s'", octstr_get_cstr(certfile)); info(0, "Using global server SSL key from file `%s'", octstr_get_cstr(keyfile));}static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx){ char subject[256]; char issuer [256]; char *status; X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), subject, sizeof(subject)); X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), issuer, sizeof (issuer)); status = preverify_ok ? "Accepting" : "Rejecting"; info(0, "%s certificate for \"%s\" signed by \"%s\"", status, subject, issuer); return preverify_ok;}void conn_config_ssl (CfgGroup *grp){ Octstr *ssl_client_certkey_file = NULL; Octstr *ssl_server_cert_file = NULL; Octstr *ssl_server_key_file = NULL; Octstr *ssl_trusted_ca_file = NULL; /* * check if SSL is desired for HTTP servers and then * load SSL client and SSL server public certificates * and private keys */ ssl_client_certkey_file = cfg_get(grp, octstr_imm("ssl-client-certkey-file")); if (ssl_client_certkey_file != NULL) use_global_client_certkey_file(ssl_client_certkey_file); ssl_server_cert_file = cfg_get(grp, octstr_imm("ssl-server-cert-file")); ssl_server_key_file = cfg_get(grp, octstr_imm("ssl-server-key-file")); if (ssl_server_cert_file != NULL && ssl_server_key_file != NULL) { use_global_server_certkey_file(ssl_server_cert_file, ssl_server_key_file); } ssl_trusted_ca_file = cfg_get(grp, octstr_imm("ssl-trusted-ca-file")); if (ssl_trusted_ca_file != NULL) { if (!SSL_CTX_load_verify_locations(global_ssl_context, octstr_get_cstr(ssl_trusted_ca_file), NULL)) { panic(0, "Failed to load SSL CA file: %s", octstr_get_cstr(ssl_trusted_ca_file)); } else { info(0, "Using CA root certificates from file %s", octstr_get_cstr(ssl_trusted_ca_file)); SSL_CTX_set_verify(global_ssl_context, SSL_VERIFY_PEER, verify_callback); } } else { SSL_CTX_set_verify(global_ssl_context, SSL_VERIFY_NONE, NULL); } octstr_destroy(ssl_client_certkey_file); octstr_destroy(ssl_server_cert_file); octstr_destroy(ssl_server_key_file); octstr_destroy(ssl_trusted_ca_file);}SSL *conn_get_ssl(Connection *conn){ if (conn != NULL) return conn->ssl; else return NULL;}#elsevoid conn_config_ssl (CfgGroup *grp){ info(0, "SSL not supported, no SSL initialization done.");}#endif /* HAVE_LIBSSL */int conn_get_id(Connection *conn) { if(conn == NULL) return 0; else return conn->fd;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -