int acl_sane_socketpair(int domain, int type, int protocol, ACL_SOCKET result[2]) { ACL_SOCKET listener = acl_inet_listen("127.0.0.1:0", 1, ACL_BLOCKING); char addr[64]; (void) domain; result[0] = ACL_SOCKET_INVALID; result[1] = ACL_SOCKET_INVALID; if (listener == ACL_SOCKET_INVALID) { acl_msg_error("%s(%d), %s: listen error %s", __FILE__, __LINE__, __FUNCTION__, acl_last_serror()); return -1; } acl_tcp_set_nodelay(listener); if (acl_getsockname(listener, addr, sizeof(addr)) < 0) { acl_msg_error("%s(%d), %s: getoskname error %s", __FILE__, __LINE__, __FUNCTION__, acl_last_serror()); acl_socket_close(listener); return -1; } result[0] = acl_inet_connect(addr, ACL_BLOCKING, 0); if (result[0] == ACL_SOCKET_INVALID) { acl_msg_error("%s(%d), %s: connect %s error %s", __FILE__, __LINE__, __FUNCTION__, addr, acl_last_serror()); acl_socket_close(listener); return -1; } result[1] = acl_inet_accept(listener); acl_socket_close(listener); if (result[1] == ACL_SOCKET_INVALID) { acl_msg_error("%s(%d), %s: accept error %s", __FILE__, __LINE__, __FUNCTION__, acl_last_serror()); acl_socket_close(result[0]); result[0] = ACL_SOCKET_INVALID; return -1; } acl_tcp_set_nodelay(result[0]); acl_tcp_set_nodelay(result[1]); return 0; }
stream_hook* stream::setup_hook(stream_hook* hook) { if (stream_ == NULL) { logger_error("stream_ null"); return NULL; } stream_hook* old_hook = hook_; if (stream_->type == ACL_VSTREAM_TYPE_FILE) { ACL_FSTREAM_RD_FN read_fn = stream_->fread_fn; ACL_FSTREAM_WR_FN write_fn = stream_->fwrite_fn; stream_->fread_fn = fread_hook; stream_->fwrite_fn = fsend_hook; acl_vstream_add_object(stream_, HOOK_KEY, this); if (hook->open(stream_) == false) { // 如果打开失败,则恢复 stream_->fread_fn = read_fn; stream_->fwrite_fn = write_fn; acl_vstream_del_object(stream_, HOOK_KEY); return hook; } } else { ACL_VSTREAM_RD_FN read_fn = stream_->read_fn; ACL_VSTREAM_WR_FN write_fn = stream_->write_fn; stream_->read_fn = read_hook; stream_->write_fn = send_hook; acl_vstream_add_object(stream_, HOOK_KEY, this); acl_tcp_set_nodelay(ACL_VSTREAM_SOCK(stream_)); if (hook->open(stream_) == false) { // 如果打开失败,则恢复 stream_->read_fn = read_fn; stream_->write_fn = write_fn; acl_vstream_del_object(stream_, HOOK_KEY); return hook; } } hook_ = hook; return old_hook; }
static void run_server(const char *addr) { ACL_VSTREAM *sstream = acl_vstream_listen(addr, 128); acl_pthread_pool_t *pool; CONN *conn; acl_pthread_t tid; acl_pthread_attr_t attr; ACL_VSTREAM *client; if (sstream == NULL) { acl_msg_error("listen %s error(%s)", addr, acl_last_serror()); return; } pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); printf("listening on %s ...\n", addr); pool = acl_thread_pool_create(10, 10); while (1) { acl_mem_slice_delay_destroy(); if (acl_read_wait(ACL_VSTREAM_SOCK(sstream), 5) == -1) continue; client = acl_vstream_accept(sstream, NULL, 0); if (client == NULL) { acl_msg_error("accept error(%s)", acl_last_serror()); break; } acl_tcp_set_nodelay(ACL_VSTREAM_SOCK(client)); conn = acl_mycalloc(1, sizeof(CONN)); conn->stream = client; if (0) thread_run(conn); else if (1) acl_pthread_create(&tid, &attr, thread_main, conn); else acl_pthread_pool_add(pool, thread_run, conn); } acl_vstream_close(sstream); }
bool ssl_aio_stream::ssl_client_init() { #ifdef HAS_POLARSSL ACL_VSTREAM* stream = get_vstream(); acl_assert(stream); // 0. Initialize the RNG and the session data havege_init((havege_state*) hs_); int ret; if ((ret = ssl_init((ssl_context*) ssl_)) != 0) { logger_error("failed, ssl_init returned %d", ret); return false; } ssl_set_endpoint((ssl_context*) ssl_, SSL_IS_CLIENT); ssl_set_authmode((ssl_context*) ssl_, SSL_VERIFY_NONE); ssl_set_rng((ssl_context*) ssl_, ::havege_random, hs_); //ssl_set_dbg((ssl_context*) ssl_, my_debug, stdout); ssl_set_bio((ssl_context*) ssl_, __sock_read, this, __sock_send, this); const int* cipher_suites = ssl_list_ciphersuites(); if (cipher_suites == NULL) { logger_error("ssl_list_ciphersuites null"); return false; } ssl_set_ciphersuites((ssl_context*) ssl_, cipher_suites); ssl_set_session((ssl_context*) ssl_, (ssl_session*) ssn_); acl_vstream_ctl(stream, ACL_VSTREAM_CTL_READ_FN, __ssl_read, ACL_VSTREAM_CTL_WRITE_FN, __ssl_send, ACL_VSTREAM_CTL_CTX, this, ACL_VSTREAM_CTL_END); acl_tcp_set_nodelay(ACL_VSTREAM_SOCK(stream)); #endif return true; }
socket_stream* server_socket::accept(int timeout /* = 0 */) { if (fd_ == ACL_SOCKET_INVALID) { logger_error("server socket not opened!"); return NULL; } if (block_ && timeout > 0) { if (acl_read_wait(fd_, timeout) == -1) return NULL; } ACL_SOCKET fd = acl_accept(fd_, NULL, 0, NULL); if (fd == ACL_SOCKET_INVALID) { if (block_) logger_error("accept error %s", last_serror()); else if (last_error() != ACL_EAGAIN && last_error() != ACL_EWOULDBLOCK) { logger_error("accept error %s", last_serror()); } return NULL; } socket_stream* client = new socket_stream(); if (client->open(fd) == false) { logger_error("create socket_stream error!"); return NULL; } if (!unix_sock_) acl_tcp_set_nodelay(fd); return client; }
bool socket_stream::open_ssl_client(void) { if (stream_ == NULL) { logger_error("stream_ null"); return false; } #ifdef HAS_POLARSSL // 如果打开已经是 SSL 模式的流,则直接返回 if (ssl_ != NULL) { acl_assert(ssn_); acl_assert(hs_); return true; } ssl_ = acl_mycalloc(1, sizeof(ssl_context)); ssn_ = acl_mycalloc(1, sizeof(ssl_session)); hs_ = acl_mymalloc(sizeof(havege_state)); // Initialize the RNG and the session data ::havege_init((havege_state*) hs_); int ret; // Setup stuff if ((ret = ssl_init((ssl_context*) ssl_)) != 0) { logger_error("failed, ssl_init returned %d", ret); return false; } ssl_set_endpoint((ssl_context*) ssl_, SSL_IS_CLIENT); ssl_set_authmode((ssl_context*) ssl_, SSL_VERIFY_NONE); ssl_set_rng((ssl_context*) ssl_, havege_random, hs_); //ssl_set_dbg(ssl_, my_debug, stdout); ssl_set_bio((ssl_context*) ssl_, sock_read, this, sock_send, this); const int* cipher_suites = ssl_list_ciphersuites(); if (cipher_suites == NULL) { logger_error("ssl_list_ciphersuites null"); return false; } ssl_set_ciphersuites((ssl_context*) ssl_, cipher_suites); ssl_set_session((ssl_context*) ssl_, (ssl_session*) ssn_); acl_vstream_ctl(stream_, ACL_VSTREAM_CTL_READ_FN, ssl_read, ACL_VSTREAM_CTL_WRITE_FN, ssl_send, ACL_VSTREAM_CTL_CTX, this, ACL_VSTREAM_CTL_END); acl_tcp_set_nodelay(ACL_VSTREAM_SOCK(stream_)); // Handshake while((ret = ssl_handshake((ssl_context*) ssl_)) != 0) { if (ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE) { logger_error("ssl_handshake failed: 0x%x", ret); return false; } } return true; #else logger_error("define HAS_POLARSSL first!"); return false; #endif }
static void run_one(TLS_APPL_STATE *client_tls_ctx) { ACL_VSTREAM *client; TLS_SESS_STATE *client_sess_ctx; TLS_CLIENT_START_PROPS tls_props; char buf[4096]; int i, ret; time_t last, now; int tls_level = 2; char *tls_nexthop = "test.com.cn"; char *host = "test.com.cn"; char *namaddrport = "test.com.cn"; char *serverid = "service:addr:port:helo"; char *tls_protocols = SSL_TXT_TLSV1; char *tls_grade = "low"; /* high, medium, low, export, null */ char *tls_exclusions = ""; ACL_ARGV *tls_matchargv = 0; client = acl_vstream_connect(serv_addr, ACL_BLOCKING, 20, 30, 8192); if (client == NULL) { printf("connect %s error(%s)\n", serv_addr, acl_last_serror()); return; } acl_tcp_set_nodelay(ACL_VSTREAM_SOCK(client)); #if 0 client_sess_ctx = TLS_CLIENT_START(&tls_props, ctx = client_tls_ctx, stream = client, log_level = var_client_tls_loglevel, timeout = var_client_starttls_tmout, tls_level = tls_level, nexthop = tls_nexthop, host = host, namaddr = namaddrport, serverid = serverid, protocols = tls_protocols, cipher_grade = tls_grade, cipher_exclusions = tls_exclusions, matchargv = tls_matchargv, fpt_dgst = var_client_tls_fpt_dgst); #else tls_props.ctx = client_tls_ctx; tls_props.stream = client; tls_props.log_level = var_client_tls_loglevel; tls_props.timeout = var_client_starttls_tmout; tls_props.tls_level = tls_level; tls_props.nexthop = tls_nexthop; tls_props.host = host; tls_props.namaddr = namaddrport; tls_props.serverid = serverid; tls_props.protocols = tls_protocols; tls_props.cipher_grade = tls_grade; tls_props.cipher_exclusions = tls_exclusions; tls_props.matchargv = tls_matchargv; tls_props.fpt_dgst = var_client_tls_fpt_dgst; client_sess_ctx = tls_client_start(&tls_props); #endif if (client_sess_ctx == NULL) { printf("TLS_CLIENT_START error\n"); acl_vstream_close(client); return; } if (tls_level >= TLS_LEV_VERIFY) { if (!TLS_CERT_IS_TRUSTED(client_sess_ctx)) { printf("Server certificate not trusted\n"); } } if (tls_level > TLS_LEV_ENCRYPT) { if (!TLS_CERT_IS_MATCHED(client_sess_ctx)) { printf("Server certificate not verified\n"); } } time(&last); i = 0; while (1) { ret = acl_vstream_fprintf(client, "hello world\n"); if (ret == ACL_VSTREAM_EOF) goto END; ret = acl_vstream_gets(client, buf, sizeof(buf)); if (ret == ACL_VSTREAM_EOF) goto END; break; i++; if (i % 50000 == 0) { time(&now); printf("client: i=%d, time=%ld\n", i, now - last); last = now; } } if (0) { if (acl_vstream_writen(client, request, strlen(request)) == ACL_VSTREAM_EOF) printf("write request error\n"); else { while (1) { if (acl_vstream_gets_nonl(client, buf, sizeof(buf)) == ACL_VSTREAM_EOF) break; /* printf("%s\n", buf); */ } /* printf("gets respond over now\n"); */ } } END: tls_client_stop(client_tls_ctx, client, var_client_starttls_tmout, 0, client_sess_ctx); acl_vstream_close(client); }