/** * [Client only] * Setup the configuration for the server this client is connecting to: * - Get server host and port. * - Get address of server. * * server: Of the form server_host:server_port. The server to connect to. * If no port is specified, defaults to port 80. * returns: 0 on success, -1 otherwise. */ int do_config_server(char *server) { ASSERT_CLIENT_ONLY; /* Parse server into its hostname and port. */ char *host, *server_port_str, *_server = server; int server_port; host = strsep(&server, ":"); if (server == NULL) { fprintf(stderr, "[ERROR] No port specified for server %s\n", host); return -1; } server_port_str = strsep(&server, ":"); server_port = atoi(server_port_str); config->sconn = calloc(sizeof(conn_t), 1); conn_add(config->sconn); /* Get IP address of server. See if this is a server on the same machine. */ in_addr_t dst_ip = ip_from_hostname(_server); if (dst_ip == 0) return -1; else if (dst_ip != LOCALHOST) unix_socket = false; /* Set up connection details. */ int port = server_port == 0 ? DEFAULT_PORT : server_port; conn_setup(config->sconn, dst_ip, port, unix_socket); return 0; }
/** * [Server only] * Handle a new connection from a client. Set up connection details and * initialize sequence numbers. * * pkt: The SYN segment from the client. * returns: The conn_t associated with the new connection. */ conn_t *tcp_new_connection(char *pkt) { ASSERT_SERVER_ONLY; /* Ignore if too many clients are connected. */ if (num_connected >= MAX_NUM_CLIENTS) { fprintf(stderr, "[ERROR] Maximum number of clients (%d) reached\n", MAX_NUM_CLIENTS); return NULL; } num_connected++; iphdr_t *ip_hdr = (iphdr_t *) pkt; tcphdr_t *syn = (tcphdr_t *) (pkt + IP_HDR_SIZE); /* Set up connection details and add to list of connections. */ conn_t *conn = calloc(sizeof(conn_t), 1); conn_setup(conn, ntohl(ip_hdr->saddr), ntohs(syn->th_sport), unix_socket); conn->their_init_seqno = ntohl(syn->th_seq); conn->ackno = conn->their_init_seqno + 1; conn_add(conn); /* Send a SYN-ACK to the client. */ send_synack(conn); /* Get window size of the client. */ ctcp_cfg->send_window = ntohs(syn->window); ctcp_config_t *config_copy = calloc(sizeof(ctcp_config_t), 1); memcpy(config_copy, ctcp_cfg, sizeof(ctcp_config_t)); /* Student code. */ ctcp_state_t *state = ctcp_init(conn, config_copy); conn->state = state; fprintf(stderr, "[INFO] Client connected\n"); return conn; }
static int add_conn(struct iscsi_target *target, unsigned long ptr) { int err; struct iscsi_session *session; struct conn_info info; if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0) return err; if (!(session = session_lookup(target, info.sid))) return -ENOENT; return conn_add(session, &info); }
/* 连接信息从用户态转入内核态 */ static int add_conn(struct iscsi_target *target, unsigned long ptr) { struct iscsi_session *session; struct conn_info info; int err; /* 拷贝用户态连接信息 */ err = copy_from_user(&info, (void *) ptr, sizeof(info)); if (err) return -EFAULT; /* 根据target和用户态连接信息中的会话id, 找到会话信息 */ session = session_lookup(target, info.sid); if (!session) return -ENOENT; return conn_add(session, &info); }
static void conn_main(void) { const AtmAddr_t *addr; int main_conn; const char *str; int i; addr = get_var_addr(&conn_unit, "S1"); if (addr == NULL) { dump_printf(EL_ERROR, "S1 (LES Address) must be specified"); event_put(&conn_unit, CE_EXIT, NULL); } else { str = get_var_str(&conn_unit,"S2"); if (str == NULL) { set_var_str(&conn_unit, "S2", S2_default); } i = get_var_int(&conn_unit,"S3"); if (i == 0) { set_var_int(&conn_unit,"S3", S3_default); } i = get_var_int(&conn_unit,"S4"); if (i == 0) { set_var_int(&conn_unit,"S4", S4_default); } i = get_var_int(&conn_unit,"S5"); if (i == 0) { set_var_int(&conn_unit,"S5", S5_default); } addr = get_var_addr(&conn_unit, "S6"); if (addr == NULL) { dump_printf(EL_ERROR, "S6 (BUS Address) must be specified"); event_put(&conn_unit, CE_EXIT, NULL); } else { main_conn = atm_create_socket(CONTROL_DIRECT, get_var_addr(&conn_unit, "S1")); if (main_conn >= 0) { (void)conn_add(CT_MAIN, main_conn,0); } } } }
static void start_daemon(int lockfd) { int maxfd, pid, pipefd, ret; struct timeval tv; fd_set rfds; conn_t *tmp, *tmpnext; us_serialize(SERIALIZE_INIT); if ((pid = fork()) < 0) fatal_with_errno(EXIT_FAILURE, "Unable to enter background"); if (pid != 0) { /* parent */ /* wait for child to set up the listener */ us_serialize(SERIALIZE_WAIT); return; } /* child */ close(0); close(1); close(2); /* make fds 0-2 point somewhere defined */ if (open("/dev/null", O_RDWR) != 0) fatal_with_errno(EXIT_FAILURE, "open /dev/null"); if (dup(0) == -1) fatal_with_errno(EXIT_FAILURE, "dup"); if (dup(0) == -1) fatal_with_errno(EXIT_FAILURE, "dup"); pipefd = open_sock(); if (verbose) upslogx(LOG_INFO, "Timer daemon started"); /* release the parent */ us_serialize(SERIALIZE_SET); /* drop the lock now that the background is running */ unlink(lockfn); close(lockfd); /* now watch for activity */ for (;;) { /* wait at most 1s so we can check our timers regularly */ tv.tv_sec = 1; tv.tv_usec = 0; FD_ZERO(&rfds); FD_SET(pipefd, &rfds); maxfd = pipefd; for (tmp = connhead; tmp != NULL; tmp = tmp->next) { FD_SET(tmp->fd, &rfds); if (tmp->fd > maxfd) maxfd = tmp->fd; } ret = select(maxfd + 1, &rfds, NULL, NULL, &tv); if (ret > 0) { if (FD_ISSET(pipefd, &rfds)) conn_add(pipefd); tmp = connhead; while (tmp) { tmpnext = tmp->next; if (FD_ISSET(tmp->fd, &rfds)) { if (sock_read(tmp) < 0) { close(tmp->fd); conn_del(tmp); } } tmp = tmpnext; } } checktimers(); } }
int main(int argc, char *argv[]) { int echo_port = PORT; if(argc > 1) { LOG("IN %d OUT %d RDHUP %d HUP %d ERR %d", EPOLLIN, EPOLLOUT, EPOLLRDHUP, EPOLLHUP, EPOLLERR); char *endptr = NULL; echo_port = strtol(argv[1], &endptr, 10); if (echo_port <= 0 || echo_port >= LONG_MAX) { LOG("LONG_MIN %ld LONG_MAX %ld, echo port %d", LONG_MIN, LONG_MAX, echo_port); exit(-1); } } LOG("listen to localhost:%d\n", echo_port); // 处理信号 register_sig(SIGTERM, signal_handler); register_sig(SIGINT, signal_handler); register_sig(SIGQUIT, signal_handler); register_sig(SIGPIPE, SIG_IGN); /* 设置SIGURG 的处理函数 sig_urg */ //if(fcntl(ss_fd, F_SETOWN, getpid()) < 0) { //perror("can not set OOB own"); //} //register_sig(SIGURG, signal_handler); int ss_fd = -1; struct sockaddr_in server_addr = {0}; struct sockaddr_in client_addr = {0}; socklen_t addr_in_len = sizeof(struct sockaddr_in); int yes = 1; ss_fd = socket( AF_INET, SOCK_STREAM, 0); if(ss_fd == -1){ perror("create server socket error"); return EXIT_FAILURE; } if (setsockopt(ss_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); return EXIT_FAILURE; } memset(&server_addr, 0, sizeof(struct sockaddr_in)); memset(&client_addr, 0, sizeof(struct sockaddr_in)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(echo_port); server_addr.sin_addr.s_addr = htons(INADDR_ANY); if (bind(ss_fd, (struct sockaddr *)&server_addr, addr_in_len) == -1) { perror("bind server socket error"); return EXIT_FAILURE; } else { printf("bind successfully \n"); } if (listen(ss_fd, BACKLOG) == -1) { perror("listen server socket error"); return EXIT_FAILURE; } else { printf("listen successfully \n"); } printf("listen port %d\n", echo_port); struct epoll_event ev = {0}; struct epoll_event events[MAXEVENTS] = {{0}}; int epfd = epoll_create(MAXCLIENTS); //add server socket to epoll ev.events = EPOLLIN ; //| EPOLLET; ev.data.fd = ss_fd; if(setnonblocking(ss_fd) != 0) { perror("css_fd an not nonblocking"); return EXIT_FAILURE; } epoll_ctl(epfd, EPOLL_CTL_ADD, ss_fd, &ev); if(epfd == -1){ perror("epoll listen socket"); return EXIT_FAILURE; } #define E_TIMEOUT 10 /*********************************** main loop **************************************/ while(!closing) { int ready_fds = epoll_wait(epfd, events, MAXEVENTS, E_TIMEOUT); if(ready_fds == -1){ perror("epoll_wait"); break; } for(int n = 0; n < ready_fds; ++n) { if (events[n].events & EPOLLERR || events[n].events & EPOLLRDHUP || events[n].events & EPOLLHUP) { D_L("ERROR or HUP\n"); if (events[n].data.fd != ss_fd) { closeclient(epfd, events[n].data.fd); } continue; } if (events[n].events & EPOLLIN) { if(events[n].data.fd == ss_fd) { //listening socket while(true) { int c_fd = accept(ss_fd, (struct sockaddr *) &client_addr, &addr_in_len); if(c_fd < 0){ if(errno == EAGAIN){ break; } else if(errno == EINTR){ continue; } else { D_L("accept error %s", strerror(errno)); close(ss_fd); break; } } setnonblocking(c_fd); setkeepalive(c_fd); ev.events = EPOLLET | EPOLLIN | EPOLLOUT | EPOLLRDHUP; ev.data.fd = c_fd; //add to epoll events queue if (STAT.conn_amount < MAXCLIENTS) { D_L("total [%d] client, new fd %d Addr: %s:%d", STAT.conn_amount, c_fd,\ inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); if (epoll_ctl(epfd, EPOLL_CTL_ADD, c_fd, &ev) < 0) { fprintf(stderr, "epoll set insertion error: fd=%d", c_fd); break; } conn_add(c_fd); } else { const char *refuse_str = "max connections, refuse and close, bye"; D_L("%s\n", refuse_str); send(c_fd, refuse_str, strlen(refuse_str), 0); close(c_fd); } } } else { //common client int fd = events[n].data.fd; conn_list_iter it = conn_list.find(fd); if (it != conn_list.end()) { int left_sz = MAX_BUFSZ - it->second.rsize; int rsz = recv(fd, it->second.rbuf + it->second.rsize, left_sz, 0); if (rsz <= 0) { D_L("get from fd %d err: %s, close it", fd, strerror(errno)); closeclient(epfd, fd); continue; } else if (rsz < left_sz) { //D_L("get from fd %d len: %d", fd, rsz); it->second.rsize += rsz; } else { D_L("recv buf size is to small for bufsz %d fd %d len %d", MAX_BUFSZ, fd, rsz); closeclient(epfd, fd); continue; } } else { D_L("get unknown fd %d EPOLLIN", fd); } } } if (events[n].events & EPOLLOUT) { int fd = events[n].data.fd; conn_list_iter it = conn_list.find(fd); if (it != conn_list.end()) { if (it->second.wsize == 0 && it->second.rsize == 0) { continue; } int nop_sz = it->second.rsize; int left_sz = MAX_BUFSZ - it->second.wsize; if (nop_sz > left_sz) { //buffer too small, send first int wsz = send(fd, it->second.wbuf, it->second.wsize, 0); if (wsz < 0) { D_L("send to fd %d err: %s", fd, strerror(errno)); if (errno == EINTR || errno == EAGAIN) { continue; } closeclient(epfd, fd); continue; } if (wsz != it->second.wsize) { memmove(it->second.wbuf, it->second.wbuf + wsz, it->second.wsize - wsz); } it->second.wsize -= wsz; } left_sz = MAX_BUFSZ - it->second.wsize; if (nop_sz > left_sz) { D_L("send buf size to small for fd %d nop_size %d left_size %d", fd, nop_sz, left_sz); closeclient(epfd, fd); continue; } memcpy(it->second.wbuf + it->second.wsize, it->second.rbuf, nop_sz); it->second.wsize += nop_sz; it->second.rsize -= nop_sz; char *buf = it->second.wbuf; int wsz = send(fd, buf, it->second.wsize, 0); if (wsz < 0) { if (errno == EINTR || errno == EAGAIN) { continue; } D_L("send to fd %d err: %s, close it", fd, strerror(errno)); closeclient(epfd, fd); continue; } it->second.wsize -= wsz; } else { D_L("get unknown fd %d EPOLLOUT", fd); closeclient(epfd, fd); } } //D_L("unkown events get fd %d:%x", events[n].data.fd, events[n].events); } } close(epfd); return 0; }
/* * Handle new connections or data arrival * data points to Conn_t */ static int data_handler(const Event_t *event, void *funcdata) { Conn_t *tmp, *newconn; int fd, nbytes; static char buffer[BUFSIZE]; LaneControl_t *ctmp; struct sockaddr_atmsvc addr; assert(event->data != NULL); tmp = (Conn_t *)event->data; dump_conn(tmp); if (tmp->type == CT_MAIN) { nbytes = sizeof(addr); memset(&addr,0, nbytes); fd = accept(tmp->fd, (struct sockaddr *)&addr, &nbytes); if (fd <0) { dump_error(&conn_unit, "accept"); if (errno == ENETRESET) { Debug_unit(&conn_unit,"Restart. Sleeping 10 secs..."); sleep(10); event_put(&conn_unit, CE_RESTART, NULL); } else if (errno == EUNATCH) { Debug_unit(&conn_unit,"Exiting..."); event_put(&conn_unit, CE_EXIT, NULL); } return -1; } newconn = conn_add(CT_SVC_CD, fd,0); newconn->state = call_state(CE_SVC_OPEN, 0, newconn); } else { /* tmp->fd or tmp->sfd ?*/ nbytes = read(tmp->active_fd, buffer, BUFSIZE); if (nbytes < 0) { dump_error(&conn_unit, "read"); if (errno == EUNATCH) event_put(&conn_unit, CE_EXIT, NULL); if (errno == ENETRESET) { Debug_unit(&conn_unit, "Restart. Sleeping 10 secs..."); sleep(10); event_put(&conn_unit, CE_RESTART, NULL); } } else if (nbytes == 0) { /* EOF */ Debug_unit(&conn_unit, "EOF"); tmp->state = call_state(CE_SVC_CLOSE, 0, tmp); } else { buffer[nbytes] = '\0'; Debug_unit(&conn_unit, "Data: %2.2x %2.2x %2.2x", 0xff&buffer[0],0xff&buffer[1],0xff&buffer[2]); ctmp = (LaneControl_t *)buffer; if (is_control(ctmp) == 1) { control_packet = (LaneControl_t*)buffer; dump_control(ctmp); tmp->proxy = is_proxy(); tmp->state = call_state(CE_DATA, ctmp->opcode, tmp); } else Debug_unit(&conn_unit,"Not a control_packet, discarding..."); } } mem_free(&conn_unit, event); return 1; }