/*
udp_serv.c: Support echo server for TCP port 10000/10001/10002.

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\vh2k.h"
#include "..\lib\Tcpip32.h"
#include "..\lib\MFW.h"

#define _SHOW_IP_ADDRESS_ 

void do_echo( int skt , int mode);
#define BUFSIZE 1460       /* read/write buffer size */

/*
typedef struct {
    unsigned port;
    int socket;
    int state;
    int connect;
    void (*CallBackFun)(int skt,int mode);
} TCP_SERVER;
*/
TCP_SERVER TcpServer={
    10001,      // port
    -1,         // socket
    0,          // state
    0,          // connect
    do_echo     // CallBackFun
};

void DoUdp10K(int skt);

UDP_SOCKET Udp10K={
    -1,         // int socket;
    10000,      // unsigned MyPort;
    NULL,       // char *RemoteIp; 
    0,          // unsigned RemotePort;
    1,          // int fNonBlock;
    1,          // int fEnableBroadcast;
    0,          // int status; 
    DoUdp10K    // void (*CallBackFun)(int skt);
};

unsigned char MyIp[4];
long LedTime;

void ShowIp(void)
{ 
    static int idx=0;
    int data;
    
    data=MyIp[idx];
    idx++;
#ifndef _NO_LED5_
    Show5DigitLedWithDot(1, idx);
    Show5DigitLed(5, data%10);
    data/=10;
    if(data){
        Show5DigitLed(4, data%10);
        data/=10;
        if(data)
            Show5DigitLed(3, data);
        else
            Show5DigitLed(3, 16);
    }
    else{
        Show5DigitLed(4, 16);
        Show5DigitLed(3, 16);
    }
    Show5DigitLed(2, 16);
#endif
    if(idx>=4)
        idx=0;
}

/* demo for use command 19 or 23 */
int UserCmd19_23(PTCPREADDATA p)
{ 
    int skt;
    unsigned char *buf;
    int length,i;

    skt=p->Socket;
    buf=p->ReadUartChar;
    length=p->Length;
    /* Just reply the inpput command here. */ 
    XS_WriteSocket(skt, buf, length);
    return 1; 
}

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];
        
    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]);
    LedTime=GetTimeTicks();

    XS_AddSystemLoopFun(UserLoop);
    
    XS_AddServer(&TcpServer);

    XS_AddServer(&Port10K);     // add the default TCP server (listen port: 10000)


    pXS_Port10kCmd[33]=XS_LoadFile_33;  // 設定使用 command 33 (LOAD 檔案功能) 
    pXS_Port10kCmd[19]=UserCmd19_23;    // 設定給 command 19 使用。(跟原 x-server 的 command 19 有些不同。) 
    pXS_Port10kCmd[23]=UserCmd19_23;    // 設定給 command 23 使用。 
    
    pXS_Port10kCmd[17]=XS_Inport_17;    // 設定使用 XS 提供的 command 17
    pXS_Port10kCmd[18]=XS_Outport_18;   // 設定使用 XS 提供的 command 18

    /* Add UDP search function */ 
    XS_AddUdpSocket(&XS_UdpSearch);
    bAcceptBroadcast=1; // 記得要設定成可以接收廣播封包 
    
    /* Add UDP telnet client */
    XS_AddUdpSocket(&Udp10K);
    XS_StartSocket();
    XS_AddSystemLoopFun(XS_SocketLoopFun);
    EnableWDT();
    MAXTXTOUT=6000UL; 
}

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

unsigned status_8019as=0;
int Socket0=-1; 
extern int errno;
long st,old_dt;
unsigned char TestData='0'; 
void UserLoop(void)
{ 
    long tmpt;
    int key,err; 

    RefreshWDT();
    if(Kbhit()){
        switch((key=Getch())){
            case 27:
                QuitMain=1;
                break;
            default:
                break;
        }
    }
#ifdef _SHOW_IP_ADDRESS_
    tmpt=GetTimeTicks();
    if(tmpt-LedTime>=500){
        LedTime+=500;
        LedToggle();
        ShowIp();
    }
#endif
}

// when client is connected, do echo here
char buf[BUFSIZE], SendBack[BUFSIZE+2];
void do_echo(int skt, int mode)
{ 
    int i, cc, 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=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++){
                SendBack[i]=buf[i];
            }
            Sendlen=cc;
SendMessage:
            err= writesocket(skt,SendBack,Sendlen);
            if(err<0){               /* write error */
                Print( "echo write error %d\n\r", err );
                XS_CloseSocket(skt);
            }
        }
    }
}

void DoUdp10K(int skt)
{ int len;
  int i; 
 
    struct sockaddr_in sockAddrWhoSent;

    len = recvfrom(skt, buf, BUFSIZE, 0, (struct sockaddr *) &sockAddrWhoSent, &i);
    if(len>0){
        buf[len]=0;
        // here just echo back the received message. 
        Puts(buf);
        i = sendto(skt, buf, len, 0, (struct sockaddr *) &sockAddrWhoSent, sizeof(sockAddrWhoSent));
        if (i < 0) {
            //do nothing - no retry mechanism
            Print("sendto failed A: err %d(errno=%d)\r\n",i,errno);
        }
    }
    else {
        Print( "Udp read error:%d(srrno=%d)\r\n", len,errno );
    } 
}

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