예제 #1
0
파일: forward.c 프로젝트: aaronshang/acl
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);
	}
}
예제 #2
0
파일: forward.c 프로젝트: aaronshang/acl
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));
}
예제 #3
0
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_);
}
예제 #4
0
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);
	}
}
예제 #5
0
파일: main.c 프로젝트: 10jschen/acl
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);
}
예제 #6
0
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);
}
예제 #7
0
파일: forward.c 프로젝트: aaronshang/acl
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);
}