VSocket.cpp
上传用户:sbftbdw
上传日期:2007-01-03
资源大小:379k
文件大小:8k
源码类别:

远程控制编程

开发平台:

Visual C++

  1. //  Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory
  2. //
  3. //  This file is part of the VNC system.
  4. //
  5. //  The VNC system is free software; you can redistribute it and/or modify
  6. //  it under the terms of the GNU General Public License as published by
  7. //  the Free Software Foundation; either version 2 of the License, or
  8. //  (at your option) any later version.
  9. //
  10. //  This program is distributed in the hope that it will be useful,
  11. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //  GNU General Public License for more details.
  14. //
  15. //  You should have received a copy of the GNU General Public License
  16. //  along with this program; if not, write to the Free Software
  17. //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
  18. //  USA.
  19. //
  20. // If the source code for the VNC system is not available from the place 
  21. // whence you received this file, check http://www.orl.co.uk/vnc or contact
  22. // the authors on vnc@orl.co.uk for information on obtaining it.
  23. // VSocket.cpp
  24. // The VSocket class provides a platform-independent socket abstraction
  25. // with the simple functionality required for an RFB server.
  26. class VSocket;
  27. ////////////////////////////////////////////////////////
  28. // System includes
  29. #include "stdhdrs.h"
  30. #include <iostream.h>
  31. #include <stdio.h>
  32. #ifdef __WIN32__
  33. #include <io.h>
  34. #include <winsock.h>
  35. #else
  36. #include <sys/types.h>
  37. #include <sys/socket.h>
  38. #include <arpa/inet.h>
  39. #include <netinet/in.h>
  40. #include <netdb.h>
  41. #include <unistd.h>
  42. #include <errno.h>
  43. #include <string.h>
  44. #include <signal.h>
  45. #endif
  46. #include <sys/types.h>
  47. ////////////////////////////////////////////////////////
  48. // Custom includes
  49. #include "VTypes.h"
  50. ////////////////////////////////////////////////////////
  51. // *** Lovely hacks to make Win32 work.  Hurrah!
  52. #ifdef __WIN32__
  53. #define EWOULDBLOCK WSAEWOULDBLOCK
  54. #endif
  55. ////////////////////////////////////////////////////////
  56. // Socket implementation
  57. #include "VSocket.h"
  58. // The socket timeout value (currently 5 seconds, for no reason...)
  59. // *** THIS IS NOT CURRENTLY USED ANYWHERE
  60. const VInt rfbMaxClientWait = 5000;
  61. ////////////////////////////
  62. // Socket implementation initialisation
  63. VSocketSystem::VSocketSystem()
  64. {
  65.   // Initialise the socket subsystem
  66.   // This is only provided for compatibility with Windows.
  67. #ifdef __WIN32__
  68.   // Initialise WinPoxySockets on Win32
  69.   WORD wVersionRequested;
  70.   WSADATA wsaData;
  71.   wVersionRequested = MAKEWORD(2, 0);
  72.   if (WSAStartup(wVersionRequested, &wsaData) != 0)
  73.   {
  74.     m_status = VFalse;
  75. return;
  76.   }
  77. #else
  78.   // Disable the nasty read/write failure signals on UNIX
  79.   signal(SIGPIPE, SIG_IGN);
  80. #endif
  81.   // If successful, or if not required, then continue!
  82.   m_status = VTrue;
  83. }
  84. VSocketSystem::~VSocketSystem()
  85. {
  86. if (m_status)
  87. {
  88. WSACleanup();
  89. }
  90. }
  91. ////////////////////////////
  92. VSocket::VSocket()
  93. {
  94.   // Clear out the internal socket fields
  95.   sock = -1;
  96. }
  97. ////////////////////////////
  98. VSocket::~VSocket()
  99. {
  100.   // Close the socket
  101.   Close();
  102. }
  103. ////////////////////////////
  104. VBool
  105. VSocket::Create()
  106. {
  107.   const int one = 1;
  108.   // Check that the old socket was closed
  109.   if (sock >= 0)
  110.     Close();
  111.   // Create the socket
  112.   if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  113.     {
  114.       return VFalse;
  115.     }
  116.   // Set the socket options:
  117.   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)))
  118.     {
  119.       return VFalse;
  120.     }
  121.   return VTrue;
  122. }
  123. ////////////////////////////
  124. VBool
  125. VSocket::Close()
  126. {
  127.   if (sock >= 0)
  128.     {
  129.   log.Print(LL_SOCKINFO, VNCLOG("closing socketn"));
  130.   shutdown(sock, SD_BOTH);
  131. #ifdef __WIN32__
  132.   closesocket(sock);
  133. #else
  134.   close(sock);
  135. #endif
  136.       sock = -1;
  137.     }
  138.   return VTrue;
  139. }
  140. ////////////////////////////
  141. VBool
  142. VSocket::Shutdown()
  143. {
  144.   if (sock >= 0)
  145.     {
  146.   log.Print(LL_SOCKINFO, VNCLOG("shutdown socketn"));
  147.   shutdown(sock, SD_BOTH);
  148.     }
  149.   return VTrue;
  150. }
  151. ////////////////////////////
  152. VBool
  153. VSocket::Bind(const VCard port)
  154. {
  155.   struct sockaddr_in addr;
  156.   // Check that the socket is open!
  157.   if (sock < 0)
  158.     return VFalse;
  159.   // If a specific port is being set then check it's not already used!
  160.   if (port != 0)
  161.   {
  162. VSocket dummy;
  163. if (dummy.Create())
  164. {
  165. // If we're able to connect then the port number is in use...
  166. if (dummy.Connect("localhost", port))
  167. return VFalse;
  168. }
  169.   }
  170.   // Set up the address to bind the socket to
  171.   addr.sin_family = AF_INET;
  172.   addr.sin_port = htons(port);
  173.   addr.sin_addr.s_addr = INADDR_ANY;
  174.   if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
  175.       return VFalse;
  176.   return VTrue;
  177. }
  178. ////////////////////////////
  179. VBool
  180. VSocket::Connect(const VString address, const VCard port)
  181. {
  182.   // Check the socket
  183.   if (sock < 0)
  184.     return VFalse;
  185.   // Create an address structure and clear it
  186.   struct sockaddr_in addr;
  187.   memset(&addr, 0, sizeof(addr));
  188.   // Fill in the address if possible
  189.   addr.sin_family = AF_INET;
  190.   addr.sin_addr.s_addr = inet_addr(address);
  191.   // Was the string a valid IP address?
  192.   if (addr.sin_addr.s_addr == -1)
  193.     {
  194.       // No, so get the actual IP address of the host name specified
  195.       struct hostent *pHost;
  196.       pHost = gethostbyname(address);
  197.       if (pHost != NULL)
  198.   {
  199.   if (pHost->h_addr == NULL)
  200.   return VFalse;
  201.   addr.sin_addr.s_addr = ((struct in_addr *)pHost->h_addr)->s_addr;
  202.   }
  203.   else
  204.     return VFalse;
  205.     }
  206.   // Set the port number in the correct format
  207.   addr.sin_port = htons(port);
  208.   // Actually connect the socket
  209.   if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0)
  210.     return VTrue;
  211.   return VFalse;
  212. }
  213. ////////////////////////////
  214. VBool
  215. VSocket::Listen()
  216. {
  217.   // Check socket
  218.   if (sock < 0)
  219.     return VFalse;
  220. // Set it to listen
  221.   if (listen(sock, 5) < 0)
  222.     return VFalse;
  223.   return VTrue;
  224. }
  225. ////////////////////////////
  226. VSocket *
  227. VSocket::Accept()
  228. {
  229.   int new_socket_id;
  230.   VSocket * new_socket;
  231.   // Check this socket
  232.   if (sock < 0)
  233.     return NULL;
  234.   // Accept an incoming connection
  235.   if ((new_socket_id = accept(sock, NULL, 0)) < 0)
  236.     return NULL;
  237.   // Create a new VSocket and return it
  238.   new_socket = new VSocket;
  239.   if (new_socket != NULL)
  240.     {
  241.       new_socket->sock = new_socket_id;
  242.     }
  243.   else
  244.     {
  245. shutdown(new_socket_id, SD_BOTH);
  246. closesocket(new_socket_id);
  247.     }
  248.   return new_socket;
  249. }
  250. ////////////////////////////
  251. VString
  252. VSocket::GetPeerName()
  253. {
  254. struct sockaddr_in sockinfo;
  255. struct in_addr address;
  256. int sockinfosize = sizeof(sockinfo);
  257. VString name;
  258. // Get the peer address for the client socket
  259. getpeername(sock, (struct sockaddr *)&sockinfo, &sockinfosize);
  260. memcpy(&address, &sockinfo.sin_addr, sizeof(address));
  261. name = inet_ntoa(address);
  262. if (name == NULL)
  263. return "<unavailable>";
  264. else
  265. return name;
  266. }
  267. ////////////////////////////
  268. VString
  269. VSocket::GetSockName()
  270. {
  271. struct sockaddr_in sockinfo;
  272. struct in_addr address;
  273. int sockinfosize = sizeof(sockinfo);
  274. VString name;
  275. // Get the peer address for the client socket
  276. getsockname(sock, (struct sockaddr *)&sockinfo, &sockinfosize);
  277. memcpy(&address, &sockinfo.sin_addr, sizeof(address));
  278. name = inet_ntoa(address);
  279. if (name == NULL)
  280. return "<unavailable>";
  281. else
  282. return name;
  283. }
  284. ////////////////////////////
  285. VInt
  286. VSocket::Send(const char *buff, const VCard bufflen)
  287. {
  288.   return send(sock, buff, bufflen, 0);
  289. }
  290. ////////////////////////////
  291. VBool
  292. VSocket::SendExact(const char *buff, const VCard bufflen)
  293. {
  294.   return Send(buff, bufflen) == (VInt)bufflen;
  295. }
  296. ////////////////////////////
  297. VInt
  298. VSocket::Read(char *buff, const VCard bufflen)
  299. {
  300.   return recv(sock, buff, bufflen, 0);
  301. }
  302. ////////////////////////////
  303. VBool
  304. VSocket::ReadExact(char *buff, const VCard bufflen)
  305. {
  306. int n;
  307. VCard currlen = bufflen;
  308.     
  309. while (currlen > 0)
  310. {
  311. // Try to read some data in
  312. n = Read(buff, currlen);
  313. if (n > 0)
  314. {
  315. // Adjust the buffer position and size
  316. buff += n;
  317. currlen -= n;
  318. } else if (n == 0) {
  319. log.Print(LL_SOCKERR, VNCLOG("zero bytes readn"));
  320. return VFalse;
  321. } else {
  322. if (errno != EWOULDBLOCK)
  323. {
  324. log.Print(LL_SOCKERR, VNCLOG("socket error %dn"), errno);
  325. return VFalse;
  326. }
  327. }
  328.     }
  329. return VTrue;
  330. }