/*
1Ser1Cli.c: Supports one server and one Client for TCP port 10000

Compiler: BC++ 3.1, 
          Turbo C++ 1.01(3.01) (free from http://cc.codegear.com/free/cpp)
          
Project: Server.c
         ..\lib\7186el.lib
         ..\lib\tcp_dm32.lib
         ..\lib\FW_nnnnn.lib
         
Hordware: uPAC-7186EX

[Dec 18, 2008] by Liam
*/

#include <conio.h>
#include <stdio.h>
#include "..\lib\7186e.h"
#include "..\lib\Tcpip32.h"
#include "..\lib\MFW.h"

#define CMDPORT 10000
#define BUFSIZE 1460       /* read/write buffer size */

void do_echo( int skt , int mode);
void do_GetResponse( int skt); //TCP client's callback function
void ShowSocketStatus(void);

TCP_CLIENT TcpClient;
TCP_SERVER TcpServer;

unsigned char MyIp[4];

char *GetModuleName(void)   /* User's program must support this function for UDP search */ 
{
    return "uPAC-7186EX-FW" ;
}


char *GetAliasName(void)    /* User's program must support this function for UDP search */ 
{
    return "test1" ;
} 

void XS_UserInit(int argc,char *argv[])
{
    extern int bAcceptBroadcast;
    extern unsigned long ACKDELAY;  /* vaariable in tcp.c */
    extern long MAXTXTOUT;
    void UserLoop(void);
    
    char version[20];
    char slocalIP[17];
    char MsgTest[]="command";
    int MsgTest_len=sizeof(MsgTest); 
    
    InitLib();
    Print("sizeof(MsgTest)=%d\r\n",MsgTest_len);
    bAcceptBroadcast=0;
    ACKDELAY=200;
    XS_GetVersion(version);
    Print("[X-Server library]: version=%s ",version);
    XS_GetLibDate(version);
    Print("date=%s\r\n",version);
    GetTcpipLibDate(version);
    Print("Tcpip library version:%X, Library Date is %s\r\n",GetTcpipLibVer(),version);
    GetIp(MyIp);
    sprintf(slocalIP,"%d.%d.%d.%d",MyIp[0],MyIp[1],MyIp[2],MyIp[3]);
    Print("IP=%s\r\n", slocalIP);

    XS_AddSystemLoopFun(UserLoop);
    
    TcpClient.ip="10.0.9.49";             //  default IP
    TcpClient.port=CMDPORT;               //  unsigned port;
    TcpClient.socket=0;                   //  int socket;
    TcpClient.tmpState=0;                 //  int tmpState;
    TcpClient.bConnected=-1;              //  int bConnected;
    TcpClient.iConnectTryCount=1;         //  int iConnectTryCount;   //連線不成功時重試次數
    TcpClient.lConnetTimeout=4000;        // 等連線成功的 timeout 時間。(0 就用預設值 400ms)
    TcpClient.ltmpT=0;                    //  long    ltmpT;
    TcpClient.CallBackFun=do_GetResponse; //void  (*CallBackFun)(int skt);
    TcpClient.LoopFun=NULL;               //void  (*LoopFun)(void)
    XS_AddClient(&TcpClient);             //Add a client  
    
    TcpServer.port=CMDPORT;               //    unsigned port; 
    TcpServer.socket=-1;
    TcpServer.state=0;
    TcpServer.connect=0;
    TcpServer.CallBackFun=do_echo;        //void (*CallBackFun)(int skt,int mode);
    XS_AddServer(&TcpServer);             //Add a TCP server
    
//  EnableWDT();
    XS_AddSystemLoopFun(XS_SocketLoopFun);    
    XS_StartSocket();
    MAXTXTOUT=6000UL;
}

void XS_UserEnd(void)
{
    XS_StopSocket();
    DisableWDT();
}

unsigned status_8019as=0;
extern int errno;
unsigned char TestData='0'; 
unsigned long gltem;
int giSend;

void UserLoop(void)
{ 
    long  tmpt;
    int key,err; 
    char sTemp[20];
    int iLen;

    RefreshWDT();
    if(Kbhit()){
        switch((key=Getch())){
            case 27:
                QuitMain=1;
                break;
            case 'c':
            case 'C':
                if(TcpClient.bConnected==-1){
                    TcpClient.bConnected=-2;                    
                }
                Print( "connect  \r\n");
                giSend=1;
                break;
            case 'q':
            case 'Q':
                //Break the TCP connection
                if(TcpClient.bConnected==1)
                    XS_CloseSocket(TcpClient.socket);
                giSend=0;
                break;
            case 's':
            case 'S':                 
                ShowSocketStatus();
                break;
            default:                    
                break;
        }
    }
    
    if(TcpClient.bConnected==1 && giSend==1){ //Send First package                                
        iLen=sprintf(sTemp, "%s", "Ethernet echo test!!\r\n");
        Print("bConnected  \r\n");
        err=writesocket(TcpClient.socket, sTemp, iLen);
        if(err<0){      // write error
            Print( "write error %d, close client socket.\r\n", err);
            XS_CloseSocket(TcpClient.socket);  
        }
        giSend=0;
    }
}

char buf[BUFSIZE], SendBack[BUFSIZE+2];
void do_GetResponse(int skt)
{ 
    int err, Sendlen;

    err=readsocket(skt, buf, sizeof(buf)-1);
    if(err<=0){     // error or disconnected by remote side
        XS_CloseSocket(skt);
    }
    else{
        Print(buf);
        Sendlen=sprintf(SendBack, "Client call %d\r\n", gltem);
        err= writesocket(TcpClient.socket, SendBack, Sendlen);
    }
}

// when client is connected, do echo here
void do_echo(int skt, int mode)
{ 
    int i, err, Sendlen;

    if(!mode){
        Sendlen=sprintf(SendBack, "Welcome connect to port %u\r\nThere are %d clients connect to this port\r\n",
                        TcpServer.port, TcpServer.connect);
        goto SendMessage;
    }
    else{
        err=readsocket(skt, buf, sizeof(buf)-1);
        if(err<=0){         // error or disconnected by remote side
            XS_CloseSocket(skt);
        }
        else{
            Print(buf);
            Sendlen=sprintf(SendBack, "Server Echo %d\r\n", gltem++);
SendMessage:
            err=writesocket(skt, SendBack, Sendlen);
            if(err<0){      // write error
                Print("echo write error %d\r\n", err);
                XS_CloseSocket(skt);
            }
        }
    }
}

void main(int argc, char *argv[])
{
    XS_main(argc, argv);    // call the XS library main function
}

#define ESTABLISHED   1     // state machine states
#define FINWAIT_1     2
#define FINWAIT_2     3
#define CLOSED_WAIT   4
#define TIMEWAIT      5
#define LAST_ACK      6
#define CLOSED        7
#define SYN_SENT      8
#define SYN_RECEIVED  9
#define LISTEN       16

void ShowSocketStatus(void)
{
    int i;

    Puts("\r\n");
    for(i=0; i<MaxSocketNo; i++){
        Print("[%02d=%02d:", i, connblo[i].state);
        switch(connblo[i].state){
            case ESTABLISHED: Print("ESTABLISHED]"); break;
            case FINWAIT_1: Print("FINWAIT_1]"); break;
            case FINWAIT_2: Print("FINWAIT_2]"); break;
            case CLOSED_WAIT: Print("CLOSED_WAIT]"); break;
            case TIMEWAIT: Print("TIMEWAIT]"); break;
            case LAST_ACK: Print("LAST_ACK]"); break;
            case CLOSED: Print("CLOSED]"); break;
            case SYN_SENT: Print("SYN_SENT]"); break;
            case SYN_RECEIVED: Print("SYN_RECEIVED]"); break;
            case LISTEN: Print("LISTEN]"); break;
            case 0: Print("NOT_USED_YET]"); break;
            default: Print("!!!UnKnown STATE!!!]"); break;
        }
        
        Print(",stat=%x", connblo[i].blockstat);
        if(i & 1)
            Print("\r\n");
        else
            Print(" , ");
    }
}
