OpenCores
URL https://opencores.org/ocsvn/plasma/plasma/trunk

Subversion Repositories plasma

[/] [plasma/] [trunk/] [kernel/] [tcpip.c] - Diff between revs 418 and 419

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 418 Rev 419
/*--------------------------------------------------------------------
/*--------------------------------------------------------------------
 * TITLE: Plasma TCP/IP Protocol Stack
 * TITLE: Plasma TCP/IP Protocol Stack
 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
 * DATE CREATED: 4/22/06
 * DATE CREATED: 4/22/06
 * FILENAME: tcpip.c
 * FILENAME: tcpip.c
 * PROJECT: Plasma CPU core
 * PROJECT: Plasma CPU core
 * COPYRIGHT: Software placed into the public domain by the author.
 * COPYRIGHT: Software placed into the public domain by the author.
 *    Software 'as is' without warranty.  Author liable for nothing.
 *    Software 'as is' without warranty.  Author liable for nothing.
 * DESCRIPTION:
 * DESCRIPTION:
 *    Plasma TCP/IP Protocol Stack
 *    Plasma TCP/IP Protocol Stack
 *
 *
 *    Possible call stack when receiving a packet:
 *    Possible call stack when receiving a packet:
 *       IPMainThread()
 *       IPMainThread()
 *          IPProcessEthernetPacket()
 *          IPProcessEthernetPacket()
 *             IPProcessTCPPacket()
 *             IPProcessTCPPacket()
 *                TCPSendPacket()
 *                TCPSendPacket()
 *                   IPSendPacket()
 *                   IPSendPacket()
 *                      IPChecksum()
 *                      IPChecksum()
 *                      IPSendFrame()
 *                      IPSendFrame()
 *                         FrameInsert()
 *                         FrameInsert()
 *--------------------------------------------------------------------*/
 *--------------------------------------------------------------------*/
#include "rtos.h"
#include "rtos.h"
#define INSIDE_TCPIP
#define INSIDE_TCPIP
#include "tcpip.h"
#include "tcpip.h"
 
 
//ETHER FIELD                 OFFSET   LENGTH   VALUE
//ETHER FIELD                 OFFSET   LENGTH   VALUE
#define ETHERNET_DEST         0        //6
#define ETHERNET_DEST         0        //6
#define ETHERNET_SOURCE       6        //6
#define ETHERNET_SOURCE       6        //6
#define ETHERNET_FRAME_TYPE   12       //2      IP=0x0800; ARP=0x0806
#define ETHERNET_FRAME_TYPE   12       //2      IP=0x0800; ARP=0x0806
 
 
//ARP   FIELD                 OFFSET   LENGTH   VALUE
//ARP   FIELD                 OFFSET   LENGTH   VALUE
#define ARP_HARD_TYPE         14       //2      0x0001
#define ARP_HARD_TYPE         14       //2      0x0001
#define ARP_PROT_TYPE         16       //2      0x0800
#define ARP_PROT_TYPE         16       //2      0x0800
#define ARP_HARD_SIZE         18       //1      0x06
#define ARP_HARD_SIZE         18       //1      0x06
#define ARP_PROT_SIZE         19       //1      0x04
#define ARP_PROT_SIZE         19       //1      0x04
#define ARP_OP                20       //2      ARP=1;ARPreply=2
#define ARP_OP                20       //2      ARP=1;ARPreply=2
#define ARP_ETHERNET_SENDER   22       //6
#define ARP_ETHERNET_SENDER   22       //6
#define ARP_IP_SENDER         28       //4
#define ARP_IP_SENDER         28       //4
#define ARP_ETHERNET_TARGET   32       //6
#define ARP_ETHERNET_TARGET   32       //6
#define ARP_IP_TARGET         38       //4
#define ARP_IP_TARGET         38       //4
#define ARP_PAD               42       //18     0
#define ARP_PAD               42       //18     0
 
 
//IP    FIELD                 OFFSET   LENGTH   VALUE
//IP    FIELD                 OFFSET   LENGTH   VALUE
#define IP_VERSION_LENGTH     14       //1      0x45
#define IP_VERSION_LENGTH     14       //1      0x45
#define IP_TYPE_OF_SERVICE    15       //1      0x00
#define IP_TYPE_OF_SERVICE    15       //1      0x00
#define IP_LENGTH             16       //2
#define IP_LENGTH             16       //2
#define IP_ID16               18       //2
#define IP_ID16               18       //2
#define IP_FRAG_OFFSET        20       //2
#define IP_FRAG_OFFSET        20       //2
#define IP_TIME_TO_LIVE       22       //1      0x80
#define IP_TIME_TO_LIVE       22       //1      0x80
#define IP_PROTOCOL           23       //1      TCP=0x06;PING=0x01;UDP=0x11
#define IP_PROTOCOL           23       //1      TCP=0x06;PING=0x01;UDP=0x11
#define IP_CHECKSUM           24       //2
#define IP_CHECKSUM           24       //2
#define IP_SOURCE             26       //4
#define IP_SOURCE             26       //4
#define IP_DEST               30       //4
#define IP_DEST               30       //4
 
 
//PSEUDO FIELD                OFFSET   LENGTH   VALUE
//PSEUDO FIELD                OFFSET   LENGTH   VALUE
#define PSEUDO_IP_SOURCE      0        //4
#define PSEUDO_IP_SOURCE      0        //4
#define PSEUDO_IP_DEST        4        //4
#define PSEUDO_IP_DEST        4        //4
#define PSEUDO_ZERO           8        //1      0
#define PSEUDO_ZERO           8        //1      0
#define PSEUDO_IP_PROTOCOL    9        //1
#define PSEUDO_IP_PROTOCOL    9        //1
#define PSEUDO_LENGTH         10       //2
#define PSEUDO_LENGTH         10       //2
 
 
//UDP   FIELD                 OFFSET   LENGTH   VALUE
//UDP   FIELD                 OFFSET   LENGTH   VALUE
#define UDP_SOURCE_PORT       34       //2
#define UDP_SOURCE_PORT       34       //2
#define UDP_DEST_PORT         36       //2
#define UDP_DEST_PORT         36       //2
#define UDP_LENGTH            38       //2
#define UDP_LENGTH            38       //2
#define UDP_CHECKSUM          40       //2
#define UDP_CHECKSUM          40       //2
#define UDP_DATA              42
#define UDP_DATA              42
 
 
//DHCP  FIELD                 OFFSET   LENGTH   VALUE
//DHCP  FIELD                 OFFSET   LENGTH   VALUE
#define DHCP_OPCODE           42       //1      REQUEST=1;REPLY=2
#define DHCP_OPCODE           42       //1      REQUEST=1;REPLY=2
#define DHCP_HW_TYPE          43       //1      1
#define DHCP_HW_TYPE          43       //1      1
#define DHCP_HW_LEN           44       //1      6
#define DHCP_HW_LEN           44       //1      6
#define DHCP_HOP_COUNT        45       //1      0
#define DHCP_HOP_COUNT        45       //1      0
#define DHCP_TRANS_ID         46       //4
#define DHCP_TRANS_ID         46       //4
#define DHCP_NUM_SEC          50       //2      0
#define DHCP_NUM_SEC          50       //2      0
#define DHCP_UNUSED           52       //2
#define DHCP_UNUSED           52       //2
#define DHCP_CLIENT_IP        54       //4
#define DHCP_CLIENT_IP        54       //4
#define DHCP_YOUR_IP          58       //4
#define DHCP_YOUR_IP          58       //4
#define DHCP_SERVER_IP        62       //4
#define DHCP_SERVER_IP        62       //4
#define DHCP_GATEWAY_IP       66       //4
#define DHCP_GATEWAY_IP       66       //4
#define DHCP_CLIENT_ETHERNET  70       //16
#define DHCP_CLIENT_ETHERNET  70       //16
#define DHCP_SERVER_NAME      86       //64
#define DHCP_SERVER_NAME      86       //64
#define DHCP_BOOT_FILENAME    150      //128
#define DHCP_BOOT_FILENAME    150      //128
#define DHCP_MAGIC_COOKIE     278      //4      0x63825363
#define DHCP_MAGIC_COOKIE     278      //4      0x63825363
#define DHCP_OPTIONS          282      //N
#define DHCP_OPTIONS          282      //N
 
 
#define DHCP_MESSAGE_TYPE     53       //1 type
#define DHCP_MESSAGE_TYPE     53       //1 type
#define DHCP_DISCOVER         1
#define DHCP_DISCOVER         1
#define DHCP_OFFER            2
#define DHCP_OFFER            2
#define DHCP_REQUEST          3
#define DHCP_REQUEST          3
#define DHCP_ACK              5
#define DHCP_ACK              5
#define DHCP_REQUEST_IP       50       //4 ip
#define DHCP_REQUEST_IP       50       //4 ip
#define DHCP_REQUEST_SERV_IP  54       //4 ip
#define DHCP_REQUEST_SERV_IP  54       //4 ip
#define DHCP_CLIENT_ID        61       //7 1 ethernet
#define DHCP_CLIENT_ID        61       //7 1 ethernet
#define DHCP_HOST_NAME        12       //6 plasma
#define DHCP_HOST_NAME        12       //6 plasma
#define DHCP_PARAMS           55       //4 1=subnet; 15=domain_name; 3=router; 6=dns
#define DHCP_PARAMS           55       //4 1=subnet; 15=domain_name; 3=router; 6=dns
#define DHCP_PARAM_SUBNET     1
#define DHCP_PARAM_SUBNET     1
#define DHCP_PARAM_ROUTER     3
#define DHCP_PARAM_ROUTER     3
#define DHCP_PARAM_DNS        6
#define DHCP_PARAM_DNS        6
#define DHCP_END_OPTION       0xff
#define DHCP_END_OPTION       0xff
 
 
//DHCP  FIELD                 OFFSET   LENGTH   VALUE
//DHCP  FIELD                 OFFSET   LENGTH   VALUE
#define DNS_ID                0        //2    
#define DNS_ID                0        //2    
#define DNS_FLAGS             2        //2      
#define DNS_FLAGS             2        //2      
#define DNS_NUM_QUESTIONS     4        //2      1 
#define DNS_NUM_QUESTIONS     4        //2      1 
#define DNS_NUM_ANSWERS_RR    6        //2      0/1
#define DNS_NUM_ANSWERS_RR    6        //2      0/1
#define DNS_NUM_AUTHORITY_RR  8        //2      0 
#define DNS_NUM_AUTHORITY_RR  8        //2      0 
#define DNS_NUM_ADDITIONAL_RR 10       //2      0
#define DNS_NUM_ADDITIONAL_RR 10       //2      0
#define DNS_QUESTIONS         12       //2   
#define DNS_QUESTIONS         12       //2   
 
 
#define DNS_FLAGS_RESPONSE    0x8000
#define DNS_FLAGS_RESPONSE    0x8000
#define DNS_FLAGS_RECURSIVE   0x0100
#define DNS_FLAGS_RECURSIVE   0x0100
#define DNS_FLAGS_ERROR       0x0003
#define DNS_FLAGS_ERROR       0x0003
#define DNS_FLAGS_OK          0x0000
#define DNS_FLAGS_OK          0x0000
#define DNS_QUERY_TYPE_IP     1
#define DNS_QUERY_TYPE_IP     1
#define DNS_QUERY_CLASS       1
#define DNS_QUERY_CLASS       1
#define DNS_PORT              53
#define DNS_PORT              53
 
 
//TCP   FIELD                 OFFSET   LENGTH   VALUE
//TCP   FIELD                 OFFSET   LENGTH   VALUE
#define TCP_SOURCE_PORT       34       //2
#define TCP_SOURCE_PORT       34       //2
#define TCP_DEST_PORT         36       //2
#define TCP_DEST_PORT         36       //2
#define TCP_SEQ               38       //4
#define TCP_SEQ               38       //4
#define TCP_ACK               42       //4
#define TCP_ACK               42       //4
#define TCP_HEADER_LENGTH     46       //1      0x50
#define TCP_HEADER_LENGTH     46       //1      0x50
#define TCP_FLAGS             47       //1      SYNC=0x2;ACK=0x10;FIN=0x1
#define TCP_FLAGS             47       //1      SYNC=0x2;ACK=0x10;FIN=0x1
#define TCP_WINDOW_SIZE       48       //2
#define TCP_WINDOW_SIZE       48       //2
#define TCP_CHECKSUM          50       //2
#define TCP_CHECKSUM          50       //2
#define TCP_URGENT_POINTER    52       //2
#define TCP_URGENT_POINTER    52       //2
#define TCP_DATA              54       //length-N
#define TCP_DATA              54       //length-N
 
 
#define TCP_FLAGS_FIN         1
#define TCP_FLAGS_FIN         1
#define TCP_FLAGS_SYN         2
#define TCP_FLAGS_SYN         2
#define TCP_FLAGS_RST         4
#define TCP_FLAGS_RST         4
#define TCP_FLAGS_PSH         8
#define TCP_FLAGS_PSH         8
#define TCP_FLAGS_ACK         16
#define TCP_FLAGS_ACK         16
 
 
//PING  FIELD                 OFFSET   LENGTH   VALUE
//PING  FIELD                 OFFSET   LENGTH   VALUE
#define PING_TYPE             34       //1      SEND=8;REPLY=0
#define PING_TYPE             34       //1      SEND=8;REPLY=0
#define PING_CODE             35       //1      0
#define PING_CODE             35       //1      0
#define PING_CHECKSUM         36       //2
#define PING_CHECKSUM         36       //2
#define PING_ID               38       //2
#define PING_ID               38       //2
#define PING_SEQUENCE         40       //2
#define PING_SEQUENCE         40       //2
#define PING_DATA             44
#define PING_DATA             44
 
 
static void IPClose2(IPSocket *Socket);
static void IPClose2(IPSocket *Socket);
static void IPArp(unsigned char ipAddress[4]);
static void IPArp(unsigned char ipAddress[4]);
 
 
typedef struct ArpCache_s {
typedef struct ArpCache_s {
   unsigned char ip[4];
   unsigned char ip[4];
   unsigned char mac[6];
   unsigned char mac[6];
} ArpCache_t;
} ArpCache_t;
static ArpCache_t ArpCache[10];
static ArpCache_t ArpCache[10];
static int ArpCacheIndex;
static int ArpCacheIndex;
 
 
static uint8 ethernetAddressGateway[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static uint8 ethernetAddressGateway[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
#ifndef WIN32
#ifndef WIN32
static uint8 ethernetAddressPlasma[] =  {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4};
static uint8 ethernetAddressPlasma[] =  {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4};
#else
#else
static uint8 ethernetAddressPlasma[] =  {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd5};
static uint8 ethernetAddressPlasma[] =  {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd5};
#endif
#endif
 
 
static uint8 ipAddressPlasma[] =  {192, 168, 100, 10};      //changed by DHCP
static uint8 ipAddressPlasma[] =  {192, 168, 100, 10};      //changed by DHCP
static uint8 ipAddressGateway[] = {0x00, 0x00, 0x00, 0x00}; //changed by DHCP
static uint8 ipAddressGateway[] = {0x00, 0x00, 0x00, 0x00}; //changed by DHCP
static uint32 ipAddressDns;                                 //changed by DHCP
static uint32 ipAddressDns;                                 //changed by DHCP
 
 
static OS_Mutex_t *IPMutex;
static OS_Mutex_t *IPMutex;
static int FrameFreeCount;
static int FrameFreeCount;
static IPFrame *FrameFreeHead;
static IPFrame *FrameFreeHead;
static IPFrame *FrameSendHead;
static IPFrame *FrameSendHead;
static IPFrame *FrameSendTail;
static IPFrame *FrameSendTail;
static IPFrame *FrameResendHead;
static IPFrame *FrameResendHead;
static IPFrame *FrameResendTail;
static IPFrame *FrameResendTail;
static IPSocket *SocketHead;
static IPSocket *SocketHead;
static uint32 Seconds;
static uint32 Seconds;
static int DhcpRetrySeconds;
static int DhcpRetrySeconds;
static IPSendFuncPtr FrameSendFunc;
static IPSendFuncPtr FrameSendFunc;
static OS_MQueue_t *IPMQueue;
static OS_MQueue_t *IPMQueue;
static OS_Thread_t *IPThread;
static OS_Thread_t *IPThread;
int IPVerbose=1;
int IPVerbose=1;
 
 
static const unsigned char dhcpDiscover[] = {
static const unsigned char dhcpDiscover[] = {
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,             //dest
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,             //dest
   0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4,             //src
   0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4,             //src
   0x08, 0x00,
   0x08, 0x00,
   0x45, 0x00, 0x01, 0x48, 0x2e, 0xf5, 0x00, 0x00, //ip
   0x45, 0x00, 0x01, 0x48, 0x2e, 0xf5, 0x00, 0x00, //ip
   0x80, 0x11, 0x0a, 0xb1, 0x00, 0x00, 0x00, 0x00,
   0x80, 0x11, 0x0a, 0xb1, 0x00, 0x00, 0x00, 0x00,
   0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff,
   0x00, 0x44, 0x00, 0x43, 0x01, 0x34, 0x45, 0x66, //udp
   0x00, 0x44, 0x00, 0x43, 0x01, 0x34, 0x45, 0x66, //udp
   0x01, 0x01, 0x06, 0x00, 0x69, 0x26, 0xb5, 0x52  //dhcp
   0x01, 0x01, 0x06, 0x00, 0x69, 0x26, 0xb5, 0x52  //dhcp
};
};
 
 
static unsigned char dhcpOptions[] = {
static unsigned char dhcpOptions[] = {
   0x63, 0x82, 0x53, 0x63,      //cookie
   0x63, 0x82, 0x53, 0x63,      //cookie
   0x35, 0x01, 0x01,            //DHCP Discover
   0x35, 0x01, 0x01,            //DHCP Discover
   0x3d, 0x07, 0x01, 0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4, //Client identifier
   0x3d, 0x07, 0x01, 0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4, //Client identifier
#ifndef WIN32
#ifndef WIN32
   0x0c, 0x06, 'p', 'l', 'a', 's', 'm', 'a',             //Host name
   0x0c, 0x06, 'p', 'l', 'a', 's', 'm', 'a',             //Host name
#else
#else
   0x0c, 0x06, 'p', 'l', 'a', 's', 'm', 'b',             //Host name
   0x0c, 0x06, 'p', 'l', 'a', 's', 'm', 'b',             //Host name
#endif
#endif
   0x37, 0x03, DHCP_PARAM_SUBNET, DHCP_PARAM_ROUTER, DHCP_PARAM_DNS, //Parameters
   0x37, 0x03, DHCP_PARAM_SUBNET, DHCP_PARAM_ROUTER, DHCP_PARAM_DNS, //Parameters
   DHCP_END_OPTION
   DHCP_END_OPTION
};
};
 
 
 
 
//Get a free frame; can be called from an ISR
//Get a free frame; can be called from an ISR
IPFrame *IPFrameGet(int freeCount)
IPFrame *IPFrameGet(int freeCount)
{
{
   IPFrame *frame=NULL;
   IPFrame *frame=NULL;
   uint32 state;
   uint32 state;
 
 
   state = OS_CriticalBegin();
   state = OS_CriticalBegin();
   if(FrameFreeCount > freeCount)
   if(FrameFreeCount >= freeCount)
   {
   {
      frame = FrameFreeHead;
      frame = FrameFreeHead;
      if(FrameFreeHead)
      if(FrameFreeHead)
      {
      {
         FrameFreeHead = FrameFreeHead->next;
         FrameFreeHead = FrameFreeHead->next;
         --FrameFreeCount;
         --FrameFreeCount;
      }
      }
   }
   }
   OS_CriticalEnd(state);
   OS_CriticalEnd(state);
   if(frame)
   if(frame)
   {
   {
      assert(frame->state == 0);
      assert(frame->state == 0);
      frame->state = 1;
      frame->state = 1;
   }
   }
   return frame;
   return frame;
}
}
 
 
 
 
static void FrameFree(IPFrame *frame)
static void FrameFree(IPFrame *frame)
{
{
   uint32 state;
   uint32 state;
 
 
   assert(frame->state == 1);
   assert(frame->state == 1);
   frame->state = 0;
   frame->state = 0;
   state = OS_CriticalBegin();
   state = OS_CriticalBegin();
   frame->next = FrameFreeHead;
   frame->next = FrameFreeHead;
   FrameFreeHead = frame;
   FrameFreeHead = frame;
   ++FrameFreeCount;
   ++FrameFreeCount;
   OS_CriticalEnd(state);
   OS_CriticalEnd(state);
}
}
 
 
 
 
static void FrameInsert(IPFrame **head, IPFrame **tail, IPFrame *frame)
static void FrameInsert(IPFrame **head, IPFrame **tail, IPFrame *frame)
{
{
   assert(frame->state == 1);
   assert(frame->state == 1);
   frame->state = 2;
   frame->state = 2;
   OS_MutexPend(IPMutex);
   OS_MutexPend(IPMutex);
   frame->prev = NULL;
   frame->prev = NULL;
   frame->next = *head;
   frame->next = *head;
   if(*head)
   if(*head)
      (*head)->prev = frame;
      (*head)->prev = frame;
   *head = frame;
   *head = frame;
   if(*tail == NULL)
   if(*tail == NULL)
      *tail = frame;
      *tail = frame;
   OS_MutexPost(IPMutex);
   OS_MutexPost(IPMutex);
}
}
 
 
 
 
static void FrameRemove(IPFrame **head, IPFrame **tail, IPFrame *frame)
static void FrameRemove(IPFrame **head, IPFrame **tail, IPFrame *frame)
{
{
   assert(frame->state == 2);
   assert(frame->state == 2);
   if(frame->state != 2)
   if(frame->state != 2)
   {
   {
      printf("frame->state=%d\n", frame->state);
      printf("frame->state=%d\n", frame->state);
      return;
      return;
   }
   }
   frame->state = 1;
   frame->state = 1;
   if(frame->prev)
   if(frame->prev)
      frame->prev->next = frame->next;
      frame->prev->next = frame->next;
   else
   else
      *head = frame->next;
      *head = frame->next;
   if(frame->next)
   if(frame->next)
      frame->next->prev = frame->prev;
      frame->next->prev = frame->prev;
   else
   else
      *tail = frame->prev;
      *tail = frame->prev;
   frame->prev = NULL;
   frame->prev = NULL;
   frame->next = NULL;
   frame->next = NULL;
}
}
 
 
 
 
static int IPChecksum(int checksum, const unsigned char *data, int length)
static int IPChecksum(int checksum, const unsigned char *data, int length)
{
{
   int i;
   int i;
   checksum = ~checksum & 0xffff;
   checksum = ~checksum & 0xffff;
   for(i = 0; i < length-1; i += 2)
   for(i = 0; i < length-1; i += 2)
   {
   {
      checksum += (data[i] << 8) | data[i+1];
      checksum += (data[i] << 8) | data[i+1];
   }
   }
   if(i < length)
   if(i < length)
      checksum += data[i] << 8;
      checksum += data[i] << 8;
   while(checksum >> 16)
   while(checksum >> 16)
      checksum = (checksum & 0xffff) + (checksum >> 16);
      checksum = (checksum & 0xffff) + (checksum >> 16);
   checksum = ~checksum & 0xffff;
   checksum = ~checksum & 0xffff;
   return checksum;
   return checksum;
}
}
 
 
 
 
static int EthernetVerifyChecksums(const unsigned char *packet, int length)
static int EthernetVerifyChecksums(const unsigned char *packet, int length)
{
{
   int checksum, length2;
   int checksum, length2;
   unsigned char pseudo[12];
   unsigned char pseudo[12];
 
 
   //Calculate checksums
   //Calculate checksums
   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00)  //IP
   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00)  //IP
   {
   {
      checksum = IPChecksum(0xffff, packet+IP_VERSION_LENGTH, 20);
      checksum = IPChecksum(0xffff, packet+IP_VERSION_LENGTH, 20);
      if(checksum)
      if(checksum)
         return -1;
         return -1;
      if(packet[IP_PROTOCOL] == 0x01)         //PING
      if(packet[IP_PROTOCOL] == 0x01)         //PING
      {
      {
         checksum = IPChecksum(0xffff, packet+PING_TYPE, length-PING_TYPE);
         checksum = IPChecksum(0xffff, packet+PING_TYPE, length-PING_TYPE);
      }
      }
      else if(packet[IP_PROTOCOL] == 0x11)    //UDP
      else if(packet[IP_PROTOCOL] == 0x11)    //UDP
      {
      {
         if(packet[UDP_CHECKSUM] == 0 && packet[UDP_CHECKSUM+1] == 0)
         if(packet[UDP_CHECKSUM] == 0 && packet[UDP_CHECKSUM+1] == 0)
            return 0;
            return 0;
         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
         pseudo[PSEUDO_ZERO] = 0;
         pseudo[PSEUDO_ZERO] = 0;
         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
         memcpy(pseudo+PSEUDO_LENGTH, packet+UDP_LENGTH, 2);
         memcpy(pseudo+PSEUDO_LENGTH, packet+UDP_LENGTH, 2);
         checksum = IPChecksum(0xffff, pseudo, 12);
         checksum = IPChecksum(0xffff, pseudo, 12);
         length2 = (packet[UDP_LENGTH] << 8) + packet[UDP_LENGTH+1];
         length2 = (packet[UDP_LENGTH] << 8) + packet[UDP_LENGTH+1];
         checksum = IPChecksum(checksum, packet+UDP_SOURCE_PORT, length2);
         checksum = IPChecksum(checksum, packet+UDP_SOURCE_PORT, length2);
      }
      }
      else if(packet[IP_PROTOCOL] == 0x06)    //TCP
      else if(packet[IP_PROTOCOL] == 0x06)    //TCP
      {
      {
         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
         pseudo[PSEUDO_ZERO] = 0;
         pseudo[PSEUDO_ZERO] = 0;
         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
         length = (packet[IP_LENGTH] << 8) + packet[IP_LENGTH+1];
         length = (packet[IP_LENGTH] << 8) + packet[IP_LENGTH+1];
         length2 = length - 20;
         length2 = length - 20;
         pseudo[PSEUDO_LENGTH] = (unsigned char)(length2 >> 8);
         pseudo[PSEUDO_LENGTH] = (unsigned char)(length2 >> 8);
         pseudo[PSEUDO_LENGTH+1] = (unsigned char)length2;
         pseudo[PSEUDO_LENGTH+1] = (unsigned char)length2;
         checksum = IPChecksum(0xffff, pseudo, 12);
         checksum = IPChecksum(0xffff, pseudo, 12);
         checksum = IPChecksum(checksum, packet+TCP_SOURCE_PORT, length2);
         checksum = IPChecksum(checksum, packet+TCP_SOURCE_PORT, length2);
      }
      }
      if(checksum)
      if(checksum)
         return -1;
         return -1;
   }
   }
   return 0;
   return 0;
}
}
 
 
 
 
static void IPFrameReschedule(IPFrame *frame)
static void IPFrameReschedule(IPFrame *frame)
{
{
   int length;
   int length;
   length = frame->length - TCP_DATA;
   length = frame->length - TCP_DATA;
   if(frame->packet[TCP_FLAGS] & (TCP_FLAGS_FIN | TCP_FLAGS_SYN))
   if(frame->packet[TCP_FLAGS] & (TCP_FLAGS_FIN | TCP_FLAGS_SYN))
      ++length;
      ++length;
   if(frame->socket == NULL || frame->socket->state == IP_UDP || length == 0 ||
   if(frame->socket == NULL || frame->socket->state == IP_UDP || length == 0 ||
      frame->socket->state == IP_PING || ++frame->retryCnt > 4)
      frame->socket->state == IP_PING || ++frame->retryCnt > 4)
   {
   {
      FrameFree(frame);     //can't be ACK'ed
      FrameFree(frame);     //can't be ACK'ed
   }
   }
#ifdef WIN32
#ifdef WIN32
   else if(FrameFreeCount < FRAME_COUNT_SYNC)
   else if(FrameFreeCount < FRAME_COUNT_SYNC)
   {
   {
      FrameFree(frame);     //can't be ACK'ed
      FrameFree(frame);     //can't be ACK'ed
   }
   }
#endif
#endif
   else
   else
   {
   {
      //Put on resend list until TCP ACK'ed
      //Put on resend list until TCP ACK'ed
      frame->timeout = (short)(RETRANSMIT_TIME * frame->retryCnt);
      frame->timeout = (short)(RETRANSMIT_TIME * frame->retryCnt);
      FrameInsert(&FrameResendHead, &FrameResendTail, frame);
      FrameInsert(&FrameResendHead, &FrameResendTail, frame);
   }
   }
}
}
 
 
 
 
static void IPSendFrame(IPFrame *frame)
static void IPSendFrame(IPFrame *frame)
{
{
   uint32 message[4];
   uint32 message[4];
   int i;
   int i;
   unsigned char *packet=frame->packet;
   unsigned char *packet=frame->packet;
 
 
   //Check if MAC address unknown
   //Check if MAC address unknown
   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00 && //IP
   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00 && //IP
      packet[ETHERNET_DEST] == 0xff && packet[IP_DEST] != 0xff)
      packet[ETHERNET_DEST] == 0xff && packet[IP_DEST] != 0xff)
   {
   {
      for(i = 0; i < sizeof(ArpCache) / sizeof(ArpCache_t); ++i)
      for(i = 0; i < sizeof(ArpCache) / sizeof(ArpCache_t); ++i)
      {
      {
         if(memcmp(packet+IP_DEST, ArpCache[i].ip, 4) == 0)
         if(memcmp(packet+IP_DEST, ArpCache[i].ip, 4) == 0)
         {
         {
            memcpy(packet+ETHERNET_DEST, ArpCache[i].mac, 6);
            memcpy(packet+ETHERNET_DEST, ArpCache[i].mac, 6);
            if(frame->socket)
            if(frame->socket)
               memcpy(frame->socket->headerSend+ETHERNET_DEST, ArpCache[i].mac, 6);
               memcpy(frame->socket->headerSend+ETHERNET_DEST, ArpCache[i].mac, 6);
            break;
            break;
         }
         }
      }
      }
      if(packet[ETHERNET_DEST] == 0xff)
      if(packet[ETHERNET_DEST] == 0xff)
         IPArp(packet+IP_DEST);
         IPArp(packet+IP_DEST);
   }
   }
 
 
   if(FrameSendFunc)
   if(FrameSendFunc)
   {
   {
      //Single threaded
      //Single threaded
      FrameSendFunc(frame->packet, frame->length);
      FrameSendFunc(frame->packet, frame->length);
      IPFrameReschedule(frame);
      IPFrameReschedule(frame);
   }
   }
   else
   else
   {
   {
      //Add Packet to send queue
      //Add Packet to send queue
      FrameInsert(&FrameSendHead, &FrameSendTail, frame);
      FrameInsert(&FrameSendHead, &FrameSendTail, frame);
 
 
      //Wakeup sender thread
      //Wakeup sender thread
      message[0] = 2;
      message[0] = 2;
      OS_MQueueSend(IPMQueue, message);
      OS_MQueueSend(IPMQueue, message);
   }
   }
}
}
 
 
 
 
static void IPSendPacket(IPSocket *socket, IPFrame *frame, int length)
static void IPSendPacket(IPSocket *socket, IPFrame *frame, int length)
{
{
   int checksum, length2=length;
   int checksum, length2=length;
   unsigned char pseudo[12], *packet=frame->packet;
   unsigned char pseudo[12], *packet=frame->packet;
 
 
   frame->length = (uint16)length;
   frame->length = (uint16)length;
 
 
   //Calculate checksums
   //Calculate checksums
   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00)  //IP
   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00)  //IP
   {
   {
      length2 = length - IP_VERSION_LENGTH;
      length2 = length - IP_VERSION_LENGTH;
      packet[IP_LENGTH] = (uint8)(length2 >> 8);
      packet[IP_LENGTH] = (uint8)(length2 >> 8);
      packet[IP_LENGTH+1] = (uint8)length2;
      packet[IP_LENGTH+1] = (uint8)length2;
      memset(packet+IP_CHECKSUM, 0, 2);
      memset(packet+IP_CHECKSUM, 0, 2);
      checksum = IPChecksum(0xffff, packet+IP_VERSION_LENGTH, 20);
      checksum = IPChecksum(0xffff, packet+IP_VERSION_LENGTH, 20);
      packet[IP_CHECKSUM] = (unsigned char)(checksum >> 8);
      packet[IP_CHECKSUM] = (unsigned char)(checksum >> 8);
      packet[IP_CHECKSUM+1] = (unsigned char)checksum;
      packet[IP_CHECKSUM+1] = (unsigned char)checksum;
      if(packet[IP_PROTOCOL] == 0x01)         //ICMP & PING
      if(packet[IP_PROTOCOL] == 0x01)         //ICMP & PING
      {
      {
         memset(packet+PING_CHECKSUM, 0, 2);
         memset(packet+PING_CHECKSUM, 0, 2);
         checksum = IPChecksum(0xffff, packet+PING_TYPE, length-PING_TYPE);
         checksum = IPChecksum(0xffff, packet+PING_TYPE, length-PING_TYPE);
         packet[PING_CHECKSUM] = (unsigned char)(checksum >> 8);
         packet[PING_CHECKSUM] = (unsigned char)(checksum >> 8);
         packet[PING_CHECKSUM+1] = (unsigned char)checksum;
         packet[PING_CHECKSUM+1] = (unsigned char)checksum;
      }
      }
      else if(packet[IP_PROTOCOL] == 0x11)    //UDP
      else if(packet[IP_PROTOCOL] == 0x11)    //UDP
      {
      {
         length2 = length - UDP_SOURCE_PORT;
         length2 = length - UDP_SOURCE_PORT;
         packet[UDP_LENGTH] = (uint8)(length2 >> 8);
         packet[UDP_LENGTH] = (uint8)(length2 >> 8);
         packet[UDP_LENGTH+1] = (uint8)length2;
         packet[UDP_LENGTH+1] = (uint8)length2;
         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
         pseudo[PSEUDO_ZERO] = 0;
         pseudo[PSEUDO_ZERO] = 0;
         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
         memcpy(pseudo+PSEUDO_LENGTH, packet+UDP_LENGTH, 2);
         memcpy(pseudo+PSEUDO_LENGTH, packet+UDP_LENGTH, 2);
         checksum = IPChecksum(0xffff, pseudo, 12);
         checksum = IPChecksum(0xffff, pseudo, 12);
         memset(packet+UDP_CHECKSUM, 0, 2);
         memset(packet+UDP_CHECKSUM, 0, 2);
         length2 = (packet[UDP_LENGTH] << 8) + packet[UDP_LENGTH+1];
         length2 = (packet[UDP_LENGTH] << 8) + packet[UDP_LENGTH+1];
         checksum = IPChecksum(checksum, packet+UDP_SOURCE_PORT, length2);
         checksum = IPChecksum(checksum, packet+UDP_SOURCE_PORT, length2);
         packet[UDP_CHECKSUM] = (unsigned char)(checksum >> 8);
         packet[UDP_CHECKSUM] = (unsigned char)(checksum >> 8);
         packet[UDP_CHECKSUM+1] = (unsigned char)checksum;
         packet[UDP_CHECKSUM+1] = (unsigned char)checksum;
      }
      }
      else if(packet[IP_PROTOCOL] == 0x06)    //TCP
      else if(packet[IP_PROTOCOL] == 0x06)    //TCP
      {
      {
         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
         pseudo[PSEUDO_ZERO] = 0;
         pseudo[PSEUDO_ZERO] = 0;
         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
         length2 = (packet[IP_LENGTH] << 8) + packet[IP_LENGTH+1];
         length2 = (packet[IP_LENGTH] << 8) + packet[IP_LENGTH+1];
         length2 = length2 - 20;
         length2 = length2 - 20;
         pseudo[PSEUDO_LENGTH] = (unsigned char)(length2 >> 8);
         pseudo[PSEUDO_LENGTH] = (unsigned char)(length2 >> 8);
         pseudo[PSEUDO_LENGTH+1] = (unsigned char)length2;
         pseudo[PSEUDO_LENGTH+1] = (unsigned char)length2;
         checksum = IPChecksum(0xffff, pseudo, 12);
         checksum = IPChecksum(0xffff, pseudo, 12);
         memset(packet+TCP_CHECKSUM, 0, 2);
         memset(packet+TCP_CHECKSUM, 0, 2);
         checksum = IPChecksum(checksum, packet+TCP_SOURCE_PORT, length2);
         checksum = IPChecksum(checksum, packet+TCP_SOURCE_PORT, length2);
         packet[TCP_CHECKSUM] = (unsigned char)(checksum >> 8);
         packet[TCP_CHECKSUM] = (unsigned char)(checksum >> 8);
         packet[TCP_CHECKSUM+1] = (unsigned char)checksum;
         packet[TCP_CHECKSUM+1] = (unsigned char)checksum;
      }
      }
   }
   }
 
 
   length2 = length - TCP_DATA;
   length2 = length - TCP_DATA;
   if(socket && (packet[TCP_FLAGS] & (TCP_FLAGS_FIN | TCP_FLAGS_SYN)))
   if(socket && (packet[TCP_FLAGS] & (TCP_FLAGS_FIN | TCP_FLAGS_SYN)))
      length2 = 1;
      length2 = 1;
   frame->socket = socket;
   frame->socket = socket;
   frame->timeout = 0;
   frame->timeout = 0;
   frame->retryCnt = 0;
   frame->retryCnt = 0;
   if(socket)
   if(socket)
      frame->seqEnd = socket->seq + length2;
      frame->seqEnd = socket->seq + length2;
   IPSendFrame(frame);
   IPSendFrame(frame);
}
}
 
 
 
 
static void TCPSendPacket(IPSocket *socket, IPFrame *frame, int length)
static void TCPSendPacket(IPSocket *socket, IPFrame *frame, int length)
{
{
   uint8 *packet = frame->packet;
   uint8 *packet = frame->packet;
   int flags, count;
   int flags, count;
 
 
   flags = packet[TCP_FLAGS];
   flags = packet[TCP_FLAGS];
   memcpy(packet, socket->headerSend, TCP_SEQ);
   memcpy(packet, socket->headerSend, TCP_SEQ);
   packet[TCP_FLAGS] = (uint8)flags;
   packet[TCP_FLAGS] = (uint8)flags;
   if(flags & TCP_FLAGS_SYN)
   if(flags & TCP_FLAGS_SYN)
      packet[TCP_HEADER_LENGTH] = 0x60;  //set maximum segment size
      packet[TCP_HEADER_LENGTH] = 0x60;  //set maximum segment size
   else
   else
      packet[TCP_HEADER_LENGTH] = 0x50;
      packet[TCP_HEADER_LENGTH] = 0x50;
   packet[TCP_SEQ]   = (uint8)(socket->seq >> 24);
   packet[TCP_SEQ]   = (uint8)(socket->seq >> 24);
   packet[TCP_SEQ+1] = (uint8)(socket->seq >> 16);
   packet[TCP_SEQ+1] = (uint8)(socket->seq >> 16);
   packet[TCP_SEQ+2] = (uint8)(socket->seq >> 8);
   packet[TCP_SEQ+2] = (uint8)(socket->seq >> 8);
   packet[TCP_SEQ+3] = (uint8)socket->seq;
   packet[TCP_SEQ+3] = (uint8)socket->seq;
   packet[TCP_ACK]   = (uint8)(socket->ack >> 24);
   packet[TCP_ACK]   = (uint8)(socket->ack >> 24);
   packet[TCP_ACK+1] = (uint8)(socket->ack >> 16);
   packet[TCP_ACK+1] = (uint8)(socket->ack >> 16);
   packet[TCP_ACK+2] = (uint8)(socket->ack >> 8);
   packet[TCP_ACK+2] = (uint8)(socket->ack >> 8);
   packet[TCP_ACK+3] = (uint8)socket->ack;
   packet[TCP_ACK+3] = (uint8)socket->ack;
   count = RECEIVE_WINDOW - (socket->ack - socket->ackProcessed);
   count = RECEIVE_WINDOW - (socket->ack - socket->ackProcessed);
   if(count < 0)
   if(count < 0)
      count = 0;
      count = 0;
   packet[TCP_WINDOW_SIZE] = (uint8)(count >> 8);
   packet[TCP_WINDOW_SIZE] = (uint8)(count >> 8);
   packet[TCP_WINDOW_SIZE+1] = (uint8)count;
   packet[TCP_WINDOW_SIZE+1] = (uint8)count;
   packet[TCP_URGENT_POINTER] = 0;
   packet[TCP_URGENT_POINTER] = 0;
   packet[TCP_URGENT_POINTER+1] = 0;
   packet[TCP_URGENT_POINTER+1] = 0;
   IPSendPacket(socket, frame, length);
   IPSendPacket(socket, frame, length);
}
}
 
 
 
 
static void EthernetCreateResponse(unsigned char *packetOut,
static void EthernetCreateResponse(unsigned char *packetOut,
                                   const unsigned char *packet,
                                   const unsigned char *packet,
                                   int length)
                                   int length)
{
{
   //Swap destination and source fields
   //Swap destination and source fields
   memcpy(packetOut, packet, length);
   memcpy(packetOut, packet, length);
   memcpy(packetOut+ETHERNET_DEST, packet+ETHERNET_SOURCE, 6);
   memcpy(packetOut+ETHERNET_DEST, packet+ETHERNET_SOURCE, 6);
   memcpy(packetOut+ETHERNET_SOURCE, packet+ETHERNET_DEST, 6);
   memcpy(packetOut+ETHERNET_SOURCE, packet+ETHERNET_DEST, 6);
   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00)  //IP
   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00)  //IP
   {
   {
      memcpy(packetOut+IP_SOURCE, packet+IP_DEST, 4);
      memcpy(packetOut+IP_SOURCE, packet+IP_DEST, 4);
      memcpy(packetOut+IP_DEST, packet+IP_SOURCE, 4);
      memcpy(packetOut+IP_DEST, packet+IP_SOURCE, 4);
      if(packet[IP_PROTOCOL] == 0x06 || packet[IP_PROTOCOL] == 0x11)   //TCP/UDP
      if(packet[IP_PROTOCOL] == 0x06 || packet[IP_PROTOCOL] == 0x11)   //TCP/UDP
      {
      {
         memcpy(packetOut+TCP_SOURCE_PORT, packet+TCP_DEST_PORT, 2);
         memcpy(packetOut+TCP_SOURCE_PORT, packet+TCP_DEST_PORT, 2);
         memcpy(packetOut+TCP_DEST_PORT, packet+TCP_SOURCE_PORT, 2);
         memcpy(packetOut+TCP_DEST_PORT, packet+TCP_SOURCE_PORT, 2);
      }
      }
   }
   }
}
}
 
 
 
 
static void IPArp(unsigned char ipAddress[4])
static void IPArp(unsigned char ipAddress[4])
{
{
   IPFrame *frame;
   IPFrame *frame;
   uint8 *packetOut;
   uint8 *packetOut;
 
 
   frame = IPFrameGet(0);
   frame = IPFrameGet(0);
   if(frame == NULL)
   if(frame == NULL)
      return;
      return;
   packetOut = frame->packet;
   packetOut = frame->packet;
   memset(packetOut, 0, 512);
   memset(packetOut, 0, 512);
   memset(packetOut+ETHERNET_DEST, 0xff, 6);
   memset(packetOut+ETHERNET_DEST, 0xff, 6);
   memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
   memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
   packetOut[ETHERNET_FRAME_TYPE] = 0x08;
   packetOut[ETHERNET_FRAME_TYPE] = 0x08;
   packetOut[ETHERNET_FRAME_TYPE+1] = 0x06;
   packetOut[ETHERNET_FRAME_TYPE+1] = 0x06;
   packetOut[ARP_HARD_TYPE+1] = 0x01;
   packetOut[ARP_HARD_TYPE+1] = 0x01;
   packetOut[ARP_PROT_TYPE] = 0x08;
   packetOut[ARP_PROT_TYPE] = 0x08;
   packetOut[ARP_HARD_SIZE] = 0x06;
   packetOut[ARP_HARD_SIZE] = 0x06;
   packetOut[ARP_PROT_SIZE] = 0x04;
   packetOut[ARP_PROT_SIZE] = 0x04;
   packetOut[ARP_OP+1] = 1;
   packetOut[ARP_OP+1] = 1;
   memcpy(packetOut+ARP_ETHERNET_SENDER, ethernetAddressPlasma, 6);
   memcpy(packetOut+ARP_ETHERNET_SENDER, ethernetAddressPlasma, 6);
   memcpy(packetOut+ARP_IP_SENDER, ipAddressPlasma, 4);
   memcpy(packetOut+ARP_IP_SENDER, ipAddressPlasma, 4);
   memcpy(packetOut+ARP_IP_TARGET, ipAddress, 4);
   memcpy(packetOut+ARP_IP_TARGET, ipAddress, 4);
   IPSendPacket(NULL, frame, 60);
   IPSendPacket(NULL, frame, 60);
}
}
 
 
 
 
static void IPDhcp(const unsigned char *packet, int length, int state)
static void IPDhcp(const unsigned char *packet, int length, int state)
{
{
   uint8 *packetOut, *ptr;
   uint8 *packetOut, *ptr;
   const uint8 *ptr2;
   const uint8 *ptr2;
   IPFrame *frame;
   IPFrame *frame;
   static int request=0;
   static int request=0;
 
 
   if(state == 1)
   if(state == 1)
   {
   {
      //Create DHCP Discover
      //Create DHCP Discover
      frame = IPFrameGet(0);
      frame = IPFrameGet(0);
      if(frame == NULL)
      if(frame == NULL)
         return;
         return;
      packetOut = frame->packet;
      packetOut = frame->packet;
      memset(packetOut, 0, 512);
      memset(packetOut, 0, 512);
      memcpy(packetOut, dhcpDiscover, sizeof(dhcpDiscover));
      memcpy(packetOut, dhcpDiscover, sizeof(dhcpDiscover));
      memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
      memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
      memcpy(packetOut+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6);
      memcpy(packetOut+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6);
      memcpy(packetOut+DHCP_MAGIC_COOKIE, dhcpOptions, sizeof(dhcpOptions));
      memcpy(packetOut+DHCP_MAGIC_COOKIE, dhcpOptions, sizeof(dhcpOptions));
      memcpy(packetOut+DHCP_MAGIC_COOKIE+10, ethernetAddressPlasma, 6);
      memcpy(packetOut+DHCP_MAGIC_COOKIE+10, ethernetAddressPlasma, 6);
      IPSendPacket(NULL, frame, 400);
      IPSendPacket(NULL, frame, 400);
      request = DHCP_DISCOVER;
      request = DHCP_DISCOVER;
      DhcpRetrySeconds = 2;
      DhcpRetrySeconds = 2;
   }
   }
   else if(state == 2 && memcmp(packet+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6) == 0)
   else if(state == 2 && memcmp(packet+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6) == 0)
   {
   {
      if(packet[DHCP_MAGIC_COOKIE+6] == DHCP_OFFER && request == DHCP_DISCOVER)
      if(packet[DHCP_MAGIC_COOKIE+6] == DHCP_OFFER && request == DHCP_DISCOVER)
      {
      {
         //Process DHCP Offer and send DHCP Request
         //Process DHCP Offer and send DHCP Request
         frame = IPFrameGet(0);
         frame = IPFrameGet(0);
         if(frame == NULL)
         if(frame == NULL)
            return;
            return;
         packetOut = frame->packet;
         packetOut = frame->packet;
         memset(packetOut, 0, 512);
         memset(packetOut, 0, 512);
         memcpy(packetOut, dhcpDiscover, sizeof(dhcpDiscover));
         memcpy(packetOut, dhcpDiscover, sizeof(dhcpDiscover));
         memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
         memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
         memcpy(packetOut+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6);
         memcpy(packetOut+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6);
         memcpy(packetOut+DHCP_MAGIC_COOKIE, dhcpOptions, sizeof(dhcpOptions));
         memcpy(packetOut+DHCP_MAGIC_COOKIE, dhcpOptions, sizeof(dhcpOptions));
         memcpy(packetOut+DHCP_MAGIC_COOKIE+10, ethernetAddressPlasma, 6);
         memcpy(packetOut+DHCP_MAGIC_COOKIE+10, ethernetAddressPlasma, 6);
         request = DHCP_REQUEST;
         request = DHCP_REQUEST;
         packetOut[DHCP_MAGIC_COOKIE+6] = DHCP_REQUEST;
         packetOut[DHCP_MAGIC_COOKIE+6] = DHCP_REQUEST;
         ptr = packetOut+DHCP_MAGIC_COOKIE+sizeof(dhcpOptions)-1;
         ptr = packetOut+DHCP_MAGIC_COOKIE+sizeof(dhcpOptions)-1;
         ptr[0] = DHCP_REQUEST_IP;
         ptr[0] = DHCP_REQUEST_IP;
         ptr[1] = 4;
         ptr[1] = 4;
         memcpy(ptr+2, packet+DHCP_YOUR_IP, 4);
         memcpy(ptr+2, packet+DHCP_YOUR_IP, 4);
         ptr[6] = DHCP_REQUEST_SERV_IP;
         ptr[6] = DHCP_REQUEST_SERV_IP;
         ptr[7] = 4;
         ptr[7] = 4;
         memcpy(ptr+8, packet+DHCP_SERVER_IP, 4);
         memcpy(ptr+8, packet+DHCP_SERVER_IP, 4);
         ptr[12] = DHCP_END_OPTION;
         ptr[12] = DHCP_END_OPTION;
         IPSendPacket(NULL, frame, 400);
         IPSendPacket(NULL, frame, 400);
      }
      }
      else if(packet[DHCP_MAGIC_COOKIE+6] == DHCP_ACK && request == DHCP_REQUEST)
      else if(packet[DHCP_MAGIC_COOKIE+6] == DHCP_ACK && request == DHCP_REQUEST)
      {
      {
         //Process DHCP Ack
         //Process DHCP Ack
         request = 0;
         request = 0;
         DhcpRetrySeconds = 3600*4;
         DhcpRetrySeconds = 3600*4;
         memcpy(ipAddressPlasma, packet+DHCP_YOUR_IP, 4);
         memcpy(ipAddressPlasma, packet+DHCP_YOUR_IP, 4);
         printf("IP=%d.%d.%d.%d ", ipAddressPlasma[0], ipAddressPlasma[1],
         printf("IP=%d.%d.%d.%d ", ipAddressPlasma[0], ipAddressPlasma[1],
            ipAddressPlasma[2], ipAddressPlasma[3]);
            ipAddressPlasma[2], ipAddressPlasma[3]);
         memcpy(ipAddressGateway, packet+DHCP_GATEWAY_IP, 4);
         memcpy(ipAddressGateway, packet+DHCP_GATEWAY_IP, 4);
         if(ipAddressGateway[0] == 0 && ipAddressGateway[1] == 0 &&
         if(ipAddressGateway[0] == 0 && ipAddressGateway[1] == 0 &&
            ipAddressGateway[2] == 0 && ipAddressGateway[3] == 0)
            ipAddressGateway[2] == 0 && ipAddressGateway[3] == 0)
            memcpy(ipAddressGateway, packet+DHCP_SERVER_IP, 4);
            memcpy(ipAddressGateway, packet+DHCP_SERVER_IP, 4);
         printf("GW=%d.%d.%d.%d ", ipAddressGateway[0], ipAddressGateway[1],
         printf("GW=%d.%d.%d.%d ", ipAddressGateway[0], ipAddressGateway[1],
            ipAddressGateway[2], ipAddressGateway[3]);
            ipAddressGateway[2], ipAddressGateway[3]);
         memcpy(ethernetAddressGateway, packet+ETHERNET_SOURCE, 6);
         memcpy(ethernetAddressGateway, packet+ETHERNET_SOURCE, 6);
         ptr2 = packet+DHCP_MAGIC_COOKIE+4;
         ptr2 = packet+DHCP_MAGIC_COOKIE+4;
         while(ptr2[0] != DHCP_END_OPTION && (int)(ptr2 - packet) < length)
         while(ptr2[0] != DHCP_END_OPTION && (int)(ptr2 - packet) < length)
         {
         {
            if(ptr2[0] == DHCP_PARAM_DNS)
            if(ptr2[0] == DHCP_PARAM_DNS)
            {
            {
               ipAddressDns = (ptr2[2] << 24) | (ptr2[3] << 16) | (ptr2[4] << 8) | ptr2[5];
               ipAddressDns = (ptr2[2] << 24) | (ptr2[3] << 16) | (ptr2[4] << 8) | ptr2[5];
               printf("DNS=%d.%d.%d.%d ", ptr2[2], ptr2[3], ptr2[4], ptr2[5]);
               printf("DNS=%d.%d.%d.%d ", ptr2[2], ptr2[3], ptr2[4], ptr2[5]);
            }
            }
            ptr2 += ptr2[1] + 2;
            ptr2 += ptr2[1] + 2;
         }
         }
 
 
         //Check if DHCP reply came from gateway
         //Check if DHCP reply came from gateway
         if(memcmp(packet+IP_SOURCE, ipAddressGateway, 4))
         if(memcmp(packet+IP_SOURCE, ipAddressGateway, 4))
         {
         {
            memset(ethernetAddressGateway, 0xff, 6);
            memset(ethernetAddressGateway, 0xff, 6);
            IPArp(ipAddressGateway);     //Send ARP to gateway
            IPArp(ipAddressGateway);     //Send ARP to gateway
         }
         }
      }
      }
   }
   }
}
}
 
 
 
 
uint32 IPAddressSelf(void)
uint32 IPAddressSelf(void)
{
{
   return (ipAddressPlasma[0] << 24) | (ipAddressPlasma[1] << 16) |
   return (ipAddressPlasma[0] << 24) | (ipAddressPlasma[1] << 16) |
          (ipAddressPlasma[2] << 8) | ipAddressPlasma[3];
          (ipAddressPlasma[2] << 8) | ipAddressPlasma[3];
}
}
 
 
 
 
static int IPProcessTCPPacket(IPFrame *frameIn)
static int IPProcessTCPPacket(IPFrame *frameIn)
{
{
   uint32 seq, ack;
   uint32 seq, ack;
   int length, ip_length, bytes, rc=0, notify=0, window;
   int length, ip_length, bytes, rc=0, notify=0, window;
   IPSocket *socket, *socketNew;
   IPSocket *socket, *socketNew;
   IPFrame *frameOut, *frame2, *framePrev;
   IPFrame *frameOut, *frame2, *framePrev;
   uint8 *packet, *packetOut;
   uint8 *packet, *packetOut;
 
 
 
#if 0
 
   //Test missing packets
 
   extern void __stdcall Sleep(unsigned long value);
 
   Sleep(1);
 
   if(rand() % 13 == 0)
 
      return 0;
 
#endif
 
 
   packet = frameIn->packet;
   packet = frameIn->packet;
   length = frameIn->length;
   length = frameIn->length;
 
 
   ip_length = (packet[IP_LENGTH] << 8) | packet[IP_LENGTH+1];
   ip_length = (packet[IP_LENGTH] << 8) | packet[IP_LENGTH+1];
   seq = (packet[TCP_SEQ] << 24) | (packet[TCP_SEQ+1] << 16) |
   seq = (packet[TCP_SEQ] << 24) | (packet[TCP_SEQ+1] << 16) |
         (packet[TCP_SEQ+2] << 8) | packet[TCP_SEQ+3];
         (packet[TCP_SEQ+2] << 8) | packet[TCP_SEQ+3];
   ack = (packet[TCP_ACK] << 24) | (packet[TCP_ACK+1] << 16) |
   ack = (packet[TCP_ACK] << 24) | (packet[TCP_ACK+1] << 16) |
         (packet[TCP_ACK+2] << 8) | packet[TCP_ACK+3];
         (packet[TCP_ACK+2] << 8) | packet[TCP_ACK+3];
 
 
   //Check if start of connection
   //Check if start of connection
   if((packet[TCP_FLAGS] & (TCP_FLAGS_SYN | TCP_FLAGS_ACK)) == TCP_FLAGS_SYN)
   if((packet[TCP_FLAGS] & (TCP_FLAGS_SYN | TCP_FLAGS_ACK)) == TCP_FLAGS_SYN)
   {
   {
      if(IPVerbose)
      if(IPVerbose)
         printf("S");
         printf("S");
      //Check if duplicate SYN
      //Check if duplicate SYN
      for(socket = SocketHead; socket; socket = socket->next)
      for(socket = SocketHead; socket; socket = socket->next)
      {
      {
         if(socket->state != IP_LISTEN &&
         if(socket->state != IP_LISTEN &&
            packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
            packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
            memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&
            memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&
            memcmp(packet+TCP_SOURCE_PORT, socket->headerRcv+TCP_SOURCE_PORT, 4) == 0)
            memcmp(packet+TCP_SOURCE_PORT, socket->headerRcv+TCP_SOURCE_PORT, 4) == 0)
         {
         {
            if(IPVerbose)
            if(IPVerbose)
               printf("s");
               printf("s");
            return 0;
            return 0;
         }
         }
      }
      }
 
 
      //Find an open port
      //Find an open port
      for(socket = SocketHead; socket; socket = socket->next)
      for(socket = SocketHead; socket; socket = socket->next)
      {
      {
         if(socket->state == IP_LISTEN &&
         if(socket->state == IP_LISTEN &&
            packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
            packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
            memcmp(packet+TCP_DEST_PORT, socket->headerRcv+TCP_DEST_PORT, 2) == 0)
            memcmp(packet+TCP_DEST_PORT, socket->headerRcv+TCP_DEST_PORT, 2) == 0)
         {
         {
            //Create a new socket
            //Create a new socket
            frameOut = IPFrameGet(FRAME_COUNT_SYNC);
            frameOut = IPFrameGet(FRAME_COUNT_SYNC);
            if(frameOut == NULL)
            if(frameOut == NULL)
               return 0;
               return 0;
            socketNew = (IPSocket*)malloc(sizeof(IPSocket));
            socketNew = (IPSocket*)malloc(sizeof(IPSocket));
            if(socketNew == NULL)
            if(socketNew == NULL)
               return 0;
               return 0;
            memcpy(socketNew, socket, sizeof(IPSocket));
            memcpy(socketNew, socket, sizeof(IPSocket));
            socketNew->state = IP_TCP;
            socketNew->state = IP_TCP;
            socketNew->timeout = SOCKET_TIMEOUT;
            socketNew->timeout = SOCKET_TIMEOUT;
            socketNew->ack = seq;
            socketNew->ack = seq;
            socketNew->ackProcessed = seq + 1;
            socketNew->ackProcessed = seq + 1;
            socketNew->seq = socketNew->ack + 0x12345678;
            socketNew->seq = socketNew->ack + 0x12345678;
            socketNew->seqReceived = socketNew->seq;
            socketNew->seqReceived = socketNew->seq;
            socketNew->seqWindow = (packet[TCP_WINDOW_SIZE] << 8) | packet[TCP_WINDOW_SIZE+1];
            socketNew->seqWindow = (packet[TCP_WINDOW_SIZE] << 8) | packet[TCP_WINDOW_SIZE+1];
 
 
            //Send ACK
            //Send ACK
            packetOut = frameOut->packet;
            packetOut = frameOut->packet;
            EthernetCreateResponse(packetOut, packet, length);
            EthernetCreateResponse(packetOut, packet, length);
            memcpy(socketNew->headerRcv, packet, TCP_SEQ);
            memcpy(socketNew->headerRcv, packet, TCP_SEQ);
            memcpy(socketNew->headerSend, packetOut, TCP_SEQ);
            memcpy(socketNew->headerSend, packetOut, TCP_SEQ);
            packetOut[TCP_FLAGS] = TCP_FLAGS_SYN | TCP_FLAGS_ACK;
            packetOut[TCP_FLAGS] = TCP_FLAGS_SYN | TCP_FLAGS_ACK;
            ++socketNew->ack;
            ++socketNew->ack;
            packetOut[TCP_DATA] = 2;    //maximum segment size = 536
            packetOut[TCP_DATA] = 2;    //maximum segment size = 536
            packetOut[TCP_DATA+1] = 4;
            packetOut[TCP_DATA+1] = 4;
            packetOut[TCP_DATA+2] = 2;
            packetOut[TCP_DATA+2] = 2;
            packetOut[TCP_DATA+3] = 24;
            packetOut[TCP_DATA+3] = 24;
            TCPSendPacket(socketNew, frameOut, TCP_DATA+4);
            TCPSendPacket(socketNew, frameOut, TCP_DATA+4);
            ++socketNew->seq;
            ++socketNew->seq;
 
 
            //Add socket to linked list
            //Add socket to linked list
            OS_MutexPend(IPMutex);
            OS_MutexPend(IPMutex);
            socketNew->next = SocketHead;
            socketNew->next = SocketHead;
            socketNew->prev = NULL;
            socketNew->prev = NULL;
            if(SocketHead)
            if(SocketHead)
               SocketHead->prev = socketNew;
               SocketHead->prev = socketNew;
            SocketHead = socketNew;
            SocketHead = socketNew;
            OS_MutexPost(IPMutex);
            OS_MutexPost(IPMutex);
            if(socketNew->funcPtr)
            if(socketNew->funcPtr)
               OS_Job((JobFunc_t)socketNew->funcPtr, socketNew, 0, 0);
               OS_Job((JobFunc_t)socketNew->funcPtr, socketNew, 0, 0);
            return 0;
            return 0;
         }
         }
      }
      }
 
 
      //Send reset
      //Send reset
      frameOut = IPFrameGet(0);
      frameOut = IPFrameGet(0);
      if(frameOut == NULL)
      if(frameOut == NULL)
         return 0;
         return 0;
      packetOut = frameOut->packet;
      packetOut = frameOut->packet;
      EthernetCreateResponse(packetOut, packet, TCP_DATA);
      EthernetCreateResponse(packetOut, packet, TCP_DATA);
      memset(packetOut+TCP_SEQ, 0, 4);
      memset(packetOut+TCP_SEQ, 0, 4);
      ++seq;
      ++seq;
      packetOut[TCP_ACK]   = (uint8)(seq >> 24);
      packetOut[TCP_ACK]   = (uint8)(seq >> 24);
      packetOut[TCP_ACK+1] = (uint8)(seq >> 16);
      packetOut[TCP_ACK+1] = (uint8)(seq >> 16);
      packetOut[TCP_ACK+2] = (uint8)(seq >> 8);
      packetOut[TCP_ACK+2] = (uint8)(seq >> 8);
      packetOut[TCP_ACK+3] = (uint8)seq;
      packetOut[TCP_ACK+3] = (uint8)seq;
      packetOut[TCP_HEADER_LENGTH] = 0x50;
      packetOut[TCP_HEADER_LENGTH] = 0x50;
      packetOut[TCP_FLAGS] = TCP_FLAGS_RST;
      packetOut[TCP_FLAGS] = TCP_FLAGS_RST;
      IPSendPacket(NULL, frameOut, TCP_DATA);
      IPSendPacket(NULL, frameOut, TCP_DATA);
      return 0;
      return 0;
   }
   }
 
 
   //Find an open socket
   //Find an open socket
   for(socket = SocketHead; socket; socket = socket->next)
   for(socket = SocketHead; socket; socket = socket->next)
   {
   {
      if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
      if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
         memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&
         memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&
         memcmp(packet+TCP_SOURCE_PORT, socket->headerRcv+TCP_SOURCE_PORT, 4) == 0)
         memcmp(packet+TCP_SOURCE_PORT, socket->headerRcv+TCP_SOURCE_PORT, 4) == 0)
      {
      {
         break;
         break;
      }
      }
   }
   }
   if(socket == NULL)
   if(socket == NULL)
   {
   {
      return 0;
      return 0;
   }
   }
 
 
   //Determine window
   //Determine window
   socket->seqWindow = (packet[TCP_WINDOW_SIZE] << 8) | packet[TCP_WINDOW_SIZE+1];
   socket->seqWindow = (packet[TCP_WINDOW_SIZE] << 8) | packet[TCP_WINDOW_SIZE+1];
   bytes = ip_length - (TCP_DATA - IP_VERSION_LENGTH);
   bytes = ip_length - (TCP_DATA - IP_VERSION_LENGTH);
 
 
   //Check if packets can be removed from retransmition list
   //Check if packets can be removed from retransmition list
   if(packet[TCP_FLAGS] & TCP_FLAGS_ACK)
   if(packet[TCP_FLAGS] & TCP_FLAGS_ACK)
   {
   {
      if(ack != socket->seqReceived)
      if(ack != socket->seqReceived)
      {
      {
         OS_MutexPend(IPMutex);
         OS_MutexPend(IPMutex);
         for(frame2 = FrameResendHead; frame2; )
         for(frame2 = FrameResendHead; frame2; )
         {
         {
            framePrev = frame2;
            framePrev = frame2;
            frame2 = frame2->next;
            frame2 = frame2->next;
            if(framePrev->socket == socket && (int)(ack - framePrev->seqEnd) >= 0)
            if(framePrev->socket == socket && (int)(ack - framePrev->seqEnd) >= 0)
            {
            {
               //Remove packet from retransmition queue
               //Remove packet from retransmition queue
               if(socket->timeout)
               if(socket->timeout)
                  socket->timeout = socket->timeoutReset;
                  socket->timeout = socket->timeoutReset;
               FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);
               FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);
               FrameFree(framePrev);
               FrameFree(framePrev);
            }
            }
         }
         }
         OS_MutexPost(IPMutex);
         OS_MutexPost(IPMutex);
         socket->seqReceived = ack;
         socket->seqReceived = ack;
         socket->resentDone = 0;
         socket->resentDone = 0;
      }
      }
      else if(ack == socket->seqReceived && bytes == 0 &&
      else if(ack == socket->seqReceived && bytes == 0 &&
         (packet[TCP_FLAGS] & (TCP_FLAGS_RST | TCP_FLAGS_FIN)) == 0 &&
         (packet[TCP_FLAGS] & (TCP_FLAGS_RST | TCP_FLAGS_FIN)) == 0 &&
         socket->resentDone == 0)
         socket->resentDone == 0)
      {
      {
         //Detected that packet was lost, resend all
         //Detected that packet was lost, resend
         if(IPVerbose)
         if(IPVerbose)
            printf("A");
            printf("A");
         OS_MutexPend(IPMutex);
         OS_MutexPend(IPMutex);
         for(frame2 = FrameResendHead; frame2; )
         for(frame2 = FrameResendHead; frame2; )
         {
         {
            framePrev = frame2;
            framePrev = frame2;
            frame2 = frame2->next;
            frame2 = frame2->next;
            if(framePrev->socket == socket)
            if(framePrev->socket == socket)
            {
            {
               //Remove packet from retransmition queue
               //Remove packet from retransmition queue
               FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);
               FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);
               IPSendFrame(framePrev);
               IPSendFrame(framePrev);
 
               break;
            }
            }
         }
         }
         OS_MutexPost(IPMutex);
         OS_MutexPost(IPMutex);
         socket->resentDone = 1;
         socket->resentDone = 1;
      }
      }
   }
   }
 
 
   //Check if SYN/ACK
   //Check if SYN/ACK
   if((packet[TCP_FLAGS] & (TCP_FLAGS_SYN | TCP_FLAGS_ACK)) ==
   if((packet[TCP_FLAGS] & (TCP_FLAGS_SYN | TCP_FLAGS_ACK)) ==
      (TCP_FLAGS_SYN | TCP_FLAGS_ACK))
      (TCP_FLAGS_SYN | TCP_FLAGS_ACK))
   {
   {
      //Ack SYN/ACK
      //Ack SYN/ACK
      socket->ack = seq + 1;
      socket->ack = seq + 1;
      socket->ackProcessed = seq + 1;
      socket->ackProcessed = seq + 1;
      frameOut = IPFrameGet(FRAME_COUNT_SEND);
      frameOut = IPFrameGet(FRAME_COUNT_SEND);
      if(frameOut)
      if(frameOut)
      {
      {
         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
         TCPSendPacket(socket, frameOut, TCP_DATA);
         TCPSendPacket(socket, frameOut, TCP_DATA);
      }
      }
      if(socket->funcPtr)
      if(socket->funcPtr)
         OS_Job((JobFunc_t)socket->funcPtr, socket, 0, 0);
         OS_Job((JobFunc_t)socket->funcPtr, socket, 0, 0);
      return 0;
      return 0;
   }
   }
   if(packet[TCP_HEADER_LENGTH] != 0x50)
   if(packet[TCP_HEADER_LENGTH] != 0x50)
   {
   {
      if(IPVerbose)
      if(IPVerbose)
         printf("length error\n");
         printf("length error\n");
      return 0;
      return 0;
   }
   }
 
 
 
   if(frameIn->length > ip_length + IP_VERSION_LENGTH)
 
      frameIn->length = (uint16)(ip_length + IP_VERSION_LENGTH);
 
 
   //Check if RST flag set
   //Check if RST flag set
   if(packet[TCP_FLAGS] & TCP_FLAGS_RST)
   if(packet[TCP_FLAGS] & TCP_FLAGS_RST)
   {
   {
      notify = 1;
      notify = 1;
      IPClose2(socket);
      IPClose2(socket);
   }
   }
   //Copy packet into socket
   //Copy packet into socket
   else if(socket->ack == seq && bytes > 0)
   else if(socket->ack == seq && bytes > 0)
   {
   {
      //Insert packet into socket linked list
      //Insert packet into socket linked list
      notify = 1;
      notify = 1;
      if(socket->timeout)
      if(socket->timeout)
         socket->timeout = socket->timeoutReset;
         socket->timeout = socket->timeoutReset;
      if(IPVerbose)
      if(IPVerbose)
         printf("D");
         printf("D");
      if(frameIn->length > ip_length + IP_VERSION_LENGTH)
      for(;;)
         frameIn->length = (uint16)(ip_length + IP_VERSION_LENGTH);
      {
      FrameInsert(&socket->frameReadHead, &socket->frameReadTail, frameIn);
      FrameInsert(&socket->frameReadHead, &socket->frameReadTail, frameIn);
      socket->ack += bytes;
         socket->ack += bytes;
 
 
 
         //Check if any frameFuture packets match the seq
 
         for(;;)
 
         {
 
            frame2 = socket->frameFutureTail;
 
            if(frame2 == NULL)
 
               break;
 
            packet = frame2->packet;
 
            seq = (packet[TCP_SEQ] << 24) | (packet[TCP_SEQ+1] << 16) |
 
                  (packet[TCP_SEQ+2] << 8) | packet[TCP_SEQ+3];
 
            if(socket->ack > seq)
 
            {
 
               FrameRemove(&socket->frameFutureHead, &socket->frameFutureTail, frame2);
 
               FrameFree(frame2);
 
            }
 
            else if(socket->ack == seq)
 
            {
 
               FrameRemove(&socket->frameFutureHead, &socket->frameFutureTail, frame2);
 
               break;
 
            }
 
            else
 
            {
 
               frame2 = NULL;
 
               break;
 
            }
 
         }
 
         if(frame2 == NULL)
 
            break;
 
         ip_length = (packet[IP_LENGTH] << 8) | packet[IP_LENGTH+1];
 
         bytes = ip_length - (TCP_DATA - IP_VERSION_LENGTH);
 
         frameIn = frame2;
 
         if(IPVerbose)
 
            printf("d");
 
      }
 
 
      //Ack data
      //Ack data
      window = RECEIVE_WINDOW - (socket->ack - socket->ackProcessed);
      window = RECEIVE_WINDOW - (socket->ack - socket->ackProcessed);
      frameOut = IPFrameGet(FRAME_COUNT_SEND);
      frameOut = IPFrameGet(FRAME_COUNT_SEND);
      if(frameOut)
      if(frameOut)
      {
      {
         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
         TCPSendPacket(socket, frameOut, TCP_DATA);
         TCPSendPacket(socket, frameOut, TCP_DATA);
      }
      }
 
 
      //Using frame
      //Using frame
      rc = 1;
      rc = 1;
   }
   }
   else if(bytes)
   else if(bytes)
   {
   {
 
      if(socket->ack < seq && seq <= socket->ack + 65536)
 
      {
 
         //Save frame to frameFuture
 
         FrameInsert(&socket->frameFutureHead, &socket->frameFutureTail, frameIn);
 
         rc = 1;  //using frame
 
      }
 
 
      //Ack with current offset since data missing
      //Ack with current offset since data missing
      frameOut = IPFrameGet(FRAME_COUNT_SEND);
      frameOut = IPFrameGet(FRAME_COUNT_SEND);
      if(frameOut)
      if(frameOut)
      {
      {
         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
         TCPSendPacket(socket, frameOut, TCP_DATA);
         TCPSendPacket(socket, frameOut, TCP_DATA);
      }
      }
   }
   }
 
 
   //Check if FIN flag set
   //Check if FIN flag set
   if(packet[TCP_FLAGS] & TCP_FLAGS_FIN && socket->ack >= seq)
   if((packet[TCP_FLAGS] & TCP_FLAGS_FIN) && socket->ack >= seq)
   {
   {
      notify = 1;
      notify = 1;
      socket->timeout = SOCKET_TIMEOUT;
      socket->timeout = SOCKET_TIMEOUT;
      if(IPVerbose)
      if(IPVerbose)
         printf("F");
         printf("F");
      frameOut = IPFrameGet(0);
      frameOut = IPFrameGet(0);
      if(frameOut == NULL)
      if(frameOut == NULL)
         return 0;
         return 0;
      packetOut = frameOut->packet;
      packetOut = frameOut->packet;
      packetOut[TCP_FLAGS] = TCP_FLAGS_ACK;
      packetOut[TCP_FLAGS] = TCP_FLAGS_ACK;
      ++socket->ack;
      ++socket->ack;
      TCPSendPacket(socket, frameOut, TCP_DATA);
      TCPSendPacket(socket, frameOut, TCP_DATA);
      if(socket->state == IP_FIN_SERVER)
      if(socket->state == IP_FIN_SERVER)
         socket->timeout = SOCKET_TIMEOUT;
         socket->timeout = SOCKET_TIMEOUT;
      else if(socket->state == IP_TCP)
      else if(socket->state == IP_TCP)
         socket->state = IP_FIN_CLIENT;
         socket->state = IP_FIN_CLIENT;
   }
   }
 
 
   //Notify application
   //Notify application
   if(socket->funcPtr && notify)
   if(socket->funcPtr && notify)
      OS_Job((JobFunc_t)socket->funcPtr, socket, 0, 0);
      OS_Job((JobFunc_t)socket->funcPtr, socket, 0, 0);
   return rc;
   return rc;
}
}
 
 
 
 
int IPProcessEthernetPacket(IPFrame *frameIn, int length)
int IPProcessEthernetPacket(IPFrame *frameIn, int length)
{
{
   int ip_length, rc;
   int ip_length, rc;
   IPSocket *socket;
   IPSocket *socket;
   IPFrame *frameOut;
   IPFrame *frameOut;
   uint8 *packet, *packetOut;
   uint8 *packet, *packetOut;
 
 
   packet = frameIn->packet;
   packet = frameIn->packet;
   frameIn->length = (uint16)length;
   frameIn->length = (uint16)length;
 
 
   if(packet[ETHERNET_FRAME_TYPE] != 0x08 || frameIn->length > PACKET_SIZE)
   if(packet[ETHERNET_FRAME_TYPE] != 0x08 || frameIn->length > PACKET_SIZE)
      return 0;  //wrong ethernet type, packet not used
      return 0;  //wrong ethernet type, packet not used
 
 
   //ARP?
   //ARP?
   if(packet[ETHERNET_FRAME_TYPE+1] == 0x06)
   if(packet[ETHERNET_FRAME_TYPE+1] == 0x06)
   {
   {
      //Check if ARP reply
      //Check if ARP reply
      if(memcmp(packet+ETHERNET_DEST, ethernetAddressPlasma, 6) == 0 &&
      if(memcmp(packet+ETHERNET_DEST, ethernetAddressPlasma, 6) == 0 &&
         packet[ARP_OP+1] == 2)
         packet[ARP_OP+1] == 2)
      {
      {
         memcpy(ArpCache[ArpCacheIndex].ip, packet+ARP_IP_SENDER, 4);
         memcpy(ArpCache[ArpCacheIndex].ip, packet+ARP_IP_SENDER, 4);
         memcpy(ArpCache[ArpCacheIndex].mac, packet+ARP_ETHERNET_SENDER, 6);
         memcpy(ArpCache[ArpCacheIndex].mac, packet+ARP_ETHERNET_SENDER, 6);
         if(++ArpCacheIndex >= sizeof(ArpCache) / sizeof(ArpCache_t))
         if(++ArpCacheIndex >= sizeof(ArpCache) / sizeof(ArpCache_t))
            ArpCacheIndex = 0;
            ArpCacheIndex = 0;
         if(memcmp(packet+ARP_IP_SENDER, ipAddressGateway, 4) == 0)
         if(memcmp(packet+ARP_IP_SENDER, ipAddressGateway, 4) == 0)
         {
         {
            //Found MAC address for gateway
            //Found MAC address for gateway
            memcpy(ethernetAddressGateway, packet+ARP_ETHERNET_SENDER, 6);
            memcpy(ethernetAddressGateway, packet+ARP_ETHERNET_SENDER, 6);
         }
         }
         return 0;
         return 0;
      }
      }
 
 
      //Check if ARP request
      //Check if ARP request
      if(packet[ARP_OP] != 0 || packet[ARP_OP+1] != 1 ||
      if(packet[ARP_OP] != 0 || packet[ARP_OP+1] != 1 ||
         memcmp(packet+ARP_IP_TARGET, ipAddressPlasma, 4))
         memcmp(packet+ARP_IP_TARGET, ipAddressPlasma, 4))
         return 0;
         return 0;
      //Create ARP response
      //Create ARP response
      frameOut = IPFrameGet(0);
      frameOut = IPFrameGet(0);
      if(frameOut == NULL)
      if(frameOut == NULL)
         return 0;
         return 0;
      packetOut = frameOut->packet;
      packetOut = frameOut->packet;
      memcpy(packetOut, packet, frameIn->length);
      memcpy(packetOut, packet, frameIn->length);
      memcpy(packetOut+ETHERNET_DEST, packet+ETHERNET_SOURCE, 6);
      memcpy(packetOut+ETHERNET_DEST, packet+ETHERNET_SOURCE, 6);
      memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
      memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
      packetOut[ARP_OP+1] = 2; //ARP reply
      packetOut[ARP_OP+1] = 2; //ARP reply
      memcpy(packetOut+ARP_ETHERNET_SENDER, ethernetAddressPlasma, 6);
      memcpy(packetOut+ARP_ETHERNET_SENDER, ethernetAddressPlasma, 6);
      memcpy(packetOut+ARP_IP_SENDER, packet+ARP_IP_TARGET, 4);
      memcpy(packetOut+ARP_IP_SENDER, packet+ARP_IP_TARGET, 4);
      memcpy(packetOut+ARP_ETHERNET_TARGET, packet+ARP_ETHERNET_SENDER, 6);
      memcpy(packetOut+ARP_ETHERNET_TARGET, packet+ARP_ETHERNET_SENDER, 6);
      memcpy(packetOut+ARP_IP_TARGET, packet+ARP_IP_SENDER, 4);
      memcpy(packetOut+ARP_IP_TARGET, packet+ARP_IP_SENDER, 4);
      IPSendPacket(NULL, frameOut, frameIn->length);
      IPSendPacket(NULL, frameOut, frameIn->length);
      return 0;
      return 0;
   }
   }
 
 
   //Check if proper type of packet
   //Check if proper type of packet
   ip_length = (packet[IP_LENGTH] << 8) | packet[IP_LENGTH+1];
   ip_length = (packet[IP_LENGTH] << 8) | packet[IP_LENGTH+1];
   if(frameIn->length < UDP_DATA || ip_length > frameIn->length - IP_VERSION_LENGTH)
   if(frameIn->length < UDP_DATA || ip_length > frameIn->length - IP_VERSION_LENGTH)
      return 0;
      return 0;
   if(packet[ETHERNET_FRAME_TYPE+1] != 0x00 ||
   if(packet[ETHERNET_FRAME_TYPE+1] != 0x00 ||
      packet[IP_VERSION_LENGTH] != 0x45)
      packet[IP_VERSION_LENGTH] != 0x45)
      return 0;
      return 0;
 
 
   //Check if DHCP reply
   //Check if DHCP reply
   if(packet[IP_PROTOCOL] == 0x11 &&
   if(packet[IP_PROTOCOL] == 0x11 &&
      packet[UDP_SOURCE_PORT] == 0 && packet[UDP_SOURCE_PORT+1] == 67 &&
      packet[UDP_SOURCE_PORT] == 0 && packet[UDP_SOURCE_PORT+1] == 67 &&
      packet[UDP_DEST_PORT] == 0 && packet[UDP_DEST_PORT+1] == 68)
      packet[UDP_DEST_PORT] == 0 && packet[UDP_DEST_PORT+1] == 68)
   {
   {
      IPDhcp(packet, frameIn->length, 2);            //DHCP reply
      IPDhcp(packet, frameIn->length, 2);            //DHCP reply
      return 0;
      return 0;
   }
   }
 
 
   //Check if correct destination address
   //Check if correct destination address
   if(memcmp(packet+ETHERNET_DEST, ethernetAddressPlasma, 6) ||
   if(memcmp(packet+ETHERNET_DEST, ethernetAddressPlasma, 6) ||
      memcmp(packet+IP_DEST, ipAddressPlasma, 4))
      memcmp(packet+IP_DEST, ipAddressPlasma, 4))
      return 0;
      return 0;
   rc = EthernetVerifyChecksums(packet, frameIn->length);
   rc = EthernetVerifyChecksums(packet, frameIn->length);
#ifndef WIN32
#ifndef WIN32
   if(rc && FrameSendFunc)
   if(rc && FrameSendFunc)
   {
   {
      printf("C ");
      printf("C ");
      return 0;
      return 0;
   }
   }
#endif
#endif
 
 
   //PING request?
   //PING request?
   if(packet[IP_PROTOCOL] == 1)
   if(packet[IP_PROTOCOL] == 1)
   {
   {
      if(packet[PING_TYPE] == 0)  //PING reply
      if(packet[PING_TYPE] == 0)  //PING reply
      {
      {
         for(socket = SocketHead; socket; socket = socket->next)
         for(socket = SocketHead; socket; socket = socket->next)
         {
         {
            if(socket->state == IP_PING &&
            if(socket->state == IP_PING &&
               memcmp(packet+IP_SOURCE, socket->headerSend+IP_DEST, 4) == 0)
               memcmp(packet+IP_SOURCE, socket->headerSend+IP_DEST, 4) == 0)
            {
            {
               OS_Job((JobFunc_t)socket->funcPtr, socket, 0, 0);
               OS_Job((JobFunc_t)socket->funcPtr, socket, 0, 0);
               return 0;
               return 0;
            }
            }
         }
         }
      }
      }
      if(packet[PING_TYPE] != 8)
      if(packet[PING_TYPE] != 8)
         return 0;
         return 0;
      frameOut = IPFrameGet(FRAME_COUNT_SEND);
      frameOut = IPFrameGet(FRAME_COUNT_SEND);
      if(frameOut == NULL)
      if(frameOut == NULL)
         return 0;
         return 0;
      packetOut = frameOut->packet;
      packetOut = frameOut->packet;
      EthernetCreateResponse(packetOut, packet, frameIn->length);
      EthernetCreateResponse(packetOut, packet, frameIn->length);
      frameOut->packet[PING_TYPE] = 0;       //PING reply
      frameOut->packet[PING_TYPE] = 0;       //PING reply
      IPSendPacket(NULL, frameOut, frameIn->length);
      IPSendPacket(NULL, frameOut, frameIn->length);
      return 0;
      return 0;
   }
   }
 
 
   //TCP packet?
   //TCP packet?
   if(packet[IP_PROTOCOL] == 0x06)
   if(packet[IP_PROTOCOL] == 0x06)
   {
   {
      return IPProcessTCPPacket(frameIn);
      return IPProcessTCPPacket(frameIn);
   }
   }
 
 
   //UDP packet?
   //UDP packet?
   if(packet[IP_PROTOCOL] == 0x11)
   if(packet[IP_PROTOCOL] == 0x11)
   {
   {
      //Find open socket
      //Find open socket
      for(socket = SocketHead; socket; socket = socket->next)
      for(socket = SocketHead; socket; socket = socket->next)
      {
      {
         if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
         if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
            memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&
            memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&
            memcmp(packet+UDP_SOURCE_PORT, socket->headerRcv+UDP_SOURCE_PORT, 2) == 0)
            memcmp(packet+UDP_SOURCE_PORT, socket->headerRcv+UDP_SOURCE_PORT, 2) == 0)
         {
         {
            break;
            break;
         }
         }
      }
      }
 
 
      if(socket == NULL)
      if(socket == NULL)
      {
      {
         //Find listening socket
         //Find listening socket
         for(socket = SocketHead; socket; socket = socket->next)
         for(socket = SocketHead; socket; socket = socket->next)
         {
         {
            if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
            if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
               memcmp(packet+UDP_DEST_PORT, socket->headerRcv+UDP_DEST_PORT, 2) == 0)
               memcmp(packet+UDP_DEST_PORT, socket->headerRcv+UDP_DEST_PORT, 2) == 0)
            {
            {
               EthernetCreateResponse(socket->headerSend, packet, UDP_DATA);
               EthernetCreateResponse(socket->headerSend, packet, UDP_DATA);
               break;
               break;
            }
            }
         }
         }
      }
      }
 
 
      if(socket)
      if(socket)
      {
      {
         if(IPVerbose)
         if(IPVerbose)
            printf("U");
            printf("U");
         FrameInsert(&socket->frameReadHead, &socket->frameReadTail, frameIn);
         FrameInsert(&socket->frameReadHead, &socket->frameReadTail, frameIn);
         OS_Job((JobFunc_t)socket->funcPtr, socket, 0, 0);
         OS_Job((JobFunc_t)socket->funcPtr, socket, 0, 0);
         return 1;
         return 1;
      }
      }
   }
   }
   return 0;
   return 0;
}
}
 
 
 
 
#ifndef WIN32
#ifndef WIN32
static void IPMainThread(void *arg)
static void IPMainThread(void *arg)
{
{
   uint32 message[4];
   uint32 message[4];
   int rc;
   int rc;
   IPFrame *frame, *frameOut=NULL;
   IPFrame *frame, *frameOut=NULL;
   uint32 ticks, ticksLast;
   uint32 ticks, ticksLast;
   (void)arg;
   (void)arg;
 
 
   ticksLast = OS_ThreadTime();
   ticksLast = OS_ThreadTime();
   memset(message, 0, sizeof(message));
   memset(message, 0, sizeof(message));
 
 
   for(;;)
   for(;;)
   {
   {
      Led(7, 0);
      Led(7, 0);
      rc = OS_MQueueGet(IPMQueue, message, 10);
      rc = OS_MQueueGet(IPMQueue, message, 10);
      if(rc == 0)
      if(rc == 0)
      {
      {
         frame = (IPFrame*)message[1];
         frame = (IPFrame*)message[1];
         if(message[0] == 0)       //frame received
         if(message[0] == 0)       //frame received
         {
         {
            Led(7, 1);
            Led(7, 1);
            frame->length = (uint16)message[2];
            frame->length = (uint16)message[2];
            rc = IPProcessEthernetPacket(frame, frame->length);
            rc = IPProcessEthernetPacket(frame, frame->length);
            if(rc == 0)
            if(rc == 0)
               FrameFree(frame);
               FrameFree(frame);
         }
         }
         else if(message[0] == 1)  //frame sent
         else if(message[0] == 1)  //frame sent
         {
         {
            Led(7, 2);
            Led(7, 2);
            assert(frame == frameOut);
            assert(frame == frameOut);
            IPFrameReschedule(frame);
            IPFrameReschedule(frame);
            frameOut = NULL;
            frameOut = NULL;
         }
         }
         else if(message[0] == 2)  //frame ready to send
         else if(message[0] == 2)  //frame ready to send
         {
         {
         }
         }
      }
      }
 
 
      if(frameOut == NULL)
      if(frameOut == NULL)
      {
      {
         OS_MutexPend(IPMutex);
         OS_MutexPend(IPMutex);
         frameOut = FrameSendTail;
         frameOut = FrameSendTail;
         if(frameOut)
         if(frameOut)
            FrameRemove(&FrameSendHead, &FrameSendTail, frameOut);
            FrameRemove(&FrameSendHead, &FrameSendTail, frameOut);
         OS_MutexPost(IPMutex);
         OS_MutexPost(IPMutex);
         if(frameOut)
         if(frameOut)
         {
         {
            Led(7, 4);
            Led(7, 4);
            UartPacketSend(frameOut->packet, frameOut->length);
            UartPacketSend(frameOut->packet, frameOut->length);
         }
         }
      }
      }
 
 
      ticks = OS_ThreadTime();
      ticks = OS_ThreadTime();
      if(ticks - ticksLast > 100)
      if(ticks - ticksLast > 100)
      {
      {
         IPTick();
         IPTick();
         ticksLast = ticks;
         ticksLast = ticks;
      }
      }
   }
   }
}
}
#endif
#endif
 
 
 
 
uint8 *MyPacketGet(void)
uint8 *MyPacketGet(void)
{
{
   return (uint8*)IPFrameGet(FRAME_COUNT_RCV);
   return (uint8*)IPFrameGet(FRAME_COUNT_RCV);
}
}
 
 
 
 
//Set FrameSendFunction only if single threaded
//Set FrameSendFunction only if single threaded
void IPInit(IPSendFuncPtr frameSendFunction, uint8 macAddress[6], char name[6])
void IPInit(IPSendFuncPtr frameSendFunction, uint8 macAddress[6], char name[6])
{
{
   int i;
   int i;
   IPFrame *frame;
   IPFrame *frame;
 
 
   if(macAddress)
   if(macAddress)
      memcpy(ethernetAddressPlasma, macAddress, 6);
      memcpy(ethernetAddressPlasma, macAddress, 6);
   if(name)
   if(name)
      memcpy(dhcpOptions+18, name, 6);
      memcpy(dhcpOptions+18, name, 6);
   FrameSendFunc = frameSendFunction;
   FrameSendFunc = frameSendFunction;
   IPMutex = OS_MutexCreate("IPSem");
   IPMutex = OS_MutexCreate("IPSem");
   IPMQueue = OS_MQueueCreate("IPMQ", FRAME_COUNT*2, 32);
   IPMQueue = OS_MQueueCreate("IPMQ", FRAME_COUNT*2, 32);
   for(i = 0; i < FRAME_COUNT; ++i)
   for(i = 0; i < FRAME_COUNT; ++i)
   {
   {
      frame = (IPFrame*)malloc(sizeof(IPFrame));
      frame = (IPFrame*)malloc(sizeof(IPFrame));
      memset(frame, 0, sizeof(IPFrame));
      memset(frame, 0, sizeof(IPFrame));
      frame->next = FrameFreeHead;
      frame->next = FrameFreeHead;
      frame->prev = NULL;
      frame->prev = NULL;
      FrameFreeHead = frame;
      FrameFreeHead = frame;
   }
   }
   FrameFreeCount = FRAME_COUNT;
   FrameFreeCount = FRAME_COUNT;
#ifndef WIN32
#ifndef WIN32
   UartPacketConfig(MyPacketGet, PACKET_SIZE, IPMQueue);
   UartPacketConfig(MyPacketGet, PACKET_SIZE, IPMQueue);
   if(frameSendFunction == NULL)
   if(frameSendFunction == NULL)
      IPThread = OS_ThreadCreate("TCP/IP", IPMainThread, NULL, 240, 6000);
      IPThread = OS_ThreadCreate("TCP/IP", IPMainThread, NULL, 240, 6000);
#endif
#endif
   IPDhcp(NULL, 360, 1);        //Send DHCP request
   IPDhcp(NULL, 360, 1);        //Send DHCP request
}
}
 
 
 
 
//To open a socket for listen set ipAddress to 0
//To open a socket for listen set ipAddress to 0
IPSocket *IPOpen(IPMode_e mode, uint32 ipAddress, uint32 port, IPSockFuncPtr funcPtr)
IPSocket *IPOpen(IPMode_e mode, uint32 ipAddress, uint32 port, IPSockFuncPtr funcPtr)
{
{
   IPSocket *socket;
   IPSocket *socket;
   uint8 *ptrSend, *ptrRcv;
   uint8 *ptrSend, *ptrRcv;
   IPFrame *frame;
   IPFrame *frame;
   static int portSource=0x1007;
   static int portSource=0x1007;
 
 
   socket = (IPSocket*)malloc(sizeof(IPSocket));
   socket = (IPSocket*)malloc(sizeof(IPSocket));
   if(socket == NULL)
   if(socket == NULL)
      return socket;
      return socket;
   memset(socket, 0, sizeof(IPSocket));
   memset(socket, 0, sizeof(IPSocket));
   socket->prev = NULL;
   socket->prev = NULL;
   socket->state = IP_LISTEN;
   socket->state = IP_LISTEN;
   socket->timeout = 0;
   socket->timeout = 0;
   socket->timeoutReset = SOCKET_TIMEOUT;
   socket->timeoutReset = SOCKET_TIMEOUT;
   socket->frameReadHead = NULL;
   socket->frameReadHead = NULL;
   socket->frameReadTail = NULL;
   socket->frameReadTail = NULL;
 
   socket->frameFutureHead = NULL;
 
   socket->frameFutureTail = NULL;
   socket->readOffset = 0;
   socket->readOffset = 0;
   socket->funcPtr = funcPtr;
   socket->funcPtr = funcPtr;
   socket->userData = 0;
   socket->userData = 0;
   socket->userFunc = NULL;
   socket->userFunc = NULL;
   socket->userPtr = NULL;
   socket->userPtr = NULL;
   socket->seqWindow = 2048;
   socket->seqWindow = 2048;
   ptrSend = socket->headerSend;
   ptrSend = socket->headerSend;
   ptrRcv = socket->headerRcv;
   ptrRcv = socket->headerRcv;
 
 
   if(ipAddress == 0)
   if(ipAddress == 0)
   {
   {
      //Setup listing port
      //Setup listing port
      socket->headerRcv[TCP_DEST_PORT] = (uint8)(port >> 8);
      socket->headerRcv[TCP_DEST_PORT] = (uint8)(port >> 8);
      socket->headerRcv[TCP_DEST_PORT+1] = (uint8)port;
      socket->headerRcv[TCP_DEST_PORT+1] = (uint8)port;
   }
   }
   else
   else
   {
   {
      //Setup sending packet
      //Setup sending packet
      memset(ptrSend, 0, UDP_LENGTH);
      memset(ptrSend, 0, UDP_LENGTH);
      memset(ptrRcv, 0, UDP_LENGTH);
      memset(ptrRcv, 0, UDP_LENGTH);
 
 
      //Setup Ethernet
      //Setup Ethernet
      if(ipAddress != IPAddressSelf())
      if(ipAddress != IPAddressSelf())
         memcpy(ptrSend+ETHERNET_DEST, ethernetAddressGateway, 6);
         memcpy(ptrSend+ETHERNET_DEST, ethernetAddressGateway, 6);
      else
      else
         memcpy(ptrSend+ETHERNET_DEST, ethernetAddressPlasma, 6);
         memcpy(ptrSend+ETHERNET_DEST, ethernetAddressPlasma, 6);
      memcpy(ptrSend+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
      memcpy(ptrSend+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
      ptrSend[ETHERNET_FRAME_TYPE] = 0x08;
      ptrSend[ETHERNET_FRAME_TYPE] = 0x08;
 
 
      //Setup IP
      //Setup IP
      ptrSend[IP_VERSION_LENGTH] = 0x45;
      ptrSend[IP_VERSION_LENGTH] = 0x45;
      ptrSend[IP_TIME_TO_LIVE] = 0x80;
      ptrSend[IP_TIME_TO_LIVE] = 0x80;
 
 
      //Setup IP addresses
      //Setup IP addresses
      memcpy(ptrSend+IP_SOURCE, ipAddressPlasma, 4);
      memcpy(ptrSend+IP_SOURCE, ipAddressPlasma, 4);
      ptrSend[IP_DEST] = (uint8)(ipAddress >> 24);
      ptrSend[IP_DEST] = (uint8)(ipAddress >> 24);
      ptrSend[IP_DEST+1] = (uint8)(ipAddress >> 16);
      ptrSend[IP_DEST+1] = (uint8)(ipAddress >> 16);
      ptrSend[IP_DEST+2] = (uint8)(ipAddress >> 8);
      ptrSend[IP_DEST+2] = (uint8)(ipAddress >> 8);
      ptrSend[IP_DEST+3] = (uint8)ipAddress;
      ptrSend[IP_DEST+3] = (uint8)ipAddress;
      ptrRcv[IP_SOURCE] = (uint8)(ipAddress >> 24);
      ptrRcv[IP_SOURCE] = (uint8)(ipAddress >> 24);
      ptrRcv[IP_SOURCE+1] = (uint8)(ipAddress >> 16);
      ptrRcv[IP_SOURCE+1] = (uint8)(ipAddress >> 16);
      ptrRcv[IP_SOURCE+2] = (uint8)(ipAddress >> 8);
      ptrRcv[IP_SOURCE+2] = (uint8)(ipAddress >> 8);
      ptrRcv[IP_SOURCE+3] = (uint8)ipAddress;
      ptrRcv[IP_SOURCE+3] = (uint8)ipAddress;
      memcpy(ptrRcv+IP_DEST, ipAddressPlasma, 4);
      memcpy(ptrRcv+IP_DEST, ipAddressPlasma, 4);
 
 
      //Setup ports
      //Setup ports
      ptrSend[TCP_SOURCE_PORT] = (uint8)(portSource >> 8);
      ptrSend[TCP_SOURCE_PORT] = (uint8)(portSource >> 8);
      ptrSend[TCP_SOURCE_PORT+1] = (uint8)portSource;
      ptrSend[TCP_SOURCE_PORT+1] = (uint8)portSource;
      ptrSend[TCP_DEST_PORT] = (uint8)(port >> 8);
      ptrSend[TCP_DEST_PORT] = (uint8)(port >> 8);
      ptrSend[TCP_DEST_PORT+1] = (uint8)port;
      ptrSend[TCP_DEST_PORT+1] = (uint8)port;
      ptrRcv[TCP_SOURCE_PORT] = (uint8)(port >> 8);
      ptrRcv[TCP_SOURCE_PORT] = (uint8)(port >> 8);
      ptrRcv[TCP_SOURCE_PORT+1] = (uint8)port;
      ptrRcv[TCP_SOURCE_PORT+1] = (uint8)port;
      ptrRcv[TCP_DEST_PORT] = (uint8)(portSource >> 8);
      ptrRcv[TCP_DEST_PORT] = (uint8)(portSource >> 8);
      ptrRcv[TCP_DEST_PORT+1] = (uint8)portSource;
      ptrRcv[TCP_DEST_PORT+1] = (uint8)portSource;
      ++portSource;
      ++portSource;
   }
   }
 
 
   if(mode == IP_MODE_TCP)
   if(mode == IP_MODE_TCP)
   {
   {
      if(ipAddress)
      if(ipAddress)
         socket->state = IP_TCP;
         socket->state = IP_TCP;
      else
      else
         socket->state = IP_LISTEN;
         socket->state = IP_LISTEN;
      ptrSend[IP_PROTOCOL] = 0x06;  //TCP
      ptrSend[IP_PROTOCOL] = 0x06;  //TCP
      ptrRcv[IP_PROTOCOL] = 0x06;
      ptrRcv[IP_PROTOCOL] = 0x06;
   }
   }
   else if(mode == IP_MODE_UDP)
   else if(mode == IP_MODE_UDP)
   {
   {
      socket->state = IP_UDP;
      socket->state = IP_UDP;
      ptrSend[IP_PROTOCOL] = 0x11;  //UDP
      ptrSend[IP_PROTOCOL] = 0x11;  //UDP
      ptrRcv[IP_PROTOCOL] = 0x11;
      ptrRcv[IP_PROTOCOL] = 0x11;
   }
   }
   else if(mode == IP_MODE_PING)
   else if(mode == IP_MODE_PING)
   {
   {
      socket->state = IP_PING;
      socket->state = IP_PING;
      ptrSend[IP_PROTOCOL] = 0x01;  //PING
      ptrSend[IP_PROTOCOL] = 0x01;  //PING
      memset(ptrSend+PING_TYPE, 0, 8);
      memset(ptrSend+PING_TYPE, 0, 8);
      ptrSend[PING_TYPE] = 8;       //SEND
      ptrSend[PING_TYPE] = 8;       //SEND
   }
   }
 
 
   //Add socket to linked list
   //Add socket to linked list
   OS_MutexPend(IPMutex);
   OS_MutexPend(IPMutex);
   socket->next = SocketHead;
   socket->next = SocketHead;
   socket->prev = NULL;
   socket->prev = NULL;
   if(SocketHead)
   if(SocketHead)
      SocketHead->prev = socket;
      SocketHead->prev = socket;
   SocketHead = socket;
   SocketHead = socket;
   OS_MutexPost(IPMutex);
   OS_MutexPost(IPMutex);
 
 
   if(mode == IP_MODE_TCP && ipAddress)
   if(mode == IP_MODE_TCP && ipAddress)
   {
   {
      //Send TCP SYN
      //Send TCP SYN
      socket->seq = 0x01234567;
      socket->seq = 0x01234567;
      frame = IPFrameGet(0);
      frame = IPFrameGet(0);
      if(frame)
      if(frame)
      {
      {
         frame->packet[TCP_FLAGS] = TCP_FLAGS_SYN;
         frame->packet[TCP_FLAGS] = TCP_FLAGS_SYN;
         frame->packet[TCP_DATA] = 2;    //maximum segment size = 536
         frame->packet[TCP_DATA] = 2;    //maximum segment size = 536
         frame->packet[TCP_DATA+1] = 4;
         frame->packet[TCP_DATA+1] = 4;
         frame->packet[TCP_DATA+2] = 2;
         frame->packet[TCP_DATA+2] = 2;
         frame->packet[TCP_DATA+3] = 24;
         frame->packet[TCP_DATA+3] = 24;
         TCPSendPacket(socket, frame, TCP_DATA+4);
         TCPSendPacket(socket, frame, TCP_DATA+4);
         ++socket->seq;
         ++socket->seq;
      }
      }
   }
   }
   return socket;
   return socket;
}
}
 
 
 
 
void IPWriteFlush(IPSocket *socket)
void IPWriteFlush(IPSocket *socket)
{
{
   uint8 *packetOut;
   uint8 *packetOut;
 
 
   if(socket == NULL)
   if(socket == NULL)
      socket = (IPSocket*)OS_ThreadInfoGet(OS_ThreadSelf(), 0);
      socket = (IPSocket*)OS_ThreadInfoGet(OS_ThreadSelf(), 0);
   if(socket->frameSend && socket->state != IP_UDP &&
   if(socket->frameSend && socket->state != IP_UDP &&
      socket->state != IP_PING)
      socket->state != IP_PING)
   {
   {
      packetOut = socket->frameSend->packet;
      packetOut = socket->frameSend->packet;
      packetOut[TCP_FLAGS] = TCP_FLAGS_ACK | TCP_FLAGS_PSH;
      packetOut[TCP_FLAGS] = TCP_FLAGS_ACK | TCP_FLAGS_PSH;
      TCPSendPacket(socket, socket->frameSend, TCP_DATA + socket->sendOffset);
      TCPSendPacket(socket, socket->frameSend, TCP_DATA + socket->sendOffset);
      socket->seq += socket->sendOffset;
      socket->seq += socket->sendOffset;
      socket->frameSend = NULL;
      socket->frameSend = NULL;
      socket->sendOffset = 0;
      socket->sendOffset = 0;
   }
   }
}
}
 
 
 
 
uint32 IPWrite(IPSocket *socket, const uint8 *buf, uint32 length)
uint32 IPWrite(IPSocket *socket, const uint8 *buf, uint32 length)
{
{
   IPFrame *frameOut;
   IPFrame *frameOut;
   uint8 *packetOut;
   uint8 *packetOut;
   uint32 bytes, count=0, tries=0;
   uint32 bytes, count=0, tries=0;
   int offset;
   int offset;
   OS_Thread_t *self;
   OS_Thread_t *self;
 
 
   if(socket == NULL)
   if(socket == NULL)
      socket = (IPSocket*)OS_ThreadInfoGet(OS_ThreadSelf(), 0);
      socket = (IPSocket*)OS_ThreadInfoGet(OS_ThreadSelf(), 0);
 
 
   if(socket->state > IP_TCP)
   if(socket->state > IP_TCP)
      return 0;
      return 0;
 
 
   if(socket->timeout)
   if(socket->timeout)
      socket->timeout = socket->timeoutReset;
      socket->timeout = socket->timeoutReset;
 
 
#ifndef EXCLUDE_FILESYS
#ifndef EXCLUDE_FILESYS
   if(socket->fileOut)   //override stdout
   if(socket->fileOut)   //override stdout
      return fwrite((char*)buf, 1, length, socket->fileOut);
      return fwrite((char*)buf, 1, length, (FILE*)socket->fileOut);
#endif
#endif
 
 
   //printf("IPWrite(0x%x, %d)", Socket, Length);
   //printf("IPWrite(0x%x, %d)", Socket, Length);
   self = OS_ThreadSelf();
   self = OS_ThreadSelf();
   while(length)
   while(length)
   {
   {
      //Rate limit output
      //Rate limit output
      if(socket->seq - socket->seqReceived >= SEND_WINDOW)
      if(socket->seq - socket->seqReceived >= SEND_WINDOW)
      {
      {
         //printf("l(%d,%d,%d) ", socket->seq - socket->seqReceived, socket->seq, socket->seqReceived);
         //printf("l(%d,%d,%d) ", socket->seq - socket->seqReceived, socket->seq, socket->seqReceived);
         if(self != IPThread && ++tries < 200)
         if(self != IPThread && ++tries < 200)
         {
         {
            OS_ThreadSleep(1);
            OS_ThreadSleep(1);
            continue;
            continue;
         }
         }
      }
      }
      tries = 0;
      tries = 0;
      while(socket->frameSend == NULL)
      while(socket->frameSend == NULL)
      {
      {
         socket->frameSend = IPFrameGet(FRAME_COUNT_SEND);
         socket->frameSend = IPFrameGet(FRAME_COUNT_SEND);
         socket->sendOffset = 0;
         socket->sendOffset = 0;
         if(socket->frameSend == NULL)
         if(socket->frameSend == NULL)
         {
         {
            //printf("L");
            //printf("L");
            if(self == IPThread || ++tries > 200)
            if(self == IPThread || ++tries > 200)
               break;
               break;
            else
            else
               OS_ThreadSleep(1);
               OS_ThreadSleep(1);
         }
         }
      }
      }
      frameOut = socket->frameSend;
      frameOut = socket->frameSend;
      offset = socket->sendOffset;
      offset = socket->sendOffset;
      if(frameOut == NULL)
      if(frameOut == NULL)
         break;
         break;
      packetOut = frameOut->packet;
      packetOut = frameOut->packet;
 
 
      if(socket->state == IP_PING)
      if(socket->state == IP_PING)
      {
      {
         bytes = length;
         bytes = length;
         memcpy(packetOut, socket->headerSend, PING_DATA);
         memcpy(packetOut, socket->headerSend, PING_DATA);
         memcpy(packetOut+PING_DATA, buf, bytes);
         memcpy(packetOut+PING_DATA, buf, bytes);
         IPSendPacket(socket, socket->frameSend, PING_DATA + bytes);
         IPSendPacket(socket, socket->frameSend, PING_DATA + bytes);
         socket->frameSend = NULL;
         socket->frameSend = NULL;
      }
      }
      else if(socket->state != IP_UDP)
      else if(socket->state != IP_UDP)
      {
      {
         bytes = 512 - offset;
         bytes = 512 - offset;
         if(bytes > length)
         if(bytes > length)
            bytes = length;
            bytes = length;
         socket->sendOffset += bytes;
         socket->sendOffset += bytes;
         memcpy(packetOut+TCP_DATA+offset, buf, bytes);
         memcpy(packetOut+TCP_DATA+offset, buf, bytes);
         if(socket->sendOffset >= 512)
         if(socket->sendOffset >= 512)
            IPWriteFlush(socket);
            IPWriteFlush(socket);
         //if(Socket->seq - Socket->seqReceived > Socket->seqWindow)
         //if(Socket->seq - Socket->seqReceived > Socket->seqWindow)
         //{
         //{
         //   printf("W");
         //   printf("W");
         //   OS_ThreadSleep(10);
         //   OS_ThreadSleep(10);
         //}
         //}
      }
      }
      else  //UDP
      else  //UDP
      {
      {
         bytes = length;
         bytes = length;
         memcpy(packetOut+UDP_DATA+offset, buf, bytes);
         memcpy(packetOut+UDP_DATA+offset, buf, bytes);
         memcpy(packetOut, socket->headerSend, UDP_LENGTH);
         memcpy(packetOut, socket->headerSend, UDP_LENGTH);
         IPSendPacket(socket, socket->frameSend, UDP_DATA + bytes);
         IPSendPacket(socket, socket->frameSend, UDP_DATA + bytes);
         socket->frameSend = NULL;
         socket->frameSend = NULL;
      }
      }
      count += bytes;
      count += bytes;
      buf += bytes;
      buf += bytes;
      length -= bytes;
      length -= bytes;
   }
   }
   return count;
   return count;
}
}
 
 
 
 
uint32 IPRead(IPSocket *socket, uint8 *buf, uint32 length)
uint32 IPRead(IPSocket *socket, uint8 *buf, uint32 length)
{
{
   IPFrame *frame, *frame2;
   IPFrame *frame, *frame2;
   int count=0, bytes, offset;
   int count=0, bytes, offset;
 
 
   if(socket == NULL)
   if(socket == NULL)
      socket = (IPSocket*)OS_ThreadInfoGet(OS_ThreadSelf(), 0);
      socket = (IPSocket*)OS_ThreadInfoGet(OS_ThreadSelf(), 0);
 
 
#ifndef EXCLUDE_FILESYS
#ifndef EXCLUDE_FILESYS
   if(socket->fileIn)   //override stdin
   if(socket->fileIn)   //override stdin
   {
   {
      bytes = fread(buf, 1, 1, socket->fileIn);
      bytes = fread(buf, 1, 1, (FILE*)socket->fileIn);
      if(bytes == 0)
      if(bytes == 0)
      {
      {
         buf[0] = 0;
         buf[0] = 0;
         fclose(socket->fileIn);
         fclose((FILE*)socket->fileIn);
         socket->fileIn = NULL;
         socket->fileIn = NULL;
         bytes = 1;
         bytes = 1;
      }
      }
      return bytes;
      return bytes;
   }
   }
#endif
#endif
 
 
   if(socket->state == IP_UDP)
   if(socket->state == IP_UDP)
      offset = UDP_DATA;
      offset = UDP_DATA;
   else
   else
      offset = TCP_DATA;
      offset = TCP_DATA;
 
 
   OS_MutexPend(IPMutex);
   OS_MutexPend(IPMutex);
   for(frame = socket->frameReadTail; length && frame; )
   for(frame = socket->frameReadTail; length && frame; )
   {
   {
      bytes = frame->length - offset - socket->readOffset;
      bytes = frame->length - offset - socket->readOffset;
      if(bytes > (int)length)
      if(bytes > (int)length)
         bytes = length;
         bytes = length;
      memcpy(buf, frame->packet + offset + socket->readOffset, bytes);
      memcpy(buf, frame->packet + offset + socket->readOffset, bytes);
      buf += bytes;
      buf += bytes;
      socket->readOffset += bytes;
      socket->readOffset += bytes;
      length -= bytes;
      length -= bytes;
      count += bytes;
      count += bytes;
 
 
      //Check if done with packet
      //Check if done with packet
      frame2 = frame;
      frame2 = frame;
      frame = frame->prev;
      frame = frame->prev;
      if(socket->readOffset == frame2->length - offset)
      if(socket->readOffset == frame2->length - offset)
      {
      {
         //Remove packet from socket linked list
         //Remove packet from socket linked list
         socket->readOffset = 0;
         socket->readOffset = 0;
         FrameRemove(&socket->frameReadHead, &socket->frameReadTail, frame2);
         FrameRemove(&socket->frameReadHead, &socket->frameReadTail, frame2);
         socket->ackProcessed += frame2->length - offset;
         socket->ackProcessed += frame2->length - offset;
         if(socket->state == IP_TCP &&
         if(socket->state == IP_TCP &&
            socket->ack - socket->ackProcessed > RECEIVE_WINDOW - 2048)
            socket->ack - socket->ackProcessed > RECEIVE_WINDOW - 2048)
         {
         {
            //Update receive window for flow control
            //Update receive window for flow control
            frame2->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
            frame2->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
            TCPSendPacket(socket, frame2, TCP_DATA);
            TCPSendPacket(socket, frame2, TCP_DATA);
         }
         }
         else
         else
            FrameFree(frame2);
            FrameFree(frame2);
      }
      }
   }
   }
   OS_MutexPost(IPMutex);
   OS_MutexPost(IPMutex);
   return count;
   return count;
}
}
 
 
 
 
static void IPClose2(IPSocket *socket)
static void IPClose2(IPSocket *socket)
{
{
   IPFrame *frame, *framePrev;
   IPFrame *frame, *framePrev;
 
 
   //printf("IPClose2(%x) ", (int)socket);
   //printf("IPClose2(%x) ", (int)socket);
 
 
   OS_MutexPend(IPMutex);
   OS_MutexPend(IPMutex);
 
 
   //Remove pending packets
   //Remove pending packets
   for(frame = FrameSendHead; frame; )
   for(frame = FrameSendHead; frame; )
   {
   {
      framePrev = frame;
      framePrev = frame;
      frame = frame->next;
      frame = frame->next;
      if(framePrev->socket == socket)
      if(framePrev->socket == socket)
      {
      {
         FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);
         FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);
         FrameFree(framePrev);
         FrameFree(framePrev);
      }
      }
   }
   }
 
 
   //Remove packets from retransmision list
   //Remove packets from retransmision list
   for(frame = FrameResendHead; frame; )
   for(frame = FrameResendHead; frame; )
   {
   {
      framePrev = frame;
      framePrev = frame;
      frame = frame->next;
      frame = frame->next;
      if(framePrev->socket == socket)
      if(framePrev->socket == socket)
      {
      {
         FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);
         FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);
         FrameFree(framePrev);
         FrameFree(framePrev);
      }
      }
   }
   }
 
 
   //Remove packets from socket read linked list
   //Remove packets from socket read linked list
   for(frame = socket->frameReadHead; frame; )
   for(frame = socket->frameReadHead; frame; )
   {
   {
      framePrev = frame;
      framePrev = frame;
      frame = frame->next;
      frame = frame->next;
      FrameRemove(&socket->frameReadHead, &socket->frameReadTail, framePrev);
      FrameRemove(&socket->frameReadHead, &socket->frameReadTail, framePrev);
      FrameFree(framePrev);
      FrameFree(framePrev);
   }
   }
 
 
 
   //Remove packets from socket future linked list
 
   for(frame = socket->frameFutureHead; frame; )
 
   {
 
      framePrev = frame;
 
      frame = frame->next;
 
      FrameRemove(&socket->frameFutureHead, &socket->frameFutureTail, framePrev);
 
      FrameFree(framePrev);
 
   }
 
 
   //Give application time to stop using socket
   //Give application time to stop using socket
   socket->timeout = SOCKET_TIMEOUT;
   socket->timeout = SOCKET_TIMEOUT;
   socket->state = IP_CLOSED;
   socket->state = IP_CLOSED;
 
 
   OS_MutexPost(IPMutex);
   OS_MutexPost(IPMutex);
}
}
 
 
 
 
void IPClose(IPSocket *socket)
void IPClose(IPSocket *socket)
{
{
   IPFrame *frameOut;
   IPFrame *frameOut;
 
 
   //printf("IPClose(%x) ", (int)socket);
   //printf("IPClose(%x) ", (int)socket);
 
 
   IPWriteFlush(socket);
   IPWriteFlush(socket);
   if(socket->state <= IP_UDP)
   if(socket->state <= IP_UDP)
   {
   {
      IPClose2(socket);
      IPClose2(socket);
      return;
      return;
   }
   }
   frameOut = IPFrameGet(0);
   frameOut = IPFrameGet(0);
   if(frameOut == NULL)
   if(frameOut == NULL)
      return;
      return;
   frameOut->packet[TCP_FLAGS] = TCP_FLAGS_FIN | TCP_FLAGS_ACK;
   frameOut->packet[TCP_FLAGS] = TCP_FLAGS_FIN | TCP_FLAGS_ACK;
   TCPSendPacket(socket, frameOut, TCP_DATA);
   TCPSendPacket(socket, frameOut, TCP_DATA);
   ++socket->seq;
   ++socket->seq;
   socket->timeout = SOCKET_TIMEOUT;
   socket->timeout = SOCKET_TIMEOUT;
   socket->timeoutReset = SOCKET_TIMEOUT;
   socket->timeoutReset = SOCKET_TIMEOUT;
   socket->state = IP_FIN_SERVER;
   socket->state = IP_FIN_SERVER;
}
}
 
 
 
 
int IPPrintf(IPSocket *socket, char *format,
int IPPrintf(IPSocket *socket, char *format,
              int arg0, int arg1, int arg2, int arg3,
              int arg0, int arg1, int arg2, int arg3,
              int arg4, int arg5, int arg6, int arg7)
              int arg4, int arg5, int arg6, int arg7)
{
{
   char buffer[256], *ptr = buffer;
   char buffer[256], *ptr = buffer;
   int rc = 1;
   int rc = 1;
   int length;
   int length;
 
 
   if(socket == NULL)
   if(socket == NULL)
      socket = (IPSocket*)OS_ThreadInfoGet(OS_ThreadSelf(), 0);
      socket = (IPSocket*)OS_ThreadInfoGet(OS_ThreadSelf(), 0);
   if(strcmp(format, "%s") == 0)
   if(strcmp(format, "%s") == 0)
      ptr = (char*)arg0;
      ptr = (char*)arg0;
   else
   else
      rc = sprintf(buffer, format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
      rc = sprintf(buffer, format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
   length = strlen(ptr);
   length = strlen(ptr);
   IPWrite(socket, (unsigned char*)ptr, length);
   IPWrite(socket, (unsigned char*)ptr, length);
   if(socket->dontFlush == 0 || strstr(format, "\n"))
   if(socket->dontFlush == 0 || strstr(format, "\n"))
      IPWriteFlush(socket);
      IPWriteFlush(socket);
   return rc;
   return rc;
}
}
 
 
 
 
 
 
void IPTick(void)
void IPTick(void)
{
{
   IPFrame *frame, *frame2;
   IPFrame *frame, *frame2;
   IPSocket *socket, *socket2;
   IPSocket *socket, *socket2;
   unsigned long ticks;
   unsigned long ticks;
   static unsigned long ticksPrev=0, ticksPrev2=0;
   static unsigned long ticksPrev=0, ticksPrev2=0;
 
 
   ticks = OS_ThreadTime();
   ticks = OS_ThreadTime();
#ifdef WIN32
#ifdef WIN32
   ticks = ticksPrev + 100;
   ticks = ticksPrev + 100;
#endif
#endif
   if(ticks - ticksPrev >= 95)
   if(ticks - ticksPrev >= 95)
   {
   {
      if(IPVerbose && (Seconds % 60) == 0)
      if(IPVerbose && (Seconds % 60) == 0)
      {
      {
         if(FrameFreeCount >= FRAME_COUNT-1)
         if(FrameFreeCount >= FRAME_COUNT-1)
            printf("T");
            printf("T");
         else
         else
            printf("T(%d)", FrameFreeCount);
            printf("T(%d)", FrameFreeCount);
      }
      }
      ++Seconds;
      ++Seconds;
      if(--DhcpRetrySeconds <= 0)
      if(--DhcpRetrySeconds <= 0)
         IPDhcp(NULL, 400, 1);   //DHCP request
         IPDhcp(NULL, 400, 1);   //DHCP request
   }
   }
 
 
   OS_MutexPend(IPMutex);
   OS_MutexPend(IPMutex);
 
 
   //Retransmit timeout packets
   //Retransmit timeout packets
   for(frame = FrameResendHead; frame; )
   for(frame = FrameResendHead; frame; )
   {
   {
      frame2 = frame;
      frame2 = frame;
      frame = frame->next;
      frame = frame->next;
      frame2->timeout = (short)(frame2->timeout - (ticks - ticksPrev2));
      frame2->timeout = (short)(frame2->timeout - (ticks - ticksPrev2));
      if(--frame2->timeout <= 0)
      if(--frame2->timeout <= 0)
      {
      {
         if(IPVerbose)
         if(IPVerbose)
            printf("r" /*"(%x,%x,%d,%d,%d)"*/, (int)frame2, (int)frame2->socket,
            printf("r" /*"(%x,%x,%d,%d,%d)"*/, (int)frame2, (int)frame2->socket,
               frame2->retryCnt, frame2->length - TCP_DATA,
               frame2->retryCnt, frame2->length - TCP_DATA,
               frame2->socket->state);
               frame2->socket->state);
         FrameRemove(&FrameResendHead, &FrameResendTail, frame2);
         FrameRemove(&FrameResendHead, &FrameResendTail, frame2);
         if(frame2->retryCnt < 4 && frame2->socket->state < IP_CLOSED)
         if(frame2->retryCnt < 4 && frame2->socket->state < IP_CLOSED)
            IPSendFrame(frame2);
            IPSendFrame(frame2);
         else
         else
         {
         {
            if(frame2->socket->state == IP_TCP)
            if(frame2->socket->state == IP_TCP)
               IPClose(frame2->socket);
               IPClose(frame2->socket);
            FrameFree(frame2);
            FrameFree(frame2);
         }
         }
      }
      }
   }
   }
 
 
   if(ticks - ticksPrev >= 95)
   if(ticks - ticksPrev >= 95)
   {
   {
      //Close timed out sockets
      //Close timed out sockets
      for(socket = SocketHead; socket; )
      for(socket = SocketHead; socket; )
      {
      {
         socket2 = socket;
         socket2 = socket;
         socket = socket->next;
         socket = socket->next;
         if(socket2->timeout && --socket2->timeout == 0)
         if(socket2->timeout && --socket2->timeout == 0)
         {
         {
            socket2->timeout = SOCKET_TIMEOUT;
            socket2->timeout = SOCKET_TIMEOUT;
            if(socket2->state <= IP_TCP || socket2->state == IP_FIN_CLIENT)
            if(socket2->state <= IP_TCP || socket2->state == IP_FIN_CLIENT)
               IPClose(socket2);
               IPClose(socket2);
            else if(socket2->state != IP_CLOSED)
            else if(socket2->state != IP_CLOSED)
               IPClose2(socket2);
               IPClose2(socket2);
            else
            else
            {
            {
               if(socket2->prev == NULL)
               if(socket2->prev == NULL)
                  SocketHead = socket2->next;
                  SocketHead = socket2->next;
               else
               else
                  socket2->prev->next = socket2->next;
                  socket2->prev->next = socket2->next;
               if(socket2->next)
               if(socket2->next)
                  socket2->next->prev = socket2->prev;
                  socket2->next->prev = socket2->prev;
               //printf("freeSocket(%x) ", (int)socket2);
               //printf("freeSocket(%x) ", (int)socket2);
               free(socket2);
               free(socket2);
            }
            }
         }
         }
      }
      }
      ticksPrev = ticks;
      ticksPrev = ticks;
   }
   }
   OS_MutexPost(IPMutex);
   OS_MutexPost(IPMutex);
   ticksPrev2 = ticks;
   ticksPrev2 = ticks;
}
}
 
 
 
 
static void DnsCallback(IPSocket *socket)
static void DnsCallback(IPSocket *socket)
{
{
   uint8 buf[200], *ptr;
   uint8 buf[200], *ptr;
   uint32 ipAddress;
   uint32 ipAddress;
   int bytes;
   int bytes;
 
 
   memset(buf, 0, sizeof(buf));
   memset(buf, 0, sizeof(buf));
   bytes = IPRead(socket, buf, sizeof(buf));
   bytes = IPRead(socket, buf, sizeof(buf));
   if(buf[DNS_NUM_ANSWERS_RR+1])
   if(buf[DNS_NUM_ANSWERS_RR+1])
   {
   {
      for(ptr = buf + DNS_QUESTIONS; ptr + 14 <= buf + bytes; ++ptr)
      for(ptr = buf + DNS_QUESTIONS; ptr + 14 <= buf + bytes; ++ptr)
      {
      {
         if(ptr[0] == 0 && ptr[1] == 1 && ptr[2] == 0 && ptr[3] == 1 &&
         if(ptr[0] == 0 && ptr[1] == 1 && ptr[2] == 0 && ptr[3] == 1 &&
            ptr[8] == 0 && ptr[9] == 4)
            ptr[8] == 0 && ptr[9] == 4)
         {
         {
            ipAddress = (ptr[10] << 24) | (ptr[11] << 16) | (ptr[12] << 8) | ptr[13];
            ipAddress = (ptr[10] << 24) | (ptr[11] << 16) | (ptr[12] << 8) | ptr[13];
            printf("ipAddress = %d.%d.%d.%d\n", ptr[10], ptr[11], ptr[12], ptr[13]);
            printf("ipAddress = %d.%d.%d.%d\n", ptr[10], ptr[11], ptr[12], ptr[13]);
            socket->userData = ipAddress;
            socket->userData = ipAddress;
            if(socket->userFunc)
            if(socket->userFunc)
            {
            {
               socket->userFunc(socket, socket->userPtr, ipAddress);
               socket->userFunc(socket, (uint8*)socket->userPtr, ipAddress);
            }
            }
            break;
            break;
         }
         }
      }
      }
   }
   }
   IPClose(socket);
   IPClose(socket);
}
}
 
 
 
 
void IPResolve(char *name, IPCallbackPtr resolvedFunc, void *arg)
void IPResolve(char *name, IPCallbackPtr resolvedFunc, void *arg)
{
{
   uint8 buf[200], *ptr;
   uint8 buf[200], *ptr;
   int length, i;
   int length, i;
   IPSocket *socket;
   IPSocket *socket;
 
 
   socket = IPOpen(IP_MODE_UDP, ipAddressDns, DNS_PORT, DnsCallback);
   socket = IPOpen(IP_MODE_UDP, ipAddressDns, DNS_PORT, DnsCallback);
   memset(buf, 0, sizeof(buf));
   memset(buf, 0, sizeof(buf));
   buf[DNS_ID+1] = 1;
   buf[DNS_ID+1] = 1;
   buf[DNS_FLAGS] = 1;
   buf[DNS_FLAGS] = 1;
   buf[DNS_NUM_QUESTIONS+1] = 1;
   buf[DNS_NUM_QUESTIONS+1] = 1;
 
 
   //Setup name
   //Setup name
   ptr = buf + DNS_QUESTIONS;
   ptr = buf + DNS_QUESTIONS;
   strncpy((char*)ptr+1, name, 100);
   strncpy((char*)ptr+1, name, 100);
   ptr[0] = 1;
   ptr[0] = 1;
   while(ptr[0])
   while(ptr[0])
   {
   {
      for(i = 0; i < 100; ++i)
      for(i = 0; i < 100; ++i)
      {
      {
         if(ptr[i+1] == '.' || ptr[i+1] == 0)
         if(ptr[i+1] == '.' || ptr[i+1] == 0)
         {
         {
            ptr[0] = (uint8)i;
            ptr[0] = (uint8)i;
            ptr += i+1;
            ptr += i+1;
            break;
            break;
         }
         }
      }
      }
   }
   }
   ++ptr;
   ++ptr;
   ptr[1] = DNS_QUERY_TYPE_IP;
   ptr[1] = DNS_QUERY_TYPE_IP;
   ptr[3] = DNS_QUERY_CLASS;
   ptr[3] = DNS_QUERY_CLASS;
   length = (int)(ptr - buf) + 4;
   length = (int)(ptr - buf) + 4;
   if(length < 60)
   if(length < 60)
      length = 60;
      length = 60;
 
 
   socket->userFunc = resolvedFunc;
   socket->userFunc = resolvedFunc;
   socket->userPtr = arg;
   socket->userPtr = arg;
   socket->userData = 0;
   socket->userData = 0;
   IPWrite(socket, buf, length);
   IPWrite(socket, buf, length);
}
}
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.