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

远程控制编程

开发平台:

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. // vncHTTPConnect.cpp
  24. // Implementation of the HTTP server class
  25. #include "stdhdrs.h"
  26. #include "VSocket.h"
  27. #include "vncHTTPConnect.h"
  28. #include "vncServer.h"
  29. #include <omnithread.h>
  30. #include "resource.h"
  31. // HTTP messages/message formats
  32. const char HTTP_MSG_OK [] ="HTTP/1.0 200 OKnn";
  33. const char HTTP_FMT_INDEX[] ="<HTML><TITLE>VNC desktop</TITLE>n"
  34. "<APPLET CODE=vncviewer.class ARCHIVE=vncviewer.jar WIDTH=%d HEIGHT=%d>n"
  35. "<param name=PORT value=%d></APPLET></HTML>n";
  36. const char HTTP_MSG_NOSOCKCONN [] ="<HTML><TITLE>VNC desktop</TITLE>n"
  37. "<BODY>The requested desktop is not configured to accept incoming connections.</BODY>n"
  38. "</HTML>n";
  39. const char HTTP_MSG_NOSUCHFILE [] ="HTTP/1.0 404 Not foundnn"
  40.     "<HEAD><TITLE>File Not Found</TITLE></HEAD>n"
  41.     "<BODY><H1>The requested file could not be found</H1></BODY>n";
  42. // Filename to resource ID mappings for the Java class files:
  43. typedef struct _FileToResourceMap {
  44. char *filename;
  45. char *type;
  46. int resourceID;
  47. } FileMap;
  48. const FileMap filemapping [] ={
  49. {"/vncviewer.jar", "JavaArchive", IDR_VNCVIEWER_JAR},
  50. {"/authenticationPanel.class", "JavaClass", IDR_AUTHPANEL_CLASS},
  51. {"/clipboardFrame.class", "JavaClass", IDR_CLIPBOARDFRAME_CLASS},
  52. {"/DesCipher.class", "JavaClass", IDR_DESCIPHER_CLASS},
  53. {"/optionsFrame.class", "JavaClass", IDR_OPTIONSFRAME_CLASS},
  54. {"/rfbProto.class", "JavaClass", IDR_RFBPROTO_CLASS},
  55. {"/vncCanvas.class", "JavaClass", IDR_VNCCANVAS_CLASS},
  56. {"/vncviewer.class", "JavaClass", IDR_VNCVIEWER_CLASS},
  57. {"/animatedMemoryImageSource.class", "JavaClass", IDR_ANIMMEMIMAGESRC_CLASS}
  58. };
  59. const int filemappingsize = 9;
  60. // The function for the spawned thread to run
  61. class vncHTTPConnectThread : public omni_thread
  62. {
  63. public:
  64. // Init routine
  65. virtual BOOL Init(VSocket *socket, vncServer *server);
  66. // Code to be executed by the thread
  67. virtual void *run_undetached(void * arg);
  68. // Routines to handle HTTP requests
  69. virtual void DoHTTP(VSocket *socket);
  70. virtual char *ReadLine(VSocket *socket, char delimiter, int max);
  71. // Fields used internally
  72. BOOL m_shutdown;
  73. protected:
  74. vncServer *m_server;
  75. VSocket *m_socket;
  76. };
  77. // Method implementations
  78. BOOL vncHTTPConnectThread::Init(VSocket *socket, vncServer *server)
  79. {
  80. // Save the server pointer
  81. m_server = server;
  82. // Save the socket pointer
  83. m_socket = socket;
  84. // Start the thread
  85. m_shutdown = FALSE;
  86. start_undetached();
  87. return TRUE;
  88. }
  89. // Code to be executed by the thread
  90. void *vncHTTPConnectThread::run_undetached(void * arg)
  91. {
  92. log.Print(LL_INTINFO, VNCLOG("started HTTP server threadn"));
  93. // Go into a loop, listening for connections on the given socket
  94. while (!m_shutdown)
  95. {
  96. // Accept an incoming connection
  97. VSocket *new_socket = m_socket->Accept();
  98. if (new_socket == NULL)
  99. break;
  100. log.Print(LL_CLIENTS, VNCLOG("HTTP client connectedn"));
  101. // Successful accept - perform the transaction
  102. DoHTTP(new_socket);
  103. // And close the client
  104. new_socket->Shutdown();
  105. new_socket->Close();
  106. delete new_socket;
  107. }
  108. log.Print(LL_INTINFO, VNCLOG("quitting HTTP server threadn"));
  109. return NULL;
  110. }
  111. void vncHTTPConnectThread::DoHTTP(VSocket *socket)
  112. {
  113. char filename[1024];
  114. char *line;
  115. // Read in the HTTP header
  116. if ((line = ReadLine(socket, 'n', 1024)) == NULL)
  117. return;
  118. // Scan the header for the filename and free the storage
  119. int result = sscanf(line, "GET %s ", &filename);
  120. delete [] line;
  121. if ((result == 0) || (result == EOF))
  122. return;
  123. log.Print(LL_CLIENTS, VNCLOG("file %s requestedn"), filename);
  124. // Read in the rest of the browser's request data and discard...
  125. BOOL emptyline=TRUE;
  126. for (;;)
  127. {
  128. char c;
  129. if (!socket->ReadExact(&c, 1))
  130. return;
  131. if (c=='n')
  132. {
  133. if (emptyline)
  134. break;
  135. emptyline = TRUE;
  136. }
  137. else
  138. if (c >= ' ')
  139. {
  140. emptyline = FALSE;
  141. }
  142. }
  143. log.Print(LL_INTINFO, VNCLOG("parameters readn"));
  144.     if (filename[0] != '/')
  145. {
  146. log.Print(LL_CONNERR, VNCLOG("filename didn't begin with '/'n"));
  147. socket->SendExact(HTTP_MSG_NOSUCHFILE, strlen(HTTP_MSG_NOSUCHFILE));
  148. return;
  149. }
  150. // Switch, dependent upon the filename:
  151. if (strcmp(filename, "/") == 0)
  152. {
  153. char indexpage[1024];
  154. log.Print(LL_CLIENTS, VNCLOG("sending main pagen"));
  155. // Send the OK notification message to the client
  156. if (!socket->SendExact(HTTP_MSG_OK, strlen(HTTP_MSG_OK)))
  157. return;
  158. // Compose the index page
  159. if (m_server->SockConnected())
  160. {
  161. int width, height, depth;
  162. // Get the screen's dimensions
  163. m_server->GetScreenInfo(width, height, depth);
  164. // Send the java applet page
  165. sprintf(indexpage, HTTP_FMT_INDEX,
  166. width, height+32, m_server->GetPort()
  167. );
  168. }
  169. else
  170. {
  171. // Send a "sorry, not allowed" page
  172. sprintf(indexpage, HTTP_MSG_NOSOCKCONN);
  173. }
  174. // Send the page
  175. if (socket->SendExact(indexpage, strlen(indexpage)))
  176. log.Print(LL_INTINFO, VNCLOG("sent pagen"));
  177. return;
  178. }
  179. // File requested was not the index so check the mappings
  180. // list for a different file.
  181. // Now search the mappings for the desired file
  182. for (int x=0; x < filemappingsize; x++)
  183. {
  184. if (strcmp(filename, filemapping[x].filename) == 0)
  185. {
  186. HRSRC resource;
  187. HGLOBAL resourcehan;
  188. char *resourceptr;
  189. int resourcesize;
  190. log.Print(LL_INTINFO, VNCLOG("requested file recognisedn"));
  191. // Find the resource here
  192. resource = FindResource(NULL,
  193. MAKEINTRESOURCE(filemapping[x].resourceID),
  194. filemapping[x].type
  195. );
  196. if (resource == NULL)
  197. return;
  198. // Get its size
  199. resourcesize = SizeofResource(NULL, resource);
  200. // Load the resource
  201. resourcehan = LoadResource(NULL, resource);
  202. if (resourcehan == NULL)
  203. return;
  204. // Lock the resource
  205. resourceptr = (char *)LockResource(resourcehan);
  206. if (resourceptr == NULL)
  207. return;
  208. log.Print(LL_INTINFO, VNCLOG("sending file...n"));
  209. // Send the OK message
  210. if (!socket->SendExact(HTTP_MSG_OK, strlen(HTTP_MSG_OK)))
  211. return;
  212. // Now send the entirety of the data to the client
  213. if (!socket->SendExact(resourceptr, resourcesize))
  214. return;
  215. log.Print(LL_INTINFO, VNCLOG("file successfully sentn"));
  216. return;
  217. }
  218. }
  219. // Send the NoSuchFile notification message to the client
  220. if (!socket->SendExact(HTTP_MSG_NOSUCHFILE, strlen(HTTP_MSG_NOSUCHFILE)))
  221. return;
  222. }
  223. char *vncHTTPConnectThread::ReadLine(VSocket *socket, char delimiter, int max)
  224. {
  225. // Allocate the maximum required buffer
  226. char *buffer = new char[max+1];
  227. int buffpos = 0;
  228. // Read in data until a delimiter is read
  229. for (;;)
  230. {
  231. char c;
  232. if (!socket->ReadExact(&c, 1))
  233. {
  234. delete [] buffer;
  235. return NULL;
  236. }
  237. if (c == delimiter)
  238. {
  239. buffer[buffpos] = 0;
  240. return buffer;
  241. }
  242. buffer[buffpos] = c;
  243. buffpos++;
  244. if (buffpos == (max-1))
  245. {
  246. buffer[buffpos] = 0;
  247. return buffer;
  248. }
  249. }
  250. }
  251. // The vncSockConnect class implementation
  252. vncHTTPConnect::vncHTTPConnect()
  253. {
  254. m_thread = NULL;
  255. }
  256. vncHTTPConnect::~vncHTTPConnect()
  257. {
  258.     m_socket.Shutdown();
  259.     // Join with our lovely thread
  260.     if (m_thread != NULL)
  261.     {
  262. // *** This is a hack to force the listen thread out of the accept call,
  263. // because Winsock accept semantics are broken.
  264. ((vncHTTPConnectThread *)m_thread)->m_shutdown = TRUE;
  265. VSocket socket;
  266. socket.Create();
  267. socket.Bind(0);
  268. socket.Connect("localhost", m_port);
  269. socket.Close();
  270. void *returnval;
  271. m_thread->join(&returnval);
  272. m_thread = NULL;
  273. m_socket.Close();
  274.     }
  275. }
  276. BOOL vncHTTPConnect::Init(vncServer *server, UINT port)
  277. {
  278. // Save the port id
  279. m_port = port;
  280. // Create the listening socket
  281. if (!m_socket.Create())
  282. return FALSE;
  283. // Bind it
  284. if (!m_socket.Bind(m_port))
  285. return FALSE;
  286. // Set it to listen
  287. if (!m_socket.Listen())
  288. return FALSE;
  289. // Create the new thread
  290. m_thread = new vncHTTPConnectThread;
  291. if (m_thread == NULL)
  292. return FALSE;
  293. // And start it running
  294. return ((vncHTTPConnectThread *)m_thread)->Init(&m_socket, server);
  295. }