// socket utilities assume that the critical section has already been entered. static void free_socket( const int t ) { _WSAResetEvent( sockets[t].ev ); if(sockets[t].s != INVALID_SOCKET) { _closesocket( sockets[t].s ); sockets[t].s = INVALID_SOCKET; } sockets[t].state = CLOSED; sockets[t].stream_to_mac_stalled_until = 0; sockets[t].in_use = false; sockets[t].time_wait = 0; // if there was an attached listening socket (ftp), close it. int lst = sockets[t].child; if( lst >= 0 ) { if(l_sockets[lst].s != INVALID_SOCKET) { D(bug(" closing listening socket %d\r\n", lst)); _closesocket( l_sockets[lst].s ); l_sockets[lst].s = INVALID_SOCKET; } l_sockets[lst].port = 0; l_sockets[lst].parent = -1; } sockets[t].child = -1; }
void ListenerSocketConnection::stopConnection() { // do not read more continueRead = false; // stop receiving messages MessagingService *ms = MessagingService::getService(); if( pub != NULL ) { ms -> destroyPublisher( pub ); pub = NULL; } if( sub != NULL ) { ms -> unsubscribe( sub ); sub = NULL; } // close socket part if( socket != INVALID_SOCKET ) { shutdown( socket , SD_BOTH ); logout = true; _closesocket( socket ); socket = INVALID_SOCKET; } if( connected ) { logger.logInfo( "stopConnection: connection=" + getName() + ": disconnected" ); connected = false; } }
static void tcp_accept_callback( const int lst ) { D(bug("[%d] tcp_accept_callback()\r\n", lst)); struct sockaddr_in to; memset( &to, 0, sizeof(to) ); to.sin_family = AF_INET; int tolen = sizeof(to); SOCKET s = _accept( l_sockets[lst].s, (struct sockaddr *)&to, &tolen ); if( s == INVALID_SOCKET ) { D(bug("[%d] connection not accepted, error code %d\r\n", lst, _WSAGetLastError())); } else { _WSAEventSelect( s, 0, 0 ); uint16 src_port = l_sockets[lst].port; uint16 dest_port = ntohs(to.sin_port); uint32 ip_dest = ntohl(to.sin_addr.s_addr); D(bug("[%d] connection accepted, local port:%d, remote %s:%d\r\n", lst, src_port, _inet_ntoa(to.sin_addr), dest_port)); if( l_sockets[lst].ip != 0 && l_sockets[lst].ip != ip_dest ) { _closesocket( s ); D(bug("[%d] authorization failure. connection closed.\r\n", lst )); } else { int t = alloc_new_socket( src_port, dest_port, ip_dest ); if( t < 0 ) { D(bug("<%d> out of slot space, connection dropped\r\n", t )); free_socket(t); } else { sockets[t].s = s; sockets[t].state = LISTEN; sockets[t].src_port = src_port; sockets[t].dest_port = dest_port; sockets[t].ip_src = macos_ip_address; sockets[t].ip_dest = ip_dest; sockets[t].seq_out = 0x00000001; sockets[t].seq_in = 0; // not known yet sockets[t].mac_ack = sockets[t].seq_out; // zero out pending bytes tcp_reply( SYN, t ); sockets[t].seq_out++; sockets[t].state = SYN_SENT; sockets[t].time_wait = GetTickCount() + SYN_FLOOD_PROTECTION_TIMEOUT; D(bug("<%d> Connect: LISTEN -> SYN_SENT\r\n", t)); _WSAResetEvent( sockets[t].ev ); if( SOCKET_ERROR == _WSAEventSelect( sockets[t].s, sockets[t].ev, FD_CLOSE ) ) { D(bug("<%d> WSAEventSelect() failed with error code %d\r\n", t, _WSAGetLastError())); } // No data from the remote host is needed until the connection is established. // So don't initiate read yet. } } } }
socket_t::~socket_t() { if(s != INVALID_SOCKET) { _closesocket( s ); // slam! s = INVALID_SOCKET; } delete [] out_buffers[0].buf; delete [] buffers[0].buf; }
void SocketServer::closeListeningPort() { shutdownInProgress = true; // close listening socket if( listenSocket != INVALID_SOCKET ) { _closesocket( listenSocket ); listenSocket = INVALID_SOCKET; String msg = "closeListeningPort: stopped listener on address=" + getAddress( &listen_inet ); logger.logInfo( msg ); } }
/********************************************************************* * * _FTPServerChildTask * */ static void _FTPServerChildTask(void * Context) { int Sock; int Opt; _pFS_API = &IP_FS_FS; Sock = (int)Context; Opt = 1; setsockopt(Sock, SOL_SOCKET, SO_KEEPALIVE, &Opt, sizeof(Opt)); IP_FTPS_Process(&_IP_API, Context, _pFS_API, &_Application); _closesocket(Sock); _ConnectCnt--; OS_Terminate(0); }
/*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ int CWsHook::closesocket(SOCKET s) { int ret = SOCKET_ERROR; if( dlg ) dlg->CloseSocket(s); if( _closesocket ) ret = _closesocket(s); if (tlsIndex != TLS_OUT_OF_INDEXES) TlsSetValue(tlsIndex, 0); return ret; }
void final_tcp() { D(bug("closing all tcp sockets\r\n")); for( int i=0; i<MAX_SOCKETS; i++ ) { if(sockets[i].s != INVALID_SOCKET) { D(bug(" closing socket %d\r\n", i)); } free_socket( i ); if(sockets[i].buffers_write[0].buf) { delete [] sockets[i].buffers_write[0].buf; sockets[i].buffers_write[0].buf = 0; } if(sockets[i].buffers_read[0].buf) { delete [] sockets[i].buffers_read[0].buf; sockets[i].buffers_read[0].buf = 0; } } D(bug("closing all tcp listening socket\r\n")); for( int i=0; i<MAX_SOCKETS; i++ ) { if(l_sockets[i].s != INVALID_SOCKET) { D(bug(" closing listening socket %d\r\n", i)); _closesocket( l_sockets[i].s ); l_sockets[i].s = INVALID_SOCKET; } } // The router module has already set the shutdown flag. WaitForSingleObject( tcp_handle, INFINITE ); WaitForSingleObject( tcp_l_handle, INFINITE ); for( int i=0; i<MAX_SOCKETS; i++ ) { if(sockets[i].ev != WSA_INVALID_EVENT) { _WSACloseEvent(sockets[i].ev); sockets[i].ev = WSA_INVALID_EVENT; } } for( int i=0; i<MAX_SOCKETS; i++ ) { if(l_sockets[i].ev != WSA_INVALID_EVENT) { _WSACloseEvent(l_sockets[i].ev); l_sockets[i].ev = WSA_INVALID_EVENT; } } DeleteCriticalSection( &tcp_section ); }
/********************************************************************* * * _FTPServerParentTask * */ static void _FTPServerParentTask(void) { int s, Sock; struct sockaddr Addr; int i; // // Loop until we get a socket into listening state // do { s = _ListenAtTcpAddr(21); if (s != SOCKET_ERROR) { break; } OS_Delay(100); // Try again } while (1); // // Loop once per client and create a thread for the actual server // while (1) { // // Wait for an incoming connection // int AddrLen = sizeof(Addr); if ((Sock = accept(s, &Addr, &AddrLen)) == SOCKET_ERROR) { continue; // Error } if (_ConnectCnt++ < MAX_CONNECTIONS) { for (i = 0; i < MAX_CONNECTIONS; i++) { U8 r; r = OS_IsTask(&_aFTPTasks[i]); if (r == 0) { OS_CREATETASK_EX(&_aFTPTasks[i], "IP_FTPServerChild", _FTPServerChildTask, TASKPRIO_FTPSCHILD, _aFTPStacks[i], (void *)Sock); break; } } } else { IP_FTPS_OnConnectionLimit(&_IP_API, (void *)Sock); OS_Delay(2000); // Give connection some time to complete _closesocket(Sock); _ConnectCnt--; } } }
void close_all_sockets() { D(bug("closing all(%d) sockets\r\n", open_sockets)); EnterCriticalSection( &router_section ); for( int i=0; i<open_sockets; i++ ) { socket_t *cmpl = all_sockets[i]; D(bug("closing socket(%d,%d)\r\n", cmpl->src_port, cmpl->dest_port)); if(cmpl->s == INVALID_SOCKET) { delete all_sockets[i]; all_sockets[i] = all_sockets[--open_sockets]; } else { // read completion will deallocate _closesocket( cmpl->s ); } } LeaveCriticalSection( &router_section ); }
void close_old_sockets() { DWORD now = GetTickCount(); EnterCriticalSection( &router_section ); for( int i=open_sockets-1; i>=0; i-- ) { socket_t *cmpl = all_sockets[i]; if( !cmpl->permanent && now >= cmpl->socket_ttl ) { D(bug("expiring socket(%d,%d)\r\n", cmpl->src_port, cmpl->dest_port)); if(cmpl->s == INVALID_SOCKET) { delete all_sockets[i]; all_sockets[i] = all_sockets[--open_sockets]; } else { // read completion will deallocate _closesocket( cmpl->s ); } } } LeaveCriticalSection( &router_section ); }
void write_tcp( tcp_t *tcp, int len ) { if(len < sizeof(tcp_t)) { D(bug("<%d> Too small tcp packet(%d) on unknown slot, dropped\r\n", -1, len)); return; } uint16 src_port = ntohs(tcp->src_port); uint16 dest_port = ntohs(tcp->dest_port); BOOL ok = true; BOOL handle_data = false; BOOL initiate_read = false; EnterCriticalSection( &tcp_section ); int t = find_socket( src_port, dest_port ); if(t < 0) { t = alloc_new_socket( src_port, dest_port, ntohl(tcp->ip.dest) ); ok = t >= 0; } if(ok) { D(bug("<%d> write_tcp %d bytes from port %d to port %d\r\n", t, len, src_port, dest_port)); } else { D(bug("<%d> FAILED write_tcp %d bytes from port %d to port %d\r\n", t, len, src_port, dest_port)); } if( ok && ISSET(tcp->flags,RST) ) { D(bug("<%d> RST set, resetting socket\r\n", t)); if( sockets[t].s != INVALID_SOCKET ) { D(bug("<%d> doing an extra shutdown (ie4)\r\n", t)); _shutdown( sockets[t].s, SD_BOTH ); } free_socket( t ); ok = false; } if(ok) { D(bug("<%d> State machine start = %s\r\n", t, STATENAME(sockets[t].state))); // always update receive window sockets[t].mac_window = ntohs(tcp->window); int header_len = tcp->header_len >> 2; int option_bytes = header_len - 20; char *data = (char *)tcp + sizeof(tcp_t) + option_bytes; int dlen = len - sizeof(tcp_t) - option_bytes; if( !ISSET(tcp->flags,ACK) ) { D(bug("<%d> ACK not set\r\n", t)); } if( ISSET(tcp->flags,SYN) ) { D(bug("<%d> SYN set\r\n", t)); // Note that some options are valid even if there is no SYN. // I don't care about those however. uint32 new_mss; process_options( t, (uint8 *)data - option_bytes, option_bytes, new_mss ); if(new_mss) { sockets[t].mac_mss = (int)new_mss; if( new_mss < sockets[t].buffers_read[0].len ) { sockets[t].buffers_read[0].len = new_mss; } D(bug("<%d> Max segment size set to %d\r\n", t, new_mss)); } } if( ISSET(tcp->flags,FIN) ) { D(bug("<%d> FIN set\r\n", t)); } // The sequence number Mac expects to see next time. sockets[t].mac_ack = ntohl(tcp->ack); D(bug("<%d> From Mac: Seq=%d, Ack=%d, window=%d, router Seq=%d\r\n", t, ntohl(tcp->seq), sockets[t].mac_ack, sockets[t].mac_window, sockets[t].seq_out)); if( sockets[t].stream_to_mac_stalled_until && sockets[t].mac_ack == sockets[t].seq_out && (sockets[t].state == ESTABLISHED || sockets[t].state == CLOSE_WAIT) ) { if( has_mac_read_space(t) ) { initiate_read = true; sockets[t].stream_to_mac_stalled_until = 0; D(bug("<%d> read resumed, mac can accept more data\r\n", t)); } } switch( sockets[t].state ) { case CLOSED: sockets[t].src_port = src_port; sockets[t].dest_port = dest_port; sockets[t].ip_src = ntohl(tcp->ip.src); sockets[t].ip_dest = ntohl(tcp->ip.dest); if( ISSET(tcp->flags,SYN) ) { sockets[t].seq_out = 0x00000001; sockets[t].seq_in = ntohl(tcp->seq) + 1; _WSAResetEvent( sockets[t].ev ); if( SOCKET_ERROR == _WSAEventSelect( sockets[t].s, sockets[t].ev, FD_CONNECT | FD_CLOSE ) ) { D(bug("<%d> WSAEventSelect() failed with error code %d\r\n", t, _WSAGetLastError())); } D(bug("<%d> connecting local port %d to remote %s:%d\r\n", t, src_port, _inet_ntoa(sockets[t].from.sin_addr), dest_port)); sockets[t].state = LISTEN; if( _WSAConnect( sockets[t].s, (const struct sockaddr *)&sockets[t].from, sockets[t].from_len, NULL, NULL, NULL, NULL ) == SOCKET_ERROR ) { int connect_error = _WSAGetLastError(); if( connect_error == WSAEWOULDBLOCK ) { D(bug("<%d> WSAConnect() i/o pending.\r\n", t)); } else { D(bug("<%d> WSAConnect() failed with error %d.\r\n", t, connect_error)); } } else { D(bug("<%d> WSAConnect() ok.\r\n", t)); } } else { if( ISSET(tcp->flags,FIN) ) { D(bug("<%d> No SYN but FIN on a closed socket.\r\n", t)); free_socket(t); } else { D(bug("<%d> No SYN on a closed socket. resetting.\r\n", t)); free_socket(t); } } break; case LISTEN: // handled in connect callback break; case SYN_SENT: if( ISSET(tcp->flags,SYN) && ISSET(tcp->flags,ACK) ) { sockets[t].seq_in = ntohl(tcp->seq) + 1; tcp_reply( ACK, t ); sockets[t].state = ESTABLISHED; initiate_read = true; sockets[t].accept_more_data_from_mac = true; sockets[t].time_wait = 0; } else if( ISSET(tcp->flags,SYN) ) { sockets[t].seq_in = ntohl(tcp->seq) + 1; tcp_reply( ACK|SYN, t ); sockets[t].seq_out++; sockets[t].state = SYN_RCVD; sockets[t].time_wait = 0; } else if( ISSET(tcp->flags,ACK) ) { // What was the bright idea here. D(bug("<%d> State is SYN_SENT, but got only ACK from Mac??\r\n", t)); sockets[t].state = FINWAIT_2; sockets[t].time_wait = 0; } break; case SYN_RCVD: if( ISSET(tcp->flags,ACK) ) { sockets[t].state = ESTABLISHED; handle_data = true; initiate_read = true; sockets[t].accept_more_data_from_mac = true; } break; case ESTABLISHED: if( ISSET(tcp->flags,FIN) ) { sockets[t].seq_in++; tcp_reply( ACK, t ); _shutdown( sockets[t].s, SD_SEND ); sockets[t].state = CLOSE_WAIT; } handle_data = true; break; case CLOSE_WAIT: // handled in tcp_read_completion break; case LAST_ACK: if( ISSET(tcp->flags,ACK) ) { D(bug("<%d> LAST_ACK received, socket closed\r\n", t)); free_socket( t ); } break; case FINWAIT_1: if( ISSET(tcp->flags,FIN) && ISSET(tcp->flags,ACK) ) { sockets[t].seq_in++; tcp_reply( ACK, t ); if(sockets[t].remote_closed) { _closesocket(sockets[t].s); sockets[t].s = INVALID_SOCKET; } else { _shutdown( sockets[t].s, SD_SEND ); } sockets[t].state = TIME_WAIT; sockets[t].time_wait = GetTickCount() + 2 * sockets[t].msl; } else if( ISSET(tcp->flags,FIN) ) { sockets[t].seq_in++; tcp_reply( ACK, t ); if(sockets[t].remote_closed) { _closesocket(sockets[t].s); sockets[t].s = INVALID_SOCKET; } else { _shutdown( sockets[t].s, SD_SEND ); } sockets[t].state = CLOSING; } else if( ISSET(tcp->flags,ACK) ) { sockets[t].state = FINWAIT_2; } break; case FINWAIT_2: if( ISSET(tcp->flags,FIN) ) { sockets[t].seq_in++; tcp_reply( ACK, t ); if(sockets[t].remote_closed) { _closesocket(sockets[t].s); sockets[t].s = INVALID_SOCKET; } else { _shutdown( sockets[t].s, SD_SEND ); } sockets[t].state = TIME_WAIT; sockets[t].time_wait = GetTickCount() + 2 * sockets[t].msl; } break; case CLOSING: if( ISSET(tcp->flags,ACK) ) { sockets[t].state = TIME_WAIT; sockets[t].time_wait = GetTickCount() + 2 * sockets[t].msl; } break; case TIME_WAIT: // Catching stray packets: wait MSL * 2 seconds, -> CLOSED // Timer already set since we might not get here at all. // I'm using exceptionally low MSL value (5 secs). D(bug("<%d> time wait, datagram discarded\r\n", t)); break; } // The "t" descriptor may already be freed. However, it's safe // to peek the state value inside the critical section. D(bug("<%d> State machine end = %s\r\n", t, STATENAME(sockets[t].state))); D(bug("<%d> handle_data=%d, initiate_read=%d\r\n", t, handle_data, initiate_read)); if( handle_data && dlen && sockets[t].accept_more_data_from_mac ) { if( sockets[t].seq_in != ntohl(tcp->seq) ) { D(bug("<%d> dropping duplicate datagram seq=%d, expected=%d\r\n", t, ntohl(tcp->seq), sockets[t].seq_in)); } else { set_ttl( t, tcp->ip.ttl ); struct sockaddr_in to; memset( &to, 0, sizeof(to) ); to.sin_family = AF_INET; to.sin_port = tcp->dest_port; to.sin_addr.s_addr = tcp->ip.dest; D(bug("<%d> sending %d bytes to remote host\r\n", t, dlen)); sockets[t].accept_more_data_from_mac = false; if( dlen > MAX_SEGMENT_SIZE ) { D(bug("<%d> IMPOSSIBLE: b_send() dropped %d bytes! \r\n", t, dlen-MAX_SEGMENT_SIZE)); dlen = MAX_SEGMENT_SIZE; } memcpy( sockets[t].buffers_write[0].buf, data, dlen ); sockets[t].buffers_write[0].len = dlen; sockets[t].bytes_remaining_to_send = dlen; sockets[t].bytes_to_send = dlen; bool send_now = false; if( ISSET(tcp->flags,PSH) ) { send_now = true; } else { // todo -- delayed send send_now = true; } if(send_now) { // Patch ftp server or client address if needed. int lst = 1; bool is_pasv; uint16 ftp_data_port = 0; if(ftp_is_ftp_port(sockets[t].src_port)) { // Local ftp server may be entering to passive mode. is_pasv = true; ftp_parse_port_command( sockets[t].buffers_write[0].buf, dlen, ftp_data_port, is_pasv ); } else if(ftp_is_ftp_port(sockets[t].dest_port)) { // Local ftp client may be using port command. is_pasv = false; ftp_parse_port_command( sockets[t].buffers_write[0].buf, dlen, ftp_data_port, is_pasv ); } if(ftp_data_port) { D(bug("<%d> ftp %s command detected, port %d\r\n", t, (is_pasv ? "SERVER PASV REPLY" : "CLIENT PORT"), ftp_data_port )); // Note: for security reasons, only allow incoming connection from sockets[t].ip_dest lst = alloc_listen_socket( ftp_data_port, sockets[t].ip_dest, 0/*iface*/, true ); if(lst < 0) { D(bug("<%d> no more free slots\r\n", t)); } else { // First start listening (need to know the local name later) tcp_start_listen( lst ); // When t is closed, lst must be closed too. sockets[t].child = lst; l_sockets[lst].parent = t; // Find out the local name struct sockaddr_in name; int namelen = sizeof(name); memset( &name, 0, sizeof(name) ); if( _getsockname( sockets[t].s, (struct sockaddr *)&name, &namelen ) == SOCKET_ERROR ) { D(bug("_getsockname() failed, error=%d\r\n", _WSAGetLastError() )); } ftp_modify_port_command( sockets[t].buffers_write[0].buf, dlen, MAX_SEGMENT_SIZE, ntohl(name.sin_addr.s_addr), ftp_data_port, is_pasv ); sockets[t].buffers_write[0].len = dlen; sockets[t].bytes_remaining_to_send = dlen; // Do not change "bytes_to_send" field as it is used for ack calculation } } // end of ftp patch if(!b_send(t)) { // on error, close the ftp data listening socket if one was created if(lst >= 0) { D(bug("[%d] closing listening port %d after write error\r\n", t, l_sockets[lst].port)); _closesocket( l_sockets[lst].s ); l_sockets[lst].s = INVALID_SOCKET; l_sockets[lst].port = 0; l_sockets[lst].ip = 0; l_sockets[lst].parent = -1; sockets[t].child = -1; } } } } } if(initiate_read) { if(!b_recfrom(t)) { // post icmp error message } } } LeaveCriticalSection( &tcp_section ); }
static void CALLBACK tcp_read_completion( DWORD error, DWORD bytes_read, LPWSAOVERLAPPED lpOverlapped, DWORD flags ) { EnterCriticalSection( &tcp_section ); const int t = (int)lpOverlapped->hEvent; sockets[t].bytes_received = bytes_read; D(bug("<%d> tcp_read_completion(error=%d, bytes_read=%d)\r\n", t, error, bytes_read)); D(bug("<%d> tcp_read_completion() start, old state = %s\r\n", t, STATENAME(sockets[t].state))); if(!sockets[t].in_use) { D(bug("<%d> ignoring canceled read\r\n", t)); } else { if( error != 0 ) { D(bug("<%d> resetting after read error\r\n", t)); tcp_reply( RST, t ); free_socket(t); } else { if(bytes_read == 0) { _closesocket( sockets[t].s ); sockets[t].s = INVALID_SOCKET; } else if( bytes_read > 0) { send_buffer( t, false ); } switch( sockets[t].state ) { case SYN_RCVD: if( bytes_read == 0 ) { D(bug("<%d> Closing: SYN_RCVD -> FINWAIT_1\r\n", t)); tcp_reply( ACK|FIN, t ); sockets[t].seq_out++; sockets[t].state = FINWAIT_1; } break; case ESTABLISHED: if( bytes_read == 0 ) { D(bug("<%d> Closing: ESTABLISHED -> FINWAIT_1\r\n", t)); tcp_reply( ACK|FIN, t ); sockets[t].seq_out++; sockets[t].state = FINWAIT_1; } break; case LISTEN: tcp_reply( SYN, t ); sockets[t].seq_out++; sockets[t].state = SYN_SENT; sockets[t].time_wait = GetTickCount() + SYN_FLOOD_PROTECTION_TIMEOUT; D(bug("<%d> LISTEN -> SYN_SENT\r\n", t)); break; case CLOSE_WAIT: if( bytes_read == 0) { tcp_reply( ACK|FIN, t ); sockets[t].seq_out++; sockets[t].state = LAST_ACK; D(bug("<%d> Closing: CLOSE_WAIT -> LAST_ACK\r\n", t)); if(sockets[t].remote_closed) { // Just in case that mac gets out of sync. _closesocket(sockets[t].s); sockets[t].s = INVALID_SOCKET; } } break; default: break; } if(!is_router_shutting_down && sockets[t].s != INVALID_SOCKET) { if(sockets[t].state != LISTEN) { b_recfrom(t); } } } } LeaveCriticalSection( &tcp_section ); }
static unsigned int WINAPI tcp_listen_thread(void *arg) { WSAEVENT wait_handles[MAX_SOCKETS]; for( int i=0; i<MAX_SOCKETS; i++ ) { wait_handles[i] = l_sockets[i].ev; tcp_start_listen( i ); } while(!is_router_shutting_down) { DWORD ret = WaitForMultipleObjects( MAX_SOCKETS, wait_handles, FALSE, 200 ); if(is_router_shutting_down) break; EnterCriticalSection( &tcp_section ); if( ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + MAX_SOCKETS ) { const int lst = ret - WAIT_OBJECT_0; D(bug("[%d] connection attempt to port %d\r\n", lst, l_sockets[lst].port)); WSANETWORKEVENTS what; if( _WSAEnumNetworkEvents( l_sockets[lst].s, l_sockets[lst].ev, &what ) != SOCKET_ERROR ) { if( what.lNetworkEvents & FD_ACCEPT ) { if( what.iErrorCode[FD_ACCEPT_BIT] == 0 ) { D(bug("[%d] Connect ok\r\n", lst)); tcp_accept_callback(lst); } else { D(bug("[%d] Connect error=%d\r\n", lst, what.iErrorCode[FD_ACCEPT_BIT])); // Post icmp error } } } // close on errors too if(l_sockets[lst].once) { D(bug("[%d] once mode: closing listening socket on port %d\r\n", lst, l_sockets[lst].port)); if( _closesocket( l_sockets[lst].s ) == SOCKET_ERROR ) { int err = _WSAGetLastError(); D(bug("[%d] close error %d\r\n", lst, err)); } l_sockets[lst].s = INVALID_SOCKET; l_sockets[lst].port = 0; l_sockets[lst].ip = 0; int t = l_sockets[lst].parent; if( t >= 0 ) { sockets[t].child = -1; } l_sockets[lst].parent = -1; } _WSAResetEvent( l_sockets[lst].ev ); } LeaveCriticalSection( &tcp_section ); } return 0; }
/********************************************************************* * * _Disconnect * * Function description * This function is called from the FTP server module to close the * the data connection. */ static void _Disconnect(FTPS_SOCKET socket) { _closesocket((long) socket); }