Example #1
0
int main( void )
{
	stop_watchdog();
	setup_finish_ports();
	setup_clock();
	setup_uart();
	rf_init(sizeof(struct packet));
	configure_timer_38k();
	timer_38k_enable(1);
	configure_watchdog();

	__enable_interrupt();

	// Show battery voltage on start
	display_vcc();

	// Setup RF channel
	setup_channel();

	set_state(st_stopped);

	// Start/stop loop
	for (;;) {
		wait_start();
		set_state(st_started);
		beep(SHORT_DELAY_TICKS);
		detect_finish();
		set_state(st_stopped);
		report_finish();
	}
}
// reset by peer(client)
CASE_TEST(channel, io_stream_tcp_reset_by_client)
{
    atbus::channel::io_stream_channel svr, cli;
    atbus::channel::io_stream_init(&svr, NULL, NULL);
    atbus::channel::io_stream_init(&cli, NULL, NULL);

    svr.evt.callbacks[atbus::channel::io_stream_callback_evt_t::EN_FN_DISCONNECTED] = disconnected_callback_test_fn;

    int check_flag = g_check_flag = 0;

    int inited_fds = 0;
    inited_fds += setup_channel(svr, "ipv6://:::16387", NULL);
    CASE_EXPECT_EQ(1, g_check_flag);
    CASE_EXPECT_NE(NULL, svr.ev_loop);
    if (0 == inited_fds) {
        return;
    }

    inited_fds = 0;
    inited_fds += setup_channel(cli, NULL, "ipv4://127.0.0.1:16387");
    inited_fds += setup_channel(cli, NULL, "dns://localhost:16387");
    inited_fds += setup_channel(cli, NULL, "ipv6://::1:16387");

    while (g_check_flag - check_flag < 2 * inited_fds + 1) {
        atbus::channel::io_stream_run(&svr, atbus::adapter::RUN_NOWAIT);
        atbus::channel::io_stream_run(&cli, atbus::adapter::RUN_NOWAIT);
        CASE_THREAD_SLEEP_MS(8);
    }
    CASE_EXPECT_NE(0, cli.conn_pool.size());

    check_flag = g_check_flag;
    atbus::channel::io_stream_close(&cli);
    CASE_EXPECT_EQ(0, cli.conn_pool.size());

    while (g_check_flag - check_flag < inited_fds) {
        atbus::channel::io_stream_run(&svr, atbus::adapter::RUN_NOWAIT);
        CASE_THREAD_SLEEP_MS(8);
    }
    CASE_EXPECT_EQ(1, svr.conn_pool.size());

    atbus::channel::io_stream_close(&svr);
    CASE_EXPECT_EQ(0, svr.conn_pool.size());
}
Example #3
0
bool sdma_channel_init(unsigned int channel,
                       struct channel_descriptor *cd_p,
                       struct buffer_descriptor *base_bd_p)
{
    struct channel_control_block *ccb_p;

    if (channel == 0 || channel >= CH_NUM ||
        cd_p == NULL || base_bd_p == NULL)
        return false;

    ccb_p = &ccb_array[channel];

    /* If initialized already, should close first then init. */
    if (ccb_p->status.opened_init != 0)
        return false;

    /* Initialize channel control block. */
    ccb_p->curr_bd_ptr = base_bd_p;
    ccb_p->base_bd_ptr = base_bd_p;
    ccb_p->channel_desc = cd_p;
    ccb_p->status.error = 0;
    ccb_p->status.opened_init = 1;
    ccb_p->status.state_direction = 0;
    ccb_p->status.execute = 0;

    /* Finish any channel descriptor inits. */
    cd_p->ccb_ptr = ccb_p;
    cd_p->is_setup = 0;

    /* Do an initial setup now. */
    if (!setup_channel(ccb_p))
    {
        logf("SDMA ch init failed: %d", channel);
        cd_p->ccb_ptr = NULL;
        memset(ccb_p, 0x00, sizeof (struct channel_control_block));
        return false;
    }

    /* Enable interrupt if a callback is specified. */
    if (cd_p->callback != NULL)
        bitset32(&sdma_enabled_ints, 1ul << channel);

    /* Minimum schedulable = 1 */
    sdma_channel_set_priority(channel, 1);

    logf("SDMA ch initialized: %d", channel);
    return true;
}
/*!**************************************************************************************
 @Function	 	main
 @Return		void
 @Description 		Main function invoked after Application launch.
******************************************************************************************/
int main(void)
{
	int n=-1;
	pthread_t thread1;
	pthread_t thread2;

	/* Ensure the contents are erased and file is created if doesn't exist*/
	FILE *fd_instance = fopen( INSTANCEID_FIFO_NAME, "w");
	fprintf(fd_instance,"%d",-1);
	fclose(fd_instance);

	printf("Initializing egl..\n\n");
	if( 0 == initApplication())
	{
		printf("EGL init failed");
		return 0;
	}
	initView();

	/* Launch user and pipe control threads */
	n = pthread_create(&thread1, NULL, pipe_ctrl_thread, NULL);
	n = pthread_create(&thread2, NULL, user_ctrl_thread, NULL);

	while(1)
	{
		if(id != -1)
			setup_channel();

		/* If any of the bc_cat devices are alive render */
		if( (dev_fd0 != -1) || (dev_fd1 != -1) || (dev_fd2 != -1)  || (dev_fd3 != -1) )
		{
			render_thread(dev_fd0,0);
			render_thread(dev_fd1,1);
			render_thread(dev_fd2,2);
			render_thread(dev_fd3,3);

			/* eglswapbuffers must be called only after all active devices have finished rendering
			   inorder to avoid any artifacts due to incomplete/partial frame updates*/
			eglSwapBuffers(dpy, surface);
		}
		else
		{
			sleep(2);
		}
		
	}
	return 0;
}
Example #5
0
/* Resets a channel to start of script next time it runs. */
bool sdma_channel_reset(unsigned int channel)
{
    struct channel_control_block *ccb_p;

    if (channel == 0 || channel >= CH_NUM)
        return false;

    ccb_p = &ccb_array[channel];

    if (ccb_p->status.opened_init == 0)
        return false;

    if (!setup_channel(ccb_p))
        return false;

    return true;
}
Example #6
0
static int open_channel(orte_rmcast_channel_t channel, char *name,
                        char *network, int port, char *interface, uint8_t direction)
{
    opal_list_item_t *item;
    rmcast_base_channel_t *nchan, *chan;
    uint32_t netaddr=0, netmask=0, intr=0;
    int rc;
    unsigned int i, n, start, end, range;
    bool port_assigned;
    
    OPAL_OUTPUT_VERBOSE((2, orte_rmcast_base.rmcast_output,
                         "%s opening channel %d for %s",
                         ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), channel, name));

    /* parse the network, if provided */
    if (NULL != network) {
        if (ORTE_SUCCESS != (rc = opal_iftupletoaddr(network, &netaddr, &netmask))) {
            orte_show_help("help-rmcast-base.txt", "invalid-net-mask", true, network, ORTE_ERROR_NAME(rc));
            return ORTE_ERR_SILENT;
        }        
    }
    
    /* parse the interface, if provided */
    if (NULL != interface) {
        if (ORTE_SUCCESS != (rc = opal_iftupletoaddr(interface, &intr, NULL))) {
            orte_show_help("help-rmcast-base.txt", "invalid-net-mask", true, interface, ORTE_ERROR_NAME(rc));
            return ORTE_ERR_SILENT;
        }        
    }
    
    /* see if this name has already been assigned a channel on the specified network */
    OPAL_OUTPUT_VERBOSE((7, orte_rmcast_base.rmcast_output,
                         "%s open_channel: searching for %s:%d",
                         ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), name, channel));
                        
    chan = NULL;
    ORTE_ACQUIRE_THREAD(&orte_rmcast_base.main_ctl);
    for (item = opal_list_get_first(&orte_rmcast_base.channels);
         item != opal_list_get_end(&orte_rmcast_base.channels);
         item = opal_list_get_next(item)) {
        nchan = (rmcast_base_channel_t*)item;
        
        OPAL_OUTPUT_VERBOSE((7, orte_rmcast_base.rmcast_output,
                             "%s open_channel: channel %s:%d",
                             ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
                             nchan->name, channel));

        if (nchan->channel == channel ||
            0 == strcasecmp(nchan->name, name)) {
             chan = nchan;
            break;
        }
    }
    
    if (NULL != chan) {
        /* already exists - check that the requested
         * sockets are setup
         */
        OPAL_OUTPUT_VERBOSE((2, orte_rmcast_base.rmcast_output,
                             "%s rmcast:udp using existing channel %s:%d network %03d.%03d.%03d.%03d port %d",
                             ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
                             chan->name, chan->channel,
                             OPAL_IF_FORMAT_ADDR(chan->network),
                             (int)chan->port));
        
        if (ORTE_SUCCESS != (rc = setup_channel(chan, direction))) {
            ORTE_ERROR_LOG(rc);
            ORTE_RELEASE_THREAD(&orte_rmcast_base.main_ctl);
            return rc;
        }
        ORTE_RELEASE_THREAD(&orte_rmcast_base.main_ctl);
        return ORTE_SUCCESS;
    }
    
    /* we didn't find an existing match, so create a new channel */
    OPAL_OUTPUT_VERBOSE((2, orte_rmcast_base.rmcast_output,
                         "%s creating new channel %s for %s",
                         ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
                         orte_rmcast_base_print_channel(channel), name));

    chan = OBJ_NEW(rmcast_base_channel_t);
    chan->name = strdup(name);
    chan->channel = channel;
    /* if we were not given a network, use the default */
    if (NULL == network) {
        chan->network = orte_rmcast_base.xmit_network;
    } else {
        chan->network = netaddr;
    }
    /* if we were not given an interface, use the default */
    if (NULL == interface) {
        chan->interface = orte_rmcast_base.interface;
    } else {
        chan->interface = intr;
    }
    /* if we were not given a port, use a default one */
    if (port < 0) {
        /* cycle thru the port ranges until we find the
         * port corresponding to this channel number
         */
        n=0;
        port_assigned = false;
        for (i=0; NULL != orte_rmcast_base.ports.start[i]; i++) {
            /* how many ports are in this range? */
            start = strtol(orte_rmcast_base.ports.start[i], NULL, 10);
            end = strtol(orte_rmcast_base.ports.end[i], NULL, 10);
            range = end - start + 1;
            if (chan->channel < (n + range)) {
                /* take the corresponding port */
                chan->port = start + (chan->channel - n);
                port_assigned = true;
                break;
            }
            n += range;
        }
        if (!port_assigned) {
            opal_output(0, "%s CANNOT ASSIGN PORT TO CHANNEL %s",
                        ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
                        orte_rmcast_base_print_channel(chan->channel));
            return ORTE_ERROR;
        }
    } else {
        chan->port = port;
    }
    opal_list_append(&orte_rmcast_base.channels, &chan->item);
    ORTE_RELEASE_THREAD(&orte_rmcast_base.main_ctl);
    
    /* if this is my input, set that value */
    if (ORTE_RMCAST_MY_INPUT & direction) {
        orte_rmcast_base.my_input_channel = chan;
    }

    /* if this is my output, set that value */
    if (ORTE_RMCAST_MY_OUTPUT & direction) {
        orte_rmcast_base.my_output_channel = chan;
    }

    OPAL_OUTPUT_VERBOSE((2, orte_rmcast_base.rmcast_output,
                         "%s rmcast:udp opening new channel %s:%s network %03d.%03d.%03d.%03d port %d for%s%s",
                         ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
                         chan->name, orte_rmcast_base_print_channel(chan->channel),
                         OPAL_IF_FORMAT_ADDR(chan->network),
                         (int)chan->port,
                         (ORTE_RMCAST_RECV & direction) ? " RECV" : " ",
                         (ORTE_RMCAST_XMIT & direction) ? " XMIT" : " "));

    if (ORTE_SUCCESS != (rc = setup_channel(chan, direction))) {
        ORTE_ERROR_LOG(rc);
        return rc;
    }
    
    return ORTE_SUCCESS;
}
Example #7
0
vrpn_Tracker_ButtonFly::vrpn_Tracker_ButtonFly
         (const char * name, vrpn_Connection * trackercon,
          vrpn_Tracker_ButtonFlyParam * params, float update_rate,
	  bool reportChanges) :
	vrpn_Tracker (name, trackercon),
	d_vel_scale(NULL),
	d_vel_scale_value(1.0),
	d_rot_scale(NULL),
	d_rot_scale_value(1.0),
	d_update_interval (update_rate ? (1/update_rate) : 1.0),
        d_reportChanges (reportChanges)
{
  int i;

  //--------------------------------------------------------------------
  // Copy the parameter values and initialize the values and pointers
  // in the list of axes.  The setup_channel() call opens the button
  // remote and sets up a callback to handle the changes.
  d_num_axes = params->num_axes;
  for (i = 0; i < params->num_axes; i++) {
    d_axes[i].axis = params->axes[i];
    d_axes[i].active = false;
    d_axes[i].bf = this;
    setup_channel(&d_axes[i]);
  }

  //--------------------------------------------------------------------
  // Open the scale analogs if they have non-NULL names.
  // If the name starts with the "*" character, use tracker
  //      connection rather than getting a new connection for it.
  // Set up a callback for each to set the scale factor.

  if (params->vel_scale_name != NULL) {

    // Copy the parameters into our member variables
    d_vel_scale_channel = params->vel_scale_channel;
    d_vel_scale_offset = params->vel_scale_offset;
    d_vel_scale_scale = params->vel_scale_scale;
    d_vel_scale_power = params->vel_scale_power;

    // Open the analog device and point the remote at it.
    // If the name starts with the '*' character, use
    // the server connection rather than making a new one.
    if (params->vel_scale_name[0] == '*') {
      d_vel_scale = new vrpn_Analog_Remote
             (&(params->vel_scale_name[1]), d_connection);
    } else {
      d_vel_scale = new vrpn_Analog_Remote(params->vel_scale_name);
    }

    // Set up the callback handler
    if (d_vel_scale == NULL) {
      fprintf(stderr,"vrpn_Tracker_ButtonFly: "
           "Can't open Analog %s\n",params->vel_scale_name);
    } else {
      // Set up the callback handler for the channel
      d_vel_scale->register_change_handler(this, handle_velocity_update);
    }
  }

  if (params->rot_scale_name != NULL) {

    // Copy the parameters into our member variables
    d_rot_scale_channel = params->rot_scale_channel;
    d_rot_scale_offset = params->rot_scale_offset;
    d_rot_scale_scale = params->rot_scale_scale;
    d_rot_scale_power = params->rot_scale_power;

    // Open the analog device and point the remote at it.
    // If the name starts with the '*' character, use
    // the server connection rather than making a new one.
    if (params->rot_scale_name[0] == '*') {
      d_rot_scale = new vrpn_Analog_Remote
             (&(params->rot_scale_name[1]), d_connection);
    } else {
      d_rot_scale = new vrpn_Analog_Remote(params->rot_scale_name);
    }

    // Set up the callback handler
    if (d_rot_scale == NULL) {
      fprintf(stderr,"vrpn_Tracker_ButtonFly: "
           "Can't open Analog %s\n",params->rot_scale_name);
    } else {
      // Set up the callback handler for the channel
      d_rot_scale->register_change_handler(this, handle_rotation_update);
    }
  }

  //--------------------------------------------------------------------
  // Whenever we get the first connection to this server, we also
  // want to reset the matrix to identity, so that you start at the
  // beginning. Set up a handler to do this.
  register_autodeleted_handler(d_connection->register_message_type
                                      (vrpn_got_first_connection),
		handle_newConnection, this);

  //--------------------------------------------------------------------
  // Set the initialization matrix to identity, then also set
  // the current matrix to identity.
  for ( i =0; i< 4; i++)
	  for (int j=0; j< 4; j++) 
		  d_initMatrix[i][j] = 0;

  d_initMatrix[0][0] = d_initMatrix[1][1] = d_initMatrix[2][2] =
                     d_initMatrix[3][3] = 1.0;
  reset();
}
Example #8
0
vrpn_Tracker_AnalogFly::vrpn_Tracker_AnalogFly
         (const char * name, vrpn_Connection * trackercon,
          vrpn_Tracker_AnalogFlyParam * params, float update_rate,
          bool absolute, bool reportChanges,
          bool worldFrame) :
	vrpn_Tracker (name, trackercon),
	d_update_interval (update_rate ? (1/update_rate) : 1.0),
	d_absolute (absolute),
	d_reportChanges (reportChanges),
	d_worldFrame (worldFrame),
	d_reset_button(NULL),
	d_which_button (params->reset_which),
	d_clutch_button(NULL),
	d_clutch_which (params->clutch_which),
	d_clutch_engaged(false),
	d_clutch_was_off(false)
{
	int i;

	d_x.axis = params->x; d_y.axis = params->y; d_z.axis = params->z;
	d_sx.axis = params->sx; d_sy.axis = params->sy; d_sz.axis = params->sz;

	d_x.ana = d_y.ana = d_z.ana = NULL;
	d_sx.ana = d_sy.ana = d_sz.ana = NULL;

	d_x.value = d_y.value = d_z.value = 0.0;
	d_sx.value = d_sy.value = d_sz.value = 0.0;

	d_x.af = this; d_y.af = this; d_z.af = this;
	d_sx.af = this; d_sy.af = this; d_sz.af = this;

	//--------------------------------------------------------------------
	// Open analog remotes for any channels that have non-NULL names.
	// If the name starts with the "*" character, use tracker
        //      connection rather than getting a new connection for it.
	// Set up callbacks to handle updates to the analog values
	setup_channel(&d_x);
	setup_channel(&d_y);
	setup_channel(&d_z);
	setup_channel(&d_sx);
	setup_channel(&d_sy);
	setup_channel(&d_sz);

	//--------------------------------------------------------------------
	// Open the reset button if is has a non-NULL name.
	// If the name starts with the "*" character, use tracker
        // connection rather than getting a new connection for it.
	// Set up callback for it to reset the matrix to identity.

	// If the name is NULL, don't do anything.
	if (params->reset_name != NULL) {

		// Open the button device and point the remote at it.
		// If the name starts with the '*' character, use
                // the server connection rather than making a new one.
		if (params->reset_name[0] == '*') {
                  try {
                    d_reset_button = new vrpn_Button_Remote
                    (&(params->reset_name[1]),
                      d_connection);
                  } catch (...) {
                    d_reset_button = NULL;
                  }
		} else {
                  try {
		    d_reset_button = new vrpn_Button_Remote
                      (params->reset_name);
                  } catch (...) {
                    d_reset_button = NULL;
                  }
		}
		if (d_reset_button == NULL) {
			fprintf(stderr,"vrpn_Tracker_AnalogFly: "
                             "Can't open Button %s\n",params->reset_name);
		} else {
			// Set up the callback handler for the channel
			d_reset_button->register_change_handler
                             (this, handle_reset_press);
		}
	}

	//--------------------------------------------------------------------
	// Open the clutch button if is has a non-NULL name.
	// If the name starts with the "*" character, use tracker
        // connection rather than getting a new connection for it.
	// Set up callback for it to control clutching.

	// If the name is NULL, don't do anything.
	if (params->clutch_name != NULL) {

		// Open the button device and point the remote at it.
		// If the name starts with the '*' character, use
                // the server connection rather than making a new one.
		if (params->clutch_name[0] == '*') {
                  try {
                    d_clutch_button = new vrpn_Button_Remote
                               (&(params->clutch_name[1]),
				d_connection);
                  } catch (...) {
                    d_clutch_button = NULL;
                  }
                } else {
                  try {
                    d_clutch_button = new vrpn_Button_Remote
                               (params->clutch_name);
                  } catch (...) {
                    d_clutch_button = NULL;
                  }
		}
		if (d_clutch_button == NULL) {
			fprintf(stderr,"vrpn_Tracker_AnalogFly: "
                             "Can't open Button %s\n",params->clutch_name);
		} else {
			// Set up the callback handler for the channel
			d_clutch_button->register_change_handler
                             (this, handle_clutch_press);
		}
	}

        // If the clutch button is NULL, then engage the clutch always.
        if (params->clutch_name == NULL) {
          d_clutch_engaged = true;
        }

	//--------------------------------------------------------------------
	// Whenever we get the first connection to this server, we also
        // want to reset the matrix to identity, so that you start at the
        // beginning. Set up a handler to do this.
	register_autodeleted_handler(d_connection->register_message_type(vrpn_got_first_connection),
		      handle_newConnection, this);

	//--------------------------------------------------------------------
	// Set the initialization matrix to identity, then also set
        // the current matrix to identity and the clutch matrix to
        // identity.
        for ( i =0; i< 4; i++) {
          for (int j=0; j< 4; j++)  {
	    d_initMatrix[i][j] = 0;
          }
        }

	d_initMatrix[0][0] = d_initMatrix[1][1] = d_initMatrix[2][2] =
                             d_initMatrix[3][3] = 1.0;
	reset();
        q_matrix_copy(d_clutchMatrix, d_initMatrix);
        q_matrix_copy(d_currentMatrix, d_initMatrix);

	//--------------------------------------------------------------------
	// Set the current timestamp to "now" and current matrix to identity
	// for absolute trackers.  This is done in case we never hear from the
	// analog devices.  Reset doesn't do this for absolute trackers.
	if (d_absolute) {
	    vrpn_gettimeofday(&d_prevtime, NULL);
	    vrpn_Tracker::timestamp = d_prevtime;
	    q_matrix_copy(d_currentMatrix, d_initMatrix);
	    convert_matrix_to_tracker();
	}
}
// buffer recv/send size limit
CASE_TEST(channel, io_stream_tcp_size_extended)
{
    atbus::channel::io_stream_channel svr, cli;
    atbus::channel::io_stream_conf conf;
    atbus::channel::io_stream_init_configure(&conf);
    conf.send_buffer_limit_size = conf.recv_buffer_max_size + 1;

    atbus::channel::io_stream_init(&svr, NULL, &conf);
    atbus::channel::io_stream_init(&cli, NULL, &conf);
    
    svr.evt.callbacks[atbus::channel::io_stream_callback_evt_t::EN_FN_RECVED] = recv_size_err_callback_check_fn;
    cli.evt.callbacks[atbus::channel::io_stream_callback_evt_t::EN_FN_RECVED] = recv_size_err_callback_check_fn;
    svr.evt.callbacks[atbus::channel::io_stream_callback_evt_t::EN_FN_DISCONNECTED] = disconnected_callback_test_fn;
    svr.evt.callbacks[atbus::channel::io_stream_callback_evt_t::EN_FN_DISCONNECTED] = disconnected_callback_test_fn;

    int check_flag = g_check_flag = 0;

    int inited_fds = 0;
    inited_fds += setup_channel(svr, "ipv6://:::16387", NULL);
    CASE_EXPECT_EQ(1, g_check_flag);
    CASE_EXPECT_NE(NULL, svr.ev_loop);

    inited_fds = 0;
    inited_fds += setup_channel(cli, NULL, "ipv4://127.0.0.1:16387");

    while (g_check_flag - check_flag < 2 * inited_fds) {
        atbus::channel::io_stream_run(&svr, atbus::adapter::RUN_NOWAIT);
        atbus::channel::io_stream_run(&cli, atbus::adapter::RUN_NOWAIT);
        CASE_THREAD_SLEEP_MS(8);
    }
    CASE_EXPECT_NE(0, cli.conn_pool.size());

    check_flag = g_check_flag;

    int res = atbus::channel::io_stream_send(cli.conn_pool.begin()->second.get(), get_test_buffer(), conf.recv_buffer_limit_size + 1);
    CASE_EXPECT_EQ(0, res);

    res = atbus::channel::io_stream_send(cli.conn_pool.begin()->second.get(), get_test_buffer(), conf.send_buffer_limit_size + 1);
    CASE_EXPECT_EQ(EN_ATBUS_ERR_INVALID_SIZE, res);

    while (g_check_flag - check_flag < 1) {
        atbus::channel::io_stream_run(&svr, atbus::adapter::RUN_NOWAIT);
        atbus::channel::io_stream_run(&cli, atbus::adapter::RUN_NOWAIT);
        CASE_THREAD_SLEEP_MS(32);
    }

    // 错误的数据大小会导致连接断开
    res = atbus::channel::io_stream_send(cli.conn_pool.begin()->second.get(), get_test_buffer(), conf.send_buffer_limit_size);
    CASE_EXPECT_EQ(0, res);

    // 有接收端关闭,所以一定是接收端先出发关闭连接。
    // 这里只要判定后触发方完成回调,那么先触发方必然已经完成
    while (!cli.conn_pool.empty()) {
        atbus::channel::io_stream_run(&svr, atbus::adapter::RUN_NOWAIT);
        atbus::channel::io_stream_run(&cli, atbus::adapter::RUN_NOWAIT);
        CASE_THREAD_SLEEP_MS(32);
    }

    CASE_EXPECT_EQ(0, cli.conn_pool.size());
    CASE_EXPECT_EQ(1, svr.conn_pool.size());

    atbus::channel::io_stream_close(&cli);
    atbus::channel::io_stream_close(&svr);
}
CASE_TEST(channel, io_stream_tcp_basic)
{
    atbus::adapter::loop_t loop;
    uv_loop_init(&loop);

    atbus::channel::io_stream_channel svr, cli;
    atbus::channel::io_stream_init(&svr, &loop, NULL);
    atbus::channel::io_stream_init(&cli, &loop, NULL);
    CASE_EXPECT_EQ(&loop, svr.ev_loop);
    CASE_EXPECT_EQ(&loop, cli.ev_loop);

    g_check_flag = 0;

    int inited_fds = 0;
    inited_fds += setup_channel(svr, "ipv6://:::16387", NULL);
    CASE_EXPECT_EQ(1, g_check_flag);
    CASE_EXPECT_NE(NULL, svr.ev_loop);
    
    if (0 == inited_fds) {
        uv_loop_close(&loop);
        return;
    }

    inited_fds = 0;
    inited_fds += setup_channel(cli, NULL, "ipv4://127.0.0.1:16387");
    inited_fds += setup_channel(cli, NULL, "dns://localhost:16387");
    inited_fds += setup_channel(cli, NULL, "ipv6://::1:16387");

    int check_flag = g_check_flag;
    while (g_check_flag - check_flag < 2 * inited_fds) {
        uv_run(&loop, UV_RUN_ONCE);
    }

    svr.evt.callbacks[atbus::channel::io_stream_callback_evt_t::EN_FN_RECVED] = recv_callback_check_fn;
    cli.evt.callbacks[atbus::channel::io_stream_callback_evt_t::EN_FN_RECVED] = recv_callback_check_fn;
    char* buf = get_test_buffer();

    check_flag = g_check_flag;
    // small buffer
    atbus::channel::io_stream_send(cli.conn_pool.begin()->second.get(), buf, 13);
    g_check_buff_sequence.push_back(std::make_pair(0, 13));
    atbus::channel::io_stream_send(cli.conn_pool.begin()->second.get(), buf + 13, 28);
    g_check_buff_sequence.push_back(std::make_pair(13, 28));
    atbus::channel::io_stream_send(cli.conn_pool.begin()->second.get(), buf + 13 + 28, 100);
    g_check_buff_sequence.push_back(std::make_pair(13 + 28, 100));

    // big buffer
    atbus::channel::io_stream_send(cli.conn_pool.begin()->second.get(), buf + 1024, 56 * 1024 + 3);
    g_check_buff_sequence.push_back(std::make_pair(1024, 56 * 1024 + 3));

    while (g_check_flag - check_flag < 4) {
        uv_run(&loop, UV_RUN_ONCE);
    }

    // many big buffer
    {
        check_flag = g_check_flag;
        atbus::channel::io_stream_channel::conn_pool_t::iterator it = svr.conn_pool.begin();
        // 跳过listen的socket
        if (it->second->addr.address == "ipv6://:::16387") {
            ++it;
        }

        size_t sum_size = 0;
        g_recv_rec = std::make_pair(0, 0);
        for (int i = 0; i < 153; ++ i) {
            size_t s = static_cast<size_t>(rand() % 2048);
            size_t l = static_cast<size_t>(rand() % 10240) + 20 * 1024;
            atbus::channel::io_stream_send(it->second.get(), buf + s, l);
            g_check_buff_sequence.push_back(std::make_pair(s, l));
            sum_size += l;
        }

        CASE_MSG_INFO() << "send " << sum_size << " bytes data with " << g_check_buff_sequence.size() << " packages done." << std::endl;

        while (g_check_flag - check_flag < 153) {
            uv_run(&loop, UV_RUN_ONCE);
        }

        CASE_MSG_INFO() << "recv " << g_recv_rec.second << " bytes data with " << g_recv_rec.first << " packages and checked done." << std::endl;
    }

    atbus::channel::io_stream_close(&svr);
    atbus::channel::io_stream_close(&cli);
    CASE_EXPECT_EQ(0, svr.conn_pool.size());
    CASE_EXPECT_EQ(0, cli.conn_pool.size());

    uv_loop_close(&loop);
}
Example #11
0
vrpn_Poser_Analog::vrpn_Poser_Analog(const char* name, vrpn_Connection * c, vrpn_Poser_AnalogParam* p, bool act_as_tracker) :
    vrpn_Poser(name, c),
    vrpn_Tracker(name, c),
    d_act_as_tracker(act_as_tracker)
{
    int i;

    //	register_server_handlers();

    // Make sure that we have a valid connection
    if (d_connection == NULL) {
	    fprintf(stderr,"vrpn_Poser_Analog: No connection\n");
	    return;
    }

    // Register a handler for the position change callback for this device
    if (register_autodeleted_handler(req_position_m_id,
		    handle_change_message, this, d_sender_id)) {
	    fprintf(stderr,"vrpn_Poser_Analog: can't register position handler\n");
	    d_connection = NULL;
    }

    // Register a handler for the velocity change callback for this device
    if (register_autodeleted_handler(req_velocity_m_id,
			handle_vel_change_message, this, d_sender_id)) {
	    fprintf(stderr,"vrpn_Poser_Analog: can't register velocity handler\n");
	    d_connection = NULL;
    }

    // Set up the axes
    x.axis = p->x; y.axis = p->y; z.axis = p->z;
    rx.axis = p->rx; ry.axis = p->ry; rz.axis = p->rz;

    x.ana = y.ana = z.ana = NULL;
    rx.ana = ry.ana = rz.ana = NULL;

    x.value = y.value = z.value = 0.0;
    rx.value = ry.value = rz.value = 0.0;

    x.pa = this; y.pa = this; z.pa = this;
    rx.pa = this; ry.pa = this; rz.pa = this;

    //--------------------------------------------------------------------
    // Open analog remotes for any channels that have non-NULL names.
    // If the name starts with the "*" character, use tracker
    //      connection rather than getting a new connection for it.
    setup_channel(&x);
    setup_channel(&y);
    setup_channel(&z);
    setup_channel(&rx);
    setup_channel(&ry);
    setup_channel(&rz);

    // Set up the workspace max and min values
    for (i = 0; i < 3; i++) {
        p_pos_min[i] = p->pos_min[i];
        p_pos_max[i] = p->pos_max[i];
        p_vel_min[i] = p->vel_min[i];
        p_vel_max[i] = p->vel_max[i];
        p_pos_rot_min[i] = p->pos_rot_min[i];
        p_pos_rot_max[i] = p->pos_rot_max[i];
        p_vel_rot_min[i] = p->vel_rot_min[i];
        p_vel_rot_max[i] = p->vel_rot_max[i];
    }

    // Check the pose for each channel against the max and min values of the workspace
    // and set it to the location closest to the origin.
    p_pos[0] = p_pos[1] = p_pos[2] = 0.0;
    p_quat[0] = p_quat[1] = p_quat[2] = 0.0; p_quat[3] = 1.0;
    for (i = 0; i < 3; i++) {
        if (p_pos[i] < p_pos_min[i]) {
            p_pos[i] = p_pos_min[i];
        }
        else if (p_pos[i] > p_pos_max[i]) {
            p_pos[i] = p_pos_max[i];
        }
    }
}
Example #12
0
int main(int argc, char *argv[])
{
	int daemonize = 0;
	char *pidfile = NULL;
	char *envarea = NULL;
	int cnid = -1;
	pcre *msgfilter = NULL;
	pcre *stdfilter = NULL;

	int argi;
	struct sigaction sa;
	RbtIterator handle;


	/* Dont save the error buffer */
	save_errbuf = 0;

	/* Create the peer container */
	peers = rbtNew(name_compare);

	for (argi=1; (argi < argc); argi++) {
		if (argnmatch(argv[argi], "--debug")) {
			debug = 1;
		}
		else if (argnmatch(argv[argi], "--channel=")) {
			char *cn = strchr(argv[argi], '=') + 1;

			for (cnid = C_STATUS; (channelnames[cnid] && strcmp(channelnames[cnid], cn)); cnid++) ;
			if (channelnames[cnid] == NULL) cnid = -1;
		}
		else if (argnmatch(argv[argi], "--daemon")) {
			daemonize = 1;
		}
		else if (argnmatch(argv[argi], "--no-daemon")) {
			daemonize = 0;
		}
		else if (argnmatch(argv[argi], "--pidfile=")) {
			char *p = strchr(argv[argi], '=');
			pidfile = strdup(p+1);
		}
		else if (argnmatch(argv[argi], "--log=")) {
			char *p = strchr(argv[argi], '=');
			logfn = strdup(p+1);
		}
		else if (argnmatch(argv[argi], "--env=")) {
			char *p = strchr(argv[argi], '=');
			loadenv(p+1, envarea);
		}
		else if (argnmatch(argv[argi], "--area=")) {
			char *p = strchr(argv[argi], '=');
			envarea = strdup(p+1);
		}
		else if (argnmatch(argv[argi], "--locator=")) {
			char *p = strchr(argv[argi], '=');
			locator_init(p+1);
			locatorbased = 1;
		}
		else if (argnmatch(argv[argi], "--service=")) {
			char *p = strchr(argv[argi], '=');
			locatorservice = get_servicetype(p+1);
		}
		else if (argnmatch(argv[argi], "--filter=")) {
			char *p = strchr(argv[argi], '=');
			msgfilter = compileregex(p+1);
			if (!msgfilter) {
				errprintf("Invalid filter (bad expression): %s\n", p+1);
			}
			else {
				stdfilter = compileregex("^@@(logrotate|shutdown|drophost|droptest|renamehost|renametest)");
			}
		}
		else {
			char *childcmd;
			char **childargs;
			int i = 0;

			childcmd = argv[argi];
			childargs = (char **) calloc((1 + argc - argi), sizeof(char *));
			while (argi < argc) { childargs[i++] = argv[argi++]; }
			addlocalpeer(childcmd, childargs);
		}
	}

	/* Sanity checks */
	if (cnid == -1) {
		errprintf("No channel/unknown channel specified\n");
		return 1;
	}
	if (locatorbased && (locatorservice == ST_MAX)) {
		errprintf("Must specify --service when using locator\n");
		return 1;
	}
	if (!locatorbased && (rbtBegin(peers) == rbtEnd(peers))) {
		errprintf("Must specify command for local worker\n");
		return 1;
	}

	/* Do cache responses to avoid doing too many lookups */
	if (locatorbased) locator_prepcache(locatorservice, 0);

	/* Go daemon */
	if (daemonize) {
		/* Become a daemon */
		pid_t daemonpid = fork();
		if (daemonpid < 0) {
			/* Fork failed */
			errprintf("Could not fork child\n");
			exit(1);
		}
		else if (daemonpid > 0) {
			/* Parent creates PID file and exits */
			FILE *fd = NULL;
			if (pidfile) fd = fopen(pidfile, "w");
			if (fd) {
				fprintf(fd, "%d\n", (int)daemonpid);
				fclose(fd);
			}
			exit(0);
		}
		/* Child (daemon) continues here */
		setsid();
	}

	/* Catch signals */
	setup_signalhandler("xymond_channel");
	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = sig_handler;
	sigaction(SIGINT, &sa, NULL);
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGCHLD, &sa, NULL);
	signal(SIGALRM, SIG_IGN);

	/* Switch stdout/stderr to the logfile, if one was specified */
	freopen("/dev/null", "r", stdin);	/* xymond_channel's stdin is not used */
	if (logfn) {
		freopen(logfn, "a", stdout);
		freopen(logfn, "a", stderr);
	}

	/* Attach to the channel */
	channel = setup_channel(cnid, CHAN_CLIENT);
	if (channel == NULL) {
		errprintf("Channel not available\n");
		running = 0;
	}

	while (running) {
		/* 
		 * Wait for GOCLIENT to go up.
		 *
		 * Note that we use IPC_NOWAIT if there are messages in the
		 * queue, because then we just want to pick up a message if
		 * there is one, and if not we want to continue pushing the
		 * queued data to the worker.
		 */
		struct sembuf s;
		int n;

		s.sem_num = GOCLIENT; s.sem_op  = -1; s.sem_flg = ((pendingcount > 0) ? IPC_NOWAIT : 0);
		n = semop(channel->semid, &s, 1);

		if (n == 0) {
			/*
			 * GOCLIENT went high, and so we got alerted about a new
			 * message arriving. Copy the message to our own buffer queue.
			 */
			char *inbuf = NULL;

			if (!msgfilter || matchregex(channel->channelbuf, msgfilter) || matchregex(channel->channelbuf, stdfilter)) {
				inbuf = strdup(channel->channelbuf);
			}

			/* 
			 * Now we have safely stored the new message in our buffer.
			 * Wait until any other clients on the same channel have picked up 
			 * this message (GOCLIENT reaches 0).
			 *
			 * We wrap this into an alarm handler, because it can occasionally
			 * fail, causing the whole system to lock up. We dont want that....
			 * We'll set the alarm to trigger after 1 second. Experience shows
			 * that we'll either succeed in a few milliseconds, or fail completely
			 * and wait the full alarm-timer duration.
			 */
			gotalarm = 0; signal(SIGALRM, sig_handler); alarm(2); 
			do {
				s.sem_num = GOCLIENT; s.sem_op  = 0; s.sem_flg = 0;
				n = semop(channel->semid, &s, 1);
			} while ((n == -1) && (errno == EAGAIN) && running && (!gotalarm));
			signal(SIGALRM, SIG_IGN);

			if (gotalarm) {
				errprintf("Gave up waiting for GOCLIENT to go low.\n");
			}

			/* 
			 * Let master know we got it by downing BOARDBUSY.
			 * This should not block, since BOARDBUSY is upped
			 * by the master just before he ups GOCLIENT.
			 */
			do {
				s.sem_num = BOARDBUSY; s.sem_op  = -1; s.sem_flg = IPC_NOWAIT;
				n = semop(channel->semid, &s, 1);
			} while ((n == -1) && (errno == EINTR));
			if (n == -1) {
				errprintf("Tried to down BOARDBUSY: %s\n", strerror(errno));
			}

			if (inbuf) {
				/*
				 * See if they want us to rotate logs. We pass this on to
				 * the worker module as well, but must handle our own logfile.
				 */
				if (strncmp(inbuf, "@@logrotate", 11) == 0) {
					freopen(logfn, "a", stdout);
					freopen(logfn, "a", stderr);
				}

				/*
				 * Put the new message on our outbound queue.
				 */
				if (addmessage(inbuf) != 0) {
					/* Failed to queue message, free the buffer */
					xfree(inbuf);
				}
			}
		}
		else {
			if (errno != EAGAIN) {
				dbgprintf("Semaphore wait aborted: %s\n", strerror(errno));
				continue;
			}
		}

		/* 
		 * We've picked up messages from the master. Now we 
		 * must push them to the worker process. Since there 
		 * is no way to hang off both a semaphore and select(),
		 * we'll just push as much data as possible into the 
		 * pipe. If we get to a point where we would block,
		 * then wait a teeny bit of time and restart the 
		 * whole loop with checking for new messages from the
		 * master etc.
		 *
		 * In theory, this could become an almost busy-wait loop.
		 * In practice, however, the queue will be empty most
		 * of the time because we'll just shove the data to the
		 * worker child.
		 */
		for (handle = rbtBegin(peers); (handle != rbtEnd(peers)); handle = rbtNext(peers, handle)) {
			int canwrite = 1, hasfailed = 0;
			xymon_peer_t *pwalk;
			time_t msgtimeout = gettimer() - MSGTIMEOUT;
			int flushcount = 0;

			pwalk = (xymon_peer_t *) gettreeitem(peers, handle);
			if (pwalk->msghead == NULL) continue; /* Ignore peers with nothing queued */

			switch (pwalk->peerstatus) {
			  case P_UP:
				canwrite = 1;
				break;

			  case P_DOWN:
				openconnection(pwalk);
				canwrite = (pwalk->peerstatus == P_UP);
				break;

			  case P_FAILED:
				canwrite = 0;
				break;
			}

			/* See if we have stale messages queued */
			while (pwalk->msghead && (pwalk->msghead->tstamp < msgtimeout)) {
				flushmessage(pwalk);
				flushcount++;
			}

			if (flushcount) {
				errprintf("Flushed %d stale messages for %s:%d\n",
					  flushcount,
				  	  inet_ntoa(pwalk->peeraddr.sin_addr), 
					  ntohs(pwalk->peeraddr.sin_port));
			}

			while (pwalk->msghead && canwrite) {
				fd_set fdwrite;
				struct timeval tmo;

				/* Check that this peer is ready for writing. */
				FD_ZERO(&fdwrite); FD_SET(pwalk->peersocket, &fdwrite);
				tmo.tv_sec = 0; tmo.tv_usec = 2000;
				n = select(pwalk->peersocket+1, NULL, &fdwrite, NULL, &tmo);
				if (n == -1) {
					errprintf("select() failed: %s\n", strerror(errno));
					canwrite = 0; 
					hasfailed = 1;
					continue;
				}
				else if ((n == 0) || (!FD_ISSET(pwalk->peersocket, &fdwrite))) {
					canwrite = 0;
					continue;
				}

				n = write(pwalk->peersocket, pwalk->msghead->bufp, pwalk->msghead->buflen);
				if (n >= 0) {
					pwalk->msghead->bufp += n;
					pwalk->msghead->buflen -= n;
					if (pwalk->msghead->buflen == 0) flushmessage(pwalk);
				}
				else if (errno == EAGAIN) {
					/*
					 * Write would block ... stop for now. 
					 */
					canwrite = 0;
				}
				else {
					hasfailed = 1;
				}

				if (hasfailed) {
					/* Write failed, or message grew stale */
					errprintf("Peer at %s:%d failed: %s\n",
						  inet_ntoa(pwalk->peeraddr.sin_addr), ntohs(pwalk->peeraddr.sin_port),
						  strerror(errno));
					canwrite = 0;
					shutdownconnection(pwalk);
					if (pwalk->peertype == P_NET) locator_serverdown(pwalk->peername, locatorservice);
					pwalk->peerstatus = P_FAILED;
				}
			}
		}
	}

	/* Detach from channels */
	close_channel(channel, CHAN_CLIENT);

	/* Close peer connections */
	for (handle = rbtBegin(peers); (handle != rbtEnd(peers)); handle = rbtNext(peers, handle)) {
		xymon_peer_t *pwalk = (xymon_peer_t *) gettreeitem(peers, handle);
		shutdownconnection(pwalk);
	}

	/* Remove the PID file */
	if (pidfile) unlink(pidfile);

	return 0;
}