]> git.mxchange.org Git - flightgear.git/blob - src/Network/jpg-httpd.cxx
Merge branch 'work4' into next
[flightgear.git] / src / Network / jpg-httpd.cxx
1 // httpd.hxx -- FGFS http property manager interface / external script
2 //              and control class
3 //
4 // Written by Curtis Olson, started June 2001.
5 //
6 // Copyright (C) 2001  Curtis L. Olson - http://www.flightgear.org/~curt
7 //
8 // Jpeg Image Support added August 2001
9 //  by Norman Vine - nhv@cape.com
10 //
11 // This program is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU General Public License as
13 // published by the Free Software Foundation; either version 2 of the
14 // License, or (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful, but
17 // WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 // General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24 //
25 // $Id$
26
27
28 #ifdef HAVE_CONFIG_H
29 #  include <config.h>
30 #endif
31
32 #include <simgear/compiler.h>
33
34 #include <stdlib.h>             // atoi() atof()
35
36 #include <string>
37
38 #include <simgear/debug/logstream.hxx>
39 #include <simgear/io/iochannel.hxx>
40 #include <simgear/math/sg_types.hxx>
41 #include <simgear/props/props.hxx>
42
43 #include <Main/fg_props.hxx>
44 #include <Main/globals.hxx>
45 #include <Main/renderer.hxx>
46
47 #include "jpg-httpd.hxx"
48
49 #define __MAX_HTTP_BLOCK_SIZE       4096
50 #define __MAX_STRING_SIZE           2048
51 #define __TIMEOUT_COUNT             5
52 #define __HTTP_GET_STRING           "GET "
53
54 #include <osgUtil/SceneView>
55 #include <osgViewer/Viewer>
56 extern osg::ref_ptr<osgUtil::SceneView> sceneView;
57
58 using std::string;
59
60
61 bool FGJpegHttpd::open() {
62     if ( is_enabled() ) {
63         SG_LOG( SG_IO, SG_ALERT, "This shouldn't happen, but the channel " 
64                 << "is already in use, ignoring" );
65         return false;
66     }
67
68     imageServer = new HttpdImageServer( port );
69     
70     set_hz( 5 );                // default to processing requests @ 5Hz
71     set_enabled( true );
72
73     return true;
74 }
75
76
77 bool FGJpegHttpd::process() {
78     netChannel::poll();
79
80     return true;
81 }
82
83
84 bool FGJpegHttpd::close() {
85     delete imageServer;
86
87     return true;
88 }
89
90 // Handle http GET requests
91 void HttpdImageChannel :: foundTerminator( void ) {
92
93     closeWhenDone();
94
95     char      szTemp[256];
96     char      szResponse[__MAX_STRING_SIZE];
97     char      *pRequest     = buffer.getData();
98     int       nStep         = 0;
99     int       nBytesSent    = 0;
100     int       nTimeoutCount = 0;
101     int       nBufferCount  = 0;
102     int       nImageLen;
103     int       nBlockSize;
104
105
106     if ( strstr( pRequest, __HTTP_GET_STRING ) != NULL ) {
107         
108         SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< HTTP Request : " << pRequest );
109
110         double left, right, bottom, top, zNear, zFar;
111         osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
112         viewer->getCamera()->getProjectionMatrixAsFrustum(left, right,
113                                                           bottom, top,
114                                                           zNear, zFar);
115         JpgFactory->setFrustum( left, right, bottom, top, zNear, zFar );
116
117         nImageLen  = JpgFactory -> render();
118         nBlockSize = ( nImageLen < __MAX_HTTP_BLOCK_SIZE ? nImageLen : __MAX_HTTP_BLOCK_SIZE );
119
120         if( nImageLen ) {
121             strcpy( szResponse, "HTTP/1.1 200 OK" );
122             strcat( szResponse, getTerminator() );
123             strcat( szResponse, "Content-Type: image/jpeg" );
124             strcat( szResponse, getTerminator() );
125
126             SG_LOG( SG_IO, SG_DEBUG, "info->numbytes = " << nImageLen );
127             sprintf( szTemp, "Content-Length: %d", nImageLen );
128             strcat( szResponse, szTemp );
129
130             strcat( szResponse, getTerminator() );
131             strcat( szResponse, "Connection: close" );
132             strcat( szResponse, getTerminator() );
133             strcat( szResponse, getTerminator() );
134
135             if( getHandle() == -1 )  {
136                 SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< Invalid socket handle. Ignoring request.\n" );
137                 buffer.remove();
138                 SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< End of image Transmission.\n" );
139                 return;
140             }
141
142             if( send( ( char * ) szResponse, strlen( szResponse ) ) <= 0 )  {
143                 SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< Error to send HTTP response. Ignoring request.\n" );
144                 buffer.remove();
145                 SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< End of image Transmission.\n" );
146                 return;
147             }
148
149             /*
150              * Send block with size defined by __MAX_HTTP_BLOCK_SIZE
151              */
152             while( nStep <= nImageLen ) {
153                 nBufferCount++;
154
155                 if( getHandle() == -1 )  {
156                     SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< Invalid socket handle. Ignoring request.\n" );
157                     break;
158                 }
159
160                 nBytesSent = send( ( char * ) JpgFactory -> data() + nStep, nBlockSize );
161
162                 if( nBytesSent <= 0 )  {
163                     if( nTimeoutCount == __TIMEOUT_COUNT )  {
164                         SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< Timeout reached. Exiting before end of image transmission.\n" );
165                         nTimeoutCount = 0;
166                         break;
167                     }
168
169                 SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< Zero bytes sent.\n" );
170
171 #ifdef _WIN32
172                 Sleep(1000);
173 #else
174                 sleep(1);
175 #endif
176                 nTimeoutCount++;
177                 continue;
178             }
179
180             SG_LOG( SG_IO, SG_DEBUG, ">>>>>>>>> (" << nBufferCount << ") BLOCK STEP " << nStep << " - IMAGELEN " << nImageLen << " - BLOCKSIZE " << nBlockSize << " - SENT " << nBytesSent );
181
182             /*
183              * Calculate remaining image.
184              */
185             if( ( nStep + nBlockSize ) >= nImageLen ) {
186                 nBlockSize = ( nImageLen - nStep );
187                 nStep += nBlockSize;
188             }
189
190             nStep += nBytesSent;
191             nTimeoutCount = 0;
192 #ifdef _WIN32
193             Sleep(1);
194 #else
195             usleep( 1000 );
196 #endif
197         }
198
199         SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< End of image Transmission.\n" );
200
201         } else {
202             SG_LOG( SG_IO, SG_DEBUG, "!!! NO IMAGE !!!  info -> numbytes = " << nImageLen );
203         }
204
205         /*
206          * Release JPEG buffer.
207          */
208         JpgFactory -> destroy();
209     }
210
211     buffer.remove();
212 }