/***************************************************************************
 *   Copyright (C) 2008 by SK Communications.                              *
 *   http://kldp.net/projects/nateon/                                      *
 *                                                                         *
 *   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 3 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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <stdlib.h>
#include <kextsock.h>
#include <kdebug.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kapplication.h>
#include <kconfig.h>
#include <qmutex.h>
#include <qregexp.h>

#include "../currentaccount.h"
#include "../knateondebug.h"
#include "mimemessage.h"
#include "util/common.h"
#include "knateoncommon.h"
#include "nateonconnection.h"
#include "nomhttpproxy.h"

extern nmconfig stConfig;

NateonConnection::NateonConnection(QString sIdentifier)
:config(0),
m_pCurrentAccount(0),
m_nTrid(0),
m_sIdentifier(sIdentifier),
m_bInitialized(false),
m_nMissedPings(0),
m_bSendPings(false),
m_pSocket(0),
m_bWriteLocked(false),
m_Buffer(0),
bRunning( FALSE ),
 m_pHttpProxy(0),
 bMultiLine( false )
{
	config = kapp->config();
	
    // Create the socket
    m_pSocket = new KExtendedSocket();

    // Connect it up and set some defaults
    // 0x00 = anySocket | 0x600000 = bufferedSocket
    m_pSocket->setSocketFlags( 0x00 | 0x600000 );
    m_pSocket->enableRead( true );
	// m_pSocket->setTimeout( 30   );

    m_pingTimer.stop();

    // Connect the ping timer to the sendPing slot
    connect( &m_pingTimer, SIGNAL( timeout() ), SLOT( sendPing() ) );

	m_pRetryTimer.stop();
	connect( &m_pRetryTimer, SIGNAL( timeout() ), SLOT( slotRetry() ) );
	
	  // Configure the multi packet buffer
	// multiPacketBuffer_.setAutoDelete( FALSE );
	
  // Configure mutex. (TODO: check if this is really needed anymore)
	mproxywriteLocked_ = new QMutex();
	
#ifdef KNATEONTEST
    ASSERT( m_pSocket != 0 );
#endif
	connect( &connectionTimer_, SIGNAL( timeout() ), this, SLOT( slotConnectionTimeout() ) );

	qCommand.setAutoDelete ( FALSE );
	qCommand.clear();

// 	connect( this, SIGNAL( addQueue() ), SLOT( slotRunCommand() ) );
	connect( &tCommandTimeout, SIGNAL( timeout() ), SLOT( slotCommandTimeout() ) );

	nextCommand.clear();
	nextCommand.setAutoDelete( FALSE );
}


// The destructor
NateonConnection::~NateonConnection()
{
    // Disconnect from the server on exit
    if ( isConnected() )
    {
        disconnectFromServer();
    }

    // Delete the socket
    delete m_pSocket;
	delete mproxywriteLocked_;
#ifdef NETDEBUG
	kdDebug() << "DESTROYED Connection" << endl;
#endif
}


// Insert "%" values for certain regular expressions, i.e. "%20" for " ".
void NateonConnection::addPercents(QString &sWord) const
{
    sWord = sWord.replace(QRegExp(" "),"%20");
}


// If the connection is successful...
void NateonConnection::connectionSuccess()
{
	// setSendPings( true );
#ifdef NETDEBUG
    kdDebug() << "Connection: Socket connected successfully." << endl;
#endif
}


// Connect to the given server via the socket
bool NateonConnection::connectToServer(const QString& server, const int& port)
{
#ifdef KNATEONTEST
	ASSERT( ( port >= 0 ) && ( port < 32768 ) );
#endif
#ifdef NETDEBUG
	kdDebug() << "Connection: Connect to server at " << server << ":" << port << "." << endl;
	kdDebug() << "Socket status is " << m_pSocket->socketStatus() << "." << endl;
#endif

	// This seams to solve some problems with re-connecting
	// to the switchboard if there is a timeout.
	m_pSocket->reset();
	
	// Check that we are disconnected (the socket is null)
	if ( !( ( m_pSocket->socketStatus() == KExtendedSocket::nothing )
			|| ( m_pSocket->socketStatus() == KExtendedSocket::done ) ) )
	{
#ifdef NETDEBUG
		kdDebug() << "Connection: Socket is not disconnected.  Already connected?" << endl;
#endif
		return false;
	}

	// Either connect directly or via the proxy based on the user's settings
	/*! 연결(방화벽) */
	config->setGroup( "Config_Connection" );
	/*! 프록시 사용 여부 */
	bool bUseProxy = config->readBoolEntry( "Use_Proxy", false );

	
	
	if ( bUseProxy )
	{
        /*!
         * 접속 시도 시간 10초
         */
        connectionTimer_.stop();
        connectionTimer_.start( 10000, true );
		return connectToServerViaProxy( server, port );
	}
	else
	{
        /*!
         * 접속 시도 시간 5초
         */
        connectionTimer_.stop();
        connectionTimer_.start( 5000, true );
		return connectToServerDirectly( server, port );
	}
}


// Connect to the given server, not using the proxy
bool NateonConnection::connectToServerDirectly(const QString& server, const int& port)
{
	disconnect( m_pSocket, SIGNAL( readyRead() ), this, SLOT( proxyDataReceived() ) );
	disconnect( m_pSocket, SIGNAL( readyRead() ), this, SLOT( dataReceived()) );
	disconnect( m_pSocket, SIGNAL( connectionSuccess( void ) ), this, SLOT( connectionSuccess( void ) ) );
 	disconnect( m_pSocket, SIGNAL( connectionSuccess( void ) ), this, SLOT( proxyConnected( void ) ) );
	disconnect( m_pSocket, SIGNAL( closed( int ) ), this, SLOT( socketclosed( int ) ) );
	disconnect( m_pSocket, SIGNAL( connectionFailed( int ) ), this, SLOT( socketError( int ) ) );
	
	connect( m_pSocket, SIGNAL( readyRead() ), this, SLOT( dataReceived() ) );
	connect( m_pSocket, SIGNAL( connectionFailed( int ) ), this, SLOT( socketError( int ) ) );
	connect( m_pSocket, SIGNAL( connectionSuccess( void ) ), this, SLOT( connectionSuccess( void ) ) );
	connect( m_pSocket, SIGNAL( closed( int ) ), this, SLOT( socketclosed( int ) ) );
	
	// #ifdef KNATEONDEBUG_CONNECTION_SOCKET
#ifdef NETDEBUG
	kdDebug() << "Connection: Using direct connection." << endl;
#endif
	// #endif

	m_pSocket->setAddress( server, port );
	// Apparently async lookups don't work correctly under Qt3
	int nRet = m_pSocket->lookup();
#ifdef NETDEBUG
	kdDebug() << "Lookup Result : " << nRet << ", Server : " << server << ", Port : " << port << endl;
#endif
	if ( nRet != 0 )
		return nRet == 0;
	
	int connectionSuccess = m_pSocket->startAsyncConnect();
#ifdef NETDEBUG
	kdDebug() << "connectionSuccess : " << connectionSuccess << endl;
#endif
	return connectionSuccess == 0;
}


//Send different request(send authentication info, connect to the destination)
bool NateonConnection::connectToServerViaProxy(const QString& sServer, const int& nPort)
{
	disconnect( m_pSocket, SIGNAL( readyRead() ), this, SLOT( proxyDataReceived() ) );
	disconnect( m_pSocket, SIGNAL( readyRead() ), this, SLOT( dataReceived()) );
	disconnect( m_pSocket, SIGNAL( connectionSuccess( void ) ), this, SLOT( connectionSuccess( void ) ) );
	disconnect( m_pSocket, SIGNAL( connectionSuccess( void ) ), this, SLOT( proxyConnected( void ) ) );
	disconnect( m_pSocket, SIGNAL( closed( int ) ), this, SLOT( socketclosed( int ) ) );
	disconnect( m_pSocket, SIGNAL( connectionFailed( int ) ), this, SLOT( socketError( int ) ) );
	
	connect( m_pSocket, SIGNAL( readyRead() ), this, SLOT( proxyDataReceived() ) );
	connect( m_pSocket, SIGNAL( connectionFailed( int ) ), this, SLOT( socketError( int ) ) );
	connect( m_pSocket, SIGNAL( connectionSuccess( void ) ), this, SLOT( proxyConnected( void ) ) );
	connect( m_pSocket, SIGNAL( closed( int ) ), this, SLOT( socketclosed( int ) ) );
	
#ifdef NETDEBUG
	kdDebug() << "Connection: Using proxy connection." << endl;
#endif
	
	config->setGroup( "Config_Connection" );

	int nProxyType = config->readNumEntry( "Proxy_Type", 0 );
	int nProxyPort;
	/*! sock4, sock5 */
	if ( ( nProxyType == 0 ) || ( nProxyType == 1 ) )
		nProxyPort = config->readNumEntry( "Proxy_Port", 1080 );
	else {
		/*! http proxy */
		nProxyPort = config->readNumEntry( "Proxy_Port", 6588 );
		m_pHttpProxy = new NOMHTTPProxy( sServer, nPort );
	}
	
	
	m_pCurrentAccount->setProxyType( (Account::PROXYTYPE) nProxyType );
	m_pCurrentAccount->setProxyServer( config->readEntry( "Proxy_Server", QString::null ) );
	m_pCurrentAccount->setProxyPort( nProxyPort );
	m_pCurrentAccount->setProxyID( config->readEntry( "Proxy_ID", QString::null ) );
	m_pCurrentAccount->setProxyPassword( config->readEntry( "Proxy_Password", QString::null ) );

	if( m_pCurrentAccount->getProxyServer() == QString::null ) return false;
	
	struct hostent *hostent=NULL;
	hostent = gethostbyname( sServer );
	if( hostent==NULL ) return false;

	//now only support ipv4

	//save server's ip address and port in struct sockaddr_in
	memcpy( &m_addr_destServer.sin_addr, hostent->h_addr, 4 );
	m_addr_destServer.sin_port = htons( nPort );

	//save server and port for later connection
	m_sDestServer = sServer;
	m_nDestPort = nPort;


	m_nProxyState = 0;

    kdDebug() << "Connecting Server : " << m_pCurrentAccount->getProxyServer() <<", Port : " << m_pCurrentAccount->getProxyPort() << endl;
    
	m_pSocket->setAddress( m_pCurrentAccount->getProxyServer(), m_pCurrentAccount->getProxyPort());
	
	//at present, use synchronous connection
	return m_pSocket->connect() == 0;
}


void NateonConnection::parseMultiLine( const QStringList& slCommand, const char *pData, Q_ULONG nDataLen )
{
    MimeMessage mimeMessage( pData );
    
    if ( strncmp( pData, "IMSG", 4 ) == 0 ) {
        parseMessage( "IMSG", slCommand, mimeMessage );
    } else if ( strncmp( pData, "INVT", 4 ) == 0 ) {
        parseBuffer( slCommand, pData );
    } else if ( strncmp( pData, "REQC", 4 ) == 0 ) {
        parseBuffer( slCommand, pData );
    } else {
        parseMessage( "", slCommand, mimeMessage );
    }

//     if ( strncmp( pData, "CONF", 4 ) == 0 ) {
//         parseMessage( "", slCommand, mimeMessage );
//     }
//     else if ( strncmp( pData, "CTOC", 4 ) == 0 ) {
//     }
//     else {
//         kdDebug() << QString::fromUtf8( pData ) << endl;
//     }
}


// Read data from the socket
void NateonConnection::dataReceived()
{
#ifdef KNATEONTEST
	ASSERT( m_pSocket != 0 );
#endif

//     Q_ULONG nDataLen;
//     nDataLen = m_pSocket->bytesAvailable();

//     char *pData = ( char * )malloc( nDataLen + 1 );
//     memset( pData, 0x00, nDataLen + 1 );
//     Q_ULONG nBytesRead = m_pSocket->readBlock( pData, nDataLen );
//     if ( nBytesRead < 0 )
//         return;

//     resetPingTimer();

//     if (
//         strncmp( pData, "CONF", 4 ) == 0 ||
//         strncmp( pData, "CTOC", 4 ) == 0 ||
//         strncmp( pData, "GLST", 4 ) == 0 ||
//         strncmp( pData, "LIST", 4 ) == 0
//         ) {
//         bMultiLine = true;
//     }

//     if ( bMultiLine ) {

//         m_Buffer.add( pData, nBytesRead );
//         int nIndex = m_Buffer.findNewline();
//         if (nIndex == -1)
//             return;

//         char *pData2 = ( char * )m_Buffer.data();

//         char *pCommand = ( char * )malloc( nIndex + 1 );
//         memset( pCommand, 0x00, nIndex + 1 );
//         memcpy( pCommand, pData2, nIndex );

//         kdDebug() << "XX :[" << QString::fromUtf8( pCommand ) << "]" << endl;
        
//         QStringList slCommand = QStringList::split( " ", pCommand );
//         free( pCommand );
        
//         int nMessageLength = slCommand[ slCommand.count() - 1 ].toInt();

//         char *pBody = ( char * )malloc( nMessageLength + 1 );
//         memset( pBody, 0x00, nMessageLength + 1 );
//         memcpy( pBody, pData2 + ( nIndex + 2 ), nMessageLength );
        
//         if ( ( m_Buffer.length() - ( nIndex + 2 ) ) >= nMessageLength ) {
//             bMultiLine = false;
//             emit messageReceived(QString::fromUtf8( pData2 ));
//             parseMultiLine( slCommand, pBody, nMessageLength );
//         }
//         else {
//             bMultiLine = true;
//             return;
//         }
//     }
//     else {
//         bMultiLine = false;
//         QStringList slCommand = QStringList::split( " ", pData );
//         if ( slCommand[0] == "PONG" && m_bSendPings ) {
//             m_bPingReceived = true;
//             m_nMissedPings = 0;
//         }
//         else {
//             emit messageReceived(QString::fromUtf8( pData ));
//             parseCommand( slCommand );
//         }
//     }
    
	char rawblock[1024];
	QCString sBlock, sCommandLine;
	int nIndex, nBytesRemaining, nBytesRead, nMessageLength;
	QStringList slCommand;
	bool bIscompleteMessage = false;

	do
	{
		// Find out how much data remains in the socket
		nBytesRemaining = m_pSocket->bytesAvailable();

		// Read in a block from the socket
		memset( rawblock, 0x00, 1024 );
		nBytesRead = m_pSocket->readBlock( rawblock, 1024 );


		// If the noBytesRead is less than zero, it's an error code, so exit
		if ( nBytesRead < 0 )
		{
			//KMessageBox::error(0, UTF8("adwaawawdaw"));
			return;
		}

		// We've received some data, reset the ping timer
		resetPingTimer();

		// Add the block to the buffer
 		m_Buffer.add( rawblock, nBytesRead );

 		// If the buffer contains "\r\n" then there should be at least one full command in there.
		while ( true )
		{ \
			// Find the location of the end of the command
			nIndex = m_Buffer.findNewline();

			if (nIndex == -1) break;

			// Pull off a command line
			sCommandLine = m_Buffer.left( nIndex );

			// don't know why it need this, commandLine should already be this length
			sCommandLine = sCommandLine.left( nIndex );

			// Convert the line to a QStringList command
			slCommand = QStringList::split( " ", QString::fromUtf8( sCommandLine ) );
			int *ckInt = new int( slCommand[1].toInt() );
			const QString *nC = nextCommand.find( ckInt );
			if ( nC != 0 )
			{
#ifdef NETDEBUG
				kdDebug() << "FFFF: [" << *nC << "]" << endl;
#endif
				writeData( *nC );
				nextCommand.remove( ckInt );
			}
			delete ckInt;
			// Check if this is a BODY-LEN + BODY protocol type :(
			if ( slCommand[0] == "CONF" || slCommand[0] == "CTOC" || slCommand[0] == "CMSG" )
			{
				// Get message length (last parameter)
				nMessageLength   = slCommand[ slCommand.count() - 1 ].toInt();
				// Compare length with the size of the buffer
				bIscompleteMessage = ((m_Buffer.length() - nIndex - 2) >= nMessageLength);

				// Check if the rest of the message is in the buffer
				if ( bIscompleteMessage  )
				{
					// Remove the command from the buffer
					m_Buffer.remove( nIndex + 2 );

					// Full message: send to network window
					/*! 로그가 깨지는데 왜그럴까? */
					emit messageReceived( sCommandLine.append("\n").append(  m_Buffer.left(nMessageLength) ) );

					// Get the message from the buffer and create the mime message
					// Note we can't parse Strings here, the message could contain binary p2p data.
					// Unicode characters are translated in the MimeMessage constructor itself.
					MimeMessage mimeMessage(m_Buffer.left( nMessageLength ));
					// and parse it

					QString sTemp( m_Buffer.left(4) );

					/// CMSG(or CTOC)에서 쪽지는 IMSG, 대화는 INVT 임. 분기가 필요해서 m_Buffer.left(4) 인자를 둠.
					if ( sTemp == "IMSG" )
					{
						parseMessage( m_Buffer.left(4), slCommand, mimeMessage );
					} else if ( sTemp == "INVT" ) {
						parseBuffer(slCommand, QString( m_Buffer.left( nMessageLength ) ));
					} else if ( sTemp == "REQC" ) {
						QString sBody;
						sBody = QString(m_Buffer.left( nMessageLength ));
						parseBuffer(slCommand, sBody);
					} else {
						parseMessage( m_Buffer.left(4), slCommand, mimeMessage );
					}
					// delete from the buffer
					m_Buffer.remove( nMessageLength );
				}
				// If the buffer doesn't contain the rest of the message, just wait until "dataReceived" is called again.
				else
				{
					// Break out of the loop
					break;
				}
			}
			// Check if this is the other data type
			else
			{
				// This is a regular command
#if 0
				// Convert the line to a QStringList command
				slCommand = QStringList::split( " ", QString::fromUtf8( sCommandLine ) );
#endif
				// Remove the command from the buffer.
				m_Buffer.remove( nIndex + 2 );

				// Emit message for network window
				emit messageReceived(QString::fromUtf8(sCommandLine));
				// emit messageReceived( sCommandLine );

				// We parse ping responses internally
				if ( slCommand[0] == "PONG" && m_bSendPings )
				{
					m_bPingReceived = true;
					m_nMissedPings = 0;
				}
				else
				{
					// Parse the command.
					parseCommand( slCommand );
				}
			}
		}
	}
	while(nBytesRemaining > 0);
}


void NateonConnection::disconnectFromServer( bool isTransfer )
{
#ifdef NETDEBUG
    kdDebug() << "Connection: Send 'OUT'." << endl;
#endif

    // stop any more pings
    setSendPings( FALSE );

    // If the socket is connected...
    if ( isConnected() )
    {
        // Send "OUT"
        writeData("LOUT\r\n");
    }
#ifdef NETDEBUG
    kdDebug() << "Connection: Flush the socket." << endl;
#endif

    // Flush the socket
    m_pSocket->flush();

#ifdef NETDEBUG
    kdDebug() << "Connection: Close the socket." << endl;
#endif

    // Close the socket
    m_pSocket->closeNow();
    // Reset the socket
    m_pSocket->reset();

#ifdef NETDEBUG
    kdDebug() << "Connection: emit 'disconnected'." << endl;
#endif

    if ( !isTransfer ) emit disconnected();
}


// Return an acknowledgement number
int NateonConnection::getTrid()
{
    return m_nTrid++;
}


// Find out how much data is waiting in the buffer
unsigned int NateonConnection::getBufferSize()
{
    return m_Buffer.length();
}


// Get some amount of data from the buffer
QString NateonConnection::getDataFromBuffer(const int& nLength)
{
#ifdef KNATEONTEST
    uint oldBufferLength = m_Buffer.length();
#endif

    QString sData;
    sData = QString::fromUtf8( m_Buffer.left( nLength ) );

    // Remove the full message from the buffer
    m_Buffer.remove( nLength );

#ifdef KNATEONTEST
	ASSERT( (uint)( m_Buffer.length() ) == (uint)( oldBufferLength - nLength ) );
#endif
#ifdef NETDEBUG
    kdDebug() << m_sIdentifier << " <<< " << sData << endl;
#endif

    return sData;
}


// Get the IP address of this machine.
const QString NateonConnection::getLocalIP() const
{
#ifdef NETDEBUG
    kdDebug() << "Connection::getLocalIp()" << endl;
#endif

    QString sIp = "";
    const KSocketAddress *address;
    address = m_pSocket->localAddress();
    if ( address != 0 )
    {
        sIp = address->pretty();
        // Local address gives something like "1.2.3.4 port 5" in the english
        //  version, and "1.2.3.4-Portnammersomething 5" in the german version.
        // So, to get the port, replace any "-"'s with " " then get everything
        //  to the left of the first space.  That should work.
        sIp = sIp.replace( QRegExp("-"), " " );
#ifdef NETDEBUG
        kdDebug() << "C:    Raw IP is " << sIp << endl;
#endif
        if ( sIp.contains(" ") )
        {
            sIp = sIp.left( sIp.find(" ") );
        }
#ifdef NETDEBUG
        kdDebug() << "C:    IP is " << sIp << endl;
#endif
    }
#ifdef NETDEBUG
    else
    {
        kdDebug() << "Connection::getLocalIp(): WARNING - IP not found.  Local address was null?" << endl;
    }
#endif
	
#ifdef NETDEBUG
    kdDebug() << "C:    Done getLocalIp()." << endl;
#endif
    return sIp;
}


// Get whether we're sending pings or not
bool NateonConnection::getSendPings() const
{
    return m_bSendPings;
}


// Extract some information from a message (like "Name: Joe;" - extract the "Joe")
QString NateonConnection::getValueFromMessage(const QString& sField, const QString& sMessage, bool bGoToEndOfLine) const
{
    QString sValue;
    int      nFieldStart, nFieldEnd;
#ifdef KNATEONTEST
    ASSERT( sMessage.contains( sField ) );
#endif

    if ( !sMessage.contains( sField ) )
    {
        return "";
    }

    // Find the occurance of "field" in the message
    nFieldStart = sMessage.find( sField );
    nFieldEnd = sMessage.find( " ", nFieldStart );
    if ( nFieldEnd < 0 )
    {                            // For some reason, there's no space after the field.
        return "";
    }
    // Take everything to the right of the message beginning
    sValue = sMessage.right( sMessage.length() - nFieldEnd - 1 );
    // The value should be anything before returns or spaces
    sValue = sValue.left( sValue.find("\r\n") );
    if ( !bGoToEndOfLine )
    {
        sValue = sValue.left( sValue.find(" ") );
    }
    // Strip semicolons off the end of the value
    if ( sValue.right(1) == ";" )
    {
        sValue = sValue.left( sValue.length() - 1 );
    }
    return sValue;
}


// Whether or not the class is connected
bool NateonConnection::isConnected() const
{
    return ( m_pSocket->socketStatus() == KExtendedSocket::connected );
}


// Replace any "%" values with their regular values, i.e. "%20" to " ".
void NateonConnection::removePercents(QString &sWord) const
{
	sWord = sWord.replace( QRegExp( "%20" ), " " );
	sWord = sWord.replace( QRegExp( "%0D" ), "\r" );
	sWord = sWord.replace( QRegExp( "%0A" ), "\n" );
#if 0
	sWord = sWord.replace( QRegExp( "%20" ), " " );
	sWord = sWord.replace( QRegExp( "%21" ), "!" );
	sWord = sWord.replace( QRegExp( "%22" ), "\"" );
	sWord = sWord.replace( QRegExp( "%23" ), "#" );
	sWord = sWord.replace( QRegExp( "%24" ), "$" );
	sWord = sWord.replace( QRegExp( "%25" ), "%" );
	sWord = sWord.replace( QRegExp( "%26" ), "&" );
	sWord = sWord.replace( QRegExp( "%27" ), "'" );
	sWord = sWord.replace( QRegExp( "%28" ), "(" );
	sWord = sWord.replace( QRegExp( "%29" ), ")" );
	sWord = sWord.replace( QRegExp( "%2A" ), "*" );
	sWord = sWord.replace( QRegExp( "%2B" ), "+" );
	sWord = sWord.replace( QRegExp( "%2C" ), "," );
	sWord = sWord.replace( QRegExp( "%2D" ), "-" );
	sWord = sWord.replace( QRegExp( "%2E" ), "." );
	sWord = sWord.replace( QRegExp( "%2F" ), "/" );
	sWord = sWord.replace( QRegExp( "%30" ), "0" );
	sWord = sWord.replace( QRegExp( "%31" ), "1" );
	sWord = sWord.replace( QRegExp( "%32" ), "2" );
	sWord = sWord.replace( QRegExp( "%33" ), "3" );
	sWord = sWord.replace( QRegExp( "%34" ), "4" );
	sWord = sWord.replace( QRegExp( "%35" ), "5" );
	sWord = sWord.replace( QRegExp( "%36" ), "6" );
	sWord = sWord.replace( QRegExp( "%37" ), "7" );
	sWord = sWord.replace( QRegExp( "%38" ), "8" );
	sWord = sWord.replace( QRegExp( "%39" ), "9" );
	sWord = sWord.replace( QRegExp( "%3A" ), ":" );
	sWord = sWord.replace( QRegExp( "%3B" ), ";" );
	sWord = sWord.replace( QRegExp( "%3C" ), "<" );
	sWord = sWord.replace( QRegExp( "%3D" ), "=" );
	sWord = sWord.replace( QRegExp( "%3E" ), ">" );
	sWord = sWord.replace( QRegExp( "%3F" ), "?" );
	sWord = sWord.replace( QRegExp( "%40" ), "@" );
	sWord = sWord.replace( QRegExp( "%41" ), "A" );
	sWord = sWord.replace( QRegExp( "%42" ), "B" );
	sWord = sWord.replace( QRegExp( "%43" ), "C" );
	sWord = sWord.replace( QRegExp( "%44" ), "D" );
	sWord = sWord.replace( QRegExp( "%45" ), "E" );
	sWord = sWord.replace( QRegExp( "%46" ), "F" );
	sWord = sWord.replace( QRegExp( "%47" ), "G" );
	sWord = sWord.replace( QRegExp( "%48" ), "H" );
	sWord = sWord.replace( QRegExp( "%49" ), "I" );
	sWord = sWord.replace( QRegExp( "%4A" ), "J" );
	sWord = sWord.replace( QRegExp( "%4B" ), "K" );
	sWord = sWord.replace( QRegExp( "%4C" ), "L" );
	sWord = sWord.replace( QRegExp( "%4D" ), "M" );
	sWord = sWord.replace( QRegExp( "%4E" ), "N" );
	sWord = sWord.replace( QRegExp( "%4F" ), "O" );
	sWord = sWord.replace( QRegExp( "%50" ), "P" );
	sWord = sWord.replace( QRegExp( "%51" ), "Q" );
	sWord = sWord.replace( QRegExp( "%52" ), "R" );
	sWord = sWord.replace( QRegExp( "%53" ), "S" );
	sWord = sWord.replace( QRegExp( "%54" ), "T" );
	sWord = sWord.replace( QRegExp( "%55" ), "U" );
	sWord = sWord.replace( QRegExp( "%56" ), "V" );
	sWord = sWord.replace( QRegExp( "%57" ), "W" );
	sWord = sWord.replace( QRegExp( "%58" ), "X" );
	sWord = sWord.replace( QRegExp( "%59" ), "Y" );
	sWord = sWord.replace( QRegExp( "%5A" ), "Z" );
	sWord = sWord.replace( QRegExp( "%5B" ), "[" );
	sWord = sWord.replace( QRegExp( "%5C" ), "\\" );
	sWord = sWord.replace( QRegExp( "%5D" ), "]" );
	sWord = sWord.replace( QRegExp( "%5E" ), "^" );
	sWord = sWord.replace( QRegExp( "%5F" ), "_" );
	sWord = sWord.replace( QRegExp( "%60" ), "`" );
	sWord = sWord.replace( QRegExp( "%61" ), "a" );
	sWord = sWord.replace( QRegExp( "%62" ), "b" );
	sWord = sWord.replace( QRegExp( "%63" ), "c" );
	sWord = sWord.replace( QRegExp( "%64" ), "d" );
	sWord = sWord.replace( QRegExp( "%65" ), "e" );
	sWord = sWord.replace( QRegExp( "%66" ), "f" );
	sWord = sWord.replace( QRegExp( "%67" ), "g" );
	sWord = sWord.replace( QRegExp( "%68" ), "h" );
	sWord = sWord.replace( QRegExp( "%69" ), "i" );
	sWord = sWord.replace( QRegExp( "%6A" ), "j" );
	sWord = sWord.replace( QRegExp( "%6B" ), "k" );
	sWord = sWord.replace( QRegExp( "%6C" ), "l" );
	sWord = sWord.replace( QRegExp( "%6D" ), "m" );
	sWord = sWord.replace( QRegExp( "%6E" ), "n" );
	sWord = sWord.replace( QRegExp( "%6F" ), "o" );
	sWord = sWord.replace( QRegExp( "%70" ), "p" );
	sWord = sWord.replace( QRegExp( "%71" ), "q" );
	sWord = sWord.replace( QRegExp( "%72" ), "r" );
	sWord = sWord.replace( QRegExp( "%73" ), "s" );
	sWord = sWord.replace( QRegExp( "%74" ), "t" );
	sWord = sWord.replace( QRegExp( "%75" ), "u" );
	sWord = sWord.replace( QRegExp( "%76" ), "v" );
	sWord = sWord.replace( QRegExp( "%77" ), "w" );
	sWord = sWord.replace( QRegExp( "%78" ), "X" );
	sWord = sWord.replace( QRegExp( "%79" ), "y" );
	sWord = sWord.replace( QRegExp( "%7A" ), "z" );
	sWord = sWord.replace( QRegExp( "%7B" ), "{" );
	sWord = sWord.replace( QRegExp( "%7C" ), "|" );
	sWord = sWord.replace( QRegExp( "%7D" ), "}" );
	sWord = sWord.replace( QRegExp( "%7E" ), "~" );
#endif
}


// Initialize the object
bool NateonConnection::initialize()
{
    if ( m_bInitialized )
    {
#ifdef NETDEBUG
        kdDebug() << "Connection already initialized!" << endl;
#endif
        return false;
    }

    m_pCurrentAccount = CurrentAccount::instance();
    if ( m_pCurrentAccount == 0 )
    {
#ifdef NETDEBUG
        kdDebug() << "Connection: Couldn't get an instance of the current account." << endl;
#endif
        return false;
    }

    m_bInitialized = true;

    return m_bInitialized;
}


// If the connection to proxy is successful...
void NateonConnection::proxyConnected(void)
{
    char command[9];
    bzero(command,9);

    m_nProxyState = 1;
	
	switch( m_pCurrentAccount->getProxyType() )
	{
		// Socks4 Proxy
	case Account::TYPE_SOCKS4:
		
		command[0]='\x04';   //version num
		command[1]='\x01';   //\x01 stands for "Connect"
		memcpy(&command[2],&m_addr_destServer.sin_port,2);
		memcpy(&command[4],&m_addr_destServer.sin_addr,4);
		writeProxyData(command,9);
		break;
		
		// Socks5 Proxy
	case Account::TYPE_SOCKS5:
		
		//if both uid and password are not empty, the proxy may need authentication.
		if ( ( m_pCurrentAccount->getProxyUID() != QString::null )
		     && ( m_pCurrentAccount->getProxyPassword() != QString::null ) )
		{
			// Version num
			command[0]='\x05';
			// METHOD number
			command[1]='\x02';
			// Need authentication
			command[2]='\x02';
			// Need not authentication
			command[3]='\x00';
			// Proxy will pick a METHOD from the upper two
			
			writeProxyData(command,4);
		}
		else                 //We assume that no authentication is needed
		{
			command[0]='\x05';
			command[1]='\x01';
			command[2]='\x00';
			
			writeProxyData(command,3);
		}
		break;
		
	case Account::TYPE_HTTP: //Have some problems now, I'll commit later
        connectionSuccess();
		break;
	}
}


// Read proxy reply from the socket
void NateonConnection::proxyDataReceived(void)
{
    kdDebug() << "proxyDataReceived!!!" << endl;
    
    int nbytesRead,nbytesAvailable;
    char *buf=NULL;

    if((nbytesAvailable=m_pSocket->bytesAvailable())<=0)
    {
        qWarning("m_pSocket has no information to read.\n");
        return;
    }
    if((buf=new char [nbytesAvailable+1])==NULL)
    {
        qWarning("Can't allocate space.\n");
        return;
    }

    bzero(buf, nbytesAvailable+1);

    nbytesRead=m_pSocket->readBlock(buf, nbytesAvailable+1);
    if(nbytesRead<=0||nbytesRead>nbytesAvailable)
    {
        qWarning("Reading from socket error");
        return;
    }

    QStringList slCommand;
    switch(m_pCurrentAccount->getProxyType())
    {
	case Account::TYPE_SOCKS4:

		if(m_nProxyState==1)
		{
			if( nbytesRead!=8 )
			{
				//Reply must have exact 8 bytes
				setProxyState(PROXYERROR );
				return;
			}

			if( buf[1]==90 ) //Request for connecting to the host granted
			{
				setProxyState(PROXYHOSTCONNECTED );
			}
			else
			{
				//buf[1]==91 stands for request rejected or failed
				//92 stands for request rejected becasue SOCKS server cannot connect to identd on the client
				//93 stands for request rejected because the client program and identd report different user-ids
				setProxyState(PROXYFAIL );
			}
		}
		break;

	case  Account::TYPE_HTTP:
        kdDebug() << "[" << buf << "]" << endl;
        
 		if(strncmp(buf,"HTTP/1.",7)==0&&strncmp(buf+9,"200",3)==0) {
            kdDebug() << "[ H E A D E R ]" << endl;
            QStringList slCommandList = QStringList::split( "\n", buf );
            QStringList slTicket = QStringList::split( ":", slCommandList[1] );
            QString sTicket = slTicket[1].stripWhiteSpace();
            m_pHttpProxy->setTicket( sTicket.toUInt() );
            kdDebug() << "Get Command : [" << slCommandList[6] << "]" <<  endl;
            slCommand = QStringList::split( " ", slCommandList[6] );
        }
        else {
            slCommand = QStringList::split( " ", buf );
            kdDebug() << "[ B O D Y ]" << endl;
        }

        if ( slCommand.count() > 0 ) {
            // We parse ping responses internally
            if ( slCommand[0] == "PONG" && m_bSendPings ) {
                m_bPingReceived = true;
                m_nMissedPings = 0;
            }
            else {
                // Parse the command.
                parseCommand( slCommand );
            }
        }
        break;

	case  Account::TYPE_SOCKS5:

		socks5_reply(buf,nbytesRead);
		break;
    }
}


// Show a message that the proxy failed
void NateonConnection::proxyFailed()
{
    QString message;
    // Show a message to the user
    message = UTF8("There was a problem connecting to the proxy.");
    KMessageBox::error( 0, message );
    // Disconnect from the server
    disconnectFromServer();
}


// Resets the ping timer
void NateonConnection::resetPingTimer()
{
    if ( m_bSendPings )
    {
        m_pingTimer.stop();

        // 30s ping timer
        m_pingTimer.start( 10000 );
    }
}


// Send a command to the server
int NateonConnection::sendCommand(const QString& sPrefix, const QString &sText)
{
    int nTrid = getTrid();

    // Send the data to the server
    QString sCommand;
    sCommand = sPrefix;
    sCommand += " ";
    sCommand += QString::number( nTrid );
    sCommand += " ";
    sCommand += sText;
	
    writeData( sCommand );

    // Return the ack used
    return nTrid;
}


// Send a command to the server
int NateonConnection::sendBinaryCommand(const QString& sPrefix, const QByteArray &sText)
{
#ifdef KNATEONTEST
    ASSERT( sPrefix.length() == 3 );
#endif

    int      nTrid = getTrid();
    QString sTridString;
    // Get an acknowledgement number and convert it to a string
    sTridString.sprintf("%d", nTrid);

#ifdef KNATEONTEST
    ASSERT( sTridString.toInt() == nTrid );
#endif
#ifdef NETDEBUG
    kdDebug() << "MsnConnection: Sending " << sPrefix << " command (" << sTridString << ")." << endl;
#endif

    // Don't break the ascii-zero characters!
	// Copy at once.
    QString sFullHeader = sPrefix + " " + sTridString + " ";
    uint nCmdLength = sFullHeader.length() + sText.size();
    uint nPos = 0;

    QByteArray binCommand(nCmdLength);

    // This lame solution appears to be the only way to preserve the ascii-zero header bytes.
    for(uint i = 0; i < sFullHeader.length(); ++i) binCommand[nPos++] = sFullHeader[i].latin1();
    for(uint i = 0; i < sText.size();         ++i) binCommand[nPos++] = sText[i];

#ifdef NETDEBUG
    kdDebug() << "MsnConnection: p2p message size = " << binCommand.size() << endl;
#endif

    writeBinaryData(binCommand);

    // Return the ack used
    return nTrid;
}


// Send a "ping" to the server
void NateonConnection::sendPing()
{
    QString sMessage;

    if ( m_bPingReceived == false )
    {
        m_nMissedPings++;

	    m_pingTimer.changeInterval ( 3000 );
	    
        if ( m_nMissedPings == 1 )
        {
            sMessage += UTF8( "1 ping lost" );
        }
        else
        {
            sMessage += UTF8( "%1 pings lost" ).arg(m_nMissedPings);
        }

        emit statusMessage( sMessage, 2 );
    }
    else
    {
        emit statusMessage( UTF8( "Connection good" ), 1 );
    }

    m_bPingReceived = false;

    if ( m_nMissedPings == 3 )
    {
#if 1
        kdDebug() << "WARNING: 5 missed server pings, assuming disconnected" << endl;
#endif
	    disconnectFromServer();
	    emit pingError();
    }

    writeData( "PONG 0\r\n" );
}


// Set whether we're sending pings or not (also resets ping timer)
void NateonConnection::setSendPings( bool bSendPings )
{
    m_bSendPings = bSendPings;

    m_nMissedPings = 0;

    m_bPingReceived = true;

    if ( m_bSendPings )
    {
        sendPing();

        resetPingTimer();
    }
    else
    {
        m_pingTimer.stop();
    }
}


// Dealing different proxy state, implemented in class MsnNotificationConnection
void NateonConnection::setProxyState(PROXYSTATE state)
{
    switch(state)
    {
	case PROXYCONNECTED:

		break;

	case PROXYHOSTCONNECTED:

		m_nProxyState=0;
		if(m_pSocket!=0)
		{
			disconnect( m_pSocket, SIGNAL( readyRead() ), this, SLOT( proxyDataReceived() ) );
			disconnect( m_pSocket, SIGNAL( readyRead() ), this, SLOT( dataReceived()) );
			disconnect( m_pSocket, SIGNAL( connectionSuccess( void ) ), this, SLOT( connectionSuccess( void ) ) );
			disconnect( m_pSocket, SIGNAL( connectionSuccess( void ) ), this, SLOT( proxyConnected( void ) ) );
			disconnect( m_pSocket, SIGNAL( closed( int ) ), this, SLOT( socketclosed( int ) ) );
			disconnect( m_pSocket, SIGNAL( connectionFailed( int ) ), this, SLOT( socketError( int ) ) );
			
			connect( m_pSocket, SIGNAL( readyRead() ), this, SLOT( proxyDataReceived() ) );
			connect( m_pSocket, SIGNAL( connectionFailed( int ) ), this, SLOT( socketError( int ) ) );
			connect( m_pSocket, SIGNAL( connectionSuccess( void ) ), this, SLOT( proxyConnected( void ) ) );
			connect( m_pSocket, SIGNAL( closed( int ) ), this, SLOT( socketclosed( int ) ) );
#if 0
			disconnect(m_pSocket, SIGNAL(readyRead()), this, SLOT(proxyDataReceived()) );
			disconnect(m_pSocket, SIGNAL(connectionSuccess(void) ), this, SLOT(proxyConnected(void)) );
			connect(m_pSocket, SIGNAL(readyRead()), this, SLOT(dataReceived()) );
			connect(m_pSocket, SIGNAL(connectionSuccess(void) ), this, SLOT( connectionSuccess(void)) );
#endif
		}
		connectionSuccess(); // Send version commands
		break;

	case PROXYERROR:
	case PROXYFAIL:
		m_nProxyState = 0;
		if(m_pSocket!=0)
		{
			disconnect( m_pSocket, SIGNAL( readyRead() ), this, SLOT( proxyDataReceived() ) );
			disconnect( m_pSocket, SIGNAL( readyRead() ), this, SLOT( dataReceived()) );
			disconnect( m_pSocket, SIGNAL( connectionSuccess( void ) ), this, SLOT( connectionSuccess( void ) ) );
			disconnect( m_pSocket, SIGNAL( connectionSuccess( void ) ), this, SLOT( proxyConnected( void ) ) );
			disconnect( m_pSocket, SIGNAL( closed( int ) ), this, SLOT( socketclosed( int ) ) );
			disconnect( m_pSocket, SIGNAL( connectionFailed( int ) ), this, SLOT( socketError( int ) ) );
			
			connect( m_pSocket, SIGNAL( readyRead() ), this, SLOT( dataReceived() ) );
			connect( m_pSocket, SIGNAL( connectionFailed( int ) ), this, SLOT( socketError( int ) ) );
			connect( m_pSocket, SIGNAL( connectionSuccess( void ) ), this, SLOT( connectionSuccess( void ) ) );
			connect( m_pSocket, SIGNAL( closed( int ) ), this, SLOT( socketclosed( int ) ) );
#if 0
			disconnect( m_pSocket, SIGNAL(readyRead()),this, SLOT(proxyDataReceived()) );
			disconnect( m_pSocket, SIGNAL( connectionSuccess(void) ),this, SLOT( proxyConnected(void)) );
			connect( m_pSocket, SIGNAL(readyRead()),this, SLOT(dataReceived()) );
			connect( m_pSocket, SIGNAL( connectionSuccess(void) ),this, SLOT( connectionSuccess(void)) );
#endif
		}
		proxyFailed();
		break;
    }
}


// Detect a socket error
void NateonConnection::socketError(int error)
{
	Q_UNUSED( error );
	
#if 1
    kdDebug() << "Connection:WARNING - Received error " << error << " from the socket." << endl;
#endif
    disconnectFromServer();
}


// Send authentication info to the socks5 server
void NateonConnection::socks5_auth(void)
{
    QString uid=m_pCurrentAccount->getProxyUID();
    QString pwd=m_pCurrentAccount->getProxyPassword();

    int ulen = uid.length();
    int plen = pwd.length();
    char * command = new char[3+ulen+plen];
    sprintf((char *)command,"  %s %s",uid.local8Bit().data(),pwd.local8Bit().data());

    command[0]='\x01';           // Version of the subnegotiation, not the protocol
    command[1]=ulen;
    command[2+ulen] = plen;

    writeProxyData( command,3+ulen+plen );
    delete []command;
}


// Finally request to connect to the host via the socks5 proxy
void NateonConnection::socks5_connect(void)
{
    char command[10];
    bzero(command,10);

    command[0]='\x05';           // Protocol version
    command[1]='\x01';           // CONNECT
    command[2]='\x00';           // RESERVED, now is '\x00'
    command[3]='\x01';           // Indicates IP V4 address
                                 //4 bytes IP address
    memcpy( command+4, &m_addr_destServer.sin_addr,4 );
	//2 bytes port
    memcpy( command+8, &m_addr_destServer.sin_port,2 );

    writeProxyData(command, 10 );
}


// Send different request(send authentication info, connect to the destination)
// to the socks5 server according to its reply
void NateonConnection::socks5_reply(const char *buf,int nread)
{
    switch( m_nProxyState)
    {
	case 1:                  // Reply indicates wheather to use authentication

		if( nread!=2 )
		{
			//Reply must have exact 2 bytes
			setProxyState(PROXYERROR );
			return;
		}

		switch( buf[1] )
		{
		case '\x00':     // No authentation needed

			socks5_connect();
			m_nProxyState=3;
			return;

		case '\x02':     // Authentation needed

			socks5_auth();
			m_nProxyState=2;
			return;

		case '\xff':     //NO ACCEPTABLE METHODS
		default:

			//'\x03' to '\x7F'      IANA ASSIGNED
			//'\x80' to '\xFE'      RESERVED FOR PRIVATE METHODS
			setProxyState(PROXYFAIL);
			return;
		}
		break;

	case 2:                  //Reply indicates whether the uid and password sent are correct

		if( nread!=2 )
		{
			//Reply must have exact 2 bytes
			setProxyState(PROXYERROR);
			return;
		}

		if( buf[1]!='\00')   //auth fails
		{
			setProxyState(PROXYFAIL );
			return;
		}

		// uid and password are correct, and now start a connection to the messenger's host
		socks5_connect();
		m_nProxyState=3;
		break;

	case 3:                  // Reply indicates whether the proxy has made a connection to the host.

		if( nread!=10 )
		{
			//Reply must have exact 10 bytes
			setProxyState(PROXYERROR );
			return;
		}

		if(buf[1]!='\00' )   //connection fails
		{
			setProxyState(PROXYFAIL );
			return;
		}

		// Connection to the host is established
		setProxyState(PROXYHOSTCONNECTED );
		break;

	default:
		m_nProxyState=0;
		break;
    }
}


// Write data to the socket
void NateonConnection::writeData(const QString& sData)
{
    int nBytesWritten;

    while ( m_bWriteLocked )
    {
	    sleep(1);
#ifdef NETDEBUG
        kdDebug() << "Connection: WRITE DATA IS LOCKED TO AVOID WRITING OVERLAPPING DATA TO THE SOCKET." << endl;
#endif
    }

    // Lock the writing of data.
    m_bWriteLocked = true;

    if ( isConnected() )
    {
	    QCString unicode;
	    if ( m_pCurrentAccount->getProxyType() == 2 ) {
		    /*! HTTP Proxy */
		    QString sHttp( m_pHttpProxy->getPOST( sData ) );
		    unicode = sHttp.utf8();
	    } else {
		    unicode = sData.utf8();
	    }
		nBytesWritten = m_pSocket->writeBlock( unicode.data(), unicode.length() );
    }
    // Unlock the writing of data.
    m_bWriteLocked = false;

    emit messageSent( QString::fromUtf8(sData) );
}


// Write data to the socket without conversions
void NateonConnection::writeBinaryData(const QByteArray& data)
{
#ifdef NETDEBUG
    kdDebug() << "Connection: Writing data to the socket." << endl;
    kdDebug() << "Check for a lock" << endl;
#endif
    int nBytesWritten;

    while ( m_bWriteLocked )
    {
#ifdef NETDEBUG
        kdDebug() << "Connection: WRITE DATA IS LOCKED TO AVOID WRITING OVERLAPPING DATA TO THE SOCKET." << endl;
#endif
    }
    // Lock the writing of data.
    m_bWriteLocked = true;

    if ( isConnected() )
    {

#ifdef NETDEBUG
        kdDebug() << m_sIdentifier << " >>> [P2P message data]" << endl;
#endif

        int nDataLength = 0;

        nDataLength = data.size();

        // NOTE: Assumes the caller used the right encoding already...!
        //       using .utf8() here breaks the ascii zero chars again.
        nBytesWritten = m_pSocket->writeBlock( data.data(), nDataLength );
#ifdef NETDEBUG
        if ( nBytesWritten != nDataLength )
        {
	        kdDebug() << "Connection: WARNING - Wanted to write " << data.size() << " bytes to the socket, wrote " << nBytesWritten << "." << endl;
        }
#endif
    }
#ifdef NETDEBUG
    else
    {
		kdDebug() << "[2] Connection: WARNING - Attempting to write data to a disconnected socket." << endl;
    }
#endif
    // Unlock the writing of data.
    m_bWriteLocked = false;
    emit messageSent(QString(data));
}


// Write data to the socket dealing requests and replies with the proxy
void NateonConnection::writeProxyData(const char *buf,int len)
{
	mproxywriteLocked_->lock();
    m_pSocket->writeBlock(buf, len);

    //socket_->flush();
	mproxywriteLocked_->unlock();
}


/*!
  \fn NateonConnection::socketclosed()
*/
void NateonConnection::socketclosed(int nFlag)
{
    kdDebug() << "socketclosed : " << nFlag << endl;
    
    // Q_UNUSED( nFlag );
	disconnectFromServer();
}


#include "nateonconnection.moc"

void NateonConnection::sendCommand_noTid(const QString& sPrefix, const QString& sText)
{
    // Send the data to the server
    QString sCommand = sPrefix + sText;
    writeData( sCommand );

    // Return the ack used
    return;
}


const QString NateonConnection::getUserID() const
{
    return m_pCurrentAccount->getID();
}

void NateonConnection::slotConnectionTimeout()
{
    kdDebug() << "slotConnectionTimeout" << endl;
	m_pRetryTimer.stop();
	m_pRetryTimer.start( 3000, TRUE );
	
	disconnectFromServer();
}

void NateonConnection::slotRetry()
{
	if ( ( m_pSocket->socketStatus() == KExtendedSocket::lookupInProgress ) ||
	     ( m_pSocket->socketStatus() == KExtendedSocket::connected ) ||
	     ( m_pSocket->socketStatus() == KExtendedSocket::connecting ) )
	{
		m_pRetryTimer.stop();
	}
	else
	{
#ifdef NETDEBUG
		kdDebug() << ">>> Retry Connectting... " << endl;
#endif
		m_pSocket->startAsyncConnect();
		connectionTimer_.stop();
		connectionTimer_.start(5000, true);
		// m_pRetryTimer.start( 3000, TRUE );
	}
}

void NateonConnection::slotRunCommand()
{
	if ( bRunning )
		return;
	bRunning = TRUE;

	while( !qCommand.isEmpty() )
	{
		QString *sCommand = qCommand.dequeue();
		if ( sCommand == 0 )
			break;
		QStringList slCommand = QStringList::split( " ", *sCommand );
		sConfirmCommand = slCommand[0];
		sConfirmTID = slCommand[1];
		writeData( *sCommand );
		bRunning = TRUE;
		tCommandTimeout.start( 3000 );
	}
}

void NateonConnection::slotCommandTimeout()
{
#ifdef NETDEBUG
	kdDebug() << "ERROR :" << sConfirmCommand << " " << sConfirmTID << "... " << " Not Received!!!" << endl;
#endif
	bRunning = FALSE;
	slotRunCommand();
}

void NateonConnection::addCommand(int nTID, const QString & sPrefix, const QString & sText)
{
	QString *sCommand = new QString();
	*sCommand = sPrefix;
	*sCommand += " ";
	*sCommand += QString::number( nTID );
	*sCommand += " ";
	*sCommand += sText;
	*sCommand += "\r\n";

	int *myInt = new int();
	*myInt = nTID;
	
	nextCommand.insert( myInt, sCommand );
}

void NateonConnection::sendCmd(const QString & sCommand)
{
	writeData( sCommand );
}


