/*******************************************************************************
  Microchip TCP/IP Stack Definitions

  Summary:
    
  Description:
*******************************************************************************/

/*******************************************************************************
FileName:  tcpip_manager_control.h 
Copyright © 2012 released Microchip Technology Inc.  All rights
reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
*******************************************************************************/

#ifndef _TCPIP_MANAGER_CONTROL_H_
#define _TCPIP_MANAGER_CONTROL_H_

#include "tcpip/tcpip_mac.h"



#if defined (TCPIP_IF_MRF24W)
    #include "wf_config.h" // pull in additional defines from wireless settings
#endif

#if defined(TCPIP_STACK_USE_SNMP_SERVER)
	#include "snmp_config.h"
#endif

typedef enum
{
    TCPIP_STACK_ADDRESS_SERVICE_NONE    = 0,    // no service
    TCPIP_STACK_ADDRESS_SERVICE_DHCPC,          // DHCP client
    TCPIP_STACK_ADDRESS_SERVICE_ZCLL,           // ZCLL
    TCPIP_STACK_ADDRESS_SERVICE_DHCPS,          // DHCP server
    //
    TCPIP_STACK_ADDRESS_SERVICE_MASK    = 0x7,     // mask of address services
                                                // hast to match the position in the TCPIP_STACK_NET_IF_FLAGS!!!
}TCPIP_STACK_ADDRESS_SERVICE_TYPE;

typedef enum
{
    TCPIP_STACK_ADDRESS_SERVICE_EVENT_NONE    = 0,      // no event
    TCPIP_STACK_ADDRESS_SERVICE_EVENT_RUN_FAIL,         // run time failure event
    TCPIP_STACK_ADDRESS_SERVICE_EVENT_CONN_LOST,        // conn lost event
    TCPIP_STACK_ADDRESS_SERVICE_EVENT_USER_STOP,        // user stop event
}TCPIP_STACK_ADDRESS_SERVICE_EVENT;


typedef union
{
    struct
    {
        // stack configuration dynamic flags
        uint16_t bIsDHCPEnabled         : 1;    // init: controls the DHCP enable/disable on the interface
                                                // runtime: mirror bit set by the DHCP to reflect the current/last status
        uint16_t bIsZcllEnabled         : 1;    // init: controls the ZCLL service enable/disable on the interface
                                                // runtime: mirror bit set by the ZCLL Server to reflect the current/last status
        uint16_t bIsDHCPSrvEnabled      : 1;    // init: controls the DHCP Server enable/disable on the interface
                                                // runtime: mirror bit set by the DHCP Server to reflect the current/last status
                                                // TCPIP_STACK_ADDRESS_SERVICE_MASK has to match!!!
        uint16_t bIsDNSServerAuto       : 1;    // DNS Server auto enable/disable on this interface
        uint16_t bInterfaceEnabled      : 1;    // 0 when TCPIP_MAC_POWER_DOWN/TCPIP_MAC_POWER_LOW 
        uint16_t bIPv6Enabled           : 1;
        uint16_t bIPv6InConfig          : 1;
volatile uint16_t bNewTcpipEventAvlbl   : 1;    // event available flag
        uint16_t powerMode              : 3;    // current power mode
        uint16_t localAndType           : 2;    // type of AND operation to be performed for local/nonlocal detection
        uint16_t localOrType            : 2;    // type of OR operation to be performed for local/nonlocal detection

        // available
        uint16_t reserved : 1;      // not used
    };
    uint16_t v;
}TCPIP_STACK_NET_IF_FLAGS;      // flags per interface

// network interface descriptor
// 4 bytes aligned!
typedef struct
{
    uint16_t        size;                   // structure size; used in the configuration save/restore
    uint16_t        macId;                  // corresponding MAC id
	IPV4_ADDR		netIPAddr;              // IP address; currently only one IP add per interface
	IPV4_ADDR		netMask;                // Subnet mask
	IPV4_ADDR		netGateway;             // Gateway
	IPV4_ADDR		PrimaryDNSServer;       // Primary DNS Server
	IPV4_ADDR		SecondaryDNSServer;     // Secondary DNS Server
	IPV4_ADDR		DefaultIPAddr;          // Default IP address
	IPV4_ADDR		DefaultMask;            // Default subnet mask
	IPV4_ADDR		DefaultGateway;         // Default Gateway
	IPV4_ADDR		DefaultDNSServer;       // Default DNS Server
	IPV4_ADDR		DefaultDNSServer2;      // Default Secondary DNS Server
	uint8_t		    NetBIOSName[16];        // NetBIOS name
	MAC_ADDR	    netMACAddr;             // MAC address
    TCPIP_STACK_NET_IF_FLAGS Flags;
    TCPIP_NETWORK_CONFIG_FLAGS startFlags;  // flags for interface start up

}TCPIP_STACK_NET_IF_DCPT;

#include "tcpip/tcpip_helpers.h"
#include "tcpip_helpers_private.h"

// TCPIP network structure containing interface information
//  
typedef struct
{
    struct  // TCPIP_STACK_NET_IF_DCPT!!!; Anonymous for now;
    // KEEP IN SYNC! ALIGNED! ALWAYS AT BEGINNING!
    {
        uint16_t        size;                   // structure size; used in the configuration save/restore
        uint16_t        macId;                  // corresponding MAC id
        IPV4_ADDR		netIPAddr;              // IP address; currently only one IP add per interface
        IPV4_ADDR		netMask;                // Subnet mask
        IPV4_ADDR		netGateway;             // Gateway
        IPV4_ADDR		PrimaryDNSServer;       // Primary DNS Server
        IPV4_ADDR		SecondaryDNSServer;     // Secondary DNS Server
        IPV4_ADDR		DefaultIPAddr;          // Default IP address
        IPV4_ADDR		DefaultMask;            // Default subnet mask
        IPV4_ADDR		DefaultGateway;         // Default Gateway
        IPV4_ADDR		DefaultDNSServer;       // Default DNS Server
        IPV4_ADDR		DefaultDNSServer2;      // Default Secondary DNS Server
        uint8_t		    NetBIOSName[16];        // NetBIOS name
        MAC_ADDR	    netMACAddr;             // MAC address
        TCPIP_STACK_NET_IF_FLAGS Flags;
        TCPIP_NETWORK_CONFIG_FLAGS startFlags;  // flags for interface start up

    };

    // NOTE the alignmment!
    IPV4_ADDR           localAndMask;           // AND mask for local/nonlocal destination network detection 
    IPV4_ADDR           localOrMask;            // OR mask for local/nonlocal destination network detection 
    
    TCPIP_MAC_HANDLE    hIfMac;                 // quick reference to which MAC this interface belongs to
                                                // ((__aligned__)) !!!
#if defined(TCPIP_STACK_USE_EVENT_NOTIFICATION)
    SINGLE_LIST         registeredClients;      // stack notification clients
                                                // ((__aligned__)) !!!
#endif  // defined(TCPIP_STACK_USE_EVENT_NOTIFICATION)
    uint16_t            netIfIx;                // index of this entry in the tcpipNetIf table.
                                                // netIfIx = (this - &tcpipNetIf[0])/sizeof(TCPIP_NET_IF)
                                                // stored to avoid the run time division
    uint16_t            activeEvents;           // TCPIP_EVENT accumulated event available
                                                // TCPIP_EVENT fits within 16 bits!
                                                // link up/down events are not 
                                                // necessarily triggered by hardware
    uint8_t             linkPrev;               // previous status of the link
} TCPIP_NET_IF;


// network storage configuration descriptor
// this network configuration is saved to the external storage
// NOTE: this structure is EXACTLY the same as the 1st part of the TCPIP_NET_IF
// so that the TCPIP_NET_IF <-> TCPIP_NET_STORAGE functions are trivial (memcpy, see below).
// Keep them in SYNC!
typedef struct __attribute__((__packed__)) 
{
	IPV4_ADDR		netIPAddr;              // IP address; currently only one IP add per interface
	IPV4_ADDR		netMask;                // Subnet mask
	IPV4_ADDR		netGateway;             // Default Gateway
	IPV4_ADDR		PrimaryDNSServer;       // Primary DNS Server
	IPV4_ADDR		SecondaryDNSServer;     // Secondary DNS Server
	IPV4_ADDR		DefaultIPAddr;          // Default IP address
	IPV4_ADDR		DefaultMask;            // Default subnet mask
	uint8_t		    NetBIOSName[16];        // NetBIOS name
	MAC_ADDR	    netMACAddr;              // Application MAC address

    uint16_t        macId;                  // corresponding MAC id
}TCPIP_NET_STORAGE;

// TCPIP stack event registration

typedef struct  _TAG_TCPIP_LIST_NODE
{
	struct _TAG_TCPIP_LIST_NODE *next;	// next node in list
                                                // safe cast to SGL_LIST_NODE node!!!
    TCPIP_STACK_EVENT_HANDLER   handler;    // handler to be called for event
    const void*                 hParam;     // handler parameter
    TCPIP_EVENT                 evMask;     // event that triggers the notification
    TCPIP_NET_IF*               pNetIf;     // interface it belongs to
}TCPIP_EVENT_LIST_NODE;


// network interface action for initialization/de-initialization
typedef enum
{
    TCPIP_STACK_ACTION_INIT,         // stack is initialized 
    TCPIP_STACK_ACTION_REINIT,       // stack is re-initialized
    TCPIP_STACK_ACTION_DEINIT,       // stack is de-initialized
    TCPIP_STACK_ACTION_IF_UP,        // interface is brought up 
    TCPIP_STACK_ACTION_IF_DOWN,      // interface is brought down
}TCPIP_STACK_ACTION;


// data that's passed as reference to each other module init/deinit, etc
typedef struct _TCPIP_STACK_MODULE_CTRL
{
    // permanent data; this data is maintained by the stack for one full session
    // i.e. accross StackInit() -> StackDeInit() calls
    // 
    //
    // number of the interfaces supported in this seession
    int     nIfs;         
	// number of the modules enabled in this session
	int 	nMdls;
    // allocation parameters
    const void* memH;                                   // handle to be used in the TCPIP_HEAP_ calls

    // transient data; contains info for a specific call
    //
    //
    // pointer to the current interface
    TCPIP_NET_IF* pNetIf;
    // index of the current interface addressed
    int     netIx;
    // current action for the stack
    TCPIP_STACK_ACTION      stackAction;
    // the power mode for this interface to go to
    // valid only if stackAction == init/re-init; ignored for de-init
    TCPIP_MAC_POWER_MODE  powerMode;
    
}TCPIP_STACK_MODULE_CTRL;


// copies a TCPIP_NET_IF struct to a TCPIP_NET_STORAGE one
// NOTE: the TCPIP_NET_STORAGE is EXACTLY the same as the 1st part of the TCPIP_NET_IF
// Keep them in SYNC!
extern __inline__ void __attribute__((always_inline)) _TCPIPStackCpyNetIfToStorageEntry(TCPIP_NET_STORAGE* pDst, TCPIP_NET_HANDLE netH)
{
    memcpy(pDst, (TCPIP_NET_IF*)netH, sizeof(*pDst));
}

// copies a TCPIP_NET_STORAGE struct to a TCPIP_NET_IF one
// NOTE: the TCPIP_NET_STORAGE is EXACTLY the same as the 1st part of the TCPIP_NET_IF
// Keep them in SYNC!
extern __inline__ void __attribute__((always_inline)) _TCPIPStackCpyStorageEntryToNetIf(TCPIP_NET_HANDLE netH, const TCPIP_NET_STORAGE* pSrc)
{
    memcpy((TCPIP_NET_IF*)netH, pSrc, sizeof(*pSrc));
}

TCPIP_NET_IF*         _TCPIPStackIpAddToNet(IPV4_ADDR* pIpAddress, bool useDefault);

TCPIP_NET_IF*         _TCPIPStackIpAddFromNet(TCPIP_NET_IF* pNetIf, IPV4_ADDR* pIpAddress);

int  _TCPIPStackNetIx(TCPIP_NET_IF* pNetIf);


uint32_t  _TCPIPStackNetAddress(TCPIP_NET_IF* pNetIf);

void  _TCPIPStackSetNetAddress(TCPIP_NET_IF* pNetIf, IPV4_ADDR* ipAddress, IPV4_ADDR* mask, bool setDefault);


uint32_t  _TCPIPStackNetMask(TCPIP_NET_IF* pNetIf);

void  _TCPIPStackSetGatewayAddress(TCPIP_NET_IF* pNetIf, IPV4_ADDR* ipAddress);
void  _TCPIPStackSetPriDNSAddress(TCPIP_NET_IF* pNetIf, IPV4_ADDR* ipAddress);

void  _TCPIPStackSetSecondDNSAddress(TCPIP_NET_IF* pNetIf, IPV4_ADDR* ipAddress);

TCPIP_NET_IF*         _TCPIPStackNetByAddress(IPV4_ADDR* pIpAddress);


bool  _TCPIPStackIsAddressOfNet( TCPIP_NET_IF* pNetIf, IPV4_ADDR* pIpAdd);

// detects net-directed bcast
bool  _TCPIPStackIsNetBcastAddress(TCPIP_NET_IF* pNetIf, IPV4_ADDR* pIpAdd);

// detects limited or net-directed bcast
bool  _TCPIPStackIsBcastAddress(TCPIP_NET_IF* pNetIf, IPV4_ADDR* pIpAdd);

bool  _TCPIPStackIsNetUp(TCPIP_NET_IF* pNetIf);

bool  _TCPIPStackIsNetLinked(TCPIP_NET_IF* pNetIf);

TCPIP_NET_IF*         _TCPIPStackMacIdToNet(TCPIP_STACK_MODULE macId);

TCPIP_STACK_MODULE  _TCPIPStackNetMacId(TCPIP_NET_IF* pNetIf);

TCPIP_NET_IF*     _TCPIPStackMacToNet(TCPIP_MAC_HANDLE hMac);

TCPIP_MAC_HANDLE  _TCPIPStackNetToMac(TCPIP_NET_IF* pNetIf);

int         _TCPIPStackMacToNetIx(TCPIP_MAC_HANDLE hMac);



const uint8_t*  _TCPIPStackNetMacAddress(TCPIP_NET_IF* pNetIf);

extern __inline__ TCPIP_NET_IF*  __attribute__((always_inline)) _TCPIPStackHandleToNet(TCPIP_NET_HANDLE hNet)
{
    // do some checking
    // if #debug enabled, etc
    return hNet?(TCPIP_NET_IF*)hNet:0;
}

// detects if an IP address is a local network
bool    _TCPIPStackIsLocalNetwork(TCPIP_NET_IF* pNetIf, IPV4_ADDR destIpAdd);

// converts between an interface name and a MAC (TCPIP_STACK_MODULE) ID 
// TCPIP_MODULE_MAC_NONE - no MAC id could be found
TCPIP_STACK_MODULE    _TCPIPStackStringToMACId(const char* str);

// string (interface name) corresponding to the given MAC id.
// NULL if no such MAC id.
const char*     _TCPIPStackMACIdToString(TCPIP_STACK_MODULE macId);

// helper to select an address service for interface
TCPIP_STACK_ADDRESS_SERVICE_TYPE _TCPIPStackAddressServiceSelect(TCPIP_NET_IF* pNetIf, TCPIP_NETWORK_CONFIG_FLAGS configFlags);

// helper to decide if an address service can be started
bool    _TCPIPStackAddressServiceCanStart(TCPIP_NET_IF* pNetIf, TCPIP_STACK_ADDRESS_SERVICE_TYPE adSvcType);

// notification helper that an address service has some stop event
void    _TCPIPStackAddressServiceEvent(TCPIP_NET_IF* pNetIf, TCPIP_STACK_ADDRESS_SERVICE_TYPE adSvcType, TCPIP_STACK_ADDRESS_SERVICE_EVENT evType);

// address service default status
void    _TCPIPStackAddressServiceSetDefault(TCPIP_NET_IF* pNetIf);

#endif  // _TCPIP_MANAGER_CONTROL_H_


