Difference Analysis Generated by HtmlDiff on 01.03.2003 16:52  

Base file: eMule0.26d.Maella.v2.0.beta6\src\BaseClient.cpp

Modified file: vampirev1esrc\src\BaseClient.cpp

//this file is part of eMule
//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.

#include "StdAfx.h"
#include "updownclient.h"
#include "emule.h"
#include "uploadqueue.h"
#include "Clientlist.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


//  members of CUpDownClient
//  which are used by down and uploading functions 

CUpDownClient::CUpDownClient(CClientReqSocket* sender)
// Maella => -Accurate measure of bandwidth: IP, TCP or UDP, eDonkey protocol, etc-
: m_upHistory_list(UPLOAD_SAMPLES),
  m_downHistory_list(DOWNLOAD_SAMPLES)
// Maella end
{
    socket = sender;
    reqfile = 0;
    Init();
}

CUpDownClient::CUpDownClient(uint16 in_port, uint32 in_userid,uint32 in_serverip, uint16 in_serverport,CPartFile* in_reqfile){
    socket = 0;
    Init();
    m_nUserID = in_userid;
    m_nUserPort = in_port;
    sourcesslot=m_nUserID%SOURCESSLOTS;
    if (!HasLowID())
        sprintf(m_szFullUserIP,"%i.%i.%i.%i",(uint8)m_nUserID,(uint8)(m_nUserID>>8),(uint8)(m_nUserID>>16),(uint8)(m_nUserID>>24));
    m_dwServerIP = in_serverip;
    m_nServerPort = in_serverport;
    reqfile = in_reqfile;
    ReGetClientSoft();
}

void CUpDownClient::Init(){
    memset(m_szFullUserIP,0,21);
    credits = 0;
    m_byChatstate = 0;
    m_nUDPPort = 0;
    m_cFailed = 0;
    m_dwBanTime = 0;
    m_nTransferedUp = 0;
    m_cAsked = 0;
    m_cDownAsked = 0;
    m_pszUsername = 0;
    m_dwUserIP = 0;
    m_nUserID = 0;
    m_nServerPort = 0;
    m_bBanned = false;
    m_bFileListRequested = false;
    m_dwLastUpRequest = 0;
    m_bEmuleProtocol = false;
    usedcompressiondown = false;
    m_bUsedComprUp = false;
    m_bCompleteSource = false;
    m_bFriendSlot = false;
    m_bCommentDirty = false;
    m_bReaskPending = false;
    m_bUDPPending = false;
    m_byEmuleVersion = 0;
    m_nUserPort = 0;
    m_nPartCount = 0;
    m_nUpPartCount = 0;
    m_abyPartStatus = 0;
    m_abyUpPartStatus = 0;
    m_dwLastAskedTime = 0;
    m_nDownloadState = DS_NONE;
    m_pszClientFilename = 0;
    m_dwUploadTime = 0;
    m_nTransferedDown = 0;
    m_byUploadState = US_NONE;
    m_dwLastBlockReceived = 0;
    m_byEmuleVersion = 0;
    m_byDataCompVer = 0;
    m_byUDPVer = 0;
    m_bySourceExchangeVer = 0;
    m_byAcceptCommentVer = 0;
    m_byExtendedRequestsVer = 0;
    m_nRemoteQueueRank = 0;
    m_dwLastSourceRequest = 0;
    m_dwLastSourceAnswer = 0;
    m_byCompatableClient = 0;
    m_bIsHybrid = false;
    m_Friend = NULL;
    m_iRate=0;
    m_strComment="";
    m_nCurSessionUp = 0;
    m_clientSoft=SO_UNKNOWN;
    m_bRemoteQueueFull = false;
    memset( m_achUserHash, 0, 16);
    SetWaitStartTime();
    if (socket){
        SOCKADDR_IN sockAddr;
        memset(&sockAddr, 0, sizeof(sockAddr));
        uint32 nSockAddrLen = sizeof(sockAddr);
        socket->GetPeerName((SOCKADDR*)&sockAddr,(int*)&nSockAddrLen);
        m_dwUserIP = sockAddr.sin_addr.S_un.S_addr;
        strcpy(m_szFullUserIP,inet_ntoa(sockAddr.sin_addr));
    }
    sourcesslot=0;

    // Maella => -Accurate measure of bandwidth: IP, TCP or UDP, eDonkey protocol, etc-
    m_displayUpDatarateCounter = 0;
    m_displayDownDatarateCounter = 0;

    m_nUpDatarate = 0;
    m_nUpDatarateMeasure = 0;
    m_sumUpHistory = 0;

    m_nDownDatarate = 0;
    m_nDownDatarateMeasure = 0;
    m_sumDownHistory = 0;   
    
    TransferredData newItem = {0, ::GetTickCount()};
    for(int i = 0; i < (UPLOAD_SAMPLES); i++) {
        // Use the list class like a circular buffer
        m_upHistory_list.AddHead(newItem);
    }
    for(int i = 0; i < (DOWNLOAD_SAMPLES); i++) {
        // Use the list class like a circular buffer
        m_downHistory_list.AddHead(newItem);
    }
    // Maella end

    // Maella => -AntiCrash/AntiFake handling- (Vorlost/Mortillo)
    m_BannedForTriedCrash = false;
    // Maella end
}

CUpDownClient::~CUpDownClient(){
    //Beep(400,5);
    theApp.clientlist->RemoveClient(this);
    if (m_Friend){
        m_Friend->m_LinkedClient = NULL;
        theApp.friendlist->RefreshFriend(m_Friend);
        m_Friend = NULL;
    }
    if (m_pszClientFilename)
        delete[] m_pszClientFilename;
    if (socket){
        socket->client = 0;
        socket->Safe_Delete();
    }
    if (m_pszUsername)
        delete[] m_pszUsername;
    if (m_abyPartStatus)
        delete[] m_abyPartStatus;
    if (m_abyUpPartStatus)
        delete[] m_abyUpPartStatus;
    ClearUploadBlockRequests();

    for (POSITION pos = m_DownloadBlocks_list.GetHeadPosition();pos != 0;m_DownloadBlocks_list.GetNext(pos))
        delete m_DownloadBlocks_list.GetAt(pos);
    m_DownloadBlocks_list.RemoveAll();
    for (POSITION pos = m_RequestedFiles_list.GetHeadPosition();pos != 0;m_RequestedFiles_list.GetNext(pos))
        delete m_RequestedFiles_list.GetAt(pos);
    m_RequestedFiles_list.RemoveAll();
    for (POSITION pos = m_PendingBlocks_list.GetHeadPosition();pos != 0;m_PendingBlocks_list.GetNext(pos)){
        Pending_Block_Struct *pending = m_PendingBlocks_list.GetAt(pos);
        delete pending->block;
        // Not always allocated
        if (pending->zStream) delete pending->zStream;
        delete pending;
    }

    if (m_iRate>0 || m_strComment.GetLength()>0) {
        m_iRate=0; m_strComment="";
        reqfile->UpdateFileRatingCommentAvail();
    }

    m_PendingBlocks_list.RemoveAll();
    
    // Maella => -Accurate measure of bandwidth: IP, TCP or UDP, eDonkey protocol, etc-
    m_upHistory_list.RemoveAll();
    m_downHistory_list.RemoveAll();
    // Maella end

    DEBUG_ONLY (theApp.listensocket->Debug_ClientDeleted(this));
}

void CUpDownClient::ProcessHelloPacket(char* pachPacket, uint32 nSize){
    CSafeMemFile* data = new CSafeMemFile((BYTE*)pachPacket,nSize);
    uint8 hashsize;
    data->Read(&hashsize,1);
    this->ProcessHelloTypePacket(data);
    delete data;
}

void CUpDownClient::ProcessHelloAnswer(char* pachPacket, uint32 nSize){
    CSafeMemFile* data = new CSafeMemFile((BYTE*)pachPacket,nSize);
    this->ProcessHelloTypePacket(data);
    delete data;
}

void CUpDownClient::ProcessHelloTypePacket(CSafeMemFile* data){
    
    m_bIsHybrid = false;
    data->Read(&m_achUserHash,16);
    uint32 nUserID;
    data->Read(&nUserID,4);
    if (!m_nUserID)
        m_nUserID = nUserID;
    data->Read(&m_nUserPort,2); // hmm clientport is sent twice - why?
    uint32  tagcount;
    data->Read(&tagcount,4);
    for (int i = 0;i != tagcount; i++){
        CTag* temptag = new CTag(data);
        switch(temptag->tag->specialtag){
            // Maella => -AntiCrash/AntiFake handling- (Vorlost/Mortillo)
            case CT_NAME: 
                if (m_pszUsername)
                    delete[] m_pszUsername;
// Old code
//              if( temptag->tag->stringvalue )
//                  m_pszUsername = nstrdup(temptag->tag->stringvalue);
//              else
//                  m_pszUsername=NULL;
                    
                if(temptag->tag->stringvalue == NULL){
                    m_BannedForTriedCrash = true;

                    // Log
                    char buffer[100];
                    buffer[0] = '\0';
                    for(uint16 i=0; i<16; i++) sprintf(buffer, "%s%02X", buffer, (uchar)m_achUserHash[i]);
                    theApp.emuledlg->AddLogLine(true,"A client tries to Crash eMule with an invalid Username !!! Userhash:%s, Userport:%d, we name him now:!!!CrashName!!!", buffer, m_nUserPort );

                    m_pszUsername = nstrdup("!!!CrashName!!!");
                }
                else {
                    m_pszUsername = nstrdup(temptag->tag->stringvalue);
                }
                break;
            // Maella end

            case CT_VERSION:
                m_nClientVersion = temptag->tag->intvalue;
                break;

            case CT_PORT: 
                m_nUserPort = temptag->tag->intvalue;               
                break;
        }
        delete temptag;
    }
    data->Read(&m_dwServerIP,4);
    data->Read(&m_nServerPort,2);
    // Hybrid now has an extra uint32.. What is it for?
    // Also, many clients seem to send an extra 6? These are not eDonkeys or Hybrids..
    if ( data->GetLength() - data->GetPosition() == 4 ){
//      uint32 test;
//      data->Read(&test,4);
        m_bIsHybrid = true;
//      if( m_nClientVersion > 10000 && m_nClientVersion < 100000 )
//          m_nClientVersion = m_nClientVersion - (m_nClientVersion/10000)*10000;
//      if( m_nClientVersion > 1000 )
//          m_nClientVersion = m_nClientVersion - (m_nClientVersion/1000)*1000;
//      if( m_nClientVersion < 100 )
//          m_nClientVersion *= 10;
    }
    // tecxx 1609 2002 - add client's servet to serverlist (Moved to uploadqueue.cpp)

    SOCKADDR_IN sockAddr;
    memset(&sockAddr, 0, sizeof(sockAddr));
    uint32 nSockAddrLen = sizeof(sockAddr);
    socket->GetPeerName((SOCKADDR*)&sockAddr,(int*)&nSockAddrLen);
    m_dwUserIP = sockAddr.sin_addr.S_un.S_addr;
    strcpy(m_szFullUserIP,inet_ntoa(sockAddr.sin_addr));

    // get client credits
    // key, 255.255.0.0 subnetmask

    if (theApp.glob_prefs->AddServersFromClient()){
        in_addr addhost;
        addhost.S_un.S_addr = m_dwServerIP;
        CServer* addsrv = new CServer(m_nServerPort, inet_ntoa(addhost));
        addsrv->SetListName(addsrv->GetAddress());

        if (!theApp.emuledlg->serverwnd.serverlistctrl.AddServer(addsrv, true))
            delete addsrv;
        /*else
            theApp.emuledlg->AddLogLine(false,"Added new server: %s:%d", srv->GetFullIP(), srv->GetPort());*/
    }
    if(!HasLowID() && m_nUserID != m_dwUserIP)
        m_nUserID = m_dwUserIP;

    uchar key[16];
    memcpy(key,m_achUserHash,16);
    credits = theApp.clientcredits->GetCredit(key);
    if ( (m_Friend = theApp.friendlist->LinkFriend(key, m_dwUserIP, m_nUserPort) ) != NULL){
        m_Friend->m_LinkedClient = this;
        m_Friend->m_dwHasHash = 1;
        for( int i = 0; i < 16; i++ )
            m_Friend->m_abyUserhash[i] = GetUserHash()[i];
        m_Friend->m_strName.Format("%s", m_pszUsername);
        m_Friend->m_dwLastUsedIP = m_dwUserIP;
        m_Friend->m_nLastUsedPort = m_nUserPort;
        theApp.friendlist->RefreshFriend(m_Friend);
    }
    ReGetClientSoft();
}

void CUpDownClient::SendHelloPacket(){
    // if IP is filtered, dont greet him but disconnect...
    if (socket){
        SOCKADDR_IN sockAddr;
        memset(&sockAddr, 0, sizeof(sockAddr));
        uint32 nSockAddrLen = sizeof(sockAddr);
        socket->GetPeerName((SOCKADDR*)&sockAddr,(int*)&nSockAddrLen);
        if ( theApp.ipfilter->IsFiltered(sockAddr.sin_addr.S_un.S_addr)) {
            theApp.emuledlg->AddDebugLogLine(true,GetResString(IDS_IPFILTERED),GetFullIP(),theApp.ipfilter->GetLastHit());
            Disconnected();
            theApp.stat_filteredclients++;
            return;
        }
    }

    CMemFile* data = new CMemFile();
    uint8 hashsize = 16;
    data->Write(&hashsize,1);
    SendHelloTypePacket(data);
    Packet* packet = new Packet(data);
    delete data;
    packet->opcode = OP_HELLO;
    if (socket){
        theApp.uploadqueue->AddUpDataOverheadOther(packet->size);
        socket->SendPacket(packet,true);
    }
}

void CUpDownClient::SendMuleInfoPacket(bool bAnswer){
    CMemFile* data = new CMemFile();
    uint8 version = CURRENT_VERSION_SHORT;
    data->Write(&version,1);
    uint8 protversion = EMULE_PROTOCOL;
    data->Write(&protversion,1);
    uint32 tagcount = 6;
    data->Write(&tagcount,4);
    CTag tag(ET_COMPRESSION,1);
    tag.WriteTagToFile(data);
    CTag tag2(ET_UDPVER,2);
    tag2.WriteTagToFile(data);
    CTag tag3(ET_UDPPORT,theApp.glob_prefs->GetUDPPort());
    tag3.WriteTagToFile(data);
    CTag tag4(ET_SOURCEEXCHANGE,1);
    tag4.WriteTagToFile(data);
    CTag tag5(ET_COMMENTS,1);
    tag5.WriteTagToFile(data);
    CTag tag6(ET_EXTENDEDREQUEST,1);
    tag6.WriteTagToFile(data);
    Packet* packet = new Packet(data,OP_EMULEPROT);
    delete data;
    if (!bAnswer)
        packet->opcode = OP_EMULEINFO;
    else
        packet->opcode = OP_EMULEINFOANSWER;
    if (socket){
        theApp.uploadqueue->AddUpDataOverheadOther(packet->size);
        socket->SendPacket(packet,true,true);
    }
}

void CUpDownClient::ProcessMuleInfoPacket(char* pachPacket, uint32 nSize){
    CSafeMemFile* data = new CSafeMemFile((BYTE*)pachPacket,nSize);
    m_byCompatableClient = 0;
    data->Read(&m_byEmuleVersion,1);
    if( m_byEmuleVersion == 0x2B )
        m_byEmuleVersion = 0x22;
    uint8 protversion;
    data->Read(&protversion,1);

    //implicitly supported options by older clients
    if (protversion == EMULE_PROTOCOL) {
        //in the future do not use version to guess about new features

        if(m_byEmuleVersion < 0x25 && m_byEmuleVersion > 0x22)
            m_byUDPVer = 1;

        if(m_byEmuleVersion < 0x25 && m_byEmuleVersion > 0x21)
            m_bySourceExchangeVer = 1;

        if(m_byEmuleVersion == 0x24)
            m_byAcceptCommentVer = 1;

    } else {
        delete data;
        return;
    }
    m_bEmuleProtocol = true;

    uint32 tagcount;
    data->Read(&tagcount,4);
    for (int i = 0;i != tagcount; i++){
        CTag* temptag = new CTag(data);
        switch(temptag->tag->specialtag){
            case ET_COMPRESSION:
                m_byDataCompVer = temptag->tag->intvalue;
                break;
            case ET_UDPPORT:
                m_nUDPPort = temptag->tag->intvalue;
                break;
            case ET_UDPVER:
                m_byUDPVer = temptag->tag->intvalue;
                break;
            case ET_SOURCEEXCHANGE:
                m_bySourceExchangeVer = temptag->tag->intvalue;
                break;
            case ET_COMMENTS:
                m_byAcceptCommentVer = temptag->tag->intvalue;
                break;
            case ET_EXTENDEDREQUEST:
                m_byExtendedRequestsVer = temptag->tag->intvalue;
                break;
            case ET_COMPATABLECLIENT:
                m_byCompatableClient = temptag->tag->intvalue;
                break;
        }
        delete temptag;
    }
    if( m_byDataCompVer == 0 ){
        m_bySourceExchangeVer = 0;
        m_byExtendedRequestsVer = 0;
        m_byAcceptCommentVer = 0;
        m_nUDPPort = 0;
    }
    delete data;
}

void CUpDownClient::SendHelloAnswer(){
    CMemFile* data = new CMemFile();
    SendHelloTypePacket(data);
    Packet* packet = new Packet(data);
    delete data;
    packet->opcode = OP_HELLOANSWER;
    if (socket){
        theApp.uploadqueue->AddUpDataOverheadOther(packet->size);
        socket->SendPacket(packet,true);
    }
}

void CUpDownClient::SendHelloTypePacket(CMemFile* data){
    data->Write(theApp.glob_prefs->GetUserHash(),16);
    uint32 clientid = theApp.serverconnect->GetClientID();
    data->Write(&clientid,4);
    uint16 nPort = theApp.glob_prefs->GetPort();
    data->Write(&nPort,2);
    uint32 tagcount = 2;
    data->Write(&tagcount,4);
    CTag* tag = new CTag(CT_NAME,theApp.glob_prefs->GetUserNick());
    tag->WriteTagToFile(data);
    delete tag;
    tag = new CTag(CT_VERSION,EDONKEYVERSION);
    tag->WriteTagToFile(data);
    delete tag;
//  tag = new CTag(CT_PORT,theApp.glob_prefs->GetPort());
//  tag->WriteTagToFile(data);
//  delete tag;
    uint32 dwIP;
    if (theApp.serverconnect->IsConnected()){
        dwIP = theApp.serverconnect->GetCurrentServer()->GetIP();
        nPort = theApp.serverconnect->GetCurrentServer()->GetPort();
    }
    else{
        nPort = 0;
        dwIP = 0;
    }
    data->Write(&dwIP,4);
    data->Write(&nPort,2);
}

void CUpDownClient::ProcessMuleCommentPacket(char* pachPacket, uint32 nSize){
    if (nSize>2){
        CSafeMemFile data((BYTE*)pachPacket,nSize);
        int length;
        data.Read(&m_iRate,sizeof(m_iRate));
        data.Read(&length,sizeof(length));
        reqfile->SetHasRating(true);
        theApp.emuledlg->AddDebugLogLine(false,GetResString(IDS_RATINGRECV),m_pszClientFilename,m_iRate);
        if (length>50) length=50;
        if (length>0){
            char* desc=new char[length+1];
            memset(desc,0,length+1);
            data.Read(desc,length);
            theApp.emuledlg->AddDebugLogLine(false,GetResString(IDS_DESCRIPTIONRECV), m_pszClientFilename, desc);
            m_strComment.Format("%s",desc);
            reqfile->SetHasComment(true);
            delete desc;
        }

    }
    if (reqfile->HasRating() || reqfile->HasComment()) theApp.emuledlg->transferwnd.downloadlistctrl.UpdateItem(reqfile);
}
void CUpDownClient::Disconnected(){
    ASSERT(theApp.clientlist->Debug_IsValidClient(this));
    if (GetUploadState() == US_UPLOADING)
        theApp.uploadqueue->RemoveFromUploadQueue(this);
    if (GetDownloadState() == DS_DOWNLOADING){
        SetDownloadState(DS_ONQUEUE);
    }
    if ((GetDownloadState() == DS_REQHASHSET) && (reqfile))
        reqfile->hashsetneeded= true;
    ASSERT(theApp.clientlist->Debug_IsValidClient(this));
    //check if this client is needed in any way, if not delete it
    bool bDelete = true;
    switch(m_byUploadState){
        case US_ONUPLOADQUEUE:
            bDelete = false;
    };
    switch(m_nDownloadState){
        case DS_ONQUEUE:
        case DS_TOOMANYCONNS:
        case DS_NONEEDEDPARTS:
        case DS_LOWTOLOWIP:
            bDelete = false;
    };

    switch(m_byUploadState){
        case US_CONNECTING:
        case US_WAITCALLBACK:
        case US_ERROR:
            bDelete = true;
    };
    switch(m_nDownloadState){
        case DS_CONNECTING:
        {
            m_cFailed++;
            if (m_cFailed <= 2){
                TryToConnect();
                return;
            }
        }
        case DS_WAITCALLBACK:
        case DS_ERROR:
            bDelete = true;
    };
    

    if (GetChatState()){
        bDelete = false;
        theApp.emuledlg->chatwnd.chatselector.ConnectingResult(this,false);
    }
    if (socket){
        ASSERT (theApp.listensocket->IsValidSocket(socket));
        socket->Safe_Delete();
    }
    socket = 0;
    if (m_bFileListRequested){
        theApp.emuledlg->AddDebugLogLine(false,GetResString(IDS_SHAREDFILES_FAILED),GetUserName());
        m_bFileListRequested = false;
    }
    if (m_Friend)
        theApp.friendlist->RefreshFriend(m_Friend);
    if (bDelete){
        delete this;
    }

}

void CUpDownClient::TryToConnect(bool bIgnoreMaxCon){
    if (theApp.listensocket->TooManySockets() && !bIgnoreMaxCon && !(socket && socket->IsConnected())){
        Disconnected();
        return;
    }
    if ((theApp.serverconnect->GetClientID() < 16777216) && HasLowID()){
        if (GetDownloadState() == DS_CONNECTING)
            SetDownloadState(DS_LOWTOLOWIP);
        else if (GetDownloadState() == DS_REQHASHSET){
            SetDownloadState(DS_ONQUEUE);
            reqfile->hashsetneeded = true;
        }
        if (GetUploadState() == US_CONNECTING){
            Disconnected();
        }
    }

    if (!socket){
        socket = new CClientReqSocket(theApp.glob_prefs,this);
        if (!socket->Create()){
            socket->Safe_Delete();
            return;
        }
    }
    else if (!socket->IsConnected()){
        socket->Safe_Delete();
        socket = new CClientReqSocket(theApp.glob_prefs,this);
        if (!socket->Create()){
            socket->Safe_Delete();
            return;
        }
    }
    else{
        ConnectionEstablished();
        return;
    }
    // MOD Note: Do not change this part - Merkur
    if (HasLowID()){
        if (GetDownloadState() == DS_CONNECTING)
            SetDownloadState(DS_WAITCALLBACK);
        if (GetUploadState() == US_CONNECTING){
            Disconnected();
            return;
        }

        if (theApp.serverconnect->IsLocalServer(m_dwServerIP,m_nServerPort)){
            Packet* packet = new Packet(OP_CALLBACKREQUEST,4);
            memcpy(packet->pBuffer,&m_nUserID,4);
            theApp.uploadqueue->AddUpDataOverheadServer(packet->size);
            theApp.serverconnect->SendPacket(packet);
        }
        else{
            if (GetUploadState() == US_NONE && (!GetRemoteQueueRank() || m_bReaskPending) ){
                theApp.downloadqueue->RemoveSource(this);
                Disconnected();
                return;
            }
            else{
                if (GetDownloadState() == DS_WAITCALLBACK){
                    m_bReaskPending = true;
                    SetDownloadState(DS_ONQUEUE);
                }
            }
        }
    }
    // MOD Note - end
    else{
        socket->Connect(GetFullIP(),GetUserPort());
        SendHelloPacket();
    }
}

void CUpDownClient::ConnectionEstablished(){
    m_cFailed = 0;
    // ok we have a connection, lets see if we want anything from this client
    if (GetChatState() == MS_CONNECTING)
        theApp.emuledlg->chatwnd.chatselector.ConnectingResult(this,true);
    switch(GetDownloadState()){
        case DS_CONNECTING:
        case DS_WAITCALLBACK:
            m_bReaskPending = false;
            SetDownloadState(DS_CONNECTED);
            SendFileRequest();
    }
    if (m_bReaskPending){
        m_bReaskPending = false;
        if (GetDownloadState() != DS_NONE && GetDownloadState() != DS_DOWNLOADING){
            SetDownloadState(DS_CONNECTED);
            SendFileRequest();
        }
    }
    switch(GetUploadState()){
        case US_CONNECTING:
        case US_WAITCALLBACK:
            if (theApp.uploadqueue->IsDownloading(this)){
                SetUploadState(US_UPLOADING);
                Packet* packet = new Packet(OP_ACCEPTUPLOADREQ,0);
                theApp.uploadqueue->AddUpDataOverheadFileRequest(packet->size);
                socket->SendPacket(packet,true);
            }
    }
    if (m_bFileListRequested){
        Packet* packet = new Packet(OP_ASKSHAREDFILES,0);
        theApp.uploadqueue->AddUpDataOverheadOther(packet->size);
        socket->SendPacket(packet,true,true);
    }
}

void CUpDownClient::ReGetClientSoft(){
    if (!m_pszUsername) {m_clientSoft=SO_UNKNOWN;return;}
    if (m_achUserHash[5] == 13 && m_achUserHash[14] == 110) {m_clientSoft= SO_OLDEMULE;return;}
    if (m_achUserHash[5] == 14 && m_achUserHash[14] == 111){
        if( m_byCompatableClient == 1 ){
            m_clientSoft= SO_CDONKEY;
            return;
        }
        else{
            m_clientSoft= SO_EMULE;
            return;
        }
    }
    if (m_achUserHash[5] == 'M' && m_achUserHash[14] == 'L') {m_clientSoft= SO_MLDONKEY;return;}
    if( m_bIsHybrid )
        m_clientSoft=SO_EDONKEYHYBRID;
    else
        m_clientSoft=SO_EDONKEY;
}

void CUpDownClient::SetUserName(char* pszNewName){
    if (m_pszUsername)
        delete[] m_pszUsername;
    if( pszNewName )
        m_pszUsername = nstrdup(pszNewName);
    else
        m_pszUsername = NULL;
}

void CUpDownClient::RequestSharedFileList(){
    theApp.emuledlg->AddDebugLogLine(true,GetResString(IDS_SHAREDFILES_REQUEST),GetUserName());
    m_bFileListRequested = true;
    TryToConnect(true);
}

void CUpDownClient::ProcessSharedFileList(char* pachPacket, uint32 nSize){
    if (m_bFileListRequested){
        m_bFileListRequested = false;
        theApp.searchlist->ProcessSearchanswer(pachPacket,nSize,this);
    }
}