Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
363 johboh 1
/*********************************************************************
2
*
3
*                  TCP Module for Microchip TCP/IP Stack
4
*                   Based on RFC 793
5
*
6
*********************************************************************
7
* FileName:        TCP.C
8
* Dependencies:    string.h
9
*                  StackTsk.h
10
*                  Helpers.h
11
*                  IP.h
12
*                  MAC.h
13
*                  ARP.h
14
*                  Tick.h
15
*                  TCP.h
16
* Processor:       PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F
17
* Complier:        Microchip C18 v3.02 or higher
18
*                   Microchip C30 v2.01 or higher
19
* Company:         Microchip Technology, Inc.
20
*
21
* Software License Agreement
22
*
23
* This software is owned by Microchip Technology Inc. ("Microchip")
24
* and is supplied to you for use exclusively as described in the
25
* associated software agreement.  This software is protected by
26
* software and other intellectual property laws.  Any use in
27
* violation of the software license may subject the user to criminal
28
* sanctions as well as civil liability.  Copyright 2006 Microchip
29
* Technology Inc.  All rights reserved.
30
*
31
* This software is provided "AS IS."  MICROCHIP DISCLAIMS ALL
32
* WARRANTIES, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, NOT LIMITED
33
* TO MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
34
* INFRINGEMENT.  Microchip shall in no event be liable for special,
35
* incidental, or consequential damages.
36
*
37
 *
38
 * Author               Date    Comment
39
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40
 * Nilesh Rajbharti     5/8/01  Original        (Rev 1.0)
41
 * Nilesh Rajbharti     5/22/02 Rev 2.0 (See version.log for detail)
42
 * Nilesh Rajbharti     11/1/02 Fixed TCPTick() SYN Retry bug.
43
 * Nilesh Rajbharti     12/5/02 Modified TCPProcess()
44
 *                              to include localIP as third param.
45
 *                              This was done to allow this function
46
 *                              to calculate checksum correctly.
47
 * Roy Schofield        10/1/04 TCPConnect() startTick bug fix.
48
 * Howard Schlunder     1/3/05  Fixed HandleTCPSeg() unexpected
49
 *                              discard problem identified by Richard
50
 *                              Shelquist.
51
 * Howard Schlunder     1/16/06 Fixed an imporbable RX checksum bug
52
 *                              when using a Microchip Ethernet controller)
53
 * Howard Schlunder     5/10/06 Revised TCP state machine, add TCP_FIN_2
54
 * Howard Schlunder     8/01/06 Adjusted response to ACK only in TCP_SYN_SENT state
55
 * Howard Schlunder     8/03/06 Fixed checksum comparison check
56
 *                              reported by DouglasPunch on Microchip Forum.
57
 * Howard Schlunder     8/11/06 Fixed a resource leak causing MAC TX
58
 *                              Buffers to be obtained but not
59
 *                              released when many web requests were
60
 *                              received concurrently.
61
********************************************************************/
62
#define THIS_IS_TCP
63
 
64
#include <string.h>
65
 
66
#include "..\Include\StackTsk.h"
67
#include "..\Include\Helpers.h"
68
#include "..\Include\IP.h"
69
#include "..\Include\MAC.h"
70
#include "..\Include\Tick.h"
71
#include "..\Include\TCP.h"
72
 
73
#if defined(STACK_USE_TCP)
74
 
75
// Max TCP data length is MAC_TX_BUFFER_SIZE - sizeof(TCP_HEADER) -
76
// sizeof(IP_HEADER) - sizeof(ETHER_HEADER)
77
#define MAX_TCP_DATA_LEN        (MAC_TX_BUFFER_SIZE - 54)
78
 
79
// TCP Timeout value to begin with.
80
#define TCP_START_TIMEOUT_VAL   ((TICK)TICK_1S * (TICK)3)
81
 
82
// TCP Flags defined in RFC
83
#define FIN     (0x01)
84
#define SYN     (0x02)
85
#define RST     (0x04)
86
#define PSH     (0x08)
87
#define ACK     (0x10)
88
#define URG     (0x20)
89
 
90
// TCP Header
91
typedef struct _TCP_HEADER
92
{
93
    WORD    SourcePort;
94
    WORD    DestPort;
95
    DWORD   SeqNumber;
96
    DWORD   AckNumber;
97
 
98
    struct
99
    {
100
        unsigned char Reserved3      : 4;
101
        unsigned char Val            : 4;
102
    } DataOffset;
103
 
104
    union
105
    {
106
        struct
107
        {
108
            unsigned char flagFIN    : 1;
109
            unsigned char flagSYN    : 1;
110
            unsigned char flagRST    : 1;
111
            unsigned char flagPSH    : 1;
112
            unsigned char flagACK    : 1;
113
            unsigned char flagURG    : 1;
114
            unsigned char Reserved2  : 2;
115
        } bits;
116
        BYTE byte;
117
    } Flags;
118
 
119
    WORD    Window;
120
    WORD    Checksum;
121
    WORD    UrgentPointer;
122
} TCP_HEADER;
123
 
124
// TCP Options as defined by RFC
125
#define TCP_OPTIONS_END_OF_LIST     (0x00)
126
#define TCP_OPTIONS_NO_OP           (0x01)
127
#define TCP_OPTIONS_MAX_SEG_SIZE    (0x02)
128
typedef struct _TCP_OPTIONS
129
{
130
    BYTE        Kind;
131
    BYTE        Length;
132
    WORD_VAL    MaxSegSize;
133
} TCP_OPTIONS;
134
 
135
#define SwapPseudoTCPHeader(h)  (h.TCPLength = swaps(h.TCPLength))
136
// IP pseudo header as defined by RFC 793
137
typedef struct _PSEUDO_HEADER
138
{
139
    IP_ADDR SourceAddress;
140
    IP_ADDR DestAddress;
141
    BYTE Zero;
142
    BYTE Protocol;
143
    WORD TCPLength;
144
} PSEUDO_HEADER;
145
 
146
#define LOCAL_PORT_START_NUMBER (1024)
147
#define LOCAL_PORT_END_NUMBER   (5000)
148
 
149
 
150
// Local temp port numbers.
151
#ifdef STACK_CLIENT_MODE
152
static WORD _NextPort = LOCAL_PORT_START_NUMBER;
153
#endif
154
 
155
// The TCB array is very large.  With the C18 compiler, one must 
156
// modify the linker script to make an array that spans more than 
157
// one memory bank.  To do this, make the necessary changes to your 
158
// processor's linker script (.lkr).  Here is an example showing 
159
// gpr11 and 128 bytes of gpr12 being combined into one 384 byte 
160
// block used exclusively by the TCB_MEM data section:
161
// ...
162
// //DATABANK   NAME=gpr11      START=0xB00          END=0xBFF
163
// //DATABANK   NAME=gpr12      START=0xC00          END=0xCFF
164
// DATABANK   NAME=gpr11b     START=0xB00          END=0xC7F           PROTECTED
165
// DATABANK   NAME=gpr12      START=0xC80          END=0xCFF
166
// ...
167
// SECTION    NAME=TCB_MEM    RAM=gpr11b
168
// ...
169
#pragma udata TCB_MEM
170
SOCKET_INFO TCB[MAX_SOCKETS];
171
#pragma udata bla   // Return to any other RAM section
172
 
173
static void HandleTCPSeg(TCP_SOCKET s,
174
                         NODE_INFO *remote,
175
                         TCP_HEADER *h,
176
                         WORD len);
177
 
178
static void TransmitTCP(NODE_INFO *remote,
179
                        TCP_PORT localPort,
180
                        TCP_PORT remotePort,
181
                        DWORD seq,
182
                        DWORD ack,
183
                        BYTE flags,
184
                        BUFFER buffer,
185
                        WORD len);
186
 
187
static TCP_SOCKET FindMatchingSocket(TCP_HEADER *h,
188
                                     NODE_INFO *remote);
189
static void SwapTCPHeader(TCP_HEADER* header);
190
static void CloseSocket(SOCKET_INFO* ps);
191
 
192
#define SendTCP(remote, localPort, remotePort, seq, ack, flags)     \
193
    TransmitTCP(remote, localPort, remotePort, seq, ack, flags, \
194
    INVALID_BUFFER, 0)
195
 
196
 
197
/*********************************************************************
198
* Function:        void TCPInit(void)
199
*
200
* PreCondition:    None
201
*
202
* Input:           None
203
*
204
* Output:          TCP is initialized.
205
*
206
* Side Effects:    None
207
*
208
* Overview:        Initialize all socket states
209
*
210
* Note:            This function is called only once during lifetime
211
*                  of the application.
212
********************************************************************/
213
void TCPInit(void)
214
{
215
    TCP_SOCKET s;
216
    SOCKET_INFO* ps;
217
 
218
    // Initialize all sockets.
219
    for(s = 0; s < MAX_SOCKETS; s++)
220
    {
221
        ps = &TCB[s];
222
 
223
        ps->smState             = TCP_CLOSED;
224
        ps->Flags.bServer       = FALSE;
225
        ps->Flags.bIsPutReady   = TRUE;
226
        ps->Flags.bFirstRead    = TRUE;
227
        ps->Flags.bIsTxInProgress = FALSE;
228
        ps->Flags.bIsGetReady   = FALSE;
229
        if(ps->TxBuffer != INVALID_BUFFER)
230
        {
231
            MACDiscardTx(ps->TxBuffer);
232
            ps->TxBuffer        = INVALID_BUFFER;
233
        }
234
        ps->TimeOut             = TCP_START_TIMEOUT_VAL;
235
        ps->TxCount             = 0;
236
    }
237
}
238
 
239
 
240
 
241
/*********************************************************************
242
* Function:        TCP_SOCKET TCPListen(TCP_PORT port)
243
*
244
* PreCondition:    TCPInit() is already called.
245
*
246
* Input:           port    - A TCP port to be opened.
247
*
248
* Output:          Given port is opened and returned on success
249
*                  INVALID_SOCKET if no more sockets left.
250
*
251
* Side Effects:    None
252
*
253
* Overview:        None
254
*
255
* Note:            None
256
********************************************************************/
257
TCP_SOCKET TCPListen(TCP_PORT port)
258
{
259
    TCP_SOCKET s;
260
    SOCKET_INFO* ps;
261
 
262
    for(s = 0; s < MAX_SOCKETS; s++)
263
    {
264
        ps = &TCB[s];
265
 
266
        if(ps->smState == TCP_CLOSED)
267
        {
268
            // We have a CLOSED socket.
269
            // Initialize it with LISTENing state info.
270
            ps->smState             = TCP_LISTEN;
271
            ps->localPort           = port;
272
            ps->remotePort          = 0;
273
 
274
            // There is no remote node IP address info yet.
275
            ps->remote.IPAddr.Val   = 0x00;
276
 
277
            // If a socket is listened on, it is a SERVER.
278
            ps->Flags.bServer       = TRUE;
279
 
280
            ps->Flags.bIsGetReady   = FALSE;
281
            if(ps->TxBuffer != INVALID_BUFFER)
282
            {
283
                MACDiscardTx(ps->TxBuffer);
284
                ps->TxBuffer        = INVALID_BUFFER;
285
            }
286
            ps->Flags.bIsPutReady   = TRUE;
287
 
288
            return s;
289
        }
290
    }
291
    return INVALID_SOCKET;
292
}
293
 
294
 
295
 
296
/*********************************************************************
297
* Function:        TCP_SOCKET TCPConnect(NODE_INFO* remote,
298
*                                      TCP_PORT remotePort)
299
*
300
* PreCondition:    TCPInit() is already called.
301
*
302
* Input:           remote      - Remote node address info
303
*                  remotePort  - remote port to be connected.
304
*
305
* Output:          A new socket is created, connection request is
306
*                  sent and socket handle is returned.
307
*
308
* Side Effects:    None
309
*
310
* Overview:        None
311
*
312
* Note:            By default this function is not included in
313
*                  source.  You must define STACK_CLIENT_MODE to
314
*                  be able to use this function.
315
********************************************************************/
316
#ifdef STACK_CLIENT_MODE
317
TCP_SOCKET TCPConnect(NODE_INFO *remote, TCP_PORT remotePort)
318
{
319
    TCP_SOCKET s;
320
    SOCKET_INFO* ps;
321
    BOOL lbFound;
322
 
323
 
324
    lbFound = FALSE;
325
 
326
    // Find an available socket
327
    for(s = 0; s < MAX_SOCKETS; s++)
328
    {
329
        ps = &TCB[s];
330
        if(ps->smState == TCP_CLOSED)
331
        {
332
            lbFound = TRUE;
333
            break;
334
        }
335
    }
336
 
337
    // If there is no socket available, return error.
338
    if(!lbFound)
339
        return INVALID_SOCKET;
340
 
341
    // Each new socket that is opened by this node, gets
342
    // next sequential port number.
343
    ps->localPort = ++_NextPort;
344
    if(_NextPort >= LOCAL_PORT_END_NUMBER)
345
        _NextPort = LOCAL_PORT_START_NUMBER-1;
346
 
347
    // This is a client socket.
348
    ps->Flags.bServer = FALSE;
349
 
350
    // This is the port, we are trying to connect to.
351
    ps->remotePort = remotePort;
352
 
353
    // Each new socket that is opened by this node, will
354
    // start with next the next seqeuence number (essentially random)
355
    ps->SND_SEQ++;
356
    ps->SND_ACK = 0;
357
 
358
    memcpy((BYTE*)&ps->remote, (const void*)remote, sizeof(ps->remote));
359
 
360
    // Send SYN message.
361
    SendTCP(&ps->remote,
362
        ps->localPort,
363
        ps->remotePort,
364
        ps->SND_SEQ,
365
        ps->SND_ACK,
366
        SYN);
367
 
368
    ps->smState = TCP_SYN_SENT;
369
    ps->SND_SEQ++;
370
 
371
    // Allow TCPTick() to operate properly
372
    ps->startTick = tickGet();  
373
 
374
    return s;
375
}
376
#endif
377
 
378
 
379
 
380
/*********************************************************************
381
* Function:        BOOL TCPIsConnected(TCP_SOCKET s)
382
*
383
* PreCondition:    TCPInit() is already called.
384
*
385
* Input:           s       - Socket to be checked for connection.
386
*
387
* Output:          TRUE    if given socket is connected
388
*                  FALSE   if given socket is not connected.
389
*
390
* Side Effects:    None
391
*
392
* Overview:        None
393
*
394
* Note:            A socket is said to be connected if it is not
395
*                  in LISTEN and CLOSED mode.  Socket may be in
396
*                  SYN_RCVD or FIN_WAIT_1 and may contain socket
397
*                  data.
398
********************************************************************/
399
BOOL TCPIsConnected(TCP_SOCKET s)
400
{
401
    return (TCB[s].smState == TCP_ESTABLISHED);
402
}
403
 
404
 
405
 
406
/*********************************************************************
407
* Function:        void TCPDisconnect(TCP_SOCKET s)
408
*
409
* PreCondition:    TCPInit() is already called     AND
410
*                  TCPIsPutReady(s) == TRUE
411
*
412
* Input:           s       - Socket to be disconnected.
413
*
414
* Output:          A disconnect request is sent for given socket.
415
*
416
* Side Effects:    None
417
*
418
* Overview:        None
419
*
420
* Note:            None
421
********************************************************************/
422
void TCPDisconnect(TCP_SOCKET s)
423
{
424
    SOCKET_INFO *ps;
425
 
426
    ps = &TCB[s];
427
 
428
    // If socket is not connected, may be it is already closed
429
    // or in the process of closing.  Since we have called this
430
    // explicitly, close it forcefully.
431
    if(ps->smState != TCP_ESTABLISHED && ps->smState != TCP_SYN_RECEIVED)
432
    {
433
        CloseSocket(ps);
434
        return;
435
    }
436
 
437
    // Discard any outstanding data that is to be read.
438
    TCPDiscard(s);
439
 
440
    // Send FIN message.
441
    SendTCP(&ps->remote,
442
        ps->localPort,
443
        ps->remotePort,
444
        ps->SND_SEQ,
445
        ps->SND_ACK,
446
        FIN | ACK);
447
//  DebugPrint(".");
448
 
449
    ps->SND_SEQ++;
450
 
451
    ps->smState = TCP_FIN_WAIT_1;
452
 
453
    return;
454
}
455
 
456
/*********************************************************************
457
* Function:        BOOL TCPFlush(TCP_SOCKET s)
458
*
459
* PreCondition:    TCPInit() is already called.
460
*
461
* Input:           s       - Socket whose data is to be transmitted.
462
*
463
* Output:          All and any data associated with this socket
464
*                  is marked as ready for transmission.
465
*
466
* Side Effects:    None
467
*
468
* Overview:        None
469
*
470
* Note:            None
471
********************************************************************/
472
BOOL TCPFlush(TCP_SOCKET s)
473
{
474
    SOCKET_INFO *ps;
475
 
476
    ps = &TCB[s];
477
 
478
    // Make sure that there is TxBuffer assigned to this socket.
479
    if ( ps->TxBuffer == INVALID_BUFFER )
480
        return FALSE;
481
 
482
    if ( ps->Flags.bIsPutReady == FALSE )
483
        return FALSE;
484
 
485
    TransmitTCP(&ps->remote,
486
        ps->localPort,
487
        ps->remotePort,
488
        ps->SND_SEQ,
489
        ps->SND_ACK,
490
        ACK + PSH,      // Use PSH to make sure the end application receives the data right away
491
        ps->TxBuffer,
492
        ps->TxCount);
493
    ps->SND_SEQ += (DWORD)ps->TxCount;
494
    ps->Flags.bIsPutReady       = FALSE;
495
    ps->Flags.bIsTxInProgress   = FALSE;
496
 
497
#ifdef TCP_NO_WAIT_FOR_ACK
498
    if(ps->TxBuffer != INVALID_BUFFER)
499
    {
500
        MACDiscardTx(ps->TxBuffer);
501
        ps->TxBuffer        = INVALID_BUFFER;
502
    }
503
    ps->Flags.bIsPutReady       = TRUE;
504
#endif
505
 
506
    return TRUE;
507
}
508
 
509
 
510
 
511
/*********************************************************************
512
* Function:        BOOL TCPIsPutReady(TCP_SOCKET s)
513
*
514
* PreCondition:    TCPInit() is already called.
515
*
516
* Input:           s       - socket to test
517
*
518
* Output:          TRUE if socket 's' is free to transmit
519
*                  FALSE if socket 's' is not free to transmit.
520
*
521
* Side Effects:    None
522
*
523
* Overview:        None
524
*
525
* Note:            Each socket maintains only transmit buffer.
526
*                  Hence until a data packet is acknowledeged by
527
*                  remote node, socket will not be ready for
528
*                  next transmission.
529
*                  All control transmission such as Connect,
530
*                  Disconnect do not consume/reserve any transmit
531
*                  buffer.
532
********************************************************************/
533
BOOL TCPIsPutReady(TCP_SOCKET s)
534
{
535
    if(TCB[s].RemoteWindow == 0)
536
        return FALSE;
537
 
538
    if ( TCB[s].TxBuffer == INVALID_BUFFER )
539
        return IPIsTxReady(FALSE);
540
    else
541
        return TCB[s].Flags.bIsPutReady;
542
}
543
 
544
 
545
 
546
 
547
/*********************************************************************
548
* Function:        BOOL TCPPut(TCP_SOCKET s, BYTE byte)
549
*
550
* PreCondition:    TCPIsPutReady() == TRUE
551
*
552
* Input:           s       - socket to use
553
*                  byte    - a data byte to send
554
*
555
* Output:          TRUE if given byte was put in transmit buffer
556
*                  FALSE if transmit buffer is full.
557
*
558
* Side Effects:    None
559
*
560
* Overview:        None
561
*
562
* Note:            None
563
********************************************************************/
564
BOOL TCPPut(TCP_SOCKET s, BYTE byte)
565
{
566
    SOCKET_INFO* ps;
567
 
568
    ps = &TCB[s];
569
 
570
    // Make sure that the remote node is able to accept our data
571
    if(ps->RemoteWindow == 0)
572
        return FALSE;
573
 
574
    if(ps->TxBuffer == INVALID_BUFFER)
575
    {
576
        ps->TxBuffer = MACGetTxBuffer(FALSE);
577
 
578
        // Check to make sure that we received a TX Buffer
579
        if(ps->TxBuffer == INVALID_BUFFER)
580
            return FALSE;
581
 
582
        ps->TxCount = 0;
583
 
584
        IPSetTxBuffer(ps->TxBuffer, sizeof(TCP_HEADER));
585
    }
586
 
587
    ps->Flags.bIsTxInProgress = TRUE;
588
 
589
    MACPut(byte);
590
    ps->RemoteWindow--;
591
 
592
    if(++ps->TxCount >= MAX_TCP_DATA_LEN)
593
        TCPFlush(s);
594
 
595
    return TRUE;
596
}
597
 
598
/*********************************************************************
599
* Function:        BOOL TCPDiscard(TCP_SOCKET s)
600
*
601
* PreCondition:    TCPInit() is already called.
602
*
603
* Input:           s       - socket
604
*
605
* Output:          TRUE if socket received data was discarded
606
*                  FALSE if socket received data was already
607
*                          discarded.
608
*
609
* Side Effects:    None
610
*
611
* Overview:        None
612
*
613
* Note:            None
614
********************************************************************/
615
BOOL TCPDiscard(TCP_SOCKET s)
616
{
617
    SOCKET_INFO* ps;
618
 
619
    ps = &TCB[s];
620
 
621
    // This socket must contain data for it to be discarded.
622
    if(!ps->Flags.bIsGetReady)
623
        return FALSE;
624
 
625
    MACDiscardRx();
626
    ps->Flags.bIsGetReady = FALSE;
627
 
628
    return TRUE;
629
}
630
 
631
 
632
 
633
 
634
/*********************************************************************
635
* Function:        WORD TCPGetArray(TCP_SOCKET s, BYTE *buffer,
636
*                                      WORD count)
637
*
638
* PreCondition:    TCPInit() is already called     AND
639
*                  TCPIsGetReady(s) == TRUE
640
*
641
* Input:           s       - socket
642
*                  buffer  - Buffer to hold received data.
643
*                  count   - Buffer length
644
*
645
* Output:          Number of bytes loaded into buffer.
646
*
647
* Side Effects:    None
648
*
649
* Overview:        None
650
*
651
* Note:            None
652
********************************************************************/
653
WORD TCPGetArray(TCP_SOCKET s, BYTE *buffer, WORD count)
654
{
655
    SOCKET_INFO *ps;
656
 
657
    ps = &TCB[s];
658
 
659
    if ( ps->Flags.bIsGetReady )
660
    {
661
        if ( ps->Flags.bFirstRead )
662
        {
663
            // Position read pointer to begining of TCP data
664
            IPSetRxBuffer(sizeof(TCP_HEADER));
665
 
666
            ps->Flags.bFirstRead = FALSE;
667
        }
668
 
669
        ps->Flags.bIsTxInProgress = TRUE;
670
 
671
        return MACGetArray(buffer, count);
672
    }
673
    else
674
        return 0;
675
}
676
 
677
 
678
 
679
/*********************************************************************
680
* Function:        BOOL TCPGet(TCP_SOCKET s, BYTE *byte)
681
*
682
* PreCondition:    TCPInit() is already called     AND
683
*                  TCPIsGetReady(s) == TRUE
684
*
685
* Input:           s       - socket
686
*                  byte    - Pointer to a byte.
687
*
688
* Output:          TRUE if a byte was read.
689
*                  FALSE if byte was not read.
690
*
691
* Side Effects:    None
692
*
693
* Overview:        None
694
*
695
* Note:            None
696
********************************************************************/
697
BOOL TCPGet(TCP_SOCKET s, BYTE *byte)
698
{
699
    SOCKET_INFO* ps;
700
 
701
    ps = &TCB[s];
702
 
703
    if ( ps->Flags.bIsGetReady )
704
    {
705
        if ( ps->Flags.bFirstRead )
706
        {
707
            // Position read pointer to begining of correct
708
            // buffer.
709
            IPSetRxBuffer(sizeof(TCP_HEADER));
710
 
711
            ps->Flags.bFirstRead = FALSE;
712
 
713
        }
714
 
715
        if ( ps->RxCount == 0 )
716
        {
717
            MACDiscardRx();
718
            ps->Flags.bIsGetReady = FALSE;
719
            return FALSE;
720
        }
721
 
722
        ps->RxCount--;
723
        *byte = MACGet();
724
        return TRUE;
725
    }
726
    return FALSE;
727
}
728
 
729
 
730
 
731
/*********************************************************************
732
* Function:        BOOL TCPIsGetReady(TCP_SOCKET s)
733
*
734
* PreCondition:    TCPInit() is already called.
735
*
736
* Input:           s       - socket to test
737
*
738
* Output:          TRUE if socket 's' contains any data.
739
*                  FALSE if socket 's' does not contain any data.
740
*
741
* Side Effects:    None
742
*
743
* Overview:        None
744
*
745
* Note:            None
746
********************************************************************/
747
BOOL TCPIsGetReady(TCP_SOCKET s)
748
{
749
    /*
750
    * A socket is said to be "Get" ready when it has already
751
    * received some data.  Sometime, a socket may be closed,
752
    * but it still may contain data.  Thus in order to ensure
753
    * reuse of a socket, caller must make sure that it reads
754
    * a socket, if is ready.
755
    */
756
    return(TCB[s].Flags.bIsGetReady);
757
}
758
 
759
 
760
 
761
/*********************************************************************
762
* Function:        void TCPTick(void)
763
*
764
* PreCondition:    TCPInit() is already called.
765
*
766
* Input:           None
767
*
768
* Output:          Each socket FSM is executed for any timeout
769
*                  situation.
770
*
771
* Side Effects:    None
772
*
773
* Overview:        None
774
*
775
* Note:            None
776
********************************************************************/
777
void TCPTick(void)
778
{
779
    TCP_SOCKET s;
780
    TICK diffTicks;
781
    TICK tick;
782
    SOCKET_INFO* ps;
783
    DWORD seq;
784
    BYTE flags;
785
 
786
    flags = 0x00;
787
    // Periodically all "not closed" sockets must perform timed operations
788
    for(s = 0; s < MAX_SOCKETS; s++)
789
    {
790
        ps = &TCB[s];
791
 
792
        if ( ps->Flags.bIsGetReady || ps->Flags.bIsTxInProgress )
793
            continue;
794
 
795
 
796
        // Closed or Passively Listening socket do not care
797
        // about timeout conditions.
798
        if ( (ps->smState == TCP_CLOSED) ||
799
            (ps->smState == TCP_LISTEN &&
800
            ps->Flags.bServer == TRUE) )
801
            continue;
802
 
803
        tick = tickGet();
804
 
805
        // Calculate timeout value for this socket.
806
        diffTicks = tick-ps->startTick;
807
 
808
        // If timeout has not occured, do not do anything.
809
        if(diffTicks <= ps->TimeOut)
810
            continue;
811
 
812
        // Most states require retransmission, so check for transmitter
813
        // availability right here - common for all.
814
        if(!IPIsTxReady(TRUE))
815
            return;
816
 
817
        // Restart timeout reference.
818
        ps->startTick = tickGet();
819
 
820
        // Update timeout value if there is need to wait longer.
821
        ps->TimeOut <<= 1;
822
 
823
        // This will be one more attempt.
824
        ps->RetryCount++;
825
 
826
        // A timeout has occured.  Respond to this timeout condition
827
        // depending on what state this socket is in.
828
        switch(ps->smState)
829
        {
830
        case TCP_SYN_SENT:
831
            // Keep sending SYN until we hear from remote node.
832
            // This may be for infinite time, in that case
833
            // caller must detect it and do something.
834
            // Bug Fix: 11/1/02
835
            flags = SYN;
836
            break;
837
 
838
        case TCP_SYN_RECEIVED:
839
            // We must receive ACK before timeout expires.
840
            // If not, resend SYN+ACK.
841
            // Abort, if maximum attempts counts are reached.
842
            if(ps->RetryCount <= MAX_RETRY_COUNTS)
843
            {
844
                flags = SYN | ACK;
845
            }
846
            else
847
            {
848
                if(ps->Flags.bServer)
849
                {
850
                    ps->smState = TCP_LISTEN;
851
                }
852
                else
853
                {
854
                    flags = SYN;
855
                    ps->smState = TCP_SYN_SENT;
856
                }
857
            }
858
            break;
859
 
860
        case TCP_ESTABLISHED:
861
#if !defined(TCP_NO_WAIT_FOR_ACK)
862
            // Don't let this connection idle for very long time.
863
            // If we did not receive or send any message before timeout
864
            // expires, close this connection.
865
            if(ps->RetryCount <= MAX_RETRY_COUNTS)
866
            {
867
                if(ps->TxBuffer != INVALID_BUFFER)
868
                {
869
                    MACSetTxBuffer(ps->TxBuffer, 0);
870
                    MACFlush();
871
                }
872
                else
873
                    flags = ACK;
874
            }
875
            else
876
            {
877
                // Forget about previous transmission.
878
                if(ps->TxBuffer != INVALID_BUFFER)
879
                {
880
                    MACDiscardTx(ps->TxBuffer);
881
                    ps->TxBuffer = INVALID_BUFFER;
882
                }
883
 
884
#endif
885
                // Request closure.
886
                flags = FIN | ACK;
887
//              DebugPrint("!");
888
 
889
                ps->smState = TCP_FIN_WAIT_1;
890
#if !defined(TCP_NO_WAIT_FOR_ACK)
891
            }
892
#endif
893
            break;
894
 
895
        case TCP_FIN_WAIT_1:
896
            if(ps->RetryCount <= MAX_RETRY_COUNTS)
897
            {
898
                    // Send another FIN
899
                    flags = FIN;
900
            }
901
            else
902
            {
903
                // Close on our own, we can't seem to communicate 
904
                // with the remote node anymore
905
                CloseSocket(ps);
906
            }
907
            break;
908
 
909
        case TCP_FIN_WAIT_2:
910
        case TCP_CLOSING:
911
            // Close on our own, we can't seem to communicate 
912
            // with the remote node anymore
913
            CloseSocket(ps);
914
            break;
915
 
916
        case TCP_TIME_WAIT:
917
            // Wait around for a while (2MSL) and then goto closed state
918
            CloseSocket(ps);
919
            break;
920
 
921
        case TCP_CLOSE_WAIT:
922
            flags = FIN;
923
            ps->smState = TCP_LAST_ACK;
924
            break;
925
 
926
        case TCP_LAST_ACK:
927
            // Send some more FINs or close anyway
928
            if(ps->RetryCount <= MAX_RETRY_COUNTS)
929
                flags = FIN;
930
            else
931
                CloseSocket(ps);
932
            break;
933
        }
934
 
935
 
936
        if(flags)
937
        {
938
            if(flags & ACK)
939
                seq = ps->SND_SEQ;
940
            else
941
                seq = ps->SND_SEQ++;
942
 
943
            SendTCP(&ps->remote,
944
                ps->localPort,
945
                ps->remotePort,
946
                seq,
947
                ps->SND_ACK,
948
                flags);
949
        }
950
    }
951
}
952
 
953
 
954
 
955
/*********************************************************************
956
* Function:        BOOL TCPProcess(NODE_INFO* remote,
957
*                                  IP_ADDR *localIP,
958
*                                  WORD len)
959
*
960
* PreCondition:    TCPInit() is already called     AND
961
*                  TCP segment is ready in MAC buffer
962
*
963
* Input:           remote      - Remote node info
964
*                  len         - Total length of TCP semgent.
965
*
966
* Output:          TRUE if this function has completed its task
967
*                  FALSE otherwise
968
*
969
* Side Effects:    None
970
*
971
* Overview:        None
972
*
973
* Note:            None
974
********************************************************************/
975
BOOL TCPProcess(NODE_INFO *remote, IP_ADDR *localIP, WORD len)
976
{
977
    TCP_HEADER      TCPHeader;
978
    PSEUDO_HEADER   pseudoHeader;
979
    TCP_SOCKET      socket;
980
    WORD_VAL        checksum1;
981
    WORD_VAL        checksum2;
982
    BYTE            optionsSize;
983
 
984
    // Calculate IP pseudoheader checksum.
985
    pseudoHeader.SourceAddress      = remote->IPAddr;
986
    pseudoHeader.DestAddress        = *localIP;
987
    pseudoHeader.Zero               = 0x0;
988
    pseudoHeader.Protocol           = IP_PROT_TCP;
989
    pseudoHeader.TCPLength          = len;
990
 
991
    SwapPseudoTCPHeader(pseudoHeader);
992
 
993
    checksum1.Val = ~CalcIPChecksum((BYTE*)&pseudoHeader,
994
        sizeof(pseudoHeader));
995
 
996
 
997
    // Now calculate TCP packet checksum in NIC RAM - should match
998
    // pesudo header checksum
999
    checksum2.Val = CalcIPBufferChecksum(len);
1000
 
1001
    // Compare checksums.  Note that the endianness is different.
1002
    if(checksum1.v[0] != checksum2.v[1] || checksum1.v[1] != checksum2.v[0])
1003
    {
1004
        MACDiscardRx();
1005
        return TRUE;
1006
    }
1007
 
1008
    // Retrieve TCP header.
1009
    IPSetRxBuffer(0);
1010
    MACGetArray((BYTE*)&TCPHeader, sizeof(TCPHeader));
1011
    SwapTCPHeader(&TCPHeader);
1012
 
1013
 
1014
    // Skip over options and retrieve all data bytes.
1015
    optionsSize = (BYTE)((TCPHeader.DataOffset.Val << 2)-
1016
        sizeof(TCPHeader));
1017
    len = len - optionsSize - sizeof(TCPHeader);
1018
 
1019
    // Position packet read pointer to start of data area.
1020
    IPSetRxBuffer((TCPHeader.DataOffset.Val << 2));
1021
 
1022
    // Find matching socket.
1023
    socket = FindMatchingSocket(&TCPHeader, remote);
1024
    if(socket != INVALID_SOCKET)
1025
    {
1026
        HandleTCPSeg(socket, remote, &TCPHeader, len);
1027
    }
1028
    else
1029
    {
1030
        // If this is an unknown socket, or we don't have any 
1031
        // listening sockets available, discard it we can't 
1032
        // process it right now
1033
        MACDiscardRx();
1034
 
1035
//      // Send a RESET to the remote node is it knows that we 
1036
//      // are not available
1037
//      TCPHeader.AckNumber += len;
1038
//      if( TCPHeader.Flags.bits.flagSYN ||
1039
//          TCPHeader.Flags.bits.flagFIN )
1040
//          TCPHeader.AckNumber++;
1041
//      
1042
//      SendTCP(remote,
1043
//          TCPHeader.DestPort,
1044
//          TCPHeader.SourcePort,
1045
//          TCPHeader.AckNumber,
1046
//          TCPHeader.SeqNumber,
1047
//          RST);
1048
    }
1049
 
1050
    return TRUE;
1051
}
1052
 
1053
 
1054
/*********************************************************************
1055
* Function:        static void TransmitTCP(NODE_INFO* remote
1056
*                                          TCP_PORT localPort,
1057
*                                          TCP_PORT remotePort,
1058
*                                          DWORD seq,
1059
*                                          DWORD ack,
1060
*                                          BYTE flags,
1061
*                                          BUFFER buffer,
1062
*                                          WORD len)
1063
*
1064
* PreCondition:    TCPInit() is already called     AND
1065
*                  TCPIsPutReady() == TRUE
1066
*
1067
* Input:           remote      - Remote node info
1068
*                  localPort   - Source port number
1069
*                  remotePort  - Destination port number
1070
*                  seq         - Segment sequence number
1071
*                  ack         - Segment acknowledge number
1072
*                  flags       - Segment flags
1073
*                  buffer      - Buffer to which this segment
1074
*                                is to be transmitted
1075
*                  len         - Total data length for this segment.
1076
*
1077
* Output:          A TCP segment is assembled and put to transmit.
1078
*
1079
* Side Effects:    None
1080
*
1081
* Overview:        None
1082
*
1083
* Note:            None
1084
********************************************************************/
1085
static void TransmitTCP(NODE_INFO *remote,
1086
                        TCP_PORT localPort,
1087
                        TCP_PORT remotePort,
1088
                        DWORD tseq,
1089
                        DWORD tack,
1090
                        BYTE flags,
1091
                        BUFFER buffer,
1092
                        WORD len)
1093
{
1094
    WORD_VAL        checkSum;
1095
    TCP_HEADER      header;
1096
    TCP_OPTIONS     options;
1097
    PSEUDO_HEADER   pseudoHeader;
1098
 
1099
    //  Make sure that this Tx buffer isn't currently being transmitted
1100
    while( !IPIsTxReady(TRUE) );    //TODO: This may need to be conditionally false
1101
 
1102
    // Obtain an AutoFree buffer if this packet is a control packet 
1103
    // only (contains no application data in an already allocated 
1104
    // buffer)
1105
    if(buffer == INVALID_BUFFER)
1106
        buffer = MACGetTxBuffer(TRUE);
1107
 
1108
    if(buffer == INVALID_BUFFER)
1109
        return;
1110
 
1111
    IPSetTxBuffer(buffer, 0);
1112
 
1113
    header.SourcePort           = localPort;
1114
    header.DestPort             = remotePort;
1115
    header.SeqNumber            = tseq;
1116
    header.AckNumber            = tack;
1117
    header.Flags.bits.Reserved2 = 0;
1118
    header.DataOffset.Reserved3 = 0;
1119
    header.Flags.byte           = flags;
1120
    // Receive window = MAC Free buffer size - TCP header (20) - IP header (20)
1121
    //                  - ETHERNET header (14 if using NIC) .
1122
    header.Window               = MACGetFreeRxSize();
1123
#if !defined(STACK_USE_SLIP)
1124
    /*
1125
    * Limit one segment at a time from remote host.
1126
    * This limit increases overall throughput as remote host does not
1127
    * flood us with packets and later retry with significant delay.
1128
    */
1129
    if ( header.Window >= MAC_RX_BUFFER_SIZE )
1130
        header.Window = MAC_RX_BUFFER_SIZE;
1131
 
1132
    else if ( header.Window > 54 )
1133
    {
1134
        header.Window -= 54;
1135
    }
1136
    else
1137
        header.Window = 0;
1138
#else
1139
    if ( header.Window > 40 )
1140
    {
1141
        header.Window -= 40;
1142
    }
1143
    else
1144
        header.Window = 0;
1145
#endif
1146
 
1147
    header.Checksum             = 0;
1148
    header.UrgentPointer        = 0;
1149
 
1150
    SwapTCPHeader(&header);
1151
 
1152
    len += sizeof(header);
1153
 
1154
    if ( flags & SYN )
1155
    {
1156
        len += sizeof(options);
1157
        options.Kind = TCP_OPTIONS_MAX_SEG_SIZE;
1158
        options.Length = 0x04;
1159
 
1160
        // Load MSS in already swapped order.
1161
        options.MaxSegSize.v[0]  = (MAC_RX_BUFFER_SIZE >> 8); // 0x05;
1162
        options.MaxSegSize.v[1]  = (MAC_RX_BUFFER_SIZE & 0xff); // 0xb4;
1163
 
1164
        header.DataOffset.Val   = (sizeof(header) + sizeof(options)) >> 2;
1165
    }
1166
    else
1167
        header.DataOffset.Val   = sizeof(header) >> 2;
1168
 
1169
 
1170
    // Calculate IP pseudoheader checksum.
1171
    pseudoHeader.SourceAddress  = AppConfig.MyIPAddr;
1172
    pseudoHeader.DestAddress    = remote->IPAddr;
1173
    pseudoHeader.Zero           = 0x0;
1174
    pseudoHeader.Protocol       = IP_PROT_TCP;
1175
    pseudoHeader.TCPLength      = len;
1176
 
1177
    SwapPseudoTCPHeader(pseudoHeader);
1178
 
1179
    header.Checksum = ~CalcIPChecksum((BYTE*)&pseudoHeader,
1180
        sizeof(pseudoHeader));
1181
    checkSum.Val = header.Checksum;
1182
 
1183
    // Write IP header.
1184
    IPPutHeader(remote, IP_PROT_TCP, len);
1185
    IPPutArray((BYTE*)&header, sizeof(header));
1186
 
1187
    if ( flags & SYN )
1188
        IPPutArray((BYTE*)&options, sizeof(options));
1189
 
1190
    IPSetTxBuffer(buffer, 0);
1191
 
1192
    checkSum.Val = CalcIPBufferChecksum(len);
1193
 
1194
    // Update the checksum.
1195
    IPSetTxBuffer(buffer, 16);
1196
    MACPut(checkSum.v[1]);
1197
    MACPut(checkSum.v[0]);
1198
    MACSetTxBuffer(buffer, 0);
1199
 
1200
    MACFlush();
1201
 
1202
#if !defined(TCP_NO_WAIT_FOR_ACK) && !defined(DEBUG)
1203
    // If we send the packet again, the remote node might think that we timed 
1204
    // out and retransmitted.  It could thus immediately send back an ACK and 
1205
    // dramatically improve throuput.
1206
    while(!IPIsTxReady(TRUE));
1207
    MACFlush();
1208
#endif
1209
}
1210
 
1211
 
1212
 
1213
/*********************************************************************
1214
* Function:        static TCP_SOCKET FindMatchingSocket(TCP_HEADER *h,
1215
*                                      NODE_INFO* remote)
1216
*
1217
* PreCondition:    TCPInit() is already called
1218
*
1219
* Input:           h           - TCP Header to be matched against.
1220
*                  remote      - Node who sent this header.
1221
*
1222
* Output:          A socket that matches with given header and remote
1223
*                  node is searched.
1224
*                  If such socket is found, its index is returned
1225
*                  else INVALID_SOCKET is returned.
1226
*
1227
* Side Effects:    None
1228
*
1229
* Overview:        None
1230
*
1231
* Note:            None
1232
********************************************************************/
1233
static TCP_SOCKET FindMatchingSocket(TCP_HEADER *h, NODE_INFO *remote)
1234
{
1235
    SOCKET_INFO *ps;
1236
    TCP_SOCKET s;
1237
    TCP_SOCKET partialMatch;
1238
 
1239
    partialMatch = INVALID_SOCKET;
1240
 
1241
    for ( s = 0; s < MAX_SOCKETS; s++ )
1242
    {
1243
        ps = &TCB[s];
1244
 
1245
        if ( ps->smState != TCP_CLOSED )
1246
        {
1247
            if ( ps->localPort == h->DestPort )
1248
            {
1249
                if ( ps->smState == TCP_LISTEN )
1250
                    partialMatch = s;
1251
 
1252
                if ( ps->remotePort == h->SourcePort &&
1253
                    ps->remote.IPAddr.Val == remote->IPAddr.Val )
1254
                {
1255
                    return s;
1256
                }
1257
            }
1258
        }
1259
    }
1260
 
1261
    // We are not listening on this port
1262
    if(partialMatch == INVALID_SOCKET)
1263
        return INVALID_SOCKET;
1264
 
1265
    // Copy the remote node IP/MAC address and source TCP port 
1266
    // number into our TCB and return this socket to the caller
1267
    ps = &TCB[partialMatch];
1268
    memcpy((void*)&ps->remote, (void*)remote, sizeof(*remote));
1269
    ps->remotePort          = h->SourcePort;
1270
    ps->Flags.bIsGetReady   = FALSE;
1271
    if(ps->TxBuffer != INVALID_BUFFER)
1272
    {
1273
        MACDiscardTx(ps->TxBuffer);
1274
        ps->TxBuffer        = INVALID_BUFFER;
1275
    }
1276
    ps->Flags.bIsPutReady   = TRUE;
1277
 
1278
    return partialMatch;
1279
}
1280
 
1281
 
1282
 
1283
 
1284
 
1285
 
1286
/*********************************************************************
1287
* Function:        static void SwapTCPHeader(TCP_HEADER* header)
1288
*
1289
* PreCondition:    None
1290
*
1291
* Input:           header      - TCP Header to be swapped.
1292
*
1293
* Output:          Given header is swapped.
1294
*
1295
* Side Effects:    None
1296
*
1297
* Overview:        None
1298
*
1299
* Note:            None
1300
********************************************************************/
1301
static void SwapTCPHeader(TCP_HEADER* header)
1302
{
1303
    header->SourcePort      = swaps(header->SourcePort);
1304
    header->DestPort        = swaps(header->DestPort);
1305
    header->SeqNumber       = swapl(header->SeqNumber);
1306
    header->AckNumber       = swapl(header->AckNumber);
1307
    header->Window          = swaps(header->Window);
1308
    header->Checksum        = swaps(header->Checksum);
1309
    header->UrgentPointer   = swaps(header->UrgentPointer);
1310
}
1311
 
1312
 
1313
 
1314
/*********************************************************************
1315
* Function:        static void CloseSocket(SOCKET_INFO* ps)
1316
*
1317
* PreCondition:    TCPInit() is already called
1318
*
1319
* Input:           ps  - Pointer to a socket info that is to be
1320
*                          closed.
1321
*
1322
* Output:          Given socket information is reset and any
1323
*                  buffer held by this socket is discarded.
1324
*
1325
* Side Effects:    None
1326
*
1327
* Overview:        None
1328
*
1329
* Note:            None
1330
********************************************************************/
1331
static void CloseSocket(SOCKET_INFO* ps)
1332
{
1333
    if(ps->TxBuffer != INVALID_BUFFER)
1334
    {
1335
        MACDiscardTx(ps->TxBuffer);
1336
        ps->TxBuffer            = INVALID_BUFFER;
1337
        ps->Flags.bIsPutReady   = TRUE;
1338
    }
1339
 
1340
    ps->remote.IPAddr.Val = 0x00;
1341
    ps->remotePort = 0x00;
1342
    if(ps->Flags.bIsGetReady)
1343
    {
1344
        MACDiscardRx();
1345
    }
1346
    ps->Flags.bIsGetReady       = FALSE;
1347
    ps->TimeOut                 = TCP_START_TIMEOUT_VAL;
1348
 
1349
    ps->Flags.bIsTxInProgress   = FALSE;
1350
 
1351
    if(ps->Flags.bServer)
1352
    {
1353
        ps->smState = TCP_LISTEN;
1354
    }
1355
    else
1356
    {
1357
        ps->smState = TCP_CLOSED;
1358
    }
1359
 
1360
    ps->TxCount = 0;
1361
 
1362
    return;
1363
}
1364
 
1365
 
1366
 
1367
/*********************************************************************
1368
* Function:        static void HandleTCPSeg(TCP_SOCKET s,
1369
*                                      NODE_INFO *remote,
1370
*                                      TCP_HEADER* h,
1371
*                                      WORD len)
1372
*
1373
* PreCondition:    TCPInit() is already called     AND
1374
*                  TCPProcess() is the caller.
1375
*
1376
* Input:           s           - Socket that owns this segment
1377
*                  remote      - Remote node info
1378
*                  h           - TCP Header
1379
*                  len         - Total buffer length.
1380
*
1381
* Output:          TCP FSM is executed on given socket with
1382
*                  given TCP segment.
1383
*
1384
* Side Effects:    None
1385
*
1386
* Overview:        None
1387
*
1388
* Note:            None
1389
********************************************************************/
1390
static void HandleTCPSeg(TCP_SOCKET s,
1391
                         NODE_INFO *remote,
1392
                         TCP_HEADER *h,
1393
                         WORD len)
1394
{
1395
    DWORD ack;
1396
    DWORD seq;
1397
    DWORD prevAck, prevSeq;
1398
    SOCKET_INFO *ps;
1399
    BYTE flags;
1400
 
1401
    ps = &TCB[s];
1402
 
1403
    flags = 0x00;
1404
 
1405
    // Clear timeout info
1406
    ps->RetryCount  = 0;
1407
    ps->startTick   = tickGet();
1408
    ps->TimeOut = TCP_START_TIMEOUT_VAL;
1409
 
1410
    // Reset FSM, if RST is received.
1411
    if(h->Flags.bits.flagRST)
1412
    {
1413
        MACDiscardRx();
1414
        ps->smState = ps->Flags.bServer ? TCP_LISTEN : TCP_SYN_SENT;
1415
        return;
1416
    }
1417
 
1418
    seq = ps->SND_SEQ;
1419
 
1420
    // ack is just a temporary variable
1421
    ack = h->Window - (seq - h->AckNumber) - ps->TxCount;
1422
    if((signed long)ack < 0)
1423
        ps->RemoteWindow = 0;
1424
    else
1425
        ps->RemoteWindow = ack;
1426
 
1427
 
1428
#ifdef STACK_CLIENT_MODE
1429
    // Handle TCP_SYN_SENT state
1430
    // The TCP_SYN_SENT state occurs when an application 
1431
    // calls TCPConnect().  After an initial SYN is sent,
1432
    // we expect a SYN + ACK before establishing the 
1433
    // connection.
1434
    if(ps->smState == TCP_SYN_SENT)
1435
    {
1436
        // Check if this is a SYN packet.  Unsynchronized, we cannot
1437
        // handle any other packet types.
1438
        if(!h->Flags.bits.flagSYN)
1439
        {
1440
            MACDiscardRx();
1441
 
1442
            // Send out a RESET if the remote node thinks a connection is already established
1443
            if(h->Flags.bits.flagACK)
1444
            {
1445
                flags = RST;
1446
                goto SendTCPControlPacket;
1447
            }
1448
 
1449
            return;
1450
        }
1451
 
1452
        // We now have a sequence number for the remote node
1453
        ps->SND_ACK = h->SeqNumber + len + 1;
1454
        ack = ps->SND_ACK;
1455
 
1456
        // If there is no ACK, we must go to TCP_SYN_RECEIVED.  With an ACK, 
1457
        // we can establish the connection now.
1458
        if(!h->Flags.bits.flagACK)
1459
        {
1460
            ps->smState = TCP_SYN_RECEIVED;
1461
            MACDiscardRx();
1462
            // Send out a SYN+ACK for simultaneous connection open
1463
            flags = SYN | ACK;
1464
            goto SendTCPControlPacket;
1465
        }
1466
 
1467
        // We received SYN+ACK, establish the connection now
1468
        ps->smState = TCP_ESTABLISHED;
1469
        // Send out an ACK
1470
        flags = ACK;
1471
 
1472
        ps->RemoteWindow = h->Window;
1473
 
1474
        // Check for application data and make it 
1475
        // available, if present
1476
        if(len)
1477
        {
1478
            ps->Flags.bIsGetReady   = TRUE;
1479
            ps->RxCount             = len;
1480
            ps->Flags.bFirstRead    = TRUE;
1481
        }
1482
        else    // No application data in this packet
1483
        {
1484
            MACDiscardRx();
1485
        }
1486
        goto SendTCPControlPacket;
1487
    }
1488
#endif
1489
 
1490
    // Handle TCP_LISTEN state
1491
    if(ps->smState == TCP_LISTEN )
1492
    {
1493
        MACDiscardRx();
1494
 
1495
        // Send a RST if this isn't a SYN packet
1496
        if(!h->Flags.bits.flagSYN)
1497
        {
1498
            flags = RST;
1499
            goto SendTCPControlPacket;
1500
        }
1501
 
1502
        ps->SND_ACK = h->SeqNumber + len + 1;
1503
        ps->RemoteWindow = h->Window;
1504
 
1505
        // This socket has received connection request (SYN).
1506
        // Remember calling node, assign next segment seq. number
1507
        // for this potential connection.
1508
        memcpy((void*)&ps->remote, (const void*)remote, sizeof(*remote));
1509
        ps->remotePort = h->SourcePort;
1510
 
1511
        // Grant connection request.
1512
        ps->smState = TCP_SYN_RECEIVED;
1513
        seq = ps->SND_SEQ++;
1514
        ack =  ps->SND_ACK;
1515
        flags = SYN | ACK;
1516
        goto SendTCPControlPacket;
1517
    }
1518
 
1519
 
1520
    // Remember current seq and ack for our connection so that if
1521
    // we have to silently discard this packet, we can go back to
1522
    // previous ack and seq numbers.
1523
    prevAck = ps->SND_ACK;
1524
    prevSeq = ps->SND_SEQ;
1525
 
1526
    ack = h->SeqNumber;
1527
    ack += (DWORD)len;
1528
    seq = ps->SND_SEQ;
1529
 
1530
    // State is something other than TCP_LISTEN, handle it.
1531
    {
1532
        // Check to see if the incomming sequence number is what 
1533
        // we expect (last transmitted ACK value).  Throw this packet 
1534
        // away if it is wrong.
1535
        if(h->SeqNumber == prevAck)
1536
        {
1537
            // After receiving a SYNchronization request, we expect an 
1538
            // ACK to our transmitted SYN
1539
            if(ps->smState == TCP_SYN_RECEIVED)
1540
            {
1541
                if(h->Flags.bits.flagACK)
1542
                {
1543
                    // ACK received as expected, this connection is 
1544
                    // now established
1545
                    ps->SND_ACK = ack;
1546
                    ps->smState = TCP_ESTABLISHED;
1547
 
1548
                    // Check if this first packet has application data 
1549
                    // in it.  Make it available if so.
1550
                    if(len)
1551
                    {
1552
                        ps->Flags.bIsGetReady   = TRUE;
1553
                        ps->RxCount             = len;
1554
                        ps->Flags.bFirstRead    = TRUE;
1555
                    }
1556
                    else
1557
                        MACDiscardRx();
1558
                }
1559
                else    // No ACK to our SYN
1560
                {
1561
                    MACDiscardRx();
1562
                }
1563
            }
1564
            // Connection is established, closing, or otherwise
1565
            else
1566
            {
1567
 
1568
                // Save the seq+len value of the packet for our future 
1569
                // ACK transmission, and so out of sequence packets 
1570
                // can be detected in the future.
1571
                ps->SND_ACK = ack;
1572
 
1573
                // Handle packets received while connection established.
1574
                if(ps->smState == TCP_ESTABLISHED)
1575
                {
1576
                    // If this packet has the ACK set, mark all 
1577
                    // previous TX packets as no longer needed for 
1578
                    // possible retransmission.
1579
                    // TODO: Make this more sophisticated so that partial ACKs due to fragmentation are handled correctly.  i.e. Keep a real output stream buffer with slidable window capability.
1580
                    if(h->Flags.bits.flagACK && !ps->Flags.bIsPutReady)
1581
                    {
1582
                        if(ps->TxBuffer != INVALID_BUFFER)
1583
                        {
1584
                            MACDiscardTx(ps->TxBuffer);
1585
                            ps->TxBuffer            = INVALID_BUFFER;
1586
                            ps->Flags.bIsPutReady   = TRUE;
1587
                        }
1588
                    }
1589
 
1590
                    // Check if the remote node is closing the connection
1591
                    if(h->Flags.bits.flagFIN)
1592
                    {
1593
//                      DebugPrint("|");
1594
                        flags = FIN | ACK;
1595
                        seq = ps->SND_SEQ++;
1596
                        ack = ++ps->SND_ACK;
1597
                        ps->smState = TCP_LAST_ACK;
1598
                    }
1599
 
1600
                    // Check if there is any application data in 
1601
                    // this packet.
1602
                    if(len)
1603
                    {
1604
                        // There is data.  Make it available if we 
1605
                        // don't already have data available.
1606
                        if(!ps->Flags.bIsGetReady)
1607
                        {
1608
                            ps->Flags.bIsGetReady   = TRUE;
1609
                            ps->RxCount             = len;
1610
                            ps->Flags.bFirstRead    = TRUE;
1611
 
1612
                            // 4/1/02
1613
                            flags |= ACK;
1614
                        }
1615
                        // There is data, but we cannot handle it at this time.
1616
                        else
1617
                        {
1618
//                          DebugPrint("D");
1619
                            // Since we cannot accept this packet,
1620
                            // restore to previous seq and ack.
1621
                            // and do not send anything back.
1622
                            // Host has to resend this packet when
1623
                            // we are ready.
1624
                            ps->SND_SEQ = prevSeq;
1625
                            ps->SND_ACK = prevAck;
1626
 
1627
                            MACDiscardRx();
1628
                        }
1629
                    }
1630
                    // There is no data in this packet, and thus it 
1631
                    // can be thrown away.
1632
                    else
1633
                    {
1634
                        MACDiscardRx();
1635
                    }
1636
                }
1637
                // Connection is not established; check if we've sent 
1638
                // a FIN and expect our last ACK
1639
                else if(ps->smState == TCP_LAST_ACK)
1640
                {
1641
                    MACDiscardRx();
1642
 
1643
                    if(h->Flags.bits.flagACK)
1644
                    {
1645
                        CloseSocket(ps);
1646
                    }
1647
                }
1648
                else if(ps->smState == TCP_FIN_WAIT_1)
1649
                {
1650
                    MACDiscardRx();
1651
 
1652
                    if(h->Flags.bits.flagFIN)
1653
                    {
1654
                        flags = ACK;
1655
                        ack = ++ps->SND_ACK;
1656
                        if(h->Flags.bits.flagACK)
1657
                        {
1658
                            CloseSocket(ps);
1659
                        }
1660
                        else
1661
                        {
1662
                            ps->smState = TCP_CLOSING;
1663
                        }
1664
                    }
1665
                    else if(h->Flags.bits.flagACK)
1666
                    {
1667
                        ps->smState = TCP_FIN_WAIT_2;
1668
                    }
1669
                }
1670
                else if(ps->smState == TCP_FIN_WAIT_2)
1671
                {
1672
                    MACDiscardRx();
1673
 
1674
                    if(h->Flags.bits.flagFIN)
1675
                    {
1676
                        flags = ACK;
1677
                        ack = ++ps->SND_ACK;
1678
                        CloseSocket(ps);
1679
                    }
1680
                }
1681
                else if ( ps->smState == TCP_CLOSING )
1682
                {
1683
                    MACDiscardRx();
1684
 
1685
                    if ( h->Flags.bits.flagACK )
1686
                    {
1687
                        CloseSocket(ps);
1688
                    }
1689
                }
1690
            }
1691
        }
1692
        // This packet's sequence number does not match what we were 
1693
        // expecting (the last value we ACKed).  Throw this packet 
1694
        // away.  This may happen if packets are delivered out of order.
1695
        // Not enough memory is available on our PIC or Ethernet 
1696
        // controller to implement a robust stream reconstruction 
1697
        // buffer.  As a result, the remote node will just have to 
1698
        // retransmit its packets starting with the proper sequence number.
1699
        else
1700
        {
1701
            MACDiscardRx();
1702
 
1703
            // Send a new ACK out in case if the previous one was lost 
1704
            // (ACKs aren't ACKed).  This is required to prevent an 
1705
            // unlikely but possible situation which would cause the 
1706
            // connection to time out if the ACK was lost and the 
1707
            // remote node keeps sending us older data than we are 
1708
            // expecting.
1709
            flags = ACK;   
1710
            ack = prevAck;
1711
        }
1712
    }
1713
 
1714
SendTCPControlPacket:
1715
    if(flags)
1716
    {
1717
        SendTCP(remote,
1718
            h->DestPort,
1719
            h->SourcePort,
1720
            seq,
1721
            ack,
1722
            flags);
1723
    }
1724
}
1725
 
1726
 
1727
#endif //#if defined(STACK_USE_TCP)