Root/plasma/kernel/tcpip.c

1/*--------------------------------------------------------------------
2 * TITLE: Plasma TCP/IP Protocol Stack
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 4/22/06
5 * FILENAME: tcpip.c
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Plasma TCP/IP Protocol Stack
11 *
12 * Possible call stack when receiving a packet:
13 * IPMainThread()
14 * IPProcessEthernetPacket()
15 * IPProcessTCPPacket()
16 * TCPSendPacket()
17 * IPSendPacket()
18 * IPChecksum()
19 * IPSendFrame()
20 * FrameInsert()
21 *--------------------------------------------------------------------*/
22#ifdef WIN32
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <assert.h>
27#define _LIBC
28#endif
29#include "rtos.h"
30#define IPPRINTF
31#include "tcpip.h"
32
33
34//ETHER FIELD OFFSET LENGTH VALUE
35#define ETHERNET_DEST 0 //6
36#define ETHERNET_SOURCE 6 //6
37#define ETHERNET_FRAME_TYPE 12 //2 IP=0x0800; ARP=0x0806
38
39//ARP FIELD OFFSET LENGTH VALUE
40#define ARP_HARD_TYPE 14 //2 0x0001
41#define ARP_PROT_TYPE 16 //2 0x0800
42#define ARP_HARD_SIZE 18 //1 0x06
43#define ARP_PROT_SIZE 19 //1 0x04
44#define ARP_OP 20 //2 ARP=1;ARPreply=2
45#define ARP_ETHERNET_SENDER 22 //6
46#define ARP_IP_SENDER 28 //4
47#define ARP_ETHERNET_TARGET 32 //6
48#define ARP_IP_TARGET 38 //4
49#define ARP_PAD 42 //18 0
50
51//IP FIELD OFFSET LENGTH VALUE
52#define IP_VERSION_LENGTH 14 //1 0x45
53#define IP_TYPE_OF_SERVICE 15 //1 0x00
54#define IP_LENGTH 16 //2
55#define IP_ID16 18 //2
56#define IP_FRAG_OFFSET 20 //2
57#define IP_TIME_TO_LIVE 22 //1 0x80
58#define IP_PROTOCOL 23 //1 TCP=0x06;PING=0x01;UDP=0x11
59#define IP_CHECKSUM 24 //2
60#define IP_SOURCE 26 //4
61#define IP_DEST 30 //4
62
63//PSEUDO FIELD OFFSET LENGTH VALUE
64#define PSEUDO_IP_SOURCE 0 //4
65#define PSEUDO_IP_DEST 4 //4
66#define PSEUDO_ZERO 8 //1 0
67#define PSEUDO_IP_PROTOCOL 9 //1
68#define PSEUDO_LENGTH 10 //2
69
70//UDP FIELD OFFSET LENGTH VALUE
71#define UDP_SOURCE_PORT 34 //2
72#define UDP_DEST_PORT 36 //2
73#define UDP_LENGTH 38 //2
74#define UDP_CHECKSUM 40 //2
75#define UDP_DATA 42
76
77//DHCP FIELD OFFSET LENGTH VALUE
78#define DHCP_OPCODE 42 //1 REQUEST=1;REPLY=2
79#define DHCP_HW_TYPE 43 //1 1
80#define DHCP_HW_LEN 44 //1 6
81#define DHCP_HOP_COUNT 45 //1 0
82#define DHCP_TRANS_ID 46 //4
83#define DHCP_NUM_SEC 50 //2 0
84#define DHCP_UNUSED 52 //2
85#define DHCP_CLIENT_IP 54 //4
86#define DHCP_YOUR_IP 58 //4
87#define DHCP_SERVER_IP 62 //4
88#define DHCP_GATEWAY_IP 66 //4
89#define DHCP_CLIENT_ETHERNET 70 //16
90#define DHCP_SERVER_NAME 86 //64
91#define DHCP_BOOT_FILENAME 150 //128
92#define DHCP_MAGIC_COOKIE 278 //4 0x63825363
93#define DHCP_OPTIONS 282 //N
94
95#define DHCP_MESSAGE_TYPE 53 //1 type
96#define DHCP_DISCOVER 1
97#define DHCP_OFFER 2
98#define DHCP_REQUEST 3
99#define DHCP_ACK 5
100#define DHCP_REQUEST_IP 50 //4 ip
101#define DHCP_REQUEST_SERV_IP 54 //4 ip
102#define DHCP_CLIENT_ID 61 //7 1 ethernet
103#define DHCP_HOST_NAME 12 //6 plasma
104#define DHCP_PARAMS 55 //4 1=subnet; 15=domain_name; 3=router; 6=dns
105#define DHCP_PARAM_SUBNET 1
106#define DHCP_PARAM_ROUTER 3
107#define DHCP_PARAM_DNS 6
108#define DHCP_END_OPTION 0xff
109
110//DHCP FIELD OFFSET LENGTH VALUE
111#define DNS_ID 0 //2
112#define DNS_FLAGS 2 //2
113#define DNS_NUM_QUESTIONS 4 //2 1
114#define DNS_NUM_ANSWERS_RR 6 //2 0/1
115#define DNS_NUM_AUTHORITY_RR 8 //2 0
116#define DNS_NUM_ADDITIONAL_RR 10 //2 0
117#define DNS_QUESTIONS 12 //2
118
119#define DNS_FLAGS_RESPONSE 0x8000
120#define DNS_FLAGS_RECURSIVE 0x0100
121#define DNS_FLAGS_ERROR 0x0003
122#define DNS_FLAGS_OK 0x0000
123#define DNS_QUERY_TYPE_IP 1
124#define DNS_QUERY_CLASS 1
125#define DNS_PORT 53
126
127//TCP FIELD OFFSET LENGTH VALUE
128#define TCP_SOURCE_PORT 34 //2
129#define TCP_DEST_PORT 36 //2
130#define TCP_SEQ 38 //4
131#define TCP_ACK 42 //4
132#define TCP_HEADER_LENGTH 46 //1 0x50
133#define TCP_FLAGS 47 //1 SYNC=0x2;ACK=0x10;FIN=0x1
134#define TCP_WINDOW_SIZE 48 //2
135#define TCP_CHECKSUM 50 //2
136#define TCP_URGENT_POINTER 52 //2
137#define TCP_DATA 54 //length-N
138
139#define TCP_FLAGS_FIN 1
140#define TCP_FLAGS_SYN 2
141#define TCP_FLAGS_RST 4
142#define TCP_FLAGS_PSH 8
143#define TCP_FLAGS_ACK 16
144
145//PING FIELD OFFSET LENGTH VALUE
146#define PING_TYPE 34 //1 SEND=8;REPLY=0
147#define PING_CODE 35 //1 0
148#define PING_CHECKSUM 36 //2
149#define PING_ID 38 //2
150#define PING_SEQUENCE 40 //2
151#define PING_DATA 44
152
153static void IPClose2(IPSocket *Socket);
154
155static uint8 ethernetAddressGateway[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
156#ifndef WIN32
157static uint8 ethernetAddressPlasma[] = {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4};
158#else
159static uint8 ethernetAddressPlasma[] = {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd5};
160#endif
161
162static uint8 ipAddressPlasma[] = {0x9d, 0xfe, 0x28, 10}; //changed by DHCP
163static uint8 ipAddressGateway[] = {0xff, 0xff, 0xff, 0xff}; //changed by DHCP
164static uint32 ipAddressDns; //changed by DHCP
165
166static OS_Mutex_t *IPMutex;
167static int FrameFreeCount;
168static IPFrame *FrameFreeHead;
169static IPFrame *FrameSendHead;
170static IPFrame *FrameSendTail;
171static IPFrame *FrameResendHead;
172static IPFrame *FrameResendTail;
173static IPSocket *SocketHead;
174static uint32 Seconds;
175static int DhcpRetrySeconds;
176static IPFuncPtr FrameSendFunc;
177static OS_MQueue_t *IPMQueue;
178static OS_Thread_t *IPThread;
179int IPVerbose=1;
180
181static const unsigned char dhcpDiscover[] = {
182   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, //dest
183   0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4, //src
184   0x08, 0x00,
185   0x45, 0x00, 0x01, 0x48, 0x2e, 0xf5, 0x00, 0x00, //ip
186   0x80, 0x11, 0x0a, 0xb1, 0x00, 0x00, 0x00, 0x00,
187   0xff, 0xff, 0xff, 0xff,
188   0x00, 0x44, 0x00, 0x43, 0x01, 0x34, 0x45, 0x66, //udp
189   0x01, 0x01, 0x06, 0x00, 0x69, 0x26, 0xb5, 0x52 //dhcp
190};
191
192static unsigned char dhcpOptions[] = {
193   0x63, 0x82, 0x53, 0x63, //cookie
194   0x35, 0x01, 0x01, //DHCP Discover
195   0x3d, 0x07, 0x01, 0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4, //Client identifier
196#ifndef WIN32
197   0x0c, 0x06, 'p', 'l', 'a', 's', 'm', 'a', //Host name
198#else
199   0x0c, 0x06, 'p', 'l', 'a', 's', 'm', 'b', //Host name
200#endif
201   0x37, 0x03, DHCP_PARAM_SUBNET, DHCP_PARAM_ROUTER, DHCP_PARAM_DNS, //Parameters
202   DHCP_END_OPTION
203};
204
205
206//Get a free frame; can be called from an ISR
207IPFrame *IPFrameGet(int freeCount)
208{
209   IPFrame *frame=NULL;
210   uint32 state;
211
212   state = OS_CriticalBegin();
213   if(FrameFreeCount > freeCount)
214   {
215      frame = FrameFreeHead;
216      if(FrameFreeHead)
217      {
218         FrameFreeHead = FrameFreeHead->next;
219         --FrameFreeCount;
220      }
221   }
222   OS_CriticalEnd(state);
223   if(frame)
224   {
225      assert(frame->state == 0);
226      frame->state = 1;
227   }
228   return frame;
229}
230
231
232static void FrameFree(IPFrame *frame)
233{
234   uint32 state;
235
236   assert(frame->state == 1);
237   frame->state = 0;
238   state = OS_CriticalBegin();
239   frame->next = FrameFreeHead;
240   FrameFreeHead = frame;
241   ++FrameFreeCount;
242   OS_CriticalEnd(state);
243}
244
245
246static void FrameInsert(IPFrame **head, IPFrame **tail, IPFrame *frame)
247{
248   assert(frame->state == 1);
249   frame->state = 2;
250   OS_MutexPend(IPMutex);
251   frame->prev = NULL;
252   frame->next = *head;
253   if(*head)
254      (*head)->prev = frame;
255   *head = frame;
256   if(*tail == NULL)
257      *tail = frame;
258   OS_MutexPost(IPMutex);
259}
260
261
262static void FrameRemove(IPFrame **head, IPFrame **tail, IPFrame *frame)
263{
264   assert(frame->state == 2);
265   frame->state = 1;
266   if(frame->prev)
267      frame->prev->next = frame->next;
268   else
269      *head = frame->next;
270   if(frame->next)
271      frame->next->prev = frame->prev;
272   else
273      *tail = frame->prev;
274   frame->prev = NULL;
275   frame->next = NULL;
276}
277
278
279static int IPChecksum(int checksum, const unsigned char *data, int length)
280{
281   int i;
282   checksum = ~checksum & 0xffff;
283   for(i = 0; i < length-1; i += 2)
284   {
285      checksum += (data[i] << 8) | data[i+1];
286   }
287   if(i < length)
288      checksum += data[i] << 8;
289   while(checksum >> 16)
290      checksum = (checksum & 0xffff) + (checksum >> 16);
291   checksum = ~checksum & 0xffff;
292   return checksum;
293}
294
295
296static int EthernetVerifyChecksums(const unsigned char *packet, int length)
297{
298   int checksum, length2;
299   unsigned char pseudo[12];
300
301   //Calculate checksums
302   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00) //IP
303   {
304      checksum = IPChecksum(0xffff, packet+IP_VERSION_LENGTH, 20);
305      if(checksum)
306         return -1;
307      if(packet[IP_PROTOCOL] == 0x01) //PING
308      {
309         checksum = IPChecksum(0xffff, packet+PING_TYPE, length-PING_TYPE);
310      }
311      else if(packet[IP_PROTOCOL] == 0x11) //UDP
312      {
313         if(packet[UDP_CHECKSUM] == 0 && packet[UDP_CHECKSUM+1] == 0)
314            return 0;
315         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
316         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
317         pseudo[PSEUDO_ZERO] = 0;
318         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
319         memcpy(pseudo+PSEUDO_LENGTH, packet+UDP_LENGTH, 2);
320         checksum = IPChecksum(0xffff, pseudo, 12);
321         length2 = (packet[UDP_LENGTH] << 8) + packet[UDP_LENGTH+1];
322         checksum = IPChecksum(checksum, packet+UDP_SOURCE_PORT, length);
323      }
324      else if(packet[IP_PROTOCOL] == 0x06) //TCP
325      {
326         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
327         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
328         pseudo[PSEUDO_ZERO] = 0;
329         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
330         length = (packet[IP_LENGTH] << 8) + packet[IP_LENGTH+1];
331         length2 = length - 20;
332         pseudo[PSEUDO_LENGTH] = (unsigned char)(length2 >> 8);
333         pseudo[PSEUDO_LENGTH+1] = (unsigned char)length2;
334         checksum = IPChecksum(0xffff, pseudo, 12);
335         checksum = IPChecksum(checksum, packet+TCP_SOURCE_PORT, length2);
336      }
337      if(checksum)
338         return -1;
339   }
340   return 0;
341}
342
343
344static void IPFrameReschedule(IPFrame *frame)
345{
346   int length;
347   length = frame->length - TCP_DATA;
348   if(frame->packet[TCP_FLAGS] & (TCP_FLAGS_FIN | TCP_FLAGS_SYN))
349      ++length;
350   if(frame->socket == NULL || frame->socket->state == IP_UDP || length == 0 ||
351      frame->socket->state == IP_PING || ++frame->retryCnt > 4)
352   {
353      FrameFree(frame); //can't be ACK'ed
354   }
355#ifdef WIN32
356   else if(FrameFreeCount < FRAME_COUNT_SYNC)
357   {
358      FrameFree(frame); //can't be ACK'ed
359   }
360#endif
361   else
362   {
363      //Put on resend list until TCP ACK'ed
364      frame->timeout = (short)(RETRANSMIT_TIME * frame->retryCnt);
365      FrameInsert(&FrameResendHead, &FrameResendTail, frame);
366   }
367}
368
369
370static void IPSendFrame(IPFrame *frame)
371{
372   uint32 message[4];
373
374   if(FrameSendFunc)
375   {
376      //Single threaded
377      FrameSendFunc(frame->packet, frame->length);
378      IPFrameReschedule(frame);
379   }
380   else
381   {
382      //Add Packet to send queue
383      FrameInsert(&FrameSendHead, &FrameSendTail, frame);
384
385      //Wakeup sender thread
386      message[0] = 2;
387      OS_MQueueSend(IPMQueue, message);
388   }
389}
390
391
392static void IPSendPacket(IPSocket *socket, IPFrame *frame, int length)
393{
394   int checksum, length2=length;
395   unsigned char pseudo[12], *packet=frame->packet;
396
397   frame->length = (uint16)length;
398
399   //Calculate checksums
400   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00) //IP
401   {
402      length2 = length - IP_VERSION_LENGTH;
403      packet[IP_LENGTH] = (uint8)(length2 >> 8);
404      packet[IP_LENGTH+1] = (uint8)length2;
405      memset(packet+IP_CHECKSUM, 0, 2);
406      checksum = IPChecksum(0xffff, packet+IP_VERSION_LENGTH, 20);
407      packet[IP_CHECKSUM] = (unsigned char)(checksum >> 8);
408      packet[IP_CHECKSUM+1] = (unsigned char)checksum;
409      if(packet[IP_PROTOCOL] == 0x01) //ICMP & PING
410      {
411         memset(packet+PING_CHECKSUM, 0, 2);
412         checksum = IPChecksum(0xffff, packet+PING_TYPE, length-PING_TYPE);
413         packet[PING_CHECKSUM] = (unsigned char)(checksum >> 8);
414         packet[PING_CHECKSUM+1] = (unsigned char)checksum;
415      }
416      else if(packet[IP_PROTOCOL] == 0x11) //UDP
417      {
418         length2 = length - UDP_SOURCE_PORT;
419         packet[UDP_LENGTH] = (uint8)(length2 >> 8);
420         packet[UDP_LENGTH+1] = (uint8)length2;
421         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
422         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
423         pseudo[PSEUDO_ZERO] = 0;
424         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
425         memcpy(pseudo+PSEUDO_LENGTH, packet+UDP_LENGTH, 2);
426         checksum = IPChecksum(0xffff, pseudo, 12);
427         memset(packet+UDP_CHECKSUM, 0, 2);
428         length2 = (packet[UDP_LENGTH] << 8) + packet[UDP_LENGTH+1];
429         checksum = IPChecksum(checksum, packet+UDP_SOURCE_PORT, length2);
430         packet[UDP_CHECKSUM] = (unsigned char)(checksum >> 8);
431         packet[UDP_CHECKSUM+1] = (unsigned char)checksum;
432      }
433      else if(packet[IP_PROTOCOL] == 0x06) //TCP
434      {
435         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
436         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
437         pseudo[PSEUDO_ZERO] = 0;
438         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
439         length2 = (packet[IP_LENGTH] << 8) + packet[IP_LENGTH+1];
440         length2 = length2 - 20;
441         pseudo[PSEUDO_LENGTH] = (unsigned char)(length2 >> 8);
442         pseudo[PSEUDO_LENGTH+1] = (unsigned char)length2;
443         checksum = IPChecksum(0xffff, pseudo, 12);
444         memset(packet+TCP_CHECKSUM, 0, 2);
445         checksum = IPChecksum(checksum, packet+TCP_SOURCE_PORT, length2);
446         packet[TCP_CHECKSUM] = (unsigned char)(checksum >> 8);
447         packet[TCP_CHECKSUM+1] = (unsigned char)checksum;
448      }
449   }
450
451   length2 = length - TCP_DATA;
452   if(socket && (packet[TCP_FLAGS] & (TCP_FLAGS_FIN | TCP_FLAGS_SYN)))
453      length2 = 1;
454   frame->socket = socket;
455   frame->timeout = 0;
456   frame->retryCnt = 0;
457   if(socket)
458      frame->seqEnd = socket->seq + length2;
459   IPSendFrame(frame);
460}
461
462
463static void TCPSendPacket(IPSocket *socket, IPFrame *frame, int length)
464{
465   uint8 *packet = frame->packet;
466   int flags, count;
467
468   flags = packet[TCP_FLAGS];
469   memcpy(packet, socket->headerSend, TCP_SEQ);
470   packet[TCP_FLAGS] = (uint8)flags;
471   if(flags & TCP_FLAGS_SYN)
472      packet[TCP_HEADER_LENGTH] = 0x60; //set maximum segment size
473   else
474      packet[TCP_HEADER_LENGTH] = 0x50;
475   packet[TCP_SEQ] = (uint8)(socket->seq >> 24);
476   packet[TCP_SEQ+1] = (uint8)(socket->seq >> 16);
477   packet[TCP_SEQ+2] = (uint8)(socket->seq >> 8);
478   packet[TCP_SEQ+3] = (uint8)socket->seq;
479   packet[TCP_ACK] = (uint8)(socket->ack >> 24);
480   packet[TCP_ACK+1] = (uint8)(socket->ack >> 16);
481   packet[TCP_ACK+2] = (uint8)(socket->ack >> 8);
482   packet[TCP_ACK+3] = (uint8)socket->ack;
483   count = RECEIVE_WINDOW - (socket->ack - socket->ackProcessed);
484   if(count < 0)
485      count = 0;
486   packet[TCP_WINDOW_SIZE] = (uint8)(count >> 8);
487   packet[TCP_WINDOW_SIZE+1] = (uint8)count;
488   packet[TCP_URGENT_POINTER] = 0;
489   packet[TCP_URGENT_POINTER+1] = 0;
490   IPSendPacket(socket, frame, length);
491}
492
493
494static void EthernetCreateResponse(unsigned char *packetOut,
495                                   const unsigned char *packet,
496                                   int length)
497{
498   //Swap destination and source fields
499   memcpy(packetOut, packet, length);
500   memcpy(packetOut+ETHERNET_DEST, packet+ETHERNET_SOURCE, 6);
501   memcpy(packetOut+ETHERNET_SOURCE, packet+ETHERNET_DEST, 6);
502   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00) //IP
503   {
504      memcpy(packetOut+IP_SOURCE, packet+IP_DEST, 4);
505      memcpy(packetOut+IP_DEST, packet+IP_SOURCE, 4);
506      if(packet[IP_PROTOCOL] == 0x06 || packet[IP_PROTOCOL] == 0x11) //TCP/UDP
507      {
508         memcpy(packetOut+TCP_SOURCE_PORT, packet+TCP_DEST_PORT, 2);
509         memcpy(packetOut+TCP_DEST_PORT, packet+TCP_SOURCE_PORT, 2);
510      }
511   }
512}
513
514
515static void IPDhcp(const unsigned char *packet, int length, int state)
516{
517   uint8 *packetOut, *ptr;
518   const uint8 *ptr2;
519   IPFrame *frame;
520   static int request=0;
521
522   if(state == 1)
523   {
524      //Create DHCP Discover
525      frame = IPFrameGet(0);
526      if(frame == NULL)
527         return;
528      packetOut = frame->packet;
529      memset(packetOut, 0, 512);
530      memcpy(packetOut, dhcpDiscover, sizeof(dhcpDiscover));
531      memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
532      memcpy(packetOut+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6);
533      memcpy(packetOut+DHCP_MAGIC_COOKIE, dhcpOptions, sizeof(dhcpOptions));
534      memcpy(packetOut+DHCP_MAGIC_COOKIE+10, ethernetAddressPlasma, 6);
535      IPSendPacket(NULL, frame, 400);
536      request = DHCP_DISCOVER;
537      DhcpRetrySeconds = 2;
538   }
539   else if(state == 2 && memcmp(packet+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6) == 0)
540   {
541      if(packet[DHCP_MAGIC_COOKIE+6] == DHCP_OFFER && request == DHCP_DISCOVER)
542      {
543         //Process DHCP Offer and send DHCP Request
544         frame = IPFrameGet(0);
545         if(frame == NULL)
546            return;
547         packetOut = frame->packet;
548         memset(packetOut, 0, 512);
549         memcpy(packetOut, dhcpDiscover, sizeof(dhcpDiscover));
550         memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
551         memcpy(packetOut+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6);
552         memcpy(packetOut+DHCP_MAGIC_COOKIE, dhcpOptions, sizeof(dhcpOptions));
553         memcpy(packetOut+DHCP_MAGIC_COOKIE+10, ethernetAddressPlasma, 6);
554         request = DHCP_REQUEST;
555         packetOut[DHCP_MAGIC_COOKIE+6] = DHCP_REQUEST;
556         ptr = packetOut+DHCP_MAGIC_COOKIE+sizeof(dhcpOptions)-1;
557         ptr[0] = DHCP_REQUEST_IP;
558         ptr[1] = 4;
559         memcpy(ptr+2, packet+DHCP_YOUR_IP, 4);
560         ptr[6] = DHCP_REQUEST_SERV_IP;
561         ptr[7] = 4;
562         memcpy(ptr+8, packet+DHCP_SERVER_IP, 4);
563         ptr[12] = DHCP_END_OPTION;
564         IPSendPacket(NULL, frame, 400);
565      }
566      else if(packet[DHCP_MAGIC_COOKIE+6] == DHCP_ACK && request == DHCP_REQUEST)
567      {
568         //Process DHCP Ack
569         request = 0;
570         DhcpRetrySeconds = 3600*4;
571         memcpy(ipAddressPlasma, packet+DHCP_YOUR_IP, 4);
572         printf("IP=%d.%d.%d.%d ", ipAddressPlasma[0], ipAddressPlasma[1],
573            ipAddressPlasma[2], ipAddressPlasma[3]);
574         memcpy(ipAddressGateway, packet+DHCP_GATEWAY_IP, 4);
575         if(ipAddressGateway[0] == 0 && ipAddressGateway[1] == 0 &&
576            ipAddressGateway[2] == 0 && ipAddressGateway[3] == 0)
577            memcpy(ipAddressGateway, packet+DHCP_SERVER_IP, 4);
578         printf("GW=%d.%d.%d.%d ", ipAddressGateway[0], ipAddressGateway[1],
579            ipAddressGateway[2], ipAddressGateway[3]);
580         memcpy(ethernetAddressGateway, packet+ETHERNET_SOURCE, 6);
581         ptr2 = packet+DHCP_MAGIC_COOKIE+4;
582         while(ptr2[0] != DHCP_END_OPTION && (int)(ptr2 - packet) < length)
583         {
584            if(ptr2[0] == DHCP_PARAM_DNS)
585            {
586               ipAddressDns = (ptr2[2] << 24) | (ptr2[3] << 16) | (ptr2[4] << 8) | ptr2[5];
587               printf("DNS=%d.%d.%d.%d ", ptr2[2], ptr2[3], ptr2[4], ptr2[5]);
588            }
589            ptr2 += ptr2[1] + 2;
590         }
591
592         //Check if DHCP reply came from gateway
593         if(memcmp(packet+IP_SOURCE, ipAddressGateway, 4))
594         {
595            //Send ARP to gateway
596            frame = IPFrameGet(0);
597            if(frame == NULL)
598               return;
599            packetOut = frame->packet;
600            memset(packetOut, 0, 512);
601            memset(packetOut+ETHERNET_DEST, 0xff, 6);
602            memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
603            packetOut[ETHERNET_FRAME_TYPE] = 0x08;
604            packetOut[ETHERNET_FRAME_TYPE+1] = 0x06;
605            packetOut[ARP_HARD_TYPE+1] = 0x01;
606            packetOut[ARP_PROT_TYPE] = 0x08;
607            packetOut[ARP_HARD_SIZE] = 0x06;
608            packetOut[ARP_PROT_SIZE] = 0x04;
609            packetOut[ARP_OP+1] = 1;
610            memcpy(packetOut+ARP_ETHERNET_SENDER, ethernetAddressPlasma, 6);
611            memcpy(packetOut+ARP_IP_SENDER, ipAddressPlasma, 4);
612            memcpy(packetOut+ARP_IP_TARGET, ipAddressGateway, 4);
613            IPSendPacket(NULL, frame, 60);
614         }
615      }
616   }
617}
618
619
620uint32 IPAddressSelf(void)
621{
622   return (ipAddressPlasma[0] << 24) | (ipAddressPlasma[1] << 16) |
623          (ipAddressPlasma[2] << 8) | ipAddressPlasma[3];
624}
625
626
627static int IPProcessTCPPacket(IPFrame *frameIn)
628{
629   uint32 seq, ack;
630   int length, ip_length, bytes, rc=0, notify=0;
631   IPSocket *socket, *socketNew;
632   IPFrame *frameOut, *frame2, *framePrev;
633   uint8 *packet, *packetOut;
634
635   packet = frameIn->packet;
636   length = frameIn->length;
637
638   ip_length = (packet[IP_LENGTH] << 8) | packet[IP_LENGTH+1];
639   seq = (packet[TCP_SEQ] << 24) | (packet[TCP_SEQ+1] << 16) |
640         (packet[TCP_SEQ+2] << 8) | packet[TCP_SEQ+3];
641   ack = (packet[TCP_ACK] << 24) | (packet[TCP_ACK+1] << 16) |
642         (packet[TCP_ACK+2] << 8) | packet[TCP_ACK+3];
643
644   //Check if start of connection
645   if((packet[TCP_FLAGS] & (TCP_FLAGS_SYN | TCP_FLAGS_ACK)) == TCP_FLAGS_SYN)
646   {
647      if(IPVerbose)
648         printf("S");
649      //Check if duplicate SYN
650      for(socket = SocketHead; socket; socket = socket->next)
651      {
652         if(socket->state != IP_LISTEN &&
653            packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
654            memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&
655            memcmp(packet+TCP_SOURCE_PORT, socket->headerRcv+TCP_SOURCE_PORT, 4) == 0)
656         {
657            if(IPVerbose)
658               printf("s");
659            return 0;
660         }
661      }
662
663      //Find an open port
664      for(socket = SocketHead; socket; socket = socket->next)
665      {
666         if(socket->state == IP_LISTEN &&
667            packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
668            memcmp(packet+TCP_DEST_PORT, socket->headerRcv+TCP_DEST_PORT, 2) == 0)
669         {
670            //Create a new socket
671            frameOut = IPFrameGet(FRAME_COUNT_SYNC);
672            if(frameOut == NULL)
673               return 0;
674            socketNew = (IPSocket*)malloc(sizeof(IPSocket));
675            if(socketNew == NULL)
676               return 0;
677            memcpy(socketNew, socket, sizeof(IPSocket));
678            socketNew->state = IP_TCP;
679            socketNew->timeout = SOCKET_TIMEOUT;
680            socketNew->ack = seq;
681            socketNew->ackProcessed = seq + 1;
682            socketNew->seq = socketNew->ack + 0x12345678;
683            socketNew->seqReceived = socketNew->seq;
684            socketNew->seqWindow = (packet[TCP_WINDOW_SIZE] << 8) | packet[TCP_WINDOW_SIZE+1];
685
686            //Send ACK
687            packetOut = frameOut->packet;
688            EthernetCreateResponse(packetOut, packet, length);
689            memcpy(socketNew->headerRcv, packet, TCP_SEQ);
690            memcpy(socketNew->headerSend, packetOut, TCP_SEQ);
691            packetOut[TCP_FLAGS] = TCP_FLAGS_SYN | TCP_FLAGS_ACK;
692            ++socketNew->ack;
693            packetOut[TCP_DATA] = 2; //maximum segment size = 536
694            packetOut[TCP_DATA+1] = 4;
695            packetOut[TCP_DATA+2] = 2;
696            packetOut[TCP_DATA+3] = 24;
697            TCPSendPacket(socketNew, frameOut, TCP_DATA+4);
698            ++socketNew->seq;
699
700            //Add socket to linked list
701            OS_MutexPend(IPMutex);
702            socketNew->next = SocketHead;
703            socketNew->prev = NULL;
704            if(SocketHead)
705               SocketHead->prev = socketNew;
706            SocketHead = socketNew;
707            OS_MutexPost(IPMutex);
708            if(socketNew->funcPtr)
709               OS_Job(socketNew->funcPtr, socketNew, 0, 0);
710            return 0;
711         }
712      }
713
714      //Send reset
715      frameOut = IPFrameGet(0);
716      if(frameOut == NULL)
717         return 0;
718      packetOut = frameOut->packet;
719      EthernetCreateResponse(packetOut, packet, TCP_DATA);
720      memset(packetOut+TCP_SEQ, 0, 4);
721      ++seq;
722      packetOut[TCP_ACK] = (uint8)(seq >> 24);
723      packetOut[TCP_ACK+1] = (uint8)(seq >> 16);
724      packetOut[TCP_ACK+2] = (uint8)(seq >> 8);
725      packetOut[TCP_ACK+3] = (uint8)seq;
726      packetOut[TCP_HEADER_LENGTH] = 0x50;
727      packetOut[TCP_FLAGS] = TCP_FLAGS_RST;
728      IPSendPacket(NULL, frameOut, TCP_DATA);
729      return 0;
730   }
731
732   //Find an open socket
733   for(socket = SocketHead; socket; socket = socket->next)
734   {
735      if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
736         memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&
737         memcmp(packet+TCP_SOURCE_PORT, socket->headerRcv+TCP_SOURCE_PORT, 4) == 0)
738      {
739         break;
740      }
741   }
742   if(socket == NULL)
743   {
744      return 0;
745   }
746
747   //Determine window
748   socket->seqWindow = (packet[TCP_WINDOW_SIZE] << 8) | packet[TCP_WINDOW_SIZE+1];
749   bytes = ip_length - (TCP_DATA - IP_VERSION_LENGTH);
750
751   //Check if packets can be removed from retransmition list
752   if(packet[TCP_FLAGS] & TCP_FLAGS_ACK)
753   {
754      if(ack != socket->seqReceived)
755      {
756         OS_MutexPend(IPMutex);
757         for(frame2 = FrameResendHead; frame2; )
758         {
759            framePrev = frame2;
760            frame2 = frame2->next;
761            if(framePrev->socket == socket && (int)(ack - framePrev->seqEnd) >= 0)
762            {
763               //Remove packet from retransmition queue
764               if(socket->timeout)
765                  socket->timeout = socket->timeoutReset;
766               FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);
767               FrameFree(framePrev);
768            }
769         }
770         OS_MutexPost(IPMutex);
771         socket->seqReceived = ack;
772         socket->resentDone = 0;
773      }
774      else if(ack == socket->seqReceived && bytes == 0 &&
775         (packet[TCP_FLAGS] & (TCP_FLAGS_RST | TCP_FLAGS_FIN)) == 0 &&
776         socket->resentDone == 0)
777      {
778         //Detected that packet was lost, resend all
779         if(IPVerbose)
780            printf("A");
781         OS_MutexPend(IPMutex);
782         for(frame2 = FrameResendHead; frame2; )
783         {
784            framePrev = frame2;
785            frame2 = frame2->next;
786            if(framePrev->socket == socket)
787            {
788               //Remove packet from retransmition queue
789               FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);
790               IPSendFrame(framePrev);
791            }
792         }
793         OS_MutexPost(IPMutex);
794         socket->resentDone = 1;
795      }
796   }
797
798   //Check if SYN/ACK
799   if((packet[TCP_FLAGS] & (TCP_FLAGS_SYN | TCP_FLAGS_ACK)) ==
800      (TCP_FLAGS_SYN | TCP_FLAGS_ACK))
801   {
802      //Ack SYN/ACK
803      socket->ack = seq + 1;
804      socket->ackProcessed = seq + 1;
805      frameOut = IPFrameGet(FRAME_COUNT_SEND);
806      if(frameOut)
807      {
808         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
809         TCPSendPacket(socket, frameOut, TCP_DATA);
810      }
811      if(socket->funcPtr)
812         OS_Job(socket->funcPtr, socket, 0, 0);
813      return 0;
814   }
815   if(packet[TCP_HEADER_LENGTH] != 0x50)
816   {
817      if(IPVerbose)
818         printf("length error\n");
819      return 0;
820   }
821
822   //Check if RST flag set
823   if(packet[TCP_FLAGS] & TCP_FLAGS_RST)
824   {
825      notify = 1;
826      if(socket->state == IP_FIN_SERVER)
827         IPClose2(socket);
828      else if(socket->state == IP_TCP)
829         socket->state = IP_FIN_CLIENT;
830   }
831   //Copy packet into socket
832   else if(socket->ack == seq && bytes > 0)
833   {
834      //Insert packet into socket linked list
835      notify = 1;
836      if(socket->timeout)
837         socket->timeout = socket->timeoutReset;
838      if(IPVerbose)
839         printf("D");
840      if(frameIn->length > ip_length + IP_VERSION_LENGTH)
841         frameIn->length = (uint16)(ip_length + IP_VERSION_LENGTH);
842      FrameInsert(&socket->frameReadHead, &socket->frameReadTail, frameIn);
843      socket->ack += bytes;
844
845      //Ack data
846      frameOut = IPFrameGet(FRAME_COUNT_SEND);
847      if(frameOut)
848      {
849         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
850         TCPSendPacket(socket, frameOut, TCP_DATA);
851      }
852
853      //Using frame
854      rc = 1;
855   }
856   else if(bytes)
857   {
858      //Ack with current offset since data missing
859      frameOut = IPFrameGet(FRAME_COUNT_SEND);
860      if(frameOut)
861      {
862         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
863         TCPSendPacket(socket, frameOut, TCP_DATA);
864      }
865   }
866
867   //Check if FIN flag set
868   if(packet[TCP_FLAGS] & TCP_FLAGS_FIN && socket->ack >= seq)
869   {
870      notify = 1;
871      socket->timeout = SOCKET_TIMEOUT;
872      if(IPVerbose)
873         printf("F");
874      frameOut = IPFrameGet(0);
875      if(frameOut == NULL)
876         return 0;
877      packetOut = frameOut->packet;
878      packetOut[TCP_FLAGS] = TCP_FLAGS_ACK;
879      ++socket->ack;
880      TCPSendPacket(socket, frameOut, TCP_DATA);
881      if(socket->state == IP_FIN_SERVER)
882         IPClose2(socket);
883      else if(socket->state == IP_TCP)
884         socket->state = IP_FIN_CLIENT;
885   }
886
887   //Notify application
888   if(socket->funcPtr && notify)
889      OS_Job(socket->funcPtr, socket, 0, 0);
890   return rc;
891}
892
893
894int IPProcessEthernetPacket(IPFrame *frameIn, int length)
895{
896   int ip_length, rc;
897   IPSocket *socket;
898   IPFrame *frameOut;
899   uint8 *packet, *packetOut;
900
901   packet = frameIn->packet;
902   frameIn->length = (uint16)length;
903
904   if(packet[ETHERNET_FRAME_TYPE] != 0x08 || frameIn->length > PACKET_SIZE)
905      return 0; //wrong ethernet type, packet not used
906
907   //ARP?
908   if(packet[ETHERNET_FRAME_TYPE+1] == 0x06)
909   {
910      //Check if ARP reply
911      if(memcmp(packet+ETHERNET_DEST, ethernetAddressPlasma, 6) == 0 &&
912         packet[ARP_OP+1] == 2 && memcmp(packet+ARP_IP_SENDER, ipAddressGateway, 4) == 0)
913      {
914         //Found MAC address for gateway
915         memcpy(ethernetAddressGateway, packet+ARP_ETHERNET_SENDER, 6);
916         return 0;
917      }
918
919      //Check if ARP request
920      if(packet[ARP_OP] != 0 || packet[ARP_OP+1] != 1 ||
921         memcmp(packet+ARP_IP_TARGET, ipAddressPlasma, 4))
922         return 0;
923      //Create ARP response
924      frameOut = IPFrameGet(0);
925      if(frameOut == NULL)
926         return 0;
927      packetOut = frameOut->packet;
928      memcpy(packetOut, packet, frameIn->length);
929      memcpy(packetOut+ETHERNET_DEST, packet+ETHERNET_SOURCE, 6);
930      memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
931      packetOut[ARP_OP+1] = 2; //ARP reply
932      memcpy(packetOut+ARP_ETHERNET_SENDER, ethernetAddressPlasma, 6);
933      memcpy(packetOut+ARP_IP_SENDER, packet+ARP_IP_TARGET, 4);
934      memcpy(packetOut+ARP_ETHERNET_TARGET, packet+ARP_ETHERNET_SENDER, 6);
935      memcpy(packetOut+ARP_IP_TARGET, packet+ARP_IP_SENDER, 4);
936      IPSendPacket(NULL, frameOut, frameIn->length);
937      return 0;
938   }
939
940   //Check if proper type of packet
941   ip_length = (packet[IP_LENGTH] << 8) | packet[IP_LENGTH+1];
942   if(frameIn->length < UDP_DATA || ip_length > frameIn->length - IP_VERSION_LENGTH)
943      return 0;
944   if(packet[ETHERNET_FRAME_TYPE+1] != 0x00 ||
945      packet[IP_VERSION_LENGTH] != 0x45)
946      return 0;
947
948   //Check if DHCP reply
949   if(packet[IP_PROTOCOL] == 0x11 &&
950      packet[UDP_SOURCE_PORT] == 0 && packet[UDP_SOURCE_PORT+1] == 67 &&
951      packet[UDP_DEST_PORT] == 0 && packet[UDP_DEST_PORT+1] == 68)
952   {
953      IPDhcp(packet, frameIn->length, 2); //DHCP reply
954      return 0;
955   }
956
957   //Check if correct destination address
958   if(memcmp(packet+ETHERNET_DEST, ethernetAddressPlasma, 6) ||
959      memcmp(packet+IP_DEST, ipAddressPlasma, 4))
960      return 0;
961   rc = EthernetVerifyChecksums(packet, frameIn->length);
962#ifndef WIN32
963   if(rc && FrameSendFunc)
964   {
965      printf("C ");
966      return 0;
967   }
968#endif
969
970   //PING request?
971   if(packet[IP_PROTOCOL] == 1)
972   {
973      if(packet[PING_TYPE] == 0) //PING reply
974      {
975         for(socket = SocketHead; socket; socket = socket->next)
976         {
977            if(socket->state == IP_PING &&
978               memcmp(packet+IP_SOURCE, socket->headerSend+IP_DEST, 4) == 0)
979            {
980               OS_Job(socket->funcPtr, socket, 0, 0);
981               return 0;
982            }
983         }
984      }
985      if(packet[PING_TYPE] != 8)
986         return 0;
987      frameOut = IPFrameGet(FRAME_COUNT_SEND);
988      if(frameOut == NULL)
989         return 0;
990      packetOut = frameOut->packet;
991      EthernetCreateResponse(packetOut, packet, frameIn->length);
992      frameOut->packet[PING_TYPE] = 0; //PING reply
993      IPSendPacket(NULL, frameOut, frameIn->length);
994      return 0;
995   }
996
997   //TCP packet?
998   if(packet[IP_PROTOCOL] == 0x06)
999   {
1000      return IPProcessTCPPacket(frameIn);
1001   }
1002
1003   //UDP packet?
1004   if(packet[IP_PROTOCOL] == 0x11)
1005   {
1006      //Find open socket
1007      for(socket = SocketHead; socket; socket = socket->next)
1008      {
1009         if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
1010            memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&
1011            memcmp(packet+UDP_SOURCE_PORT, socket->headerRcv+UDP_SOURCE_PORT, 2) == 0)
1012         {
1013            break;
1014         }
1015      }
1016
1017      if(socket == NULL)
1018      {
1019         //Find listening socket
1020         for(socket = SocketHead; socket; socket = socket->next)
1021         {
1022            if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
1023               memcmp(packet+UDP_DEST_PORT, socket->headerRcv+UDP_DEST_PORT, 2) == 0)
1024            {
1025               EthernetCreateResponse(socket->headerSend, packet, UDP_DATA);
1026               break;
1027            }
1028         }
1029      }
1030
1031      if(socket)
1032      {
1033         if(IPVerbose)
1034            printf("U");
1035         FrameInsert(&socket->frameReadHead, &socket->frameReadTail, frameIn);
1036         OS_Job(socket->funcPtr, socket, 0, 0);
1037         return 1;
1038      }
1039   }
1040   return 0;
1041}
1042
1043
1044#ifndef WIN32
1045static void IPMainThread(void *arg)
1046{
1047   uint32 message[4];
1048   int rc;
1049   IPFrame *frame, *frameOut=NULL;
1050   uint32 ticks, ticksLast;
1051   (void)arg;
1052
1053   ticksLast = OS_ThreadTime();
1054   memset(message, 0, sizeof(message));
1055
1056   for(;;)
1057   {
1058      Led(7, 0);
1059      rc = OS_MQueueGet(IPMQueue, message, 10);
1060      if(rc == 0)
1061      {
1062         frame = (IPFrame*)message[1];
1063         if(message[0] == 0) //frame received
1064         {
1065            Led(7, 1);
1066            frame->length = (uint16)message[2];
1067            rc = IPProcessEthernetPacket(frame, frame->length);
1068            if(rc == 0)
1069               FrameFree(frame);
1070         }
1071         else if(message[0] == 1) //frame sent
1072         {
1073            Led(7, 2);
1074            assert(frame == frameOut);
1075            IPFrameReschedule(frame);
1076            frameOut = NULL;
1077         }
1078         else if(message[0] == 2) //frame ready to send
1079         {
1080         }
1081      }
1082
1083      if(frameOut == NULL)
1084      {
1085         OS_MutexPend(IPMutex);
1086         frameOut = FrameSendTail;
1087         if(frameOut)
1088            FrameRemove(&FrameSendHead, &FrameSendTail, frameOut);
1089         OS_MutexPost(IPMutex);
1090         if(frameOut)
1091         {
1092            Led(7, 4);
1093            UartPacketSend(frameOut->packet, frameOut->length);
1094         }
1095      }
1096
1097      ticks = OS_ThreadTime();
1098      if(ticks - ticksLast > 100)
1099      {
1100         IPTick();
1101         ticksLast = ticks;
1102      }
1103   }
1104}
1105#endif
1106
1107
1108uint8 *MyPacketGet(void)
1109{
1110   return (uint8*)IPFrameGet(FRAME_COUNT_RCV);
1111}
1112
1113
1114//Set FrameSendFunction only if single threaded
1115void IPInit(IPFuncPtr frameSendFunction, uint8 macAddress[6], char name[6])
1116{
1117   int i;
1118   IPFrame *frame;
1119
1120   if(macAddress)
1121      memcpy(ethernetAddressPlasma, macAddress, 6);
1122   if(name)
1123      memcpy(dhcpOptions+18, name, 6);
1124   FrameSendFunc = frameSendFunction;
1125   IPMutex = OS_MutexCreate("IPSem");
1126   IPMQueue = OS_MQueueCreate("IPMQ", FRAME_COUNT*2, 32);
1127   for(i = 0; i < FRAME_COUNT; ++i)
1128   {
1129      frame = (IPFrame*)malloc(sizeof(IPFrame));
1130      memset(frame, 0, sizeof(IPFrame));
1131      frame->next = FrameFreeHead;
1132      frame->prev = NULL;
1133      FrameFreeHead = frame;
1134   }
1135   FrameFreeCount = FRAME_COUNT;
1136#ifndef WIN32
1137   UartPacketConfig(MyPacketGet, PACKET_SIZE, IPMQueue);
1138   if(frameSendFunction == NULL)
1139      IPThread = OS_ThreadCreate("TCP/IP", IPMainThread, NULL, 240, 6000);
1140#endif
1141   IPDhcp(NULL, 360, 1); //Send DHCP request
1142}
1143
1144
1145//To open a socket for listen set ipAddress to 0
1146IPSocket *IPOpen(IPMode_e mode, uint32 ipAddress, uint32 port, IPFuncPtr funcPtr)
1147{
1148   IPSocket *socket;
1149   uint8 *ptrSend, *ptrRcv;
1150   IPFrame *frame;
1151   static int portSource=0x1007;
1152
1153   socket = (IPSocket*)malloc(sizeof(IPSocket));
1154   if(socket == NULL)
1155      return socket;
1156   memset(socket, 0, sizeof(IPSocket));
1157   socket->prev = NULL;
1158   socket->state = IP_LISTEN;
1159   socket->timeout = 0;
1160   socket->timeoutReset = SOCKET_TIMEOUT;
1161   socket->frameReadHead = NULL;
1162   socket->frameReadTail = NULL;
1163   socket->readOffset = 0;
1164   socket->funcPtr = funcPtr;
1165   socket->userData = 0;
1166   socket->userFunc = NULL;
1167   socket->userPtr = NULL;
1168   socket->seqWindow = 2048;
1169   ptrSend = socket->headerSend;
1170   ptrRcv = socket->headerRcv;
1171
1172   if(ipAddress == 0)
1173   {
1174      //Setup listing port
1175      socket->headerRcv[TCP_DEST_PORT] = (uint8)(port >> 8);
1176      socket->headerRcv[TCP_DEST_PORT+1] = (uint8)port;
1177   }
1178   else
1179   {
1180      //Setup sending packet
1181      memset(ptrSend, 0, UDP_LENGTH);
1182      memset(ptrRcv, 0, UDP_LENGTH);
1183
1184      //Setup Ethernet
1185      if(ipAddress != IPAddressSelf())
1186         memcpy(ptrSend+ETHERNET_DEST, ethernetAddressGateway, 6);
1187      else
1188         memcpy(ptrSend+ETHERNET_DEST, ethernetAddressPlasma, 6);
1189      memcpy(ptrSend+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
1190      ptrSend[ETHERNET_FRAME_TYPE] = 0x08;
1191
1192      //Setup IP
1193      ptrSend[IP_VERSION_LENGTH] = 0x45;
1194      ptrSend[IP_TIME_TO_LIVE] = 0x80;
1195
1196      //Setup IP addresses
1197      memcpy(ptrSend+IP_SOURCE, ipAddressPlasma, 4);
1198      ptrSend[IP_DEST] = (uint8)(ipAddress >> 24);
1199      ptrSend[IP_DEST+1] = (uint8)(ipAddress >> 16);
1200      ptrSend[IP_DEST+2] = (uint8)(ipAddress >> 8);
1201      ptrSend[IP_DEST+3] = (uint8)ipAddress;
1202      ptrRcv[IP_SOURCE] = (uint8)(ipAddress >> 24);
1203      ptrRcv[IP_SOURCE+1] = (uint8)(ipAddress >> 16);
1204      ptrRcv[IP_SOURCE+2] = (uint8)(ipAddress >> 8);
1205      ptrRcv[IP_SOURCE+3] = (uint8)ipAddress;
1206      memcpy(ptrRcv+IP_DEST, ipAddressPlasma, 4);
1207
1208      //Setup ports
1209      ptrSend[TCP_SOURCE_PORT] = (uint8)(portSource >> 8);
1210      ptrSend[TCP_SOURCE_PORT+1] = (uint8)portSource;
1211      ptrSend[TCP_DEST_PORT] = (uint8)(port >> 8);
1212      ptrSend[TCP_DEST_PORT+1] = (uint8)port;
1213      ptrRcv[TCP_SOURCE_PORT] = (uint8)(port >> 8);
1214      ptrRcv[TCP_SOURCE_PORT+1] = (uint8)port;
1215      ptrRcv[TCP_DEST_PORT] = (uint8)(portSource >> 8);
1216      ptrRcv[TCP_DEST_PORT+1] = (uint8)portSource;
1217      ++portSource;
1218   }
1219
1220   if(mode == IP_MODE_TCP)
1221   {
1222      if(ipAddress)
1223         socket->state = IP_TCP;
1224      else
1225         socket->state = IP_LISTEN;
1226      ptrSend[IP_PROTOCOL] = 0x06; //TCP
1227      ptrRcv[IP_PROTOCOL] = 0x06;
1228   }
1229   else if(mode == IP_MODE_UDP)
1230   {
1231      socket->state = IP_UDP;
1232      ptrSend[IP_PROTOCOL] = 0x11; //UDP
1233      ptrRcv[IP_PROTOCOL] = 0x11;
1234   }
1235   else if(mode == IP_MODE_PING)
1236   {
1237      socket->state = IP_PING;
1238      ptrSend[IP_PROTOCOL] = 0x01; //PING
1239      memset(ptrSend+PING_TYPE, 0, 8);
1240      ptrSend[PING_TYPE] = 8; //SEND
1241   }
1242
1243   //Add socket to linked list
1244   OS_MutexPend(IPMutex);
1245   socket->next = SocketHead;
1246   socket->prev = NULL;
1247   if(SocketHead)
1248      SocketHead->prev = socket;
1249   SocketHead = socket;
1250   OS_MutexPost(IPMutex);
1251
1252   if(mode == IP_MODE_TCP && ipAddress)
1253   {
1254      //Send TCP SYN
1255      socket->seq = 0x01234567;
1256      frame = IPFrameGet(0);
1257      if(frame)
1258      {
1259         frame->packet[TCP_FLAGS] = TCP_FLAGS_SYN;
1260         frame->packet[TCP_DATA] = 2; //maximum segment size = 536
1261         frame->packet[TCP_DATA+1] = 4;
1262         frame->packet[TCP_DATA+2] = 2;
1263         frame->packet[TCP_DATA+3] = 24;
1264         TCPSendPacket(socket, frame, TCP_DATA+4);
1265         ++socket->seq;
1266      }
1267   }
1268   return socket;
1269}
1270
1271
1272void IPWriteFlush(IPSocket *socket)
1273{
1274   uint8 *packetOut;
1275   if(socket->frameSend && socket->state != IP_UDP &&
1276      socket->state != IP_PING)
1277   {
1278      packetOut = socket->frameSend->packet;
1279      packetOut[TCP_FLAGS] = TCP_FLAGS_ACK | TCP_FLAGS_PSH;
1280      TCPSendPacket(socket, socket->frameSend, TCP_DATA + socket->sendOffset);
1281      socket->seq += socket->sendOffset;
1282      socket->frameSend = NULL;
1283      socket->sendOffset = 0;
1284   }
1285}
1286
1287
1288uint32 IPWrite(IPSocket *socket, const uint8 *buf, uint32 length)
1289{
1290   IPFrame *frameOut;
1291   uint8 *packetOut;
1292   uint32 bytes, count=0, tries=0;
1293   int offset;
1294   OS_Thread_t *self;
1295
1296   if(socket->timeout)
1297      socket->timeout = socket->timeoutReset;
1298
1299#ifdef INCLUDE_FILESYS
1300   if(socket->fileOut) //override stdout
1301      return fwrite((char*)buf, 1, length, socket->fileOut);
1302#endif
1303 
1304   //printf("IPWrite(0x%x, %d)", Socket, Length);
1305   self = OS_ThreadSelf();
1306   while(length)
1307   {
1308      //Rate limit output
1309      if(socket->seq - socket->seqReceived >= SEND_WINDOW)
1310      {
1311         //printf("l(%d,%d,%d) ", socket->seq - socket->seqReceived, socket->seq, socket->seqReceived);
1312         if(self != IPThread && ++tries < 200)
1313         {
1314            OS_ThreadSleep(1);
1315            continue;
1316         }
1317      }
1318      tries = 0;
1319      while(socket->frameSend == NULL)
1320      {
1321         socket->frameSend = IPFrameGet(FRAME_COUNT_SEND);
1322         socket->sendOffset = 0;
1323         if(socket->frameSend == NULL)
1324         {
1325            //printf("L");
1326            if(self == IPThread || ++tries > 200)
1327               break;
1328            else
1329               OS_ThreadSleep(1);
1330         }
1331      }
1332      frameOut = socket->frameSend;
1333      offset = socket->sendOffset;
1334      if(frameOut == NULL)
1335         break;
1336      packetOut = frameOut->packet;
1337
1338      if(socket->state == IP_PING)
1339      {
1340         bytes = length;
1341         memcpy(packetOut, socket->headerSend, PING_DATA);
1342         memcpy(packetOut+PING_DATA, buf, bytes);
1343         IPSendPacket(socket, socket->frameSend, PING_DATA + bytes);
1344         socket->frameSend = NULL;
1345      }
1346      else if(socket->state != IP_UDP)
1347      {
1348         bytes = 512 - offset;
1349         if(bytes > length)
1350            bytes = length;
1351         socket->sendOffset += bytes;
1352         memcpy(packetOut+TCP_DATA+offset, buf, bytes);
1353         if(socket->sendOffset >= 512)
1354            IPWriteFlush(socket);
1355         //if(Socket->seq - Socket->seqReceived > Socket->seqWindow)
1356         //{
1357         // printf("W");
1358         // OS_ThreadSleep(10);
1359         //}
1360      }
1361      else //UDP
1362      {
1363         bytes = length;
1364         memcpy(packetOut+UDP_DATA+offset, buf, bytes);
1365         memcpy(packetOut, socket->headerSend, UDP_LENGTH);
1366         IPSendPacket(socket, socket->frameSend, UDP_DATA + bytes);
1367         socket->frameSend = NULL;
1368      }
1369      count += bytes;
1370      buf += bytes;
1371      length -= bytes;
1372   }
1373   return count;
1374}
1375
1376
1377uint32 IPRead(IPSocket *socket, uint8 *buf, uint32 length)
1378{
1379   IPFrame *frame, *frame2;
1380   int count=0, bytes, offset;
1381
1382#ifdef INCLUDE_FILESYS
1383   if(socket->fileIn) //override stdin
1384   {
1385      bytes = fread(buf, 1, 1, socket->fileIn);
1386      if(bytes == 0)
1387      {
1388         buf[0] = 0;
1389         fclose(socket->fileIn);
1390         socket->fileIn = NULL;
1391         bytes = 1;
1392      }
1393      return bytes;
1394   }
1395#endif
1396
1397   if(socket->state == IP_UDP)
1398      offset = UDP_DATA;
1399   else
1400      offset = TCP_DATA;
1401
1402   OS_MutexPend(IPMutex);
1403   for(frame = socket->frameReadTail; length && frame; )
1404   {
1405      bytes = frame->length - offset - socket->readOffset;
1406      if(bytes > (int)length)
1407         bytes = length;
1408      memcpy(buf, frame->packet + offset + socket->readOffset, bytes);
1409      buf += bytes;
1410      socket->readOffset += bytes;
1411      length -= bytes;
1412      count += bytes;
1413
1414      //Check if done with packet
1415      frame2 = frame;
1416      frame = frame->prev;
1417      if(socket->readOffset == frame2->length - offset)
1418      {
1419         //Remove packet from socket linked list
1420         socket->readOffset = 0;
1421         FrameRemove(&socket->frameReadHead, &socket->frameReadTail, frame2);
1422         socket->ackProcessed += frame2->length - offset;
1423         if(socket->state == IP_TCP &&
1424            socket->ack - socket->ackProcessed > RECEIVE_WINDOW - 2048)
1425         {
1426            //Update receive window for flow control
1427            frame2->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
1428            TCPSendPacket(socket, frame2, TCP_DATA);
1429         }
1430         else
1431            FrameFree(frame2);
1432      }
1433   }
1434   OS_MutexPost(IPMutex);
1435   return count;
1436}
1437
1438
1439static void IPClose2(IPSocket *socket)
1440{
1441   IPFrame *frame, *framePrev;
1442
1443   OS_MutexPend(IPMutex);
1444
1445   //Mark packets as don't retransmit
1446   for(frame = FrameSendHead; frame; frame = frame->next)
1447   {
1448      if(frame->socket == socket)
1449         frame->socket = NULL;
1450   }
1451
1452   //Remove packets from retransmision list
1453   for(frame = FrameResendHead; frame; )
1454   {
1455      framePrev = frame;
1456      frame = frame->next;
1457      if(framePrev->socket == socket)
1458      {
1459         FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);
1460         FrameFree(framePrev);
1461      }
1462   }
1463
1464   //Remove packets from socket read linked list
1465   for(frame = socket->frameReadHead; frame; )
1466   {
1467      framePrev = frame;
1468      frame = frame->next;
1469      FrameRemove(&socket->frameReadHead, &socket->frameReadTail, framePrev);
1470      FrameFree(framePrev);
1471   }
1472
1473   //Remove socket
1474   if(socket->state == IP_CLOSED || socket->state <= IP_UDP)
1475   {
1476      if(socket->prev == NULL)
1477         SocketHead = socket->next;
1478      else
1479         socket->prev->next = socket->next;
1480      if(socket->next)
1481         socket->next->prev = socket->prev;
1482      free(socket);
1483   }
1484   else
1485   {
1486      //Give application 10 seconds to stop using socket
1487      if(socket->state > IP_UDP)
1488         socket->state = IP_CLOSED;
1489      socket->timeout = 10;
1490   }
1491   OS_MutexPost(IPMutex);
1492}
1493
1494
1495void IPClose(IPSocket *socket)
1496{
1497   IPFrame *frameOut;
1498
1499   IPWriteFlush(socket);
1500   if(socket->state <= IP_UDP)
1501   {
1502      IPClose2(socket);
1503      return;
1504   }
1505   frameOut = IPFrameGet(0);
1506   if(frameOut == NULL)
1507      return;
1508   frameOut->packet[TCP_FLAGS] = TCP_FLAGS_FIN | TCP_FLAGS_ACK;
1509   TCPSendPacket(socket, frameOut, TCP_DATA);
1510   ++socket->seq;
1511   if(socket->state == IP_FIN_CLIENT)
1512      IPClose2(socket);
1513   else
1514      socket->state = IP_FIN_SERVER;
1515}
1516
1517
1518void IPPrintf(IPSocket *socket, char *message,
1519              int arg0, int arg1, int arg2, int arg3)
1520{
1521   char buf[500];
1522   if(socket == NULL)
1523   {
1524      printf(message, arg0, arg1, arg2, arg3);
1525      return;
1526   }
1527   if(strcmp(message, "%s") == 0)
1528      IPWrite(socket, (uint8*)arg0, (int)strlen((char*)arg0));
1529   else
1530   {
1531      sprintf(buf, message, arg0, arg1, arg2, arg3, 0, 0, 0, 0);
1532      IPWrite(socket, (uint8*)buf, (int)strlen(buf));
1533   }
1534   if(socket->dontFlush == 0 || strstr(message, "\n"))
1535      IPWriteFlush(socket);
1536}
1537
1538
1539void IPTick(void)
1540{
1541   IPFrame *frame, *frame2;
1542   IPSocket *socket, *socket2;
1543   unsigned long ticks;
1544   static unsigned long ticksPrev=0, ticksPrev2=0;
1545
1546   ticks = OS_ThreadTime();
1547#ifdef WIN32
1548   ticks = ticksPrev + 100;
1549#endif
1550   if(ticks - ticksPrev >= 95)
1551   {
1552      if(IPVerbose && (Seconds % 60) == 0)
1553      {
1554         if(FrameFreeCount >= FRAME_COUNT-1)
1555            printf("T");
1556         else
1557            printf("T(%d)", FrameFreeCount);
1558      }
1559      ++Seconds;
1560      if(--DhcpRetrySeconds <= 0)
1561         IPDhcp(NULL, 400, 1); //DHCP request
1562   }
1563
1564   OS_MutexPend(IPMutex);
1565
1566   //Retransmit timeout packets
1567   for(frame = FrameResendHead; frame; )
1568   {
1569      frame2 = frame;
1570      frame = frame->next;
1571      frame2->timeout = (short)(frame2->timeout - (ticks - ticksPrev2));
1572      if(--frame2->timeout <= 0)
1573      {
1574         if(IPVerbose)
1575            printf("r");
1576         FrameRemove(&FrameResendHead, &FrameResendTail, frame2);
1577         IPSendFrame(frame2);
1578      }
1579   }
1580
1581   if(ticks - ticksPrev >= 95)
1582   {
1583      //Close timed out sockets
1584      for(socket = SocketHead; socket; )
1585      {
1586         socket2 = socket;
1587         socket = socket->next;
1588         if(socket2->timeout && --socket2->timeout == 0)
1589         {
1590            socket2->timeout = 10;
1591            if(IPVerbose && socket2->state != IP_CLOSED &&
1592                            socket2->state != IP_FIN_SERVER)
1593               printf("t(%d,%d)", socket2->state, FrameFreeCount);
1594            if(socket2->state == IP_TCP)
1595               IPClose(socket2);
1596            else if(socket2->state == IP_FIN_CLIENT)
1597               IPClose(socket2);
1598            else
1599               IPClose2(socket2);
1600         }
1601      }
1602      ticksPrev = ticks;
1603   }
1604   OS_MutexPost(IPMutex);
1605   ticksPrev2 = ticks;
1606}
1607
1608
1609static void DnsCallback(IPSocket *socket)
1610{
1611   uint8 buf[200], *ptr;
1612   uint32 ipAddress;
1613   int bytes;
1614
1615   memset(buf, 0, sizeof(buf));
1616   bytes = IPRead(socket, buf, sizeof(buf));
1617   if(buf[DNS_NUM_ANSWERS_RR+1])
1618   {
1619      for(ptr = buf + DNS_QUESTIONS; ptr + 14 <= buf + bytes; ++ptr)
1620      {
1621         if(ptr[0] == 0 && ptr[1] == 1 && ptr[2] == 0 && ptr[3] == 1 &&
1622            ptr[8] == 0 && ptr[9] == 4)
1623         {
1624            ipAddress = (ptr[10] << 24) | (ptr[11] << 16) | (ptr[12] << 8) | ptr[13];
1625            printf("ipAddress = %d.%d.%d.%d\n", ptr[10], ptr[11], ptr[12], ptr[13]);
1626            socket->userData = ipAddress;
1627            if(socket->userFunc)
1628            {
1629               socket->userFunc(socket, ipAddress, socket->userPtr);
1630            }
1631            break;
1632         }
1633      }
1634   }
1635   IPClose(socket);
1636}
1637
1638
1639void IPResolve(char *name, IPFuncPtr resolvedFunc, void *arg)
1640{
1641   uint8 buf[200], *ptr;
1642   int length, i;
1643   IPSocket *socket;
1644
1645   socket = IPOpen(IP_MODE_UDP, ipAddressDns, DNS_PORT, DnsCallback);
1646   memset(buf, 0, sizeof(buf));
1647   buf[DNS_ID+1] = 1;
1648   buf[DNS_FLAGS] = 1;
1649   buf[DNS_NUM_QUESTIONS+1] = 1;
1650
1651   //Setup name
1652   ptr = buf + DNS_QUESTIONS;
1653   strncpy((char*)ptr+1, name, 100);
1654   ptr[0] = 1;
1655   while(ptr[0])
1656   {
1657      for(i = 0; i < 100; ++i)
1658      {
1659         if(ptr[i+1] == '.' || ptr[i+1] == 0)
1660         {
1661            ptr[0] = (uint8)i;
1662            ptr += i+1;
1663            break;
1664         }
1665      }
1666   }
1667   ++ptr;
1668   ptr[1] = DNS_QUERY_TYPE_IP;
1669   ptr[3] = DNS_QUERY_CLASS;
1670   length = (int)(ptr - buf) + 4;
1671   if(length < 60)
1672      length = 60;
1673
1674   socket->userFunc = (IPFuncPtr)resolvedFunc;
1675   socket->userPtr = arg;
1676   socket->userData = 0;
1677   IPWrite(socket, buf, length);
1678}
1679
1680

Archive Download this file

Branches:
master



interactive