/*
 * Copyright 2015 Mario Richter, Peter Stephan
 * This file is part of NeMo.
 *
 * NeMo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * NeMo 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with NeMo.  If not, see <http://www.gnu.org/licenses/>.
 */

/*!
 * \file net_tcp.h
 * \ingroup net
 * \brief Headerfile für die Netzwerk-Routinen zur TCP-Kommunikation.
 */

#ifndef TCP_H_
#define TCP_H_


// --------------------------------------
// Defines

// Die folgenden zwei defines beeinflussen maßgeblich den RAM-Verbrauch der Firmware.
// Diese sollten für die jeweilige Anwendung entsprechend angepasst werden, um Speicher zu sparen.

#define TCP_RXTX_BUFLEN             512         //!< Anzahl Bytes für jeweils Sende- und Empfangspuffer
#define TCP_MAX_CONNECTIONS         3           //!< Max. Anzahl gleichzeitig geöffneter Verbindungen

#define TCP_MAX_OPEN_PORTS          8           //!< Anzahl Einträge in der Liste offener Ports

#define TCP_CONN_TIMEOUT            270         //!< Timeout bei Inaktivität in Sekunden
#define TCP_TIMEWAIT_TIME           100         //!< Timeout bei Verbindungsende (*10ms)
#define TCP_ACK_TIMEOUT             70          //!< Timeout für Bestätigung eines gesendeten Packets (*10ms)
#define TCP_WINDOW_LENGTH           512         //!< Fenstergröße für TCP-Packets
#define TCP_ARP_REQUEST_TIMEOUT     30          //!< Timeout / Wartezeit für ARP-Requests bei neuer Verbindung (*10ms)
#define TCP_MAX_REPEAT_CNT          5           //!< Max. Anzahl an Wiederholungen vor Verbindungsabbruch (TCP)
#define TCP_MAX_ARP_REPEAT_CNT      3           //!< Max. Anzahl an Wiederholungen vor Verbindungsabbruch (ARP)

#define TCP_STAT_CLOSED             0           //!< TCP Status: Keine Verbindung
#define TCP_STAT_SYN_SENT           1           //!< TCP Status: Verbindungsaufbau
#define TCP_STAT_SYN_RCVD           2           //!< TCP Status: Verbindungsanforderung
#define TCP_STAT_ESTABLISHED        3           //!< TCP Status: Verbindung hergestellt
#define TCP_STAT_FIN_WAIT_1         4           //!< TCP Status: Verbindungsabbau initiiert (Client)
#define TCP_STAT_FIN_WAIT_2         5           //!< TCP Status: Verbindungsabbau erwartet
#define TCP_STAT_CLOSING            6           //!< TCP Status: Verbindungsabbau simultan
#define TCP_STAT_TIME_WAIT          7           //!< TCP Status: Verbindungsabbau ACK Timer
#define TCP_STAT_CLOSE_WAIT         8           //!< TCP Status: Verbindungsabbau initiiert (Server)
#define TCP_STAT_LAST_ACK           9           //!< TCP Status: Verbindungsabbau ACK erwartet
#define TCP_STAT_ARP_REQUEST        10          //!< TCP Status: ARP Request (MAC-Adresse beziehen)

#define TCP_FLAGS_FIN               1           //!< TCP Flags: FIN (Verbindungsende)
#define TCP_FLAGS_SYN               2           //!< TCP Flags: SYN (Verbindungsaufbau)
#define TCP_FLAGS_RST               4           //!< TCP Flags: RST (Verbindungsreset)
#define TCP_FLAGS_PSH               8           //!< TCP Flags: PSH (Daten pushen)
#define TCP_FLAGS_ACK               16          //!< TCP Flags: ACK (Bestätigung)
#define TCP_FLAGS_URG               32          //!< TCP Flags: URG (Dringend)

#define TCP_HNDL_NEWDATA            1           //!< TCP Handlerflags: Neue Daten verfügbar
#define TCP_HNDL_ESTABLISHED        2           //!< TCP Handlerflags: Neue Verbindung hergestellt
#define TCP_HNDL_CLOSING            3           //!< TCP Handlerflags: Verbindung wird von Remote geschlossen

// --------------------------------------
// Strukturen und Unions

//! Typedef für Zeiger auf jeweilige (vom Anwender zu definierende) connHandler-Funktion
typedef void (*connHandler) (uint8_t, uint8_t);

//! Struktur für die Liste offener Ports und deren Handler-Funktion
typedef volatile struct
{
  uint16_t      port;               //!< TCP-Portnummer
  connHandler   handler;            //!< zugehörige Handlerfunktion
}tcpPortListType;

//! Struktur für die Liste aktiver Verbindungen
typedef volatile struct
{
  uint8_t       remoteIp[4];              //!< IP-Adresse des Remote-Partners
  uint16_t      remotePort;               //!< Port des Remote-Partners
  uint16_t      localPort;                //!< Eigener Port
  uint32_t      sndUNA;                   //!< Erste nicht bestätigte Sequenznummer
  uint32_t      sndNXT;                   //!< Sequenznummer für neue Daten
  uint32_t      sndNXTlast;               //!< Zuletzt gesendete Sequenznummer (falls Paket erneut gesendet werden muss)
  uint32_t      iss;                      //!< Initial gesendete Sequenznummer
  uint32_t      rcvNXT;                   //!< Nächste zu empfangende Sequenz
  uint32_t      irs;                      //!< Initial empfangene Sequenznummer
  uint16_t      timer;                    //!< Lebensdauer (wird bei 0 geschlossen)
  uint8_t       status;                   //!< Status der Verbindung
  connHandler   handler;                  //!< zugehörige Handlerfunktion (Kopie)
  uint8_t       retryCnt;                 //!< Zähler für Wiederholungsversuche
  uint8_t       closeAfterSend;           //!< Wenn != 0, dann Verbindung schließen wenn Sendebuffer leer
  /* ------------------------------------------------------------------ */
  uint8_t       txbuf[TCP_RXTX_BUFLEN];   //!< Sendepuffer
  uint16_t      txwrit;                   //!< Schreibposition im Sendepuffer
  uint16_t      txread;                   //!< Leseposition im Sendepuffer
  /* ----------------------------------------------------------------- */
  uint8_t       rxbuf[TCP_RXTX_BUFLEN];   //!< Empfangspuffer
  uint16_t      rxwrit;                   //!< Schreibposition im Empfangspuffer
  uint16_t      rxread;                   //!< Leseposition im Empfangspuffer
}tcpConnListType;


// --------------------------------------
// Globale Variablen

extern tcpPortListType tcpPortList[];
extern tcpConnListType tcpConnList[];

extern uint16_t tcpInitialSeqCnt;


// --------------------------------------
// Funktionsdeklarationen

uint8_t tcpListen(uint16_t port, connHandler handler);
uint8_t tcpUnlisten(uint16_t port);
uint16_t tcpDataLen(uint8_t index);
uint8_t tcpOpen(uint8_t * ipAddr, uint16_t remotePort, uint16_t localPort, connHandler handler);
uint8_t tcpClose(uint8_t index);
uint8_t tcpSend(uint8_t ind, uint8_t * data, uint8_t len);
void tcpTimer(void);

void tcpShowPortList(uint8_t ind);
void tcpShowConnList(uint8_t ind);
void tcpHandlePacket(pktType * packet);
void tcpCreatePacket(pktType * packet, uint8_t * destMac, uint8_t * destIp, uint16_t destPort, uint16_t srcPort,
                     uint32_t seqNr, uint32_t ackNr, uint16_t len, uint16_t flags, uint16_t window);
uint8_t tcpSetConnStatus(uint8_t index, uint8_t status);
uint8_t tcpGetConnHandle(uint8_t * localIp, uint8_t * remoteIp, uint16_t localPort, uint16_t remotePort);
connHandler tcpGetPortHandler(uint16_t port);
uint8_t tcpCheckListen(pktType * packet);
uint16_t tcpCalcChecksum(pktType * packet);
uint8_t tcpGetFreeConnEntry(void);

#endif /* TCP_H_ */
