JNetReturn Sender::Connect( std::string IPAddress, short port ) { SOCKET* newConnection = new SOCKET(); sockaddr_in senderAddress; senderAddress.sin_family = AF_INET; senderAddress.sin_port = 0; senderAddress.sin_addr.S_un.S_addr = inet_addr( IPAddress_.c_str() ); sockaddr_in remoteAddress; remoteAddress.sin_family = AF_INET; remoteAddress.sin_port = htons( port ); remoteAddress.sin_addr.S_un.S_addr = inet_addr( IPAddress.c_str() ); *newConnection = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0); if( *newConnection == INVALID_SOCKET ) { printf("Error, invalid socket, error code: %d\n", WSAGetLastError() ); delete newConnection; newConnection = NULL; return JNetReturn::SocketError; } //socket was created fine, time to bind it. int result = bind( *newConnection, reinterpret_cast<sockaddr*>( &senderAddress), sizeof(senderAddress) ); if( result == SOCKET_ERROR ) { printf("Error binding socket to local endpoint. Error code: %d\n", WSAGetLastError() ); FreeSocket( &newConnection ); return JNetReturn::SocketError; } result = connect( *newConnection, reinterpret_cast<sockaddr*>( &remoteAddress), sizeof(remoteAddress) ); if(result == SOCKET_ERROR ) { result = WSAGetLastError(); printf("Failed to connect. Error code: %d\n", result ); FreeSocket( &newConnection ); return JNetReturn::SocketError; } //last step create the connection try { connection_ = new Connection( newConnection ); } catch( JNetException const & exception ) { printf("Failed to create a connection object.\n"); printf("Error code: %d\nError: %s\n", exception.Code(), exception.What() ); FreeSocket( &newConnection ); } return JNetReturn::Success; }
/*----------------------------------------------------------------------------*/ int mtcp_epoll_create(mctx_t mctx, int size) { mtcp_manager_t mtcp = g_mtcp[mctx->cpu]; struct mtcp_epoll *ep; socket_map_t epsocket; if (size <= 0) { errno = EINVAL; return -1; } epsocket = AllocateSocket(mctx, MTCP_SOCK_EPOLL, FALSE); if (!epsocket) { errno = ENFILE; return -1; } ep = (struct mtcp_epoll *)calloc(1, sizeof(struct mtcp_epoll)); if (!ep) { FreeSocket(mctx, epsocket->id, FALSE); return -1; } /* create event queues */ ep->usr_queue = CreateEventQueue(size); if (!ep->usr_queue) return -1; ep->usr_shadow_queue = CreateEventQueue(size); if (!ep->usr_shadow_queue) { DestroyEventQueue(ep->usr_queue); return -1; } ep->mtcp_queue = CreateEventQueue(size); if (!ep->mtcp_queue) { DestroyEventQueue(ep->usr_queue); DestroyEventQueue(ep->usr_shadow_queue); return -1; } TRACE_EPOLL("epoll structure of size %d created.\n", size); mtcp->ep = ep; epsocket->ep = ep; if (pthread_mutex_init(&ep->epoll_lock, NULL)) { return -1; } if (pthread_cond_init(&ep->epoll_cond, NULL)) { return -1; } return epsocket->id; }
/*----------------------------------------------------------------------------*/ int mtcp_close(mctx_t mctx, int sockid) { mtcp_manager_t mtcp; int ret; mtcp = GetMTCPManager(mctx); if (!mtcp) { return -1; } if (sockid < 0 || sockid >= CONFIG.max_concurrency) { TRACE_API("Socket id %d out of range.\n", sockid); errno = EBADF; return -1; } if (mtcp->smap[sockid].socktype == MTCP_SOCK_UNUSED) { TRACE_API("Invalid socket id: %d\n", sockid); errno = EBADF; return -1; } TRACE_API("Socket %d: mtcp_close called.\n", sockid); switch (mtcp->smap[sockid].socktype) { case MTCP_SOCK_STREAM: ret = CloseStreamSocket(mctx, sockid); break; case MTCP_SOCK_LISTENER: ret = CloseListeningSocket(mctx, sockid); break; case MTCP_SOCK_EPOLL: ret = CloseEpollSocket(mctx, sockid); break; case MTCP_SOCK_PIPE: ret = PipeClose(mctx, sockid); break; default: errno = EINVAL; ret = -1; break; } FreeSocket(mctx, sockid, FALSE); return ret; }
static void tcpsock_close(Socket *sock) { TCPSocket *tcpsock = (TCPSocket*) sock; if (tcpsock->thread != NULL) { // terminate the semSendFetch semaphore, causing the handler thread to send a FIN and // later terminate. semTerminate(&tcpsock->semSendFetch); } else { FreeSocket(sock); }; };
static void ReapConfServers() { struct servercstruct *slist, *tnext; slist=serverclist; while(slist!=NULL) { tnext=slist->next; if(slist->reap) { UnlinkListItem(slist,serverclist); FreeSocket(slist->sinfo); free(slist->address); free(slist->password); free(slist); } slist=tnext; } }
bool CIocpServer::CheckClients( ) { m_ClientsLock.Enter( ); int tmpcnt = 0, tmpcnt2 = 0; for( CIndexArray<CIocpSocket>::Iter i = m_Clients.First( ); i.isValid( ); i++ ) { CIocpSocket* sock = *i; sock->m_Lock.Enter( ); //* If client should be timed out, print info :) if( m_ClientTimeout != 0 && sock->m_LastRecv < GetTickCount( ) - m_ClientTimeout ) printf( "[OBJ:%d:%s] %d(R:%d,S:%d,D:%d), %d\n", i.id( ), sock->m_Ip, sock->m_RefCount, sock->m_RRefCount, sock->m_SRefCount, sock->m_DRefCount, GetTickCount( ) - sock->m_LastRecv ); //* If client timed out, disconnect if( m_ClientTimeout > 0 ) { if( sock->m_LastRecv < GetTickCount( ) - m_ClientTimeout ) sock->CloseSocket( ); } //* If the client has no references, delete it if( sock->m_RefCount == 0 ) { sock->Disconnected( ); m_Clients.Remove( i ); sock->m_Lock.Leave( ); FreeSocket( sock ); tmpcnt2++; } else { sock->m_Lock.Leave( ); } tmpcnt++; } //printf( "Clients Count :: %d/%d/%d\n", tmpcnt2, tmpcnt, m_Clients.GetUsedCount( ) ); bool hasobjects = m_Clients.GetUsedCount( ) > 0; m_ClientsLock.Leave( ); return hasobjects; };
static __inline__ int raw_NET2_TCPConnectToIP(IPaddress *ip) { int s = -1; s = AllocSocket(TCPClientSocket); if (-1 == s) { setError("NET2: out of memory", -1); return -1; } socketHeap[s]->s.tcpSocket = snTCPOpen(ip); if (NULL == socketHeap[s]->s.tcpSocket) { setError("NET2: can't open a socket", -1); FreeSocket(s); return -1; } socketHeap[s]->state = addState; return s; }
static __inline__ int raw_NET2_TCPAcceptOnIP(IPaddress *ip) { int s = -1; s = AllocSocket(TCPServerSocket); if (-1 == s) { setError("NET2: out of memory", -1); return -1; } socketHeap[s]->s.tcpSocket = snTCPOpen(ip); if (NULL == socketHeap[s]->s.tcpSocket) { setError("NET2: can't open a socket", -1); FreeSocket(s); return -1; } socketHeap[s]->p.tcpPort = ip->port; socketHeap[s]->state = addState; return s; }
static __inline__ int raw_NET2_UDPAcceptOn(int port, int size) { int s = -1; s = AllocSocket(UDPServerSocket); if (-1 == s) { setError("NET2: out of memory", s); return -1; } socketHeap[s]->s.udpSocket = snUDPOpen(port); if (NULL == socketHeap[s]->s.udpSocket) { setError("NET2: can't open a socket", s); FreeSocket(s); return -1; } socketHeap[s]->p.udpLen = size; socketHeap[s]->state = addState; return s; }
static int PumpNetworkEvents(void *nothing) { int i = 0; #define timeOut (10) while (!doneYet) { if (-1 == snCheckSockets(socketSet, timeOut)) { setError("NET2: the CheckSockets call failed", -1); } lockData(); while ((!doneYet) && waitForRead) { waitUntilRead(); } for (i = 0; ((!doneYet) && (i < lastHeapSocket)); i++) { if (addState == socketHeap[i]->state) { switch(socketHeap[i]->type) { case unusedSocket: sendError("NET2: trying to add an unused socket", i); break; case TCPServerSocket: case TCPClientSocket: if (-1 != snTCPAddSocket(socketHeap[i]->s.tcpSocket)) { socketHeap[i]->state = readyState; } else { socketHeap[i]->state = delState; sendError("NET2: can't add a TCP socket to the socket set", i); } break; case UDPServerSocket: if (-1 != snUDPAddSocket(socketHeap[i]->s.udpSocket)) { socketHeap[i]->state = readyState; } else { socketHeap[i]->state = delState; sendError("NET2: can't add a UDP socket to the socket set", i); } break; default: sendError("NET2: invalid socket type, this should never happen", i); break; } } else if (delState == socketHeap[i]->state) { switch(socketHeap[i]->type) { case unusedSocket: sendError("NET2: trying to delete an unused socket", i); break; case TCPServerSocket: case TCPClientSocket: if (-1 == snTCPDelSocket(socketHeap[i]->s.tcpSocket)) { sendError("NET2: can't delete a TCP socket from the socket set", i); } snTCPClose(socketHeap[i]->s.tcpSocket); FreeSocket(i); break; case UDPServerSocket: if (-1 == snUDPDelSocket(socketHeap[i]->s.udpSocket)) { sendError("NET2: can't delete a UDP socket from the socket set", i); } snUDPClose(socketHeap[i]->s.udpSocket); FreeSocket(i); break; default: sendError("NET2: invalid socket type, this should never happen", i); break; } } else if ((TCPServerSocket == socketHeap[i]->type) && (snSocketReady(socketHeap[i]->s.genSocket))) { TCPsocket socket = NULL; socket = snTCPAccept(socketHeap[i]->s.tcpSocket); if (NULL != socket) { int s = -1; s = AllocSocket(TCPClientSocket); if (-1 != s) { //printf("got a connection!\n"); socketHeap[s]->s.tcpSocket = socket; socketHeap[s]->state = addState; sendEvent(NET2_TCPACCEPTEVENT, s, socketHeap[i]->p.tcpPort); } else // can't handle the connection, so close it. { snTCPClose(socket); sendError("NET2: a TCP accept failed", i); // let the app know } } } else if ((TCPClientSocket == socketHeap[i]->type) && (readyState == socketHeap[i]->state) && (snSocketReady(socketHeap[i]->s.genSocket))) { int len; CharQue *tb = &socketHeap[i]->q.tb; if (tcpQueLen <= tb->len) { waitForRead = 1; } else { len = snTCPRead(socketHeap[i]->s.tcpSocket, &tb->buf[tb->len], tcpQueLen - tb->len); if (0 < len) { int oldlen = tb->len; tb->len += len; if (0 == oldlen) { sendEvent(NET2_TCPRECEIVEEVENT, i, -1); } } else // no byte, must be dead. { socketHeap[i]->state = dyingState; sendEvent(NET2_TCPCLOSEEVENT, i, -1); } } } else if ((UDPServerSocket == socketHeap[i]->type) && (readyState == socketHeap[i]->state) && (snSocketReady(socketHeap[i]->s.genSocket))) { int recv = 0; UDPpacket *p = NULL; PacketQue *ub = &socketHeap[i]->q.ub; if (PacketQueFull(ub)) { waitForRead = 1; } else { while ((!PacketQueFull(ub)) && (NULL != (p = snUDPAllocPacket(socketHeap[i]->p.udpLen))) && (1 == (recv = snUDPRecv(socketHeap[i]->s.udpSocket, p)))) { if (PacketQueEmpty(ub)) { EnquePacket(ub, &p); sendEvent(NET2_UDPRECEIVEEVENT, i, -1); } else { EnquePacket(ub, &p); } } // unravel terminating conditions and free left over memory // if we need to if (!PacketQueFull(ub)) // if the packet que is full then everything is fine { if (NULL != p) // couldn't alloc a packet { if (0 >= recv) // ran out of packets { snUDPFreePacket(p); } } else { sendError("NET2: out of memory", i); } } } } } unlockData(); } return 0; }
/*----------------------------------------------------------------------------*/ int mtcp_abort(mctx_t mctx, int sockid) { mtcp_manager_t mtcp; tcp_stream *cur_stream; int ret; mtcp = GetMTCPManager(mctx); if (!mtcp) { return -1; } if (sockid < 0 || sockid >= CONFIG.max_concurrency) { TRACE_API("Socket id %d out of range.\n", sockid); errno = EBADF; return -1; } if (mtcp->smap[sockid].socktype == MTCP_SOCK_UNUSED) { TRACE_API("Invalid socket id: %d\n", sockid); errno = EBADF; return -1; } if (mtcp->smap[sockid].socktype != MTCP_SOCK_STREAM) { TRACE_API("Not an end socket. id: %d\n", sockid); errno = ENOTSOCK; return -1; } cur_stream = mtcp->smap[sockid].stream; if (!cur_stream) { TRACE_API("Stream %d: does not exist.\n", sockid); errno = ENOTCONN; return -1; } TRACE_API("Socket %d: mtcp_abort()\n", sockid); FreeSocket(mctx, sockid, FALSE); cur_stream->socket = NULL; if (cur_stream->state == TCP_ST_CLOSED) { TRACE_API("Stream %d: connection already reset.\n", sockid); return ERROR; } else if (cur_stream->state == TCP_ST_SYN_SENT) { /* TODO: this should notify event failure to all previous read() or write() calls */ cur_stream->state = TCP_ST_CLOSED; cur_stream->close_reason = TCP_ACTIVE_CLOSE; SQ_LOCK(&mtcp->ctx->destroyq_lock); StreamEnqueue(mtcp->destroyq, cur_stream); SQ_UNLOCK(&mtcp->ctx->destroyq_lock); mtcp->wakeup_flag = TRUE; return 0; } else if (cur_stream->state == TCP_ST_CLOSING || cur_stream->state == TCP_ST_LAST_ACK || cur_stream->state == TCP_ST_TIME_WAIT) { cur_stream->state = TCP_ST_CLOSED; cur_stream->close_reason = TCP_ACTIVE_CLOSE; SQ_LOCK(&mtcp->ctx->destroyq_lock); StreamEnqueue(mtcp->destroyq, cur_stream); SQ_UNLOCK(&mtcp->ctx->destroyq_lock); mtcp->wakeup_flag = TRUE; return 0; } /* the stream structure will be destroyed after sending RST */ if (cur_stream->sndvar->on_resetq) { TRACE_ERROR("Stream %d: calling mtcp_abort() " "when in reset queue.\n", sockid); errno = ECONNRESET; return -1; } SQ_LOCK(&mtcp->ctx->reset_lock); cur_stream->sndvar->on_resetq = TRUE; ret = StreamEnqueue(mtcp->resetq, cur_stream); SQ_UNLOCK(&mtcp->ctx->reset_lock); mtcp->wakeup_flag = TRUE; if (ret < 0) { TRACE_ERROR("(NEVER HAPPEN) Failed to enqueue the stream to close.\n"); errno = EAGAIN; return -1; } return 0; }
static void tcpThread(void *context) { Socket *sock = (Socket*) context; TCPSocket *tcpsock = (TCPSocket*) context; Semaphore *sems[4] = {&tcpsock->semConnected, &tcpsock->semStop, &tcpsock->semAck, &tcpsock->semAckOut}; Semaphore *semsOut[3] = {&tcpsock->semStop, &tcpsock->semAckOut, &tcpsock->semSendFetch}; detachMe(); uint16_t srcport, dstport; if (sock->domain == AF_INET) { const struct sockaddr_in *inaddr = (const struct sockaddr_in*) &tcpsock->peername; struct sockaddr_in *inname = (struct sockaddr_in*) &tcpsock->sockname; srcport = inname->sin_port; dstport = inaddr->sin_port; } else { const struct sockaddr_in6 *inaddr = (const struct sockaddr_in6*) &tcpsock->peername; struct sockaddr_in6 *inname = (struct sockaddr_in6*) &tcpsock->sockname; inname->sin6_family = AF_INET6; srcport = inname->sin6_port; dstport = inaddr->sin6_port; }; int connectDone = 0; if (tcpsock->state == TCP_ESTABLISHED) { sems[0] = NULL; connectDone = 1; }; int wantExit = 0; while (1) { if (wantExit) break; uint64_t deadline = getNanotime() + sock->options[GSO_SNDTIMEO]; if (sock->options[GSO_SNDTIMEO] == 0) { deadline = 0; }; int sendOK = 0; int retransCount = 16; while (((getNanotime() < deadline) || (deadline == 0)) && (retransCount--)) { tcpsock->currentOut->segment->ackno = htonl(tcpsock->nextAckNo); ChecksumOutbound(tcpsock->currentOut); int status = sendPacketEx(&tcpsock->sockname, &tcpsock->peername, tcpsock->currentOut->segment, tcpsock->currentOut->size, IPPROTO_TCP, sock->options, sock->ifname); if (status != 0) { tcpsock->sockErr = -status; if (tcpsock->state == TCP_CONNECTING) { semSignal(&tcpsock->semConnected); }; tcpsock->state = TCP_TERMINATED; kfree(tcpsock->currentOut); wantExit = 1; break; }; uint8_t bitmap = 0; if (semPoll(4, sems, &bitmap, 0, TCP_RETRANS_TIMEOUT) == 0) { continue; }; if (bitmap & (1 << 1)) { kfree(tcpsock->currentOut); tcpsock->state = TCP_TERMINATED; wantExit = 1; break; }; if (bitmap & (1 << 2)) { semWait(&tcpsock->semAck); sendOK = 1; break; }; if (bitmap & (1 << 3)) { semWaitGen(&tcpsock->semAckOut, -1, 0, 0); }; }; if (wantExit) break; int wasFin = tcpsock->currentOut->segment->flags & TCP_FIN; kfree(tcpsock->currentOut); if (!sendOK) { tcpsock->sockErr = ETIMEDOUT; if (tcpsock->state == TCP_CONNECTING) { semSignal(&tcpsock->semConnected); }; tcpsock->state = TCP_TERMINATED; return; }; if (!connectDone) { while ((getNanotime() < deadline) || (deadline == 0)) { uint8_t bitmap = 0; semPoll(3, sems, &bitmap, 0, sock->options[GSO_SNDTIMEO]); if (bitmap & (1 << 1)) { tcpsock->state = TCP_TERMINATED; return; }; if (bitmap & (1 << 0)) { connectDone = 1; break; }; }; if (!connectDone) { tcpsock->sockErr = ETIMEDOUT; semSignal(&tcpsock->semConnected); tcpsock->state = TCP_TERMINATED; return; }; sems[0] = NULL; tcpsock->state = TCP_ESTABLISHED; }; if (wasFin) break; while (1) { uint8_t bitmap = 0; semPoll(3, semsOut, &bitmap, 0, 0); if (bitmap & (1 << 2)) { if (bitmap & (1 << 1)) { semWaitGen(&tcpsock->semAckOut, -1, 0, 0); }; int count = semWaitGen(&tcpsock->semSendFetch, 512, 0, 0); TCPOutbound *ob = CreateOutbound(&tcpsock->sockname, &tcpsock->peername, (size_t)count); ob->segment->srcport = srcport; ob->segment->dstport = dstport; ob->segment->seqno = htonl(tcpsock->nextSeqNo); // ackno filled in at the start of the loop iteration ob->segment->dataOffsetNS = 0x50; ob->segment->flags = TCP_PSH | TCP_ACK; // a count of zero means end of data, so send FIN. if (count == 0) { ob->segment->flags = TCP_FIN | TCP_ACK; tcpsock->nextSeqNo++; }; ob->segment->winsz = htons(TCP_BUFFER_SIZE); uint8_t *put = (uint8_t*) &ob->segment[1]; uint32_t size = (uint32_t)count; while (count--) { *put++ = tcpsock->bufSend[tcpsock->idxSendFetch]; tcpsock->idxSendFetch = (tcpsock->idxSendFetch+1) % TCP_BUFFER_SIZE; }; tcpsock->nextSeqNo += size; tcpsock->expectedAck = tcpsock->nextSeqNo; tcpsock->currentOut = ob; semSignal2(&tcpsock->semSendPut, (int)size); break; // continues the outer loop }; if (bitmap & (1 << 1)) { semWaitGen(&tcpsock->semAckOut, -1, 0, 0); TCPOutbound *ob = CreateOutbound(&tcpsock->sockname, &tcpsock->peername, 0); TCPSegment *ack = ob->segment; ack->srcport = srcport; ack->dstport = dstport; ack->seqno = htonl(tcpsock->nextSeqNo); ack->ackno = htonl(tcpsock->nextAckNo); ack->dataOffsetNS = 0x50; ack->flags = TCP_ACK; ack->winsz = htons(TCP_BUFFER_SIZE); ChecksumOutbound(ob); sendPacketEx(&tcpsock->sockname, &tcpsock->peername, ob->segment, ob->size, IPPROTO_TCP, sock->options, sock->ifname); kfree(ob); }; if (bitmap & (1 << 0)) { tcpsock->state = TCP_TERMINATED; wantExit = 1; break; }; }; }; // wait up to 4 minutes, acknowledging any packets if necessary (during a clean exit) uint64_t deadline = getNanotime() + 4UL * 60UL * 1000000000UL; uint64_t currentTime; Semaphore *semsClosing[2] = {&tcpsock->semStop, &tcpsock->semAckOut}; while ((currentTime = getNanotime()) < deadline) { uint8_t bitmap = 0; semPoll(2, semsClosing, &bitmap, 0, deadline - currentTime); if (bitmap & (1 << 0)) { wantExit = 1; semsClosing[0] = NULL; }; if (bitmap & (1 << 1)) { if (!wantExit) { semWaitGen(&tcpsock->semAckOut, -1, 0, 0); TCPOutbound *ob = CreateOutbound(&tcpsock->sockname, &tcpsock->peername, 0); TCPSegment *ack = ob->segment; ack->srcport = srcport; ack->dstport = dstport; ack->seqno = htonl(tcpsock->nextSeqNo); ack->ackno = htonl(tcpsock->nextAckNo); ack->dataOffsetNS = 0x50; ack->flags = TCP_FIN | TCP_ACK; ack->winsz = htons(TCP_BUFFER_SIZE); ChecksumOutbound(ob); sendPacketEx(&tcpsock->sockname, &tcpsock->peername, ob->segment, ob->size, IPPROTO_TCP, sock->options, sock->ifname); kfree(ob); }; }; }; // wait for the socket to actually be closed by the application (in case it wasn't already) while (semWaitGen(&tcpsock->semSendFetch, 512, 0, 0) != 0); // free the port and socket FreePort(srcport); FreeSocket(sock); };