1 /** 2 * libICQ2000 Client header 3 * 4 * Copyright (C) 2001 Barnaby Gray <barnaby@beedesign.co.uk> 5 * 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. 10 * 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. 15 * 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 19 * 20 */ 21 22 #ifndef CLIENT_H 23 #define CLIENT_H 24 25 #include <iostream> 26 #include <string> 27 28 #include <map> 29 #include <queue> 30 31 #include <libicq2000/sigslot.h> 32 33 #include <time.h> 34 35 #include <libicq2000/events.h> 36 #include <libicq2000/constants.h> 37 #include <libicq2000/Contact.h> 38 #include <libicq2000/ContactTree.h> 39 #include <libicq2000/ContactList.h> 40 #include <libicq2000/userinfoconstants.h> 41 42 namespace ICQ2000 43 { 44 45 /* predeclare classes */ 46 class MessageSNAC; 47 class MessageACKSNAC; 48 class MessageOfflineUserSNAC; 49 class MessageTypingNotificationSNAC; 50 class SrvResponseSNAC; 51 class UINResponseSNAC; 52 class RateInfoChangeSNAC; 53 class BuddyOnlineSNAC; 54 class BuddyOfflineSNAC; 55 class UserInfoSNAC; 56 class OutSNAC; 57 class DirectClient; 58 class DCCache; 59 class MessageHandler; 60 class RequestIDCache; 61 class RequestIDCacheValue; 62 class ICBMCookieCache; 63 class SMTPClient; 64 class SocketClient; 65 class Buffer; 66 class TCPSocket; 67 class TCPServer; 68 class Translator; 69 class FileTransferClient; 70 class FTCache; 71 class SBLListSNAC; 72 73 /** 74 * The main library object. This is the object the user interface 75 * instantiates for a connection, hooks up to signal on and has the 76 * methods to connect, disconnect and send events from. 77 */ 78 class Client : public sigslot::has_slots<> 79 { 80 private: 81 enum State { NOT_CONNECTED, 82 AUTH_AWAITING_CONN_ACK, 83 AUTH_AWAITING_AUTH_REPLY, 84 BOS_AWAITING_CONN_ACK, 85 BOS_AWAITING_LOGIN_REPLY, 86 BOS_LOGGED_IN, 87 UIN_AWAITING_CONN_ACK, 88 UIN_AWAITING_UIN_REPLY 89 } m_state; 90 91 enum Sbl_op { USER_ADD, 92 USER_REMOVE, 93 GROUP_ADD, 94 GROUP_REMOVE 95 }; 96 97 struct Sbl_edit { 98 Sbl_op operation; 99 Sbl_item item; 100 }; 101 102 unsigned short get_random_buddy_id(); 103 void processSblEdits(); 104 105 std::deque<Sbl_edit> m_sbl_edits; // edits on m_sbl_* 106 std::map<unsigned int, Sbl_item> m_sbl_map; // uin:info 107 std::map<std::string, Sbl_group> m_sbl_groups; // name:info 108 std::map<unsigned short, std::string> m_sbl_groupnames; // group_id::group_name 109 std::set<unsigned short> m_sbl_tags; // used tag ids 110 bool m_sbl_canedit; // local SBL is ready, I can do edits on it 111 unsigned short m_sbl_privacy_id; // privacy buddy ID 112 113 ContactRef m_self; 114 std::string m_password; 115 Status m_status_wanted; 116 bool m_invisible_wanted; 117 bool m_web_aware; 118 unsigned short m_random_group; 119 120 std::string m_authorizerHostname; 121 unsigned short m_authorizerPort; 122 123 std::string m_bosHostname; 124 unsigned short m_bosPort; 125 bool m_bosOverridePort; 126 127 std::string m_client_bind_host; 128 129 bool m_in_dc, m_out_dc; 130 131 unsigned short m_client_seq_num; 132 unsigned int m_requestid; 133 134 Translator * m_translator; 135 136 ContactTree m_contact_tree; 137 138 ContactList m_visible_list; 139 ContactList m_invisible_list; 140 141 bool m_fetch_sbl; 142 143 bool m_sbl_inedit; 144 std::deque<OutSNAC*> sblSNACs; 145 146 MessageHandler * m_message_handler; 147 148 unsigned char *m_cookie_data; 149 unsigned short m_cookie_length; 150 151 unsigned int m_ext_ip; 152 bool m_use_portrange; 153 bool m_use_typing_notif; 154 unsigned short m_upper_port, m_lower_port; 155 TCPSocket * m_serverSocket; 156 TCPServer * m_listenServer; 157 158 SMTPClient * m_smtp; 159 160 DCCache * m_dccache; 161 FTCache * m_ftcache; 162 163 time_t m_last_server_ping; 164 165 RequestIDCache * m_reqidcache; 166 ICBMCookieCache * m_cookiecache; 167 168 Buffer * m_recv; 169 170 void Init(); 171 unsigned short NextSeqNum(); 172 unsigned int NextRequestID(); 173 174 void ConnectAuthorizer(State state); 175 void DisconnectAuthorizer(); 176 void ConnectBOS(); 177 void DisconnectBOS(); 178 179 // -- Ping server -- 180 void PingServer(); 181 182 DirectClient* ConnectDirect(const ContactRef& c); 183 void DisconnectDirectConns(); 184 void DisconnectDirectConn(int fd); 185 186 // ------------------ Signal dispatchers ----------------- 187 void SignalConnect(); 188 void SignalDisconnect(DisconnectedEvent::Reason r); 189 void SignalMessage(MessageSNAC *snac); 190 void SignalMessageACK(MessageACKSNAC *snac); 191 void SignalMessageOfflineUser(MessageOfflineUserSNAC *snac); 192 void SignalTypingNotification(MessageTypingNotificationSNAC *snac); 193 void SignalSrvResponse(SrvResponseSNAC *snac); 194 void SignalUINResponse(UINResponseSNAC *snac); 195 void SignalUINRequestError(); 196 void SignalRateInfoChange(RateInfoChangeSNAC *snac); 197 void SignalLog(LogEvent::LogType type, const std::string& msg); 198 void SignalUserOnline(BuddyOnlineSNAC *snac); 199 void SignalUserOffline(BuddyOfflineSNAC *snac); 200 void SignalAddSocket(int fd, SocketEvent::Mode m); 201 void SignalRemoveSocket(int fd); 202 // ------------------ Outgoing packets ------------------- 203 204 // -------------- Callbacks from ContactList ------------- 205 void contactlist_cb(ContactListEvent *ev); 206 207 // ------- Callbacks from visible, invisible lists ------- 208 void visiblelist_cb(ContactListEvent *ev); 209 void invisiblelist_cb(ContactListEvent *ev); 210 211 // -------------- Callbacks from Contacts ---------------- 212 213 void SendAuthReq(); 214 void SendNewUINReq(); 215 void SendCookie(); 216 void SendCapabilities(); 217 void SendRateInfoRequest(); 218 void SendRateInfoAck(); 219 void SendPersonalInfoRequest(); 220 void SendAddICBMParameter(); 221 void SendSetUserInfo(); 222 void SendLogin(); 223 void SendRequestSBL(); 224 void SendSBLReceivedACK(); 225 void SendOfflineMessagesACK(); 226 227 void SendAdvancedACK(MessageSNAC *snac); 228 229 void Send(Buffer& b); 230 231 void HandleUserInfoSNAC(UserInfoSNAC *snac); 232 233 void FLAPwrapSNAC(Buffer& b, const OutSNAC& snac); 234 void FLAPwrapSNACandSend(const OutSNAC& snac); 235 236 // ------------------ Incoming packets ------------------- 237 238 /** 239 * non-blocking receives all waiting packets from server 240 * and parses and handles them 241 */ 242 void RecvFromServer(); 243 244 void Parse(); 245 void ParseCh1(Buffer& b, unsigned short seq_num); 246 void ParseCh2(Buffer& b, unsigned short seq_num); 247 void ParseCh3(Buffer& b, unsigned short seq_num); 248 void ParseCh4(Buffer& b, unsigned short seq_num); 249 250 // ------------------------------------------------------- 251 252 ContactRef getUserInfoCacheContact(unsigned int reqid); 253 254 void fillSBLMap(SBLListSNAC *sbl); 255 void mergeSBL(ContactTree& tree); 256 257 void SendSBLAuthReq(AuthReqEvent *ev); 258 void SendSBLAuthReply(AuthAckEvent *ev); 259 260 void ICBMCookieCache_expired_cb(MessageEvent *ev); 261 void dccache_expired_cb(DirectClient *dc); 262 void ftcache_expired_cb(FileTransferClient *ftc); 263 void reqidcache_expired_cb( RequestIDCacheValue *v ); 264 void dc_connected_cb(SocketClient *dc); 265 void dc_log_cb(LogEvent *ev); 266 void dc_socket_cb(SocketEvent *ev); 267 void dc_messageack_cb(MessageEvent *ev); 268 void ftc_messageack_cb(MessageEvent *ev); 269 270 bool SendDirect(MessageEvent *ev); 271 272 void SendViaServer(MessageEvent *ev); 273 void SendViaServerAdvanced(MessageEvent *ev); 274 void SendViaServerNormal(MessageEvent *ev); 275 276 void Disconnect(DisconnectedEvent::Reason r = DisconnectedEvent::REQUESTED); 277 278 public: 279 Client(); 280 Client(const unsigned int uin, const std::string& password); 281 ~Client(); 282 283 void setUIN(unsigned int uin); 284 unsigned int getUIN() const; 285 void setPassword(const std::string& password); 286 std::string getPassword() const; 287 288 ContactRef getSelfContact(); 289 290 bool setTranslationMap(const std::string& szMapFileName); 291 const std::string& getTranslationMapFileName() const; 292 const std::string& getTranslationMapName() const; 293 bool usingDefaultMap() const; 294 295 // -- Signals -- 296 /** 297 * The signal to connect to for listening to ConnectingEvent's. 298 * A ConnectingEvent is signalled when the client is trying to go online. 299 * @see connected, ConnectingEvent 300 */ 301 sigslot::signal1<ConnectingEvent*> connecting; 302 303 /** 304 * The signal to connect to for listening to ConnectedEvent's. 305 * A ConnectedEvent is signalled when the client is online proper. 306 * @see disconnected, ConnectedEvent 307 */ 308 sigslot::signal1<ConnectedEvent*> connected; 309 310 sigslot::signal1<SBLReceivedEvent*> sbl_received; 311 312 /** 313 * The signal to connect to for listening to DisconnectedEvent's. 314 * A DisconnectedEvent is signalled when you were disconnected 315 * from the server. This could have been because it was 316 * requested, or the server might have chucked you off. More 317 * information can be in the DisconnectedEvent. 318 * 319 * DisconnectedEvent's don't necessarily match a ConnectedEvent, 320 * if you try connecting with an incorrect password, you will 321 * never get a ConnectedEvent before the DisconnectedEvent 322 * signalling incorrect password. 323 * @see connected, DisconnectedEvent 324 */ 325 sigslot::signal1<DisconnectedEvent*> disconnected; 326 327 /** 328 * The signal to connect to for listening to incoming 329 * MessageEvent. This includes far more than just messages. 330 * @see MessageEvent 331 */ 332 sigslot::signal1<MessageEvent*> messaged; 333 334 /** 335 * The signal to connect to for listening to the acknowledgements 336 * that the library will generate for when the remote client 337 * sends back a message ack. Additionally it will it is used for 338 * signalling to the Client message delivery failures and when 339 * messages are being reattempted to be send through the server. 340 * @see messaged, MessageEvent 341 */ 342 sigslot::signal1<MessageEvent*> messageack; 343 344 /** 345 * The signal to connect to for listening to Contact list events. 346 * @see ContactListEvent 347 */ 348 sigslot::signal1<ContactListEvent*> contactlist; 349 350 /** 351 * The signal to connect to for listening for Contact Userinfo events. 352 * @see UserInfoChangeEvent 353 */ 354 sigslot::signal1<UserInfoChangeEvent*> contact_userinfo_change_signal; 355 356 /** 357 * The signal to connect to for listening for Contact Status change events. 358 * @see StatusChangeEvent 359 */ 360 sigslot::signal1<StatusChangeEvent*> contact_status_change_signal; 361 362 /** 363 * The signal to connect to for listening for Contact Typing Notification events. 364 * @see UserTypingNotificationEvent 365 */ 366 sigslot::signal1<UserTypingNotificationEvent*> contact_typing_signal; 367 368 /** 369 * The signal for when registering a new UIN has succeeded or 370 * failed after a call to RegisterUIN(). 371 * @see NewUINEvent, RegisterUIN 372 */ 373 sigslot::signal1<NewUINEvent*> newuin; 374 375 /** 376 * The signal for when the server signals the rate at which the client 377 * is sending has been changed. 378 * @see RateInfoChangeEvent 379 */ 380 sigslot::signal1<RateInfoChangeEvent*> rate; 381 382 /** 383 * The signal for all logging messages that are passed back to 384 * the client. This leads to a very flexible logging system, as 385 * the user interface may decide where to write the log message 386 * to (stdout, a dialog box, etc..) and also may pick which type 387 * of log messages to display and which to ignore. 388 * @see LogEvent 389 */ 390 sigslot::signal1<LogEvent*> logger; 391 392 /** 393 * The signal for socket events. All clients must listen to this 394 * and implement their particular scheme of blocking on multiple 395 * sockets for read/write/exception, usually the select system 396 * call in someway. Often toolkits will hide all the details of 397 * select inside them, such as the way gtk or gtkmm do. 398 * 399 * @see SocketEvent 400 */ 401 sigslot::signal1<SocketEvent*> socket; 402 403 /** 404 * The signal to connect to for listening for Self Contact Userinfo events. 405 * @see UserInfoChangeEvent 406 */ 407 sigslot::signal1<UserInfoChangeEvent*> self_contact_userinfo_change_signal; 408 409 /** 410 * The signal to connect to for listening for Self Contact Status change events. 411 * @see StatusChangeEvent 412 */ 413 sigslot::signal1<StatusChangeEvent*> self_contact_status_change_signal; 414 415 /** 416 * Signal when someone requests your away message. The client 417 * should setMessage in the AutoMessageEvent to what your away 418 * message is. This allows dynamic away messages for different 419 * people. 420 */ 421 sigslot::signal1<ICQMessageEvent*> want_auto_resp; 422 423 /** 424 * Signal when a Search Result has been updated. The last signal 425 * on a search result will be with 426 * SearchResultEvent::isFinished() set to true. After this the 427 * event is finished and deleted from memory by the library. 428 */ 429 sigslot::signal1<SearchResultEvent*> search_result; 430 431 /** 432 * Signal when an incoming file transfer request is received. 433 */ 434 sigslot::signal1<FileTransferEvent*> filetransfer_incoming_signal; 435 436 /** 437 * Signal when a FileTransferEvent object is updated. 438 */ 439 sigslot::signal1<FileTransferEvent*> filetransfer_update_signal; 440 441 // ------------- 442 443 // -- Send calls -- 444 void SendEvent(MessageEvent *ev); 445 446 // -- File Transfer methods -- 447 void SendFileTransfer(FileTransferEvent *ev); 448 void SendFileTransferACK(FileTransferEvent *ev); 449 void CancelFileTransfer(FileTransferEvent *ev); 450 451 // -- Set Status -- 452 void setStatus(const Status st); 453 void setStatus(const Status st, bool inv); 454 void setInvisible(bool inv); 455 void setWebAware(bool wa); 456 void setRandomChatGroup(unsigned short group); 457 458 Status getStatus() const; 459 bool getInvisible() const; 460 461 Status getStatusWanted() const; 462 bool getInvisibleWanted() const; 463 464 bool getWebAware() const; 465 466 void uploadSelfDetails(); 467 468 void uploadServerBasedContact(const ContactRef& c); 469 void uploadServerBasedGroup(const ContactTree::Group& gp); 470 void uploadServerBasedContactList(); 471 472 void updateServerBasedContact(const ContactRef& c); 473 474 void removeServerBasedContact(const ContactRef& c); 475 void removeServerBasedGroup(const ContactTree::Group& gp); 476 void removeServerBasedContactList(); 477 478 // -- Contact List -- 479 void addVisible(ContactRef c); 480 void removeVisible(const unsigned int uin); 481 void addInvisible(ContactRef c); 482 void removeInvisible(const unsigned int uin); 483 ContactRef getContact(const unsigned int uin); 484 485 ContactTree& getContactTree(); 486 487 void fetchSimpleContactInfo(ContactRef c); 488 void fetchDetailContactInfo(ContactRef c); 489 void fetchServerBasedContactList(); 490 void fetchServerBasedContactList(int); // the conditional form - TODO! 491 void fetchSelfSimpleContactInfo(); 492 void fetchSelfDetailContactInfo(); 493 494 void SendSBLSNAC(OutSNAC *sn); // send SBL SNAC 495 void upgradeToSBL(); // save local contact to SBL 496 497 // -- Whitepage searches -- 498 SearchResultEvent* searchForContacts(const std::string& nickname, const std::string& firstname, 499 const std::string& lastname); 500 501 SearchResultEvent* searchForContacts(const std::string& nickname, const std::string& firstname, 502 const std::string& lastname, const std::string& email, 503 AgeRange age, Sex sex, unsigned char language, const std::string& city, 504 const std::string& state, unsigned short country, 505 const std::string& company_name, const std::string& department, 506 const std::string& position, bool only_online); 507 508 SearchResultEvent* searchForContacts(unsigned int uin); 509 510 SearchResultEvent* searchForContacts(const std::string& keyword); 511 512 SearchResultEvent* searchForContacts(RandomChatGroup group); 513 514 /* 515 * Poll must be called regularly (at least every 60 seconds) 516 * but I recommended 5 seconds, so timeouts work with good 517 * granularity. 518 * It is not related to the socket callback - the client using 519 * this library must select() on the sockets it gets signalled 520 * and call socket_cb when select returns a status flag on one 521 * of the sockets. ickle simply uses the gtk-- built in signal handlers 522 * to do all this. 523 */ 524 525 // -- Network settings -- 526 void setLoginServerHost(const std::string& host); 527 std::string getLoginServerHost() const; 528 529 void setLoginServerPort(const unsigned short& port); 530 unsigned short getLoginServerPort() const; 531 532 void setBOSServerOverridePort(const bool& b); 533 bool getBOSServerOverridePort() const; 534 535 void setBOSServerPort(const unsigned short& port); 536 unsigned short getBOSServerPort() const; 537 538 void setSMTPServerHost(const std::string& host); 539 std::string getSMTPServerHost() const; 540 541 void setSMTPServerPort(unsigned short port); 542 unsigned short getSMTPServerPort() const; 543 544 void setAcceptInDC(bool d); 545 bool getAcceptInDC() const; 546 547 void setUseOutDC(bool d); 548 bool getUseOutDC() const; 549 550 void setPortRangeLowerBound(unsigned short lower); 551 void setPortRangeUpperBound(unsigned short upper); 552 unsigned short getPortRangeLowerBound() const; 553 unsigned short getPortRangeUpperBound() const; 554 555 void setUsePortRange(bool b); 556 bool getUsePortRange() const; 557 558 void setClientBindHost(const std::string& host); 559 std::string getClientBindHost() const; 560 561 void setTypingNotifications(bool b); 562 563 void Poll(); 564 void socket_cb(int fd, SocketEvent::Mode m); 565 566 void RegisterUIN(); 567 568 /* isConnected() is a convenience for the 569 * client, it should correspond exactly to ConnectedEvents 570 * & DisconnectedEvents the client gets 571 */ 572 bool isConnected() const; 573 574 void set_translator(Translator * t); 575 }; 576 } 577 578 #endif 579