ecsocket.cpp
来自「wxWidgets写的电驴」· C++ 代码 · 共 799 行 · 第 1/2 页
CPP
799 行
//// This file is part of the aMule Project.//// Copyright (c) 2004-2006 aMule Team ( admin@amule.org / http://www.amule.org )// Copyright (c) 2004-2006 Angel Vidal Veiga ( kry@users.sourceforge.net )//// Any parts of this program derived from the xMule, lMule or eMule project,// or contributed by third-party developers are copyrighted by their// respective authors.//// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA//#include "ECSocket.h"#include <wx/intl.h> // Needed for i18n#include <zlib.h> // Needed for packet (de)compression#include <cstring> // Needed for memcpy()/memmove()#include <memory> // Needed for auto_ptr<>#include "ArchSpecific.h" // Needed for ENDIAN_NTOHL#include "ECVersion.h" // Needed for EC_VERSION_ID#include "ECCodes.h" // Needed for the EC_FLAG_* values#include "ECPacket.h" // Needed for CECPacket#include <wx/app.h> // Needed for wxTheApp#include "OtherFunctions.h"#include "common/StringFunctions.h" // Needed for unicode2char()#include "Logger.h"#include <common/Format.h>#define EC_SOCKET_BUFFER_SIZE 2048#define EC_COMPRESSION_LEVEL Z_BEST_COMPRESSION#define EC_MAX_UNCOMPRESSED 1024#ifndef __GNUC__#define __attribute__(x)#endif// If your compiler gives errors on these lines, just remove them.int utf8_mbtowc(wchar_t *p, const unsigned char *s, int n) __attribute__((__visibility__("internal")));int utf8_wctomb(unsigned char *s, wchar_t wc, int maxlen) __attribute__((__visibility__("internal")));int utf8_mb_remain(char c) __attribute__((__pure__));/*----------=> Import from the Linux kernel <=----------*//* * linux/fs/nls_base.c *//* * Sample implementation from Unicode home page. * http://www.stonehand.com/unicode/standard/fss-utf.html */struct utf8_table { int cmask; int cval; int shift; uint32 lmask; uint32 lval;};static struct utf8_table utf8_table[] ={ {0x80, 0x00, 0*6, 0x7F, 0, /* 1 byte sequence */}, {0xE0, 0xC0, 1*6, 0x7FF, 0x80, /* 2 byte sequence */}, {0xF0, 0xE0, 2*6, 0xFFFF, 0x800, /* 3 byte sequence */}, {0xF8, 0xF0, 3*6, 0x1FFFFF, 0x10000, /* 4 byte sequence */}, {0xFC, 0xF8, 4*6, 0x3FFFFFF, 0x200000, /* 5 byte sequence */}, {0xFE, 0xFC, 5*6, 0x7FFFFFFF, 0x4000000, /* 6 byte sequence */}, {0, 0, 0, 0, 0, /* end of table */}};int utf8_mbtowc(uint32 *p, const unsigned char *s, int n){ uint32 l; int c0, c, nc; struct utf8_table *t; nc = 0; c0 = *s; l = c0; for (t = utf8_table; t->cmask; t++) { nc++; if ((c0 & t->cmask) == t->cval) { l &= t->lmask; if (l < t->lval) return -1; *p = l; return nc; } if (n <= nc) return -1; s++; c = (*s ^ 0x80) & 0xFF; if (c & 0xC0) return -1; l = (l << 6) | c; } return -1;}int utf8_wctomb(unsigned char *s, uint32 wc, int maxlen){ uint32 l; int c, nc; struct utf8_table *t; l = wc; nc = 0; for (t = utf8_table; t->cmask && maxlen; t++, maxlen--) { nc++; if (l <= t->lmask) { c = t->shift; *s = t->cval | (l >> c); while (c > 0) { c -= 6; s++; *s = 0x80 | ((l >> c) & 0x3F); } return nc; } } return -1;}/*----------=> End of Import <=----------*/int utf8_mb_remain(char c){ int i; for (i = 0; i < 5; ++i) { if ((c & utf8_table[i].cmask) == utf8_table[i].cval) break; } return i;}size_t CQueuedData::ReadFromSocketAll(wxSocketBase *sock, size_t len){ size_t read_rem = len; // // We get here when socket is truly blocking // do { // // Give socket a 10 sec chance to recv more data. if ( !sock->WaitForRead(10, 0) ) { break; } sock->Read(m_wr_ptr, read_rem); m_wr_ptr += sock->LastCount(); read_rem -= sock->LastCount(); if (sock->Error()) { if (sock->LastError() != wxSOCKET_WOULDBLOCK) { break; } } } while ( read_rem ); return len - read_rem;}//-------------------- CECSocketHandler --------------------#define ECSOCKET_SENDPACKET (GSOCK_MAX_EVENT + 1)#define ECSOCKET_RECEIVEDPACKET (GSOCK_MAX_EVENT + 2)#define ECSOCKET_RECEIVEDDATA (GSOCK_MAX_EVENT + 3)#define EC_SOCKET_HANDLER (wxID_HIGHEST + 644)class CECSocketHandler: public wxEvtHandler { public: CECSocketHandler() {}; private: void SocketHandler(wxSocketEvent& event); DECLARE_EVENT_TABLE()};BEGIN_EVENT_TABLE(CECSocketHandler, wxEvtHandler) EVT_SOCKET(EC_SOCKET_HANDLER, CECSocketHandler::SocketHandler)END_EVENT_TABLE()void CECSocketHandler::SocketHandler(wxSocketEvent& event){ CECSocket *socket = dynamic_cast<CECSocket *>(event.GetSocket()); wxCHECK_RET(socket, wxT("Socket event with a NULL socket!")); switch(event.GetSocketEvent()) { case wxSOCKET_LOST: socket->OnLost(); break; case wxSOCKET_INPUT: socket->OnInput(); break; case wxSOCKET_OUTPUT: socket->OnOutput(); break; case wxSOCKET_CONNECTION: socket->OnConnect(); break; default: // Nothing should arrive here... wxFAIL; break; }}static CECSocketHandler g_ECSocketHandler;//// CECSocket API - User interface functions//CECSocket::CECSocket(bool use_events) : wxSocketClient(){ m_rx_flags = m_rx_flags = 0; m_my_flags = 0x20 | EC_FLAG_ZLIB | EC_FLAG_UTF8_NUMBERS; // setup initial state: 4 flags + 4 length m_bytes_needed = 8; m_in_header = true; m_in_ptr = new unsigned char[EC_SOCKET_BUFFER_SIZE]; m_out_ptr = new unsigned char[EC_SOCKET_BUFFER_SIZE]; m_curr_rx_data = new CQueuedData(EC_SOCKET_BUFFER_SIZE); m_curr_tx_data = new CQueuedData(EC_SOCKET_BUFFER_SIZE); m_use_events = use_events; if ( use_events ) { SetEventHandler(g_ECSocketHandler, EC_SOCKET_HANDLER); SetNotify(wxSOCKET_CONNECTION_FLAG | wxSOCKET_INPUT_FLAG | wxSOCKET_OUTPUT_FLAG | wxSOCKET_LOST_FLAG); Notify(true); SetFlags(wxSOCKET_NOWAIT); } else { SetFlags(wxSOCKET_WAITALL | wxSOCKET_BLOCK); Notify(false); }}CECSocket::~CECSocket(){ if (m_in_ptr) { delete [] m_in_ptr; } if (m_out_ptr) { delete [] m_out_ptr; } if (m_curr_rx_data) { delete m_curr_rx_data; } if (m_curr_tx_data) { delete m_curr_tx_data; } while (!m_output_queue.empty()) { CQueuedData *data = m_output_queue.front(); m_output_queue.pop_front(); delete data; }}bool CECSocket::Connect(wxSockAddress& address){ bool res = wxSocketClient::Connect(address, false); if ( !m_use_events ) { res = WaitOnConnect(10, 0); if ( res ) { OnConnect(); } else { OnLost(); } } return !Error();}void CECSocket::SendPacket(const CECPacket *packet){ WritePacket(packet); OnOutput();}const CECPacket *CECSocket::SendRecvPacket(const CECPacket *packet){ wxASSERT(!m_use_events); SendPacket(packet); m_curr_rx_data->ReadFromSocketAll(this, 2 * sizeof(uint32)); if (Error() && (LastError() != wxSOCKET_WOULDBLOCK)) { OnError(); return 0; } m_curr_rx_data->Read(&m_rx_flags, sizeof(m_rx_flags)); m_rx_flags = ENDIAN_NTOHL(m_rx_flags); m_curr_rx_data->Read(&m_curr_packet_len, sizeof(m_curr_packet_len)); m_curr_packet_len = ENDIAN_NTOHL(m_curr_packet_len); if ( m_curr_rx_data->GetLength() < (m_curr_packet_len+2*sizeof(uint32)) ) { delete m_curr_rx_data; m_curr_rx_data = new CQueuedData(m_curr_packet_len); } m_curr_rx_data->ReadFromSocketAll(this, m_curr_packet_len); if (Error() && (LastError() != wxSOCKET_WOULDBLOCK)) { OnError(); return 0; } const CECPacket *reply = ReadPacket(); m_curr_rx_data->Rewind(); return reply;}wxString CECSocket::GetErrorMsg(wxSocketError code){ switch(code) { case wxSOCKET_NOERROR: return wxT("No error happened"); case wxSOCKET_INVOP: return wxT("Invalid operation"); case wxSOCKET_IOERR: return wxT("Input/Output error"); case wxSOCKET_INVADDR: return wxT("Invalid address passed to wxSocket"); case wxSOCKET_INVSOCK: return wxT("Invalid socket (uninitialized)"); case wxSOCKET_NOHOST: return wxT("No corresponding host"); case wxSOCKET_INVPORT: return wxT("Invalid port"); case wxSOCKET_WOULDBLOCK: return wxT("The socket is non-blocking and the operation would block"); case wxSOCKET_TIMEDOUT: return wxT("The timeout for this operation expired"); case wxSOCKET_MEMERR: return wxT("Memory exhausted"); case wxSOCKET_DUMMY: return wxT("Dummy code - should not happen"); } return wxString::Format(wxT("Error code 0x%08x unknown"), code);}void CECSocket::OnError(){#ifdef __DEBUG__ printf("CECSocket error: %s\n", (const char *)unicode2char(GetErrorMsg(LastError())));#endif}void CECSocket::OnLost(){}void CECSocket::Destroy(){ wxSocketBase::Destroy();}//// Event handlers//void CECSocket::OnConnect(){}void CECSocket::OnInput(){ size_t bytes_rx = 0; do { if (m_curr_rx_data) { m_curr_rx_data->ReadFromSocket(this, m_bytes_needed); } else { return; } if ( Error() ) { if (LastError() != wxSOCKET_WOULDBLOCK && LastError() != wxSOCKET_NOERROR) { OnError(); // socket already disconnected in this point delete m_curr_rx_data; m_curr_rx_data = 0; return;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?