static void tcp_sock_setup(tcp_sock_t *tcp_sock, int sock, tcp_func_t func, void *user_data) { /* Setup socket keepalive */ setsockopt_keepalive(sock); /* Setup event callback */ io_channel_setup(&tcp_sock->chan, sock, (io_func_t) tcp_sock_event, tcp_sock); tcp_sock->func = func; tcp_sock->user_data = user_data; }
void dbs_server_loop(int lsocket) { struct sockaddr_in sinRemote; int sd ; fd_set ReadFDs, WriteFDs, ExceptFDs; t_elem * elem; t_d2dbs_connection* it; BOOL bOK ; const char* pcErrorType ; struct timeval tv; int highest_fd; psock_t_socklen nAddrSize = sizeof(sinRemote); while (1) { #ifdef WIN32 if (g_ServiceStatus<0 && kbhit() && getch()=='q') d2dbs_signal_quit_wrapper(); if (g_ServiceStatus == 0) d2dbs_signal_quit_wrapper(); while (g_ServiceStatus == 2) Sleep(1000); #endif if (d2dbs_handle_signal()<0) break; dbs_handle_timed_events(); highest_fd=dbs_server_setup_fdsets(&ReadFDs, &WriteFDs, &ExceptFDs, lsocket); tv.tv_sec = 0; tv.tv_usec = SELECT_TIME_OUT; switch (psock_select(highest_fd+1, &ReadFDs, &WriteFDs, &ExceptFDs, &tv) ) { case -1: eventlog(eventlog_level_error,__FUNCTION__,"psock_select() failed : %s",strerror(psock_errno())); continue; case 0: continue; default: break; } if (PSOCK_FD_ISSET(lsocket, &ReadFDs)) { sd = psock_accept(lsocket, (struct sockaddr*)&sinRemote, &nAddrSize); if (sd == -1) { eventlog(eventlog_level_error,__FUNCTION__,"psock_accept() failed : %s",strerror(psock_errno())); return; } eventlog(eventlog_level_info,__FUNCTION__,"accepted connection from %s:%d , socket %d .", inet_ntoa(sinRemote.sin_addr) , ntohs(sinRemote.sin_port), sd); eventlog_step(prefs_get_logfile_gs(),eventlog_level_info,__FUNCTION__,"accepted connection from %s:%d , socket %d .", inet_ntoa(sinRemote.sin_addr) , ntohs(sinRemote.sin_port), sd); setsockopt_keepalive(sd); dbs_server_list_add_socket(sd, ntohl(sinRemote.sin_addr.s_addr)); if (psock_ctl(sd,PSOCK_NONBLOCK)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not set TCP socket [%d] to non-blocking mode (closing connection) (psock_ctl: %s)", sd,strerror(psock_errno())); psock_close(sd); } } else if (PSOCK_FD_ISSET(lsocket, &ExceptFDs)) { eventlog(eventlog_level_error,__FUNCTION__,"exception on listening socket"); /* FIXME: exceptions are not errors with TCP, they are out-of-band data */ return; } LIST_TRAVERSE(dbs_server_connection_list,elem) { bOK = TRUE; pcErrorType = 0; if (!(it=elem_get_data(elem))) continue; if (PSOCK_FD_ISSET(it->sd, &ExceptFDs)) { bOK = FALSE; pcErrorType = "General socket error"; /* FIXME: no no no no no */ PSOCK_FD_CLR(it->sd, &ExceptFDs); } else { if (PSOCK_FD_ISSET(it->sd, &ReadFDs)) { bOK = dbs_server_read_data(it); pcErrorType = "Read error"; PSOCK_FD_CLR(it->sd, &ReadFDs); } if (PSOCK_FD_ISSET(it->sd, &WriteFDs)) { bOK = dbs_server_write_data(it); pcErrorType = "Write error"; PSOCK_FD_CLR(it->sd, &WriteFDs); } } if (!bOK) { int err; psock_t_socklen errlen; err = 0; errlen = sizeof(err); if (psock_getsockopt(it->sd, PSOCK_SOL_SOCKET, PSOCK_SO_ERROR, &err, &errlen)==0) { if (errlen && err!=0) { eventlog(eventlog_level_error,__FUNCTION__,"data socket error : %s",strerror(err)); } } dbs_server_shutdown_connection(it); list_remove_elem(dbs_server_connection_list,&elem); } else { if (dbs_packet_handle(it)==-1) { eventlog(eventlog_level_error,__FUNCTION__,"dbs_packet_handle() failed"); dbs_server_shutdown_connection(it); list_remove_elem(dbs_server_connection_list,&elem); } } } }
int telnet_main(int argc UNUSED_PARAM, char **argv) { char *host; int port; int len; struct pollfd ufds[2]; INIT_G(); #if ENABLE_FEATURE_AUTOWIDTH get_terminal_width_height(0, &G.win_width, &G.win_height); #endif #if ENABLE_FEATURE_TELNET_TTYPE G.ttype = getenv("TERM"); #endif if (tcgetattr(0, &G.termios_def) >= 0) { G.do_termios = 1; G.termios_raw = G.termios_def; cfmakeraw(&G.termios_raw); } #if ENABLE_FEATURE_TELNET_AUTOLOGIN if (1 & getopt32(argv, "al:", &G.autologin)) G.autologin = getenv("USER"); argv += optind; #else argv++; #endif if (!*argv) bb_show_usage(); host = *argv++; port = bb_lookup_port(*argv ? *argv++ : "telnet", "tcp", 23); if (*argv) /* extra params?? */ bb_show_usage(); xmove_fd(create_and_connect_stream_or_die(host, port), netfd); setsockopt_keepalive(netfd); signal(SIGINT, record_signo); ufds[0].fd = STDIN_FILENO; ufds[0].events = POLLIN; ufds[1].fd = netfd; ufds[1].events = POLLIN; while (1) { if (poll(ufds, 2, -1) < 0) { /* error, ignore and/or log something, bay go to loop */ if (bb_got_signal) con_escape(); else sleep(1); continue; } // FIXME: reads can block. Need full bidirectional buffering. if (ufds[0].revents) { len = safe_read(STDIN_FILENO, G.buf, DATABUFSIZE); if (len <= 0) doexit(EXIT_SUCCESS); TRACE(0, ("Read con: %d\n", len)); handle_net_output(len); } if (ufds[1].revents) { len = safe_read(netfd, G.buf, DATABUFSIZE); if (len <= 0) { full_write1_str("Connection closed by foreign host\r\n"); doexit(EXIT_FAILURE); } TRACE(0, ("Read netfd (%d): %d\n", netfd, len)); handle_net_input(len); } } /* while (1) */ }