/* listen status packet */ int status_conn_init() { struct epoll_event ev; listen_fd = service(STATUS, ACCEPT); if (listen_fd < 0) { stat_dbg("listen fd error\n"); return -1; } epfd = epoll_create(MAX_EVENTS); if (epfd == -1) { stat_err("epoll_create error\n"); return -1; } ev.events = EPOLLIN; ev.data.fd = listen_fd; if (epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd, &ev) == -1) { stat_err("epoll_ctl error: listen_fd\n"); return -1; } return 0; }
bool stat_evt_http_req(struct client *cli, unsigned int events, bool *invalidate_cli) { struct http_req *req = &cli->req; char *method = req->method; // char *content_len_str; char *path = NULL; // int rc; bool rcb; char *root = (char *) "/"; /* grab useful headers */ // content_len_str = hreq_hdr(req, "content-length"); path = strdup(req->uri.path); if (!path) path = root; if (debugging) applog(LOG_INFO, "%s: status method %s, path '%s'", cli->addr_host, method, path); /* no matter whether error or not, this is our next state. * the main question is whether or not we will go immediately * into it (return true) or wait for writes to complete (return * false). * * the operations below may override this next-state setting, * however. */ if (hreq_http11(req)) cli->state = evt_recycle; else cli->state = evt_dispose; if (!strcmp(method, "GET")) { if (!strcmp(path, "/")) { rcb = stat_root(cli); } else { rcb = stat_err(cli, InvalidURI); } } else { rcb = stat_err(cli, InvalidArgument); } if (path != root); free(path); return rcb; }
/* init status cache list */ int status_list_init() { int i, cache_size, map_size, fd, init = 0; char *mapmem; cache_size = MAX_ONLINE_USER * sizeof(struct status_info); map_size = (MAX_USER + 1) * sizeof(void *); /* check whether file exist, if not, create one and set init = 1 */ if (access(STAT_FILE, 0) < 0) { fd = open(STAT_FILE, O_CREAT | O_RDWR | O_TRUNC, 0666); lseek(fd, cache_size + map_size - 1, SEEK_SET); write(fd, "", 1); init = 1; } else fd = open(STAT_FILE, O_RDWR, 0666); mapmem = mmap(NULL, cache_size + map_size, PROT_READ | PROT_WRITE, \ MAP_SHARED, fd, 0); if (mapmem == MAP_FAILED) { stat_err("mmap failed\n"); return -1; } map = (struct status_info **)mapmem; cache = (struct status_info*)(mapmem + map_size); close(fd); if (init) memset(mapmem, 0, map_size + cache_size); INIT_LIST_HEAD(&free_list_head); for (i = 0; i < MAX_ONLINE_USER; i++) list_add(&cache[i].node, &free_list_head); return 0; }
void main() #endif { int client_fd ,tmpfd; //file descriptor int nfds, left, size, i; struct epoll_event ev, events[MAX_EVENTS]; struct sockaddr_in client_addr; struct packet *inpack, *outpack; inpack = malloc(MAX_PACKET_LEN); outpack = malloc(MAX_PACKET_LEN); if (!(inpack && outpack)) { stat_err("malloc error"); return; } memset(&client_addr, 0, sizeof(client_addr)); size = sizeof(struct sockaddr_in); stat_dbg("Status start: %d\n", getpid()); /* init the free cache list */ if (status_list_init()) { stat_dbg("status_list_init failed !\n"); goto exit; } /* init the network connection */ if (status_conn_init()) { stat_dbg("Status connection init failed !\n"); goto exit; } stat_dbg("==> Status listened\n"); for (;;) { nfds = epoll_wait(epfd, events, MAX_EVENTS, -1); if (nfds == -1) { stat_err("************* epoll_wait error *************\n"); goto exit; } for (i = 0; i < nfds; i++) { tmpfd = events[i].data.fd; /* new connection */ if (tmpfd == listen_fd) { client_fd = accept(listen_fd, (struct sockaddr *)&client_addr, &size); if (client_fd < 0) { stat_err("accept error\n"); goto exit; } stat_dbg("<== client %s, port %d connected\n", inet_ntoa(client_addr.sin_addr),\ ntohs(client_addr.sin_port)); ev.events = EPOLLIN; ev.data.fd = client_fd; if (epoll_ctl(epfd, EPOLL_CTL_ADD, client_fd, &ev) == -1) { stat_err("epoll_ctl: add error\n"); goto exit; } continue; } /* recieve a packet */ if (events[i].events & EPOLLIN) { stat_dbg("<======= A Packet Arrive! =======>\n"); if (tmpfd < 0) { stat_dbg("tmpfd(%d) < 0\n", tmpfd); continue; } if (packet_read(tmpfd, (char *)inpack, PACKET_HEADER_LEN, epfd)) continue; else { stat_dbg("PACKET: len %d, cmd %04x, uin %d\n", inpack->len, inpack->cmd, \ inpack->uin); left = inpack->len - PACKET_HEADER_LEN; if (left > 0) { stat_dbg("packet left %d bytes to read\n", left); if (packet_read(tmpfd, inpack->params, left, epfd)) continue; } /* packet processing */ status_packet(inpack, outpack, tmpfd); } } } } exit: stat_dbg("STATUS Exit\n"); free(cache); free(inpack); free(outpack); }