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

📄 tcp.c

📁 ATmega103、ATmega128做的开发板web server源码
💻 C
📖 第 1 页 / 共 4 页
字号:
    {
      if ( (tcbptr->sndUNA <= tcbptr->segACK) && (tcbptr->segACK <= tcbptr->sndNXT) )
      {
        if ( (tcbptr->segACK == tcbptr->sndNXT) ) //Is the ACK to our FIN?
        {
          tcbptr->state = TCP_STATE_FIN_WAIT2;
          socketptr->state = HALF_CLOSED;
        }
        tcbptr->sndUNA = tcbptr->segACK;
        updateRT(socketNr);      //Update retransmission buffer
        tcbptr->segLEN = 20;
        tcbptr->segHdrLEN = 20;
        tcbptr->CTL = TCP_ACK;
        if ( ((tcbptr->sndWL1 < tcbptr->segSEQ) ||
              ((tcbptr->sndWL1 == tcbptr->segSEQ) && (tcbptr->sndWL2 <= tcbptr->segACK))) ) 
        {
          tcbptr->rcvWND = tcbptr->segWND;
          tcbptr->sndWL1 = tcbptr->segSEQ;
          tcbptr->sndWL2 = tcbptr->segACK;
        }
        if (  (tcbptr->segHdrLEN < tcbptr->segLEN) && (tcbptr->state != TCP_STATE_FIN_WAIT2) ) 
        {
          prepareFrame( socketNr );
          transmitIP(tcbptr->segLEN, socketptr->hisIP0, socketptr->hisIP1, 6);
        }
      }
    }
  }
}

/*TCPfin_wait2 does almost the same as TCPestablished. This state
  is entered when our FIN to the client is ACKed. If the segment
  contains a FIN, ACK the FIN and go to TIME_WAIT. Extract data if any.`*/
void TCPfin_wait2 ( unsigned char socketNr )
{
  SOCKET *socketptr = &sockets[socketNr];
  TCB *tcbptr = &tcb[socketNr];

  if ( (acceptable(socketNr) == TRUE) ) //If segment is acceptable
  {
    if ( tcbptr->segHdrLEN < tcbptr->segLEN )//Any data?
    {
      extractData ( socketNr );
    }
    if ( (tcbptr->segCTL & (TCP_RST|TCP_SYN)) ) //Illegal flags?
    {
      deleteSocket(socketNr);
    }
    else if ( (tcbptr->segCTL & TCP_ACK) ) 
    {
      if ( (tcbptr->sndUNA <= tcbptr->segACK) && (tcbptr->segACK <= tcbptr->sndNXT) ) 
      {
        if ( ((tcbptr->sndWL1 < tcbptr->segSEQ) ||
              ((tcbptr->sndWL1 == tcbptr->segSEQ) && (tcbptr->sndWL2 <= tcbptr->segACK))) ) 
        {
          tcbptr->rcvWND = tcbptr->segWND; //Update window information
          tcbptr->sndWL1 = tcbptr->segSEQ;
          tcbptr->sndWL2 = tcbptr->segACK;
        }
        tcbptr->sndUNA = tcbptr->segACK;
        updateRT(socketNr);                //Update retransmission buffer
        if ( (tcbptr->segCTL & TCP_FIN) )  //Do the client want to close the connection?
        {
          tcbptr->state = TCP_STATE_TIME_WAIT; //Go to TIME_WAIT
          socketptr->state = CLOSED;
          tcbptr->rcvNXT++;
        }
        
        tcbptr->segLEN = 20;
        tcbptr->segHdrLEN = 20;
        tcbptr->CTL = TCP_ACK;
        prepareFrame(socketNr); 
        transmitIP(tcbptr->segLEN, socketptr->hisIP0, socketptr->hisIP1, 6);
      }
    }
  }
}

/*The client has closed his part of the connection and this server is
  not done sending data. Segments received here should only contain
  ACKs to our data.*/
void TCPclose_wait ( unsigned char socketNr)
{
  TCB *tcbptr = &tcb[socketNr];

  if ( (acceptable(socketNr) == TRUE) )
  {
    if ( (tcbptr->segCTL & (TCP_RST|TCP_SYN)) ) //Illegal flags?
    {
      deleteSocket(socketNr);
    }
    else if ( (tcbptr->segCTL & TCP_ACK) ) 
    {
      if ( (tcbptr->sndUNA <= tcbptr->segACK) && (tcbptr->segACK <= tcbptr->sndNXT) ) 
      {
        tcbptr->sndUNA = tcbptr->segACK;
        updateRT(socketNr);     //update retransmission buffer
        if ( ((tcbptr->sndWL1 < tcbptr->segSEQ) ||
              ((tcbptr->sndWL1 == tcbptr->segSEQ) && (tcbptr->sndWL2 <= tcbptr->segACK))) ) 
        {
          tcbptr->rcvWND = tcbptr->segWND;
          tcbptr->sndWL1 = tcbptr->segSEQ;
          tcbptr->sndWL2 = tcbptr->segACK;
        }
      }
    }
  }
}

/*After CLOSE_WAIT, we must wait for client to ACK our
  FIN. If the segment is acceptable, delete the socket*/
void TCPlast_ack ( unsigned char socketNr )
{
  TCB *tcbptr = &tcb[socketNr];

  if ( (acceptable(socketNr) == TRUE) )
  {
    if ( (tcbptr->segCTL & (TCP_RST|TCP_SYN|TCP_ACK)) ) 
    {
      deleteSocket(socketNr);                                // drop frame 
    }
  }
}


/*deleteSocket deletes the socket and make it ready
  for a new connection.*/
void deleteSocket( unsigned char socketNr )
{
  SOCKET *socketptr = &sockets[socketNr];
  TCB *tcbptr = &tcb[socketNr];

  if (socketptr->previous != NULL)   //If the linked list contain more sockets,
  {                                  //make sure the linking maintains.
    if (socketptr->next != NULL)
    {
      socketptr->previous->next = socketptr->next;
      socketptr->next->previous = socketptr->previous;
    }
    else
    {
      socketptr->previous->next = NULL;
    }
  }
  else if (socketptr->next != NULL)
  {
    socketptr->next->previous = NULL;
  }
  socketptr->next=NULL;
  socketptr->previous=NULL;
  socketptr->state = UNLOCKED;     //Delete socket information
  socketptr->socketNr = 0xff;
  socketptr->hisIP0 = 0;
  socketptr->hisIP1 = 0;
  socketptr->hisPort = 0;
  socketptr->myPort = 0;
  socketptr->hisIP0 = 0;            //Delete TCB information
  socketptr->hisIP1 = 0;
  socketptr->hisPort = 0;
  tcbptr->sndUNA = 0;
  tcbptr->sndWND = TCP_WIN_SIZE;
  tcbptr->sndWL1 = 0;
  tcbptr->sndWL2 = 0;
  tcbptr->rcvNXT = 0;
  tcbptr->rcvWND = 0;
  tcbptr->IRS = 0;
  tcbptr->segSEQ = 0;
  tcbptr->segACK = 0;
  tcbptr->segLEN = 0;
  tcbptr->segWND = 0;
  tcbptr->readIn = 0;
  tcbptr->writeIn = 0;
  tcbptr->readOut = 0;
  tcbptr->writeOut = 0;
  tcbptr->CTL = 0;
  tcbptr->state = TCP_STATE_CLOSED;
  tcbptr->open = FALSE;
  socketptr->myPort = 0;
  deleteBuffer(socketNr);
}

/*prepareFrame creates a new frame according to the information
  in TCB. Data must already be placed in frame.*/
void prepareFrame (unsigned char socketNr)
{
  unsigned int *frameptr = &frame[TCP_SENDER_PORT-6];
  SOCKET *socketptr = &sockets[socketNr];
  TCB *tcbptr = &tcb[socketNr];
  
  tcbptr->sndWND = (TCP_WIN_SIZE-2) - writtenIn(socketNr); //Update window size
  *frameptr++ = ID.IP0;            //Make pseudo header
  *frameptr++ = ID.IP1;
  *frameptr++ = socketptr->hisIP0;
  *frameptr++ = socketptr->hisIP1;
  *frameptr++ = 6;
  *frameptr++ = tcbptr->segLEN;
  *frameptr++ = socketptr->myPort;   //Make header
  *frameptr++ = socketptr->hisPort;
  *frameptr++ = (unsigned int)((tcbptr->sndNXT>>16)&0xffff);    //SEQ0
  *frameptr++ = (unsigned int)(tcbptr->sndNXT&0xffff);          //SEQ1
  *frameptr++ = (unsigned int)((tcbptr->rcvNXT>>16)&0xffff);    //ACK0
  *frameptr++ = (unsigned int)(tcbptr->rcvNXT&0xffff);          //ACK1
  *frameptr++ = ((tcbptr->segHdrLEN<<10)&0xf000) | tcbptr->CTL; //FLAGS
  *frameptr++ = tcbptr->sndWND;                                 //WINDOW
  *frameptr   = 0;                                              //CHECKSUM
  *(frameptr+1) = 0;                                            //URGENT
  *frameptr   = checksum(&frame[TCP_SENDER_PORT-6], ((tcbptr->segLEN+12)));  //New checksum
  if ( (tcbptr->CTL & (TCP_SYN|TCP_FIN|TCP_PSH|TCP_URG)) || (tcbptr->segHdrLEN < tcbptr->segLEN) )
  {//Put in retransmission buffer if anything other than an ACK
    putBuffer(&frame[TCP_SENDER_PORT], tcbptr->segLEN, socketNr);
  }
}


/*checkProtocol checks the frame and return the number of
  the socket. If there is an error in the frame 
  with this connection, then the number 0xff is returned.
  If there is no socket with this connection, the socket
  number of a free socket is returned.*/
unsigned char checkProtocol(unsigned int ip0, unsigned int ip1, unsigned int hisPort, unsigned int myPort)
{
  unsigned char i, j, socketNr;
  SOCKET *tmpSocketptr;
  SOCKET *socketptr = sockets;
  TCB *tcbptr = tcb;
  
//  socketptr = sockets; 
  for (i=0;i<TCP_MAX_SOCKETS;i++) //Find the correct socket
  {
//    socketptr = &sockets[i];
    if ( (socketptr->hisIP0 == ip0) && (socketptr->hisIP1 == ip1) && (socketptr->hisPort == hisPort) )
    {
      return (socketptr->socketNr); //return socketNr
    }
    socketptr++;
  }
  for (i=0;i<TCP_MAX_CONNECTIONS;i++)  // There were no such socket. 
  {
    if ( (listenList[i].portNr == myPort) && //Do we listen to this port?
         ((listenList[i].ip == (((((unsigned long)ip1)<<16)) | ip0)) || listenList[i].ip==0) ) 
    {
      socketptr = sockets;  
      for (socketNr=0;socketNr<TCP_MAX_SOCKETS;socketNr++) //Find free socket
      {
//        socketptr = &sockets[socketNr];
        if (socketptr->socketNr == 0xff)                   //Found one!
        {
//          tcbptr = &tcb[socketNr];
          tcbptr->open = TRUE;
          tcbptr->state = TCP_STATE_LISTEN;   //Fill in information
          socketptr->socketNr = socketNr;
          socketptr->hisIP0 = ip0;
          socketptr->hisIP1 = ip1;
          socketptr->hisPort = hisPort;
          socketptr->myPort = myPort;
          socketptr->state = HALF_OPEN;
          socketptr->next = NULL;
    /*	  if (socketNr > 0)
          {
            temp = socketNr;
          }
    */     
          tmpSocketptr = sockets;
          for (j=0;j<TCP_MAX_SOCKETS;j++)   //Link the socket together with the rest of the sockets on this port.
          {
    //	    tmpSocketptr = &sockets[j];
            if ( (tmpSocketptr->myPort == myPort) && (tmpSocketptr->next == NULL) && (socketptr != tmpSocketptr) ) 
            {
              tmpSocketptr->next = socketptr;
              socketptr->previous = tmpSocketptr;
              return (socketptr->socketNr);
            }
            tmpSocketptr++;;
          }
          socketptr->previous = NULL;
          return (socketptr->socketNr);  //Return new socketNr.
        }
        socketptr++;
        tcbptr++; 
      }
    }
  }
  return (0xff); // The segment was not accepted. 
}




/*Function acceptable is called to check if the frame follow the
  spesifications. return TRUE if frame is OK, else send response and
  return FALSE*/
unsigned char acceptable(unsigned char socketNr)
{
  SOCKET *socketptr = &sockets[socketNr];
  TCB *tcbptr = &tcb[socketNr];

  if ( (tcbptr->segSEQ == tcbptr->rcvNXT) ) //Is the SEQnr what we expect?
  {
    if ( (((tcbptr->segLEN-tcbptr->segHdrLEN) == 0) && (tcbptr->sndWND == 0)) )  //If the window size is 0, the data length must be 0.
    {  
      return TRUE;
    }
    else if ( (((tcbptr->segLEN-tcbptr->segHdrLEN) == 0) && (tcbptr->sndWND > 0)) &&   //If the window size > 0, and SEQ is within the window.
              (tcbptr->rcvNXT <= tcbptr->segSEQ) && (tcbptr->segSEQ < (tcbptr->rcvNXT+tcbptr->sndWND)) )
    {
      return TRUE;
    }
    else if ( ((tcbptr->rcvNXT <= (tcbptr->segSEQ+(tcbptr->segLEN-tcbptr->segHdrLEN))) && //All data in the segment is within the window.
               ((tcbptr->segSEQ+(tcbptr->segLEN-tcbptr->segHdrLEN)) <= (tcbptr->rcvNXT+tcbptr->sndWND))) )
    {  
      return TRUE;
    }
  }
  tcbptr->segLEN = 20;  //Else send an ACK not including information about this segment
  tcbptr->segHdrLEN = 20;
  tcbptr->CTL = TCP_ACK;
  prepareFrame(socketNr);
  transmitIP(tcbptr->segLEN, socketptr->hisIP0, socketptr->hisIP1, 6);
  return FALSE;
}


/*writtenIn returns the amount of data written into the
  inBuffer*/
unsigned int writtenIn(unsigned char socketNr)
{
  TCB *tcbptr = &tcb[socketNr];

  tcbptr->readIn = tcbptr->readIn%TCP_WIN_SIZE;  //Make sure offsets are within buffer
  tcbptr->writeIn = tcbptr->writeIn%TCP_WIN_SIZE;
  
  if (tcbptr->writeIn < tcbptr->readIn)          //Calculate amount of data and return
  {
    return (TCP_WIN_SIZE - (tcbptr->readIn-tcbptr->writeIn));
  }
  else
  {
    return (tcbptr->writeIn - tcbptr->readIn);
  }
}



/* extractData extracts data from the frame and is called
   when the TCP state is ESTABLISHED, FIN_WAIT1 and FIN_WAIT2.

   If the frame is "out-of-order" the data is extracted and information
   about the data is written to segmentList. extractData can only handle
   one "out-of-order"-frame at one time.*/
void extractData ( unsigned char socketNr )
{
  unsigned int unwritten, i;
  unsigned char *bufferptr, *bufferptr2, *startBuffer;
  unsigned int *frameptr=&frame[TCP_DATA];
  TCB *tcbptr = &tcb[socketNr];

  unwritten = TCP_WIN_SIZE - writtenIn(socketNr);
  if (unwritten > (tcbptr->segLEN-tcbptr->segHdrLEN) ) //extract data only if the data amount is less than buffer size
  {
    if (tcbptr->rcvNXT == tcbptr->segSEQ)
    {
      unwritten = (tcbptr->segLEN - tcbptr->segHdrLEN)/2;  //Find number of bytes data in segment
      bufferptr = &tcbptr->inBuffer[tcbptr->writeIn];      //Make a pointer to the end of buffer
      bufferptr2 = &tcbptr->inBuffer[TCP_WIN_SIZE-1];      //Make a pointer to start of buffer
      startBuffer = &tcbptr->inBuffer[0];
      for (i=0;i<unwritten;i++)
      {
        *bufferptr++ = (unsigned char)(((*frameptr)>>8)&0xff); 
        if (bufferptr > bufferptr2)                       //If the bufferpointer has moved beyond the end

⌨️ 快捷键说明

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