void forward_start(CLIENT_ENTRY *entry) { const char *myname = "forward_start"; ACL_ASTREAM *server; /* 先从连接池中尝试一个连接流 */ server = peek_server_conn(entry); if (server == NULL) { /* 如果连接池中没有可利用的连接流,则开始连接服务端 */ server = forward_connect_next(entry); if (server == NULL) { acl_msg_error("%s: connect server_addr(%s:%d) error(%s)", myname, entry->domain_key, entry->server_port, acl_last_serror()); #if 1 if (entry->connect_error_fn) entry->connect_error_fn(entry); #else forward_complete(entry); #endif return; } entry->flag_conn_reuse = 0; client_entry_set_server(entry, server); acl_aio_ctl(server, ACL_AIO_CTL_CONNECT_FN, connect_callback, ACL_AIO_CTL_CTX, entry, ACL_AIO_CTL_CLOSE_HOOK_ADD, connect_close_callback, entry, ACL_AIO_CTL_TIMEO_HOOK_ADD, connect_timeout_callback, entry, ACL_AIO_CTL_END); } else { /* 复用连接池中的连接 */ entry->flag_conn_reuse = 1; client_entry_set_server(entry, server); acl_aio_ctl(server, ACL_AIO_CTL_CTX, entry, ACL_AIO_CTL_END); connect_callback(server, entry); } }
static int connect_callback(ACL_ASTREAM *server, void *context) { CLIENT_ENTRY *entry = (CLIENT_ENTRY*) context; /* 卸载回调函数,防止被重复调用 */ acl_aio_ctl(server, ACL_AIO_CTL_CONNECT_FN, NULL, ACL_AIO_CTL_CLOSE_HOOK_DEL, connect_close_callback, entry, ACL_AIO_CTL_TIMEO_HOOK_DEL, connect_timeout_callback, entry, ACL_AIO_CTL_END); entry->tm.connect = time(NULL) - entry->tm.stamp; return (entry->connect_notify_fn(entry)); }
void aio_listen_stream::hook_accept() { acl_assert(stream_); if (accept_hooked_) return; accept_hooked_ = true; acl_aio_ctl(stream_, ACL_AIO_CTL_ACCEPT_FN, accept_callback, ACL_AIO_CTL_CTX, this, ACL_AIO_CTL_END); acl_aio_accept(stream_); }
static void hdr_get_async(ctx_type type, HTTP_HDR *hdr, ACL_ASTREAM *astream, HTTP_HDR_NOTIFY notify, void *arg, int timeout) { const char *myname = "hdr_get_async"; HTTP_CHAT_CTX *ctx; ACL_VSTREAM *stream; if (hdr == NULL || astream == NULL || notify == NULL) acl_msg_fatal("%s: input invalid", myname); stream = acl_aio_vstream(astream); stream->rw_timeout = 0; /* bug fix, --zsx, 2007.7.7 */ if (hdr->chat_ctx == NULL) { hdr->chat_ctx = new_ctx(type); hdr->chat_free_ctx_fn = free_ctx_fn; } ctx = (HTTP_CHAT_CTX*) hdr->chat_ctx; ctx->hdr = hdr; ctx->timeout = timeout; ctx->notify.hdr_notify = notify; ctx->arg = arg; ctx->status = CHAT_S_HDR; if (0) { acl_aio_ctl(astream, ACL_AIO_CTL_READ_HOOK_ADD, hdr_gets_ready, ctx, ACL_AIO_CTL_TIMEOUT, timeout, ACL_AIO_CTL_END); acl_aio_gets_nonl(astream); } else { acl_aio_ctl(astream, ACL_AIO_CTL_TIMEOUT, timeout, ACL_AIO_CTL_END); acl_aio_enable_read(astream, hdr_can_read, ctx); } }
static int close_callback(ACL_ASTREAM *stream, void *context) { const char *myname = "close_callback"; ACL_AIO *aio = (ACL_AIO*) context; const char *addr = ACL_VSTREAM_PATH(stream->stream); printf("%s: re-connect %s, aio(%s)\n", myname, addr, aio ? "not null" : "null"); stream = acl_aio_connect(aio, addr, 0); if (stream == NULL) { printf("%s: connect addr(%s) error(%s)\n", myname, addr, acl_last_serror()); return (-1); } printf("%s: re-connect %s ok\n", myname, addr); acl_aio_ctl(stream, ACL_AIO_CTL_CONNECT_FN, connect_callback, ACL_AIO_CTL_CTX, aio, ACL_AIO_CTL_END); return (-1); }
SERVICE *service_create(const char *local_ip, short local_port, const char *dns_ip, short dns_port) { const char *myname = "service_create"; SERVICE *service; ACL_VSTREAM *sstream; char addr[64]; // 创建提供 TCP 方式查询时的监听流 snprintf(addr, sizeof(addr), "%s:%d", local_ip, local_port); sstream = acl_vstream_listen_ex(addr, 128, ACL_NON_BLOCKING, 1024, 10); if (sstream == NULL) { acl_msg_error("%s(%d): can't listen on addr(%s)", myname, __LINE__, addr); return (NULL); } service = (SERVICE*) acl_mycalloc(1, sizeof(SERVICE)); ACL_SAFE_STRNCPY(service->listen_addr, addr, sizeof(service->listen_addr)); ACL_SAFE_STRNCPY(service->dns_ip, dns_ip, sizeof(service->dns_ip)); service->dns_port = dns_port; snprintf(service->dns_addr, sizeof(service->dns_addr), "%s:%d", dns_ip, dns_port); service->conn_timeout = 10; service->rw_timeout = 10; service->table = acl_htable_create(100, 0); service->aio = acl_aio_create(ACL_EVENT_SELECT); service->sstream = acl_aio_open(service->aio, sstream); acl_aio_ctl(service->sstream, ACL_AIO_CTL_ACCEPT_FN, accept_callback, ACL_AIO_CTL_CTX, service, ACL_AIO_CTL_END); acl_aio_accept(service->sstream); service_udp_init(service, local_ip, local_port, dns_ip, dns_port); return (service); }
static int connect_timeout_callback(ACL_ASTREAM *astream, void *context) { const char* myname = "connect_timeout_callback"; CLIENT_ENTRY *entry = (CLIENT_ENTRY *) context; /* 卸载回调函数,防止被重复调用 */ acl_aio_ctl(astream, ACL_AIO_CTL_CONNECT_FN, NULL, ACL_AIO_CTL_CLOSE_HOOK_DEL, connect_close_callback, entry, ACL_AIO_CTL_TIMEO_HOOK_DEL, connect_timeout_callback, entry, ACL_AIO_CTL_END); if (entry->flag_has_replied == 1) return (-1); if (entry->ip_idx < entry->dns_ctx.ip_cnt) { ACL_ASTREAM *server; acl_debug(23, 1) ("%s(%d): begin to connect next ip(%s:%d)", myname, __LINE__, entry->dns_ctx.ip[entry->ip_idx], entry->server_port); /* 断开与服务端的连接,但保持与浏览器端的连接 * XXX: 因为该函数将清除一些关闭回调函数,不知是否会造成某些内存泄漏? * 注,此处并不关闭服务端连接,需要调用者自己来关闭 */ if (client_entry_detach(entry, acl_aio_vstream(entry->server)) == 1) { acl_debug(3, 1) ("%s(%d): entry is freed", myname, __LINE__); return (-1); } server = forward_connect_next(entry); if (server == NULL) goto CONNECT_ERROR; client_entry_set_server(entry, server); acl_aio_ctl(server, ACL_AIO_CTL_CONNECT_FN, connect_callback, ACL_AIO_CTL_CLOSE_HOOK_ADD, connect_close_callback, entry, ACL_AIO_CTL_TIMEO_HOOK_ADD, connect_timeout_callback, entry, ACL_AIO_CTL_CTX, entry, ACL_AIO_CTL_END); /* 通过返回-1,使异步流框架关闭服务端连接 */ return (-1); } CONNECT_ERROR: entry->tm.connect = time(NULL) - entry->tm.stamp; if (entry->ip_idx <= 0) acl_debug(23, 0) ("%s(%d): internal error, ip_idx=0, domain(%s:%d)", myname, __LINE__, entry->domain_key, entry->server_port); else acl_debug(23, 0) ("%s(%d): connect timeout, addr(%s:%d)", myname, __LINE__, entry->dns_ctx.ip[entry->ip_idx - 1], entry->server_port); entry->flag_has_replied = 1; if (entry->connect_timeout_fn) entry->connect_timeout_fn(entry); return (-1); }