/***************************************************************************
 *   Copyright (C) 2004 by yunfan                                          *
 *   yunfan_zg@163.com                                                     *
 *                                                                         *
 *   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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef EVASOCKET_H
#define EVASOCKET_H
#include <qhostaddress.h>
#include <qcstring.h>
#include <qobject.h>

// Implementing UDP & TCP connections to Tencent Server

class QSocketDevice;
class QSocketNotifier;
 
class EvaSocket : public QObject {
	Q_OBJECT
public:
	enum Type { TCP, UDP};
	enum Status { Init, Connecting, Ready, Failed, None, BytesReadWrong};
	EvaSocket(const QHostAddress &host, const short port, const Type type = UDP);
	~EvaSocket();
	
	const Type getConnectType() const { return connectionType; }
		
	void setHost( const QHostAddress &address, const short port);
	const QHostAddress &getHostAddress() const { return server; }
	const short getHostPort() const { return serverPort; }
	const Status getStatus() const { return connectionStatus; }
	
	void closeConnection();
	void startConnecting();
	bool write(const char *buf, const int len);
	bool read(char *buf, int len);
signals:
	void isReady(); // when socket is connected, emit this
	void receivedData(int);     // after receiving data from server, emit this
	void exceptionEvent(int);      // emit whenever exception happens
protected:
	QSocketDevice *connectSocket;
	QSocketNotifier *socketNotifier; 
	
	int receivedLength;
	char *receivedBuffer;
private:
	Type connectionType;
	QHostAddress server;
	short serverPort;
	
	Status connectionStatus;  //  connected or not
private slots:
	void receiving();
};

// call read after receiving proxyEvent(Proxy_Ready) SIGNAL
class EvaHttpProxy : public EvaSocket {
	Q_OBJECT
public:
	enum ProxyStatus { Proxy_None, Proxy_TCP_Ready, Proxy_Connecting, Proxy_Ready, 
				Proxy_Need_Auth, Proxy_Read_Error, Proxy_Error};
	EvaHttpProxy(const QHostAddress &proxyHost, const short proxyPort, const QString username = QString::null, 
								const QString password = QString::null);
	void setDestinationServer(const QString &server, const int port); // server could be IP or URL
	const QString &getDestinationServer() const { return destinationAddress; }
	void setAuthParameter(const QString &username, const QString &password);
	const QCString &getBase64AuthParam() const { return base64AuthParam;}
	void setBase64AuthParam(const QCString &param) { base64AuthParam = param;  status = Proxy_None; }
	bool doInitConnecting();
	bool doAuthConnecting();
	
	const ProxyStatus getProxyStatus() const { return status; }
signals:
	void dataArrived(int);
	void proxyEvent( int );
	void socketException(int);
public slots:
	void tcpReady();
private:
	ProxyStatus status;
	QString destinationAddress;
	QCString base64AuthParam;
	QCString sentBuffer;
	char *readBuffer;
	void received(int len);
private slots:
	void parseData(int len);
};

#endif
