void run_thread(struct message *info) { struct sockaddr_in client_address ; socklen_t client_length ; client_length = sizeof(client_address); void error(const char *msg) ; int new_socket_fd = accept(info->socket_fd, (struct sockaddr *) &client_address, &client_length); if (new_socket_fd < 0) { error("error on accept new socket!"); } int pid = fork(); if (pid < 0) { error("error on on fork"); } if (pid == 0) { close(info->socket_fd); handler_request(new_socket_fd); exit(0); } else { close(new_socket_fd) ; } pthread_exit(NULL); }
void loop(void) { int listenfd, clifd; int rval, i, nr; int maxi, maxfd; uid_t uid; fd_set rset, allset; char buf[MAXLINE]; /* obtain fd to listen for client request on */ if ((listenfd = serv_listen(CS_OPEN)) < 0) log_sys("serv_listen error"); FD_ZERO(&allset); FD_SET(listenfd, &allset); maxfd = listenfd; maxi = -1; for (;;) { rset = allset; /* rset get modified each time around */ rval = select(maxfd + 1, &rset, NULL, NULL, NULL); if (rval < 0) log_sys("select error"); if (FD_ISSET(listenfd, &rset)) { /* accept new client request */ if ((clifd = serv_accept(listenfd, &uid)) < 0) log_sys("serv_accept error"); i = client_add(clifd, uid); FD_SET(clifd, &allset); if (i > maxi) maxi = i; if (clifd > maxfd) maxfd = clifd; log_msg("new connection: uid %d, fd %d", uid, clifd); continue; } for (i = 0; i <= maxi; i++) { if (client[i].fd == -1) continue; if (FD_ISSET(client[i].fd, &rset)) { /* read argument buffer from client */ if ((nr = read(client[i].fd, buf, MAXLINE)) < 0) { log_sys("read error on fd %d", clifd); } else if (nr == 0) { log_msg("closed: uid %d, fd %d", client[i].uid, clifd); client_del(client[i].fd); /* client has closed cxn */ FD_CLR(clifd, &allset); close(clifd); } else { /* process client's request */ handler_request(buf, nr, clifd, client[i].uid); } } } } }
void msg_process(char * (*handler_request)(char *req_buf, int fd)) { LOCALTSS(tss); int resp_size; RPCREQ* req; char* resp; int fd; MSG_DATA *req_msg; MSG_DATA *resp_msg; req_msg = NULL; resp_msg = NULL; while(TRUE) { pthread_mutex_lock(&mutex); while (msg_list_head == NULL) pthread_cond_wait(&cond, &mutex); req_msg = msg_list_head; msg_list_head = msg_list_head->next; msg_list_len--; pthread_mutex_unlock(&mutex); if(!strncasecmp(RPC_RBD_MAGIC, req_msg->data, STRLEN(RPC_RBD_MAGIC))) { req = conn_build_req(req_msg->block_buffer, req_msg->n_size); } else { req = conn_build_req(req_msg->data, req_msg->n_size); } fd = req_msg->fd; if(req_msg->n_size) { resp = handler_request(req->data, fd); if (resp == NULL) { if (tss->tstat & TSS_PARSER_ERR) { resp = conn_build_resp_byte(RPC_PARSER_ERR, 0, NULL); } else { resp = conn_build_resp_byte(RPC_FAIL, 0, NULL); } } } else { resp = conn_build_resp_byte(RPC_FAIL, 0, NULL); } /* If it's the select where/range session, skip the success operation. */ if((fd < 0) || (((RPCRESP *)resp)->status_code & RPC_SKIP_SEND)) { //local msg, such as recovery task msg, so no need to response goto finish; } resp_size = conn_get_resp_size((RPCRESP *)resp); resp_msg = NULL; resp_msg = (MSG_DATA *)msg_mem_alloc(); resp_msg->n_size = resp_size; resp_msg->block_buffer = NULL; Assert(resp_size < MSG_SIZE); MEMCPY(resp_msg->data, resp, resp_size); resp_msg->fd = fd; struct epoll_event ev; ev.data.ptr = resp_msg; ev.events = EPOLLOUT | EPOLLET; epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev); finish: if (req_msg->block_buffer != NULL) { free(req_msg->block_buffer); } msg_mem_free(req_msg); conn_destroy_req(req); conn_destroy_resp_byte(resp); tss_init(tss); } }