Ticket #5240: tcp-draft-02.diff

File tcp-draft-02.diff, 26.0 KB (added by andreasf, 14 years ago)

updated draft patch

  • headers/private/kernel/boot/net/NetDefs.h

     headers/private/kernel/boot/net/NetDefs.h  |   43 ++
     headers/private/kernel/boot/net/NetStack.h |    3 +
     headers/private/kernel/boot/net/TCP.h      |  140 ++++++
     src/system/boot/loader/net/NetDefs.cpp     |    1 +
     src/system/boot/loader/net/NetStack.cpp    |   13 +-
     src/system/boot/loader/net/TCP.cpp         |  742 ++++++++++++++++++++++++++++
     6 files changed, 941 insertions(+), 1 deletions(-)
    
    diff --git a/headers/private/kernel/boot/net/NetDefs.h b/headers/private/kernel/boot/net/NetDefs.h
    index d190ff6..041e1ee 100644
    a b  
    11/*
    22 * Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
     3 * Copyright 2010, Andreas Faerber <andreas.faerber@web.de>
    34 * All rights reserved. Distributed under the terms of the MIT License.
    45 */
    56
    struct ip_header {  
    157158#define IP_DEFAULT_TIME_TO_LIVE     64      /* default ttl, from RFC 1340 */
    158159
    159160// IP protocols
     161#define IPPROTO_TCP                 6
    160162#define IPPROTO_UDP                 17
    161163
    162164
    struct udp_header  
    174176} __attribute__ ((__packed__));
    175177
    176178
     179// Transmission Control Protocol (TCP)
     180
     181// TCP header (RFC 793, RFC 3168)
     182struct tcp_header
     183{
     184    uint16 source;          // source port
     185    uint16 destination;     // destination port
     186    uint32 seqNumber;       // sequence number
     187    uint32 ackNumber;       // acknowledgment number
     188#if __BYTE_ORDER == __BIG_ENDIAN
     189    uint8 dataOffset:4;     // data offset
     190    uint8 reserved:4;       // reserved
     191#elif __BYTE_ORDER == __LITTLE_ENDIAN
     192    uint8 reserved:4;       // reserved
     193    uint8 dataOffset:4;     // data offset
     194#endif
     195#if __BYTE_ORDER == __BIG_ENDIAN
     196    bool cwr:1;
     197    bool ece:1;
     198    bool urg:1;
     199    bool ack:1;
     200    bool psh:1;
     201    bool rst:1;
     202    bool syn:1;
     203    bool fin:1;
     204#elif __BYTE_ORDER == __LITTLE_ENDIAN
     205    bool fin:1;
     206    bool syn:1;
     207    bool rst:1;
     208    bool psh:1;
     209    bool ack:1;
     210    bool urg:1;
     211    bool ece:1;
     212    bool cwr:1;
     213#endif
     214    uint16 window;          // window size
     215    uint16 checksum;        // checksum
     216    uint16 urgentPointer;   // urgent pointer
     217} __attribute__ ((__packed__));
     218
    177219// #pragma mark -
    178220
    179221// NetService
    extern const char *const kEthernetServiceName;  
    183225extern const char *const kARPServiceName;
    184226extern const char *const kIPServiceName;
    185227extern const char *const kUDPServiceName;
     228extern const char *const kTCPServiceName;
    186229
    187230class NetService {
    188231public:
  • headers/private/kernel/boot/net/NetStack.h

    diff --git a/headers/private/kernel/boot/net/NetStack.h b/headers/private/kernel/boot/net/NetStack.h
    index e2baeaa..f148732 100644
    a b class EthernetService;  
    1313class ARPService;
    1414class IPService;
    1515class UDPService;
     16class TCPService;
    1617
    1718
    1819class NetStack {
    public:  
    3435    ARPService *GetARPService() const           { return fARPService; }
    3536    IPService *GetIPService() const             { return fIPService; }
    3637    UDPService *GetUDPService() const           { return fUDPService; }
     38    TCPService *GetTCPService() const           { return fTCPService; }
    3739
    3840private:
    3941    static NetStack     *sNetStack;
    private:  
    4345    ARPService          *fARPService;
    4446    IPService           *fIPService;
    4547    UDPService          *fUDPService;
     48    TCPService          *fTCPService;
    4649};
    4750
    4851
  • new file headers/private/kernel/boot/net/TCP.h

    diff --git a/headers/private/kernel/boot/net/TCP.h b/headers/private/kernel/boot/net/TCP.h
    new file mode 100644
    index 0000000..7b0d8e2
    - +  
     1/*
     2 * Copyright 2010 Andreas Faerber <andreas.faerber@web.de>
     3 * All rights reserved. Distributed under the terms of the MIT License.
     4 */
     5
     6#ifndef BOOT_NET_TCP_H
     7#define BOOT_NET_TCP_H
     8
     9#include <boot/net/IP.h>
     10
     11
     12class TCPPacket {
     13public:
     14    TCPPacket();
     15    ~TCPPacket();
     16
     17    status_t SetTo(const void* data, size_t size, ip_addr_t sourceAddress,
     18        uint16 sourcePort, ip_addr_t destinationAddress,
     19        uint16 destinationPort, uint32 sequenceNumber,
     20        uint32 acknowledgmentNumber, uint8 flags);
     21
     22    ip_addr_t SourceAddress() const;
     23    ip_addr_t DestinationAddress() const;
     24    uint16 SourcePort() const;
     25    uint16 DestinationPort() const;
     26    uint32 SequenceNumber() const;
     27    uint32 AcknowledgmentNumber() const;
     28    const void* Data() const { return fData; }
     29    size_t DataSize() const { return fSize; }
     30    uint8 Flags() const { return fFlags; }
     31
     32    bool ProvidesSequenceNumber(uint32 sequenceNo) const;
     33
     34    TCPPacket* Next() const;
     35    void SetNext(TCPPacket* packet);
     36
     37private:
     38    ip_addr_t   fSourceAddress;
     39    ip_addr_t   fDestinationAddress;
     40    uint16      fSourcePort;
     41    uint16      fDestinationPort;
     42    uint32      fSequenceNumber;
     43    uint32      fAcknowledgmentNumber;
     44    void*       fData;
     45    size_t      fSize;
     46    uint8       fFlags;
     47    TCPPacket*  fNext;
     48};
     49
     50#define TCP_SYN     1
     51#define TCP_ACK     2
     52#define TCP_FIN     4
     53#define TCP_RST     8
     54
     55class TCPService;
     56
     57enum TCPSocketState {
     58    TCP_SOCKET_STATE_INITIAL,
     59    TCP_SOCKET_STATE_SYN_SENT,
     60    TCP_SOCKET_STATE_SYN_RECEIVED,
     61    TCP_SOCKET_STATE_OPEN,
     62    TCP_SOCKET_STATE_FIN_SENT,
     63    TCP_SOCKET_STATE_CLOSED
     64};
     65
     66class TCPSocket {
     67public:
     68    TCPSocket();
     69    ~TCPSocket();
     70
     71    ip_addr_t Address() const   { return fAddress; }
     72    uint16 Port() const         { return fPort; }
     73
     74    status_t Connect(ip_addr_t address, uint16 port);
     75    status_t Close();
     76    status_t Read(void* buffer, size_t bufferSize, size_t* bytesRead, bigtime_t timeout = 0);
     77    status_t Write(const void* buffer, size_t bufferSize);
     78
     79    void Acknowledge(uint32 number);
     80    void ProcessPacket(TCPPacket* packet);
     81
     82private:
     83    TCPPacket* _PeekPacket();
     84    TCPPacket* _DequeuePacket();
     85    status_t _Send(TCPPacket* packet, bool enqueue = true);
     86    status_t _ResendQueue();
     87    void _EnqueueOutgoingPacket(TCPPacket* packet);
     88    status_t _WaitForState(TCPSocketState state, bigtime_t timeout = 0);
     89    status_t _Ack();
     90
     91    TCPService* fTCPService;
     92    ip_addr_t   fAddress;
     93    uint16      fPort;
     94    ip_addr_t   fRemoteAddress;
     95    uint16      fRemotePort;
     96    uint32      fSequenceNumber;
     97    uint32      fAcknowledgeNumber;
     98    uint32      fNextSequence;
     99    TCPPacket*  fFirstPacket;
     100    TCPPacket*  fLastPacket;
     101    TCPPacket*  fFirstSentPacket;
     102    TCPPacket*  fLastSentPacket;
     103    TCPSocketState fState;
     104    TCPSocketState fRemoteState;
     105};
     106
     107class TCPService : public IPSubService {
     108public:
     109    TCPService(IPService* ipService);
     110    virtual ~TCPService();
     111
     112    status_t Init();
     113
     114    virtual uint8 IPProtocol() const;
     115
     116    virtual void HandleIPPacket(IPService* ipService, ip_addr_t sourceIP,
     117        ip_addr_t destinationIP, const void* data, size_t size);
     118
     119    status_t Send(uint16 sourcePort, ip_addr_t destinationAddress,
     120        uint16 destinationPort, uint32 sequenceNumber,
     121        uint32 acknowledgmentNumber, uint8 flags, ChainBuffer* buffer);
     122
     123    void ProcessIncomingPackets();
     124
     125    status_t BindSocket(TCPSocket* socket);
     126    void UnbindSocket(TCPSocket* socket);
     127
     128private:
     129    uint16 _ChecksumBuffer(ChainBuffer* buffer, ip_addr_t source,
     130        ip_addr_t destination, uint16 length);
     131    uint16 _ChecksumData(const void* data, uint16 length, ip_addr_t source,
     132        ip_addr_t destination);
     133
     134    TCPSocket* _FindSocket(ip_addr_t address, uint16 port);
     135
     136    IPService*          fIPService;
     137    Vector<TCPSocket*>  fSockets;
     138};
     139
     140#endif
  • src/system/boot/loader/net/NetDefs.cpp

    diff --git a/src/system/boot/loader/net/NetDefs.cpp b/src/system/boot/loader/net/NetDefs.cpp
    index 009e4c0..19b7681 100644
    a b const char *const kEthernetServiceName = "ethernet";  
    1616const char *const kARPServiceName = "arp";
    1717const char *const kIPServiceName = "ip";
    1818const char *const kUDPServiceName = "udp";
     19const char *const kTCPServiceName = "tcp";
    1920
    2021
    2122// constructor
  • src/system/boot/loader/net/NetStack.cpp

    diff --git a/src/system/boot/loader/net/NetStack.cpp b/src/system/boot/loader/net/NetStack.cpp
    index 7db3de0..0154997 100644
    a b  
    1313#include <boot/net/Ethernet.h>
    1414#include <boot/net/IP.h>
    1515#include <boot/net/UDP.h>
     16#include <boot/net/TCP.h>
    1617
    1718
    1819// sNetStack
    NetStack::NetStack()  
    2425        fEthernetService(NULL),
    2526        fARPService(NULL),
    2627        fIPService(NULL),
    27         fUDPService(NULL)
     28        fUDPService(NULL),
     29        fTCPService(NULL)
    2830{
    2931}
    3032
    3133// destructor
    3234NetStack::~NetStack()
    3335{
     36    delete fTCPService;
    3437    delete fUDPService;
    3538    delete fIPService;
    3639    delete fARPService;
    NetStack::Init()  
    7376    if (error != B_OK)
    7477        return error;
    7578
     79    // TCP service
     80    fTCPService = new(nothrow) TCPService(fIPService);
     81    if (fTCPService == NULL)
     82        return B_NO_MEMORY;
     83    error = fTCPService->Init();
     84    if (error != B_OK)
     85        return error;
     86
    7687    return B_OK;
    7788}
    7889
  • new file src/system/boot/loader/net/TCP.cpp

    diff --git a/src/system/boot/loader/net/TCP.cpp b/src/system/boot/loader/net/TCP.cpp
    new file mode 100644
    index 0000000..9b3eea6
    - +  
     1/*
     2 * Copyright 2010 Andreas Faerber <andreas.faerber@web.de>
     3 * All rights reserved. Distributed under the terms of the MIT License.
     4 */
     5
     6#include <boot/net/TCP.h>
     7
     8#include <stdio.h>
     9#include <KernelExport.h>
     10
     11#include <boot/net/ChainBuffer.h>
     12#include <boot/net/NetStack.h>
     13
     14
     15//#define TRACE_TCP
     16#ifdef TRACE_TCP
     17#   define TRACE(x) dprintf x
     18#else
     19#   define TRACE(x) ;
     20#endif
     21
     22
     23static int
     24_rand(void)
     25{
     26    static int next = 0;
     27    if (next == 0)
     28        next = system_time();
     29
     30    next = next * 1103515245 + 12345;
     31    return next;
     32}
     33
     34
     35TCPPacket::TCPPacket()
     36    :
     37    fData(NULL),
     38    fNext(NULL)
     39{
     40}
     41
     42
     43TCPPacket::~TCPPacket()
     44{
     45    free(fData);
     46}
     47
     48
     49status_t
     50TCPPacket::SetTo(const void* data, size_t size, ip_addr_t sourceAddress,
     51    uint16 sourcePort, ip_addr_t destinationAddress, uint16 destinationPort,
     52    uint32 sequenceNumber, uint32 acknowledgmentNumber, uint8 flags)
     53{
     54    if (data == NULL && size > 0)
     55        return B_BAD_VALUE;
     56
     57    if (size > 0) {
     58        fData = malloc(size);
     59        if (fData == NULL)
     60            return B_NO_MEMORY;
     61        memcpy(fData, data, size);
     62    } else {
     63        fData = NULL;
     64    }
     65
     66    fSize = size;
     67    fSourceAddress = sourceAddress;
     68    fSourcePort = sourcePort;
     69    fDestinationAddress = destinationAddress;
     70    fDestinationPort = destinationPort;
     71    fSequenceNumber = sequenceNumber;
     72    fAcknowledgmentNumber = acknowledgmentNumber;
     73    fFlags = flags;
     74
     75    return B_OK;
     76}
     77
     78
     79ip_addr_t
     80TCPPacket::SourceAddress() const
     81{
     82    return fSourceAddress;
     83}
     84
     85
     86ip_addr_t
     87TCPPacket::DestinationAddress() const
     88{
     89    return fDestinationAddress;
     90}
     91
     92
     93uint16
     94TCPPacket::SourcePort() const
     95{
     96    return fSourcePort;
     97}
     98
     99
     100uint16
     101TCPPacket::DestinationPort() const
     102{
     103    return fDestinationPort;
     104}
     105
     106
     107uint32
     108TCPPacket::SequenceNumber() const
     109{
     110    return fSequenceNumber;
     111}
     112
     113
     114uint32
     115TCPPacket::AcknowledgmentNumber() const
     116{
     117    return fAcknowledgmentNumber;
     118}
     119
     120
     121bool
     122TCPPacket::ProvidesSequenceNumber(uint32 sequenceNumber) const
     123{
     124    return fSequenceNumber <= sequenceNumber
     125        && fSequenceNumber + fSize > sequenceNumber;
     126}
     127
     128
     129TCPPacket*
     130TCPPacket::Next() const
     131{
     132    return fNext;
     133}
     134
     135
     136void
     137TCPPacket::SetNext(TCPPacket* packet)
     138{
     139    fNext = packet;
     140}
     141
     142
     143
     144
     145TCPSocket::TCPSocket()
     146    :
     147    fTCPService(NetStack::Default()->GetTCPService()),
     148    fAddress(INADDR_ANY),
     149    fPort(0),
     150    fSequenceNumber(0),
     151    fFirstPacket(NULL),
     152    fLastPacket(NULL),
     153    fFirstSentPacket(NULL),
     154    fLastSentPacket(NULL),
     155    fState(TCP_SOCKET_STATE_INITIAL),
     156    fRemoteState(TCP_SOCKET_STATE_INITIAL)
     157{
     158}
     159
     160
     161TCPSocket::~TCPSocket()
     162{
     163    if (fTCPService != NULL && fPort != 0)
     164        fTCPService->UnbindSocket(this);
     165}
     166
     167
     168status_t
     169TCPSocket::Connect(ip_addr_t address, uint16 port)
     170{
     171    fRemoteAddress = address;
     172    fRemotePort = port;
     173    fSequenceNumber = _rand();
     174    fPort = 0xC000 + ((_rand() >> 16) & ~0xc000);
     175    dprintf("TCPSocket::Connect(): connecting from port %u\n", fPort);
     176    fAcknowledgeNumber = 0;
     177    fNextSequence = 0;
     178
     179    status_t error = fTCPService->BindSocket(this);
     180    if (error != B_OK)
     181        return error;
     182
     183    // send SYN
     184    TCPPacket* packet = new(nothrow) TCPPacket();
     185    if (packet == NULL)
     186        return B_NO_MEMORY;
     187    error = packet->SetTo(NULL, 0, fAddress, fPort, address, port,
     188        fSequenceNumber, fAcknowledgeNumber, TCP_SYN);
     189    if (error != B_OK)
     190        return error;
     191    error = _Send(packet);
     192    if (error != B_OK)
     193        return error;
     194    fState = TCP_SOCKET_STATE_SYN_SENT;
     195    fSequenceNumber++;
     196    TRACE(("SYN sent\n"));
     197
     198    // receive SYN-ACK
     199    error = _WaitForState(TCP_SOCKET_STATE_OPEN, 1000000LL);
     200    if (error != B_OK) {
     201        TRACE(("no SYN-ACK received\n"));
     202        return error;
     203    }
     204    TRACE(("SYN-ACK received\n"));
     205
     206    return B_OK;
     207}
     208
     209
     210status_t
     211TCPSocket::Close()
     212{
     213    // send FIN
     214    TCPPacket* packet = new(nothrow) TCPPacket();
     215    if (packet == NULL)
     216        return B_NO_MEMORY;
     217    status_t error = packet->SetTo(NULL, 0, fAddress, fPort, fRemoteAddress, fRemotePort,
     218        fSequenceNumber, fAcknowledgeNumber, TCP_FIN | TCP_ACK);
     219    if (error != B_OK)
     220        return error;
     221    error = _Send(packet);
     222    if (error != B_OK)
     223        return error;
     224    fState = TCP_SOCKET_STATE_FIN_SENT;
     225    TRACE(("FIN sent\n"));
     226
     227    error = _WaitForState(TCP_SOCKET_STATE_CLOSED, 1000000LL);
     228    if (error != B_OK)
     229        return error;
     230
     231    return B_OK;
     232}
     233
     234
     235status_t
     236TCPSocket::Read(void* buffer, size_t bufferSize, size_t* bytesRead, bigtime_t timeout)
     237{
     238    TRACE(("TCPSocket::Read(): size = %lu\n", bufferSize));
     239    if (bytesRead == NULL)
     240        return B_BAD_VALUE;
     241
     242    *bytesRead = 0;
     243    TCPPacket* packet = NULL;
     244   
     245    bigtime_t startTime = system_time();
     246    do {
     247        fTCPService->ProcessIncomingPackets();
     248        //_ResendQueue();
     249        packet = _PeekPacket();
     250        if (packet != NULL && fRemoteState != TCP_SOCKET_STATE_OPEN)
     251            return B_WOULD_BLOCK;
     252    } while (packet == NULL && system_time() - startTime < timeout);
     253    if (packet == NULL)
     254        return (timeout == 0) ? B_WOULD_BLOCK : B_TIMED_OUT;
     255    uint32 packetOffset = fNextSequence - packet->SequenceNumber();
     256    size_t readBytes = packet->DataSize() - packetOffset;
     257    if (readBytes > bufferSize)
     258        readBytes = bufferSize;
     259    if (buffer != NULL)
     260        memcpy(buffer, (uint8*)packet->Data() + packetOffset, readBytes);
     261    *bytesRead = readBytes;
     262    if (!packet->ProvidesSequenceNumber(fNextSequence + readBytes)) {
     263        _DequeuePacket();
     264        delete packet;
     265        packet = NULL;
     266    }
     267    fNextSequence += readBytes;
     268
     269    if (packet == NULL && *bytesRead < bufferSize) {
     270        do {
     271            if (buffer != NULL)
     272                buffer = (uint8*)buffer + readBytes;
     273            bufferSize -= readBytes;
     274            fTCPService->ProcessIncomingPackets();
     275            packet = _PeekPacket();
     276            if (packet == NULL && fRemoteState != TCP_SOCKET_STATE_OPEN)
     277                break;
     278            readBytes = 0;
     279            if (packet == NULL)
     280                continue;
     281            readBytes = packet->DataSize();
     282            if (readBytes > bufferSize)
     283                readBytes = bufferSize;
     284            if (buffer != NULL)
     285                memcpy(buffer, packet->Data(), readBytes);
     286            *bytesRead += readBytes;
     287            if (readBytes == packet->DataSize()) {
     288                _DequeuePacket();
     289                delete packet;
     290            }
     291            fNextSequence += readBytes;
     292        } while (readBytes < bufferSize && system_time() - startTime < timeout);
     293    }
     294
     295    return B_OK;
     296}
     297
     298
     299status_t
     300TCPSocket::Write(const void* buffer, size_t bufferSize)
     301{
     302    if (buffer == NULL || bufferSize <= 0)
     303        return B_BAD_VALUE;
     304
     305    TCPPacket* packet = new(nothrow) TCPPacket();
     306    if (packet == NULL)
     307        return B_NO_MEMORY;
     308    status_t error = packet->SetTo(buffer, bufferSize, fAddress, fPort,
     309        fRemoteAddress, fRemotePort, fSequenceNumber, fAcknowledgeNumber,
     310        TCP_ACK);
     311    if (error != B_OK)
     312        return error;
     313    return _Send(packet);
     314}
     315
     316
     317void
     318TCPSocket::Acknowledge(uint32 number)
     319{
     320    TRACE(("TCPSocket::Acknowledge(): %lu\n", number));
     321    // dequeue packets
     322    for (TCPPacket* packet = fFirstSentPacket; packet != NULL;
     323            packet = fFirstSentPacket) {
     324        if (packet->SequenceNumber() >= number)
     325            return;
     326        fFirstSentPacket = packet->Next();
     327        delete packet;
     328    }
     329    fLastSentPacket = NULL;
     330}
     331
     332
     333void
     334TCPSocket::ProcessPacket(TCPPacket* packet)
     335{
     336    TRACE(("TCPSocket::ProcessPacket()\n"));
     337
     338    if ((packet->Flags() & TCP_FIN) != 0) {
     339        fRemoteState = TCP_SOCKET_STATE_FIN_SENT;
     340        TRACE(("FIN received\n"));
     341        _Ack();
     342    }
     343
     344    if (fState == TCP_SOCKET_STATE_SYN_SENT) {
     345        if ((packet->Flags() & TCP_SYN) != 0
     346                && (packet->Flags() & TCP_ACK) != 0) {
     347            fNextSequence = fAcknowledgeNumber = packet->SequenceNumber() + 1;
     348            fRemoteState = TCP_SOCKET_STATE_SYN_SENT;
     349            delete packet;
     350            _Ack();
     351            fState = fRemoteState = TCP_SOCKET_STATE_OPEN;
     352            return;
     353        }
     354    } else if (fState == TCP_SOCKET_STATE_OPEN) {
     355    } else if (fState == TCP_SOCKET_STATE_FIN_SENT) {
     356        if ((packet->Flags() & TCP_ACK) != 0) {
     357            TRACE(("FIN-ACK received\n"));
     358            if (fRemoteState == TCP_SOCKET_STATE_FIN_SENT)
     359                fState = TCP_SOCKET_STATE_CLOSED;
     360        }
     361    }
     362
     363    if (packet->DataSize() == 0) {
     364        TRACE(("TCPSocket::ProcessPacket(): not queuing\n"));
     365        return;
     366    }
     367
     368    if (fLastPacket == NULL) {
     369        // no packets enqueued
     370        TRACE(("TCPSocket::ProcessPacket(): first in queue\n"));
     371        packet->SetNext(NULL);
     372        fFirstPacket = fLastPacket = packet;
     373    } else if (fLastPacket->SequenceNumber() < packet->SequenceNumber()) {
     374        // enqueue in back
     375        TRACE(("TCPSocket::ProcessPacket(): enqueue in back\n"));
     376        fLastPacket->SetNext(packet);
     377        fLastPacket = packet;
     378    } else if (fFirstPacket->SequenceNumber() > packet->SequenceNumber()) {
     379        // enqueue in front
     380        TRACE(("TCPSocket::ProcessPacket(): enqueue in front\n"));
     381        packet->SetNext(fFirstPacket);
     382        fFirstPacket = packet;
     383    } else {
     384        // enqueue in middle
     385        TRACE(("TCPSocket::ProcessPacket(): enqueue in middle\n"));
     386        for (TCPPacket* queuedPacket = fFirstPacket; queuedPacket != NULL;
     387                queuedPacket = queuedPacket->Next()) {
     388            if (queuedPacket->SequenceNumber() == packet->SequenceNumber()) {
     389                TRACE(("TCPSocket::EnqueuePacket(): TCP packet dropped\n"));
     390                // we may be waiting for a previous packet
     391                return;
     392            }
     393            if (queuedPacket->Next()->SequenceNumber() > packet->SequenceNumber()) {
     394                packet->SetNext(queuedPacket->Next());
     395                queuedPacket->SetNext(packet);
     396                break;
     397            }
     398        }
     399    }
     400    if (packet->SequenceNumber() == fAcknowledgeNumber)
     401        fAcknowledgeNumber = packet->SequenceNumber() + packet->DataSize();
     402            //XXX might be greater than that
     403}
     404
     405
     406TCPPacket*
     407TCPSocket::_PeekPacket()
     408{
     409    TRACE(("TCPSocket::_PeekPacket(): fNextSequence = %lu\n", fNextSequence));
     410    for (TCPPacket* packet = fFirstPacket; packet != NULL;
     411            packet = packet->Next()) {
     412        if (packet->ProvidesSequenceNumber(fNextSequence))
     413            return packet;
     414    }
     415    return NULL;
     416}
     417
     418
     419TCPPacket*
     420TCPSocket::_DequeuePacket()
     421{
     422    //TRACE(("TCPSocket::DequeuePacket()\n"));
     423    if (fFirstPacket == NULL)
     424        return NULL;
     425
     426    if (fFirstPacket->ProvidesSequenceNumber(fNextSequence)) {
     427        TCPPacket* packet = fFirstPacket;
     428        fFirstPacket = packet->Next();
     429        if (fFirstPacket == NULL)
     430            fLastPacket = NULL;
     431        packet->SetNext(NULL);
     432        return packet;
     433    }
     434
     435    for (TCPPacket* packet = fFirstPacket;
     436            packet != NULL && packet->Next() != NULL;
     437            packet = packet->Next()) {
     438        if (packet->Next()->ProvidesSequenceNumber(fNextSequence)) {
     439            TCPPacket* nextPacket = packet->Next();
     440            packet->SetNext(nextPacket->Next());
     441            if (fLastPacket == nextPacket)
     442                fLastPacket = packet;
     443            fNextSequence += nextPacket->DataSize();
     444            return nextPacket;
     445        }
     446    }
     447    return NULL;
     448}
     449
     450
     451status_t
     452TCPSocket::_Send(TCPPacket* packet, bool enqueue)
     453{
     454    ChainBuffer buffer((void*)packet->Data(), packet->DataSize());
     455    status_t error = fTCPService->Send(fPort, fRemoteAddress, fRemotePort,
     456        packet->SequenceNumber(), fAcknowledgeNumber, packet->Flags(),
     457        &buffer);
     458    if (error != B_OK)
     459        return error;
     460    fSequenceNumber += packet->DataSize();
     461    if (enqueue)
     462        _EnqueueOutgoingPacket(packet);
     463    return B_OK;
     464}
     465
     466
     467status_t
     468TCPSocket::_ResendQueue()
     469{
     470    TRACE(("TCPSocket::_ResendQueue()\n"));
     471    for (TCPPacket* packet = fFirstSentPacket; packet != NULL;
     472            packet = packet->Next()) {
     473        ChainBuffer buffer((void*)packet->Data(), packet->DataSize());
     474        status_t error = fTCPService->Send(fPort, fRemoteAddress, fRemotePort,
     475            packet->SequenceNumber(), fAcknowledgeNumber, packet->Flags(),
     476            &buffer);
     477        if (error != B_OK)
     478            return error;
     479    }
     480    return B_OK;
     481}
     482
     483
     484void
     485TCPSocket::_EnqueueOutgoingPacket(TCPPacket* packet)
     486{
     487    if (fLastSentPacket != NULL) {
     488        fLastSentPacket->SetNext(packet);
     489        fLastSentPacket = packet;
     490    } else {
     491        fFirstSentPacket = fLastSentPacket = packet;
     492    }
     493}
     494
     495
     496status_t
     497TCPSocket::_Ack()
     498{
     499    TCPPacket* packet = new(nothrow) TCPPacket();
     500    if (packet == NULL)
     501        return B_NO_MEMORY;
     502    status_t error = packet->SetTo(NULL, 0, fAddress, fPort, fRemoteAddress,
     503        fRemotePort, fSequenceNumber, fAcknowledgeNumber, TCP_ACK);
     504    if (error != B_OK)
     505        return error;
     506    error = _Send(packet);
     507    if (error != B_OK)
     508        return error;
     509    return B_OK;
     510}
     511
     512
     513status_t
     514TCPSocket::_WaitForState(TCPSocketState state, bigtime_t timeout)
     515{
     516    if (fTCPService == NULL)
     517        return B_NO_INIT;
     518
     519    bigtime_t startTime = system_time();
     520    do {
     521        fTCPService->ProcessIncomingPackets();
     522        if (fState == state)
     523            return B_OK;
     524    } while (system_time() - startTime < timeout);
     525    return timeout == 0 ? B_WOULD_BLOCK : B_TIMED_OUT;
     526}
     527
     528
     529
     530
     531TCPService::TCPService(IPService* ipService)
     532    :
     533    IPSubService(kTCPServiceName),
     534    fIPService(ipService)
     535{
     536}
     537
     538
     539TCPService::~TCPService()
     540{
     541    if (fIPService != NULL)
     542        fIPService->UnregisterIPSubService(this);
     543}
     544
     545
     546status_t
     547TCPService::Init()
     548{
     549    if (fIPService == NULL)
     550        return B_BAD_VALUE;
     551    if (!fIPService->RegisterIPSubService(this))
     552        return B_NO_MEMORY;
     553    return B_OK;
     554}
     555
     556
     557uint8
     558TCPService::IPProtocol() const
     559{
     560    return IPPROTO_TCP;
     561}
     562
     563
     564void
     565TCPService::HandleIPPacket(IPService* ipService, ip_addr_t sourceIP,
     566    ip_addr_t destinationIP, const void* data, size_t size)
     567{
     568    TRACE(("TCPService::HandleIPPacket(): source = %08lx, destination = %08lx, "
     569        "%lu - %lu bytes\n", sourceIP, destinationIP, size, sizeof(tcp_header)));
     570
     571    if (data == NULL || size < sizeof(tcp_header))
     572        return;
     573
     574    const tcp_header* header = (const tcp_header*)data;
     575    uint16 source = ntohs(header->source);
     576    uint16 destination = ntohs(header->destination);
     577    uint32 sequenceNumber = ntohl(header->seqNumber);
     578    uint32 ackedNumber = ntohl(header->ackNumber);
     579    uint8 flags = 0;
     580    if (header->syn)
     581        flags |= TCP_SYN;
     582    if (header->ack)
     583        flags |= TCP_ACK;
     584    if (header->fin)
     585        flags |= TCP_FIN;
     586    if (header->rst)
     587        flags |= TCP_RST;
     588    TRACE(("\tsource = %u, dest = %u, seq = %lu, ack = %lu, dataOffset = %u, flags %s %s %s %s\n",
     589        source, destination, sequenceNumber, ackedNumber, header->dataOffset,
     590        header->ack ? "ACK" : "", header->syn ? "SYN" : "", header->fin ? "FIN" : "", header->rst ? "RST" : ""));
     591    if (header->dataOffset > 5) {
     592        uint8* option = (uint8*)data + sizeof(tcp_header);
     593        while ((uint32*)option < (uint32*)data + header->dataOffset) {
     594            uint8 optionKind = option[0];
     595            uint8 optionLength = 1;
     596            if (optionKind > 1)
     597                optionLength = option[1];
     598            TRACE(("\tTCP option kind %u, length %u\n", optionKind, optionLength));
     599            option += optionLength;
     600        }
     601    }
     602
     603    uint16 chksum = _ChecksumData(data, size, sourceIP, destinationIP);
     604    if (chksum != 0) {
     605        TRACE(("TCPService::HandleIPPacket(): invalid checksum (%04x)\n", header->checksum));
     606        return;
     607    }
     608
     609    TCPSocket* socket = _FindSocket(destinationIP, destination);
     610    if (socket == NULL) {
     611        //TODO if SYN, answer with RST?
     612        TRACE(("TCPService::HandleIPPacket(): no socket\n"));
     613        return;
     614    }
     615
     616    if (header->ack) {
     617        socket->Acknowledge(ackedNumber);
     618    }
     619
     620    TCPPacket* packet = new(nothrow) TCPPacket();
     621    if (packet == NULL)
     622        return;
     623    status_t error = packet->SetTo((uint32*)data + header->dataOffset,
     624        size - header->dataOffset * 4, sourceIP, source, destinationIP,
     625        destination, sequenceNumber, ackedNumber, flags);
     626    if (error == B_OK)
     627        socket->ProcessPacket(packet);
     628    else
     629        delete packet;
     630}
     631
     632
     633status_t
     634TCPService::Send(uint16 sourcePort, ip_addr_t destinationAddress,
     635    uint16 destinationPort, uint32 sequenceNumber,
     636    uint32 acknowledgmentNumber, uint8 flags, ChainBuffer* buffer)
     637{
     638    TRACE(("TCPService::Send(): seq = %lu, ack = %lu\n", sequenceNumber, acknowledgmentNumber));
     639    if (fIPService == NULL)
     640        return B_NO_INIT;
     641    if (buffer == NULL)
     642        return B_BAD_VALUE;
     643
     644    tcp_header header;
     645    ChainBuffer headerBuffer(&header, sizeof(header), buffer);
     646    memset(&header, 0, sizeof(header));
     647    header.source = htons(sourcePort);
     648    header.destination = htons(destinationPort);
     649    header.seqNumber = htonl(sequenceNumber);
     650    header.ackNumber = htonl(acknowledgmentNumber);
     651    header.dataOffset = 5;
     652    header.ack = (flags & TCP_ACK) != 0;
     653    header.syn = (flags & TCP_SYN) != 0;
     654    header.fin = (flags & TCP_FIN) != 0;
     655    header.rst = (flags & TCP_RST) != 0;
     656    header.window = 0xffff;
     657
     658    header.checksum = 0;
     659    header.checksum = htons(_ChecksumBuffer(&headerBuffer,
     660        fIPService->IPAddress(), destinationAddress,
     661        headerBuffer.TotalSize()));
     662
     663    return fIPService->Send(destinationAddress, IPPROTO_TCP, &headerBuffer);
     664}
     665
     666
     667void
     668TCPService::ProcessIncomingPackets()
     669{
     670    if (fIPService != NULL)
     671        fIPService->ProcessIncomingPackets();
     672}
     673
     674
     675status_t
     676TCPService::BindSocket(TCPSocket* socket)
     677{
     678    if (socket == NULL)
     679        return B_BAD_VALUE;
     680
     681    if (_FindSocket(socket->Address(), socket->Port()))
     682        return EADDRINUSE;
     683
     684    return fSockets.Add(socket);
     685}
     686
     687
     688void
     689TCPService::UnbindSocket(TCPSocket* socket)
     690{
     691    fSockets.Remove(socket);
     692}
     693
     694
     695uint16
     696TCPService::_ChecksumBuffer(ChainBuffer* buffer, ip_addr_t source,
     697    ip_addr_t destination, uint16 length)
     698{
     699    struct pseudo_header {
     700        ip_addr_t   source;
     701        ip_addr_t   destination;
     702        uint8       pad;
     703        uint8       protocol;
     704        uint16      length;
     705    } __attribute__ ((__packed__));
     706    pseudo_header header = {
     707        htonl(source),
     708        htonl(destination),
     709        0,
     710        IPPROTO_TCP,
     711        htons(length)
     712    };
     713
     714    ChainBuffer headerBuffer(&header, sizeof(header), buffer);
     715    uint16 checksum = ip_checksum(&headerBuffer);
     716    headerBuffer.DetachNext();
     717    return checksum;
     718}
     719
     720
     721uint16
     722TCPService::_ChecksumData(const void* data, uint16 length, ip_addr_t source,
     723    ip_addr_t destination)
     724{
     725    ChainBuffer buffer((void*)data, length);
     726    return _ChecksumBuffer(&buffer, source, destination, length);
     727}
     728
     729
     730TCPSocket*
     731TCPService::_FindSocket(ip_addr_t address, uint16 port)
     732{
     733    for (int i = 0; i < fSockets.Count(); i++) {
     734        TCPSocket* socket = fSockets.ElementAt(i);
     735        if ((address == INADDR_ANY || socket->Address() == INADDR_ANY
     736                    || socket->Address() == address)
     737                && socket->Port() == port) {
     738            return socket;
     739        }
     740    }
     741    return NULL;
     742}
  • src/system/boot/loader/net/Jamfile

    diff --git a/src/system/boot/loader/net/Jamfile b/src/system/boot/loader/net/Jamfile
    index 8555a7d..a0c54b2 100644
    a b KernelStaticLibrary boot_net :  
    1314    NetStack.cpp
    1415    RemoteDisk.cpp
    1516    UDP.cpp
     17    TCP.cpp
    1618
    1719    : -fno-pic
    1820;