Ticket #5240: 0001-Add-boot-loader-TCP-support.patch

File 0001-Add-boot-loader-TCP-support.patch, 26.8 KB (added by andreasf, 14 years ago)

proposed patch

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

    From 33eb6fa2ef20950d4ee6a950be353357ba01440a Mon Sep 17 00:00:00 2001
    From: Andreas Faerber <andreas.faerber@web.de>
    Date: Sun, 23 May 2010 16:03:05 +0200
    Subject: [PATCH] Add boot loader TCP support
    
    ---
     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/Jamfile         |    1 +
     src/system/boot/loader/net/NetDefs.cpp     |    1 +
     src/system/boot/loader/net/NetStack.cpp    |   13 +-
     src/system/boot/loader/net/TCP.cpp         |  768 ++++++++++++++++++++++++++++
     7 files changed, 968 insertions(+), 1 deletions(-)
     create mode 100644 headers/private/kernel/boot/net/TCP.h
     create mode 100644 src/system/boot/loader/net/TCP.cpp
    
    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/Jamfile

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