adding missing includes; trivial fix - comparison with string literal. by
[centerim.git] / libicq2000 / src / DirectClient.cpp
blob1550d68504d58ea1155ccc4aaa6beba1b09f320a
1 /*
2 * DirectClient
4 * Copyright (C) 2001 Barnaby Gray <barnaby@beedesign.co.uk>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "DirectClient.h"
24 #include "ICQ.h"
25 #include "constants.h"
27 #include "sstream_fix.h"
29 #include <stdlib.h>
31 using std::string;
32 using std::ostringstream;
33 using std::endl;
35 namespace ICQ2000 {
37 unsigned char DirectClient::client_check_data[] = {
38 "As part of this software beta version Mirabilis is "
39 "granting a limited access to the ICQ network, "
40 "servers, directories, listings, information and databases (\""
41 "ICQ Services and Information\"). The "
42 "ICQ Service and Information may databases (\""
43 "ICQ Services and Information\"). The "
44 "ICQ Service and Information may\0"
48 * Constructor when receiving an incoming connection
50 DirectClient::DirectClient(ContactRef self, TCPSocket *sock, MessageHandler *mh,
51 ContactTree *cl, unsigned int ext_ip, unsigned short server_port)
52 : m_state(WAITING_FOR_INIT), m_recv(),
53 m_self_contact(self), m_contact(NULL), m_contact_list(cl),
54 m_message_handler(mh), m_incoming(true), m_local_ext_ip(ext_ip),
55 m_local_server_port(server_port)
57 m_socket = sock;
58 Init();
62 * Constructor for making an outgoing connection
64 DirectClient::DirectClient(ContactRef self, ContactRef c, MessageHandler *mh, unsigned int ext_ip,
65 unsigned short server_port)
66 : m_state(NOT_CONNECTED), m_recv(), m_self_contact(self),
67 m_contact(c), m_message_handler(mh), m_incoming(false), m_local_ext_ip(ext_ip),
68 m_local_server_port(server_port)
71 Init();
72 m_socket = new TCPSocket();
73 m_remote_uin = c->getUIN();
76 DirectClient::~DirectClient()
78 m_msgcache.expireAll();
80 while (!m_msgqueue.empty()) {
81 expired_cb( m_msgqueue.front() );
82 m_msgqueue.pop_front();
85 if ( m_socket->getSocketHandle() > -1) SignalRemoveSocket( m_socket->getSocketHandle() );
86 delete m_socket;
89 void DirectClient::Init()
91 m_seqnum = 0xFFFF;
92 m_msgcache.setDefaultTimeout(30);
93 m_msgcache.expired.connect( this, &DirectClient::expired_cb) ;
96 void DirectClient::Connect() {
97 m_remote_tcp_version = m_contact->getTCPVersion();
98 if (m_remote_tcp_version >= 7) m_eff_tcp_version = 7;
99 else if (m_remote_tcp_version == 6) m_eff_tcp_version = 6;
100 else throw DisconnectedException("Cannot direct connect to client with too old TCP version");
102 m_socket->setRemoteIP( m_contact->getLanIP() );
103 m_socket->setRemotePort( m_contact->getLanPort() );
104 m_socket->setBlocking(false);
105 m_socket->Connect();
106 SignalAddSocket( m_socket->getSocketHandle(), SocketEvent::WRITE );
108 if (m_contact->getDCCookie() != 0)
110 m_session_id = m_contact->getDCCookie();
112 else
114 m_session_id = (unsigned int)(0xffffffff*(rand()/(RAND_MAX+1.0)));
118 m_state = WAITING_FOR_INIT_ACK;
121 void DirectClient::FinishNonBlockingConnect()
123 SendInitPacket();
126 void DirectClient::clearoutMessagesPoll()
128 m_msgcache.clearoutPoll();
131 void DirectClient::expired_cb(MessageEvent *ev) {
132 ev->setFinished(false);
133 ev->setDelivered(false);
134 ev->setDirect(true);
135 messageack.emit(ev);
138 void DirectClient::Recv() {
139 try {
140 while ( m_socket->connected() ) {
141 if ( !m_socket->Recv(m_recv) ) break;
142 Parse();
144 } catch(SocketException e) {
145 ostringstream ostr;
146 ostr << "Failed on recv: " << e.what();
147 throw DisconnectedException( ostr.str() );
148 } catch(ParseException e) {
149 ostringstream ostr;
150 ostr << "Failed parsing: " << e.what();
151 throw DisconnectedException( ostr.str() );
155 void DirectClient::Parse() {
156 if (m_recv.empty()) return;
158 unsigned int length;
160 while (!m_recv.empty()) {
161 m_recv.setPos(0);
163 m_recv.setLittleEndian();
164 m_recv >> length;
165 if (length == 0) return; // short read, toss it back (nothing to do)
166 if (length > Incoming_Packet_Limit) throw ParseException("Received too long incoming packet");
167 if (m_recv.remains() < length) return; // waiting for more of the packet
170 Buffer sb;
171 m_recv.chopOffBuffer( sb, length+2 );
173 ostringstream ostr;
174 ostr << "Received packet from " << IPtoString( m_socket->getRemoteIP() ) << ":" << m_socket->getRemotePort() << endl << sb;
175 SignalLog(LogEvent::DIRECTPACKET, ostr.str());
177 if (m_state == WAITING_FOR_INIT) {
178 ParseInitPacket(sb);
180 if (m_incoming) {
181 SendInitAck();
182 SendInitPacket();
183 m_state = WAITING_FOR_INIT_ACK;
184 } else {
185 SendInitAck();
186 if (m_eff_tcp_version == 7) {
187 SendInit2();
188 m_state = WAITING_FOR_INIT2;
189 } else {
190 m_state = CONNECTED;
191 flush_queue();
192 connected.emit(this);
196 } else if (m_state == WAITING_FOR_INIT_ACK) {
197 ParseInitAck(sb);
199 if (m_incoming) {
200 // Incoming
201 if (m_eff_tcp_version == 7)
202 m_state = WAITING_FOR_INIT2; // v7 has an extra stage of handshaking
203 else {
204 ConfirmUIN();
205 m_state = CONNECTED; // v5 is done handshaking now
206 flush_queue();
207 connected.emit(this);
210 } else {
211 // Outgoing - next packet should be their INIT
212 m_state = WAITING_FOR_INIT;
215 } else if (m_state == WAITING_FOR_INIT2) {
216 ParseInit2(sb);
217 // This is a V7 only packet
219 if (m_incoming) {
220 SendInit2();
221 ConfirmUIN();
224 m_state = CONNECTED;
225 flush_queue();
226 connected.emit(this);
228 } else if (m_state == CONNECTED) {
229 ParsePacket(sb);
233 if (sb.beforeEnd()) {
234 /* we assert that parsing code eats uses all data
235 * in the FLAP - seems useful to know when they aren't
236 * as it probably means they are faulty
238 ostringstream ostr;
239 ostr << "Buffer pointer not at end after parsing packet was: 0x" << std::hex << sb.pos()
240 << " should be: 0x" << sb.size();
241 SignalLog(LogEvent::WARN, ostr.str());
248 void DirectClient::ConfirmUIN() {
249 if ( m_contact_list->exists(m_remote_uin) ) {
250 ContactRef c = (*m_contact_list)[ m_remote_uin ];
251 if ( (c->getExtIP() == m_local_ext_ip && c->getLanIP() == getIP() )
252 /* They are behind the same masquerading box,
253 * and the Lan IP matches
255 || c->getExtIP() == getIP()) {
256 m_contact = c;
257 } else {
258 // spoofing attempt most likely
259 ostringstream ostr;
260 ostr << "Refusing direct connection from someone that claims to be UIN "
261 << m_remote_uin << " since their IP " << IPtoString( getIP() ) << " != " << IPtoString( c->getExtIP() );
262 throw DisconnectedException( ostr.str() );
265 } else {
266 // don't accept direct connections from contacts not on contact list
267 throw DisconnectedException("Refusing direct connection to contact not on contact list");
271 void DirectClient::SendInitPacket() {
272 Buffer b;
273 b.setLittleEndian();
274 Buffer::marker m1 = b.getAutoSizeShortMarker();
276 b << (unsigned char)0xff; // start byte
277 b << (unsigned short)0x0007; // tcp version
278 Buffer::marker m2 = b.getAutoSizeShortMarker();
280 b << m_remote_uin;
281 b << (unsigned short)0x0000;
282 b << (unsigned int)m_local_server_port;
284 b << m_self_contact->getUIN();
285 b.setBigEndian();
286 b << m_local_ext_ip;
287 b << m_socket->getLocalIP();
288 b << (unsigned char)0x04; // mode
289 b.setLittleEndian();
290 b << (unsigned int)m_local_server_port;
291 b << m_session_id;
293 b << (unsigned int)0x00000050; // unknown
294 b << (unsigned int)0x00000003; // unknown
295 if (m_eff_tcp_version == 7)
296 b << (unsigned int)0x00000000; // unknown
298 b.setAutoSizeMarker(m1);
299 b.setAutoSizeMarker(m2);
301 Send(b);
304 void DirectClient::ParseInitPacket(Buffer &b) {
305 b.setLittleEndian();
306 unsigned short length;
307 b >> length;
309 unsigned char start_byte;
310 b >> start_byte;
311 if (start_byte != 0xff) throw ParseException("Init Packet didn't start with 0xff");
313 unsigned short tcp_version;
314 b >> tcp_version;
315 b.advance(2); // revision or a length ??
317 if (m_incoming) {
318 m_remote_tcp_version = tcp_version;
319 if (tcp_version <= 5) throw ParseException("Too old client < ICQ99");
320 if (tcp_version == 6) m_eff_tcp_version = 6;
321 else m_eff_tcp_version = 7;
322 } else {
323 if (tcp_version != m_remote_tcp_version) throw ParseException("Client claiming different TCP versions");
326 unsigned int our_uin;
327 b >> our_uin;
328 if (our_uin != m_self_contact->getUIN()) throw ParseException("Local UIN in Init Packet not same as our Local UIN");
330 // 00 00
331 // xx xx senders open port
332 // 00 00
333 b.advance(6);
335 unsigned int remote_uin;
336 b >> remote_uin;
337 if (m_incoming) {
338 m_remote_uin = remote_uin;
339 } else {
340 if (m_remote_uin != remote_uin) throw ParseException("Remote UIN in Init Packet for Remote Client not what was expected");
343 // xx xx xx xx senders external IP
344 // xx xx xx xx senders lan IP
345 b.advance(8);
347 b >> m_tcp_flags;
349 // xx xx senders port again
350 // 00 00
351 b.advance(4);
353 // xx xx xx xx session id
354 unsigned int session_id;
355 b >> session_id;
356 if (m_incoming) {
357 m_session_id = session_id;
358 } else {
359 if (m_session_id != session_id) throw ParseException("Session ID from Remote Client doesn't match the one we sent");
362 // 50 00 00 00 unknown
363 // 03 00 00 00 unknown
364 b.advance(8);
366 if (m_eff_tcp_version == 7) {
367 b.advance(4); // 00 00 00 00 unknown
372 void DirectClient::ParseInitAck(Buffer &b) {
373 b.setLittleEndian();
374 unsigned short length;
375 b >> length;
376 if (length != 4) throw ParseException("Init Ack not as expected");
378 unsigned int a;
379 b >> a; // should be 0x00000001 really
382 void DirectClient::ParseInit2(Buffer &b) {
383 b.setLittleEndian();
384 unsigned short length;
385 b >> length;
386 if (length != 0x0021) throw ParseException("V7 final handshake packet incorrect length");
388 unsigned char type;
389 b >> type;
390 if (type != 0x03) throw ParseException("Expecting V7 final handshake packet, received something else");
392 unsigned int unknown;
393 b >> unknown // 0x0000000a
394 >> unknown;
395 b.advance(24); // unknowns
398 void DirectClient::SendInit2() {
399 Buffer b;
400 b.setLittleEndian();
401 Buffer::marker m1 = b.getAutoSizeShortMarker();
402 b << (unsigned char) 0x03 // start byte
403 << (unsigned int) 0x0000000a // unknown
404 << (unsigned int) 0x00000001 // unknown
405 << (unsigned int) (m_incoming ? 0x00000001 : 0x00000000) // unknown
406 << (unsigned int) 0x00000000 // unknown
407 << (unsigned int) 0x00000000; // unknown
408 if (m_incoming) {
409 b << (unsigned int) 0x00040001 // unknown
410 << (unsigned int) 0x00000000 // unknown
411 << (unsigned int) 0x00000000; // unknown
412 } else {
413 b << (unsigned int) 0x00000000 // unknown
414 << (unsigned int) 0x00000000 // unknown
415 << (unsigned int) 0x00040001; // unknown
417 b.setAutoSizeMarker(m1);
418 Send(b);
421 void DirectClient::ParsePacket(Buffer& b) {
422 Buffer c;
423 if (!Decrypt(b, c)) throw ParseException("Decrypting failed");
424 ParsePacketInt(c);
427 void DirectClient::ParsePacketInt(Buffer& b) {
428 b.setLittleEndian();
429 unsigned short length;
430 b >> length;
432 // we should get the decrypted packet in
433 unsigned int checksum;
434 unsigned short command, seqnum, unknown, version;
435 unsigned char junk;
436 string msg;
437 ostringstream ostr;
439 if (m_eff_tcp_version == 7) {
440 unsigned char start_byte;
441 b >> start_byte;
442 if (start_byte != 0x02) throw ParseException("Message Packet didn't start with 0x02");
445 b >> checksum
446 >> command
447 >> unknown // 0x000e or 0x0012 in probe packets
448 >> seqnum;
450 if (unknown != 0x000e) throw ParseException("Ignoring weird packet");
452 b.advance(12); // unknown 3 ints
454 ICQSubType *i = ICQSubType::ParseICQSubType(b, true, (command == V6_TCP_ACK));
455 if (dynamic_cast<UINICQSubType*>(i) == NULL) throw ParseException("Unknown ICQ subtype");
456 UINICQSubType *icqsubtype = dynamic_cast<UINICQSubType*>(i);
458 icqsubtype->setSeqNum(seqnum);
459 icqsubtype->setSource( m_contact->getUIN() );
461 if (command == 0) throw ParseException("Invalid TCP Packet");
463 switch(command) {
465 case V6_TCP_START:
467 if (icqsubtype->getType() == MSG_Type_FT)
469 FTICQSubType *fticqsubtype = static_cast<FTICQSubType*>( icqsubtype );
470 FileTransferEvent *ev = m_message_handler->handleIncomingFT( fticqsubtype, true );
471 m_msgcache.insert( seqnum, ev );
473 else
475 bool ack = m_message_handler->handleIncoming( icqsubtype );
476 if (ack) SendPacketAck(icqsubtype);
479 break;
480 case V6_TCP_ACK:
481 if ( m_msgcache.exists(seqnum) )
483 MessageEvent *ev = m_msgcache[seqnum];
484 ev->setDirect(true);
485 m_message_handler->handleIncomingACK( ev, icqsubtype );
486 m_msgcache.remove(seqnum);
487 if (icqsubtype->getType() != MSG_Type_FT)
488 delete ev; //WARNING!!! FileTransferEvent shall not be deleted here?
491 else
493 SignalLog(LogEvent::WARN, "Received Direct ACK for unknown message");
495 break;
497 case V6_TCP_CANCEL:
498 // FileTransfer was cancelled before we responded
499 if ( icqsubtype->getType() == MSG_Type_FT
500 && m_msgcache.exists(seqnum) )
502 MessageEvent *ev = m_msgcache[seqnum];
503 if ( ev->getType() == MessageEvent::FileTransfer )
505 FileTransferEvent *eev = static_cast<FileTransferEvent*>(ev);
506 m_message_handler->handleIncomingFTCancel( eev );
507 m_msgcache.remove(seqnum);
511 else
513 SignalLog(LogEvent::WARN, "Received Direct Cancel for unknown message");
515 break;
516 default:
517 ostr << "Unknown TCP Command received 0x" << command;
518 throw ParseException( ostr.str() );
521 delete icqsubtype;
523 b >> junk
524 >> version;
527 bool DirectClient::Decrypt(Buffer& in, Buffer& out) {
529 if (m_eff_tcp_version >= 6) {
530 // Huge *thanks* to licq for this code
532 unsigned long hex, key, B1, M1;
533 unsigned int i;
534 unsigned char X1, X2, X3;
535 unsigned int correction;
537 if (m_eff_tcp_version == 7) correction = 3;
538 else correction = 2;
540 unsigned int size = in.size()-correction;
542 in.setLittleEndian();
543 out.setLittleEndian();
545 unsigned short length;
546 in >> length;
547 out << length;
549 if (m_eff_tcp_version == 7) {
550 unsigned char start_byte;
551 in >> start_byte;
552 out << start_byte;
555 unsigned int check;
556 in >> check;
557 out << check;
559 // main XOR key
560 key = 0x67657268 * size + check;
562 for(i=4; i<(size+3)/4; i+=4) {
563 hex = key + client_check_data[i&0xFF];
565 out << (unsigned char)(in.UnpackChar() ^ (hex&0xFF));
566 out << (unsigned char)(in.UnpackChar() ^ ((hex>>8)&0xFF));
567 out << (unsigned char)(in.UnpackChar() ^ ((hex>>16)&0xFF));
568 out << (unsigned char)(in.UnpackChar() ^ ((hex>>24)&0xFF));
571 unsigned char c;
572 while (in.remains()) {
573 in >> c;
574 out << c;
577 B1 = (out[4+correction]<<24) | (out[6+correction]<<16) | (out[4+correction]<<8) | (out[6+correction]<<0);
579 // special decryption
580 B1 ^= check;
582 // validate packet
583 M1 = (B1 >> 24) & 0xFF;
584 if(M1 < 10 || M1 >= size) return false;
586 X1 = out[M1+correction] ^ 0xFF;
587 if(((B1 >> 16) & 0xFF) != X1) return false;
589 X2 = ((B1 >> 8) & 0xFF);
590 if(X2 < 220) {
591 X3 = client_check_data[X2] ^ 0xFF;
592 if((B1 & 0xFF) != X3) return false;
596 ostringstream ostr;
597 ostr << "Decrypted Direct packet from " << IPtoString( m_socket->getRemoteIP() ) << ":" << m_socket->getRemotePort() << endl << out;
598 SignalLog(LogEvent::DIRECTPACKET, ostr.str());
600 return true;
603 void DirectClient::Encrypt(Buffer& in, Buffer& out) {
605 ostringstream ostr;
606 ostr << "Unencrypted packet to " << IPtoString( m_socket->getRemoteIP() ) << ":" << m_socket->getRemotePort() << endl << in;
607 SignalLog(LogEvent::DIRECTPACKET, ostr.str());
609 if (m_eff_tcp_version == 6 || m_eff_tcp_version == 7) {
610 // Huge *thanks* to licq for this code
612 unsigned long hex, key, B1, M1;
613 unsigned int i, check;
614 unsigned char X1, X2, X3;
615 unsigned int size = in.size();
617 in.setLittleEndian();
618 out.setLittleEndian();
620 if (m_eff_tcp_version == 7) {
621 // correction for next byte
622 out << (unsigned short)(size + 1);
623 out << (unsigned char)0x02;
624 } else {
625 out << (unsigned short)size;
628 // calculate verification data
629 M1 = (rand() % ((size < 255 ? size : 255)-10))+10;
630 X1 = in[M1] ^ 0xFF;
631 X2 = rand() % 220;
632 X3 = client_check_data[X2] ^ 0xFF;
634 B1 = (in[4]<<24)|(in[6]<<16)|(in[4]<<8)|(in[6]);
636 // calculate checkcode
637 check = (M1 << 24) | (X1 << 16) | (X2 << 8) | X3;
638 check ^= B1;
640 out << check;
642 // main XOR key
643 key = 0x67657268 * size + check;
645 // XORing the actual data
646 in.advance(4);
647 for(i=4;i<(size+3)/4;i+=4){
648 hex = key + client_check_data[i&0xFF];
650 out << (unsigned char)(in.UnpackChar() ^ (hex&0xFF));
651 out << (unsigned char)(in.UnpackChar() ^ ((hex>>8)&0xFF));
652 out << (unsigned char)(in.UnpackChar() ^ ((hex>>16)&0xFF));
653 out << (unsigned char)(in.UnpackChar() ^ ((hex>>24)&0xFF));
656 unsigned char c;
657 while (in.remains()) {
658 in >> c;
659 out << c;
666 void DirectClient::SendInitAck()
668 Buffer b;
669 b.setLittleEndian();
670 Buffer::marker m1 = b.getAutoSizeShortMarker();
671 b << (unsigned int)0x00000001;
672 b.setAutoSizeMarker(m1);
673 Send(b);
676 void DirectClient::SendPacketAck(ICQSubType *icqsubtype)
678 Buffer b;
680 b.setLittleEndian();
681 b << (unsigned int)0x00000000 // checksum (filled in by Encrypt)
682 << V6_TCP_ACK
683 << (unsigned short)0x000e
684 << icqsubtype->getSeqNum()
685 << (unsigned int)0x00000000
686 << (unsigned int)0x00000000
687 << (unsigned int)0x00000000;
689 icqsubtype->Output(b);
690 Buffer c;
691 Encrypt(b,c);
692 Send(c);
695 void DirectClient::SendPacketEvent(MessageEvent *ev)
697 Buffer b;
699 unsigned short seqnum = NextSeqNum();
701 UINICQSubType *ist = m_message_handler->handleOutgoing(ev);
702 if (ist == NULL) return;
704 ist->setAdvanced(true);
706 b.setLittleEndian();
707 b << (unsigned int)0x00000000 // checksum (filled in by Encrypt)
708 << V6_TCP_START
709 << (unsigned short)0x000e
710 << seqnum
711 << (unsigned int)0x00000000
712 << (unsigned int)0x00000000
713 << (unsigned int)0x00000000;
714 ist->Output(b);
716 Buffer c;
717 Encrypt(b,c);
718 Send(c);
720 // Save seqnum so later ACK or CANCEL could be sent.
721 if (ist->getType() == MSG_Type_FT)
723 FileTransferEvent *fev = static_cast<FileTransferEvent*>(ev);
724 fev->setSeqNum(seqnum);
727 m_msgcache.insert(seqnum, ev);
729 delete ist;
732 void DirectClient::Send(Buffer &b) {
733 try {
734 ostringstream ostr;
735 ostr << "Sending packet to " << IPtoString( m_socket->getRemoteIP() ) << ":" << m_socket->getRemotePort() << endl << b;
736 SignalLog(LogEvent::DIRECTPACKET, ostr.str());
737 m_socket->Send(b);
738 } catch(SocketException e) {
739 ostringstream ostr;
740 ostr << "Failed to send: " << e.what();
741 throw DisconnectedException( ostr.str() );
746 void DirectClient::SendFTACK(FileTransferEvent *ev)
748 FTICQSubType icqsubtype;
749 icqsubtype.setAdvanced(true);
750 icqsubtype.setSeqNum(ev->getSeqNum());
751 icqsubtype.setACK(true);
752 if (ev->getState() == FileTransferEvent::ACCEPTED)
754 icqsubtype.setPort(ev->getPort());
755 icqsubtype.setRevPort(ev->getPort());
756 icqsubtype.setSize(0);
757 icqsubtype.setMessage("");
759 // port numbers, etc..
761 else
763 icqsubtype.setStatus( AcceptStatus_Denied );
764 icqsubtype.setPort(0);
765 icqsubtype.setSize(0);
766 icqsubtype.setMessage( ev->getRefusalMessage() );
768 SendPacketAck(&icqsubtype);
769 while (m_msgcache.exists(ev->getSeqNum()))
771 m_msgcache.remove(ev->getSeqNum());
775 void DirectClient::SendFTCancel(FileTransferEvent *ev)
777 FTICQSubType fist;
778 fist.setAdvanced(true);
779 fist.setSeqNum(ev->getSeqNum());
781 fist.setPort(0);
782 fist.setSize(0);
783 fist.setMessage( "" );
785 Buffer b;
786 b.setLittleEndian();
787 b << (unsigned int)0x00000000 // checksum (filled in by Encrypt)
788 << V6_TCP_CANCEL
789 << (unsigned short)0x000e
790 << fist.getSeqNum()
791 << (unsigned int)0x00000000
792 << (unsigned int)0x00000000
793 << (unsigned int)0x00000000;
794 fist.Output(b);
796 Buffer c;
797 Encrypt(b,c);
798 Send(c);
800 m_msgcache.remove(ev->getSeqNum());
803 void DirectClient::SendEvent(MessageEvent *ev)
806 if (m_state == CONNECTED) {
807 // send straight away
808 SendPacketEvent(ev);
809 } else {
810 // queue message
811 m_msgqueue.push_back(ev);
816 void DirectClient::flush_queue() {
817 while (!m_msgqueue.empty()) {
818 SendPacketEvent( m_msgqueue.front() );
819 m_msgqueue.pop_front();
823 unsigned short DirectClient::NextSeqNum() {
824 return m_seqnum--;
827 unsigned int DirectClient::getUIN() const { return m_remote_uin; }
829 unsigned int DirectClient::getIP() const { return m_socket->getRemoteIP(); }
831 unsigned short DirectClient::getPort() const { return m_socket->getRemotePort(); }
833 int DirectClient::getfd() const { return m_socket->getSocketHandle(); }
835 TCPSocket* DirectClient::getSocket() const { return m_socket; }
837 void DirectClient::setContact(ContactRef c) { m_contact = c; }
839 ContactRef DirectClient::getContact() const { return m_contact; }