Example #1
0
int main_loop( CamConfig *ccfg, Socket *picture_sock, char *picture_mem  ){
  Socket *listen_socket;
  SockSet *readset = NULL, *writeset = NULL;
  list_t *client_sockets;
  lnode_t *node;
  int cfg_listen_port, highest_fd, picture_client_ready;
  int num_sclients, num_clients;
  ClientInfo *clientinfo, *clientinfo2;

  if( (client_sockets = list_create( -1 )) == NULL)
    return -1;

  cfg_listen_port = camconfig_query_def_int( ccfg, SEC_SOCKET, 
					     "listen_port",
					     CAMCONFIG_DEF_LISTEN_PORT );

  if( (readset = sockset_new()) == NULL ||
      (writeset = sockset_new()) == NULL )
  {
    camserv_log( MODNAME, "Error allocating memory for socksets!");
    if( readset ) sockset_dest( readset );
    if( writeset ) sockset_dest( writeset );
    list_destroy( client_sockets );
    return -1;
  }

  if((listen_socket = socket_serve_tcp( NULL, cfg_listen_port, 100 )) == NULL )
  {
      camserv_log( MODNAME, "Error setting up socket on port \"%d\".  Exiting",
	       cfg_listen_port  );
      list_destroy( client_sockets );
      sockset_dest( readset );
      sockset_dest( writeset );
      return -1;
  }

  highest_fd = MAX( socket_query_fd( listen_socket ), 
		    socket_query_fd( picture_sock ));
  clientinfo = clientinfo_new( listen_socket );
  clientinfo2 = clientinfo_new( picture_sock );

  if( !clientinfo || !clientinfo2 ||
      sockset_add_fd( readset, listen_socket, clientinfo ) == -1 ||
      sockset_add_fd( readset, picture_sock, clientinfo2 ) == -1 )
  {
    camserv_log( MODNAME, "Error adding initial sockets to sockset!");
    sockset_dest( readset );
    sockset_dest( writeset );
    if( clientinfo )  clientinfo_dest( clientinfo );
    if( clientinfo2 ) clientinfo_dest( clientinfo2 );
    list_destroy( client_sockets );
    return -1;
  }

  num_clients = 0;
  num_sclients = 0;
  picture_client_ready = 1;

  setup_signals();
  Abort = 0;
  while( !Abort ){
    int sel_res, i, nset_socks;
    void **set_socks;

    /* Only need to execute this if we have a streaming client */
    if( (num_sclients > 0) && picture_client_ready == 1 ){
      send( socket_query_fd( picture_sock ), "0", sizeof( "0" ), 0 );
      picture_client_ready = 0;
    }

    sockset_reset( readset );
    sockset_reset( writeset );

    sel_res = sockset_select( highest_fd + 1, readset, writeset, NULL );
    /* Service the event */
    if( sel_res == -1 ){
      camserv_log( MODNAME, "select() failure: %s", strerror( errno ));
      break;
    } else if( sel_res == 0 ){
      camserv_log( MODNAME, "Unexpected select() fall through!" );
      continue;
    } 

    /* Readable sockets */
    set_socks = sockset_query_socks( readset );
    nset_socks = sockset_query_nsocks( readset );
    for( i=0; i< nset_socks; i++ ){
      ClientInfo *new_cinfo;

      clientinfo = set_socks[ i ];

      if( clientinfo->socket == listen_socket ) {
	/* New client */
	if( (new_cinfo = accept_client( listen_socket )) == NULL )
	  continue;

	if( (node = lnode_create( new_cinfo )) == NULL ){
	  clientinfo_dest( new_cinfo );
	  continue;
	}

	if( sockset_add_fd( readset, new_cinfo->socket, new_cinfo ) == -1 ){
	  camserv_log( MODNAME, "Failed to add socket %d to socket read set!",
		   socket_query_fd( new_cinfo->socket ));
	  clientinfo_dest( new_cinfo );
	  lnode_destroy( node );
	  continue;
	}

	if( socket_query_fd( new_cinfo->socket ) > highest_fd )
	  highest_fd = socket_query_fd( new_cinfo->socket );

	list_append( client_sockets, node );
	num_clients++;
	/* Init resource limit for this client */
	new_cinfo->create_time = time( NULL );
	new_cinfo->bytes       = 0;
	new_cinfo->frames      = 0;
	new_cinfo->max_seconds = camconfig_query_def_int( ccfg, SEC_SOCKET,
							  "max_seconds", 0 );
	new_cinfo->max_bytes   = camconfig_query_def_int( ccfg, SEC_SOCKET,
							  "max_bytes", 0 );
	new_cinfo->max_frames  = camconfig_query_def_int( ccfg, SEC_SOCKET,
							  "max_frames", 0 );

	/* Send fresh request for a picture */
	send( socket_query_fd( picture_sock ), "0", sizeof( "0" ), 0 );
	picture_client_ready = 0;
	/* Put this read socket on hold until the picture comes back */
	sockset_hold( readset, new_cinfo->socket );	

      } else {
	char cmdbuf[ 1024 ];
	int readlen;

	clientinfo = set_socks[ i ];

	/* Regular joe client, set readable */
	if( (readlen = read( socket_query_fd( clientinfo->socket), cmdbuf, 
			     sizeof( cmdbuf ) - 1)) <= 0 )
	{
	  camserv_log( MODNAME, "Closing socket: %s", 
		       socket_query_remote_name( clientinfo->socket ));

	  if (clientinfo->client_type == CLIENT_T_BROWSER ||
	      clientinfo->client_type == CLIENT_T_PROXY) {
	      num_sclients--;
	  }
	  client_remove( client_sockets, clientinfo );
	  sockset_del_fd( readset, clientinfo->socket );
	  sockset_unhold_all( writeset );
	  sockset_del_fd( writeset, clientinfo->socket );
	  clientinfo_dest( clientinfo );
	  num_clients--;
	} else {
	  if( clientinfo->socket == picture_sock ) {
	    if( dispatch_pictaker( cmdbuf, picture_mem ) == -1 )
	      camserv_log( MODNAME, "Pictaker dispatch failure!");
	    sockset_unhold_all( writeset );
	    /* Release the read hold as the picture has now been taken */
	    sockset_unhold_all( readset );
	    picture_client_ready = 1;
	  } else {
	    /* Information from a regular client */
	    cmdbuf[ readlen ] = '\0';
	    if( clientinfo->client_type == CLIENT_T_UNINIT ) {
	      char *preamble;
	      int pre_size;

	      /* Figure out what type of client we have */
	      if( !strncmp( cmdbuf, "GET", 3 )) {
		if( strstr( cmdbuf, "/singleframe" )) {
		  clientinfo->client_type = CLIENT_T_SINGLE;
		} else {
		  clientinfo->client_type = CLIENT_T_BROWSER;
		  num_sclients++;
	        }
	      } else if( !strncmp( cmdbuf, "PROXY", 5 )) {
		clientinfo->client_type = CLIENT_T_PROXY;
		/* Here we are in the same state as being done writing a pic */
		clientinfo->state       = CINFO_STATE_PICTURE;
		num_sclients++;	
		databuf_buf_set( clientinfo->writebuf, NULL, 0 ); 
	      } else 
		clientinfo->client_type = CLIENT_T_BROWSER;

	      if( clientinfo->client_type != CLIENT_T_PROXY ) {
		/* Send the initial preamble.  Only now we can decide which 
		   type of preamble to send (single vs. multi-part) */
		if( clientinfo->client_type == CLIENT_T_SINGLE )
		  preamble = get_single_preamble_text( &pre_size );
		else
		  preamble = get_multi_preamble_text( &pre_size );
		databuf_buf_set( clientinfo->writebuf, preamble, pre_size );
	      }

	      if( sockset_add_fd( writeset, clientinfo->socket, 
				  clientinfo ) == -1 )
	      {
  		  camserv_log( MODNAME, "Failed to add socket %d to write set!",
			   socket_query_fd( clientinfo->socket ));
	      }
	  } 
	} 
      } 
    } 
  } 

    if( set_socks != NULL ) free( set_socks );

    /* Writable sockets */
    set_socks = sockset_query_socks( writeset );
    nset_socks = sockset_query_nsocks( writeset );
    for( i=0; i< nset_socks; i++ ){
      ClientInfo *cinfo;

      cinfo = set_socks[ i ];
      if( cinfo->client_type == CLIENT_T_BROWSER ||
	  cinfo->client_type == CLIENT_T_SINGLE ) 
      {
	int result;

	if( (result = write_regular_client( cinfo, writeset )) != 0 ){
	  /* result: 1=close requested, -1=error detected */
	  if( result == -1 )
	    camserv_log( MODNAME, "Databuf write error on socket: %s\n",
			 socket_query_remote_name( cinfo->socket ));
	  
	  if (cinfo->client_type == CLIENT_T_BROWSER) {
	      num_sclients--;
	  }

	  client_remove( client_sockets, cinfo );
	  sockset_del_fd( readset, cinfo->socket );
	  sockset_del_fd( writeset, cinfo->socket );
	  clientinfo_dest( cinfo );
	  num_clients--;
	}
      } else {
	if( write_proxy_client( cinfo, writeset ) == -1 ){
	  camserv_log( MODNAME, "Databuf write error on socket: %d",
		   socket_query_fd( cinfo->socket ));

	  /* Should be proxy, but better check */
	  if (cinfo->client_type == CLIENT_T_PROXY) {
	      num_sclients--;
	  }
	  client_remove( client_sockets, cinfo );
	  sockset_del_fd( readset, cinfo->socket );
	  sockset_del_fd( writeset, cinfo->socket );
	  clientinfo_dest( cinfo );
	  num_clients--;
	}
      }
    }
    if( set_socks != NULL ) free( set_socks );
  }

  camserv_log( MODNAME, "Aborting.");
  sockset_dest( readset );
  sockset_dest( writeset );

  for( node = list_first( client_sockets) ; node; 
       node=list_next( client_sockets, node ))
  {
    clientinfo_dest( node->data );
  }

  /* Tell the picture taker to get out!  Get out! */
  camserv_log( MODNAME, "Closing picture taker");
  send( socket_query_fd( picture_sock ), "9", sizeof( "9" ), 0 );
  sleep( 3 );
  camserv_log( MODNAME, "done\n");

  list_destroy_nodes( client_sockets );
  list_destroy( client_sockets );
  socket_dest( listen_socket );
  return 0;
}
Example #2
0
void ur_launch_util (char *name, Web100Obj *web100obj,
                     gboolean malleable, gboolean master)
{
    static  GtkWidget *window, *vbox, *ur_sockset, *avd_list, *avd, *cpr, *dtb, *rtuner, *stuner, *triage, *vdt;

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE);
    gtk_window_set_title (GTK_WINDOW (window), name);

    if (master)
        gtk_signal_connect (GTK_OBJECT (window), "destroy",
                            GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
    else // if slave
        gtk_signal_connect (GTK_OBJECT (window), "destroy",
                            GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);


    gtk_container_set_border_width (GTK_CONTAINER (window), 10);

    vbox = gtk_vbox_new (FALSE, 0);
    gtk_container_add (GTK_CONTAINER (window), vbox);
    gtk_widget_show (vbox);

    ur_sockset = sockset_new (web100obj, malleable);
    gtk_box_pack_start (GTK_BOX(vbox), ur_sockset, FALSE, FALSE, 0);
    gtk_widget_show (ur_sockset);

    if (!strncmp ("avd_list", name, 8)) {
        avd_list = avd_list_new (web100obj);
        gtk_box_pack_start (GTK_BOX(vbox), avd_list, TRUE, TRUE, 0);
        gtk_widget_show (avd_list);
// TODO: track widgets for closing all windows for a given connection
//    if (!master) g_list_prepend (web100obj->widgets, avd_list);

        if (malleable) {
            gtk_signal_connect (GTK_OBJECT (ur_sockset),
                                "web100obj_changed",
                                GTK_SIGNAL_FUNC (avd_list_sockset_listen),
                                (gpointer) avd_list);
        }

    }
#if 0
    if (!strncmp ("avd_table", name, 9)) {
        avd = avd_table_new (web100obj);
        gtk_box_pack_start (GTK_BOX(vbox), avd, TRUE, TRUE, 0);
        gtk_widget_show (avd);

        if (malleable)
            gtk_signal_connect (GTK_OBJECT (ur_sockset),
                                "web100obj_changed",
                                GTK_SIGNAL_FUNC (avd_table_sockset_listen),
                                avd);
    }
#endif
    if (!strncmp ("cpr", name, 3)) {
        cpr = cpr_new (web100obj);
        gtk_box_pack_start (GTK_BOX(vbox), cpr, TRUE, TRUE, 0);
        gtk_widget_show (cpr);

        if (malleable)
            gtk_signal_connect (GTK_OBJECT (ur_sockset),
                                "web100obj_changed",
                                GTK_SIGNAL_FUNC (cpr_sockset_listen),
                                cpr);

    }

    if (!strncmp ("dtb", name, 3)) {
        dtb = dtb_new (web100obj);
        gtk_box_pack_start (GTK_BOX(vbox), dtb, TRUE, TRUE, 0);
        gtk_widget_show (dtb);

        if (malleable)
            gtk_signal_connect (GTK_OBJECT (ur_sockset),
                                "web100obj_changed",
                                GTK_SIGNAL_FUNC (dtb_sockset_listen),
                                dtb);

    }
    if (!strncmp ("rtuner", name, 6)) {
        rtuner = rtuner_new (web100obj);
        gtk_box_pack_start (GTK_BOX(vbox), rtuner, TRUE, TRUE, 0);
        gtk_widget_show (rtuner);

        if (malleable)
            gtk_signal_connect (GTK_OBJECT (ur_sockset),
                                "web100obj_changed",
                                GTK_SIGNAL_FUNC (rtuner_sockset_listen),
                                rtuner);

    }
    if (!strncmp ("stuner", name, 6)) {
        stuner = stuner_new (web100obj);
        gtk_box_pack_start (GTK_BOX(vbox), stuner, TRUE, TRUE, 0);
        gtk_widget_show (stuner);

        if (malleable)
            gtk_signal_connect (GTK_OBJECT (ur_sockset),
                                "web100obj_changed",
                                GTK_SIGNAL_FUNC (stuner_sockset_listen),
                                stuner);

    }
    if (!strncmp ("triage", name, 6)) {
        triage = triage_new (web100obj);
        gtk_box_pack_start (GTK_BOX(vbox), triage, TRUE, TRUE, 0);
        gtk_widget_show (triage);

        if (malleable)
            gtk_signal_connect (GTK_OBJECT (ur_sockset),
                                "web100obj_changed",
                                GTK_SIGNAL_FUNC (triage_sockset_listen),
                                triage);

    }
    if (!strncmp ("vdt", name, 3)) {
        vdt = vdt_new (web100obj, "DataBytesIn");
        gtk_box_pack_start (GTK_BOX(vbox), vdt, TRUE, TRUE, 0);
        gtk_widget_show (vdt);

        if (malleable)
            gtk_signal_connect (GTK_OBJECT (ur_sockset),
                                "web100obj_changed",
                                GTK_SIGNAL_FUNC (vdt_sockset_listen),
                                vdt);

    }
    gtk_widget_show (window);
}