added basic support for an embedded HTTP server. server

currently supports editing the screen map but changing
the map won't behave correctly if there are connected
screens.
This commit is contained in:
crs
2002-05-30 16:13:16 +00:00
parent 2cc63e31aa
commit 70f5f9491d
14 changed files with 1986 additions and 10 deletions

View File

@@ -1,4 +1,5 @@
#include "CServer.h"
#include "CHTTPServer.h"
#include "CInputPacketStream.h"
#include "COutputPacketStream.h"
#include "CServerProtocol.h"
@@ -15,6 +16,7 @@
#include "CThread.h"
#include "CTimerThread.h"
#include "CStopwatch.h"
#include "CFunctionJob.h"
#include "TMethodJob.h"
#include "CLog.h"
#include <assert.h>
@@ -44,7 +46,8 @@ else { wait(0); exit(1); }
CServer::CServer() : m_primary(NULL),
m_active(NULL),
m_primaryInfo(NULL),
m_seqNum(0)
m_seqNum(0),
m_httpServer(NULL)
{
m_socketFactory = NULL;
m_securityFactory = NULL;
@@ -63,18 +66,21 @@ void CServer::run()
// connect to primary screen
openPrimaryScreen();
// start listening for HTTP requests
m_httpServer = new CHTTPServer(this);
CThread(new TMethodJob<CServer>(this, &CServer::acceptHTTPClients));
// start listening for new clients
CThread(new TMethodJob<CServer>(this, &CServer::acceptClients));
// start listening for configuration connections
// FIXME
// handle events
log((CLOG_DEBUG "starting event handling"));
m_primary->run();
// clean up
log((CLOG_NOTE "stopping server"));
delete m_httpServer;
m_httpServer = NULL;
cleanupThreads();
closePrimaryScreen();
}
@@ -82,6 +88,8 @@ void CServer::run()
log((CLOG_ERR "server error: %s", e.what()));
// clean up
delete m_httpServer;
m_httpServer = NULL;
cleanupThreads();
closePrimaryScreen();
}
@@ -89,6 +97,8 @@ void CServer::run()
log((CLOG_DEBUG "unknown server error"));
// clean up
delete m_httpServer;
m_httpServer = NULL;
cleanupThreads();
closePrimaryScreen();
throw;
@@ -109,6 +119,12 @@ void CServer::setScreenMap(const CScreenMap& screenMap)
m_screenMap = screenMap;
}
CString CServer::getPrimaryScreenName() const
{
CLock lock(&m_mutex);
return (m_primaryInfo == NULL) ? "" : m_primaryInfo->m_name;
}
void CServer::getScreenMap(CScreenMap* screenMap) const
{
assert(screenMap != NULL);
@@ -956,6 +972,88 @@ void CServer::handshakeClient(void* vsocket)
}
}
void CServer::acceptHTTPClients(void*)
{
log((CLOG_DEBUG1 "starting to wait for HTTP clients"));
// add this thread to the list of threads to cancel. remove from
// list in d'tor.
CCleanupNote cleanupNote(this);
std::auto_ptr<IListenSocket> listen;
try {
// create socket listener
// listen = std::auto_ptr<IListenSocket>(m_socketFactory->createListen());
assign(listen, new CTCPListenSocket, IListenSocket); // FIXME
// bind to the desired port. keep retrying if we can't bind
// the address immediately.
CStopwatch timer;
CNetworkAddress addr(50002 /* FIXME -- m_httpPort */);
for (;;) {
try {
log((CLOG_DEBUG1 "binding listen socket"));
listen->bind(addr);
break;
}
catch (XSocketAddressInUse&) {
// give up if we've waited too long
if (timer.getTime() >= m_bindTimeout) {
log((CLOG_DEBUG1 "waited too long to bind HTTP, giving up"));
throw;
}
// wait a bit before retrying
log((CLOG_DEBUG1 "bind HTTP failed; waiting to retry"));
CThread::sleep(5.0);
}
}
// accept connections and begin processing them
log((CLOG_DEBUG1 "waiting for HTTP connections"));
for (;;) {
// accept connection
CThread::testCancel();
ISocket* socket = listen->accept();
log((CLOG_NOTE "accepted HTTP connection"));
CThread::testCancel();
// handle HTTP request
CThread(new TMethodJob<CServer>(
this, &CServer::processHTTPRequest, socket));
}
}
catch (XBase& e) {
log((CLOG_ERR "cannot listen for HTTP clients: %s", e.what()));
quit();
}
}
void CServer::processHTTPRequest(void* vsocket)
{
// add this thread to the list of threads to cancel. remove from
// list in d'tor.
CCleanupNote cleanupNote(this);
ISocket* socket = reinterpret_cast<ISocket*>(vsocket);
try {
// process the request and force delivery
m_httpServer->processRequest(socket);
socket->getOutputStream()->flush();
// wait a moment to give the client a chance to hangup first
CThread::sleep(3.0);
// clean up
socket->close();
delete socket;
}
catch (...) {
delete socket;
throw;
}
}
void CServer::clearGotClipboard(ClipboardID id)
{
for (CScreenList::const_iterator index = m_screens.begin();