⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 evasocket.cpp

📁 linux下的eva源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************** *   Copyright (C) 2004-2005 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.             * ***************************************************************************/ #include "evasocket.h"#include "qmdcodec.h"#include <unistd.h>#include <stdio.h>#include <string.h>#include <arpa/inet.h>#include <sys/mman.h>#include <stdlib.h>#include <qsocketdevice.h> #include <qsocketnotifier.h>#include <qapplication.h>#include <qmutex.h>#include <qtimer.h>#include <qstringlist.h>#include <qurl.h>#include <qiodevice.h>#include <qtextstream.h>#include <qdns.h>#include <qcstring.h>#include <kdebug.h>/*!	\class EvaSocket evasocket.h	\brief The EvaSocket class provides a UDP or TCP connection		It provides a very simple non-blocking socket connection.	socketWriteNotifier is only used once to notify that the connection is ready 	to write, after isReady() emited, socketWriteNotifier is disabled unless 	setHost() is called. */EvaSocket::EvaSocket(const  QHostAddress &host, const short port, const Type type)	: socketReadNotifier(NULL), socketWriteNotifier(NULL){	connectionStatus = None;	receivedLength = 0;	receivedBuffer = NULL;	connectionType = type;        server = host;	serverPort = port;	if(connectionType == UDP){		connectSocket = new QSocketDevice(QSocketDevice::Datagram); 	}else{		connectSocket = new QSocketDevice(QSocketDevice::Stream);		connectSocket->setBlocking(false);        	socketWriteNotifier =  new QSocketNotifier(connectSocket->socket(),							QSocketNotifier::Write,0,"writeNotifier");		QObject::connect(socketWriteNotifier,SIGNAL(activated(int)),SLOT(slotWriteReady(int)));		socketWriteNotifier->setEnabled(false);	}	socketReadNotifier = new QSocketNotifier(connectSocket->socket(),						QSocketNotifier::Read,0,"readNotifier");	connectionStatus = Init;	QObject::connect(socketReadNotifier,SIGNAL(activated(int)),SLOT(slotReceiveReady(int)));	socketReadNotifier->setEnabled(false);}EvaSocket::~EvaSocket(){	delete connectSocket;	if(socketReadNotifier) {		socketReadNotifier->setEnabled(false);		delete socketReadNotifier;	}	if(socketWriteNotifier) {		socketWriteNotifier->setEnabled(false);		delete socketWriteNotifier;	}}const QHostAddress EvaSocket::getSocketAddress( ){	if(connectSocket) return connectSocket->address();	return QHostAddress();}const unsigned short EvaSocket::getSocketPort( ){	if(connectSocket) return connectSocket->port();	return 0;}void EvaSocket::setHost(const QHostAddress &address, const short port){	server = address;	serverPort = port;  	connectionStatus = None;	if(connectSocket->isValid()){		delete connectSocket;		if(socketReadNotifier) {			socketReadNotifier->setEnabled(false);			delete socketReadNotifier;		}		if(socketWriteNotifier) {			socketWriteNotifier->setEnabled(false);			delete socketWriteNotifier;		}		if(connectionType == UDP){			connectSocket = new QSocketDevice(QSocketDevice::Datagram); 		}else{			connectSocket = new QSocketDevice(QSocketDevice::Stream); 			connectSocket->setBlocking(false);			socketWriteNotifier =  new QSocketNotifier(connectSocket->socket(),								QSocketNotifier::Write,0,"writeNotifier");			QObject::connect(socketWriteNotifier,SIGNAL(activated(int)),SLOT(slotWriteReady(int)));			socketWriteNotifier->setEnabled(false);		}		socketReadNotifier = new QSocketNotifier(connectSocket->socket(),							QSocketNotifier::Read,0,"SocketNotifier");		QObject::connect(socketReadNotifier,SIGNAL(activated(int)),SLOT(slotReceiveReady(int)));		if(connectionType == TCP)			socketReadNotifier->setEnabled(false);	}	connectionStatus = Init;}void EvaSocket::closeConnection(){	if(connectSocket->isOpen()) connectSocket->close();	connectionStatus = None;	receivedLength = 0;}void EvaSocket::startConnecting(){	if(connectionStatus != Init) {		emit exceptionEvent(connectionStatus);		return;	}	connectionStatus = Connecting;	if(connectionType == TCP){		if(!connectSocket->connect(server, serverPort)){			fprintf(stderr,"connecting server failed\nError type: ");			connectionStatus = Failed;			switch(connectSocket->error()){				case QSocketDevice::NoError:					fprintf(stderr,"NoError\n");					break;				case QSocketDevice::AlreadyBound:					fprintf(stderr,"AlreadyBound\n");					break; 				case QSocketDevice::Inaccessible:					fprintf(stderr,"Inaccessible\n");					break;				case QSocketDevice::NoResources:					fprintf(stderr,"NoResources\n");					break;				case QSocketDevice::InternalError:					fprintf(stderr,"InternalError\n");					break;				case QSocketDevice::Impossible:					fprintf(stderr,"Impossible\n");					break;				case QSocketDevice::NoFiles:					fprintf(stderr,"NoFiles\n");					break;				case QSocketDevice::ConnectionRefused:					fprintf(stderr,"ConnectionRefused\n");					break;				case QSocketDevice::NetworkFailure:					fprintf(stderr,"NetworkFailure\n");					break;				case QSocketDevice::UnknownError:					fprintf(stderr,"UnknownError\n");					break;				default:					printf("not listed error\n");			}			emit exceptionEvent(connectionStatus);			return;		}	}	if(socketReadNotifier) socketReadNotifier->setEnabled(true);	if(connectionType == TCP && socketWriteNotifier) {		socketWriteNotifier->setEnabled(true);	}else{		connectionStatus = Ready;		emit isReady();	}}bool EvaSocket::write(const char *buf, const int len){	if(connectionStatus != Ready || !buf ) return false;	if(!connectSocket->isValid()){		if(connectionType == TCP && socketReadNotifier && socketWriteNotifier){			socketReadNotifier->setEnabled(false);			socketWriteNotifier->setEnabled(false);		}		emit exceptionEvent(Failed);		return false;	}	QMutex mutex;	mutex.lock();	int BytesSent = 0;	if(socketWriteNotifier) socketWriteNotifier->setEnabled(false);	if(connectionType == UDP){		BytesSent =connectSocket->writeBlock(buf, len, server, serverPort);	}else{		int bytes = 0;		int times = 0;		while(BytesSent < len){			bytes =connectSocket->writeBlock(buf + BytesSent, len - BytesSent);			if(bytes == -1) {				printf("EvaSocket::write retry :%d\n", times);				if(!connectSocket->error()){					if(times>20){						fprintf(stderr, "EvaSocket::write -- error : retried %d times\n", times);						mutex.unlock();						return false;					}					usleep(10000);					//qApp->processEvents();					times++;					continue;				}else					break;			}			BytesSent += bytes;		}	}	mutex.unlock();	if(len != BytesSent){		printf("EvaSocket::write -- error code: %d\n", connectSocket->error());		return false;	}	return true;}bool EvaSocket::read(char *buf, int len){	if(connectionStatus != Ready || receivedLength != len || !buf ){		printf("EvaSocket::read -- receivedLength: %d, len: %d\n", receivedLength, len);		return false;	}	memcpy(buf, receivedBuffer, receivedLength);	if(socketReadNotifier) socketReadNotifier->setEnabled(true);	return true;}void EvaSocket::setWriteNotifierEnabled( bool enabled ){	if(socketWriteNotifier) socketWriteNotifier->setEnabled(enabled);}void EvaSocket::slotWriteReady(int /*socket */){	if(socketWriteNotifier) socketWriteNotifier->setEnabled(false);	if(connectionStatus == Connecting){		connectionStatus = Ready;		emit isReady();	} else{		emit writeReady();	}}void EvaSocket::slotReceiveReady(int /*socket*/){	if( (socketReadNotifier->type() != QSocketNotifier::Read) || (!connectSocket->isValid()) ){		socketReadNotifier->setEnabled(false);		printf("EvaSocket::slotReceiveReady -- socket not valid or notifier not set to Read \n");		emit exceptionEvent(Failed);		return;	}			int ByteCount = 0;	ByteCount = connectSocket->bytesAvailable();		if(receivedBuffer!=NULL) delete receivedBuffer;	receivedBuffer = new char[ByteCount * 2];  		receivedLength = connectSocket->readBlock(receivedBuffer,ByteCount*2);	if(!receivedLength){		printf("EvaSocket::slotReceiveReady -- connection closed due to ZERO byte\n");		socketReadNotifier->setEnabled(false);		emit exceptionEvent(Failed);		return;	}		if(receivedLength == -1){		printf("EvaSocket::slotReceiveReady -- readBlock return -1\n");		emit exceptionEvent(Failed);		return;	}	if(socketReadNotifier) socketReadNotifier->setEnabled(false);	emit receivedData(receivedLength);	if(receivedLength != ByteCount)		printf("EvaSocket::slotReceiveReady -- bytesAvailable() might not be accurate.\n");}/* =========================================================== */EvaHttpProxy::EvaHttpProxy(const QHostAddress &proxyHost, const short proxyPort, const QString username, const QString password)	: EvaSocket(proxyHost, proxyPort, EvaSocket::TCP),	status(Proxy_None),	destinationAddress(""),	base64AuthParam(""),	readBuffer(NULL){	if(username!=QString::null && password!= QString::null){		setAuthParameter(username, password);	}	QObject::connect(this, SIGNAL(isReady()), SLOT(tcpReady()));	QObject::connect(this, SIGNAL(writeReady()), SLOT(slotWriteReady()));	QObject::connect(this, SIGNAL(receivedData(int)), SLOT(parseData(int)));	QObject::connect(this, SIGNAL(exceptionEvent(int)), SIGNAL(socketException(int)));}void EvaHttpProxy::setDestinationServer(const QString &server, const int port) // server could be IP or URL{	destinationAddress = server + ':' + QString::number(port);// qq http proxy server port: 443	status = Proxy_None;}void EvaHttpProxy::setAuthParameter(const QString &username, const QString &password){	QCString para = (username + ':' + password).local8Bit();	base64AuthParam = QCodecs::base64Encode(para);	status = Proxy_None;}bool EvaHttpProxy::doInitConnecting(){	if(getStatus() != EvaSocket::Ready) return false;	if(destinationAddress == "") return false;	sentBuffer = "CONNECT " + destinationAddress.local8Bit() + " HTTP/1.1\r\n" +		"Accept: */*\r\n" + "Content-Type: text/html\r\nProxy-Connection: Keep-Alive\r\n" +		"Content-length: 0\r\n\r\n";	status = Proxy_Connecting;	return write(sentBuffer.data(), sentBuffer.length());}bool EvaHttpProxy::doAuthConnecting(){	if(getStatus() != EvaSocket::Ready) return false;	if(destinationAddress == "") return false;	if(base64AuthParam == "") return false;		sentBuffer = "CONNECT " + destinationAddress.local8Bit() + " HTTP/1.1\r\n" +		"Proxy-Authorization: Basic " + base64AuthParam + "\r\n" +		"Accept: */*\r\nContent-Type: text/html\r\nProxy-Connection: Keep-Alive\r\n" +		"Content-length: 0\r\n\r\n";	status = Proxy_Connecting;	return write(sentBuffer.data(), sentBuffer.length());}void EvaHttpProxy::tcpReady(){	printf("EvaHttpProxy::tcpReady -- TCP connection ready\n");	if(destinationAddress == "") {		emit proxyEvent(Proxy_TCP_Ready);		return;	}		if(base64AuthParam != "")		doAuthConnecting();	else 		doInitConnecting();}void EvaHttpProxy::slotWriteReady(){	if ( status == Proxy_Ready )		emit proxyWriteReady();}void EvaHttpProxy::parseData(int len){		if(readBuffer!=NULL) free(readBuffer);	readBuffer = (char *)malloc((len+1) * sizeof(char));	if(!read(readBuffer, len)){ 		emit proxyEvent(Proxy_Read_Error);		return;	}	readBuffer[len]=0x00;	QString replyBuffer(readBuffer);	if(replyBuffer.startsWith("HTTP/1.1")){ // this is for RedHat 9, the old Qt dosen't support QString::startsWith(const QString &str, bool cs) const		int replyCode = replyBuffer.mid(9, 3).toInt();		fprintf(stderr, "Proxy Server Reply Code: %d\n",replyCode);		switch(replyCode){		case 200:			status = Proxy_Ready;			emit proxyEvent(Proxy_Ready);			break;		case 407:  //Proxy Authentication Required			status = Proxy_Need_Auth;			emit proxyEvent(Proxy_Need_Auth);			break;		case 501:  // "Not Support"		case 502:  // "Proxy Error"		default:			status = Proxy_Error;			emit proxyEvent(Proxy_Error);			break;		}		return;	}	if(status == Proxy_Ready)		dataArrived(len);}/** ============================================================== **/HttpHeader::HttpHeader()	: m_HeaderLen(0),	m_ContentLen(0),	m_Username(""),	m_Password(""),	m_Base64AuthParam(""){}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -