Beispiel #1
0
void    acl_master_flow_init(void)
{
    char   *myname = "acl_master_flow_init";

    if (pipe(acl_var_master_flow_pipe) < 0)
	acl_msg_fatal("%s(%d)->%s: pipe: %s",
			__FILE__, __LINE__, myname, strerror(errno));

    acl_non_blocking(acl_var_master_flow_pipe[0], ACL_NON_BLOCKING);
    acl_non_blocking(acl_var_master_flow_pipe[1], ACL_NON_BLOCKING);

    acl_close_on_exec(acl_var_master_flow_pipe[0], ACL_CLOSE_ON_EXEC);
    acl_close_on_exec(acl_var_master_flow_pipe[1], ACL_CLOSE_ON_EXEC);
}
Beispiel #2
0
bool master_service::on_accept(acl::aio_socket_stream* client)
{
	if (0)
	logger("connect from %s, fd %d", client->get_peer(true),
		client->sock_handle());

	acl_non_blocking(client->sock_handle(), ACL_BLOCKING);

	// 根据客户端连接服务端口号的不同来区分不同的服务应用协议
	const char* local = client->get_local(true);
	if (acl_strrncasecmp(local, var_cfg_backend_service,
		strlen(var_cfg_backend_service)) == 0)
	{
		// 创建服务对象处理来自于后端服务模块的请求
		IConnection* conn = new ServerConnection(client);

		conn->run();
		return true;
	}
	else
	{
		// 创建对象处理来自于前端客户端模块的请求
		IConnection* conn = new ClientConnection(client, var_cfg_conn_expired);

		conn->run();
		return true;
	}

	return true;
}
Beispiel #3
0
void    acl_master_status_init(ACL_MASTER_SERV *serv)
{
	const char *myname = "acl_master_status_init";

	/*
	 * Sanity checks.
	 */
	if (serv->status_fd[0] >= 0 || serv->status_fd[1] >= 0)
		acl_msg_panic("%s: status events already enabled", myname);
	if (acl_msg_verbose)
		acl_msg_info("%s: %s", myname, serv->name);

	/*
	 * Make the read end of this service's status pipe non-blocking so that
	 * we can detect partial writes on the child side. We use a duplex pipe
	 * so that the child side becomes readable when the master goes away.
	 */
	if (acl_duplex_pipe(serv->status_fd) < 0)
		acl_msg_fatal("pipe: %s", strerror(errno));
	acl_non_blocking(serv->status_fd[0], ACL_BLOCKING);
	acl_close_on_exec(serv->status_fd[0], ACL_CLOSE_ON_EXEC);
	acl_close_on_exec(serv->status_fd[1], ACL_CLOSE_ON_EXEC);
	serv->status_read_stream = acl_vstream_fdopen(serv->status_fd[0],
		O_RDWR, acl_var_master_buf_size,
		acl_var_master_rw_timeout, ACL_VSTREAM_TYPE_SOCK);

	if (acl_msg_verbose)
		acl_msg_info("%s(%d)->%s: call acl_event_enable_read, "
			"status_fd = %d", __FILE__, __LINE__,
			myname, serv->status_fd[0]);

	acl_event_enable_read(acl_var_master_global_event,
		serv->status_read_stream, 0, master_status_event,
		(void *) serv);
}
Beispiel #4
0
static bool connect_server(acl::polarssl_conf* ssl_conf, IO_CTX* ctx, int id)
{
	// 开始异步连接远程服务器
	acl::aio_socket_stream* stream = acl::aio_socket_stream::open(
			ctx->handle, ctx->addr, ctx->connect_timeout);
	if (stream == NULL)
	{
		std::cout << "connect " << ctx->addr << " error!" << std::endl;
		std::cout << "stoping ..." << std::endl;
		if (id == 0)
			ctx->handle->stop();
		return false;
	}

	acl_non_blocking(stream->sock_handle(), ACL_BLOCKING);

	// 创建连接后的回调函数类
	client_io_callback* callback = new
		client_io_callback(stream, ssl_conf, ctx,  id);

	// 添加连接成功的回调函数类
	stream->add_open_callback(callback);

	// 添加连接失败后回调函数类
	stream->add_close_callback(callback);

	// 添加连接超时的回调函数类
	stream->add_timeout_callback(callback);

	return true;
}
Beispiel #5
0
socket_stream& socket_stream::set_tcp_non_blocking(bool on)
{
	ACL_SOCKET sock = sock_handle();
	if (sock == ACL_SOCKET_INVALID)
	{
		logger_error("invalid socket handle");
		return *this;
	}
	(void) acl_non_blocking(sock, on ? ACL_NON_BLOCKING : ACL_BLOCKING);

	return *this;
}
Beispiel #6
0
int acl_stream_connect(const char *path, int block_mode, int unused_timeout)
{
	const char *myname = "acl_stream_connect";

#ifdef ACL_FREEBSD
	path = path;
	block_mode = block_mode;
	unused_timeout = unused_timeout;

	acl_msg_fatal("%s(%d): not support!", myname, __LINE__);
	return -1;
#else
	int     pair[2];
	int     fifo;

	unused_timeout = unused_timeout;

	/*
	 * The requested file system object must exist, otherwise we can't reach
	 * the server.
	 */
	if ((fifo = open(path, O_WRONLY | O_NONBLOCK, 0)) < 0)
		return -1;

	/*
	 * Create a pipe, and send one pipe end to the server.
	 */
	if (pipe(pair) < 0)
		acl_msg_fatal("%s: pipe: %s", myname, acl_last_serror());
	if (ioctl(fifo, I_SENDFD, pair[1]) < 0)
		acl_msg_fatal("%s: send file descriptor: %s",
			myname, acl_last_serror());
	close(pair[1]);

	/*
	 * This is for {unix,inet}_connect() compatibility.
	 */
	if (block_mode == ACL_NON_BLOCKING)
		acl_non_blocking(pair[0], ACL_NON_BLOCKING);

	/*
	 * Cleanup.
	 */
	close(fifo);

	/*
	 * Keep the other end of the pipe.
	 */
	return pair[0];
#endif /* ACL_FREEBSD */
}
Beispiel #7
0
void ClientConnection::run()
{
    // 必须先将套接置为阻塞状态,否则接收者调用读时会立刻返回 -1
    acl_non_blocking(conn_->sock_handle(), ACL_BLOCKING);

    // 调用描述字发送过程将客户端套接字传给服务端
    if (ManagerTimer::transfer(this) == false)
        // 如果传输描述字失败,则加入待处理队列,由定时器
        // 进行处理
        ClientManager::get_instance().set(this);
    else
    {
        // 尝试从集合中删除
        ClientManager::get_instance().del(this);
        delete this;
    }
}
Beispiel #8
0
ACL_SOCKET acl_unix_listen(const char *addr, int backlog, int block_mode)
{
#undef sun
	struct sockaddr_un sun;
	int     len = strlen(addr);
	ACL_SOCKET  sock;
	char  tbuf[256];

	/*
	 * Translate address information to internal form.
	 */
	if (len >= (int) sizeof(sun.sun_path))
		acl_msg_fatal("unix-domain name too long: %s", addr);
	memset((char *) &sun, 0, sizeof(sun));
	sun.sun_family = AF_UNIX;
#ifdef HAS_SUN_LEN
	sun.sun_len = len + 1;
#endif
	memcpy(sun.sun_path, addr, len + 1);

	/*
	 * Create a listener socket. Do whatever we can so we don't run into
	 * trouble when this process is restarted after crash.
	 */
	if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == ACL_SOCKET_INVALID)
		acl_msg_fatal("socket: %s", acl_last_strerror(tbuf, sizeof(tbuf)));
	(void) unlink(addr);

	if (bind(sock, (struct sockaddr *) & sun, sizeof(sun)) < 0)
		acl_msg_fatal("bind: %s: %s", addr, acl_last_strerror(tbuf, sizeof(tbuf)));
#ifdef FCHMOD_UNIX_SOCKETS
	if (fchmod(sock, 0666) < 0)
		acl_msg_fatal("fchmod socket %s: %s", addr,
			acl_last_strerror(tbuf, sizeof(tbuf)));
#else
	if (chmod(addr, 0666) < 0)
		acl_msg_fatal("chmod socket %s: %s", addr,
			acl_last_strerror(tbuf, sizeof(tbuf)));
#endif
	acl_non_blocking(sock, block_mode);
	if (listen(sock, backlog) < 0)
		acl_msg_fatal("listen: %s", acl_last_strerror(tbuf, sizeof(tbuf)));
	return (sock);
}
Beispiel #9
0
bool master_service::on_accept(acl::aio_socket_stream* client)
{
    if (0)
        logger("connect from %s, fd %d", client->get_peer(true),
               client->sock_handle());

    acl_non_blocking(client->sock_handle(), ACL_BLOCKING);

    IConnection* conn;

    // 根据客户端连接服务端口号的不同来区分不同的服务应用协议
    const char* local = client->get_local(true);
    if (acl_strrncasecmp(local, var_cfg_backend_service,
                         strlen(var_cfg_backend_service)) == 0)
    {
        // 创建服务对象处理来自于后端服务模块的请求
        conn = new ServerConnection(client);
    }
    else if (acl_strrncasecmp(local, var_cfg_status_service,
                              strlen(var_cfg_status_service)) == 0)
    {
        const char* ip = client->get_peer();
        if (ip == NULL || *ip == 0)
        {
            logger_error("can't get peer ip");
            return false;
        }
        if (allow_list::get_instance().allow_manager(ip) == false)
        {
            logger_warn("deny manager ip: %s", ip);
            return false;
        }

        // 创建服务对象处理状态汇报的请求
        conn = new StatusConnection(client);
    }
    else
        // 创建对象处理来自于前端客户端模块的请求
        conn = new ClientConnection(client, var_cfg_conn_expired);

    conn->run();

    return true;
}
Beispiel #10
0
int main(void)
{
	const char *addr = "0.0.0.0:8089";
	ACL_VSTREAM *sstream = acl_vstream_listen(addr, 128);

	fiber_init();
	if (sstream == NULL) {
		printf("acl_vstream_listen error %s\r\n", acl_last_serror());
		return 1;
	}

	acl_non_blocking(ACL_VSTREAM_SOCK(sstream), ACL_NON_BLOCKING);

	printf("%s: call fiber_creater\r\n", __FUNCTION__);
	fiber_create(fiber_accept, sstream, 32768);
	printf("call fiber_schedule\r\n");
	fiber_schedule();

	return 0;
}
Beispiel #11
0
static int vstream_client(void)
{
	const char *myname = "vstream_client";
	ACL_VSTREAM *client;
	char  ebuf[256], buf[4096];
	int   n, dlen = 0;

	printf("addr: %s, timeout: %d\n", addr, timeout);
	client = acl_vstream_connect(addr, ACL_NON_BLOCKING, timeout, timeout, 1024);
	if (client == NULL) {
		printf("%s(%d): connect addr %s error(%s)\n",
			myname, __LINE__, addr, acl_last_strerror(ebuf, sizeof(ebuf)));
		return (-1);
	}

	printf("%s: connect %s ok\r\n", myname, addr);
	acl_non_blocking(ACL_VSTREAM_SOCK(client), ACL_BLOCKING);

	n = acl_write_wait(ACL_VSTREAM_SOCK(client), 10);
	if (n < 0) {
		printf("connect timeout: %s\n", acl_last_serror());
		goto END;
	}
	acl_vstream_fprintf(client, "hello world\n");
	while (1) {
		n = acl_vstream_read(client, buf, sizeof(buf));
		if (n == ACL_VSTREAM_EOF) {
			printf("read over: %s\n", acl_last_serror());
			break;
		}
		dlen += n;
		buf[n] = 0;
		printf("read reply: %s\n", buf);
	}

END:
	acl_vstream_close(client);
	printf("%s: read %d\n", myname, dlen);
	return (0);
}
Beispiel #12
0
ACL_VSTREAM *acl_vstream_listen_ex(const char *addr, int qlen,
	int block_mode, int io_bufsize, int io_timeout)
{
	const char *myname = "acl_vstream_listen_ex";
	ACL_SOCKET  listenfd;
	struct sockaddr_in local;
	ACL_VSTREAM *listen_stream;
	int   len;

	if (addr == 0 || *addr == 0 || qlen <= 0)
	{
		acl_msg_error("%s: input invalid", myname);
		return NULL;
	}

#ifdef	ACL_UNIX
	/* this maybe unix addr, such as '/home/test/listen.sock' */
	if (strchr(addr, '/') != NULL) {
		listenfd = acl_unix_listen(addr, qlen, 0);
		if (listenfd == ACL_SOCKET_INVALID)
			return NULL;
		acl_non_blocking(listenfd, block_mode);
		listen_stream = acl_vstream_fdopen(listenfd,
			ACL_VSTREAM_FLAG_RW, io_bufsize,
			io_timeout, ACL_VSTREAM_TYPE_LISTEN_UNIX);

		if (listen_stream == NULL) {
			acl_socket_close(listenfd);
			acl_msg_error("%s: open vstream error, addr(%s)",
				myname, addr);
			return NULL;
		}

		acl_vstream_set_local(listen_stream, addr);

		sprintf(listen_stream->errbuf, "+OK");
		return (listen_stream);
	}
#endif
	/* addr such as '192.168.0.1:80' */
	listenfd = acl_inet_listen(addr, qlen, block_mode);
	if (listenfd == ACL_SOCKET_INVALID) {
		acl_msg_error("%s: listen addr(%s) error(%s)",
			myname, addr, acl_last_serror());
		return NULL;
	}
	listen_stream = acl_vstream_fdopen(listenfd,
		ACL_VSTREAM_FLAG_RW, io_bufsize,
		io_timeout, ACL_VSTREAM_TYPE_LISTEN_INET);
	if (listen_stream == NULL) {
		acl_socket_close(listenfd);
		acl_msg_error("%s: open vstream error addr(%s)", myname, addr);
		return NULL;
	}

	memset(&local, 0, sizeof(local));
	len = (int) sizeof(struct sockaddr);
	if (getsockname(listenfd, (struct sockaddr*) &local,
		(socklen_t *) &len) < 0)
	{
		acl_msg_warn("%s: getsockname error(%s) for sock(%d)",
			myname, acl_last_serror(), listenfd);
		acl_vstream_set_local(listen_stream, addr);
	} else {
		char  ip[32], buf[64];
		int   port;

		acl_inet_ntoa(local.sin_addr, ip, sizeof(ip));
		port = ntohs(local.sin_port);
		snprintf(buf, sizeof(buf), "%s:%d", ip, port);
		acl_vstream_set_local(listen_stream, buf);
	}

	sprintf(listen_stream->errbuf, "+OK");
	return listen_stream;
}
Beispiel #13
0
ACL_SOCKET acl_inet_listen(const char *addr, int backlog, int block_mode)
{
	const char *myname = "acl_inet_listen";
	ACL_SOCKET sock;
	int   on, nport;
	char *buf, *host = NULL, *sport = NULL;
	const char *ptr;
	struct sockaddr_in sa;

	/*
	 * Translate address information to internal form.
	 */
	buf = acl_mystrdup(addr);
	ptr = acl_host_port(buf, &host, "", &sport, (char *) 0);
	if (ptr) {
		acl_msg_error("%s(%d): %s, %s invalid", myname, __LINE__, addr, ptr);
		acl_myfree(buf);
		return ACL_SOCKET_INVALID;
	}

	if (host && *host == 0)
		host = 0;
	if (host == NULL)
		host = "0.0.0.0";

	if (sport == NULL) {
		acl_msg_error("%s(%d): no port given from addr(%s)", myname, __LINE__, addr);
		acl_myfree(buf);
		return ACL_SOCKET_INVALID;
	}
	nport = atoi(sport);
	if (nport < 0) {
		acl_msg_error("%s: port(%d) < 0 invalid from addr(%s)",
			myname, nport, addr);
		acl_myfree(buf);
		return ACL_SOCKET_INVALID;
	}

	memset(&sa, 0, sizeof(sa));
	sa.sin_family      = AF_INET;
	sa.sin_port        = htons((short) nport);
	sa.sin_addr.s_addr = inet_addr(host);

	acl_myfree(buf);

	/* Create a listener socket. */
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock == ACL_SOCKET_INVALID) {
		acl_msg_error("%s: socket %s", myname, acl_last_serror());
		return ACL_SOCKET_INVALID;
	}

	on = 1;
	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
		(char *) &on, sizeof(on)) < 0)
	{
		acl_msg_error("%s: setsockopt(SO_REUSEADDR): %s",
			myname, acl_last_serror());
	}

	if (bind(sock, (struct sockaddr *) &sa, sizeof(struct sockaddr)) < 0) {
		acl_msg_error("%s: bind %s error %s",
			myname, addr, acl_last_serror());
		acl_socket_close(sock);
		return ACL_SOCKET_INVALID;
	}

	acl_non_blocking(sock, block_mode);

	if (listen(sock, backlog) < 0) {
		acl_msg_error("%s: listen error: %s, addr(%s)",
			myname, acl_last_serror(), addr);
		acl_socket_close(sock);
		return ACL_SOCKET_INVALID;
	}

	return sock;
}
Beispiel #14
0
void    acl_master_sigsetup(void)
{
	char   *myname = "acl_master_sigsetup";
	struct sigaction action;
	static int sigs[] = {
		SIGINT, SIGQUIT, SIGILL, SIGBUS, /* SIGSEGV, only for test */ SIGTERM,
	};
	unsigned i;

	sigemptyset(&action.sa_mask);
	action.sa_flags = 0;

	/*
	 * Prepare to kill our children
	 * when we receive any of the above signals.
	 */
	action.sa_handler = master_sigdeath;
	for (i = 0; i < sizeof(sigs) / sizeof(sigs[0]); i++)
		if (sigaction(sigs[i], &action, (struct sigaction *) 0) < 0)
			acl_msg_fatal("%s: sigaction(%d): %s",
				myname, sigs[i], strerror(errno));


#ifdef USE_SIG_PIPE
	if (pipe(acl_master_sig_pipe))
		acl_msg_fatal("pipe: %s", strerror(errno));
	acl_non_blocking(ACL_SIG_PIPE_WRITE_FD, ACL_NON_BLOCKING);
	acl_non_blocking(ACL_SIG_PIPE_READ_FD, ACL_NON_BLOCKING);
	acl_close_on_exec(ACL_SIG_PIPE_WRITE_FD, ACL_CLOSE_ON_EXEC);
	acl_close_on_exec(ACL_SIG_PIPE_READ_FD, ACL_CLOSE_ON_EXEC);

	ACL_SIG_PIPE_READ_STREAM = acl_vstream_fdopen(ACL_SIG_PIPE_READ_FD,
			O_RDONLY, acl_var_master_buf_size,
			acl_var_master_rw_timeout, ACL_VSTREAM_TYPE_SOCK);
	if (ACL_SIG_PIPE_READ_STREAM == NULL)
		acl_msg_fatal("%s(%d)->%s: acl_vstream_fdopen error=%s",
			__FILE__, __LINE__, myname, strerror(errno));

	if (acl_msg_verbose)
		acl_msg_info("%s(%d)->%s: call acl_event_enable_read, "
			"SIG_PIPE_READ_FD = %d", __FILE__, __LINE__, myname,
			ACL_SIG_PIPE_READ_FD);
	acl_event_enable_read(acl_var_master_global_event,
		ACL_SIG_PIPE_READ_STREAM, 0, master_sig_event, (void *) 0);
#endif

	/*
	 * Intercept SIGHUP (re-read config file) and SIGCHLD (child exit).
	 */
#ifdef SA_RESTART
	action.sa_flags |= SA_RESTART;
#endif
	action.sa_handler = master_sighup;
	if (sigaction(SIGHUP, &action, (struct sigaction *) 0) < 0)
		acl_msg_fatal("%s: sigaction(%d): %s",
			myname, SIGHUP, strerror(errno));

	action.sa_flags |= SA_NOCLDSTOP;
	action.sa_handler = master_sigchld;
	if (sigaction(SIGCHLD, &action, (struct sigaction *) 0) < 0)
		acl_msg_fatal("%s: sigaction(%d): %s",
			myname, SIGCHLD, strerror(errno));
}
Beispiel #15
0
int acl_fifo_listen(const char *path, int permissions, int block_mode)
{
	char   *myname = "acl_fifo_listen";
	char    buf[BUF_LEN], tbuf[256];
	static int open_mode = 0;
	struct stat st;
	int     fd;
	int     count;

	/*
	 * Create a named pipe (fifo). Do whatever we can so we don't run into
	 * trouble when this process is restarted after crash.  Make sure that
	 * we open a fifo and not something else, then change permissions to
	 * what we wanted them to be, because mkfifo() is subject to umask
	 * settings. Instead we could zero the umask temporarily before
	 * creating the FIFO, but that would cost even more system calls.
	 * Figure out if the fifo needs to be opened O_RDWR or O_RDONLY. Some
	 * systems need one, some need the other. If we choose the wrong mode,
	 * the fifo will stay readable, causing the program to go into a loop.
	 */
	if (unlink(path) && acl_last_error() != ENOENT) {
		acl_msg_error("%s: remove %s: %s", myname, path,
			acl_last_strerror(tbuf, sizeof(tbuf)));
		return -1;
	}
	if (mkfifo(path, permissions) < 0) {
		acl_msg_error("%s: create fifo %s: %s", myname, path,
			acl_last_strerror(tbuf, sizeof(tbuf)));
		return -1;
	}
	switch (open_mode) {
	case 0:
		if ((fd = open(path, O_RDWR | O_NONBLOCK, 0)) < 0) {
			acl_msg_error("%s: open %s: %s", myname, path,
				acl_last_strerror(tbuf, sizeof(tbuf)));
			return -1;
		}
		if (acl_readable(fd) == 0) {
			open_mode = O_RDWR | O_NONBLOCK;
			break;
		}

		open_mode = O_RDONLY | O_NONBLOCK;
		if (acl_msg_verbose)
			acl_msg_info("open O_RDWR makes fifo readable"
				" - trying O_RDONLY");
		(void) close(fd);
		if ((fd = open(path, open_mode, 0)) < 0) {
			acl_msg_error("%s: open %s: %s", myname, path,
				acl_last_strerror(tbuf, sizeof(tbuf)));
			return -1;
		}
		break;
	default:
		if ((fd = open(path, open_mode, 0)) < 0) {
			acl_msg_error("%s: open %s: %s", myname, path,
				acl_last_strerror(tbuf, sizeof(tbuf)));
			return -1;
		}
		break;
	}

	/*
	 * Make sure we opened a FIFO and skip any cruft that might have
	 * accumulated before we opened it.
	 */
	if (fstat(fd, &st) < 0) {
		acl_msg_error("%s: fstat %s: %s", myname, path,
			acl_last_strerror(tbuf, sizeof(tbuf)));
		close(fd);
		return -1;
	}
	if (S_ISFIFO(st.st_mode) == 0) {
		acl_msg_error("%s: not a fifo: %s", myname, path);
		close(fd);
		return -1;
	}
	if (fchmod(fd, permissions) < 0) {
		acl_msg_error("%s: fchmod %s: %s", myname, path,
			acl_last_strerror(tbuf, sizeof(tbuf)));
		close(fd);
		return -1;
	}
	acl_non_blocking(fd, block_mode);
	while ((count = acl_peekfd(fd)) > 0 && read(fd, buf,
		BUF_LEN < count ? BUF_LEN : count) > 0) {
	}

	return fd;
}