--- lbbs/src/bbs_net.c 2025/05/11 04:09:08 1.32 +++ lbbs/src/bbs_net.c 2025/05/11 14:52:26 1.37 @@ -150,10 +150,18 @@ static void process_bar(int n, int len) int bbsnet_connect(int n) { - int sock, flags, ret, loop, error; - ssize_t len; + int sock, ret, loop, error; + int flags_sock; + int flags_stdin; + int flags_stdout; + int len; struct sockaddr_in sin; - char buf[LINE_BUFFER_LEN]; + char input_buf[LINE_BUFFER_LEN]; + char output_buf[LINE_BUFFER_LEN]; + int input_buf_len = 0; + int output_buf_len = 0; + int input_buf_offset = 0; + int output_buf_offset = 0; fd_set read_fds; fd_set write_fds; struct timeval timeout; @@ -215,8 +223,8 @@ int bbsnet_connect(int n) process_bar(0, MAX_PROCESS_BAR_LEN); // Set socket as non-blocking - flags = fcntl(sock, F_GETFL, 0); - fcntl(sock, F_SETFL, flags | O_NONBLOCK); + flags_sock = fcntl(sock, F_GETFL, 0); + fcntl(sock, F_SETFL, flags_sock | O_NONBLOCK); if ((ret = connect(sock, (struct sockaddr *)&sin, sizeof(sin))) < 0) { @@ -279,8 +287,6 @@ int bbsnet_connect(int n) return -1; } - fcntl(sock, F_SETFL, flags); /* restore file status flags */ - tos = IPTOS_LOWDELAY; if (setsockopt(sock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) { @@ -288,10 +294,16 @@ int bbsnet_connect(int n) } prints("\033[1;31mÁ¬½Ó³É¹¦£¡\033[m\r\n"); + iflush(); log_std("BBSNET connect to %s:%d\n", remote_addr, remote_port); - BBS_last_access_tm = t_used = time(0); + // Set STDIN/STDOUT as non-blocking + flags_stdin = fcntl(STDIN_FILENO, F_GETFL, 0); + flags_stdout = fcntl(STDOUT_FILENO, F_GETFL, 0); + fcntl(STDIN_FILENO, F_SETFL, flags_stdin | O_NONBLOCK); + fcntl(STDOUT_FILENO, F_SETFL, flags_stdout | O_NONBLOCK); + BBS_last_access_tm = t_used = time(0); loop = 1; while (loop && !SYS_server_exit) @@ -300,10 +312,14 @@ int bbsnet_connect(int n) FD_SET(STDIN_FILENO, &read_fds); FD_SET(sock, &read_fds); + FD_ZERO(&write_fds); + FD_SET(STDOUT_FILENO, &write_fds); + FD_SET(sock, &write_fds); + timeout.tv_sec = 0; timeout.tv_usec = 100 * 1000; // 0.1 second - ret = select(sock + 1, &read_fds, NULL, NULL, &timeout); + ret = select(sock + 1, &read_fds, &write_fds, NULL, &timeout); if (ret == 0) // timeout { @@ -320,31 +336,105 @@ int bbsnet_connect(int n) loop = 0; } } - else if (ret > 0) + else // if (ret > 0) { - if (FD_ISSET(STDIN_FILENO, &read_fds)) + if ((input_buf_offset >= input_buf_len) && FD_ISSET(STDIN_FILENO, &read_fds)) { - len = read(STDIN_FILENO, buf, sizeof(buf)); - if (len == 0) + ret = (int)read(STDIN_FILENO, input_buf, sizeof(input_buf)); + if (ret < 0) + { + if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) + { + log_error("read(STDIN) error (%d)\n", errno); + loop = 0; + } + } + else if (ret == 0) // broken pipe { loop = 0; } - write(sock, buf, (size_t)len); + else + { + input_buf_len = ret; + input_buf_offset = 0; - BBS_last_access_tm = time(0); + BBS_last_access_tm = time(0); + } } - if (FD_ISSET(sock, &read_fds)) + + if ((input_buf_offset < input_buf_len) && FD_ISSET(sock, &write_fds)) { - len = read(sock, buf, sizeof(buf)); - if (len == 0) + ret = (int)write(sock, input_buf + input_buf_offset, (size_t)(input_buf_len - input_buf_offset)); + if (ret < 0) + { + if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) + { + log_error("write(socket) error (%d)\n", errno); + loop = 0; + } + } + else if (ret == 0) // broken pipe { loop = 0; } - write(STDOUT_FILENO, buf, (size_t)len); + else + { + input_buf_offset += ret; + } + } + + if ((output_buf_offset >= output_buf_len) && FD_ISSET(sock, &read_fds)) + { + ret = (int)read(sock, output_buf, sizeof(output_buf)); + if (ret < 0) + { + if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) + { + log_error("read(socket) error (%d)\n", errno); + loop = 0; + } + } + else if (ret == 0) // broken pipe + { + loop = 0; + } + else + { + output_buf_len = ret; + output_buf_offset = 0; + } + } + + if ((output_buf_offset < output_buf_len) && FD_ISSET(STDOUT_FILENO, &write_fds)) + { + ret = (int)write(STDOUT_FILENO, output_buf + output_buf_offset, (size_t)(output_buf_len - output_buf_offset)); + if (ret < 0) + { + if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) + { + log_error("write(STDOUT) error (%d)\n", errno); + loop = 0; + } + } + else if (ret == 0) // broken pipe + { + loop = 0; + } + else + { + output_buf_offset += ret; + } } } } + // Restore STDIN/STDOUT flags + fcntl(STDIN_FILENO, F_SETFL, flags_stdin); + fcntl(STDOUT_FILENO, F_SETFL, flags_stdout); + + // Restore socket flags + fcntl(sock, F_SETFL, flags_sock); + if (close(sock) == -1) { log_error("Close socket failed\n"); @@ -427,9 +517,9 @@ int bbs_net() ch = igetch(0); switch (ch) { - case Ctrl('C'): + case KEY_NULL: // broken pipe + case Ctrl('C'): // user cancel return 0; - case KEY_NULL: case KEY_TIMEOUT: if (time(0) - BBS_last_access_tm >= MAX_DELAY_TIME) {