2 // This file is part of the aMule Project.
4 // Copyright (c) 2004-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2004-2008 Angel Vidal Veiga ( kry@users.sourceforge.net )
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "RemoteConnect.h"
32 DEFINE_LOCAL_EVENT_TYPE(wxEVT_EC_CONNECTION
)
34 CECLoginPacket::CECLoginPacket(const wxString
&pass
,
35 const wxString
& client
, const wxString
& version
) : CECPacket(EC_OP_AUTH_REQ
)
37 AddTag(CECTag(EC_TAG_CLIENT_NAME
, client
));
38 AddTag(CECTag(EC_TAG_CLIENT_VERSION
, version
));
39 AddTag(CECTag(EC_TAG_PROTOCOL_VERSION
, (uint64
)EC_CURRENT_PROTOCOL_VERSION
));
42 wxCHECK2(passhash
.Decode(pass
), /* Do nothing. */);
43 AddTag(CECTag(EC_TAG_PASSWD_HASH
, passhash
));
48 wxCHECK2(versionhash
.Decode(wxT(EC_VERSION_ID
)), /* Do nothing. */);
49 AddTag(CECTag(EC_TAG_VERSION_ID
, versionhash
));
55 * Connection to remote core
59 CRemoteConnect::CRemoteConnect(wxEvtHandler
* evt_handler
)
61 CECMuleSocket(evt_handler
!= 0),
64 // Give application some indication about how fast requests are served
65 // When request fifo contain more that certain number of entries, it may
66 // indicate that either core or network is slowing us down
68 // This is not mean to be absolute limit, because we can't drop requests
69 // out of calling context; it is just signal to application to slow down
71 m_notifier(evt_handler
)
75 bool CRemoteConnect::ConnectToCore(const wxString
&host
, int port
,
76 const wxString
&WXUNUSED(login
), const wxString
&pass
,
77 const wxString
& client
, const wxString
& version
)
79 m_connectionPassword
= pass
;
84 // don't even try to connect without a valid password
85 if (m_connectionPassword
.IsEmpty() || m_connectionPassword
== wxT("d41d8cd98f00b204e9800998ecf8427e")) {
86 m_server_reply
= _("You must specify a non-empty password.");
90 if (!hash
.Decode(m_connectionPassword
)) {
91 m_server_reply
= _("Invalid password, not a MD5 hash!");
93 } else if (hash
.IsEmpty()) {
94 m_server_reply
= _("You must specify a non-empty password.");
104 if ( !ConnectSocket(addr
) ) {
108 // if we're using blocking calls - enter login sequence now. Else,
109 // we will wait untill OnConnect gets called
111 CECLoginPacket
login_req(m_connectionPassword
, m_client
, m_version
);
112 std::auto_ptr
<const CECPacket
> reply(SendRecvPacket(&login_req
));
113 return ConnectionEstablished(reply
.get());
115 m_ec_state
= EC_CONNECT_SENT
;
121 void CRemoteConnect::OnConnect() {
123 wxASSERT(m_ec_state
== EC_CONNECT_SENT
);
124 CECLoginPacket
login_req(m_connectionPassword
, m_client
, m_version
);
125 CECSocket::SendPacket(&login_req
);
127 m_ec_state
= EC_REQ_SENT
;
129 // do nothing, calling code will take from here
133 void CRemoteConnect::OnClose() {
135 // Notify app of failure
136 wxECSocketEvent
event(wxEVT_EC_CONNECTION
,false,_("Connection failure"));
137 m_notifier
->AddPendingEvent(event
);
139 // FIXME: wtf is that ?
140 //CECSocket::OnClose();
143 const CECPacket
*CRemoteConnect::OnPacketReceived(const CECPacket
*packet
)
145 CECPacket
*next_packet
= 0;
149 if ( ConnectionEstablished(packet
) ) {
152 m_ec_state
= EC_FAIL
;
156 if ( !m_req_fifo
.empty() ) {
157 CECPacketHandlerBase
*handler
= m_req_fifo
.front();
158 m_req_fifo
.pop_front();
160 handler
->HandlePacket(packet
);
163 printf("EC error - packet received, but request fifo is empty\n");
170 // no reply by default
175 * Our requests are served by core in FCFS order. And core always replies. So, even
176 * if we're not interested in reply, we preserve place in request fifo.
178 void CRemoteConnect::SendRequest(CECPacketHandlerBase
*handler
, CECPacket
*request
)
181 m_req_fifo
.push_back(handler
);
182 CECSocket::SendPacket(request
);
185 void CRemoteConnect::SendPacket(CECPacket
*request
)
187 SendRequest(0, request
);
190 bool CRemoteConnect::ConnectionEstablished(const CECPacket
*reply
) {
194 m_server_reply
= _("EC Connection Failed. Empty reply.");
197 if (reply
->GetOpCode() == EC_OP_AUTH_FAIL
) {
198 const CECTag
*reason
= reply
->GetTagByName(EC_TAG_STRING
);
199 if (reason
!= NULL
) {
200 m_server_reply
= wxString(_("ExternalConn: Access denied because: ")) +
201 wxGetTranslation(reason
->GetStringData());
203 m_server_reply
= _("ExternalConn: Access denied");
206 } else if (reply
->GetOpCode() != EC_OP_AUTH_OK
) {
207 m_server_reply
= _("ExternalConn: Bad reply from server. Connection closed.");
210 if (reply
->GetTagByName(EC_TAG_SERVER_VERSION
)) {
211 m_server_reply
= _("Succeeded! Connection established to aMule ") +
212 reply
->GetTagByName(EC_TAG_SERVER_VERSION
)->GetStringData();
214 m_server_reply
= _("Succeeded! Connection established.");
220 wxECSocketEvent
event(wxEVT_EC_CONNECTION
, result
, m_server_reply
);
221 m_notifier
->AddPendingEvent(event
);
226 /******************** EC API ***********************/
228 void CRemoteConnect::StartKad() {
229 CECPacket
req(EC_OP_KAD_START
);
233 void CRemoteConnect::StopKad() {
234 CECPacket
req(EC_OP_KAD_STOP
);
238 void CRemoteConnect::ConnectED2K(uint32 ip
, uint16 port
) {
239 CECPacket
req(EC_OP_SERVER_CONNECT
);
241 req
.AddTag(CECTag(EC_TAG_SERVER
, EC_IPv4_t(ip
, port
)));
246 void CRemoteConnect::DisconnectED2K() {
247 CECPacket
req(EC_OP_SERVER_DISCONNECT
);
251 void CRemoteConnect::RemoveServer(uint32 ip
, uint16 port
) {
252 CECPacket
req(EC_OP_SERVER_REMOVE
);
254 req
.AddTag(CECTag(EC_TAG_SERVER
, EC_IPv4_t(ip
, port
)));
258 // File_checked_for_headers