Exemple #1
0
int main( int argc, char *argv[] )
{
	self = argv[0];

	srand( getpid() * time( 0 ) );

	const char *device = "";
	const char *protocol = "";
	const char *host = "";
	const char *port = "";
	const char *path = "";
	const char *file = "";
	int monitor_id = -1;

	static struct option long_options[] = {
		{"device", 1, 0, 'd'},
		{"protocol", 1, 0, 'r'},
		{"host", 1, 0, 'H'},
		{"port", 1, 0, 'P'},
	 	{"path", 1, 0, 'p'},
	 	{"file", 1, 0, 'f'},
		{"monitor", 1, 0, 'm'},
		{"help", 0, 0, 'h'},
		{"version", 0, 0, 'v'},
		{0, 0, 0, 0}
	};

	while (1)
	{
		int option_index = 0;

		int c = getopt_long (argc, argv, "d:H:P:p:f:m:h:v", long_options, &option_index);
		if (c == -1)
		{
			break;
		}

		switch (c)
		{
			case 'd':
				device = optarg;
				break;
			case 'H':
				host = optarg;
				break;
			case 'P':
				port = optarg;
				break;
			case 'p':
				path = optarg;
				break;
			case 'f':
				file = optarg;
				break;
			case 'm':
				monitor_id = atoi(optarg);
				break;
			case 'h':
			case '?':
				Usage();
				break;
			case 'v':
				std::cout << ZM_VERSION << "\n";
				exit(0);
			default:
				//fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
				break;
		}
	}

	if (optind < argc)
	{
		fprintf( stderr, "Extraneous options, " );
		while (optind < argc)
			printf ("%s ", argv[optind++]);
		printf ("\n");
		Usage();
	}

	int modes = ( device[0]?1:0 + host[0]?1:0 + file[0]?1:0 + (monitor_id>0?1:0) );
	if ( modes > 1 )
	{
		fprintf( stderr, "Only one of device, host/port/path, file or monitor id allowed\n" );
		Usage();
		exit( 0 );
	}

	if ( modes < 1 )
	{
		fprintf( stderr, "One of device, host/port/path, file or monitor id must be specified\n" );
		Usage();
		exit( 0 );
	}

	char log_id_string[32] = "";
	if ( device[0] )
	{
		const char *slash_ptr = strrchr( device, '/' );
		snprintf( log_id_string, sizeof(log_id_string), "zmc_d%s", slash_ptr?slash_ptr+1:device );
	}
	else if ( host[0] )
	{
		snprintf( log_id_string, sizeof(log_id_string), "zmc_h%s", host );
	}
	else if ( file[0] )
	{
		const char *slash_ptr = strrchr( file, '/' );
		snprintf( log_id_string, sizeof(log_id_string), "zmc_f%s", slash_ptr?slash_ptr+1:file );
	}
	else
	{
		snprintf( log_id_string, sizeof(log_id_string), "zmc_m%d", monitor_id );
	}

	zmLoadConfig();

	logInit( log_id_string );
	
	ssedetect();

	Monitor **monitors = 0;
	int n_monitors = 0;
#if ZM_HAS_V4L
	if ( device[0] )
	{
		n_monitors = Monitor::LoadLocalMonitors( device, monitors, Monitor::CAPTURE );
	}
	else
#endif // ZM_HAS_V4L
    if ( host[0] )
	{
		if ( !port )
			port = "80";
		n_monitors = Monitor::LoadRemoteMonitors( protocol, host, port, path, monitors, Monitor::CAPTURE );
	}
	else if ( file[0] )
	{
		n_monitors = Monitor::LoadFileMonitors( file, monitors, Monitor::CAPTURE );
	}
	else
	{
		Monitor *monitor = Monitor::Load( monitor_id, true, Monitor::CAPTURE );
		if ( monitor )
		{
			monitors = new Monitor *[1];
			monitors[0] = monitor;
			n_monitors = 1;
		}
	}

	if ( !n_monitors )
	{
		Error( "No monitors found" );
		exit ( -1 );
	}

	Info( "Starting Capture version %s", ZM_VERSION );

	zmSetDefaultTermHandler();
	zmSetDefaultDieHandler();

	sigset_t block_set;
	sigemptyset( &block_set );

	sigaddset( &block_set, SIGUSR1 );
	sigaddset( &block_set, SIGUSR2 );

	if ( monitors[0]->PrimeCapture() < 0 )
	{
        Error( "Failed to prime capture of initial monitor" );
		exit( -1 );
	}

	long *capture_delays = new long[n_monitors];
	long *alarm_capture_delays = new long[n_monitors];
	long *next_delays = new long[n_monitors];
	struct timeval * last_capture_times = new struct timeval[n_monitors];
	for ( int i = 0; i < n_monitors; i++ )
	{
		last_capture_times[i].tv_sec = last_capture_times[i].tv_usec = 0;
		capture_delays[i] = monitors[i]->GetCaptureDelay();
		alarm_capture_delays[i] = monitors[i]->GetAlarmCaptureDelay();
	}

    int result = 0;
	struct timeval now;
	struct DeltaTimeval delta_time;
	while( !zm_terminate )
	{
		sigprocmask( SIG_BLOCK, &block_set, 0 );
		for ( int i = 0; i < n_monitors; i++ )
		{
			long min_delay = MAXINT;

			gettimeofday( &now, NULL );
			for ( int j = 0; j < n_monitors; j++ )
			{
				if ( last_capture_times[j].tv_sec )
				{
					DELTA_TIMEVAL( delta_time, now, last_capture_times[j], DT_PREC_3 );
					if ( monitors[i]->GetState() == Monitor::ALARM )
						next_delays[j] = alarm_capture_delays[j]-delta_time.delta;
					else
						next_delays[j] = capture_delays[j]-delta_time.delta;
					if ( next_delays[j] < 0 )
						next_delays[j] = 0;
				}
				else
				{
					next_delays[j] = 0;
				}
				if ( next_delays[j] <= min_delay )
				{
					min_delay = next_delays[j];
				}
			}

			if ( next_delays[i] <= min_delay || next_delays[i] <= 0 )
			{
				if ( monitors[i]->PreCapture() < 0 )
				{
                    Error( "Failed to pre-capture monitor %d %d (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors );
                    zm_terminate = true;
                    result = -1;
                    break;
				}
				if ( monitors[i]->Capture() < 0 )
				{
                    Error( "Failed to capture image from monitor %d %s (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors );
                    zm_terminate = true;
                    result = -1;
                    break;
				}
				if ( monitors[i]->PostCapture() < 0 )
				{
                    Error( "Failed to post-capture monitor %d %s (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors );
                    zm_terminate = true;
                    result = -1;
                    break;
				}

				if ( next_delays[i] > 0 )
				{
					gettimeofday( &now, NULL );
					DELTA_TIMEVAL( delta_time, now, last_capture_times[i], DT_PREC_3 );
					long sleep_time = next_delays[i]-delta_time.delta;
					if ( sleep_time > 0 )
					{
						usleep( sleep_time*(DT_MAXGRAN/DT_PREC_3) );
					}
				}
				gettimeofday( &(last_capture_times[i]), NULL );
			}
		}
		sigprocmask( SIG_UNBLOCK, &block_set, 0 );
	}
	for ( int i = 0; i < n_monitors; i++ )
	{
		delete monitors[i];
	}
	delete [] monitors;
	delete [] alarm_capture_delays;
	delete [] capture_delays;
	delete [] next_delays;
	delete [] last_capture_times;

	logTerm();
	zmDbClose();

	return( result );
}
Exemple #2
0
int main( int argc, char *argv[] )
{
  if ( access(ZM_CONFIG, R_OK) != 0 )
  {
    fprintf( stderr, "Can't open %s: %s\n", ZM_CONFIG, strerror(errno) );
    exit( -1 );
  }

  self = argv[0];

  srand( getpid() * time( 0 ) );

  static struct option long_options[] = {
    {"device", 2, 0, 'd'},
    {"monitor", 1, 0, 'm'},
    {"verbose", 0, 0, 'v'},
    {"image", 2, 0, 'i'},
    {"scale", 1, 0, 'S'},
    {"timestamp", 2, 0, 't'},
    {"state", 0, 0, 's'},
    {"brightness", 2, 0, 'B'},
    {"contrast", 2, 0, 'C'},
    {"hue", 2, 0, 'H'},
    {"contrast", 2, 0, 'O'},
    {"read_index", 0, 0, 'R'},
    {"write_index", 0, 0, 'W'},
    {"event", 0, 0, 'e'},
    {"fps", 0, 0, 'f'},
    {"zones", 2, 0, 'z'},
    {"alarm", 0, 0, 'a'},
    {"noalarm", 0, 0, 'n'},
    {"cancel", 0, 0, 'c'},
    {"reload", 0, 0, 'L'},
    {"enable", 0, 0, 'E'},
    {"disable", 0, 0, 'D'},
    {"suspend", 0, 0, 'u'},
    {"resume", 0, 0, 'r'},
    {"query", 0, 0, 'q'},
    {"username", 1, 0, 'U'},
    {"password", 1, 0, 'P'},
    {"auth", 1, 0, 'A'},
    {"version", 1, 0, 'V'},
    {"help", 0, 0, 'h'},
    {"list", 0, 0, 'l'},
    {0, 0, 0, 0}
  };

  const char *device = 0;
  int mon_id = 0;
  bool verbose = false;
  int function = ZMU_BOGUS;

  int image_idx = -1;
  int scale = -1;
  int brightness = -1;
  int contrast = -1;
  int hue = -1;
  int colour = -1;
  char *zoneString = 0;
  char *username = 0;
  char *password = 0;
  char *auth = 0;
#if ZM_HAS_V4L
#if ZM_HAS_V4L2
  int v4lVersion = 2;
#elif ZM_HAS_V4L1
  int v4lVersion = 1;
#endif // ZM_HAS_V4L2/1
#endif // ZM_HAS_V4L
  while (1)
  {
    int option_index = 0;

    int c = getopt_long (argc, argv, "d:m:vsEDLurwei::S:t::fz::ancqhlB::C::H::O::U:P:A:V:", long_options, &option_index);
    if (c == -1)
    {
      break;
    }

    switch (c)
    {
      case 'd':
        if ( optarg )
          device = optarg;
        break;
      case 'm':
        mon_id = atoi(optarg);
        break;
      case 'v':
        verbose = true;
        break;
      case 's':
        function |= ZMU_STATE;
        break;
      case 'i':
        function |= ZMU_IMAGE;
        if ( optarg )
          image_idx = atoi( optarg );
        break;
      case 'S':
        scale = atoi(optarg);
        break;
      case 't':
        function |= ZMU_TIME;
        if ( optarg )
          image_idx = atoi( optarg );
        break;
      case 'R':
        function |= ZMU_READ_IDX;
        break;
      case 'W':
        function |= ZMU_WRITE_IDX;
        break;
      case 'e':
        function |= ZMU_EVENT;
        break;
      case 'f':
        function |= ZMU_FPS;
        break;
      case 'z':
        function |= ZMU_ZONES;
        if ( optarg )
          zoneString = optarg;
        break;
      case 'a':
        function |= ZMU_ALARM;
        break;
      case 'n':
        function |= ZMU_NOALARM;
        break;
      case 'c':
        function |= ZMU_CANCEL;
        break;
      case 'L':
        function |= ZMU_RELOAD;
        break;
      case 'E':
        function |= ZMU_ENABLE;
        break;
      case 'D':
        function |= ZMU_DISABLE;
        break;
      case 'u':
        function |= ZMU_SUSPEND;
        break;
      case 'r':
        function |= ZMU_RESUME;
        break;
      case 'q':
        function |= ZMU_QUERY;
        break;
      case 'B':
        function |= ZMU_BRIGHTNESS;
        if ( optarg )
          brightness = atoi( optarg );
        break;
      case 'C':
        function |= ZMU_CONTRAST;
        if ( optarg )
          contrast = atoi( optarg );
        break;
      case 'H':
        function |= ZMU_HUE;
        if ( optarg )
          hue = atoi( optarg );
        break;
      case 'O':
        function |= ZMU_COLOUR;
        if ( optarg )
          colour = atoi( optarg );
        break;
      case 'U':
        username = optarg;
        break;
      case 'P':
        password = optarg;
        break;
      case 'A':
        auth = optarg;
        break;
#if ZM_HAS_V4L
      case 'V':
        v4lVersion = (atoi(optarg)==1)?1:2;
        break;
#endif // ZM_HAS_V4L
      case 'h':
        Usage( 0 );
        break;
      case 'l':
        function |= ZMU_LIST;
        break;
      case '?':
        Usage();
        break;
      default:
        //fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
        break;
    }
  }

  if (optind < argc)
  {
    fprintf( stderr, "Extraneous options, " );
    while (optind < argc)
      fprintf( stderr, "%s ", argv[optind++]);
    fprintf( stderr, "\n");
    Usage();
  }

  if ( device && !(function&ZMU_QUERY) )
  {
    fprintf( stderr, "Error, -d option cannot be used with this option\n" );
    Usage();
  }
  if ( scale != -1 && !(function&ZMU_IMAGE) )
  {
    fprintf( stderr, "Error, -S option cannot be used with this option\n" );
    Usage();
  }
  //printf( "Monitor %d, Function %d\n", mon_id, function );

  zmLoadConfig();

  logInit( "zmu" );

  zmSetDefaultTermHandler();
  zmSetDefaultDieHandler();

  User *user = 0;

  if ( config.opt_use_auth )
  {
    if ( strcmp( config.auth_relay, "none" ) == 0 )
    {
      if ( !username )
      {
        fprintf( stderr, "Error, username must be supplied\n" );
        exit( -1 );
      }

      if ( username )
      {
        user = zmLoadUser( username );
      }
    }
    else
    {
      if ( !(username && password) && !auth )
      {
        fprintf( stderr, "Error, username and password or auth string must be supplied\n" );
        exit( -1 );
      }

      //if ( strcmp( config.auth_relay, "hashed" ) == 0 )
      {
        if ( auth )
        {
          user = zmLoadAuthUser( auth, false );
        }
      }
      //else if ( strcmp( config.auth_relay, "plain" ) == 0 )
      {
        if ( username && password )
        {
          user = zmLoadUser( username, password );
        }
      }
    }
    if ( !user )
    {
      fprintf( stderr, "Error, unable to authenticate user\n" );
      exit( -1 );
    }
    ValidateAccess( user, mon_id, function );
  }
  

  if ( mon_id > 0 )
  {
    Monitor *monitor = Monitor::Load( mon_id, function&(ZMU_QUERY|ZMU_ZONES), Monitor::QUERY );
    if ( monitor )
    {
      if ( verbose )
      {
        printf( "Monitor %d(%s)\n", monitor->Id(), monitor->Name() );
      }
      if ( ! monitor->connect() ) {
        Error( "Can't connect to capture daemon: %d %s", monitor->Id(), monitor->Name() );
        exit( -1 );
      } 

      char separator = ' ';
      bool have_output = false;
      if ( function & ZMU_STATE )
      {
        Monitor::State state = monitor->GetState();
        if ( verbose )
          printf( "Current state: %s\n", state==Monitor::ALARM?"Alarm":(state==Monitor::ALERT?"Alert":"Idle") );
        else
        {
          if ( have_output ) printf( "%c", separator );
          printf( "%d", state );
          have_output = true;
        }
      }
      if ( function & ZMU_TIME )
      {
        struct timeval timestamp = monitor->GetTimestamp( image_idx );
        if ( verbose )
        {
          char timestamp_str[64] = "None";
          if ( timestamp.tv_sec )
            strftime( timestamp_str, sizeof(timestamp_str), "%Y-%m-%d %H:%M:%S", localtime( &timestamp.tv_sec ) );
          if ( image_idx == -1 )
            printf( "Time of last image capture: %s.%02ld\n", timestamp_str, timestamp.tv_usec/10000 );
          else
            printf( "Time of image %d capture: %s.%02ld\n", image_idx, timestamp_str, timestamp.tv_usec/10000 );
        }
        else
        {
          if ( have_output ) printf( "%c", separator );
          printf( "%ld.%02ld", timestamp.tv_sec, timestamp.tv_usec/10000 );
          have_output = true;
        }
      }
      if ( function & ZMU_READ_IDX )
      {
        if ( verbose )
          printf( "Last read index: %d\n", monitor->GetLastReadIndex() );
        else
        {
          if ( have_output ) printf( "%c", separator );
          printf( "%d", monitor->GetLastReadIndex() );
          have_output = true;
        }
      }
      if ( function & ZMU_WRITE_IDX )
      {
        if ( verbose )
          printf( "Last write index: %d\n", monitor->GetLastWriteIndex() );
        else
        {
          if ( have_output ) printf( "%c", separator );
          printf( "%d", monitor->GetLastWriteIndex() );
          have_output = true;
        }
      }
      if ( function & ZMU_EVENT )
      {
        if ( verbose )
          printf( "Last event id: %d\n", monitor->GetLastEvent() );
        else
        {
          if ( have_output ) printf( "%c", separator );
          printf( "%d", monitor->GetLastEvent() );
          have_output = true;
        }
      }
      if ( function & ZMU_FPS )
      {
        if ( verbose )
          printf( "Current capture rate: %.2f frames per second\n", monitor->GetFPS() );
        else
        {
          if ( have_output ) printf( "%c", separator );
          printf( "%.2f", monitor->GetFPS() );
          have_output = true;
        }
      }
      if ( function & ZMU_IMAGE )
      {
        if ( verbose )
        {
          if ( image_idx == -1 )
            printf( "Dumping last image captured to Monitor%d.jpg", monitor->Id() );
          else
            printf( "Dumping buffer image %d to Monitor%d.jpg", image_idx, monitor->Id() );
          if ( scale != -1 )
            printf( ", scaling by %d%%", scale );
          printf( "\n" );
        }
        monitor->GetImage( image_idx, scale>0?scale:100 );
      }
      if ( function & ZMU_ZONES )
      {
        if ( verbose )
          printf( "Dumping zone image to Zones%d.jpg\n", monitor->Id() );
        monitor->DumpZoneImage( zoneString );
      }
      if ( function & ZMU_ALARM )
      {
        if ( verbose )
          printf( "Forcing alarm on\n" );
        monitor->ForceAlarmOn( config.forced_alarm_score, "Forced Web" );
      }
      if ( function & ZMU_NOALARM )
      {
        if ( verbose )
          printf( "Forcing alarm off\n" );
        monitor->ForceAlarmOff();
      }
      if ( function & ZMU_CANCEL )
      {
        if ( verbose )
          printf( "Cancelling forced alarm on/off\n" );
        monitor->CancelForced();
      }
      if ( function & ZMU_RELOAD )
      {
        if ( verbose )
          printf( "Reloading monitor settings\n" );
        monitor->actionReload();
      }
      if ( function & ZMU_ENABLE )
      {
        if ( verbose )
          printf( "Enabling event generation\n" );
        monitor->actionEnable();
      }
      if ( function & ZMU_DISABLE )
      {
        if ( verbose )
          printf( "Disabling event generation\n" );
        monitor->actionDisable();
      }
      if ( function & ZMU_SUSPEND )
      {
        if ( verbose )
          printf( "Suspending event generation\n" );
        monitor->actionSuspend();
      }
      if ( function & ZMU_RESUME )
      {
        if ( verbose )
          printf( "Resuming event generation\n" );
        monitor->actionResume();
      }
      if ( function & ZMU_QUERY )
      {
        char monString[16382] = "";
        monitor->DumpSettings( monString, verbose );
        printf( "%s\n", monString );
      }
      if ( function & ZMU_BRIGHTNESS )
      {
        if ( verbose )
        {
          if ( brightness >= 0 )
            printf( "New brightness: %d\n", monitor->actionBrightness( brightness ) );
          else
            printf( "Current brightness: %d\n", monitor->actionBrightness() );
        }
        else
        {
          if ( have_output ) printf( "%c", separator );
          if ( brightness >= 0 )
            printf( "%d", monitor->actionBrightness( brightness ) );
          else
            printf( "%d", monitor->actionBrightness() );
          have_output = true;
        }
      }
      if ( function & ZMU_CONTRAST )
      {
        if ( verbose )
        {
          if ( contrast >= 0 )
            printf( "New brightness: %d\n", monitor->actionContrast( contrast ) );
          else
            printf( "Current contrast: %d\n", monitor->actionContrast() );
        }
        else
        {
          if ( have_output ) printf( "%c", separator );
          if ( contrast >= 0 )
            printf( "%d", monitor->actionContrast( contrast ) );
          else
            printf( "%d", monitor->actionContrast() );
          have_output = true;
        }
      }
      if ( function & ZMU_HUE )
      {
        if ( verbose )
        {
          if ( hue >= 0 )
            printf( "New hue: %d\n", monitor->actionHue( hue ) );
          else
            printf( "Current hue: %d\n", monitor->actionHue() );
        }
        else
        {
          if ( have_output ) printf( "%c", separator );
          if ( hue >= 0 )
            printf( "%d", monitor->actionHue( hue ) );
          else
            printf( "%d", monitor->actionHue() );
          have_output = true;
        }
      }
      if ( function & ZMU_COLOUR )
      {
        if ( verbose )
        {
          if ( colour >= 0 )
            printf( "New colour: %d\n", monitor->actionColour( colour ) );
          else
            printf( "Current colour: %d\n", monitor->actionColour() );
        }
        else
        {
          if ( have_output ) printf( "%c", separator );
          if ( colour >= 0 )
            printf( "%d", monitor->actionColour( colour ) );
          else
            printf( "%d", monitor->actionColour() );
          have_output = true;
        }
      }
      if ( have_output )
      {
        printf( "\n" );
      }
      if ( !function )
      {
        Usage();
      }
      delete monitor;
    }
    else
    {
      fprintf( stderr, "Error, invalid monitor id %d\n", mon_id );
      exit( -1 );
    }
  }
  else
  {
    if ( function & ZMU_QUERY )
    {
#if ZM_HAS_V4L
      char vidString[0x10000] = "";
      bool ok = LocalCamera::GetCurrentSettings( device, vidString, v4lVersion, verbose );
      printf( "%s", vidString );
      exit( ok?0:-1 );
#else // ZM_HAS_V4L
      fprintf( stderr, "Error, video4linux is required for device querying\n" );
      exit( -1 );
#endif // ZM_HAS_V4L
    }

    if ( function & ZMU_LIST )
    {
      std::string sql = "select Id, Function+0 from Monitors";
      if ( !verbose )
      {
        sql += "where Function != 'None'";
      }
      sql += " order by Id asc";

      if ( mysql_query( &dbconn, sql.c_str() ) )
      {
        Error( "Can't run query: %s", mysql_error( &dbconn ) );
        exit( mysql_errno( &dbconn ) );
      }

      MYSQL_RES *result = mysql_store_result( &dbconn );
      if ( !result )
      {
        Error( "Can't use query result: %s", mysql_error( &dbconn ) );
        exit( mysql_errno( &dbconn ) );
      }
      int n_monitors = mysql_num_rows( result );
      Debug( 1, "Got %d monitors", n_monitors );

      printf( "%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate" );
      for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ )
      {
        int mon_id = atoi(dbrow[0]);
        int function = atoi(dbrow[1]);
        if ( !user || user->canAccess( mon_id ) )
        {
          if ( function > 1 )
          {
            Monitor *monitor = Monitor::Load( mon_id, false, Monitor::QUERY );
            if ( monitor && monitor->connect() )
            {
              struct timeval tv = monitor->GetTimestamp();
              printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n",
                monitor->Id(),
                function,
                monitor->GetState(),
                monitor->GetTriggerState(),
                tv.tv_sec, tv.tv_usec/10000,
                monitor->GetLastReadIndex(),
                monitor->GetLastWriteIndex(),
                monitor->GetLastEvent(),
                monitor->GetFPS()
              );
              delete monitor;
            }
          }
          else
          {
            struct timeval tv = { 0, 0 };
            printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n",
              mon_id,
              function,
              0,
              0,
              tv.tv_sec, tv.tv_usec/10000,
              0,
              0,
              0,
              0.0
            );
          }
        }
      }
      mysql_free_result( result );
    }
  }
  delete user;

  logTerm();
  zmDbClose();

  return( 0 );
}
Exemple #3
0
int main( int argc, char *argv[] )
{
    srand( getpid() * time( 0 ) );

	int id = -1;

	static struct option long_options[] = {
		{"monitor", 1, 0, 'm'},
		{"help", 0, 0, 'h'},
		{0, 0, 0, 0}
	};

	while (1)
	{
		int option_index = 0;

		int c = getopt_long (argc, argv, "m:h", long_options, &option_index);
		if (c == -1)
		{
			break;
		}

		switch (c)
		{
			case 'm':
				id = atoi(optarg);
				break;
			case 'h':
			case '?':
				Usage();
				break;
			default:
				//fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
				break;
		}
	}

	if (optind < argc)
	{
		fprintf( stderr, "Extraneous options, " );
		while (optind < argc)
			printf ("%s ", argv[optind++]);
		printf ("\n");
		Usage();
	}

	if ( id < 0 )
	{
		fprintf( stderr, "Bogus monitor %d\n", id );
		Usage();
		exit( 0 );
	}

	char log_id_string[16];
	snprintf( log_id_string, sizeof(log_id_string), "zma_m%d", id );

	zmLoadConfig();

	logInit( log_id_string );

	Monitor *monitor = Monitor::Load( id, true, Monitor::ANALYSIS );

	if ( monitor )
	{
		Info( "In mode %d/%d, warming up", monitor->GetFunction(), monitor->Enabled() );

		if ( config.opt_frame_server )
		{
			Event::OpenFrameSocket( monitor->Id() );
		}

		zmSetDefaultHupHandler();
		zmSetDefaultTermHandler();
		zmSetDefaultDieHandler();

		sigset_t block_set;
		sigemptyset( &block_set );

		while( !zm_terminate )
		{
			// Process the next image
			sigprocmask( SIG_BLOCK, &block_set, 0 );
			if ( !monitor->Analyse() )
			{
				usleep( monitor->Active()?ZM_SAMPLE_RATE:ZM_SUSPENDED_RATE );
			}
			if ( zm_reload )
			{
				monitor->Reload();
				zm_reload = false;
			}
			sigprocmask( SIG_UNBLOCK, &block_set, 0 );
		}
		delete monitor;
	}
	else
	{
		fprintf( stderr, "Can't find monitor with id of %d\n", id );
	}
	return( 0 );
}
Exemple #4
0
int main( int argc, char *argv[] )
{
    self = argv[0];

    srand( getpid() * time( 0 ) );

    int id = -1;

    static struct option long_options[] = {
        {"monitor", 1, 0, 'm'},
        {"help", 0, 0, 'h'},
        {"version", 0, 0, 'v'},
        {0, 0, 0, 0}
    };

    while (1)
    {
        int option_index = 0;

        int c = getopt_long (argc, argv, "m:h:v", long_options, &option_index);
        if (c == -1)
        {
            break;
        }

        switch (c)
        {
        case 'm':
            id = atoi(optarg);
            break;
        case 'h':
        case '?':
            Usage();
            break;
        case 'v':
            std::cout << ZM_VERSION << "\n";
            exit(0);
        default:
            //fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
            break;
        }
    }

    if (optind < argc)
    {
        fprintf( stderr, "Extraneous options, " );
        while (optind < argc)
            printf ("%s ", argv[optind++]);
        printf ("\n");
        Usage();
    }

    if ( id < 0 )
    {
        fprintf( stderr, "Bogus monitor %d\n", id );
        Usage();
        exit( 0 );
    }

    char log_id_string[16];
    snprintf( log_id_string, sizeof(log_id_string), "m%d", id );

    zmLoadConfig();

    logInit( "zmf" );

    ssedetect();

    Monitor *monitor = Monitor::Load( id, false, Monitor::QUERY );

    if ( !monitor )
    {
        fprintf( stderr, "Can't find monitor with id of %d\n", id );
        exit( -1 );
    }

    char capt_path[PATH_MAX];
    char anal_path[PATH_MAX];
    snprintf( capt_path, sizeof(capt_path), "%s/%d/%%s/%%0%dd-capture.jpg", config.dir_events, monitor->Id(), config.event_image_digits );
    snprintf( anal_path, sizeof(anal_path), "%s/%d/%%s/%%0%dd-analyse.jpg", config.dir_events, monitor->Id(), config.event_image_digits );
    zmSetDefaultTermHandler();
    zmSetDefaultDieHandler();

    sigset_t block_set;
    sigemptyset( &block_set );

    int sd = OpenSocket( monitor->Id() );

    FrameHeader frame_header = { 0, 0, false, 0 };
    //unsigned char *image_data = 0;

    fd_set rfds;

    struct timeval timeout;
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
    while( 1 )
    {
        struct timeval temp_timeout = timeout;

        FD_ZERO(&rfds);
        FD_SET(sd, &rfds);
        int n_found = select( sd+1, &rfds, NULL, NULL, &temp_timeout );
        if( n_found == 0 )
        {
            Debug( 1, "Select timed out" );
            continue;
        }
        else if ( n_found < 0)
        {
            Error( "Select error: %s", strerror(errno) );
            ReopenSocket( sd, monitor->Id() );
            continue;
        }

        sigprocmask( SIG_BLOCK, &block_set, 0 );

        int n_bytes = read( sd, &frame_header, sizeof(frame_header) );
        if ( n_bytes != sizeof(frame_header) )
        {
            if ( n_bytes < 0 )
            {
                Error( "Can't read frame header: %s", strerror(errno) );
            }
            else if ( n_bytes > 0 )
            {
                Error( "Incomplete read of frame header, %d bytes only", n_bytes );
            }
            else
            {
                Warning( "Socket closed at remote end" );
            }
            ReopenSocket( sd, monitor->Id() );
            continue;
        }
        Debug( 1, "Read frame header, expecting %ld bytes of image", frame_header.image_length );
        static unsigned char image_data[ZM_MAX_IMAGE_SIZE];

        // Read for pipe and loop until bytes expected have been read or an error occurs
        int bytes_read = 0;
        do
        {
            n_bytes = read( sd, image_data+bytes_read, frame_header.image_length-bytes_read );
            if (n_bytes < 0) break; // break on error
            if (n_bytes < (int)frame_header.image_length)
            {
                // print some informational messages
                if (bytes_read == 0)
                {
                    Debug(4,"Image read : Short read %d bytes of %d expected bytes",n_bytes,frame_header.image_length);
                }
                else if (bytes_read+n_bytes == (int)frame_header.image_length)
                {
                    Debug(5,"Image read : Read rest of short read: %d bytes read total of %d bytes",n_bytes,frame_header.image_length);
                }
                else
                {
                    Debug(6,"Image read : continuing, read %d bytes (%d so far)", n_bytes, bytes_read+n_bytes);
                }
            }
            bytes_read+= n_bytes;
        } while (n_bytes>0 && (bytes_read < (ssize_t)frame_header.image_length) );

        // Print errors if there was a problem
        if ( n_bytes < 1 )
        {
            Error( "Only read %d bytes of %d\n", bytes_read, frame_header.image_length);
            if ( n_bytes < 0 )
            {
                Error( "Can't read frame image data: %s", strerror(errno) );
            }
            else
            {
                Warning( "Socket closed at remote end" );
            }
            ReopenSocket( sd, monitor->Id() );
            continue;
        }

        static char subpath[PATH_MAX] = "";
        if ( config.use_deep_storage )
        {
            struct tm *time = localtime( &frame_header.event_time );
            snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec );
        }
        else
        {
            snprintf( subpath, sizeof(subpath), "%ld", frame_header.event_id );
        }

        static char path[PATH_MAX] = "";
        snprintf( path, sizeof(path), frame_header.alarm_frame?anal_path:capt_path, subpath, frame_header.frame_id );
        Debug( 1, "Got image, writing to %s", path );

        FILE *fd = 0;
        if ( (fd = fopen( path, "w" )) < 0 )
        {
            Error( "Can't fopen '%s': %s", path, strerror(errno) );
            exit( -1 );
        }
        if ( 0 == fwrite( image_data, frame_header.image_length, 1, fd ) )
        {
            Error( "Can't fwrite image data: %s", strerror(errno) );
            exit( -1 );
        }
        fclose( fd );

        sigprocmask( SIG_UNBLOCK, &block_set, 0 );
    }
    logTerm();
    zmDbClose();
}
Exemple #5
0
int main( int argc, char *argv[] )
{
  self = argv[0];

  srand( getpid() * time( 0 ) );

  int id = -1;

  static struct option long_options[] = {
    {"monitor", 1, 0, 'm'},
    {"help", 0, 0, 'h'},
    {"version", 0, 0, 'v'},
    {0, 0, 0, 0}
  };

  while (1)
  {
    int option_index = 0;

    int c = getopt_long (argc, argv, "m:h:v", long_options, &option_index);
    if (c == -1)
    {
      break;
    }

    switch (c)
    {
      case 'm':
        id = atoi(optarg);
        break;
      case 'h':
      case '?':
        Usage();
        break;
      case 'v':
        std::cout << ZM_VERSION << "\n";
        exit(0);
      default:
        //fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
        break;
    }
  }

  if (optind < argc)
  {
    fprintf( stderr, "Extraneous options, " );
    while (optind < argc)
      printf ("%s ", argv[optind++]);
    printf ("\n");
    Usage();
  }

  if ( id < 0 )
  {
    fprintf( stderr, "Bogus monitor %d\n", id );
    Usage();
    exit( 0 );
  }

  char log_id_string[16];
  snprintf( log_id_string, sizeof(log_id_string), "zma_m%d", id );

  zmLoadConfig();

  logInit( log_id_string );
  
  ssedetect();

  Monitor *monitor = Monitor::Load( id, true, Monitor::ANALYSIS );

  if ( monitor )
  {
    Info( "In mode %d/%d, warming up", monitor->GetFunction(), monitor->Enabled() );

    if ( config.opt_frame_server )
    {
      Event::OpenFrameSocket( monitor->Id() );
    }

    zmSetDefaultHupHandler();
    zmSetDefaultTermHandler();
    zmSetDefaultDieHandler();

    sigset_t block_set;
    sigemptyset( &block_set );

    useconds_t analysis_rate = monitor->GetAnalysisRate();
    unsigned int analysis_update_delay = monitor->GetAnalysisUpdateDelay();
    time_t last_analysis_update_time, cur_time;
    monitor->UpdateAdaptiveSkip();
    last_analysis_update_time = time( 0 );

    while( !zm_terminate )
    {
      // Process the next image
      sigprocmask( SIG_BLOCK, &block_set, 0 );

      // Some periodic updates are required for variable capturing framerate
      if ( analysis_update_delay )
      {
        cur_time = time( 0 );
        if ( ( cur_time - last_analysis_update_time ) > analysis_update_delay )
        {
          analysis_rate = monitor->GetAnalysisRate();
          monitor->UpdateAdaptiveSkip();
          last_analysis_update_time = cur_time;
        }
      }

      if ( !monitor->Analyse() )
      {
        usleep( monitor->Active()?ZM_SAMPLE_RATE:ZM_SUSPENDED_RATE );
      }
      else if ( analysis_rate )
      {
        usleep( analysis_rate );
      }

      if ( zm_reload )
      {
        monitor->Reload();
        zm_reload = false;
      }
      sigprocmask( SIG_UNBLOCK, &block_set, 0 );
    }
    delete monitor;
  }
  else
  {
    fprintf( stderr, "Can't find monitor with id of %d\n", id );
  }
  Image::Deinitialise();
  logTerm();
  zmDbClose();
  return( 0 );
}
Exemple #6
0
int main( int argc, const char *argv[] )
{
  self = argv[0];

  srand( getpid() * time( 0 ) );

  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;
  unsigned int frame_id = 1;
  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;

  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();

  logInit( "zms" );
  
  ssedetect();

  zmSetDefaultTermHandler();
  zmSetDefaultDieHandler();

  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 )
        {
          if ( !strcmp( name, "user" ) )
          {
            strncpy( username, value, sizeof(username) );
          }
        }
        else
        {
          //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) );
            }
          }
        }
      }
    }
  }

  if ( config.opt_use_auth )
  {
    User *user = 0;

    if ( strcmp( config.auth_relay, "none" ) == 0 )
    {
      if ( *username )
      {
        user = zmLoadUser( username );
      }
    }
    else
    {
      //if ( strcmp( config.auth_relay, "hashed" ) == 0 )
      {
        if ( *auth )
        {
          user = zmLoadAuthUser( auth, config.auth_hash_ips );
        }
      }
      //else if ( strcmp( config.auth_relay, "plain" ) == 0 )
      {
        if ( *username && *password )
        {
          user = zmLoadUser( username, password );
        }
      }
    }
    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
    {
#if HAVE_LIBAVCODEC
      stream.setStreamFormat( format );
      stream.setStreamBitrate( bitrate );
      stream.setStreamType( MonitorStream::STREAM_MPEG );
#else // HAVE_LIBAVCODEC
      Error( "MPEG streaming of '%s' attempted while disabled", query );
      fprintf( stderr, "MPEG streaming is disabled.\nYou 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.\nYou should ensure the ffmpeg libraries are installed and detected and rebuild to use this functionality.\n" );
      logTerm();
      zmDbClose();
      return( -1 );
#endif // HAVE_LIBAVCODEC
    }
    stream.runStream();
  }

  logTerm();
  zmDbClose();

  return( 0 );
}
Exemple #7
0
int main( int argc, char *argv[] )
{
    srand( getpid() * time( 0 ) );

	int id = -1;

	static struct option long_options[] = {
		{"monitor", 1, 0, 'm'},
		{"help", 0, 0, 'h'},
		{0, 0, 0, 0}
	};

	while (1)
	{
		int option_index = 0;

		int c = getopt_long (argc, argv, "m:h", long_options, &option_index);
		if (c == -1)
		{
			break;
		}

		switch (c)
		{
			case 'm':
				id = atoi(optarg);
				break;
			case 'h':
			case '?':
				Usage();
				break;
			default:
				//fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
				break;
		}
	}

	if (optind < argc)
	{
		fprintf( stderr, "Extraneous options, " );
		while (optind < argc)
			printf ("%s ", argv[optind++]);
		printf ("\n");
		Usage();
	}

	if ( id < 0 )
	{
		fprintf( stderr, "Bogus monitor %d\n", id );
		Usage();
		exit( 0 );
	}

	char dbg_id_string[16];
	snprintf( dbg_id_string, sizeof(dbg_id_string), "m%d", id );

	zmDbgInit( "zmf", dbg_id_string, 0 );

	zmLoadConfig();

	Monitor *monitor = Monitor::Load( id, false, Monitor::QUERY );

	if ( !monitor )
	{
		fprintf( stderr, "Can't find monitor with id of %d\n", id );
		exit( -1 );
	}

	char capt_path[PATH_MAX];
	char anal_path[PATH_MAX];
	snprintf( capt_path, sizeof(capt_path), "%s/%d/%%s/%%0%dd-capture.jpg", config.dir_events, monitor->Id(), config.event_image_digits );
	snprintf( anal_path, sizeof(anal_path), "%s/%d/%%s/%%0%dd-analyse.jpg", config.dir_events, monitor->Id(), config.event_image_digits );
	zmSetDefaultTermHandler();
	zmSetDefaultDieHandler();

	sigset_t block_set;
	sigemptyset( &block_set );

	int sd = OpenSocket( monitor->Id() );

	FrameHeader frame_header = { 0, 0, false, 0 };
	//unsigned char *image_data = 0;

	fd_set rfds;

	struct timeval timeout;
	timeout.tv_sec = 1;
	timeout.tv_usec = 0;
	while( 1 )
	{
		struct timeval temp_timeout = timeout;

		FD_ZERO(&rfds);
		FD_SET(sd, &rfds);
		int n_found = select( sd+1, &rfds, NULL, NULL, &temp_timeout );
		if( n_found == 0 )
		{
			Debug( 1, "Select timed out" );
			continue;
		}
		else if ( n_found < 0)
		{
			Error( "Select error: %s", strerror(errno) );
			ReopenSocket( sd, monitor->Id() );
			continue;
		}

		sigprocmask( SIG_BLOCK, &block_set, 0 );

		int n_bytes = read( sd, &frame_header, sizeof(frame_header) );
		if ( n_bytes != sizeof(frame_header) )
		{
			if ( n_bytes < 0 )
			{
				Error( "Can't read frame header: %s", strerror(errno) );
			}
			else if ( n_bytes > 0 )
			{
				Error( "Incomplete read of frame header, %d bytes only", n_bytes );
			}
			else
			{
				Warning( "Socket closed at remote end" );
			}
			ReopenSocket( sd, monitor->Id() );
			continue;
		}
		Debug( 1, "Read frame header, expecting %ld bytes of image", frame_header.image_length );
		static unsigned char image_data[ZM_MAX_IMAGE_SIZE];
		n_bytes = read( sd, image_data, frame_header.image_length );
		if ( n_bytes != (ssize_t)frame_header.image_length )
		{
			if ( n_bytes < 0 )
			{
				Error( "Can't read frame image data: %s", strerror(errno) );
			}
			else if ( n_bytes > 0 )
			{
				Error( "Incomplete read of frame image data, %d bytes only", n_bytes );
			}
			else
			{
				Warning( "Socket closed at remote end" );
			}
			ReopenSocket( sd, monitor->Id() );
			continue;
		}
		static char subpath[PATH_MAX] = "";
        if ( config.use_deep_storage )
        {
            struct tm *time = localtime( &frame_header.event_time );
            snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec );
        }
        else
        {
            snprintf( subpath, sizeof(subpath), "%ld", frame_header.event_id );
        }
		static char path[PATH_MAX] = "";
		snprintf( path, sizeof(path), frame_header.alarm_frame?anal_path:capt_path, subpath, frame_header.frame_id );
		Debug( 1, "Got image, writing to %s", path );

		FILE *fd = 0;
		if ( (fd = fopen( path, "w" )) < 0 )
		{
			Error( "Can't fopen '%s': %s", path, strerror(errno) );
			exit( -1 );
		}
		if ( 0 == fwrite( image_data, frame_header.image_length, 1, fd ) )
		{
			Error( "Can't fwrite image data: %s", strerror(errno) );
			exit( -1 );
		}
		fclose( fd );

		sigprocmask( SIG_UNBLOCK, &block_set, 0 );
	}
}