VideoTools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gvhttpserver.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2017 Graeme Walker
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gvhttpserver.cpp
19 //
20 
21 #include "gdef.h"
22 #include "gvhttpserver.h"
23 #include "gvexit.h"
24 #include "geventloop.h"
25 #include "grjpeg.h"
26 #include "groot.h"
27 #include "ghexdump.h"
28 #include "gstr.h"
29 #include "glog.h"
30 #include "gassert.h"
31 #include <fstream>
32 
34  m_streaming(false) ,
35  m_refresh(0U) ,
36  m_type("jpeg") ,
37  m_scale(1) ,
38  m_monochrome(false) ,
39  m_idle_timeout(20U) ,
40  m_first_image_timeout(3U) ,
41  m_image_repeat_timeout(1U) ,
42  m_gateway(GNet::Address::defaultAddress()) ,
43  m_more_verbose(true) ,
44  m_quick(true)
45 {
46 }
47 
48 void Gv::HttpServerConfig::init( unsigned int idle_timeout ,
49  unsigned int first_image_timeout , G::EpochTime image_repeat_timeout , unsigned int refresh ,
50  const GNet::Address & gateway , bool more_verbose )
51 {
52  m_idle_timeout = idle_timeout ;
53  m_first_image_timeout = std::max( 1U , first_image_timeout ) ;
54  m_image_repeat_timeout = image_repeat_timeout ;
55  m_refresh = refresh ;
56  m_gateway = gateway ;
57  m_more_verbose = more_verbose ;
58 }
59 
60 void Gv::HttpServerConfig::init( unsigned int idle_timeout ,
61  unsigned int first_image_timeout , G::EpochTime image_repeat_timeout , unsigned int refresh ,
62  const std::string & type )
63 {
64  m_idle_timeout = idle_timeout ;
65  m_first_image_timeout = std::max( 1U , first_image_timeout ) ;
66  m_image_repeat_timeout = image_repeat_timeout ;
67  m_refresh = refresh ;
68  m_type = type ;
69 }
70 
71 bool Gv::HttpServerConfig::integral( const G::Url & url , const std::string & key )
72 {
73  return url.has(key) && !url.parameter(key).empty() && G::Str::isUInt(url.parameter(key)) ;
74 }
75 
77 {
78  {
79  typedef G::Url::Map Map ;
80  Map params = url.pmap() ;
81  std::vector<std::string> errors ;
82  for( Map::iterator p = params.begin() ; p != params.end() ; ++p )
83  {
84  if( (*p).first != "streaming" &&
85  (*p).first != "refresh" &&
86  (*p).first != "scale" &&
87  (*p).first != "monochrome" &&
88  (*p).first != "type" &&
89  (*p).first != "quick" &&
90  (*p).first != "wait" )
91  {
92  errors.push_back( (*p).first ) ;
93  }
94  }
95  if( !errors.empty() )
96  G_WARNING( "Gv::HttpServerConfig::init: ignoring invalid url parameters: " << G::Str::printable(G::Str::join(",",errors)) ) ;
97  }
98 
99  if( integral(url,"streaming") )
100  m_streaming = !! G::Str::toUInt( url.parameter("streaming") ) ;
101 
102  if( integral(url,"refresh") )
103  m_refresh = G::Str::toUInt( url.parameter("refresh") ) ;
104 
105  if( integral(url,"scale") )
106  m_scale = G::Str::toUInt( url.parameter("scale") ) ;
107 
108  if( integral(url,"monochrome") )
109  m_monochrome = !! G::Str::toUInt( url.parameter("monochrome") ) ;
110 
111  if( url.parameter("type","") == "raw" )
112  m_type = "raw" ;
113  else if( url.parameter("type","") == "jpeg" )
114  m_type = "jpeg" ;
115  else if( url.parameter("type","") == "pnm" )
116  m_type = "pnm" ;
117  else if( url.parameter("type","") == "any" )
118  m_type = "any" ; // ie. no conversion
119  else if( !url.parameter("type","").empty() )
120  G_WARNING( "Gv::HttpServerConfig::init: ignoring unknown image type in url: [" + url.parameter("type","") + "]" ) ;
121 
122  if( integral(url,"quick") )
123  m_quick = !! G::Str::toUInt( url.parameter("quick") ) ;
124 
125  if( integral(url,"wait") )
126  m_first_image_timeout = G::Str::toUInt( url.parameter("wait") ) ;
127 }
128 
130 {
131  return m_idle_timeout ;
132 }
133 
135 {
136  return m_first_image_timeout ;
137 }
138 
140 {
141  return m_more_verbose ;
142 }
143 
144 std::string Gv::HttpServerConfig::type() const
145 {
146  return m_type ;
147 }
148 
150 {
151  return m_quick ;
152 }
153 
155 {
156  return m_streaming ;
157 }
158 
160 {
161  return m_gateway ;
162 }
163 
165 {
166  return m_image_repeat_timeout ;
167 }
168 
170 {
171  return m_scale ;
172 }
173 
175 {
176  return m_monochrome ;
177 }
178 
179 unsigned int Gv::HttpServerConfig::refresh() const
180 {
181  return m_refresh ;
182 }
183 
184 // ==
185 
187  m_any_file(false) ,
188  m_any_channel(false) ,
189  m_with_specials(false)
190 {
191 }
192 
193 std::string Gv::HttpServerResources::guessType( const G::Path & path )
194 {
195  std::string extension = path.extension() ;
196  if( extension == "js" ) return "text/javascript" ;
197  if( extension == "css" ) return "text/css" ;
198  if( extension == "html" ) return "text/html" ;
199  if( extension == "png" ) return "image/png" ;
200  if( extension == "jpeg" ) return "image/jpeg" ;
201  if( extension == "jpg" ) return "image/jpeg" ;
202  if( extension == "pnm" ) return "image/x-portable-anymap" ;
203  if( extension == "pgm" ) return "image/x-portable-anymap" ; // -graymap
204  if( extension == "pbm" ) return "image/x-portable-anymap" ; // -bitmap
205  if( extension == "ppm" ) return "image/x-portable-anymap" ; // -pixmap
206  return std::string() ;
207 }
208 
210 {
211  m_any_channel = true ;
212  m_with_specials = true ;
213 }
214 
216 {
217  return m_any_channel ;
218 }
219 
220 void Gv::HttpServerResources::addChannel( const std::string & channel_name )
221 {
222  if( channel_name == "*" )
223  m_any_channel = true ;
224  else
225  m_channels.push_back( channel_name ) ;
226 }
227 
229 {
230  //G_ASSERT( m_dir == G::Path() ) ;
231  m_dir = dir ;
232 }
233 
235 {
236  m_any_file = true ;
237 }
238 
239 std::string Gv::HttpServerResources::addFile( const G::Path & path_in )
240 {
241  if( path_in.isAbsolute() )
242  return "invalid absolute path" ;
243  G::Path path = normalise( path_in ) ;
244 
245  if( m_files.find(path.str()) != m_files.end() )
246  return "duplicate" ;
247 
248  m_files[path.str()] = G::Path::join(m_dir,path).str() ;
249  return std::string() ;
250 }
251 
252 void Gv::HttpServerResources::addFileType( const G::Path & path_in , const std::string & type )
253 {
254  G::Path path = normalise( path_in ) ;
255  m_file_types[path.str()] = type ;
256 }
257 
258 std::string Gv::HttpServerResources::setDefault( const std::string & name )
259 {
260  m_default_resource = name ;
261 
262  if( name.find('_') == 0U )
263  {
264  if( !m_any_channel && std::find(m_channels.begin(),m_channels.end(),name) == m_channels.end() )
265  return "no such channel: [" + name + "]" ;
266  }
267  else
268  {
269  if( m_files.find(name) == m_files.end() && !m_any_file )
270  return "no such file: [" + name + "]" ;
271  }
272  return std::string() ;
273 }
274 
276 {
277  return !m_any_channel && !m_any_file && m_files.empty() && m_channels.empty() ;
278 }
279 
280 Gv::HttpServerResources::ResourceType Gv::HttpServerResources::resourceType( const G::Path & url_path ) const
281 {
282  std::string basename = url_path == "/" ? m_default_resource : url_path.basename() ;
283  if( empty() ) // nothing configured
284  return t_source ;
285  else if( m_with_specials && basename.find("__") == 0U )
286  return t_special ;
287  else if( basename.find("_") == 0U )
288  return t_channel ;
289  else
290  return t_file ;
291 }
292 
293 std::vector<std::string> Gv::HttpServerResources::channels() const
294 {
295  return m_channels ;
296 }
297 
298 std::string Gv::HttpServerResources::channelName( const G::Path & url_path ) const
299 {
300  std::string basename = url_path == "/" ? m_default_resource : url_path.basename() ;
301  if( basename.find('_') == 0U && basename.find("__") != 0U )
302  return basename.substr( 1U ) ;
303  else
304  return std::string() ;
305 }
306 
307 bool Gv::HttpServerResources::channelResource( const G::Path & url_path ) const
308 {
309  return resourceType(url_path) == t_channel ;
310 }
311 
312 bool Gv::HttpServerResources::specialResource( const G::Path & url_path ) const
313 {
314  return resourceType(url_path) == t_special ;
315 }
316 
317 bool Gv::HttpServerResources::fileResource( const G::Path & url_path ) const
318 {
319  return resourceType(url_path) == t_file ;
320 }
321 
322 std::string Gv::HttpServerResources::fileResourcePath( const G::Path & url_path ) const
323 {
324  return fileResourcePair(url_path).first ;
325 }
326 
327 std::string Gv::HttpServerResources::fileResourceType( const G::Path & url_path ) const
328 {
329  return fileResourcePair(url_path).second ;
330 }
331 
332 bool Gv::HttpServerResources::readable( const G::Path & path )
333 {
334  std::ifstream f ;
335  {
336  G::Root claim_root ;
337  f.open( path.str().c_str() ) ;
338  }
339  return f.good() ;
340 }
341 
342 G::Path Gv::HttpServerResources::normalise( const G::Path & path_in )
343 {
344  // eg. /foo////.././bar -> bar
345  G::StringArray parts = path_in.collapsed().split() ;
346  if( !parts.empty() && parts.at(0U) == "/" )
347  parts.erase( parts.begin() ) ;
348  return G::Path::join( parts ) ;
349 }
350 
351 G::Path Gv::HttpServerResources::normalise( const G::Path & path_in , const std::string & default_ )
352 {
353  G::StringArray parts = path_in.collapsed().split() ;
354  if( parts.size() == 1U && parts.at(0U) == "/" )
355  parts = G::Path(default_).collapsed().split() ;
356  if( !parts.empty() && parts.at(0U) == "/" )
357  parts.erase( parts.begin() ) ;
358  return G::Path::join( parts ) ;
359 }
360 
361 std::pair<std::string,std::string> Gv::HttpServerResources::fileResourcePair( const G::Path & url_path_in ) const
362 {
363  G_ASSERT( resourceType(url_path_in) == t_file ) ;
364  std::pair<std::string,std::string> result ; // path,type or "",reason
365  std::string reason ;
366 
367  // normalise the url path and make it relative
368  G::Path url_path = normalise( url_path_in , m_default_resource ) ;
369 
370  if( m_dir == G::Path() )
371  {
372  // error
373  reason = "no base directory configured" ;
374  }
375  else if( url_path == G::Path() || url_path == "." || url_path.str().find("..") == 0U )
376  {
377  // error
378  reason = "invalid path" ;
379  }
380  else if( m_any_file )
381  {
382  G::Path file_path = G::Path::join( m_dir , url_path ) ;
383  std::string file_key = url_path.str() ;
384  Map::const_iterator file_type_p = m_file_types.find( file_key ) ;
385  std::string type = file_type_p == m_file_types.end() ? guessType(file_key) : (*file_type_p).second ;
386  if( readable(file_path) )
387  {
388  result.first = file_path.str() ;
389  result.second = type ;
390  }
391  else
392  {
393  reason = "not readable: [" + file_path.str() + "]" ;
394  }
395  }
396  else
397  {
398  G::Path file_path = G::Path::join( m_dir , url_path ) ;
399  std::string file_key = url_path.str() ;
400  Map::const_iterator file_type_p = m_file_types.find( file_key ) ;
401  std::string type = file_type_p == m_file_types.end() ? guessType(file_key) : (*file_type_p).second ;
402  Map::const_iterator file_p = m_files.find( file_key ) ;
403  if( file_p == m_files.end() )
404  {
405  // not allowed
406  reason = std::string("not in the allowed file list: [") + file_key + "]" ;
407  }
408  else if( readable(file_path) )
409  {
410  result.first = file_path.str() ;
411  result.second = type ;
412  }
413  else
414  {
415  reason = "not readable: [" + file_path.str() + "]" ;
416  }
417  }
418  if( !reason.empty() )
419  {
420  result.first = std::string() ;
421  result.second = reason ;
422  }
423  return result ;
424 }
425 
426 void Gv::HttpServerResources::log( std::ostream & out ) const
427 {
428  if( m_dir != G::Path() )
429  {
430  out << "directory: path=[" << m_dir << "]\n" ;
431  }
432  if( m_any_file )
433  {
434  out << "file: <any>\n" ;
435  }
436  for( Map::const_iterator file_p = m_files.begin() ; file_p != m_files.end() ; ++file_p )
437  {
438  out << "file: filename=[" << (*file_p).first << "]\n" ;
439  }
440  for( Map::const_iterator file_type_p = m_file_types.begin() ; file_type_p != m_file_types.end() ; ++file_type_p )
441  {
442  out << "file-type: filename=[" << (*file_type_p).first << "] type=[" << (*file_type_p).second << "]\n" ;
443  }
444  for( G::StringArray::const_iterator channel_p = m_channels.begin() ; channel_p != m_channels.end() ; ++channel_p )
445  {
446  out << "channel: name=[" << *channel_p << "]\n" ;
447  }
448  if( m_any_channel )
449  {
450  out << "channel: <any>\n" ;
451  }
452  out << "default: [" << m_default_resource << "]\n" ;
453 }
454 
456 {
457  if( !empty() )
458  {
459  std::ostringstream ss ;
460  log( ss ) ;
461  G::StringArray lines ; G::Str::splitIntoFields( ss.str() , lines , "\n" ) ;
462  for( G::StringArray::iterator p = lines.begin() ; p != lines.end() ; ++p )
463  {
464  if( !(*p).empty() )
465  G_LOG( "Gv::HttpServerResources::log: server resource: " << *p ) ;
466  }
467  }
468 }
469 
470 // ==
471 
473  const std::string & channel_name , unsigned int reopen_timeout ) :
474  Gv::ImageInput(converter,channel_name,true/*lazy*/) ,
475  m_fd(-1) ,
476  m_reopen_timeout(reopen_timeout) ,
477  m_reopen_timer(*this,&HttpServerInput::onTimeout,static_cast<GNet::EventHandler&>(*this))
478 {
479 }
480 
482 {
483  if( m_fd == -1 )
484  {
485  if( open() ) // Gv::ImageInput::open()
486  {
487  m_fd = fd() ;
488  if( m_fd != -1 )
489  attach() ;
490  }
491  }
492 }
493 
494 void Gv::HttpServerInput::attach()
495 {
496  G_ASSERT( m_fd != -1 ) ;
497  G_LOG( "Gv::HttpServerInput::attach: starting channel [" << name() << "] fd=" << m_fd ) ;
499 }
500 
501 void Gv::HttpServerInput::detach()
502 {
503  G_ASSERT( m_fd != -1 ) ;
504  G_LOG( "Gv::HttpServerInput::detach: stopping channel [" << name() << "] fd=" << m_fd ) ;
506  m_fd = -1 ;
507 }
508 
510 {
511  if( m_fd != -1 )
512  detach() ;
513 }
514 
515 void Gv::HttpServerInput::onException( std::exception & )
516 {
517  throw ;
518 }
519 
520 void Gv::HttpServerInput::readEvent()
521 {
522  if( !handleReadEvent() )
523  {
524  close() ; // Gv::ImageInput::close()
525  detach() ;
526  G_LOG( "Gv::HttpServerInput::readEvent: channel failed [" << name() << "]" ) ;
527  if( m_reopen_timeout != 0U )
528  m_reopen_timer.startTimer( m_reopen_timeout ) ;
529  }
530 }
531 
532 void Gv::HttpServerInput::onTimeout()
533 {
534  G_DEBUG( "Gv::HttpServerInput::onTimeout: checking for channel [" << name() << "]" ) ;
535  start() ;
536  if( m_fd == -1 )
537  m_reopen_timer.startTimer( m_reopen_timeout ) ;
538 }
539 
540 // ==
541 
543  const HttpServerResources & resources , unsigned int reopen_timeout ) :
544  m_converter(converter) ,
545  m_resources(&resources) ,
546  m_reopen_timeout(reopen_timeout)
547 {
548  // add configured channels
549  G::StringArray list = m_resources->channels() ;
550  for( G::StringArray::iterator p = list.begin() ; p != list.end() ; ++p )
551  {
552  addChannel( *p , true/*throw*/ ) ;
553  G_LOG( "Gv::HttpServerSources::refresh: channel _" << (m_list.size()-1U) << "=[" << *p << "]" ) ;
554  }
555 }
556 
558  m_converter(converter) ,
559  m_resources(nullptr) ,
560  m_reopen_timeout(0U)
561 {
562  G_DEBUG( "Gv::HttpServerSources::addSource: adding non-channel source [" << source.name() << "]" ) ;
563  m_list.push_back( Pair(&source,nullptr) ) ;
564 }
565 
567 {
568  return m_converter ;
569 }
570 
572 {
573  typedef std::vector<Pair> List ;
574  for( List::iterator p = m_list.begin() ; p != m_list.end() ; ++p )
575  delete (*p).second ;
576 }
577 
578 bool Gv::HttpServerSources::valid( const std::string & url_path )
579 {
580  return m_resources == nullptr || m_resources->empty() || m_resources->channelResource(url_path) ;
581 }
582 
583 bool Gv::HttpServerSources::select( const std::string & url_path , HttpServerSource & source_holder )
584 {
585  G_ASSERT( valid(url_path) ) ;
586 
587  // update the "--channel=*" list
588  //
589  if( m_resources != nullptr && m_resources->anyChannel() )
590  {
591  G::StringArray channels = G::Publisher::list() ;
592  for( G::StringArray::iterator p = channels.begin() ; p != channels.end() ; ++p )
593  {
594  Pair pair = findByName( *p ) ;
595  if( pair.first == nullptr )
596  {
597  if( addChannel( *p , false/*throw*/ ) )
598  G_LOG( "Gv::HttpServerSources::refresh: adding channel " << (m_list.size()-1U) << "=[" << *p << "]" ) ;
599  }
600  }
601  }
602 
603  // find the source
604  //
605  Pair pair( nullptr , nullptr ) ; // ImageInputSource, HttpServerInput
606  if( m_resources == nullptr || m_resources->empty() )
607  {
608  if( m_list.empty() ) throw std::runtime_error( "no sources configured" ) ;
609  std::string source_name = G::Path(url_path).basename() ;
610  pair = findByName( source_name ) ;
611  if( pair.first == nullptr )
612  pair = m_list.front() ; // _0
613  }
614  else
615  {
616  std::string channel_name = m_resources->channelName( url_path ) ;
617  if( !channel_name.empty() && G::Str::isUInt(channel_name) )
618  {
619  size_t channel_number = G::Str::toUInt( channel_name ) ;
620  pair = findByNumber( channel_number ) ;
621  }
622  else
623  {
624  std::string channel_name = m_resources->channelName( url_path ) ;
625  pair = findByName( channel_name ) ;
626  }
627  }
628 
629  // select it
630  //
631  if( pair.second != nullptr ) pair.second->start() ;
632  return source_holder.set( pair.first , pair.second?pair.second->info():std::string() ) ;
633 }
634 
635 bool Gv::HttpServerSources::addChannel( const std::string & channel_name , bool do_throw )
636 {
637  try
638  {
639  HttpServerInput * p = new HttpServerInput( m_converter , channel_name , m_reopen_timeout ) ;
640  m_list.push_back( Pair(p,p) ) ;
641  return true ;
642  }
643  catch( std::exception & ) // esp. G::PublisherError
644  {
645  G_DEBUG( "Gv::HttpServerSources::addChannel: invalid channel [" << channel_name << "]" ) ;
646  if( do_throw ) throw ;
647  return false ;
648  }
649 }
650 
651 Gv::HttpServerSources::Pair Gv::HttpServerSources::findByName( const std::string & source_name )
652 {
653  typedef std::vector<Pair> List ;
654  for( List::iterator p = m_list.begin() ; p != m_list.end() ; ++p )
655  {
656  ImageInputSource * source = (*p).first ;
657  if( source->name() == source_name )
658  return *p ;
659  }
660  return Pair( nullptr , nullptr ) ;
661 }
662 
663 Gv::HttpServerSources::Pair Gv::HttpServerSources::findByNumber( size_t channel_number )
664 {
665  if( channel_number < m_list.size() )
666  return m_list.at( channel_number ) ;
667  else
668  return Pair( nullptr , nullptr ) ;
669 }
670 
671 // ==
672 
674  m_handler(handler) ,
675  m_source(nullptr)
676 {
677 }
678 
680 {
681  if( m_source != nullptr )
682  m_source->removeImageInputHandler( m_handler ) ;
683 }
684 
685 std::string Gv::HttpServerSource::name() const
686 {
687  return m_source == nullptr ? std::string() : m_source->name() ;
688 }
689 
690 std::string Gv::HttpServerSource::info() const
691 {
692  return m_info ;
693 }
694 
696 {
697  if( m_source != nullptr )
698  m_source->resend( m_handler ) ;
699 }
700 
702 {
703  return m_source ;
704 }
705 
706 bool Gv::HttpServerSource::set( ImageInputSource * source , const std::string & info )
707 {
708  bool new_source = m_source != source ;
709  if( new_source )
710  {
711  if( m_source != nullptr )
712  m_source->removeImageInputHandler( m_handler ) ;
713  m_source = source ;
714  m_info = info ;
715  if( m_source != nullptr )
716  m_source->addImageInputHandler( m_handler ) ;
717  }
718  return new_source ;
719 }
720 
721 /// \file gvhttpserver.cpp
std::string str() const
Returns the path string.
Definition: gpath.cpp:290
unsigned int refresh() const
Returns the value for the http refresh header.
A subsecond-resolution timestamp based on a time_t.
Definition: gdatetime.h:39
static std::string printable(const std::string &in, char escape= '\\')
Returns a printable represention of the given input string.
Definition: gstr.cpp:663
void setDirectory(const G::Path &)
Sets a directory for file resources.
std::string channelName(const G::Path &url_path) const
Returns the channel name for the given channel-like url path.
bool specialResource(const G::Path &url_path) const
Returns true if the url path is for a special resource (eg. "/__").
void addImageInputHandler(ImageInputHandler &)
Adds a handler for image callbacks.
bool set(ImageInputSource *, const std::string &info)
Sets the source pointer. Used by Gv::HttpServerSources.
~HttpServerSource()
Destructor.
std::string basename() const
Returns the rightmost part of the path, ignoring "." parts.
Definition: gpath.cpp:310
void removeImageInputHandler(ImageInputHandler &)
Removes a handler for image callbacks.
bool streaming() const
Returns true if streaming using multipart/x-mixed-replace.
Synopsis:
HttpServerInput(Gr::ImageConverter &, const std::string &channel_name, unsigned int reopen_timeout)
Constructor taking a channel name.
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:55
GNet::Address gateway() const
Returns the gateway network address, or the default address if none.
static std::vector< std::string > list(std::vector< std::string > *others=nullptr)
Returns a list of channel names.
Definition: gpublisher.cpp:288
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstrings.h:33
std::string type() const
Returns the required content-type.
A class which acquires the process's special privileges on construction and releases them on destruct...
Definition: groot.h:49
void resend()
Calls resend() on the source.
virtual void dropRead(Descriptor fd)=0
Removes the given event source descriptor from the list of read sources.
virtual ~HttpServerInput()
Destructor.
A class for reading images from a publication channel and distributing them to multiple client object...
Definition: gvimageinput.h:168
A callback interface for Gv::ImageInputSource.
Definition: gvimageinput.h:84
std::string extension() const
Returns the path's basename extension, ie.
Definition: gpath.cpp:373
bool valid(const std::string &url_path)
Returns true if the given url path looks like it is for an input-source rather than a file...
A simple parser for URLs.
Definition: gurl.h:42
void addChannelAny()
Adds the wildcard channel.
Gr::ImageConverter & converter()
Returns the image-converter reference, as passed in to the constructor.
A class that encapsulates a network file descriptor and hides knowledge of its o/s-spefific error val...
Definition: gdescriptor.h:37
std::string parameter(std::string key, std::string default_=std::string()) const
Returns the decode()d value of the named parameter, or a default value.
Definition: gurl.cpp:213
std::string info() const
Returns information on the channel publisher, or the empty string for non-channel sources...
bool fileResource(const G::Path &url_path) const
Returns true if the url path is for a file (eg. "/index.html").
void init(unsigned int idle_timeout, unsigned int first_image_timeout, G::EpochTime repeat_timeout, unsigned int refresh_header, const GNet::Address &gateway, bool more_verbose)
Initialises the configuration from command-line parameters.
bool quick() const
Returns true if requesting the most-recent data from the channel rather than waiting for the next upd...
bool has(const std::string &key) const
Returns true if the named parameter is present.
Definition: gurl.cpp:208
unsigned int idleTimeout() const
Returns the connection idle timeout.
std::vector< std::string > channels() const
Returns a list of added channel names.
A base class for distributing incoming images to multiple client objects, supporting some simple imag...
Definition: gvimageinput.h:116
static unsigned int toUInt(const std::string &s)
Converts string 's' to an unsigned int.
Definition: gstr.cpp:450
virtual void addRead(Descriptor fd, EventHandler &handler)=0
Adds the given event source descriptor and associated handler to the read list.
HttpServerConfig()
Default constructor for reasonable default values.
std::string fileResourcePath(const G::Path &url_path) const
Returns the file-system path for the given url path, or the empty string if there is no matching reso...
bool empty() const
Returns true if just default-constructed with no "add" or "set" methods called.
std::string fileResourceType(const G::Path &url_path) const
Returns the content-type path for the given url path, or the empty string if there is no matching res...
bool moreVerbose() const
Returns true for more verbosity.
void addFileAny()
Allow any file in the directory.
bool isAbsolute() const
Returns !isRelative().
Definition: gpath.cpp:300
Map pmap() const
Returns the decode()d parameters as a multimap.
Definition: gurl.cpp:176
void addFileType(const G::Path &, const std::string &type)
Adds a filename-to-type mapping that overrides the extension mapping.
StringArray split() const
Spits the path into a list of component parts (ignoring "." parts unless the whole path is "...
Definition: gpath.cpp:382
Used by a ImageInputHandler-derived object to hold a ImageInputSource pointer.
Definition: gvhttpserver.h:79
G::EpochTime imageRepeatTimeout() const
Returns the repeat timeout.
Path collapsed() const
Returns the path with "foo/.." and "." parts removed, so far as is possible without changing the mean...
Definition: gpath.cpp:415
std::string setDefault(const std::string &)
Sets the default resource. Returns a warning string.
An ImageInput class that integrates with the event loop, with automatic re-opening if the channel goe...
Definition: gvhttpserver.h:48
bool anyChannel() const
Returns true if addChannelAny() called.
HttpServerResources()
Default constructor.
static std::string guessType(const G::Path &path)
Returns a probable content-type based on the filename, or the empty string.
std::pair< std::string, std::string > fileResourcePair(const G::Path &url_path) const
Returns fileResourcePath() and fileResourceType() as a pair.
static std::string join(const std::string &sep, const StringArray &strings)
Concatenates an array of strings.
Definition: gstr.cpp:972
std::string name() const
Returns the source name.
~HttpServerSources()
Destructor.
A configuration structure for resources that Gv::HttpServerPeer makes available.
Definition: gvhttpserver.h:169
unsigned int firstImageTimeout() const
Returns the first-image timeout.
An image format converter that can convert to and from the raw and jpeg formats (only), with scaling and monochrome options.
bool select(const std::string &url_path, HttpServerSource &)
Looks up the required input source and deposits its pointer into the supplied holder.
static bool isUInt(const std::string &s)
Returns true if the string can be converted into an unsigned integer without throwing an exception...
Definition: gstr.cpp:266
std::string addFile(const G::Path &)
Adds a file resource.
int scale() const
Returns the required scale factor.
HttpServerSource(ImageInputHandler &)
Constructor.
void addChannel(const std::string &channel_name)
Adds a channel resource.
A Path object represents a file system path.
Definition: gpath.h:72
std::string name() const
Returns the source name, as passed to the constructor.
static Path join(const StringArray &parts)
Builds a path from a set of parts.
Definition: gpath.cpp:390
static EventLoop & instance()
Returns a reference to an instance of the class, if any.
Definition: geventloop.cpp:43
bool monochrome() const
Returns the monochrome flag.
ImageInputSource * get()
Returns the source pointer.
bool channelResource(const G::Path &url_path) const
Returns true if the url path is for a channel (eg. "/_foo").
void log() const
Emits diagnostic logging for the configured resources.
HttpServerSources(Gr::ImageConverter &, const HttpServerResources &, unsigned int channel_reopen_timeout)
Constructor.
static void splitIntoFields(const std::string &in, StringArray &out, const std::string &seperators, char escape= '\0', bool remove_escapes=true)
Splits the string into fields.
Definition: gstr.cpp:921
void start()
Starts the input.