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);
}
示例#4
0
/*****************************************************************************
  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);
}