// This file is a part of the xMule Project.
//
// Copyright (c) 2004 Theodore R. Smith (hopeseekr@xmule.ws / http://www.xmule.ws/)
// DSA-1024 Fingerprint: 10A0 6372 9092 85A2 BB7F 907B CB8B 654B E33B F1ED
//
// Copyright (c) 2004 Franz Schneider (sf -at- fsch -dot- net / http://www.xmule.ws/)
//
// Copyright (C)2002 Merkur ( merkur-@users.sourceforge.net / http://www.emule-project.net )
//
// This program 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 2 of the License, or (at your option) any later version.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#ifdef PRECOMP
    #include "xmule-headers.h"
#endif

#include "NewSockets.h"                     // Needed for this Interface's Prototype

#include "ClientUDPSocket.h"                // Needed for CClientUDPSocket
#include "ListenSocket.h"                   // Needed for CClientReqServer
#include "otherfunctions.h"                 // Needed for GetTickCount
#include "packets.h"                        // Needed for Packet
#include "updownclient.h"                   // Needed for CUpDownClient
#include "UploadQueue.h"                    // Needed for CUpDownClient
#include "xmule.h"                          // Needed for theApp

int new_socketcount = 0;

wxUint32 new_ip[10000];

wxUint16 new_port[10000];

CClientUDPSocket* clientudp;

Packet* newsocket_packet;

CMemFile* newsocket_data;

extern int newprefs03_opt[];

extern wxString newprefs03info[];

extern int newprefs04_opt[];

extern wxString newprefs04info[];

void NewSocket_Start(wxUint8 type, wxUint32 ip, wxUint16 port)
{
    switch (type)
    {
    case 1:
        wxIPV4address addr;
        if (!ip)
        {
            addr.AnyAddress();
            addr.Service(port);
        }
        else
        {
            addr.AnyAddress();
            addr.Service(port);
        }
        clientudp = new CClientUDPSocket(addr);
        break;
    }
}

void NewSocket_Stop(wxUint8 type)
{
    switch (type)
    {
    case 1:
        clientudp->Destroy();
        break;
    }
}

void NewSocket_SendPacketOP(wxUint8 type, wxUint8 opcode, Packet* packet, wxUint32 ip, wxUint32 port)
{
    packet->opcode = opcode;
    NewSocket_SendPacket(type, packet, ip, port);
}

void NewSocket_SendPacketOPdata(wxUint8 type, wxUint8 opcode, CMemFile* data, wxUint32 ip, wxUint32 port)
{
    if (data == NULL)
    {
        newsocket_packet = new Packet(opcode, 0);
    }
    else
    {
        newsocket_packet = new Packet(data);
    }
    newsocket_packet->opcode = opcode;
    NewSocket_SendPacket(type, newsocket_packet, ip, port);
}

void NewSocket_SendPacket(wxUint8 type, Packet* packet, wxUint32 ip, wxUint32 port)
{
    if (type)
    {
        long value;
        if (newprefs03info[packet->opcode].Len() > 4)
        {
            newprefs03info[packet->opcode].Mid(2, 3) .ToLong( & value);
            if ((value > 300) && (value < 400))
            {
                value -= 300;
            }
            else
            {
                value = 0;
            }
        }
        else
        {
            value = 0;
        }
        if (value)
        {
            if (newprefs03_opt[value])
            {
                printf("w_SendPacket::");
                switch (type)
                {
                case 0:
                    printf(" TCPcliBLOCK --> ");
                    break;
                case 1:
                    printf(" UDPcli      --> ");
                    break;
                case 2:
                    printf(" TCPcli      --> ");
                    break;
                case 4:
                    printf(" TCPcliSAVE  --> ");
                    break;
                default:
                    printf(" %02x          --> ", type);
                    break;
                }
                switch (port)
                {
                case 0:
                case 1:
                    int p0;
                    p0 = ((CUpDownClient *) ip)->GetUserPort();
                    printf("%02x_%s(%d): size=%d  client=%u ip:port=%08x:%d\n", packet->opcode,
                    (const char *)(newprefs03info[packet->opcode].Mid(17)), packet->opcode, packet->size, ip,
    ((CUpDownClient *) ip)->GetIP(), p0/*(p0>>8)+(p0&0xff)<<8*/
                    );
                    break;
                default:
                    printf("%02x_%s(%d): size=%d  ip:port=%08x:%d opt=%u\n", packet->opcode,
                    (const char *)(newprefs03info[packet->opcode].Mid(17)), packet->opcode, packet->size, ip, port, newprefs03_opt[value]);
                    break;
                }
            }
        }
        else
        {
//            printf("NewSocket_SendPacket %02x --> OP_unknown = %02x size=%d  ip:port=%08x:%d\n", type, packet->opcode, packet->size, port, ip);
        }
    }
    else
    {
        //blockdata sended from uploadclient
    }
/*
    int ps;
    unsigned char* pb;
    pb = (unsigned char *) packet->pBuffer;
    ps = packet->size;
    for (int i = 1 ; i < ps ; i++)
    {
        if (pb[i] == '/')
        {
            if (pb[i - 1] == 'g')
            {
                printf("SendPacket %02x(%u): ", packet->opcode, packet->opcode);
                ascprintf("asc:", pb, ps);
                hexprintf("hex:", pb, ps);
            }
        }
    }
*/
    switch (type)
    {
    case 0:
        switch (port)
        {
        case 0:
            theApp.uploadqueue->AddUpDataOverheadOther(packet->size);
            break;
        default:
            theApp.UpdateSentBytes(port);
            break;
        }
        (void)((CUpDownClient *) ip)->socket->SendPacket(packet, true, false);
        break;
    case 1:
        switch (packet->opcode)
        {
        case OP_FILENOTFOUND:
        case OP_QUEUEFULL:
        case OP_REASKACK:
        case OP_REASKFILEPING:
            theApp.uploadqueue->AddUpDataOverheadFileRequest(packet->size);
            break;
        }
        clientudp->SendPacket(packet, ip, port & 0xffff);
        break;
    case 2:
        switch (packet->opcode)
        {
        case OP_ACCEPTUPLOADREQ:
        case OP_CANCELTRANSFER:
        case OP_FILEREQUEST:
        case OP_HASHSETANSWER:
        case OP_HASHSETREQUEST:
        case OP_REQUESTPARTS:
        case OP_SETREQFILEID:
        case OP_STARTUPLOADREQ:
            theApp.uploadqueue->AddUpDataOverheadFileRequest(packet->size);
            break;
        case OP_REQUESTSOURCES:
            theApp.uploadqueue->AddUpDataOverheadSourceExchange(packet->size);
            break;
        case OP_ASKSHAREDDIRS:
        case OP_ASKSHAREDFILES:
            //case OP_EMULEINFO:==OP_HELLO
        case OP_EMULEINFOANSWER:
        case OP_HELLO:
        case OP_HELLOANSWER:
        case OP_PUBLICKEY:
        case OP_SECIDENTSTATE:
        case OP_SIGNATURE:
        default:
            theApp.uploadqueue->AddUpDataOverheadOther(packet->size);
            break;
        }
        if (((CUpDownClient *) ip)->socket != NULL)
        {
            (void)((CUpDownClient *) ip)->socket->SendPacket(packet, true, true);
        }
        break;
    case 3:
        switch (port & 0xff)
        {
        case OP_FILEREQUEST:
        case OP_SETREQFILEID:
            theApp.uploadqueue->AddUpDataOverheadFileRequest(packet->size);
            break;
        case OP_REQUESTSOURCES:
            theApp.uploadqueue->AddUpDataOverheadSourceExchange(packet->size);
            break;
        default:
            theApp.uploadqueue->AddUpDataOverheadOther(packet->size);
            break;
        }
        (void)((CEMSocket *) ip)->SendPacket(packet, true, true);
        break;
    }
}

void NewSocket_DebugPP(void* client, wxUint8 opcode, long size, unsigned char* packet)
{
    long value;
    if (newprefs04info[opcode].Len() > 5)
    {
        newprefs04info[opcode].Mid(2, 3) .ToLong( & value);
        if ((value > 400) && (value < 500))
        {
            value -= 400;
            if (newprefs04_opt[value])
            {
                printf("r_ProcessPacket(%u)->%02x_%s(%d) size=%d  client=%u\n", value, opcode,
                (const char *)(newprefs04info[opcode].Mid(17)), opcode, size, (wxUint32) client);
            }
        }
        else
        {
            value = 0;
        }
    }
    else
    {
        value = 0;
    }
}

