int gulm_connect_csid(const char *csid, struct local_client **newclient) { int fd; struct sockaddr_in6 addr; int status; int one = 1; DEBUGLOG("Connecting socket\n"); fd = socket(PF_INET6, SOCK_STREAM, 0); if (fd < 0) { syslog(LOG_ERR, "Unable to create new socket: %m"); return -1; } addr.sin6_family = AF_INET6; memcpy(&addr.sin6_addr, csid, GULM_MAX_CSID_LEN); addr.sin6_port = htons(tcp_port); DEBUGLOG("Connecting socket %d\n", fd); if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) < 0) { /* "Connection refused" is "normal" because clvmd may not yet be running * on that node. */ if (errno != ECONNREFUSED) { syslog(LOG_ERR, "Unable to connect to remote node: %m"); } DEBUGLOG("Unable to connect to remote node: %s\n", strerror(errno)); close(fd); return -1; } /* Set Close-on-exec */ fcntl(fd, F_SETFD, 1); setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(int)); status = alloc_client(fd, csid, newclient); if (status) close(fd); else add_client(*newclient); /* If we can connect to it, it must be running a clvmd */ gulm_add_up_node(csid); return status; }
/* Read on main comms (listen) socket, accept it */ int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, const char *csid, struct local_client **new_client) { int newfd; struct sockaddr_in6 addr; socklen_t addrlen = sizeof(addr); int status; char name[GULM_MAX_CLUSTER_MEMBER_NAME_LEN]; DEBUGLOG("cluster_fd_callback\n"); *new_client = NULL; newfd = accept(listen_fd, (struct sockaddr *)&addr, &addrlen); DEBUGLOG("cluster_fd_callback, newfd=%d (errno=%d)\n", newfd, errno); if (!newfd) { syslog(LOG_ERR, "error in accept: %m"); errno = EAGAIN; return -1; /* Don't return an error or clvmd will close the listening FD */ } /* Check that the client is a member of the cluster and reject if not. */ if (gulm_name_from_csid((char *)&addr.sin6_addr, name) < 0) { syslog(LOG_ERR, "Got connect from non-cluster node %s\n", print_csid((char *)&addr.sin6_addr)); DEBUGLOG("Got connect from non-cluster node %s\n", print_csid((char *)&addr.sin6_addr)); close(newfd); errno = EAGAIN; return -1; } status = alloc_client(newfd, (char *)&addr.sin6_addr, new_client); if (status) { DEBUGLOG("cluster_fd_callback, alloc_client failed, status = %d\n", status); close(newfd); /* See above... */ errno = EAGAIN; return -1; } DEBUGLOG("cluster_fd_callback, returning %d, %p\n", newfd, *new_client); return newfd; }
CAMLprim value stub_asl_open(value ident, value facility, value stderr, value no_delay, value no_remote) { CAMLparam5(ident, facility, stderr, no_delay, no_remote); const char *c_ident = String_val(ident); const char *c_facility = String_val(facility); uint32_t options = (Bool_val(stderr)?ASL_OPT_STDERR:0) | (Bool_val(no_delay)?ASL_OPT_NO_DELAY:0) | (Bool_val(no_remote)?ASL_OPT_NO_REMOTE:0); aslclient asl = NULL; caml_release_runtime_system(); asl = asl_open(c_ident, c_facility, options); caml_acquire_runtime_system(); CAMLreturn(alloc_client(asl)); }
/* * Create a new struct Client structure and set it to initial state. * * from == NULL, create local client (a client connected to a socket). * * from != NULL, create remote client (behind a socket associated with * the client defined by 'from'). * ('from' is a local client!!). */ struct Client* make_client(struct Client *from, int status) { struct Client* cptr = 0; struct Connection* con = 0; assert(!from || cli_verify(from)); cptr = alloc_client(); assert(0 != cptr); assert(!cli_magic(cptr)); assert(0 == from || 0 != cli_connect(from)); if (!from) { /* local client, allocate a struct Connection */ con = alloc_connection(); assert(0 != con); assert(!con_magic(con)); con_magic(con) = CONNECTION_MAGIC; con_fd(con) = -1; /* initialize struct Connection */ con_freeflag(con) = 0; con_nextnick(con) = CurrentTime - NICK_DELAY; con_nexttarget(con) = CurrentTime - (TARGET_DELAY * (STARTTARGETS - 1)); con_handler(con) = UNREGISTERED_HANDLER; con_client(con) = cptr; cli_local(cptr) = 1; /* Set certain fields of the struct Client */ cli_since(cptr) = cli_lasttime(cptr) = cli_firsttime(cptr) = CurrentTime; cli_lastnick(cptr) = TStime(); } else con = cli_connect(from); /* use 'from's connection */ assert(0 != con); assert(con_verify(con)); cli_magic(cptr) = CLIENT_MAGIC; cli_connect(cptr) = con; /* set the connection and other fields */ cli_status(cptr) = status; cli_hnext(cptr) = cptr; strcpy(cli_username(cptr), "unknown"); return cptr; }
static void new_client(evutil_socket_t lsn_fd, short event, void *arg) { struct event_base *ev_base = (struct event_base *)arg; struct sockaddr_in clt_addr; socklen_t addr_len = sizeof(clt_addr); int fd = accept(lsn_fd, (struct sockaddr*)&clt_addr, &addr_len); if (fd == -1) { logging("accept new client error %s", strerror(errno)); return; } int id = alloc_client(); if (id == -1) { logging("clients is already full"); return; } strcpy(AllChannels[id]._peer_ip, inet_ntoa(clt_addr.sin_addr)); evutil_make_socket_nonblocking(fd); AllChannels[id]._bev = bufferevent_socket_new(ev_base, fd, BEV_OPT_CLOSE_ON_FREE); bufferevent_setcb(AllChannels[id]._bev, readcb, NULL, errorcb, (void *)(intptr_t)id); bufferevent_enable(AllChannels[id]._bev, EV_READ|EV_WRITE); }
CAMLprim value stub_asl_open_null(){ CAMLparam0(); CAMLreturn(alloc_client(NULL)); }
int main(void) { int i; int ifd; int len; int client_sock; struct online_user *user; Client client; struct sockaddr_in client_name; int client_name_len = sizeof(client_name); #define MAX_BUFSIZE 0x100000 char buf[MAX_BUFSIZE]; struct format *package = (struct format *)buf; tcp_server_sock = tcp_startup(SERVER_TCP_PORT); init_mysql(); register_ctrl_c(); kdpfd = epoll_create(MAXEPOLLSIZE); /* 设置要监听的事件。EPOLLIN 表示可读,EPOLLET则指定电平触发 */ ev.events = EPOLLIN; ev.data.fd = tcp_server_sock; if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, tcp_server_sock, &ev) < 0) /* 把 tcp sock 加入监听集合,以便接收连接请求 */ error_die("tcp epoll_ctl\n"); /* 记录监听的文件数,同时他也是 epoll_wait 的第三个参数。 因为内核需要知道 events 数组的有效数据有多长 */ curfds = 1; for (;;) { memset(buf,0,sizeof(buf)); printf("waiting...\n"); /* 等待有事件发生。该函数的返回值存放在 nfds 和 events 内 */ nfds = epoll_wait(kdpfd, events, curfds, -1); if (nfds < 0) error_die("epoll_wait"); for (i = 0; i < nfds; i++) { ifd = events[i].data.fd; if (ifd == tcp_server_sock) { //新的 TCP 连接请求到来 if (!(events[i].events & EPOLLIN)) error_die("failed to event is not EPOLLIN\n"); client_sock = accept(tcp_server_sock,(struct sockaddr *)&client_name,&client_name_len); setnonblocking(client_sock); ev.events = EPOLLIN; ev.data.fd = client_sock; if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, client_sock, &ev) < 0) error_die("epoll_ctl"); curfds++; client = alloc_client(client_sock); add_client(client); } else if ((events[i].events & EPOLLIN)) { /* 客户端有数据发来(POLLIN)或者发生 POLLHUP/POLLERR(这两个事件系统会自动监听) */ client = find_client(ifd); if (client != NULL && client->handler != NULL) { //已经有了处理函数,直接调用这个函数来处理 client->handler(ifd,client->private); } else { //默认的处理方法 //读入数据包头部。 len = read(ifd,package,(sizeof(struct format)-sizeof(package->data))); if (len <= 0) { //对方断线。 close_connect(ifd); continue; } if (package->length >= MAX_BUFSIZE || package->length <= 0) { while(read(ifd,package->data,4) > 0); continue; } if ((len = read(ifd,package->data,package->length) <= 0)) { //读入数据包内容 close_connect(ifd); continue; } // 处理数据 if (handle(ifd,package) == NEED_WRITE) { ev.events = EPOLLOUT; ev.data.fd = ifd; epoll_ctl(kdpfd,EPOLL_CTL_MOD,ifd,&ev); } } } else if(events[i].events & EPOLLOUT) {