ACL_MBOX *acl_mbox_create(void) { ACL_MBOX *mbox; ACL_SOCKET fds[2]; if (acl_sane_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { acl_msg_error("%s(%d), %s: acl_duplex_pipe error %s", __FILE__, __LINE__, __FUNCTION__, acl_last_serror()); return NULL; } mbox = (ACL_MBOX *) acl_mymalloc(sizeof(ACL_MBOX)); mbox->in = acl_vstream_fdopen(fds[0], O_RDONLY, sizeof(__key), 0, ACL_VSTREAM_TYPE_SOCK); mbox->out = acl_vstream_fdopen(fds[1], O_WRONLY, sizeof(__key), 0, ACL_VSTREAM_TYPE_SOCK); mbox->nsend = 0; mbox->nread = 0; mbox->ypipe = acl_ypipe_new(); mbox->lock = (acl_pthread_mutex_t *) acl_mycalloc(1, sizeof(acl_pthread_mutex_t)); if (acl_pthread_mutex_init(mbox->lock, NULL) != 0) acl_msg_fatal("%s(%d), %s: acl_pthread_mutex_init error", __FILE__, __LINE__, __FUNCTION__); return mbox; }
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); }
int main(int unused_argc, char **unused_argv) { char myname[] = "main"; ACL_WATCHDOG *wp; ACL_VSTREAM *vp; char buf[256] = "test before"; unused_argc = unused_argc; unused_argv = unused_argv; acl_msg_verbose = 2; printf("buf=%s\n", buf); vp = acl_vstream_fdopen(0, 0, 0600, 4096, 0); if (vp == NULL) acl_msg_fatal("%s(%d)->%s: vstream_fdopen err %s", __FILE__, __LINE__, myname, strerror(errno)); wp = acl_watchdog_create(10, __watchdog_fn, (char *) buf); acl_watchdog_start(wp); while (acl_vstream_gets_nonl(vp, buf, sizeof(buf) - 1) != ACL_VSTREAM_EOF) { acl_msg_info(">>> your input:%s", buf); if (strcasecmp(buf, "quit") == 0 || strcasecmp(buf, "exit") == 0) break; acl_watchdog_pat(); } acl_watchdog_destroy(wp); exit (0); }
void stream::open_stream(void) { if (stream_ != NULL) return; stream_ = acl_vstream_fdopen(ACL_SOCKET_INVALID, O_RDWR, 8192, 0, ACL_VSTREAM_TYPE_SOCK); }
void stream::open_stream(bool is_file /* = false */) { if (stream_ != NULL) return; stream_ = acl_vstream_fdopen(ACL_SOCKET_INVALID, O_RDWR, 8192, 0, is_file ? ACL_VSTREAM_TYPE_FILE : ACL_VSTREAM_TYPE_SOCK); }
bool socket_stream::open(ACL_SOCKET fd) { ACL_VSTREAM* conn = acl_vstream_fdopen(fd, O_RDWR, 8192, 0, ACL_VSTREAM_TYPE_SOCK); acl_assert(conn); return open(conn); }
int acl_unix_trigger(ACL_EVENT *event, const char *service, const char *buf, int len, int timeout) { const char *myname = "acl_unix_trigger"; struct ACL_UNIX_TRIGGER *up; ACL_SOCKET fd; if (acl_msg_verbose > 0) acl_msg_info("%s: service %s", myname, service); /* * Connect... */ if ((fd = acl_unix_connect(service, ACL_BLOCKING, timeout)) < 0) { if (acl_msg_verbose) acl_msg_warn("%s: connect to %s: %s", myname, service, strerror(errno)); return -1; } acl_close_on_exec(fd, ACL_CLOSE_ON_EXEC); /* * Stash away context. */ up = (struct ACL_UNIX_TRIGGER *) acl_mymalloc(sizeof(*up)); up->service = acl_mystrdup(service); up->stream = acl_vstream_fdopen(fd, O_RDWR, 4096, timeout, ACL_VSTREAM_TYPE_LISTEN_UNIX); /* * Write the request... */ if (acl_vstream_writen(up->stream, buf, len) < 0 || acl_vstream_writen(up->stream, "", 1) < 0) { if (acl_msg_verbose) acl_msg_warn("%s: write to %s: %s", myname, service, strerror(errno)); } /* * Wakeup when the peer disconnects, or when we lose patience. */ #ifdef __USE_TIMER if (timeout > 0) acl_event_request_timer(event, acl_unix_trigger_timer, (void *) up, (timeout + 100) * 1000000); acl_event_enable_read(event, up->stream, 0, acl_unix_trigger_event, (void *) up); #else if (timeout > 0) acl_event_enable_read(event, up->stream, timeout + 100, acl_unix_trigger_event, (void *) up); else acl_event_enable_read(event, up->stream, 0, acl_unix_trigger_event, (void *) up); #endif return 0; }
bool socket_stream::open(ACL_SOCKET fd, bool udp_mode /* = false */) { ACL_VSTREAM* conn = acl_vstream_fdopen(fd, O_RDWR, 8192, 0, ACL_VSTREAM_TYPE_SOCK); acl_assert(conn); return open(conn, udp_mode); }
acl_int64 gid_cmdline_get(int fd, const char *tag, int *errnum) { acl_int64 gid; ACL_VSTREAM *client = acl_vstream_fdopen(fd, 0, 1024, var_gid_rw_timeout, ACL_VSTREAM_TYPE_SOCK); gid = gid_cmdline_next(client, tag, errnum); acl_vstream_free(client); return (gid); }
int acl_inet_trigger(ACL_EVENT *eventp, const char *service, const char *buf, int len, int timeout) { const char *myname = "acl_inet_trigger"; struct ACL_INET_TRIGGER *ip; int fd; if (acl_msg_verbose > 1) acl_msg_info("%s: service %s", myname, service); /* * Connect... */ if ((fd = acl_inet_connect(service, ACL_BLOCKING, timeout)) < 0) { if (acl_msg_verbose) acl_msg_warn("%s: connect to %s: %s", myname, service, strerror(errno)); return (-1); } acl_close_on_exec(fd, ACL_CLOSE_ON_EXEC); /* * Stash away context. */ ip = (struct ACL_INET_TRIGGER *) acl_mymalloc(sizeof(*ip)); ip->fd = fd; ip->service = acl_mystrdup(service); ip->stream = acl_vstream_fdopen(fd, O_RDWR, 4096, timeout, ACL_VSTREAM_TYPE_LISTEN_INET); ip->eventp = eventp; /* * Write the request... */ if (acl_write_buf(fd, buf, len, timeout) < 0 || acl_write_buf(fd, "", 1, timeout) < 0) { if (acl_msg_verbose) acl_msg_warn("%s: write to %s: %s", myname, service, strerror(errno)); } /* * Wakeup when the peer disconnects, or when we lose patience. */ if (timeout > 0) acl_event_enable_read(ip->eventp, ip->stream, timeout + 100, acl_inet_trigger_event, (void *) ip); else acl_event_enable_read(ip->eventp, ip->stream, 0, acl_inet_trigger_event, (void *) ip); return (0); }
void acl_master_vars_init(int buf_size, int rw_timeout) { const char *myname = "acl_master_vars_init"; if (ACL_MASTER_STAT_STREAM != NULL) acl_vstream_free(ACL_MASTER_STAT_STREAM); if (ACL_MASTER_FLOW_READ_STREAM != NULL) acl_vstream_free(ACL_MASTER_FLOW_READ_STREAM); if (ACL_MASTER_FLOW_WRITE_STREAM != NULL) acl_vstream_free(ACL_MASTER_FLOW_WRITE_STREAM); ACL_MASTER_STAT_STREAM = acl_vstream_fdopen(ACL_MASTER_STATUS_FD, O_RDWR, buf_size, rw_timeout, ACL_VSTREAM_TYPE_SOCK); ACL_MASTER_FLOW_READ_STREAM = acl_vstream_fdopen(ACL_MASTER_FLOW_READ, O_RDONLY, buf_size, rw_timeout, ACL_VSTREAM_TYPE_SOCK); ACL_MASTER_FLOW_WRITE_STREAM = acl_vstream_fdopen(ACL_MASTER_FLOW_WRITE, O_WRONLY, buf_size, rw_timeout, ACL_VSTREAM_TYPE_SOCK); if (acl_var_master_thread_pool == NULL) acl_var_master_thread_pool = acl_thread_pool_create(100, 60); if (acl_var_master_thread_pool == NULL) acl_msg_fatal("%s(%d): create thread pool error(%s)", myname, __LINE__, strerror(errno)); }
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; }
ACL_VSTREAM *acl_vstream_accept_ex(ACL_VSTREAM *listen_stream, ACL_VSTREAM *client_stream, char *addr, int size) { const char *myname = "acl_vstream_accept_ex"; ACL_SOCKET connfd = ACL_SOCKET_INVALID; ACL_SOCKET servfd = ACL_VSTREAM_SOCK(listen_stream); char buf[256]; if ((listen_stream->type & ACL_VSTREAM_TYPE_LISTEN_INET)) { #ifdef WIN32 if (!(listen_stream->type & ACL_VSTREAM_TYPE_LISTEN_IOCP)) connfd = acl_inet_accept_ex(servfd, buf, sizeof(buf)); else if (listen_stream->iocp_sock == ACL_SOCKET_INVALID) return NULL; else { int ret; connfd = listen_stream->iocp_sock; listen_stream->iocp_sock = ACL_SOCKET_INVALID; /* iocp 方式下,需调用下面过程以允许调用 * getpeername/getsockname */ ret = setsockopt(connfd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&servfd, sizeof(servfd)); buf[0] = 0; if (ret != SOCKET_ERROR) acl_getpeername(connfd, buf, sizeof(buf)); } #else connfd = acl_inet_accept_ex(servfd, buf, sizeof(buf)); #endif if (connfd != ACL_SOCKET_INVALID && addr != NULL && size > 0) ACL_SAFE_STRNCPY(addr, buf, size); #ifdef ACL_UNIX } else if ((listen_stream->type & ACL_VSTREAM_TYPE_LISTEN_UNIX)) { connfd = acl_unix_accept(servfd); if (acl_getpeername(connfd, buf, sizeof(buf)) < 0) buf[0] = 0; if (addr) ACL_SAFE_STRNCPY(addr, buf, size); #endif } else acl_msg_fatal("%s(%d)->%s: invalid listen stream(%d)", __FILE__, __LINE__, myname, listen_stream->flag); if (connfd == ACL_SOCKET_INVALID) return NULL; if (client_stream != NULL) { acl_vstream_reset(client_stream); ACL_VSTREAM_SET_SOCK(client_stream, connfd); } else { client_stream = acl_vstream_fdopen(connfd, ACL_VSTREAM_FLAG_RW, (int) listen_stream->read_buf_len, listen_stream->rw_timeout, ACL_VSTREAM_TYPE_SOCK); /* 让 client_stream 的 context 成员继承 listen_stream 的 * context 成员变量. */ client_stream->context = listen_stream->context; } if (client_stream == NULL) return NULL; acl_vstream_set_peer(client_stream, buf); return client_stream; }
static module_service_main_fn __service_callback = NULL; /* 某个线程服务实例接收到一个新的远程客户端连接请求 */ static int msg_ipc_accept(int msg_type acl_unused, ACL_MSGIO *mio acl_unused, const ACL_MSGIO_INFO *info, void *arg) { IPC_CTX ctx; ACL_VSTREAM *stream; ACL_ASTREAM *client; SERVICE *service = (SERVICE*) arg; memcpy(&ctx, acl_vstring_str(info->body.buf), ACL_VSTRING_LEN(info->body.buf)); /* 打开异步流 */ stream = acl_vstream_fdopen(ctx.fd, O_RDWR, var_cfg_aio_buf_size, 0, ACL_VSTREAM_TYPE_SOCK); client = acl_aio_open(ctx.aio, stream); /* 开始处理该客户端连接 */ __service_callback(service, client); return (0); } /* 单线程实例非阻塞处理过程 */ static void *service_thread(void *arg) { ACL_MSGIO *ipc_client = (ACL_MSGIO*) arg; ACL_AIO *aio = acl_msgio_aio(ipc_client); /* 内存垃圾回收定时器 */
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)); }