-// httpd.hxx -- FGFS http property manager interface / external script
-// and control class
+// jpg-httpd.cxx -- FGFS jpg-http interface
//
// Written by Curtis Olson, started June 2001.
//
#include <simgear/compiler.h>
-#include <stdlib.h> // atoi() atof()
+#include <cstdlib> // atoi() atof()
-#include STL_STRING
+#include <cstring>
#include <simgear/debug/logstream.hxx>
#include <simgear/io/iochannel.hxx>
#include <simgear/math/sg_types.hxx>
#include <simgear/props/props.hxx>
+#include <simgear/io/sg_netChat.hxx>
+#include <simgear/screen/jpgfactory.hxx>
#include <Main/fg_props.hxx>
#include <Main/globals.hxx>
+#include <Viewer/renderer.hxx>
#include "jpg-httpd.hxx"
#define __HTTP_GET_STRING "GET "
#include <osgUtil/SceneView>
+#include <osgViewer/Viewer>
extern osg::ref_ptr<osgUtil::SceneView> sceneView;
-SG_USING_STD(string);
+using std::string;
+/* simple httpd server that makes an hasty stab at following the http
+ 1.1 rfc. */
+
+//////////////////////////////////////////////////////////////
+// class HttpdImageChannel
+//////////////////////////////////////////////////////////////
+
+class HttpdImageChannel : public simgear::NetChat
+{
+
+ simgear::NetBuffer buffer;
+ trJpgFactory *JpgFactory;
+
+public:
+
+ HttpdImageChannel() : buffer(512) {
+
+ int nWidth = fgGetInt( "/sim/startup/xsize", 800 );
+ int nHeight = fgGetInt( "/sim/startup/ysize", 600 );
+
+ setTerminator("\r\n");
+ JpgFactory = new trJpgFactory();
+ int error = JpgFactory -> init( nWidth, nHeight );
+ if (0 != error)
+ {
+ SG_LOG( SG_IO, SG_ALERT, "Failed to initialize JPEG-factory, error: " << error);
+ }
+ }
+
+ ~HttpdImageChannel() {
+ JpgFactory -> destroy();
+ delete JpgFactory;
+ }
+
+ virtual void collectIncomingData (const char* s, int n) {
+ buffer.append(s,n);
+ }
+
+ // Handle the actual http request
+ virtual void foundTerminator (void);
+};
+
+//////////////////////////////////////////////////////////////
+// class HttpdImageServer
+//////////////////////////////////////////////////////////////
+
+class HttpdImageServer : private simgear::NetChannel
+{
+ virtual bool writable (void) { return false; }
+
+ virtual void handleAccept (void) {
+ simgear::IPAddress addr;
+ int handle = accept ( &addr );
+ SG_LOG( SG_IO, SG_INFO, "Client " << addr.getHost() << ":" << addr.getPort() << " connected" );
+
+ HttpdImageChannel *hc = new HttpdImageChannel;
+ hc->setHandle ( handle );
+ }
+
+public:
+
+ HttpdImageServer ( int port )
+ {
+ if (!open())
+ {
+ SG_LOG( SG_IO, SG_ALERT, "Failed to open HttpdImage port.");
+ return;
+ }
+
+ if (0 != bind( "", port ))
+ {
+ SG_LOG( SG_IO, SG_ALERT, "Failed to bind HttpdImage port.");
+ return;
+ }
+
+ if (0 != listen( 5 ))
+ {
+ SG_LOG( SG_IO, SG_ALERT, "Failed to listen on HttpdImage port.");
+ return;
+ }
+
+ SG_LOG(SG_IO, SG_ALERT, "HttpdImage server started on port " << port);
+ }
+
+};
+
+//////////////////////////////////////////////////////////////
+// class FGJpegHttpd
+//////////////////////////////////////////////////////////////
+
+FGJpegHttpd::FGJpegHttpd( int p ) :
+ port(p),
+ imageServer(NULL)
+{
+}
+
+FGJpegHttpd::~FGJpegHttpd()
+{
+ delete imageServer;
+}
bool FGJpegHttpd::open() {
if ( is_enabled() ) {
- SG_LOG( SG_IO, SG_ALERT, "This shouldn't happen, but the channel "
- << "is already in use, ignoring" );
- return false;
+ SG_LOG( SG_IO, SG_ALERT, "This shouldn't happen, but the channel "
+ << "is already in use, ignoring" );
+ return false;
}
imageServer = new HttpdImageServer( port );
bool FGJpegHttpd::process() {
- netChannel::poll();
+ simgear::NetChannel::poll();
return true;
}
bool FGJpegHttpd::close() {
delete imageServer;
-
+ imageServer = NULL;
return true;
}
int nBlockSize;
- if ( strstr( pRequest, __HTTP_GET_STRING ) != NULL ) {
+ if ( strstr( pRequest, __HTTP_GET_STRING ) != NULL )
+ {
SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< HTTP Request : " << pRequest );
double left, right, bottom, top, zNear, zFar;
- sceneView->getCamera()->getProjectionMatrixAsFrustum( left, right, bottom, top, zNear, zFar );
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+ viewer->getCamera()->getProjectionMatrixAsFrustum(left, right,
+ bottom, top,
+ zNear, zFar);
JpgFactory->setFrustum( left, right, bottom, top, zNear, zFar );
nImageLen = JpgFactory -> render();
- nBlockSize = ( nImageLen < __MAX_HTTP_BLOCK_SIZE ? nImageLen : __MAX_HTTP_BLOCK_SIZE );
+ nBlockSize = ( nImageLen < __MAX_HTTP_BLOCK_SIZE ? nImageLen : __MAX_HTTP_BLOCK_SIZE );
- if( nImageLen ) {
- strcpy( szResponse, "HTTP/1.1 200 OK" );
- strcat( szResponse, getTerminator() );
- strcat( szResponse, "Content-Type: image/jpeg" );
+ if( nImageLen )
+ {
+ strcpy( szResponse, "HTTP/1.1 200 OK" );
+ strcat( szResponse, getTerminator() );
+ strcat( szResponse, "Content-Type: image/jpeg" );
strcat( szResponse, getTerminator() );
SG_LOG( SG_IO, SG_DEBUG, "info->numbytes = " << nImageLen );
sprintf( szTemp, "Content-Length: %d", nImageLen );
- strcat( szResponse, szTemp );
+ strcat( szResponse, szTemp );
strcat( szResponse, getTerminator() );
- strcat( szResponse, "Connection: close" );
- strcat( szResponse, getTerminator() );
- strcat( szResponse, getTerminator() );
-
- if( getHandle() == -1 ) {
- SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< Invalid socket handle. Ignoring request.\n" );
- buffer.remove();
- SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< End of image Transmission.\n" );
- return;
- }
-
- if( send( ( char * ) szResponse, strlen( szResponse ) ) <= 0 ) {
- SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< Error to send HTTP response. Ignoring request.\n" );
- buffer.remove();
- SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< End of image Transmission.\n" );
- return;
- }
-
- /*
- * Send block with size defined by __MAX_HTTP_BLOCK_SIZE
- */
- while( nStep <= nImageLen ) {
+ strcat( szResponse, "Connection: close" );
+ strcat( szResponse, getTerminator() );
+ strcat( szResponse, getTerminator() );
+
+ if( getHandle() == -1 )
+ {
+ SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< Invalid socket handle. Ignoring request.\n" );
+ buffer.remove();
+ SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< End of image Transmission.\n" );
+ return;
+ }
+
+ if( send( ( char * ) szResponse, strlen( szResponse ) ) <= 0 )
+ {
+ SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< Error to send HTTP response. Ignoring request.\n" );
+ buffer.remove();
+ SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< End of image Transmission.\n" );
+ return;
+ }
+
+ /*
+ * Send block with size defined by __MAX_HTTP_BLOCK_SIZE
+ */
+ while( nStep <= nImageLen )
+ {
nBufferCount++;
- if( getHandle() == -1 ) {
- SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< Invalid socket handle. Ignoring request.\n" );
- break;
- }
+ if( getHandle() == -1 )
+ {
+ SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< Invalid socket handle. Ignoring request.\n" );
+ break;
+ }
- nBytesSent = send( ( char * ) JpgFactory -> data() + nStep, nBlockSize );
+ nBytesSent = send( ( char * ) JpgFactory -> data() + nStep, nBlockSize );
- if( nBytesSent <= 0 ) {
- if( nTimeoutCount == __TIMEOUT_COUNT ) {
- SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< Timeout reached. Exiting before end of image transmission.\n" );
- nTimeoutCount = 0;
- break;
- }
+ if( nBytesSent <= 0 )
+ {
+ if( nTimeoutCount == __TIMEOUT_COUNT )
+ {
+ SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< Timeout reached. Exiting before end of image transmission.\n" );
+ nTimeoutCount = 0;
+ break;
+ }
- SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< Zero bytes sent.\n" );
+ SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< Zero bytes sent.\n" );
#ifdef _WIN32
- Sleep(1000);
+ Sleep(1000);
#else
- sleep(1);
+ sleep(1);
#endif
- nTimeoutCount++;
- continue;
- }
-
- SG_LOG( SG_IO, SG_DEBUG, ">>>>>>>>> (" << nBufferCount << ") BLOCK STEP " << nStep << " - IMAGELEN " << nImageLen << " - BLOCKSIZE " << nBlockSize << " - SENT " << nBytesSent );
-
- /*
- * Calculate remaining image.
- */
- if( ( nStep + nBlockSize ) >= nImageLen ) {
- nBlockSize = ( nImageLen - nStep );
- nStep += nBlockSize;
- }
-
- nStep += nBytesSent;
- nTimeoutCount = 0;
+ nTimeoutCount++;
+ continue;
+ }
+
+ SG_LOG( SG_IO, SG_DEBUG, ">>>>>>>>> (" << nBufferCount << ") BLOCK STEP " << nStep << " - IMAGELEN " << nImageLen << " - BLOCKSIZE " << nBlockSize << " - SENT " << nBytesSent );
+
+ /*
+ * Calculate remaining image.
+ */
+ if( ( nStep + nBlockSize ) >= nImageLen )
+ {
+ nBlockSize = ( nImageLen - nStep );
+ nStep += nBlockSize;
+ }
+
+ nStep += nBytesSent;
+ nTimeoutCount = 0;
#ifdef _WIN32
- Sleep(1);
+ Sleep(1);
#else
- usleep( 1000 );
+ usleep( 1000 );
#endif
- }
+ }
- SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< End of image Transmission.\n" );
+ SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< End of image Transmission.\n" );
} else {
- SG_LOG( SG_IO, SG_DEBUG, "!!! NO IMAGE !!! info -> numbytes = " << nImageLen );
+ SG_LOG( SG_IO, SG_ALERT, "Failed to generate JPEG image data. Error: " << nImageLen);
}
- /*
- * Release JPEG buffer.
- */
- JpgFactory -> destroy();
+ /*
+ * Release JPEG buffer.
+ */
+ JpgFactory -> destroy();
}
buffer.remove();