void on_recv(int fd, void *arg) { char buf[128] = {0}; int sock_type = get_socket_type(fd); int proto_type = get_socket_protocol(fd); switch (sock_type) { case SOCK_STREAM: if (proto_type == IPPROTO_TCP) socket_recv(fd, buf, sizeof(buf)); else if (proto_type == IPPROTO_SCTP) ; else return; break; case SOCK_DGRAM: socket_addr_recvfrom(fd, buf, sizeof(buf), (void *)&((struct socket_impl *)arg)->addr.in_addr); break; default: return; break; } printf("recv from %s: %s\n", inet_ntoa(((struct socket_impl *)arg)->addr.in_addr.sin_addr), buf); }
int reopen_socket_with_other_family(int s, int family) { int type, protocol, result, saved_fd; result = 0; // duplicate the file descriptor saved_fd = dup(s); // record the type, protocol and fd of the existing socket type = get_socket_type(s); protocol = get_socket_protocol(s); // close the socket - this way the fd integer should be available for our new socket // and the calling program will not notice that the socket is not the same original_close(s); // create an IPv6 socket on the same file descriptor s if (create_socket_on_specified_free_fd(s, family, type, protocol) == -1) { // failed ! recreate file descriptor previously closed dup2(saved_fd, s); result = -1; } else { report_socket_options(saved_fd, s); } // saved_fd is not useful anymore original_close(saved_fd); return result; }
/** * @brief tcp_server thread runine * * @param sock [in] struct sock * * @return */ static void* tcp_server_backup_service(void *sock) { /* define */ struct socket_impl *sck = (struct socket_impl *)sock; struct event_loop *evl = (event_loop_t *)&sck->evl; struct timeval tv = {0}; fd_set set; fd_set allset; int can_recv_bytes = 0; int nready = 0; int serfd = sck->fd; int maxfd = sck->fd; int clifd = -1; int fd = -1; int maxi = -1; int i = 0; int addr_len = sizeof(struct sockaddr); /* avoid sock equal to NULL */ if (sock == NULL) return NULL; /* client socket fd init */ for (i = 0; i < MAX_CLIENT_NUM; i++) sck->cli_fd[i] = -1; /* empty fd sets */ FD_ZERO(&allset); FD_SET(serfd, &allset); /* detect socket state looply */ while (1) { /* set timer */ tv.tv_sec = 0; tv.tv_usec = 10000; /* set fd sets */ set = allset; /* time waiting */ nready = select(maxfd + 1, &set, NULL, NULL, &tv); /* detect server socket state */ if (FD_ISSET(serfd, &set)) { /* accept socket */ //clifd = socket_accept(serfd); clifd = accept(serfd, \ (struct sockaddr *)&sck->addr.in_addr, (socklen_t *)&addr_len); /* on_accept */ if (clifd > 0) socket_event_process(clifd, evl->on_accept); for (i = 0; i < MAX_CLIENT_NUM; i++) { if (sck->cli_fd[i] < 0) { sck->cli_fd[i] = clifd; break; } } if (i == MAX_CLIENT_NUM) printf("too many client!\n"); /* add socket fd to the collection */ FD_SET(clifd, &allset); /* set maxfd and maxi*/ if (clifd > maxfd) maxfd = clifd; if (i > maxi) maxi = i; if (--nready <= 0) continue; } /* detect client socket state */ for (i = 0; i <= maxi; i++) { if ((fd = sck->cli_fd[i]) < 0) continue; if (FD_ISSET(fd, &set)) { /* on_recv */ can_recv_bytes = get_can_read_bytes(fd); if (can_recv_bytes > 0 || get_socket_protocol(fd) == IPPROTO_SCTP) { socket_event_process(fd, evl->on_recv); sck->curr_cli_fd = fd; } /* on_close */ if (can_recv_bytes <= 0) { FD_CLR(fd, &allset); socket_event_process(fd, evl->on_close); if (fd > 0)close(fd); sck->cli_fd[i] = -1; } if (--nready <= 0) break; } } } return NULL; }