⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp.c

📁 ATmega103、ATmega128做的开发板web server源码
💻 C
📖 第 1 页 / 共 4 页
字号:
        {
          bufferptr = startBuffer;                        //Set the pointer to the start of the buffer
        }
        *bufferptr++ = (unsigned char)((*frameptr++)&0xff);
        if (bufferptr > bufferptr2)                       //If the bufferpointer has moved beyond the end
        {
          bufferptr = startBuffer;                        //Set the pointer to the start of the buffer
        }
      }
      if ( (tcbptr->segLEN-tcbptr->segHdrLEN) & 1 ) //If the data size was odd bytes, get the last byte
      {
        *bufferptr = (unsigned char)(((*frameptr)>>8)&0xff);
      }
      tcbptr->rcvNXT +=(tcbptr->segLEN-tcbptr->segHdrLEN);    //Update next expected SEQnr.
      tcbptr->writeIn += (tcbptr->segLEN-tcbptr->segHdrLEN);  //Update writeIn pointer
    }
  }
}



/*checkTCP runs everytime a timer interrupt occursp-> The function checks
  the retransmission queue to see if there are frames to be sent and
  checks the sockets to see if there are new frames to be sent.*/
void checkTCP ( void )
{
  SOCKET *socketptr;
  TCB *tcbptr;
  unsigned char socketNr;

  ticker++;               //Increase counter
  updateBuffer();         //Update retransmission buffer, segments with timeout is retransmitted.
  tcbptr = tcb;
  socketptr = sockets;  
  for (socketNr=0;socketNr<TCP_MAX_SOCKETS;socketNr++)   //For every transmission control block.
  {
//    tcbptr = &tcb[socketNr];
//    socketptr = &sockets[socketNr];
    tcbptr->segLEN = 20;        //Prepare a frame for sending.
    tcbptr->segHdrLEN = 20;
    tcbptr->CTL = 0;            //Clear flags. If flags is set, the segment is sent.
    tcbptr->readOut = ((tcbptr->readOut)%TCP_WIN_SIZE);   //Ensure the pointers are not outside the 
    tcbptr->writeOut = ((tcbptr->writeOut)%TCP_WIN_SIZE);
    tcbptr->readIn = ((tcbptr->readIn)%TCP_WIN_SIZE);
    tcbptr->writeIn = ((tcbptr->writeIn)%TCP_WIN_SIZE);
    if ( (tcbptr->state == TCP_STATE_TIME_WAIT) )        //If the state is TIME_WAIT
    {
      deleteSocket(socketNr);                            //Just delete the socket
    }
    else if ( ((tcbptr->state == TCP_STATE_ESTABLISHED) || (tcbptr->state == TCP_STATE_CLOSE_WAIT)) && freeRT() )
    {
      if ( (tcbptr->readOut != tcbptr->writeOut) ) //If there is data to be sent.
      {
        tcbptr->segLEN += putData(socketNr);       //Put data in segment
        if (tcbptr->segLEN > 20)
        {
          tcbptr->CTL |= TCP_ACK|TCP_PSH;             //Set ACK|PSH flags
        }
      }
      if ( (tcbptr->open == FALSE) && (tcbptr->state == TCP_STATE_ESTABLISHED) ) 
      {               //There is no data and connection should be closed.
        tcbptr->CTL |= TCP_FIN | TCP_ACK;   //Send FIN and enter FIN_WAIT1
        tcbptr->state = TCP_STATE_FIN_WAIT1;
        socketptr->state = HALF_CLOSED;
      }
    }
    if ( (tcbptr->state == TCP_STATE_CLOSE_WAIT) && (tcbptr->open == FALSE) && freeRT() ) 
    {       //If state is CLOSE_WAIT and connection should be closed
      tcbptr->CTL |= TCP_ACK | TCP_FIN;
      tcbptr->state = TCP_STATE_LAST_ACK;
      socketptr->state = HALF_CLOSED;
    }
    else if ( (((TCP_WIN_SIZE-tcbptr->sndWND)- writtenIn(socketNr)) > (TCP_WIN_SIZE/10)) )
    {  //If the window size has increased more than 1/10 of window size, send a notice to client
      tcbptr->CTL |= TCP_ACK;
    }
    if (tcbptr->CTL)     //If there is a flag that is set, the segment should be sent.
    {
      prepareFrame(socketNr);
      transmitIP(tcbptr->segLEN, socketptr->hisIP0, socketptr->hisIP1, 6);
      if (tcbptr->state == TCP_STATE_FIN_WAIT1)  //Update SEQnr.
      {
        tcbptr->sndNXT++;
      }
      tcbptr->sndNXT += (tcbptr->segLEN - tcbptr->segHdrLEN);
    }
    tcbptr++;
    socketptr++;
  }
}

/*putBuffer puts a segment in the retransmission buffer*/
unsigned char putBuffer(unsigned int *pointer, unsigned int length, unsigned char sNr)
{
  unsigned char bufferNr;
  unsigned int i, *bufferptr;
  RT *RTbufferptr = RTframes;
  SOCKET *socketptr = &sockets[sNr];
  TCB *tcbptr = &tcb[sNr];
    
  for (bufferNr=0;bufferNr<TCP_NUMBER_RT_BUF;bufferNr++)  //Find free buffer space
  {
//    RTbufferptr = &RTframes[bufferNr];
    if (RTbufferptr->socketNr == 0xff)
    {
      bufferptr = &RTbufferptr->buffer[0];
      if ( ((length+1)/2)< TCP_RT_BUFFER_SIZE)  //If there is room for the segment
      {
        RTbufferptr->nextTICK = ticker + TCP_TICKS_BEFORE_RT;  //Set timeout
        RTbufferptr->RTOs = 0;                                 //Reset number of retransmissions
        RTbufferptr->size = length;                            //Set length
        RTbufferptr->socketNr = sNr;                           //Set socketNr
        RTbufferptr->hisIP0 = socketptr->hisIP0;
        RTbufferptr->hisIP1 = socketptr->hisIP1;
        RTbufferptr->SEQ = tcbptr->sndNXT+(length-tcbptr->segHdrLEN);              //Set sequence number for the segment
        for (i=0;i<(length+1)/2;i++)                           //Copy the segment into the buffer
        {
          *bufferptr++ = *pointer++;
        }
        return (bufferNr);
      }
    }
    RTbufferptr++;
  }
  return 0xff;
}

/*deleteBuffer deletes all segments in retransmission buffer
  which belong to a deleted socket*/
void deleteBuffer(unsigned char sNr)
{
  unsigned char bufferNr;
  
  for (bufferNr=0;bufferNr<TCP_NUMBER_RT_BUF;bufferNr++)//For every segment in buffer
  {
    if (RTframes[bufferNr].socketNr == sNr)             //Is the socketNr correct
    {
      RTframes[bufferNr].socketNr = 0xff;               //Delete the segment
    }
  }
}

/* updateBuffer checks all segment in retransmission buffer
   for timeout. If a timeout has occured, the segment is retransmitted
   and number of retransmissions (RTOs) increased. If RTOs has exceeded
   TCP_MAX_RT (maximum number of retransmissions) the socket is deleted*/
void updateBuffer(void)
{
  unsigned char bufferNr;
  unsigned int i, *frameptr, *buffer;
  RT *RTbufferptr = RTframes;

  for (bufferNr=0;bufferNr<TCP_NUMBER_RT_BUF;bufferNr++)  //For every segment in buffer
  {
//    RTbufferptr = &RTframes[bufferNr];
    if ( (RTbufferptr->nextTICK == ticker) && (RTbufferptr->socketNr < 0xff) ) //If there is a segment and timeout
    {
      frameptr = &frame[TCP_SENDER_PORT];
      buffer = RTbufferptr->buffer;
      for (i=0;i<(RTbufferptr->size+1)/2;i++)       //Copy segment into frame and send it.
      {
        *frameptr++ = *buffer++;
      }
      transmitIP(RTbufferptr->size, RTbufferptr->hisIP0, RTbufferptr->hisIP1, 6);
      RTbufferptr->RTOs++;  
      if (RTbufferptr->RTOs >= TCP_MAX_RT)  //If number of retransmissions has exceeded TCP_MAX_RT
      {
        deleteSocket(RTbufferptr->socketNr);  //Delete the socket and segment
        RTbufferptr->socketNr=0xff;
      }
      else
      {
        RTbufferptr->nextTICK += TCP_TICKS_BEFORE_RT; //Set a new timeout for the segment.
      }
    }
     RTbufferptr++;
  }
}

/*updateRT is called when segments is ACKed. Deletes all ACKed segments.*/
void updateRT (unsigned char sNr)
{
  unsigned char bufferNr;
  unsigned int *frameptr, *buffer, i;
  RT *RTbufferptr = RTframes;
  
  for (bufferNr=0;bufferNr<TCP_NUMBER_RT_BUF;bufferNr++)  //For all segments in buffer
  {
//    RTbufferptr = &RTframes[bufferNr];
    if ( (RTbufferptr->socketNr == sNr) )                 //If segment belongs to this socket.
    {
      if ( (RTbufferptr->SEQ <= tcb[sNr].sndUNA) )        //If the segment is ACKed.
      {
        RTbufferptr->socketNr = 0xff;                     //Delete the socket
      }
      else
      {
        frameptr = &frame[TCP_SENDER_PORT];               //If the segment is not ACKed, retransmit it!
        buffer = RTbufferptr->buffer;
        for (i=0;i<(RTbufferptr->size+1)/2;i++)
        {
          *frameptr++ = *buffer++;
        }
        transmitIP(RTbufferptr->size, RTbufferptr->hisIP0, RTbufferptr->hisIP1, 6);
      }
    }
    RTbufferptr++;
  }
}

/*freeRT returns TRUE if there is room for another segment
  in retransmission buffer, else false*/
unsigned char freeRT ( void )
{
  unsigned char i;
  RT *RTbufferptr = RTframes;

  for (i=0;i<TCP_NUMBER_RT_BUF;i++)         //For every segment in buffer
  {
//    RTbufferptr = &RTframes[i];
    if ( (RTbufferptr->socketNr == 0xff) )  //Is this buffer space free?
    {
      return TRUE;
    }
  }
  i=0;
  return FALSE;
}

/*writtenOut returns the amount of bytes in outBuffer*/
unsigned int writtenOut(unsigned char socketNr)
{
  unsigned int readOut, writeOut;
  TCB *tcbptr = &tcb[socketNr];
    
  tcbptr->readOut = tcbptr->readOut%TCP_WIN_SIZE;
  readOut = tcbptr->readOut;
  tcbptr->writeOut = tcbptr->writeOut%TCP_WIN_SIZE;
  writeOut = tcbptr->writeOut;
  if ( readOut > writeOut)
  {
    return (TCP_WIN_SIZE - readOut + writeOut);
  }  
  else
  {  
    return (writeOut - readOut);
  }
}

  
/*putData puts data from outBuffer into the frame to be sent.
  The amount of data depends on how much is waiting, and
  how much it is allowed to send.*/
unsigned int putData(unsigned char socketNr)
{
  unsigned int unsent, i, send;
  unsigned int *frameptr;
  unsigned char *bufferptr, *startptr, *endptr;
  TCB *tcbptr = &tcb[socketNr];

  unsent = writtenOut(socketNr);   //Get amount of data in outBuffer
  if ( unsent )                    //If there was data
  {
    if ( (unsent < tcbptr->rcvWND) && (unsent < tcbptr->MSS) )
    {   //If data size is less than client's window and maximum segment size
      send = unsent;
    }
    else if ( (unsent > tcbptr->rcvWND) && (unsent < tcbptr->MSS) )
    {  //If data size is less than MSS, but greater than client's window.
      send = tcbptr->rcvWND;
    }
    else if ( (unsent < tcbptr->rcvWND) && (unsent > tcbptr->MSS) )
    { //If data size is less than receiver's windoe, but greater than MSS
      send = tcbptr->MSS;
    }
    else if ( (tcbptr->rcvWND < tcbptr->MSS) )
    {  //In case data size is greater than both MSS and client's window. Pick the smallest.
      send = tcbptr->rcvWND;
    }
    else
    {
      send = tcbptr->MSS;
    }
    frameptr = &frame[TCP_DATA];
    bufferptr = &tcbptr->outBuffer[tcbptr->readOut];
    startptr = tcbptr->outBuffer;
    endptr = &tcbptr->outBuffer[TCP_WIN_SIZE-1];
    for (i=0;i<send/2;i++)     //Copy data to frame.
    {
      *frameptr = ((*bufferptr++)<<8)&0xff00;
      if (bufferptr > endptr)  //If bufferptr exceeds buffer, start at beginning.
      {
        bufferptr = startptr;
      }
      *frameptr++ |= ((*bufferptr++)&0xff);
      if (bufferptr > endptr)  //If bufferptr exceeds buffer, start at beginning.
      {
        bufferptr = startptr;
      }
    }
    if (send & 1)             //Copy last byte if odd number of bytes.
    {
      *frameptr = ((*bufferptr)<<8)&0xff00;
    }
    tcbptr->readOut += send; //Update readOut pointer.
    return send;             //Return number of bytes copied.
  }
  return 0;
}

/*TCPfindSockets find the top of the linked list with sockets
  to the specified port and returns a pointer to it.*/
SOCKET *TCPfindSockets (unsigned int port)
{
  unsigned char i;
  SOCKET *socketptr = sockets;  
  
  for (i=0;i<TCP_MAX_SOCKETS;i++)  //For every socket.
  {
//    socketptr = &sockets[i];
    if (socketptr->myPort == port && (socketptr->previous == NULL) )  //Is this the correct port and the first element?
    {
      return socketptr;
    }
    socketptr++;
  }
  return NULL;
}

/*popen ~ Passive open. Create a TCB and put the connection in state LISTEN.*/
char TCPpopen (unsigned int port, unsigned long ip)
{
  unsigned char x;
  LISTEN *listenptr = listenList;
  
  for (x=0;x<TCP_MAX_CONNECTIONS;x++)
  {
   if ( (listenptr->portNr == port) && (listenptr->ip == ip) ) //Do we already listen to the port?
    {  
      return 0;
    }
    listenptr++;
  }
  listenptr = listenList;
  for (x=0;x<TCP_MAX_CONNECTIONS;x++)
  {
    if ( !listenptr->portNr )    //Find a free entry for this port.
    {
      listenptr->portNr = port;
      listenptr->ip = ip;
      return 1;      
    }
    listenptr++;
  }
  return 0;
}

/*TCPfindTCB finds a free transmission Control Block and
  returns the number of the block if it find one, else oxff.*/
unsigned char TCPfindTCB( void )
{
  unsigned char socketNr;
  SOCKET *socketptr = sockets;

  for (socketNr=0;socketNr<TCP_MAX_SOCKETS;socketNr++)
  {
//    socketptr = &sockets[socketNr];
    if ( (socketptr++->socketNr == 0xff) ) //Is this TCB free?
    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -