/*
Client.c: Implement one TCP/IP client connection.
          Support one client for TCP port 10001.

Compiler: BC++ 3.1, 
          Turbo C++ 1.01(3.01) (free from http://cc.codegear.com/free/cpp)

Compile mode: Large

Project: Client.c
         ..\lib\7186el.Lib
         ..\lib\tcp_dm32.lib
         ..\lib\FW_nnnnn.LIB
         
[Nov 04, 2008] by Liam
*/

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

#define BUFSIZE 1460    // read/write buffer size

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

// Initialize a TCP Client with default IP 10.0.8.157 and port 10001
TCP_CLIENT TcpClient=
{
    "10.1.0.30",   // char *ip;
    10000,          // unsigned port;
    -1,             // int socket;
    0,              // int tmpState;
    -2,             // int bConnected;
    10,             // int iConnectTryCount;       // Frequency to reconnect to remote device
    4000,           // long lConnetTimeout;        // Timeout to connect to remote device
                                                   // 0: default value is 400ms
    0,              // long ltmpT;
    (void *) do_GetResponse, // void  (*CallBackFun)(int skt);
    NULL
};

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" ;
} 

unsigned char MyIp[4];

void XS_UserInit(int argc,char *argv[])
{
    extern int bAcceptBroadcast;
    extern unsigned long ACKDELAY;
    extern long MAXTXTOUT;
    void UserLoop(void);
    
    char version[20];
    int i, port;
    
    InitLib();
    
    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);
    Print("IP=%d.%d.%d.%d\r\n", MyIp[0], MyIp[1], MyIp[2], MyIp[3]);

    XS_AddSystemLoopFun(UserLoop);
    
    // Process of the arguments
    for(i=1; i<argc; i++)
    {
        if(argv[i][0]=='/')
        {
            switch(argv[i][1])
            {
                case 'i': 
                case 'I':
                    // set the IP address of the remote server.
                    TcpClient.ip=argv[i]+2;
                    Print("[remote IP=%s]", TcpClient.ip);
                    break;
                
                case 'p':
                case 'P':
                    // set the TCP port of the remote server.
                    if(1==sscanf(argv[i]+2,"%i",&port))
                    {
                        TcpClient.port=port;
                        Print("[remote port=%u(%x)]", TcpClient.port, TcpClient.port);
                    }
                    break;
            }
        }
    }
    
    XS_AddClient(&TcpClient);   //Add a client
    
    // uses the TCP/IP functions
    XS_AddSystemLoopFun(XS_SocketLoopFun);    
    XS_StartSocket();    //Called on xs09300.lib[2006/09/26] or later 

    EnableWDT();
    MAXTXTOUT=6000UL; 

    //Print("user init end: TcpClient.bConnected == %d\r\n", TcpClient.bConnected);
}

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

char Command[100];
int idx=0;

void UserLoop(void)
{ 
    long tmpt;
    int key,err;

    RefreshWDT();
    
    if(Kbhit())
    {
        switch((key=Getch()))
        { 
            // Check whether any data was inputted to command port or not
            // Command port of uPAC-7186EX is COM1      
            case 27: 
                // Press 'Esc' key to quit the program
                QuitMain=1;
                break;
            
            default:
                // The other data come-in
                Command[idx]=key;
                
                // Maximum characters of a string ==>99
                if(idx<99)
                    idx++; 
                    
                Putch(key);
                if(key=='\r')
                { 
                    // The terminal character of a string is '\r' (Press 'Enter' key)
                    Command[idx]=0;
                    Putch('\n');
                    if(Command[0]=='/')
                    {
                        // '/' denotes that the inputted string was a command 
                        if(Command[1]=='Q')
                        {
                            // Break the TCP connection
                            if(TcpClient.bConnected==1)
                            {
                                XS_CloseSocket(TcpClient.socket);
                            }
                        }
                        else if(Command[1]=='C')
                        {
                            // Build the TCP connection
                            if(TcpClient.bConnected==-1)
                            {
                                TcpClient.bConnected=-2;
                            }
                        }
                        
                        else if(Command[1]=='0' && Command[2]=='0')
                        {
                            // Show the socket status
                            ShowSocketStatus();
                        }
                        else
                        {
                            // unknow command
                            Print("Unsupport command\r\n");
                        }
                    }
                    else if(TcpClient.bConnected==1)
                    {
                        // The String that isn't the command will send to client
                        err=writesocket(TcpClient.socket, Command, idx);
                        Print(Command);
                        if(err<0)
                        {
                            // write error
                            Print("write error %d, close client socket.\r\n", err);
                            XS_CloseSocket(TcpClient.socket);
                        }
                    }
                    else
                    {
                        Print("[do nothing]\r\n");
                        Print("TcpClient.bConnected == %d\r\n", TcpClient.bConnected);
                    }
                    
                    idx=0;
                }                   
                break;
        }
    }
}

char buf[BUFSIZE], SendBack[BUFSIZE+2];
// when client is connected, do echo here
void do_GetResponse(int skt)
{ 
    int i, cc, err, Sendlen;

    err=cc=readsocket(skt, buf, sizeof(buf)-1);
    if(err<=0)
    {
        // error or disconnected by remote side
        XS_CloseSocket(skt);
    }
    else
    {
        for(i=0; i<cc; i++)
        {
            Putch(buf[i]);
            if(buf[i]=='\r') Putch('\n');
        }
    }
}

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

#define ESTABLISHED   1     // state machine states, see handbook
#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(" , ");
    }
}
