2002-09-24 06:08:50 +08:00
//
2002-12-10 21:21:41 +08:00
// ZoneMinder Streaming Server, $Date$, $Revision$
2008-07-25 17:33:23 +08:00
// Copyright (C) 2001-2008 Philip Coombes
2002-09-24 06:08:50 +08:00
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
2007-08-30 02:11:09 +08:00
# include <sys/ipc.h>
# include <sys/msg.h>
2002-09-16 17:19:24 +08:00
# include "zm.h"
2003-03-26 20:00:16 +08:00
# include "zm_db.h"
2005-01-19 09:50:24 +08:00
# include "zm_user.h"
2006-04-05 20:22:27 +08:00
# include "zm_signal.h"
2003-03-26 20:00:16 +08:00
# include "zm_monitor.h"
2002-09-16 17:19:24 +08:00
2005-01-19 09:50:24 +08:00
bool ValidateAccess ( User * user , int mon_id )
2004-12-30 02:03:13 +08:00
{
2016-04-04 22:11:48 +08:00
bool allowed = true ;
2004-12-30 02:03:13 +08:00
2016-04-04 22:11:48 +08:00
if ( mon_id > 0 )
{
if ( user - > getStream ( ) < User : : PERM_VIEW )
allowed = false ;
if ( ! user - > canAccess ( mon_id ) )
allowed = false ;
}
else
{
if ( user - > getEvents ( ) < User : : PERM_VIEW )
allowed = false ;
}
if ( ! allowed )
{
Error ( " Error, insufficient privileges for requested action " ) ;
exit ( - 1 ) ;
}
return ( allowed ) ;
2004-12-30 02:03:13 +08:00
}
2004-03-15 02:16:15 +08:00
int main ( int argc , const char * argv [ ] )
2002-09-16 17:19:24 +08:00
{
2016-04-04 22:11:48 +08:00
self = argv [ 0 ] ;
2013-10-07 07:37:50 +08:00
2016-04-04 22:11:48 +08:00
srand ( getpid ( ) * time ( 0 ) ) ;
2009-04-15 04:18:57 +08:00
2016-04-04 22:11:48 +08:00
enum { ZMS_MONITOR , ZMS_EVENT } source = ZMS_MONITOR ;
enum { ZMS_JPEG , ZMS_MPEG , ZMS_RAW , ZMS_ZIP , ZMS_SINGLE } mode = ZMS_JPEG ;
char format [ 32 ] = " " ;
int monitor_id = 0 ;
time_t event_time = 0 ;
int event_id = 0 ;
2016-04-28 21:20:56 +08:00
unsigned int frame_id = 1 ;
2016-04-04 22:11:48 +08:00
unsigned int scale = 100 ;
unsigned int rate = 100 ;
double maxfps = 10.0 ;
unsigned int bitrate = 100000 ;
unsigned int ttl = 0 ;
EventStream : : StreamMode replay = EventStream : : MODE_SINGLE ;
char username [ 64 ] = " " ;
char password [ 64 ] = " " ;
char auth [ 64 ] = " " ;
unsigned int connkey = 0 ;
unsigned int playback_buffer = 0 ;
2003-06-09 04:24:52 +08:00
2016-04-04 22:11:48 +08:00
bool nph = false ;
const char * basename = strrchr ( argv [ 0 ] , ' / ' ) ;
if ( basename ) //if we found a / lets skip past it
basename + + ;
else //argv[0] will not always contain the full path, but rather just the script name
basename = argv [ 0 ] ;
const char * nph_prefix = " nph- " ;
if ( basename & & ! strncmp ( basename , nph_prefix , strlen ( nph_prefix ) ) )
{
nph = true ;
}
zmLoadConfig ( ) ;
2004-12-29 00:46:48 +08:00
2016-04-04 22:11:48 +08:00
logInit ( " zms " ) ;
ssedetect ( ) ;
2011-06-21 17:19:10 +08:00
2016-04-04 22:11:48 +08:00
zmSetDefaultTermHandler ( ) ;
zmSetDefaultDieHandler ( ) ;
2006-04-05 20:22:27 +08:00
2016-04-04 22:11:48 +08:00
const char * query = getenv ( " QUERY_STRING " ) ;
if ( query )
{
Debug ( 1 , " Query: %s " , query ) ;
char temp_query [ 1024 ] ;
strncpy ( temp_query , query , sizeof ( temp_query ) ) ;
char * q_ptr = temp_query ;
char * parms [ 16 ] ; // Shouldn't be more than this
int parm_no = 0 ;
while ( ( parm_no < 16 ) & & ( parms [ parm_no ] = strtok ( q_ptr , " & " ) ) )
{
parm_no + + ;
q_ptr = NULL ;
}
for ( int p = 0 ; p < parm_no ; p + + )
{
char * name = strtok ( parms [ p ] , " = " ) ;
char * value = strtok ( NULL , " = " ) ;
if ( ! value )
value = ( char * ) " " ;
if ( ! strcmp ( name , " source " ) )
{
source = ! strcmp ( value , " event " ) ? ZMS_EVENT : ZMS_MONITOR ;
}
else if ( ! strcmp ( name , " mode " ) )
{
mode = ! strcmp ( value , " jpeg " ) ? ZMS_JPEG : ZMS_MPEG ;
mode = ! strcmp ( value , " raw " ) ? ZMS_RAW : mode ;
mode = ! strcmp ( value , " zip " ) ? ZMS_ZIP : mode ;
mode = ! strcmp ( value , " single " ) ? ZMS_SINGLE : mode ;
}
else if ( ! strcmp ( name , " format " ) )
strncpy ( format , value , sizeof ( format ) ) ;
else if ( ! strcmp ( name , " monitor " ) )
monitor_id = atoi ( value ) ;
else if ( ! strcmp ( name , " time " ) )
event_time = atoi ( value ) ;
else if ( ! strcmp ( name , " event " ) )
event_id = strtoull ( value , ( char * * ) NULL , 10 ) ;
else if ( ! strcmp ( name , " frame " ) )
frame_id = strtoull ( value , ( char * * ) NULL , 10 ) ;
else if ( ! strcmp ( name , " scale " ) )
scale = atoi ( value ) ;
else if ( ! strcmp ( name , " rate " ) )
rate = atoi ( value ) ;
else if ( ! strcmp ( name , " maxfps " ) )
maxfps = atof ( value ) ;
else if ( ! strcmp ( name , " bitrate " ) )
bitrate = atoi ( value ) ;
else if ( ! strcmp ( name , " ttl " ) )
ttl = atoi ( value ) ;
else if ( ! strcmp ( name , " replay " ) )
{
replay = ! strcmp ( value , " gapless " ) ? EventStream : : MODE_ALL_GAPLESS : EventStream : : MODE_SINGLE ;
replay = ! strcmp ( value , " all " ) ? EventStream : : MODE_ALL : replay ;
}
else if ( ! strcmp ( name , " connkey " ) )
connkey = atoi ( value ) ;
else if ( ! strcmp ( name , " buffer " ) )
playback_buffer = atoi ( value ) ;
else if ( config . opt_use_auth )
{
if ( strcmp ( config . auth_relay , " none " ) = = 0 )
2007-08-30 02:11:09 +08:00
{
2016-04-04 22:11:48 +08:00
if ( ! strcmp ( name , " user " ) )
{
strncpy ( username , value , sizeof ( username ) ) ;
}
2007-08-30 02:11:09 +08:00
}
else
{
2016-04-04 22:11:48 +08:00
//if ( strcmp( config.auth_relay, "hashed" ) == 0 )
{
if ( ! strcmp ( name , " auth " ) )
{
strncpy ( auth , value , sizeof ( auth ) ) ;
}
}
//else if ( strcmp( config.auth_relay, "plain" ) == 0 )
{
if ( ! strcmp ( name , " user " ) )
{
strncpy ( username , value , sizeof ( username ) ) ;
}
if ( ! strcmp ( name , " pass " ) )
{
strncpy ( password , value , sizeof ( password ) ) ;
}
}
2007-08-30 02:11:09 +08:00
}
2016-04-04 22:11:48 +08:00
}
}
}
if ( config . opt_use_auth )
{
User * user = 0 ;
if ( strcmp ( config . auth_relay , " none " ) = = 0 )
2007-08-30 02:11:09 +08:00
{
2016-04-04 22:11:48 +08:00
if ( * username )
{
user = zmLoadUser ( username ) ;
}
}
else
{
//if ( strcmp( config.auth_relay, "hashed" ) == 0 )
{
if ( * auth )
2007-08-30 02:11:09 +08:00
{
2016-04-04 22:11:48 +08:00
user = zmLoadAuthUser ( auth , config . auth_hash_ips ) ;
2007-08-30 02:11:09 +08:00
}
2016-04-04 22:11:48 +08:00
}
//else if ( strcmp( config.auth_relay, "plain" ) == 0 )
{
if ( * username & & * password )
2007-08-30 02:11:09 +08:00
{
2016-04-04 22:11:48 +08:00
user = zmLoadUser ( username , password ) ;
2007-08-30 02:11:09 +08:00
}
2016-04-04 22:11:48 +08:00
}
}
if ( ! user )
{
Error ( " Unable to authenticate user " ) ;
logTerm ( ) ;
zmDbClose ( ) ;
return ( - 1 ) ;
}
ValidateAccess ( user , monitor_id ) ;
}
setbuf ( stdout , 0 ) ;
if ( nph )
{
fprintf ( stdout , " HTTP/1.0 200 OK \r \n " ) ;
}
fprintf ( stdout , " Server: ZoneMinder Video Server/%s \r \n " , ZM_VERSION ) ;
time_t now = time ( 0 ) ;
char date_string [ 64 ] ;
strftime ( date_string , sizeof ( date_string ) - 1 , " %a, %d %b %Y %H:%M:%S GMT " , gmtime ( & now ) ) ;
fprintf ( stdout , " Expires: Mon, 26 Jul 1997 05:00:00 GMT \r \n " ) ;
fprintf ( stdout , " Last-Modified: %s \r \n " , date_string ) ;
fprintf ( stdout , " Cache-Control: no-store, no-cache, must-revalidate \r \n " ) ;
fprintf ( stdout , " Cache-Control: post-check=0, pre-check=0 \r \n " ) ;
fprintf ( stdout , " Pragma: no-cache \r \n " ) ;
// Removed as causing more problems than it fixed.
//if ( !nph )
//{
//fprintf( stdout, "Content-Length: 0\r\n");
//}
if ( source = = ZMS_MONITOR )
{
MonitorStream stream ;
stream . setStreamScale ( scale ) ;
stream . setStreamReplayRate ( rate ) ;
stream . setStreamMaxFPS ( maxfps ) ;
stream . setStreamTTL ( ttl ) ;
stream . setStreamQueue ( connkey ) ;
stream . setStreamBuffer ( playback_buffer ) ;
if ( ! stream . setStreamStart ( monitor_id ) ) {
Error ( " Unable to connect to zmc process for monitor %d " , monitor_id ) ;
fprintf ( stderr , " Unable to connect to zmc process. Please ensure that it is running. " ) ;
logTerm ( ) ;
zmDbClose ( ) ;
return ( - 1 ) ;
}
if ( mode = = ZMS_JPEG )
{
stream . setStreamType ( MonitorStream : : STREAM_JPEG ) ;
}
else if ( mode = = ZMS_RAW )
{
stream . setStreamType ( MonitorStream : : STREAM_RAW ) ;
}
else if ( mode = = ZMS_ZIP )
{
stream . setStreamType ( MonitorStream : : STREAM_ZIP ) ;
}
else if ( mode = = ZMS_SINGLE )
{
stream . setStreamType ( MonitorStream : : STREAM_SINGLE ) ;
}
else
{
2007-08-30 02:11:09 +08:00
# if HAVE_LIBAVCODEC
2016-04-04 22:11:48 +08:00
stream . setStreamFormat ( format ) ;
stream . setStreamBitrate ( bitrate ) ;
stream . setStreamType ( MonitorStream : : STREAM_MPEG ) ;
2007-08-30 02:11:09 +08:00
# else // HAVE_LIBAVCODEC
2016-04-04 22:11:48 +08:00
Error ( " MPEG streaming of '%s' attempted while disabled " , query ) ;
fprintf ( stderr , " MPEG streaming is disabled. \n You should configure with the --with-ffmpeg option and rebuild to use this functionality. \n " ) ;
logTerm ( ) ;
zmDbClose ( ) ;
return ( - 1 ) ;
# endif // HAVE_LIBAVCODEC
}
stream . runStream ( ) ;
}
else if ( source = = ZMS_EVENT )
{
EventStream stream ;
stream . setStreamScale ( scale ) ;
stream . setStreamReplayRate ( rate ) ;
stream . setStreamMaxFPS ( maxfps ) ;
stream . setStreamMode ( replay ) ;
stream . setStreamQueue ( connkey ) ;
if ( monitor_id & & event_time )
{
stream . setStreamStart ( monitor_id , event_time ) ;
}
else
{
stream . setStreamStart ( event_id , frame_id ) ;
}
if ( mode = = ZMS_JPEG )
{
stream . setStreamType ( EventStream : : STREAM_JPEG ) ;
}
else
{
# if HAVE_LIBAVCODEC
stream . setStreamFormat ( format ) ;
stream . setStreamBitrate ( bitrate ) ;
stream . setStreamType ( EventStream : : STREAM_MPEG ) ;
# else // HAVE_LIBAVCODEC
Error ( " MPEG streaming of '%s' attempted while disabled " , query ) ;
fprintf ( stderr , " MPEG streaming is disabled. \n You should ensure the ffmpeg libraries are installed and detected and rebuild to use this functionality. \n " ) ;
logTerm ( ) ;
zmDbClose ( ) ;
return ( - 1 ) ;
2007-08-30 02:11:09 +08:00
# endif // HAVE_LIBAVCODEC
}
2016-04-04 22:11:48 +08:00
stream . runStream ( ) ;
}
2014-11-15 05:17:44 +08:00
2016-04-04 22:11:48 +08:00
logTerm ( ) ;
zmDbClose ( ) ;
2014-11-15 05:17:44 +08:00
2016-04-04 22:11:48 +08:00
return ( 0 ) ;
2002-09-16 17:19:24 +08:00
}