int socket_initialize() { mastersockfd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); clientsockfd=-1; int yes=1; memset(&sock,0,sizeof(sock)); sock.sin_port=htons(tcpport); sock.sin_family=AF_INET; setsockopt(mastersockfd,SOL_SOCKET, SO_REUSEADDR,&yes,sizeof(yes)); if (bind(mastersockfd,(struct sockaddr*)&sock,sizeof(struct sockaddr_in))<0) { abort(); } printf("UART: Serial TCP listening on %d\n",tcpport); /*printf("Waiting for TCP connection. Simulation is halted until you connect.\n"); printf("Try 'telnet localhost %d' for a connection.\n",tcpport); */ listen(mastersockfd,1); poll_add(mastersockfd, POLL_IN, &uart_incoming_connection); /* if ((fd=accept(mastersockfd,(struct sockaddr*)&clientsock,&clientsocksize))<0){ perror("accept"); abort(); } poll_add(fd, POLL_IN, &uart_incoming_data); */ return 0; }
int parent_main(pid_t child_pid) { int kq; int status; sigset_t sigs; if (sigfillset(&sigs) == -1) { ERRMSG("sigfillset() failed"); goto kill_child; } if (sigprocmask(SIG_SETMASK, &sigs, NULL) == -1) { ERRMSG("sigprocmask() failed"); goto kill_child; } if ((kq = kqueue()) == -1) { ERRMSG("kqueue() failed"); goto kill_child; } if (poll_add(kq, STDIN_FILENO, EVFILT_READ) == -1) { ERRMSG("poll_add() failed"); goto kill_child; } for (;;) { int i; enum HANDLE_RESULT handle_ret = IGNORE; struct kevent e[2]; struct timespec timeout; timeout.tv_sec = 0; timeout.tv_nsec = 100 * 1000 * 1000; // 100ms int nfd = kevent(kq, NULL, 0, e, sizeof(e) / sizeof(struct kevent), &timeout); if (nfd == -1) { ERRMSG("kevent() failed"); goto kill_child; } if (nfd == 0) { int ret = waitpid(child_pid, &status, WNOHANG); if (ret == -1) { ERRMSG("waitpid() failed"); goto kill_child; } if (ret != 0) { goto child_exited; } if (sigpending(&sigs) == -1) { ERRMSG("sigpending() failed"); goto kill_child; } handle_ret = handle_signal(&sigs, child_pid); } for (i = 0; i < nfd; i++) { int fd = e[i].ident; if (fd == STDIN_FILENO) { if (e[i].flags & EV_EOF) { handle_ret = handle_in_eof(fd, child_pid); } } } switch(handle_ret) { case KILL_CHILD: goto kill_child; case WAIT_CHILD_EXIT: goto wait_child_exit; case IGNORE: break; } } kill_child: if (kill(child_pid, SIGKILL) == -1) { ERR_EXIT("kill() failed"); } wait_child_exit: if (waitpid(child_pid, &status, 0) == -1) { ERR_EXIT("waitpid() failed"); } child_exited: if (WIFEXITED(status)) { return WEXITSTATUS(status); } if (WIFSIGNALED(status)) { return WTERMSIG(status) + 128; } return 1; }
// on reprot accept, for server // ns is the struct of server static int net_socket_report_accept(struct net_pool* np, struct net_socket* ns) { log_debug("net_socket_report_accept ...\n"); union sockaddr_all u; socklen_t len = sizeof(u); int clientfd = accept(ns->fd, &u.s, &len); if(clientfd < 0) { np->onerror(np, ns->id, 2); // accept error log_error("accept failure %d", ns->id); return -1; } socket_keepalive(clientfd); poll_setnonblocking(clientfd); // when accept a new client, need to judge the count of online clients is reach the limit // so do not add the new clientfd to eventfd struct net_socket* nstmp = net_socket_new(np, clientfd, false); if(nstmp == NULL) { socket_close(clientfd); np->onerror(np, ns->id, 3);// new socket failure log_error("new socket error %d", ns->id); return -2; // new socket error } // TODO: do some judgement, such as the online number limit // add clientfd to eventfd if(poll_add(np->eventfd, clientfd, nstmp)) { socket_close(clientfd); nstmp->status = SOCKET_STATUS_INVALID; np->onerror(np, ns->id, 4); // add to eventfd failure log_error("report accept , poll add"); return -3; } nstmp->status = SOCKET_STATUS_CONNECTED; void* sin_addr = (u.s.sa_family == AF_INET) ?((void*)&u.v4.sin_addr) :((void*)&u.v6.sin6_addr); inet_ntop(u.s.sa_family, sin_addr, nstmp->info, sizeof(nstmp->info)); np->onaccept(np, ns->id, nstmp->id); log_debug("the new client fd : %d\n", clientfd); return 0; }
int kill_and_wait_sigchild(pid_t child_pid, int signal, uint32_t timeout_seconds) { if (kill(child_pid, signal) == -1) { ERRMSG("kill() failed"); return -1; } int kq; if ((kq = kqueue()) == -1) { ERRMSG("kqueue() failed"); return -1; } if (poll_add(kq, SIGCHLD, EVFILT_SIGNAL) == -1) { ERRMSG("poll_add() failed"); close(kq); return -1; } struct timespec timeout; timeout.tv_sec = timeout_seconds; timeout.tv_nsec = 0; if (kevent(kq, NULL, 0, NULL, 0, &timeout) == -1) { ERRMSG("kevent() failed"); close(kq); return -1; } close(kq); return 0; }
int uart_incoming_connection(short event) { int yes=1; socklen_t clientsocksize=sizeof(struct sockaddr_in); if ((clientsockfd=accept(mastersockfd,(struct sockaddr*)&clientsock,&clientsocksize))<0){ perror("accept"); abort(); } fprintf(stderr,"UART: incoming connection\n"); uartescape=0; setsockopt(clientsockfd,SOL_SOCKET, TCP_NODELAY, &yes,sizeof(yes)); poll_add(clientsockfd, POLL_IN, &uart_incoming_data); return 0; }
// new a net socket node // the add parametic means that let fd add to eventfd immediately or not static struct net_socket* net_socket_new(struct net_pool* np, int fd, bool add) { log_debug("net_socket_new\n"); // judge the capacity is full or not if(np->count >= np->cap) { net_expand(np); } // get the unique id for fd int id = reserve_id(np); if(id < 0) { log_error("reserve id failure"); return NULL; } struct net_socket* ns = np->ns[id % np->cap]; // TODO: use assert? // assert(ns->status == SOCKET_STATUS_RESERVE); if(ns->status != SOCKET_STATUS_RESERVE) { log_error("get allocid failure"); return NULL; } // add to eventfd or not if(add) { if(poll_add(np->eventfd, fd, ns)) { log_error("add fd to eventfd failure"); ns->status = SOCKET_STATUS_INVALID; return NULL; } } ns->fd = fd; np->count++; log_debug("[current client count] : %d\n", np->count); return ns; }
void server_process(struct pollfd *fds, int num) { int i = 0; for(i = 0; i < server_max_pollfd; ++i) { if(fds[i].revents == 0) { continue; } if(fds[i].fd == sock_fd) { if(fds[i].revents & POLLIN) { int data_fd; struct sockaddr_in clnt; int clnt_len = sizeof(clnt); memset(&clnt, 0, sizeof(clnt)); if((data_fd = accept(sock_fd, (struct sockaddr*)&clnt, &clnt_len)) < 0) { perror("accept"); } char clnt_addr[16] = ""; inet_ntop(AF_INET, &clnt.sin_addr, clnt_addr, sizeof(clnt_addr)); printf("[%s] connected\n", clnt_addr); poll_add(data_fd); } if(fds[i].revents & POLLERR) { printf("error occured\n"); } if(fds[i].revents & POLLNVAL) { printf("invalid request\n"); } } else { if(fds[i].revents & POLLIN) { char clnt_addr[16] = ""; struct sockaddr_in clnt; int clnt_len = sizeof(clnt); if(getpeername(fds[i].fd, (struct sockaddr*)&clnt, &clnt_len) < 0) { perror("getpeername"); } inet_ntop(AF_INET, &clnt.sin_addr, clnt_addr, sizeof(clnt_addr)); int recv_data = 0; int recv_cnt = 0; recv_cnt = recv(fds[i].fd, &recv_data, sizeof(recv_data), 0); if(recv_cnt > 0) { printf("receive [%d] from [%s]\n", recv_data, clnt_addr); } else if(recv_cnt == 0) { printf("[%s] disconnected\n\n", clnt_addr); close(fds[i].fd); poll_remove(i); } else if(recv_cnt == -1) { perror("recv"); } } if(fds[i].revents & POLLOUT) { printf("ready to write data\n"); } if(fds[i].revents & POLLERR) { printf("error occured\n"); } if(fds[i].revents & POLLNVAL) { printf("invalid request\n"); } if(fds[i].revents & POLLHUP) { printf("pollhup\n"); } if(fds[i].revents & POLLRDHUP) { printf("pollrdhup\n"); } } } }