teTCPError TCPServerConnection::disconnect( void ) { if (!listening()) return setError(eTCPSocketNFG); std::map<TCPsocket,TCPServerConnectedPeer>::iterator itr = peers.begin(); while ( itr != peers.end() ) { for ( unsigned int i = 0; i < dataPendingList.size(); i++ ) dataPendingList[i]->disconnect(this,&itr->second,true); net_TCP_Close(itr->first); net_DelSocket(socketSet,(net_GenericSocket)itr->first); } peers.clear(); net_TCP_Close(socket); net_DelSocket(socketSet,(net_GenericSocket)socket); net_FreeSocketSet(socketSet); socketSet = NULL; socket = NULL; return setError(eTCPNoError); }
bool TCPServerConnection::disconectPeer ( TCPServerConnectedPeer* peer ) { if (!peer) return false; std::map<TCPsocket,TCPServerConnectedPeer>::iterator itr = peers.begin(), itr2 = peers.begin(); while ( itr != peers.end() ) { if (&itr->second == peer ) { // they got discoed. for ( unsigned int i = 0; i < dataPendingList.size(); i++ ) dataPendingList[i]->disconnect(this,peer,true); net_TCP_DelSocket(socketSet, itr->first); net_TCP_Close(itr->first); itr2 = itr; itr2++; peers.erase(itr); itr = itr2; return true; } itr++; } return false; }
/* Accept an incoming connection on the given server socket. The newly created socket is returned, or NULL if there was an error. */ TCPsocket net_TCP_Accept(TCPsocket server) { TCPsocket sock; struct sockaddr_in sock_addr; socklen_t sock_alen; /* Only server sockets can accept */ if ( ! server->sflag ) { net_SetError("Only server sockets can accept()"); return(NULL); } server->ready = 0; /* Allocate a TCP socket structure */ sock = (TCPsocket)malloc(sizeof(*sock)); if ( sock == NULL ) { net_SetError("Out of memory"); goto error_return; } /* Accept a new TCP connection on a server socket */ sock_alen = sizeof(sock_addr); sock->channel = accept(server->channel, (struct sockaddr *)&sock_addr, #ifdef USE_GUSI_SOCKETS (unsigned int *)&sock_alen); #else &sock_alen); #endif if ( sock->channel == SOCKET_ERROR ) { net_SetError("accept() failed"); goto error_return; } #ifdef WIN32 { /* passing a zero value, socket mode set to block on */ unsigned long mode = 0; ioctlsocket (sock->channel, FIONBIO, &mode); } #endif /* WIN32 */ sock->remoteAddress.host = sock_addr.sin_addr.s_addr; sock->remoteAddress.port = sock_addr.sin_port; sock->sflag = 0; sock->ready = 0; /* The socket is ready */ return(sock); error_return: net_TCP_Close(sock); return(NULL); }
teTCPError TCPClientConnection::disconnect( void ) { if (!connected()) return setError(eTCPSocketNFG); net_TCP_Close(socket); socket = NULL; if (parent) parent->removeClientSocket(this); return setError(eTCPNoError); }
bool TCPServerConnection::update ( void ) { if (net_CheckSockets(socketSet, ~0) < 1) return true; // see if our boys have any new connections if ( net_SocketReady(socket) ) { TCPsocket newsock; newsock = net_TCP_Accept(socket); while ( newsock != NULL ) { TCPServerConnectedPeer peer; peer.connect(newsock); peers[newsock] = peer; bool accept = true; for ( unsigned int i = 0; i < dataPendingList.size(); i++ ) { if ( !dataPendingList[i]->connect(this,&(peers[newsock])) ) accept = false; } if (accept) net_TCP_AddSocket(socketSet, newsock); else { peers.erase(peers.find(newsock)); net_TCP_Close(newsock); } newsock = net_TCP_Accept(socket); } } std::map<TCPsocket,TCPServerConnectedPeer>::iterator itr = peers.begin(), itr2 = peers.begin(); while ( itr != peers.end() ) { if (net_SocketReady(itr->first)) { if (itr->second.readData()) { if ( itr->second.getPacketCount()) { for ( unsigned int i = 0; i < dataPendingList.size(); i++ ) dataPendingList[i]->pending(this,&itr->second,itr->second.getPacketCount()); } itr++; } else { // they got discoed. for ( unsigned int i = 0; i < dataPendingList.size(); i++ ) dataPendingList[i]->disconnect(this,&itr->second); net_TCP_DelSocket(socketSet, itr->first); net_TCP_Close(itr->first); itr2 = itr; itr2++; peers.erase(itr); itr = itr2; return true; } } else itr++; } return true; }
/* Open a TCP network socket If 'remote' is NULL, this creates a local server socket on the given port, otherwise a TCP connection to the remote host and port is attempted. The newly created socket is returned, or NULL if there was an error. */ TCPsocket net_TCP_Open(IPaddress *ip) { TCPsocket sock; struct sockaddr_in sock_addr; /* Allocate a TCP socket structure */ sock = (TCPsocket)malloc(sizeof(*sock)); if ( sock == NULL ) { net_SetError("Out of memory"); goto error_return; } /* Open the socket */ sock->channel = socket(AF_INET, SOCK_STREAM, 0); if ( sock->channel == INVALID_SOCKET ) { net_SetError("Couldn't create socket"); goto error_return; } /* Connect to remote, or bind locally, as appropriate */ if ( (ip->host != INADDR_NONE) && (ip->host != INADDR_ANY) ) { // ######### Connecting to remote memset(&sock_addr, 0, sizeof(sock_addr)); sock_addr.sin_family = AF_INET; sock_addr.sin_addr.s_addr = ip->host; sock_addr.sin_port = ip->port; /* Connect to the remote host */ if ( connect(sock->channel, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) == SOCKET_ERROR ) { net_SetError("Couldn't connect to remote host"); goto error_return; } sock->sflag = 0; } else { // ########## Binding locally memset(&sock_addr, 0, sizeof(sock_addr)); sock_addr.sin_family = AF_INET; sock_addr.sin_addr.s_addr = INADDR_ANY; sock_addr.sin_port = ip->port; /* allow local address reuse */ { int yes = 1; setsockopt(sock->channel, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes)); } /* Bind the socket for listening */ if ( bind(sock->channel, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) == SOCKET_ERROR ) { net_SetError("Couldn't bind to local port"); goto error_return; } if ( listen(sock->channel, 5) == SOCKET_ERROR ) { net_SetError("Couldn't listen to local port"); goto error_return; } #ifdef O_NONBLOCK /* Set the socket to non-blocking mode for accept() */ fcntl(sock->channel, F_SETFL, O_NONBLOCK); #else #ifdef WIN32 { /* passing a non-zero value, socket mode set non-blocking */ unsigned long mode = 1; ioctlsocket (sock->channel, FIONBIO, &mode); } #else #warning How do we set non-blocking mode on other operating systems? #endif /* WIN32 */ #endif /* O_NONBLOCK */ sock->sflag = 1; } sock->ready = 0; #ifdef TCP_NODELAY /* Set the nodelay TCP option for real-time games */ { int yes = 1; setsockopt(sock->channel, IPPROTO_TCP, TCP_NODELAY, (char*)&yes, sizeof(yes)); } #endif /* TCP_NODELAY */ /* Fill in the channel host address */ sock->remoteAddress.host = sock_addr.sin_addr.s_addr; sock->remoteAddress.port = sock_addr.sin_port; /* The socket is ready */ return(sock); error_return: net_TCP_Close(sock); return(NULL); }