size_t TCPSocket::writeStream(const byte *rgbWrite, size_t cbWrite, IPSTATUS * pStatus) { // make sure we are Connected // this will also run the stack if(TCPIsEstablished(&_socket, pStatus)) { return(TCPWrite(&_socket, rgbWrite, cbWrite, pStatus)); } return(0); }
/*** bool TCPServer::getAvailableClientsRemoteEndPoint(IPEndPoint *pRemoteEP, int index) ** bool TCPServer::getAvailableClientsRemoteEndPoint(IPEndPoint *pRemoteEP, MAC * pRemoteMAC, int index) ** ** Synopsis: ** Returns endpoint information about a TCPSocket waiting to be accepted. ** ** Parameters: ** pRemoteEP A pointer to an IPEndPoint to receive the remote endpoint information for the client ** waiting to be accepted. This may be NULL if you don't want the info ** ** pRemoteMAC A pointer to a MAC to receive the remote MAC address of the client waiting to be accepted. ** This will be the MAC address as known by ARP and will only have MAC address of machines ** on your local area network. If the IP is not local, the MAC will most probably be the MAC ** of your router. This may be NULL if you don't want the info ** ** index This is a zero based index and must be less than what AvailableClients returns. It ** selects the Client within the server list that you want remote endpoint information on. ** ** Return Values: ** true The local endpoint was returned. ** false An error occured, most likely your index was out of range ** ** Errors: ** None ** ** Notes: ** ** This allows you to determine if you want to accept this endpoint before removing it from ** the server. It allows you to accept other clients first and out of order. ** ** This call should be made immediately after AvailableClients and immediately before ** AcceptClient so that the servers pending list does not change due to another connection. ** */ bool TCPServer::getAvailableClientsRemoteEndPoint(IPEndPoint& epRemote, int index) { FFLL * pffllSocket = NULL; int c = 0; while((pffllSocket = (FFLL *) FFNext(&_ffptSockets, pffllSocket)) != NULL) { TCPSocket& tcpSocket = *((TCPSocket *) (pffllSocket->_this)); // for syntax sake if(TCPIsEstablished(&tcpSocket._socket, NULL) && c == index) { return(tcpSocket.getRemoteEndPoint(epRemote)); } } return(false); }
// We can get errors, you passed me a NULL, or an opened TCPSocket, or index out of range. TCPSocket * TCPServer::acceptClient(int index) { FFLL * pffllSocket = NULL; int c = 0; while((pffllSocket = (FFLL *) FFNext(&_ffptSockets, pffllSocket)) != NULL) { TCPSocket& tcpSocket = *((TCPSocket *) (pffllSocket->_this)); // for syntax sake if(TCPIsEstablished(&tcpSocket._socket, NULL) && c == index) { FFRemove(&_ffptSockets, pffllSocket); tcpSocket._classState = ipsInUseW; return(&tcpSocket); } } return(NULL); }
/***************************************************************************** Function: uint32_t TCPSend(SOCKET * pSocket, const void * pv, uint32_t cb, IPSTATUS * pStatus) Description: Stuff data into the socket to be sent on the next regularly scheduled send. Because of congestion control, this may take up to a fraction of a second to send. If you want it to go out immediately then call TCPFlush on the socket immediately after this call. Parameters: pSocket: The socket to send the data on pv: a pointer to a buffer of data to send cbReq: The number of bytes to send. pStatus: A pointer to a status variable to recieve the state of the send Returns: Number of bytes actually sent, could be less than requested if the socket is full. ***************************************************************************/ uint32_t TCPWrite(HSOCKET hSocket, const void * pv, uint32_t cbReq, IPSTATUS * pStatus) { TCPSOCKET * pSocket = (TCPSOCKET *) hSocket; uint32_t cb = 0; if(pSocket == NULL) { AssignStatusSafely(pStatus, ipsSocketNULL); return(0); } // we can only write data if we are in the established state if(TCPIsEstablished(pSocket, pStatus)) { SMGR * pSMGR = (SMGR*)alloca(pSocket->cbTxSMGR); if(cbReq > 0 && pSMGR != NULL && (SMGRRead((HSMGR) &pSocket->smgrRxTxBuff, pSocket->cbRxSMGR, pSMGR, pSocket->cbTxSMGR) == pSocket->cbTxSMGR)) { // This may seem like an odd place to do this, but I will update the sndUNA pointers here // I do this here instead of in the ACK processing because I do not want to take the time to open up the // stream in the ACK process, I just want to update the sndUNA pointer and move on. The downside of this is that // we may hold some pages longer than we need, but before I take MORE memory in the write, I will free those pages // which is why I will do that here before we WRITE our data below. TCPScaleSndIndexes(pSocket, pSMGR); // after we have scaled our pointers and potentially released some memory, we can // write as much data as we can to the stream cb = SMGRWrite((HSMGR) pSMGR, SMGRcbStream(pSMGR), pv, cbReq); pSocket->sndEND += cb; // save away the table that is stored on the stack // this should not fail! It is a fixed size and already allocated SMGRWrite((HSMGR) &pSocket->smgrRxTxBuff, pSocket->cbRxSMGR, pSMGR, pSocket->cbTxSMGR); } } return(cb); }
/*** int TCPServer::availableClients(void) ** ** Synopsis: ** Checks to see how many pending clients are availabe to be accepted. ** ** Parameters: ** None ** ** Return Values: ** The number of waiting TCPSockets to be accepted. ** ** Errors: ** None ** ** Notes: ** ** This is the workhorse of the TCPServer Class ** It will update pending clients if a connection is detected ** It will attempt to start listening if a socket comes avalialbe for listening ** It will clean up disconnected clients */ int TCPServer::availableClients(int& cListening, int& cWaiting, IPSTATUS * pStatus) { int cAvailable = 0; cWaiting = 0; cListening = 0; FFLL * pffllSocket = NULL; if(_pDEIPcK == NULL) { AssignStatusSafely(pStatus, ipsNotInitialized); return(0); } if(ILIsIPNetworkReady(_pDEIPcK->_pLLAdp, pStatus)) { while((pffllSocket = (FFLL *) FFNext(&_ffptSockets, pffllSocket)) != NULL) { TCPSocket& tcpSocket = *((TCPSocket *) (pffllSocket->_this)); // for syntax sake if(TCPIsEstablished(&tcpSocket._socket, NULL)) { cAvailable++; } else if(TCPIsConnected(&tcpSocket._socket, NULL)) { cWaiting++; } else if(tcpSocket._socket.tcpState == tcpListen) { cListening++; } } } return(cAvailable); }