Esempio n. 1
0
error_t udpReceiveDatagram(Socket *socket, IpAddr *srcIpAddr, uint16_t *srcPort,
   IpAddr *destIpAddr, void *data, size_t size, size_t *received, uint_t flags)
{
   SocketQueueItem *queueItem;

   //The receive queue is empty?
   if(!socket->receiveQueue)
   {
      //Set the events the application is interested in
      socket->eventMask = SOCKET_EVENT_RX_READY;
      //Reset the event object
      osEventReset(socket->event);
      //Leave critical section
      osMutexRelease(socketMutex);
      //Wait until an event is triggered
      osEventWait(socket->event, socket->timeout);
      //Enter critical section
      osMutexAcquire(socketMutex);
   }

   //Check whether the read operation timed out
   if(!socket->receiveQueue)
   {
      //No data can be read
      *received = 0;
      //Report a timeout error
      return ERROR_TIMEOUT;
   }

   //Point to the first item in the receive queue
   queueItem = socket->receiveQueue;
   //Copy data to user buffer
   *received = chunkedBufferRead(data, queueItem->buffer, queueItem->offset, size);

   //Save the source IP address
   if(srcIpAddr)
      *srcIpAddr = queueItem->srcIpAddr;
   //Save the source port number
   if(srcPort)
      *srcPort = queueItem->srcPort;
   //Save the destination IP address
   if(destIpAddr)
      *destIpAddr = queueItem->destIpAddr;

   //If the SOCKET_FLAG_PEEK flag is set, the data is copied
   //into the buffer but is not removed from the input queue
   if(!(flags & SOCKET_FLAG_PEEK))
   {
      //Remove the item from the receive queue
      socket->receiveQueue = queueItem->next;
      //Deallocate memory buffer
      chunkedBufferFree(queueItem->buffer);
   }

   //Update the state of events
   udpUpdateEvents(socket);

   //Successful read operation
   return NO_ERROR;
}
Esempio n. 2
0
error_t dhcpv6RelayStop(Dhcpv6RelayCtx *context)
{
   uint_t i;

   //Debug message
   TRACE_INFO("Stopping DHCPv6 relay agent...\r\n");

   //Ensure the specified pointer is valid
   if(!context)
      return ERROR_INVALID_PARAMETER;
   //Check DHCPv6 relay agent state
   if(!context->running)
      return ERROR_WRONG_STATE;

   //Reset ACK event before sending the kill signal
   osEventReset(context->ackEvent);
   //Stop the DHCPv6 relay agent task
   context->stopRequest = TRUE;
   //Send a signal to the task in order to abort any blocking operation
   osEventSet(context->event);

   //Wait for the process to terminate...
   osEventWait(context->ackEvent, INFINITE_DELAY);

   //Leave the All_DHCP_Relay_Agents_and_Servers multicast group
   //for each client-facing interface
   dhcpv6RelayLeaveMulticastGroup(context);

   //Close the socket that carries traffic towards the DHCPv6 server
   socketClose(context->serverSocket);

   //Properly dispose the sockets that carry traffic towards the DHCPv6 clients
   for(i = 0; i < context->clientInterfaceCount; i++)
      socketClose(context->clientSocket[i]);

   //Close event objects
   osEventClose(context->event);
   osEventClose(context->ackEvent);

   //Successful processing
   return NO_ERROR;
}
Esempio n. 3
0
Socket *tcpAccept(Socket *socket, IpAddr *clientIpAddr, uint16_t *clientPort)
{
   error_t error;
   TcpSynQueueItem *queueItem;
   Socket *newSocket;

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

   //Enter critical section
   osMutexAcquire(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
         osEventReset(socket->event);
         //Leave critical section
         osMutexRelease(socketMutex);
         //Wait until a SYN message is received from a client
         osEventWait(socket->event, socket->timeout);
         //Enter critical section
         osMutexAcquire(socketMutex);
      }

      //Check whether the queue is still empty
      if(!socket->synQueue)
      {
         //Leave critical section
         osMutexRelease(socketMutex);
         //Timeout error
         return NULL;
      }

      //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
      osMutexRelease(socketMutex);

      //Create a new socket to handle the incoming connection request
      newSocket = socketOpen(SOCKET_TYPE_STREAM, SOCKET_PROTOCOL_TCP);
      //Failed to open socket?
      if(!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
         continue;
      }

      //Enter critical section
      osMutexAcquire(socketMutex);

      //The user owns the socket
      newSocket->ownedFlag = TRUE;

      //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 = chunkedBufferSetLength((ChunkedBuffer *) &newSocket->txBuffer, newSocket->txBufferSize);
      //Allocate receive buffer
      if(!error)
         error = chunkedBufferSetLength((ChunkedBuffer *) &newSocket->rxBuffer, newSocket->rxBufferSize);

      //Failed to allocate memory?
      if(error)
      {
         //Debug message
         TRACE_WARNING("Cannot accept TCP connection!\r\n");

         //Properly close the socket
         tcpAbort(newSocket);
         //Remove the item from the SYN queue
         socket->synQueue = queueItem->next;
         //Deallocate memory buffer
         memPoolFree(queueItem);
         //Wait for the next connection attempt
         continue;
      }

      //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 = rand();
      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;
      //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;

      //Send a SYN ACK control segment
      error = tcpSendSegment(newSocket, TCP_FLAG_SYN | TCP_FLAG_ACK,
         newSocket->iss, newSocket->rcvNxt, 0, TRUE);
      //Failed to send TCP segment?
      if(error)
      {
         //Debug message
         TRACE_WARNING("Cannot accept TCP connection!\r\n");

         //Close previously created socket
         tcpAbort(newSocket);
         //Remove the item from the SYN queue
         socket->synQueue = queueItem->next;
         //Deallocate memory buffer
         memPoolFree(queueItem);
         //Wait for the next connection attempt
         continue;
      }

      //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);

      //Leave critical section
      osMutexRelease(socketMutex);
      //Return a handle to the newly created socket
      return newSocket;
   }
}