/*
 * Core definitions for DCCP-TP
 *
 * Copyright (C) 2008 Tom Phelan
 *
 * This file is part of dccp-tp.
 *
 * Dccp-tp is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Dccp-tp is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with dccp-tp.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Documentation and source code for dccp-tp is available at
 * http://www.phelan-4.com/dccp-tp/.
 */

#ifndef _DCTPACORE_H_
#define _DCTPACORE_H_

#include "dctpSupportTypes.h"     /* Get platform-specific types */

typedef unsigned int uint_t;

#define DCTP_AF_INET6  10
#define DCTP_PF_INET6  DCTP_AF_INET6

typedef struct _dctpV6Addr {
    uint8_t s_addr[16];
} dctpV6Addr;

typedef struct _dctpSockaddrV6 {
    uint16_t sin6_family;
    uint16_t sin6_port;
    uint32_t sin6_flowinfo;
    dctpV6Addr sin6_addr;
    uint32_t sin6_scope_id;
} dctpSockaddrV6;

typedef struct _dctpSockaddr {
    uint16_t sa_family;
    uint16_t sa_port;
    uint8_t sa_addr[sizeof(dctpSockaddrV6)];
} dctpSockaddr;

typedef struct _dctpV4Addr {
    uint32_t s_addr;
} dctpV4Addr;

#define DCTP_AF_INET   2
#define DCTP_PF_INET   DCTP_AF_INET
#define DCTP_INADDRANY 0
#define DCTP_INADDR_LOOPBACK 0x7f000001

typedef struct _dctpSockaddrV4 {
    uint16_t sin_family;
    uint16_t sin_port;
    dctpV4Addr sin_addr;
} dctpSockaddrV4;

typedef struct _dctpUdpHdr {
    uint16_t sport;
    uint16_t dport;
    uint16_t csumcov;
    uint16_t csum;
} dctpUdpHdr;

typedef struct _dctpTimer {
    struct _dctpTimer *next;
    struct _dctpTimer *prev;
    uint64_t expires;
    uint_t running;
    void (*action)(void *);
    void *arg;
} dctpTimer;

typedef void (*dctpTimerAction)(void *);

/* Feature defines */
#define DCTPFEAT_CCID             1
#define DCTPFEAT_ALLOWSHORTSEQNOS 2
#define DCTPFEAT_SEQWINDOW        3
#define DCTPFEAT_ECNINCAPABLE     4
#define DCTPFEAT_ACKRATIO         5
#define DCTPFEAT_SENDACKVECTOR    6
#define DCTPFEAT_SENDNDPCOUNT     7
#define DCTPFEAT_MINCSUMCOV       8
#define DCTPFEAT_CHECKDATACSUM    9
#define DCTPFEAT_MAXFEATNO        9

#define DCTPFEAT_CCIDDEF          2
#define DCTPFEAT_SEQWINDOWDEF     100
#define DCTPFEAT_ACKRATIONDEF     2
#define DCTPFEAT_CCIDSIZE         4
#define DCTPFEAT_MAXTIMEOUT       64000000  /* 64 seconds */

#define DCTPFEAT_STABLE           0
#define DCTPFEAT_CONFIRMING       1
#define DCTPFEAT_CHANGING         2
#define DCTPFEAT_MANCHANGE        3
#define DCTPFEAT_UNSTABLE         4
#define DCTPFEAT_MANUNSTABLE      6

typedef struct _dctpFeatures {
    uint8_t ccid[DCTPFEAT_CCIDSIZE];
    uint8_t allowShortSeqnos;
    uint8_t ecnIncapable;
    uint8_t sendAckVector;
    uint8_t sendNDPCount;
    uint8_t minCsumCov;
    uint8_t checkDataCsum;
    uint16_t ackRatio;
    uint64_t seqWindow;
} dctpFeatures;

/* Value for dctpSocket.magic */
#define DCTPSOCK_MAGICNO 0x44435450  /* Hex "DCTP" */

/* Values for dctpSocket.encap */
#define DCTPENCAP_RAWANY 1
#define DCTPENCAP_NATANY 2
#define DCTPENCAP_V4ANY  4
#define DCTPENCAP_V6ANY  8
#define DCTPENCAP_RAW    (DCTPENCAP_RAWANY | DCTPENCAP_V4ANY)
#define DCTPENCAP_NAT    (DCTPENCAP_NATANY | DCTPENCAP_V4ANY)
#define DCTPENCAP_RAW6   (DCTPENCAP_RAWANY | DCTPENCAP_V6ANY)
#define DCTPENCAP_NAT6   (DCTPENCAP_NATANY | DCTPENCAP_V6ANY)

/* Values for dctpSocket.state */
#define DCTPSOCK_CLOSED     0
#define DCTPSOCK_CREATED    1
#define DCTPSOCK_LISTEN     2
#define DCTPSOCK_BOUND      3
#define DCTPSOCK_REQUEST    4
#define DCTPSOCK_RESPOND    5
#define DCTPSOCK_PARTOPEN   6
#define DCTPSOCK_OPEN       7
#define DCTPSOCK_CLOSEREQ   8
#define DCTPSOCK_CLOSING    9
#define DCTPSOCK_TIMEWAIT   10

/* Values for socket options */
#define DCTPSOCKOPT_LOCALCCID            1
#define DCTPSOCKOPT_REMOTECCID           2
#define DCTPSOCKOPT_LOCALSENDACKVECTOR   3
#define DCTPSOCKOPT_REMOTESENDACKVECTOR  4

/* Values for dctpSocket.flags */
#define DCTPSOCK_O_NONBLOCK       0x00000001
#define DCTPSOCK_O_SHORTSEQ       0x00000002
#define DCTPSOCK_O_INITCOOKIE     0x00000004
#define DCTPSOCK_O_ECNINCAPABLE   0x00000008
#define DCTPSOCK_O_CHECKDATACSUM  0x00000010

/* Values for dctpSocket.*qlen */
#define DCTPSOCK_DEF_MAXPKTQLEN   32

#define DCTPSOCK_MAXEMPTYCONFIRMS 16

typedef struct _dctpSocket {
    uint32_t magic;              /* Set to DCTPSOCK_MAGICNO for valid sockets */
    uint32_t state;
    uint32_t scode;
    uint32_t destroy;
    uint32_t backlog;
    uint32_t flags;              /* Socket options */
    uint32_t xpktqlen;
    uint32_t mxpktqlen;
    uint32_t rpktqlen;
    uint32_t mrpktqlen;
    uint32_t server;
    uint32_t timeval;
    uint32_t reqDataQd;
    uint64_t iss;
    uint64_t gss;
    uint64_t gas;
    uint64_t awl;
    uint64_t awlinit;
    uint64_t awh;
    uint64_t gar;
    uint64_t isr;
    uint64_t gsr;
    uint64_t swl;
    uint64_t swh;
    uint64_t osr;
    uint64_t fgsr;
    uint64_t fgss;
    uint64_t lastRcvTime;
    uint8_t encap;
    uint8_t sendFeatureNegotiation;
    uint8_t featureNegotiationInProgress;
    dctpFeatures localFeatsCurr;
    dctpFeatures localFeatsDesired;
    uint8_t localFeatsState[DCTPFEAT_MAXFEATNO + 1];
    dctpFeatures remoteFeatsCurr;
    dctpFeatures remoteFeatsDesired;
    uint8_t remoteFeatsState[DCTPFEAT_MAXFEATNO + 1];
    uint8_t emptyConfirms[DCTPSOCK_MAXEMPTYCONFIRMS];
    dctpSockaddr localAddr;
    dctpSockaddr remoteAddr;
    struct _dctpSocket *nextWaiting;
    struct _dctpSocket *nextHash;
    struct _dctpSocket *parent;
    struct _dctpPacket *firstXpkt;
    struct _dctpPacket *lastXpkt;
    struct _dctpSocket *firstWaiting;
    struct _dctpSocket *lastWaiting;
    struct _dctpPacket *firstRpkt;
    struct _dctpPacket *lastRpkt;
    struct _dctpCcidSenderFuncs *ccidSenderFuncs;
    void *ccidSenderInfo;
    struct _dctpCcidRcvrFuncs *ccidRcvrFuncs;
    void *ccidRcvrInfo;
    struct _dctpInitCookie *cookie;
    dctpSupportMutex_t socklock;
    dctpSupportCond_t sockwait;
    dctpTimer timer;
    dctpTimer featTimer;
    dctpTimer fdelay;
    uint32_t fdelayTime;
    uint32_t featTimeval;
    uint32_t pendingTimestampEcho;
    uint32_t pendingTimestamp;
    uint64_t pendingTimestampRcvd;
    uint_t getRcvTime:1;
    uint_t useDataAck:1;
    uint_t destroyed:1;
} dctpSocket;

typedef struct _dctpDccpCanonHdr {
    /* Values in host byte order, except ports */
    uint16_t sport;
    uint16_t dport;
    uint16_t doffset;     /* doffset is in bytes, not words */
    uint8_t type;
    uint8_t ecn;
    unsigned ccval:4;
    unsigned hasAck:1;
    unsigned shortSeq:1;
    unsigned hasSC:1;
    unsigned hasReset:1;
    uint64_t seqno;
    uint64_t ackno;       /* Only valid if hasAck is nonzero */
    uint32_t scode;
    uint8_t rcode, rdata1, rdata2, rdata3;
    uint8_t *options;
} dctpDccpCanonHdr;

/* Values for dctpPacket */
#define DCTPPKT_DEF_HDRSPACE  128

typedef struct _dctpPacket {
    uint8_t *appdata;
    uint8_t *dccphdr;
    uint8_t *iphdr;
    uint16_t appdatalen;
    uint16_t dccphdrlen;
    struct _dctpPacket *nextPkt;
    dctpDccpCanonHdr chdr;
    uint32_t buflen;
    uint8_t buf[4];
} dctpPacket;

/*
 * Error codes
 */
#define DCTP_EWOULDBLOCK   11
#define DCTP_ENOMEM        12
#define DCTP_EINVAL        22
#define DCTP_EBADFD        77
#define DCTP_ENOTSOCK      88
#define DCTP_ENOPROTOOPT   92
#define DCTP_EADDRINUSE    98
#define DCTP_EADDRNOTAVAIL 99
#define DCTP_ECONNREFUSED  111

/*
 * dctpoLog priorities, values should be same as syslog priorities
 */
#define DCTPLOG_EMERG   0
#define DCTPLOG_ALERT   1
#define DCTPLOG_CRIT    2
#define DCTPLOG_ERR     3
#define DCTPLOG_WARNING 4
#define DCTPLOG_NOTICE  5
#define DCTPLOG_INFO    6
#define DCTPLOG_DEBUG   7

/*
 * Useful constants
 */
#define DCTP_24BITMASK   ((uint64_t)0x0000000000ffffff)
#define DCTP_32BITMASK   ((uint64_t)0x00000000ffffffff)
#define DCTP_48BITMASK   ((uint64_t)0x0000ffffffffffff)
#define DCTP_64thBITMASK ((uint64_t)0x8000000000000000)

#define DCTP_MSLTIME     120000000   /* Two minutes in microseconds */
#define DCTP_TIMEWAITTIME (DCTP_MSLTIME*2)
#define DCTP_INITIALRTT  200000      /* 200 ms in usecs */

#define DCTP_MAXPKTSIZE     1500
#define DCTP_DEFAULTNATPORT 50002

#define DCTP_INITIALRQTIMEOUT   1000000    /* One second */
#define DCTP_MAXREQUESTTIMEOUT  64000000   /* 64 seconds */
#define DCTP_MAXPARTOPENTIMEOUT 240000000  /* 4 minutes */
#define DCTP_MAXCLOSETIMEOUT    64000000   /* 64 seconds */
#define DCTP_INITRTO            3000000    /* 3 seconds */

#define DCTP_MINSCODETXTLEN   3
#define DCTP_MAXSCODETXTLEN   13
#define DCTP_MAXASCIISCODELEN 7
#define DCTP_INVALIDSCODE     0xffffffff

#define DCTP_NATMINPKTLEN     12

#define DCTP_DYNAMICPORTSTART 49152

/*
 * DCCP Packet types
 */
#define DCTPPKT_REQUEST   0
#define DCTPPKT_RESPONSE  1
#define DCTPPKT_DATA      2
#define DCTPPKT_ACK       3
#define DCTPPKT_DATAACK   4
#define DCTPPKT_CLOSEREQ  5
#define DCTPPKT_CLOSE     6
#define DCTPPKT_RESET     7
#define DCTPPKT_SYNC      8
#define DCTPPKT_SYNCACK   9

/*
 * Reset codes
 */
#define DCTPRESET_UNSPECIFIED       0
#define DCTPRESET_CLOSED            1
#define DCTPRESET_ABORTED           2
#define DCTPRESET_NOCONNECTION      3
#define DCTPRESET_PACKETERROR       4
#define DCTPRESET_OPTIONERROR       5
#define DCTPRESET_MANDATORYERROR    6
#define DCTPRESET_CONNECTIONREFUSED 7
#define DCTPRESET_BADSERVICECODE    8
#define DCTPRESET_TOOBUSY           9
#define DCTPRESET_BADINITCOOKIE     10
#define DCTPRESET_AGRESSIONPENALTY  11

/*
 * ECN constants
 */
#define DCTPECN_MARKED  3
#define DCTPECN_ECN1    2

/*
 * Format of decoded init cookie
 */
typedef struct _dctpInitCookie {
    /* Fill in later */
    struct _dctpSocket *sock;
    uint64_t iss;
    uint64_t isr;
} dctpInitCookie;

/*
 * Interface to CCIDs
 */
typedef struct _dctpCcidSenderFuncs {
    int (*rcvAckblePacket)(dctpSocket *, dctpPacket *);
    uint32_t (*getCurrentRTO)(dctpSocket *);
    int (*processCcidOption)(dctpSocket *, dctpPacket *, uint_t, uint_t, uint8_t *);
    void (*rcvdSlowRcvr)(dctpSocket *);
    void (*rcvdDataDropped)(dctpSocket *, uint64_t, uint8_t *, uint_t);
    uint64_t (*rcvdAckVector)(dctpSocket *, uint64_t, uint8_t *, uint_t, uint_t);
    void (*rcvdNdpCount)(dctpSocket *, dctpPacket *, uint64_t);
    void (*rcvdTimestampEcho)(dctpSocket *, uint32_t, uint32_t);
    void (*rcvdElapsedTime)(dctpSocket *, uint64_t, uint32_t);
    void (*addOptions)(dctpSocket *, dctpPacket *, uint8_t *, uint_t *);
    int (*dataXmtOK)(dctpSocket *, uint_t);
    int (*xmtPkt)(dctpSocket *, dctpPacket *);
    void (*destroyCcidInfo)(dctpSocket *);
} dctpCcidSenderFuncs;

typedef struct _dctpCcidRcvrFuncs {
    int (*rcvAckblePacket)(dctpSocket *, dctpPacket *);
    int (*processCcidOption)(dctpSocket *, uint_t, uint_t, uint8_t **);
    void (*ackAcked)(dctpSocket *, uint64_t, uint8_t);
    void (*addOptions)(dctpSocket *, dctpPacket *, uint8_t *, uint_t *);
    void (*destroyCcidInfo)(dctpSocket *);
} dctpCcidRcvrFuncs;

/*
 * Option types
 */
#define DCTPOPTION_PADDING       0
#define DCTPOPTION_MANDATORY     1
#define DCTPOPTION_SLOWRECEIVER  2
#define DCTPOPTION_CHANGEL       32
#define DCTPOPTION_CONFIRML      33
#define DCTPOPTION_CHANGER       34
#define DCTPOPTION_CONFIRMR      35
#define DCTPOPTION_INITCOOKIE    36
#define DCTPOPTION_NDPCOUNT      37
#define DCTPOPTION_ACKVECTORN0   38
#define DCTPOPTION_ACKVECTORN1   39
#define DCTPOPTION_DATADROPPED   40
#define DCTPOPTION_TIMESTAMP     41
#define DCTPOPTION_TIMESTAMPECHO 42
#define DCTPOPTION_ELAPSEDTIME   43
#define DCTPOPTION_DATACHECKSUM  44

#define DCTPOPTION_1BYTEMAX              31
#define DCTPOPTION_MINLENGTH             2
#define DCTPOPTION_FEATMINLENGTH         3
#define DCTPOPTION_TIMESTAMPLENGTH       6
#define DCTPOPTION_TIMESTAMPECHOSMALLLEN 6
#define DCTPOPTION_TIMESTAMPECHOMEDLEN   8
#define DCTPOPTION_TIMESTAMPECHOLONGLEN  10
#define DCTPOPTION_ELAPSEDTIMESMALL      4
#define DCTPOPTION_ELAPSEDTIMELARGE      6
#define DCTPOPTION_CCIDOPSTART           128
#define DCTPOPTION_CCIDOPEND             255
#define DCTPOPTION_NDPCOUNTMAXLEN        8
#define DCTPOPTION_MAXLEN                976
#define DCTPOPTION_DDROP_NORMALBIT       0x80
#define DCTPOPTION_DDROP_RUNLEN          0x0f
#define DCTPOPTION_DDROP_PROTOCONSTRAINT 0x80
#define DCTPOPTION_DDROP_APPNOTLISTENING 0x90
#define DCTPOPTION_DDROP_RCVBUFFER       0xa0

#endif  /* _DCTPACORE_H_ */

