Example #1
0
void socketClose(Socket *socket)
{
   //Make sure the socket handle is valid
   if(!socket) return;

   //Enter critical section
   osAcquireMutex(&socketMutex);

#if (TCP_SUPPORT == ENABLED)
   //Connection-oriented socket?
   if(socket->type == SOCKET_TYPE_STREAM)
   {
      //Abort the current TCP connection
      tcpAbort(socket);
   }
#endif
#if (UDP_SUPPORT == ENABLED || RAW_SOCKET_SUPPORT == ENABLED)
   //Connectionless socket or raw socket?
   if(socket->type == SOCKET_TYPE_DGRAM ||
      socket->type == SOCKET_TYPE_RAW_IP ||
      socket->type == SOCKET_TYPE_RAW_ETH)
   {
      //Point to the first item in the receive queue
      SocketQueueItem *queueItem = socket->receiveQueue;

      //Purge the receive queue
      while(queueItem)
      {
         //Keep track of the next item in the queue
         SocketQueueItem *nextQueueItem = queueItem->next;
         //Free previously allocated memory
         memPoolFree(queueItem);
         //Point to the next item
         queueItem = nextQueueItem;
      }

      //Mark the socket as closed
      socket->type = SOCKET_TYPE_UNUSED;
   }
#endif

   //Leave critical section
   osReleaseMutex(&socketMutex);
}
Example #2
0
Socket *tcpAccept(Socket *socket, IpAddr *clientIpAddr, uint16_t *clientPort)
{
   error_t error;
   Socket *newSocket;
   TcpSynQueueItem *queueItem;

   //Ensure the socket was previously placed in the listening state
   if(tcpGetState(socket) != TCP_STATE_LISTEN)
      return NULL;

   //Enter critical section
   osAcquireMutex(&socketMutex);

   //Wait for an connection attempt
   while(1)
   {
      //The SYN queue is empty?
      if(!socket->synQueue)
      {
         //Set the events the application is interested in
         socket->eventMask = SOCKET_EVENT_RX_READY;
         //Reset the event object
         osResetEvent(&socket->event);
         //Leave critical section
         osReleaseMutex(&socketMutex);
         //Wait until a SYN message is received from a client
         osWaitForEvent(&socket->event, socket->timeout);
         //Enter critical section
         osAcquireMutex(&socketMutex);
      }

      //Check whether the queue is still empty
      if(!socket->synQueue)
      {
         //Timeout error
         newSocket = NULL;
         //Exit immediately
         break;
      }

      //Point to the first item in the receive queue
      queueItem = socket->synQueue;

      //Return the client IP address and port number
      if(clientIpAddr)
         *clientIpAddr = queueItem->srcAddr;
      if(clientPort)
         *clientPort = queueItem->srcPort;

      //Leave critical section
      osReleaseMutex(&socketMutex);
      //Create a new socket to handle the incoming connection request
      newSocket = socketOpen(SOCKET_TYPE_STREAM, SOCKET_IP_PROTO_TCP);
      //Enter critical section
      osAcquireMutex(&socketMutex);

      //Socket successfully created?
      if(newSocket != NULL)
      {
         //The user owns the socket
         newSocket->ownedFlag = TRUE;

         //Inherit settings from the listening socket
         newSocket->txBufferSize = socket->txBufferSize;
         newSocket->rxBufferSize = socket->rxBufferSize;

         //Number of chunks that comprise the TX and the RX buffers
         newSocket->txBuffer.maxChunkCount = arraysize(newSocket->txBuffer.chunk);
         newSocket->rxBuffer.maxChunkCount = arraysize(newSocket->rxBuffer.chunk);

         //Allocate transmit buffer
         error = netBufferSetLength((NetBuffer *) &newSocket->txBuffer, newSocket->txBufferSize);

         //Check status code
         if(!error)
         {
            //Allocate receive buffer
            error = netBufferSetLength((NetBuffer *) &newSocket->rxBuffer, newSocket->rxBufferSize);
         }

         //Transmit and receive buffers successfully allocated?
         if(!error)
         {
            //Bind the newly created socket to the appropriate interface
            newSocket->interface = queueItem->interface;
            //Bind the socket to the specified address
            newSocket->localIpAddr = queueItem->destAddr;
            newSocket->localPort = socket->localPort;
            //Save the port number and the IP address of the remote host
            newSocket->remoteIpAddr = queueItem->srcAddr;
            newSocket->remotePort = queueItem->srcPort;
            //Save the maximum segment size
            newSocket->mss = queueItem->mss;

            //Initialize TCP control block
            newSocket->iss = netGetRand();
            newSocket->irs = queueItem->isn;
            newSocket->sndUna = newSocket->iss;
            newSocket->sndNxt = newSocket->iss + 1;
            newSocket->rcvNxt = newSocket->irs + 1;
            newSocket->rcvUser = 0;
            newSocket->rcvWnd = newSocket->rxBufferSize;

            //Default retransmission timeout
            newSocket->rto = TCP_INITIAL_RTO;

#if (TCP_CONGESTION_CONTROL_SUPPORT == ENABLED)
            //Initial congestion window
            newSocket->cwnd = MIN(TCP_INITIAL_WINDOW * newSocket->mss, newSocket->txBufferSize);
            //Slow start threshold should be set arbitrarily high
            newSocket->ssthresh = UINT16_MAX;
#endif

            //Send a SYN ACK control segment
            error = tcpSendSegment(newSocket, TCP_FLAG_SYN | TCP_FLAG_ACK,
               newSocket->iss, newSocket->rcvNxt, 0, TRUE);

            //TCP segment successfully sent?
            if(!error)
            {
               //Remove the item from the SYN queue
               socket->synQueue = queueItem->next;
               //Deallocate memory buffer
               memPoolFree(queueItem);
               //Update the state of events
               tcpUpdateEvents(socket);

               //The connection state should be changed to SYN-RECEIVED
               tcpChangeState(newSocket, TCP_STATE_SYN_RECEIVED);

               //We are done...
               break;
            }
         }

         //Dispose the socket
         tcpAbort(newSocket);
      }

      //Debug message
      TRACE_WARNING("Cannot accept TCP connection!\r\n");

      //Remove the item from the SYN queue
      socket->synQueue = queueItem->next;
      //Deallocate memory buffer
      memPoolFree(queueItem);

      //Wait for the next connection attempt
   }

   //Leave critical section
   osReleaseMutex(&socketMutex);

   //Return a handle to the newly created socket
   return newSocket;
}