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

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 "tcppacket.h"
  13. #include "tcpsession.h"
  14. #include "icqsocket.h"
  15. #include "icqplugin.h"
  16. TcpSession::TcpSession(IcqLink *link, const char *name, uint32 uin)
  17. : IcqSession(link, name, uin)
  18. {
  19. listener = NULL;
  20. isSend = true;
  21. sock = -1;
  22. destIP = 0;
  23. destPort = 0;
  24. bufSize = 0;
  25. status = TCP_STATUS_NOT_CONN;
  26. IcqContact *c = link->findContact(uin);
  27. realIP = (c ? c->realIP : 0);
  28. }
  29. TcpSession::~TcpSession()
  30. {
  31. if (sock >= 0)
  32. IcqSocket::closeSocket(sock);
  33. }
  34. void TcpSession::shutdown()
  35. {
  36. ::shutdown(sock, 2);
  37. }
  38. void TcpSession::destroy()
  39. {
  40. if (name.empty())
  41. delete this;
  42. else
  43. icqLink->destroySession(name.c_str(), uin);
  44. }
  45. void TcpSession::createPlugin()
  46. {
  47. IcqPlugin *p = PluginFactory::getPlugin(name);
  48. if (p && p->type == ICQ_PLUGIN_NET)
  49. listener = ((NetPlugin *) p)->createSession(this);
  50. }
  51. bool TcpSession::connect(uint32 ip, uint16 port, bool isSend)
  52. {
  53. destIP = ip;
  54. destPort = port;
  55. this->isSend = isSend;
  56. sock = IcqSocket::createSocket(SOCK_STREAM, this);
  57. sockaddr_in addr;
  58. memset(&addr, 0, sizeof(addr));
  59. addr.sin_family = AF_INET;
  60. IcqOption &options = icqLink->options;
  61. if (icqLink->isProxyType(PROXY_SOCKS)) {
  62. if (realIP && icqLink->socksIP == ip)
  63. ip = realIP; // We are behind the same firewall.
  64. else {
  65. ip = icqLink->socksIP;
  66. port = icqLink->options.proxy[PROXY_SOCKS].port;
  67. }
  68. }
  69. addr.sin_addr.s_addr = htonl(ip);
  70. addr.sin_port = htons(port);
  71. if (::connect(sock, (sockaddr *) &addr, sizeof(addr)) == 0)
  72. onConnect(true);
  73. else if (IcqSocket::getSocketError() != EINPROGRESS)
  74. return false;
  75. return true;
  76. }
  77. void TcpSession::enableWrite()
  78. {
  79. IcqSocket::enableWrite(sock);
  80. }
  81. OutPacket *TcpSession::createPacket(uint16 cmd)
  82. {
  83. OutPacket *p = new TcpOutPacket;
  84. *p << (uint16) MYICQ_TCP_VER << (uint32) 0;
  85. *p << cmd << icqLink->myInfo.uin;
  86. return p;
  87. }
  88. bool TcpSession::sendPacket(OutPacket *out)
  89. {
  90. if (status == TCP_STATUS_ESTABLISHED) {
  91. int n = sendDirect(out);
  92. delete out;
  93. return (n > 0);
  94. }
  95. return false;
  96. }
  97. int TcpSession::sendDirect(OutPacket *out)
  98. {
  99. return ((TcpOutPacket *) out)->send(sock);
  100. }
  101. bool TcpSession::onTcpEstablished()
  102. {
  103. status = TCP_STATUS_ESTABLISHED;
  104. if (listener && listener->onTcpEstablished())
  105. return true;
  106. OutPacket *p = createPacket(TCP_HELLO);
  107. *p << (uint8) isSend;
  108. sendDirect(p);
  109. delete p;
  110. createPlugin();
  111. return true;
  112. }
  113. void TcpSession::onConnect(bool success)
  114. {
  115. if (!success)
  116. return;
  117. if (!icqLink->isProxyType(PROXY_SOCKS) || 
  118. (realIP && icqLink->socksIP == destIP)) {
  119. onTcpEstablished();
  120. return;
  121. }
  122. status = TCP_STATUS_SOCKS_METHOD;
  123. buf[0] = 5;
  124. buf[1] = 1;
  125. buf[2] = (icqLink->options.proxy[PROXY_SOCKS].username.empty() ? 0 : 2);
  126. send(sock, buf, 3, 0);
  127. }
  128. bool TcpSession::recvPacket()
  129. {
  130. if (listener && listener->onReceive())
  131. return true;
  132. int n;
  133. while ((n = recv(sock, buf + bufSize, TCP_PACKET_SIZE - bufSize, 0)) > 0) {
  134. bufSize += n;
  135. char *start = buf;
  136. char *end = start + bufSize;
  137. uint16 len;
  138. while (start + sizeof(len) < end) {
  139. len = ntohs(*(uint16 *) start);
  140. if (end - start - sizeof(len) < len)
  141. break;
  142. start += sizeof(len);
  143. if (len >= sizeof(TCP_HEADER)) {
  144. TcpInPacket in(start, len);
  145. onPacketReceived(in);
  146. }
  147. start += len;
  148. }
  149. bufSize = end - start;
  150. if (bufSize > 0)
  151. memcpy(buf, start, bufSize);
  152. }
  153. if (n == 0)
  154. onClose();
  155. return (n >= 0);
  156. }
  157. bool TcpSession::onReceive()
  158. {
  159. if (status == TCP_STATUS_ESTABLISHED || status == TCP_STATUS_HELLO_WAIT)
  160. return recvPacket();
  161. int n = recv(sock, buf, sizeof(buf), 0);
  162. switch (status) {
  163. case TCP_STATUS_SOCKS_METHOD:
  164. if (n != 2 || buf[0] != 5 || (buf[1] != 0 && buf[1] != 2))
  165. return false;
  166. if (buf[1] == 0)
  167. status = TCP_STATUS_SOCKS_CONNECT;
  168. else {
  169. status = TCP_STATUS_SOCKS_AUTH;
  170. ProxyInfo &socks = icqLink->options.proxy[PROXY_SOCKS];
  171. char *p = buf;
  172. *p++ = 1;
  173. *p++ = n = socks.username.length();
  174. memcpy(p, socks.username.c_str(), n);
  175. p += n;
  176. *p++ = n = socks.passwd.length();
  177. memcpy(p, socks.passwd.c_str(), n);
  178. p += n;
  179. send(sock, buf, p - buf, 0);
  180. }
  181. break;
  182. case TCP_STATUS_SOCKS_AUTH:
  183. if (n != 2 || buf[0] != 1 || buf[1] != 0)
  184. return false;
  185. status = TCP_STATUS_SOCKS_CONNECT;
  186. break;
  187. case TCP_STATUS_SOCKS_CONNECT:
  188. if (n != 10 || buf[0] != 5 || buf[1] != 0)
  189. return false;
  190. onTcpEstablished();
  191. break;
  192. default:
  193. return false;
  194. }
  195. if (status == TCP_STATUS_SOCKS_CONNECT) {
  196. buf[0] = 5;
  197. buf[1] = 1;
  198. buf[2] = 0;
  199. buf[3] = 1;
  200. *(uint32 *) &buf[4] = htonl(destIP);
  201. *(uint16 *) &buf[8] = htons(destPort);
  202. send(sock, buf, 10, 0);
  203. }
  204. return true;
  205. }
  206. void TcpSession::onSend()
  207. {
  208. if (status == TCP_STATUS_ESTABLISHED)
  209. listener->onSend();
  210. }
  211. void TcpSession::onClose()
  212. {
  213. listener->onClose();
  214. }
  215. bool TcpSession::onPacketReceived(TcpInPacket &in)
  216. {
  217. uint16 cmd = in.getCmd();
  218. if (cmd == TCP_HELLO) {
  219. if (status != TCP_STATUS_HELLO_WAIT)
  220. return false;
  221. status = TCP_STATUS_ESTABLISHED;
  222. uin = in.getUIN();
  223. uint8 b;
  224. in >> b;
  225. isSend = !b;
  226. if (!listener)
  227. createPlugin();
  228. } else if (status == TCP_STATUS_HELLO_WAIT || uin != in.getUIN())
  229. return false;
  230. return listener->onPacketReceived(in);
  231. }