コード例 #1
0
ファイル: context-vxworks.c プロジェクト: eswartz/emul
int context_resume(Context * ctx, int mode, ContextAddress range_start, ContextAddress range_end) {
    switch (mode) {
    case RM_RESUME:
        return context_continue(ctx);
    case RM_STEP_INTO:
        return context_single_step(ctx);
    case RM_TERMINATE:
        return context_terminate(ctx);
    }
    errno = ERR_UNSUPPORTED;
    return -1;
}
コード例 #2
0
ファイル: logger.c プロジェクト: freestylem2m/start
int logger_shutdown(context_t *ctx)
{
	logger_config_t *cf = (logger_config_t *) ctx->data;

	if( cf->logger ) {
		context_terminate( cf->logger );
		cf->logger = 0L;
	}

	if( cf->log_fd >= 0 ) {
		close( cf->log_fd );
		cf->log_fd = -1;
	}

	free(cf);
	return 1;
}
コード例 #3
0
ファイル: logger.c プロジェクト: freestylem2m/start
ssize_t logger_handler(context_t *ctx, event_t event, driver_data_t *event_data )
{
	event_data_t *data = 0L;

	logger_config_t *cf = (logger_config_t *) ctx->data;

	//x_printf(ctx, "<%s> Event = \"%s\" (%d)\n", ctx->name, event_map[event], event);

	if( event_data->type == TYPE_DATA )
		data = & event_data->event_data;

	switch( event ) {
		case EVENT_INIT:
			if(( cf->log_driver = config_get_item( ctx->config, "logdriver" ) )) {
				if( strchr( cf->log_driver, '/' ) )
					cf->log_fd = open( cf->log_driver, O_RDWR|O_APPEND|O_CREAT, 0777 );
				else
					start_service( &cf->logger, cf->log_driver, ctx->config, ctx, 0L );
			}
			cf->state = LOGGER_STATE_RUNNING;
		case EVENT_START:
			break;

		case EVENT_TERMINATE:
			context_terminate( ctx );
			break;

		case EVENT_DATA_INCOMING:
		case EVENT_DATA_OUTGOING:
        case EVENT_LOGGING:
			if( data ) {
				char *logbuffer = alloca( LOG_BUFFER_MAX );
				snprintf(logbuffer, LOG_BUFFER_MAX, "%s: %s", event_data->source?event_data->source->name:"(unknown)", (char *)data->data);
				logbuffer[LOG_BUFFER_MAX-1] = 0;
				time_t spec;
				char spec_buffer[32];

				if( cf->logger ) {
					driver_data_t log_event = { TYPE_DATA, .source = ctx, {} };
					log_event.event_data.data = logbuffer;
					log_event.event_data.bytes = strlen(logbuffer);
					emit(cf->logger, EVENT_DATA_OUTGOING, &log_event);
				} else {
コード例 #4
0
ファイル: unicorn.c プロジェクト: freestylem2m/start
ssize_t unicorn_handler(context_t *ctx, event_t event, driver_data_t *event_data)
{
	event_data_t   *data = 0L;
	event_child_t *child = 0L;

	unicorn_config_t *cf = (unicorn_config_t *) ctx->data;

	//x_printf(ctx, "<%s> Event = \"%s\" (%d)\n", ctx->name, event_map[event], event);

	if (event_data->type == TYPE_DATA)
		data = &event_data->event_data;
	else if( event_data->type == TYPE_CHILD )
		child = & event_data->event_child;

	switch (event) {
		case EVENT_INIT:
			{
				x_printf(ctx,"calling event add SIGQUIT\n");
				event_add( ctx, SIGQUIT, EH_SIGNAL );
				x_printf(ctx,"calling event add SIGTERM\n");
				event_add( ctx, SIGTERM, EH_SIGNAL );
				x_printf(ctx,"calling event 1000 EH_WANT_TICK\n");
				event_add( ctx, 1000, EH_WANT_TICK );

				cf->driver = config_get_item( ctx->config, "endpoint" );

				if( ! config_get_timeval( ctx->config, "retry", &cf->retry_time ) )
					cf->retry_time = 120*1000;

				if( cf->driver )
					start_service( &cf->modem, cf->driver, ctx->config, ctx, 0L );

				if( !cf->modem ) {
					logger( ctx, "Unable to launch modem driver. Exiting\n" );
					cf->state = UNICORN_STATE_ERROR;
					context_terminate( ctx );
					return -1;
				}

				cf->state = UNICORN_STATE_IDLE;
			}
			break;

		case EVENT_TERMINATE:
			{
				cf->pending_action_timeout = rel_time(0L);

				cf->flags |= UNICORN_TERMINATING; // In process of terminating the modem driver
				cf->state  = UNICORN_STATE_STOPPING; // In process of terminating self

				// Ensure 'exec' driver known not to restart when the modem driver terminates.
				// If the modem driver is something other than 'exec', this should be ignored.
				uint8_t flag = 0;
				driver_data_t notification = { TYPE_CUSTOM, ctx, {} };
				notification.event_custom = &flag;
				emit(cf->modem, EXEC_SET_RESPAWN, &notification);

				if( cf->driver_state == CMD_ST_ONLINE ) {
					x_printf(ctx,"Driver is online - sending disconnect\n");
					send_unicorn_command( ctx, CMD_DISCONNECT, CMD_ST_OFFLINE, 0, 0L );
				} else {
					x_printf(ctx,"Driver is offline - sending shutdown\n");
					send_unicorn_command( ctx, CMD_STATE, CMD_ST_OFFLINE, 0, 0L );
				}
			}
			break;

		case EVENT_RESTART:
			// This event is used to signal that the modem driver needs to resync.
			// set the 'reconnecting' flag and send a disconnect
			x_printf(ctx,"EVENT_RESTART: - sending disconnect to modem\n");
			//logger(ctx, "Sending disconnect command to modem driver");
			if( event_data->source == ctx->owner ) {
				cf->pending_action_timeout = rel_time(0L);
				cf->flags |= UNICORN_WAITING_FOR_CONNECT;
				if( cf->modem ) {
					x_printf(ctx, "Sending CMD_DISCONNECT to modem driver (%s)\n",cf->modem->name);
					if( (event_data->type == TYPE_CUSTOM) && event_data->event_custom ) {
						logger(ctx, "Sending abort command to modem driver due to unexpected disconnect");
						send_unicorn_command( ctx, CMD_ABORT, CMD_ST_OFFLINE, 0, 0L );
					} else {
						logger(ctx, "Sending disconnect command to modem driver");
						send_unicorn_command( ctx, CMD_DISCONNECT, CMD_ST_OFFLINE, 0, 0L );
					}
				} else {
					x_printf(ctx, "Modem driver not running.. doing nothing.\n");
				}
			} else {
				x_printf(ctx,"Forwarding EVENT_RESTART to owner (%s)\n",ctx->name);
				emit2( ctx, EVENT_RESTART, event_data);
			}
			break;

		case EVENT_CHILD:
			x_printf(ctx,"Got a message from a child (%s:%d).. probably starting\n", child->ctx->name, child->action);
			if ( child->ctx == cf->modem ) {
				if( child->action == CHILD_STARTING ) {
					cf->state = UNICORN_STATE_RUNNING;
					cf->flags &= ~(unsigned int) UNICORN_RESTARTING;
					// Assume ensure the first time the modem driver starts it skips the connection delay
					cf->flags |= UNICORN_FIRST_START;
				}

				if ( child->action == CHILD_STOPPED ) {
					x_printf(ctx,"Modem driver terminated - restart or terminate\n");
					// modem driver terminated.  Restart or exit.
					cf->state = UNICORN_STATE_IDLE;
					if ( cf->flags & UNICORN_TERMINATING ) {
						x_printf(ctx,"Terminating immediately\n");
						context_terminate( ctx );
					} else {
						x_printf(ctx,"Need to restart modem driver\n");
						cf->flags |= UNICORN_RESTARTING;
						cf->pending_action_timeout = rel_time(0L);
						// Reset the driver state, and notify the parent that we are offline
						cf->driver_state = CMD_ST_UNKNOWN;
						context_owner_notify( ctx, CHILD_EVENT, UNICORN_MODE_OFFLINE );
					}
				}
			}
			break;

		case EVENT_DATA_INCOMING:
		case EVENT_DATA_OUTGOING:
			if( event_data->source == cf->modem ) {

				size_t bytes = data->bytes;
				size_t offset = 0;

				while( bytes ) {

					size_t to_read = u_ringbuf_avail( &cf->input );
					if( to_read > bytes )
						to_read = bytes;

					u_ringbuf_write( &cf->input, &((char *)data->data)[offset], to_read );

					bytes -= to_read;
					offset += to_read;

					while(process_unicorn_packet(ctx) >= 0);
				}

				return (ssize_t) offset;
			} else {
				send_unicorn_command( ctx, CMD_DATA, CMD_ST_ONLINE, data->bytes,data->data);
				return (ssize_t) data->bytes;
			}

			break;

		case EVENT_READ:
			break;

		case EVENT_EXCEPTION:
			break;

		case EVENT_SIGNAL:
			x_printf(ctx,"Woa! Got a sign from the gods... %d\n", event_data->event_signal);
			if( event_data->event_signal == SIGQUIT || event_data->event_signal == SIGTERM )
				emit( ctx, EVENT_TERMINATE, 0L );
			break;

		case EVENT_TICK:
			{
				time_t now = rel_time(0L);

				// Handle case where a massive time shift due to NTP resync causes all timeouts to fire simultaneously
				// This is technically deprecated due to the use of rel_time()
				if( (now - cf->last_message) > MAXIMUM_SAFE_TIMEDELTA ) {
					logger(ctx, "WARNING: Resetting timeout due to RTC time change");
					cf->last_message = now;
				}

				if( ((now - cf->last_message) > UNICORN_KEEPALIVE_TIMEOUT ) && ( cf->driver_state != CMD_ST_UNKNOWN )) {

					if( ~ cf->flags & UNICORN_LAGGED ) {
						// Its been a couple of minutes since the last keepalive, reset the driver_state
						// to unknown and prompt for one.
						logger(ctx,"Forcing connection state request due to communications timeout.\n");
						cf->flags |= UNICORN_LAGGED;
						cf->retry_count = UNICORN_KEEPALIVE_RETRY_MAX;
					}

					if( cf->retry_count ) {
						send_unicorn_command( ctx, CMD_STATE, CMD_ST_OFFLINE, 0, 0L );
						cf->retry_count --;
					} else {
						// Its been a long time since the last message, despite prompting for one
						// restart the modem driver

						logger(ctx, "Communications timeout. Restarting modem driver.");
						uint8_t sig = SIGHUP;
						driver_data_t notification = { TYPE_CUSTOM, ctx, {} };
						notification.event_custom = &sig;

						emit( cf->modem, EVENT_RESTART, &notification );
					}
					cf->last_message = now;
				}

				if( (cf->flags & UNICORN_RESTARTING) && ((now - cf->pending_action_timeout) > UNICORN_RESTART_DELAY )) {
					x_printf(ctx,"Restart delay expired - restarting modem driver\n");
					cf->pending_action_timeout = rel_time(0L);
					if( cf->driver )
						start_service( &cf->modem, cf->driver, ctx->config, ctx, 0L );
				} else if( (cf->flags & UNICORN_RECONNECTING) && ((now - cf->pending_action_timeout) > cf->retry_time )) {
					x_printf(ctx,"Reconnect delay expired - attempting reconnect\n");
					cf->pending_action_timeout = rel_time(0L);
					cf->flags &= ~(unsigned int)UNICORN_RECONNECTING;
					if( cf->modem )
						send_unicorn_command(ctx, CMD_CONNECT, CMD_ST_ONLINE, 0, 0 );
				} else if( (cf->flags & UNICORN_WAITING_FOR_CONNECT) && ((now - cf->pending_action_timeout) > UNICORN_CONNECT_TIMEOUT )) {
					x_printf(ctx,"Timeout during connect - terminating modem driver\n");
					cf->flags &= ~(unsigned int) UNICORN_WAITING_FOR_CONNECT;
					cf->state = UNICORN_STATE_IDLE;
					if( cf->modem )
						emit( cf->modem, EVENT_TERMINATE, 0L );
				}

				if( (cf->flags & UNICORN_TERMINATING) && ((now - cf->pending_action_timeout) > UNICORN_PROCESS_TERMINATION_TIMEOUT)) {
					x_printf(ctx,"termination timeout - killing the modem driver with prejudice\n");
					cf->state = UNICORN_STATE_IDLE;
					if( cf->modem )
						context_terminate( cf->modem );
					context_terminate( ctx );
				}

				// Special case.. If I am expecting a data frame, and it takes too long to arrive,
				// reset state.
				if( (cf->flags & UNICORN_EXPECTING_DATA) && ((now - cf->last_message) > FRAME_TIMEOUT)) {
					x_printf(ctx,"FRAME TIMEOUT - resetting input buffer\n");
					u_ringbuf_init( &cf->input );
					cf->flags &= ~(unsigned int)UNICORN_EXPECTING_DATA;
				}

#ifndef NDEBUG
				size_t bytes = u_ringbuf_ready( &cf->input );
				if( bytes )
					x_printf(ctx,"Un-processed data in ring buffer... %d bytes\n",(int)bytes);
#endif
			}
			break;

		default:
			x_printf(ctx,"\n *\n *\n * Emitted some kind of event \"%s\" (%d)\n *\n *\n", event_map[event], event);
	}
	return 0;
}
コード例 #5
0
ファイル: syslog.c プロジェクト: freestylem2m/start
ssize_t syslog_handler(context_t *ctx, event_t event, driver_data_t *event_data)
{
	event_data_t *data = 0L;

	syslog_config_t *cf = (syslog_config_t *) ctx->data;

	//x_printf(ctx, "<%s> Event = \"%s\" (%d)\n", ctx->name, event_map[event], event);

	if( event_data->type == TYPE_DATA )
		data = & event_data->event_data;

	switch (event) {
		case EVENT_INIT:
			{
				const char *options  = get_env( ctx, "options" );
				const char *facility = get_env( ctx, "facility" );
				const char *priority = get_env( ctx, "prio" );

				if( options ) {
					if( (cf->options = syslog_options_lookup( options )) < 0) {
						fprintf(stderr,"Warning: invalid options specified for syslog %s\n",options );
						cf->options = LOG_PID;
					}
				} else
					cf->options = LOG_PID;

				if( facility ) {
					if( (cf->facility = syslog_options_lookup( facility )) < 0) {
						fprintf(stderr,"Warning: invalid syslog facility %s. Defaulting to USER\n",facility);
						cf->facility = LOG_USER;
					}
				} else
					cf->facility = LOG_USER;

				if( priority ) {
					if( (cf->prio = syslog_options_lookup( priority )) < 0) {
						fprintf(stderr,"Warning: invalid syslog priority %s. Defaulting to NOTICE\n",facility);
						cf->facility = LOG_NOTICE;
					}
				} else
					cf->facility = LOG_NOTICE;

				cf->ident = get_env( ctx, "ident" );

				if( !cf->ident )
					cf->ident = programname;
			}

		case EVENT_START:
			openlog( cf->ident, cf->options, cf->facility );
			break;

		case EVENT_TERMINATE:
			context_terminate(ctx);
			break;

		case EVENT_DATA_INCOMING:
		case EVENT_DATA_OUTGOING:
		case EVENT_LOGGING:
			syslog( cf->prio, "%s", (char *) data->data );
			break;

		default:
			break;
	}
	return 0;
}
コード例 #6
0
ファイル: dns.c プロジェクト: freestylem2m/start
ssize_t dns_handler(context_t *ctx, event_t event, driver_data_t *event_data )
{
	dns_config_t *cf = (dns_config_t *) ctx->data;

	x_printf(ctx, "<%s> Event = \"%s\" (%d)\n", ctx->name, event_map[event], event);

	switch( event ) {
		case EVENT_INIT:
			if( event_data->type == TYPE_CUSTOM && event_data->event_custom ) {
				dns_conf_t *init = (dns_conf_t *) (event_data->event_custom);
				dns_load_servers( ctx, init->dns_resolver );

				cf->dns_timeout = init->dns_timeout;
				cf->current_host = strdup( init->dns_host );
			} else {
				const char *resolver = config_get_item( ctx->config, "resolver" );
				const char *host = config_get_item( ctx->config, "host" );

				if( ! config_get_timeval( ctx->config, "timeout", & cf->dns_timeout ))
					cf->dns_timeout = DNS_DEFAULT_TIMEOUT;

				if( ! config_get_intval( ctx->config, "retry", & cf->dns_max_retry ))
					cf->dns_max_retry = 5;

				dns_load_servers(ctx, resolver);
				cf->current_host = strdup( host );
				if( cf->dns_max_retry < cf->dns_max_servers )
					cf->dns_max_retry = cf->dns_max_servers;
			}

			cf->sock_fd = dns_resolve_host( ctx, cf->current_host );

			if( cf->sock_fd >= 0 ) {
				cf->dns_retries = cf->dns_max_retry ;
				cf->dns_timer = event_alarm_add( ctx, cf->dns_timeout, ALARM_TIMER );
				event_add( ctx, cf->sock_fd, EH_READ );
				x_printf(ctx,"attempting to resolve hostname %s (%d attempts)\n",cf->current_host, cf->dns_retries );
			} else {
				x_printf(ctx,"Failed to send query to socket...\n");
			}

		case EVENT_START:
			cf->state = DNS_STATE_RUNNING;
			break;

		case EVENT_TERMINATE:
			context_terminate( ctx );
			break;

		case EVENT_ALARM:
			{
				if( event_data->event_alarm == cf->dns_timer ) {
#ifdef ENABLE_GETADDRINFO
					// This is entirely pointless, because it can't block!!
					if( (cf->flags & DNS_NETWORK_UP) && (cf->flags & DNS_DNS_ENABLE) ) {
						x_printf(ctx,"Attempting DNS resolver check for %s\n",cf->dns_host);
						struct addrinfo *addrinfo = NULL;
						int rc = getaddrinfo( cf->dns_host, NULL, NULL, &addrinfo );
						if( rc == 0 ) {
							x_printf(ctx,"Name resolver completed..\n");
							freeaddrinfo( addrinfo );
						} else {
							x_printf(ctx,"Failure performing DNS name resolution.   Disconnecting network\n");
							logger(ctx,"Failure performing DNS name resolution.   Disconnecting network");
						}
					}
#endif
					x_printf(ctx,"TIMEOUT: dns failed to respond, trying next server\n");
					if( cf->sock_fd >= 0 ) {
						close( cf->sock_fd );
						cf->sock_fd = -1;
						event_delete( ctx, cf->sock_fd, EH_NONE );
					}

					if( cf->dns_retries-- > 0 ) {
						cf->dns_current = ( cf->dns_current + 1 ) % cf->dns_max_servers;
						cf->sock_fd = dns_resolve_host( ctx, cf->current_host );

						if( cf->sock_fd >= 0 ) {
							cf->dns_timer = event_alarm_add( ctx, cf->dns_timeout, ALARM_TIMER );
							event_add( ctx, cf->sock_fd, EH_READ );
						}
					} else {
						x_printf(ctx,"DNS RETRIES EXHAUSTED. Terminating\n");
						context_owner_notify( ctx, CHILD_EVENT, 0 );
						context_terminate( ctx );
					}

				}
			}
			break;

		case EVENT_READ:
			if( event_data->event_request.fd == cf->sock_fd ) {
				x_printf(ctx,"Got a read event on file descriptor %ld\n",event_data->event_request.fd);
				in_addr_t rc = dns_handle_dns_response( ctx, &( event_data->event_request ));
				x_printf(ctx, "handle response returned %d (0x%08x) (%s)\n", ntohl(rc), ntohl(rc), inet_ntoa( *(struct in_addr *) &rc ));

				if( rc == (unsigned long) -1 ) {
					x_printf(ctx,"Error reading from socket, skipping\n");
				} else {
					event_alarm_delete( ctx, cf->dns_timer );
					event_delete( ctx, cf->sock_fd, EH_NONE );
					close( cf->sock_fd );
					cf->sock_fd = -1;

					context_owner_notify( ctx, CHILD_EVENT, rc );
					context_terminate( ctx );
				}
			}

			break;

        default:
            x_printf(ctx,"\n *\n *\n * Emitted some kind of event \"%s\" (%d)\n *\n *\n", event_map[event], event);
    }
    return 0;
}