/*

MAgen.dll: Miranda plugin for mail.ru message exchange.

Copyright 2005-2010 Lenik.
Project home at http://www.lenik.ru/win32/magent
Author contact: lenik@lenik.ru

This program is free software.

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.

*/

struct MRIM_ConnectAndLoginThread_parm
    {
    DBVARIANT dbv_login;
    DBVARIANT dbv_password;
    unsigned long thid;
    unsigned long newstatus;
    unsigned char mrimserveraddress[128];
    };

unsigned long MRIM_ConnectAndLoginThread(struct MRIM_ConnectAndLoginThread_parm* p)
{
NETLIBOPENCONNECTION nloc;
int oldStatus;
unsigned long newconnflag = 0;
unsigned char *cptr;

#ifdef MRIM_DEBUG
    PrintDebug("MRIM_ConnectAndLoginThread: started\n");
#endif

strcpy(p->mrimserveraddress,"94.100.181.61:443");
//MessageBox(NULL,"Started","MRIM_ConnectAndLoginThread",MB_OK);
// receive MRIM server address (load balancing)
memset(&nloc,0,sizeof(nloc));
nloc.cbSize = sizeof(nloc);
nloc.flags = 0;
nloc.szHost = "mrim.mail.ru";
nloc.wPort = (WORD)atoi("443");
MRIM_t_hServerConn = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION,(WPARAM)hServerNetlibUser,(LPARAM)&nloc);
if((MRIM_hServerConn == NULL)&&(GetLastError() == 87))
    {
    nloc.cbSize = NETLIBOPENCONNECTION_V1_SIZE;
    MRIM_hServerConn = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION,(WPARAM)hServerNetlibUser,(LPARAM)&nloc);
    }
if(MRIM_t_hServerConn != NULL)
    {
    #ifdef MRIM_DEBUG
        PrintDebug("MRIM_ConnectAndLoginThread: connected to %s:443\n",nloc.szHost);
    #endif
    MRIM_t_hServerPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER,(WPARAM)MRIM_t_hServerConn,100);
    if(MRIM_t_hServerPacketRecver != NULL)
        {
        NETLIBPACKETRECVER packetRecv;
        int recvResult;

        memset(&packetRecv,0,sizeof(packetRecv));
        packetRecv.cbSize = sizeof(packetRecv);
        packetRecv.dwTimeout = 10000;
        recvResult = CallService(MS_NETLIB_GETMOREPACKETS,(WPARAM)MRIM_t_hServerPacketRecver,(LPARAM)&packetRecv);

        packetRecv.buffer[packetRecv.bytesAvailable] = 0;
        #ifdef MRIM_DEBUG
            PrintDebug("MRIM_ConnectAndLoginThread: received [%s]\n",packetRecv.buffer);
        #endif
        if((cptr=strchr(packetRecv.buffer,':')) != NULL)
            {
            if(strncmp(cptr,":443",4) == 0)
                {
                cptr[4] = 0;
                strcpy(p->mrimserveraddress,packetRecv.buffer);
                #ifdef MRIM_DEBUG
                    PrintDebug("MRIM_ConnectAndLoginThread: server address is %s\n",p->mrimserveraddress);
                #endif
                //MessageBox(NULL,packetRecv.buffer,"received address",MB_OK);
                }
            }

        Netlib_CloseHandle(MRIM_t_hServerPacketRecver);
        MRIM_t_hServerPacketRecver = NULL;
        }
    Netlib_CloseHandle(MRIM_t_hServerConn);
    MRIM_t_hServerConn = NULL;
    }

// connect to selected or pre-defined MRIM server
memset(&nloc,0,sizeof(nloc));
nloc.cbSize = sizeof(nloc);
nloc.flags = 0;
cptr = p->mrimserveraddress;
while(cptr[0] != 0)
    {
    if(cptr[0] == ':')
        {
        cptr[0] = 0;
        cptr++;
        break;
        }
    cptr++;
    }
nloc.szHost = p->mrimserveraddress;
nloc.wPort = (WORD)atoi(cptr);

MRIM_LoginInProgressFlag = 1;
if(MRIM_hServerConn == NULL)
    {
    //MessageBox(NULL,"New connection","MRIM_ConnectAndLoginThread",MB_OK);
    MRIM_hServerConn = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION,(WPARAM)hServerNetlibUser,(LPARAM)&nloc);
    if((MRIM_hServerConn == NULL)&&(GetLastError() == 87))
        {
        nloc.cbSize = NETLIBOPENCONNECTION_V1_SIZE;
        MRIM_hServerConn = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION,(WPARAM)hServerNetlibUser,(LPARAM)&nloc);
        }
    newconnflag = 1;
    }
if(MRIM_hServerConn != NULL)
    {
    #ifdef MRIM_DEBUG
        PrintDebug("MRIM_ConnectAndLoginThread: connected to server\n");
    #endif
    if(MRIM_hServerPacketRecver == NULL)
        {
        //MessageBox(NULL,"New packet receiver","MRIM_ConnectAndLoginThread",MB_OK);
        MRIM_hServerPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER,(WPARAM)MRIM_hServerConn,65536);
        newconnflag = 1;
        }
    if(MRIM_hServerPacketRecver != NULL)
        {
        //MessageBox(NULL,"New packet receiver ok","MRIM_ConnectAndLoginThread",MB_OK);
        if(newconnflag == 1)
            {
            if(MRIM_do_hello() == 0)
                {
                #ifdef MRIM_DEBUG
                    PrintDebug("MRIM_ConnectAndLoginThread: MRIM_do_hello() ok\n");
                #endif
                //MessageBox(NULL,"MRIM_do_hello() ok","MRIM_ConnectAndLoginThread",MB_OK);
                if(MRIM_do_login(p->dbv_login.pszVal,p->dbv_password.pszVal,ConvertMirandaStatusToMRIM(p->newstatus)) == 0)
                    {
                    #ifdef MRIM_DEBUG
                        PrintDebug("MRIM_ConnectAndLoginThread: MRIM_do_login() ok\n");
                    #endif
                    //MessageBox(NULL,"MRIM_do_login() ok","MRIM_ConnectAndLoginThread",MB_OK);
                    newconnflag = 0;
                    }
                }
            else{
                //MessageBox(NULL,"MRIM_do_hello() failed","MRIM_ConnectAndLoginThread",MB_OK);
                }
            }
        if(newconnflag == 0)
            {// set status
            if(MRIM_do_changestatus(ConvertMirandaStatusToMRIM(p->newstatus)) == 0)
                {
                oldStatus = MRIM_Status;
                MRIM_Status = p->newstatus;
                ProtoBroadcastAck(ProtoName,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS,(HANDLE)oldStatus,p->newstatus);
                }
            }
        }
    else{
        //MessageBox(NULL,"New packet receiver create failed","MRIM_ConnectAndLoginThread",MB_OK);
        }
    }
DBFreeVariant(&(p->dbv_password));
DBFreeVariant(&(p->dbv_login));
MRIM_LoginInProgressFlag = 0;
return(0);
}

unsigned long MRIM_ConnectAndLogin(unsigned long newstatus)
{
struct MRIM_ConnectAndLoginThread_parm *p;

if((p=((struct MRIM_ConnectAndLoginThread_parm*)malloc(sizeof(struct MRIM_ConnectAndLoginThread_parm)))) != NULL)
    {
    if(!DBGetContactSetting(NULL,ProtoName,DB_SETTING_EMAIL, &(p->dbv_login)))
        {
        if(!DBGetContactSetting(NULL,ProtoName,DB_SETTING_PASSWORD, &(p->dbv_password)))
            {
            CallService(MS_DB_CRYPT_DECODESTRING,strlen(p->dbv_password.pszVal)+1,(LPARAM)p->dbv_password.pszVal);

            p->newstatus = newstatus;
            CreateThread(NULL,0,(unsigned long (__stdcall *)(void *))MRIM_ConnectAndLoginThread,p,0,&(p->thid));
            return(0);
            }
        }
    }
return(1);
}
