icqlink.cpp
上传用户:zslianheng
上传日期:2013-04-03
资源大小:946k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Visual C++

  1. /***************************************************************************
  2.  *                                                                         *
  3.  *   This program is free software; you can redistribute it and/or modify  *
  4.  *   it under the terms of the GNU General Public License as published by  *
  5.  *   the Free Software Foundation; either version 2 of the License, or     *
  6.  *   (at your option) any later version.                                   *
  7.  *                                                                         *
  8.  *   copyright            : (C) 2002 by Zhang Yong                         *
  9.  *   email                : z-yong163@163.com                              *
  10.  ***************************************************************************/
  11. #include "icqlink.h"
  12. #include "icqwindow.h"
  13. #include "icqsocket.h"
  14. #include "serversession.h"
  15. #include "msgsession.h"
  16. #include "tcpsession.h"
  17. #include "icqdb.h"
  18. #include "icqplugin.h"
  19. #include "ndes.h"
  20. #include <time.h>
  21. IcqLink *icqLink;
  22. static bool isUdpSession(IcqSession *s)
  23. {
  24. return (s->name.compare(ICQ_SESSION_SERVER) == 0 ||
  25. s->name.compare(ICQ_SESSION_MSG) == 0);
  26. }
  27. IcqLink::IcqLink()
  28. {
  29. icqLink = this;
  30. srand(time(NULL));
  31. desinit(0);
  32. PluginFactory::init();
  33. socksIP = 0;
  34. createSession(ICQ_SESSION_SERVER, 0);
  35. }
  36. IcqLink::~IcqLink()
  37. {
  38. desdone();
  39. destroyUser();
  40. delete serverSession();
  41. IcqSocket::destroy();
  42. PluginFactory::destroy();
  43. }
  44. ContactInfo *IcqLink::getContactInfo(uint32 uin)
  45. {
  46. if (uin)
  47. return findContact(uin);
  48. return &myInfo;
  49. }
  50. TcpSessionBase *IcqLink::createTcpSession(TcpSessionListener *l, uint32 ip, uint16 port)
  51. {
  52. // Anonymous tcp session
  53. TcpSession *s = new TcpSession(this, "", 0);
  54. s->setListener(l);
  55. s->connect(ip, port, TRUE);
  56. return s;
  57. }
  58. void IcqLink::checkSendQueue()
  59. {
  60. PtrList::iterator it;
  61. for (it = sessionList.begin(); it != sessionList.end(); ++it) {
  62. if (isUdpSession((IcqSession *) *it))
  63. ((UdpSession *) *it)->checkSendQueue();
  64. }
  65. }
  66. void IcqLink::logout()
  67. {
  68. if (myInfo.status != STATUS_OFFLINE) {
  69. serverSession()->logout();
  70. myInfo.status = STATUS_OFFLINE;
  71. }
  72. destroySession();
  73. PtrList::iterator it;
  74. for (it = contactList.begin(); it != contactList.end(); ++it) {
  75. IcqContact *c = (IcqContact *) *it;
  76. c->status = STATUS_OFFLINE;
  77. c->ip = 0;
  78. c->port = 0;
  79. }
  80. }
  81. void IcqLink::destroyUser()
  82. {
  83. logout();
  84. while (!windowList.empty())
  85. delete (IcqWindow *) windowList.front();
  86. PtrList::iterator it;
  87. for (it = contactList.begin(); it != contactList.end(); ++it)
  88. delete (IcqContact *) *it;
  89. contactList.clear();
  90. for (it = msgList.begin(); it != msgList.end(); ++it)
  91. delete (IcqMsg *) *it;
  92. msgList.clear();
  93. myInfo.status = STATUS_OFFLINE;
  94. }
  95. void IcqLink::destroySession(uint32 uin)
  96. {
  97. PtrList::iterator it, next;
  98. for (it = sessionList.begin(); it != sessionList.end(); it = next) {
  99. next = it;
  100. ++next;
  101. IcqSession *session = (IcqSession *) *it;
  102. if (session->uin == uin) {
  103. delete session;
  104. sessionList.erase(it);
  105. }
  106. }
  107. }
  108. void IcqLink::destroySession()
  109. {
  110. int n = sessionList.size();
  111. while (n-- > 1) {
  112. delete (IcqSession *) sessionList.back();
  113. sessionList.pop_back();
  114. }
  115. }
  116. void IcqLink::destroyContact(uint32 uin)
  117. {
  118. destroySession(uin);
  119. PtrList l;
  120. while (!windowList.empty()) {
  121. IcqWindow *win = (IcqWindow *) windowList.front();
  122. windowList.pop_front();
  123. if (win->uin == uin)
  124. delete win;
  125. else
  126. l.push_back(win);
  127. }
  128. windowList = l;
  129. }
  130. void IcqLink::destroySession(const char *name, uint32 uin)
  131. {
  132. PtrList::iterator it;
  133. for (it = sessionList.begin(); it != sessionList.end(); ++it) {
  134. IcqSession *s = (IcqSession *) *it;
  135. if (s->uin == uin && s->name.compare(name) == 0) {
  136. delete s;
  137. sessionList.erase(it);
  138. break;
  139. }
  140. }
  141. }
  142. void IcqLink::onUserOffline(uint32 uin)
  143. {
  144. IcqContact *c = findContact(uin, CONTACT_FRIEND);
  145. if (c) {
  146. c->ip = 0;
  147. c->port = 0;
  148. c->status = STATUS_OFFLINE;
  149. }
  150. destroySession(uin);
  151. }
  152. IcqSession *IcqLink::createSession(const char *name, uint32 uin)
  153. {
  154. IcqSession *s = NULL;
  155. if (strcmp(name, ICQ_SESSION_SERVER) == 0)
  156. s = new ServerSession(this);
  157. else if (strcmp(name, ICQ_SESSION_MSG) == 0)
  158. s = new MsgSession(this, uin);
  159. else
  160. s = new TcpSession(this, name, uin);
  161. if (s)
  162. sessionList.push_back(s);
  163. return s;
  164. }
  165. TcpSession *IcqLink::acceptSession(int listenSock, const char *name)
  166. {
  167. TcpSession *s = (TcpSession *) createSession(name, 0);
  168. s->status = TCP_STATUS_HELLO_WAIT;
  169. s->sock = IcqSocket::acceptSocket(listenSock, s);
  170. return s;
  171. }
  172. uint16 IcqLink::createListenSession(const char *name)
  173. {
  174. TcpSession *s = (TcpSession *) findSession(name, 0);
  175. if (!s) {
  176. s = (TcpSession *) createSession(name, 0);
  177. s->sock = IcqSocket::createListenSocket(name);
  178. }
  179. sockaddr_in addr;
  180. socklen_t addrLen = sizeof(addr);
  181. if (getsockname(s->sock, (sockaddr *) &addr, &addrLen) < 0)
  182. return 0;
  183. return ntohs(addr.sin_port);
  184. }
  185. uint32 IcqLink::sendMessage(uint8 type, uint32 to, const char *text)
  186. {
  187. MsgSession *s = (MsgSession *) findSession(ICQ_SESSION_MSG, to);
  188. if (!s) {
  189. IcqContact *c = findContact(to);
  190. if (c) {
  191. if (c->ip == 0 || c->port == 0)
  192. return serverSession()->sendMessage(type, to, text);
  193. s = (MsgSession *) createSession(ICQ_SESSION_MSG, to);
  194. s->connect(c->ip, c->port);
  195. }
  196. }
  197. if (s)
  198. return s->sendMessage(type, text);
  199. return 0;
  200. }
  201. uint32 IcqLink::sendTcpRequest(const char *name, IcqContact *c, const char *text)
  202. {
  203. uint16 port = 0;
  204. if (c->realIP && c->ip != socksIP)
  205. port = createListenSession(name);
  206. TextOutStream out;
  207. out << name << text << port;
  208. return sendMessage(MSG_TCP_REQUEST, c->uin, out);
  209. }
  210. void IcqLink::acceptTcpRequest(const char *name, IcqContact *c, uint16 port)
  211. {
  212. IcqPlugin *p = PluginFactory::getPlugin(name);
  213. if (!p)
  214. return;
  215. if (p->type == ICQ_PLUGIN_NET) {
  216. if (port) {
  217. TcpSession *s = (TcpSession *) createSession(name, c->uin);
  218. s->connect(c->ip, port, false);
  219. port = 0;
  220. } else
  221. port = createListenSession(name);
  222. } else if (p->type == ICQ_PLUGIN_EXE) {
  223. ((ExePlugin *) p)->execServer(c);
  224. } else
  225. return;
  226. TextOutStream out;
  227. out << name << port;
  228. sendMessage(MSG_TCP_ACCEPTED, c->uin, out);
  229. }
  230. IcqContact *IcqLink::findContact(uint32 uin, int type)
  231. {
  232. PtrList::iterator it;
  233. for (it = contactList.begin(); it != contactList.end(); ++it) {
  234. IcqContact *c = (IcqContact *) *it;
  235. if (c->uin == uin && (type == -1 || c->type == type))
  236. return c;
  237. }
  238. return NULL;
  239. }
  240. IcqWindow *IcqLink::findWindow(int type, uint32 uin, uint32 seq)
  241. {
  242. PtrList::iterator it;
  243. for (it = windowList.begin(); it != windowList.end(); ++it) {
  244. IcqWindow *win = (IcqWindow *) *it;
  245. if (win->type == type &&
  246. (uin == 0 || win->uin == uin) &&
  247. (seq == 0 || win->seq == seq))
  248. return win;
  249. }
  250. return NULL;
  251. }
  252. IcqWindow *IcqLink::findWindowSeq(uint32 seq)
  253. {
  254. PtrList::iterator it;
  255. for (it = windowList.begin(); it != windowList.end(); ++it) {
  256. IcqWindow *win = (IcqWindow *) *it;
  257. if (win->isSeq(seq))
  258. return win;
  259. }
  260. return NULL;
  261. }
  262. IcqSession *IcqLink::findSession(const char *name, uint32 uin)
  263. {
  264. PtrList::iterator it;
  265. for (it = sessionList.begin(); it != sessionList.end(); ++it) {
  266. IcqSession *session = (IcqSession *) *it;
  267. if ((!uin || session->uin == uin) && session->name.compare(name) == 0)
  268. return session;
  269. }
  270. return NULL;
  271. }
  272. IcqMsg *IcqLink::findPendingMsg(uint32 uin)
  273. {
  274. if (msgList.empty())
  275. return NULL;
  276. IcqMsg *msg;
  277. if (uin) {
  278. PtrList::iterator i;
  279. for (i = msgList.begin(); i != msgList.end(); i++) {
  280. msg = (IcqMsg *) *i;
  281. if (!msg->isSysMsg() && msg->uin == uin)
  282. return msg;
  283. }
  284. } else {
  285. msg = (IcqMsg *) msgList.front();
  286. if (msg->isSysMsg())
  287. return msg;
  288. }
  289. return NULL;
  290. }
  291. void IcqLink::addPendingMsg(IcqMsg *msg)
  292. {
  293. if (!msg->isSysMsg())
  294. msgList.push_back(msg);
  295. else {
  296.     PtrList::iterator i;
  297.     for (i = msgList.begin(); i != msgList.end(); i++) {
  298. IcqMsg *p = (IcqMsg *) *i;
  299. if (!p->isSysMsg())
  300. break;
  301. }
  302. msgList.insert(i, msg);
  303. }
  304. }
  305. void IcqLink::onAck(uint32 seq)
  306. {
  307. IcqWindow *win = findWindowSeq(seq);
  308. if (win)
  309. win->onAck(seq);
  310. }
  311. void IcqLink::onSendError(uint32 seq)
  312. {
  313. IcqWindow *win = findWindowSeq(seq);
  314. if (win)
  315. win->onSendError(seq);
  316. }
  317. void IcqLink::onUpdateContactReply(IcqContact *info)
  318. {
  319. IcqContact *c = findContact(info->uin);
  320. if (c) {
  321. c->face = info->face;
  322. c->nick = info->nick;
  323. c->age = info->age;
  324. c->gender = info->gender;
  325. c->country = info->country;
  326. c->province = info->province;
  327. c->city = info->city;
  328. c->email = info->email;
  329. c->address = info->address;
  330. c->zipcode = info->zipcode;
  331. c->tel = info->tel;
  332. c->name = info->name;
  333. c->blood = info->blood;
  334. c->college = info->college;
  335. c->profession = info->profession;
  336. c->homepage = info->homepage;
  337. c->intro = info->intro;
  338. }
  339. }
  340. void IcqLink::onRecvMessage(uint8 type, uint32 from, uint32 when, const char *text, bool relay)
  341. {
  342. IcqContact *c = findContact(from);
  343. if (c) {
  344. if (c->type == CONTACT_IGNORE || c->flags.test(CF_OPTION_IGNORE))
  345. return;
  346. if (type == MSG_TCP_ACCEPTED) {
  347. TextInStream in(text);
  348. string name;
  349. uint16 port;
  350. in >> name >> port;
  351. IcqPlugin *p = PluginFactory::getPlugin(name);
  352. if (p) {
  353. if (p->type == ICQ_PLUGIN_NET) {
  354. if (port) {
  355. TcpSession *s = (TcpSession *) createSession(name.c_str(), from);
  356. s->connect(c->ip, port, true);
  357. }
  358. } else if (p->type == ICQ_PLUGIN_EXE)
  359. ((ExePlugin *) p)->execClient(c);
  360. }
  361. return;
  362. }
  363. }
  364. IcqMsg *msg = new IcqMsg;
  365. msg->type = type;
  366. msg->flags = MF_RECEIVED;
  367. if (relay)
  368. msg->flags |= MF_RELAY;
  369. msg->uin = from;
  370. msg->when = when;
  371. msg->text = text;
  372. onRecvMessage(msg);
  373. }