예제 #1
0
static void
free_observer(struct smcp_observer_s *observer) {
	smcp_observable_t const context = observer->observable;
	int8_t i = observer - observer_table;
#if SMCP_EMBEDDED
	smcp_t const interface = smcp_get_current_instance();
#else
	if(!observer->observable)
		goto bail;
	smcp_t const interface = observer->observable->interface;
#endif

	smcp_transaction_end(interface, &observer->transaction);

	if((context->first_observer==i+1) && (context->last_observer==i+1)) {
		context->first_observer = context->last_observer = 0;
	} else if(context->first_observer==i+1) {
		context->first_observer = observer_table[i].next;
	} else {
		int8_t prev;
		for(prev = context->first_observer-1; prev>=0; i = observer_table[i].next - 1) {
			if(observer_table[prev].next == i)
				break;
		}

		observer_table[prev].next = observer_table[i].next;

		if(context->last_observer == i+1)
			context->last_observer = prev;
	}

bail:
	smcp_finish_async_response(&observer->async_response);
	return;
}
예제 #2
0
smcp_status_t
plugtest_separate_handler(
	smcp_node_t		node
) {
	struct smcp_async_response_s* async_response = NULL;
	smcp_transaction_t transaction = NULL;
	smcp_status_t ret = SMCP_STATUS_NOT_ALLOWED;
	smcp_method_t method = smcp_inbound_get_code();

	if(method==COAP_METHOD_GET) {
		if(smcp_inbound_is_dupe()) {
			smcp_outbound_begin_response(COAP_CODE_EMPTY);
			smcp_outbound_send();
			ret = SMCP_STATUS_OK;
			goto bail;
		}

		async_response = calloc(sizeof(struct smcp_async_response_s),1);
		if(!async_response) {
			ret = SMCP_STATUS_MALLOC_FAILURE;
			goto bail;
		}

#if !SMCP_AVOID_PRINTF || VERBOSE_DEBUG
		printf("This request needs an async response. %p\n",async_response);
#endif

		transaction = smcp_transaction_init(
			NULL,
			SMCP_TRANSACTION_DELAY_START|SMCP_TRANSACTION_ALWAYS_INVALIDATE,
			&plugtest_separate_async_resend_response,
			&plugtest_separate_async_ack_handler,
			(void*)async_response
		);
		if(!transaction) {
			free(async_response);
			// TODO: Consider dropping instead...?
			ret = SMCP_STATUS_MALLOC_FAILURE;
			goto bail;
		}

		ret = smcp_transaction_begin(
			smcp_get_current_instance(),
			transaction,
			(smcp_inbound_get_packet()->tt==COAP_TRANS_TYPE_CONFIRMABLE)?(smcp_cms_t)(COAP_MAX_TRANSMIT_WAIT*MSEC_PER_SEC):1
		);
		if(SMCP_STATUS_OK != ret) {
			smcp_transaction_end(smcp_get_current_instance(),transaction);
			goto bail;
		}

		ret = smcp_start_async_response(async_response,0);
		if(ret) { goto bail; }

		async_response = NULL;
	}

bail:
	return ret;
}
예제 #3
0
int
tool_cmd_delete(
	smcp_t smcp, int argc, char* argv[]
) {
	previous_sigint_handler = signal(SIGINT, &signal_interrupt);
	smcp_transaction_t transaction;

	char url[1000] = "";

	if((2 == argc) && (0 == strcmp(argv[1], "--help"))) {
		printf("Help not yet implemented for this command.\n");
		return ERRORCODE_HELP;
	}

	gRet = ERRORCODE_UNKNOWN;

	if (getenv("SMCP_CURRENT_PATH")) {
		strncpy(url, getenv("SMCP_CURRENT_PATH"), sizeof(url));
	}

	if (argc == 2) {
		url_change(url, argv[1]);
	} else {
		fprintf(stderr, "Bad args.\n");
		gRet = ERRORCODE_BADARG;
		goto bail;
	}

	require((transaction=send_delete_request(smcp, url)), bail);

	gRet = ERRORCODE_INPROGRESS;

	while(ERRORCODE_INPROGRESS == gRet) {
		smcp_plat_wait(smcp, 1000);
		smcp_plat_process(smcp);
	}

	smcp_transaction_end(smcp, transaction);

bail:
	signal(SIGINT, previous_sigint_handler);
	return gRet;
}
예제 #4
0
bool send_get_request(smcp_t smcp, const char* next, coap_size_t nextlen, void *thingML_context) {
    bool ret = false;
    smcp_status_t status = 0;
    int flags = SMCP_TRANSACTION_ALWAYS_INVALIDATE;
    gRet = ERRORCODE_INPROGRESS;

    retries = 0;

    if(get_observe)
        flags |= SMCP_TRANSACTION_OBSERVE;
    if(get_keep_alive)
        flags |= SMCP_TRANSACTION_KEEPALIVE;

    smcp_transaction_end(smcp,&transaction);
    smcp_transaction_init(
        &transaction,
        flags, // Flags
        (void*)&resend_get_request,
        (void*)&get_response_handler,
        thingML_context
    );

    status = smcp_transaction_begin(smcp, &transaction, get_timeout);

    if(status) {
        check(!status);
        fprintf(stderr,
                "smcp_begin_transaction_old() returned %d(%s).\n",
                status,
                smcp_status_to_cstr(status));
        goto bail;
    }

    ret = true;

bail:
    return ret;
}
예제 #5
0
int
tool_cmd_get_url(void *thingML_context) {
    ThingMLCOAPContext* context = (ThingMLCOAPContext*) thingML_context;

    get_show_headers = context->client_coap_config.get_show_headers;
    next_len = context->client_coap_config.next_len;
    redirect_count = context->client_coap_config.redirect_count;
    size_request = context->client_coap_config.size_request;
    get_observe = context->client_coap_config.get_observe;
    get_keep_alive = context->client_coap_config.get_keep_alive;
    get_timeout = context->client_coap_config.get_timeout; // Default timeout is 30 seconds.
    last_observe_value = context->client_coap_config.last_observe_value;
    request_accept_type = context->client_coap_config.request_accept_type;
    observe_once = context->client_coap_config.observe_once;
    observe_ignore_first = context->client_coap_config.observe_ignore_first;
    get_tt = context->client_coap_config.get_tt;

    smcp_t gSMCPInstance = smcp_create(((ThingMLCOAPContext*) thingML_context)->port);

    gRet = ERRORCODE_INPROGRESS;
    require(send_get_request(gSMCPInstance, NULL, 0, thingML_context), bail);


    while(ERRORCODE_INPROGRESS == gRet) {
        smcp_wait(gSMCPInstance,1000);
        smcp_process(gSMCPInstance);
    }

bail:
    smcp_transaction_end(gSMCPInstance,&transaction);

    if(gSMCPInstance)
        smcp_release(gSMCPInstance);

    return gRet;
}
예제 #6
0
파일: cgi-node.c 프로젝트: robbie-cao/smcp
smcp_status_t
cgi_node_send_next_block(cgi_node_t node,cgi_node_request_t request) {
	smcp_status_t ret = 0;

	// If we are currently asynchronous, go ahead and send an asynchronous response.
	// Otherwise, we don't have much to do: We will just go ahead and send
	// the rest of the data at the next query.

	// TODO: Writeme!

	smcp_transaction_t transaction = smcp_transaction_init(
		request->transaction,
		0,
		&cgi_node_async_resend_response,
		&cgi_node_async_ack_handler,
		(void*)request
	);
	if(!transaction) {
		ret = SMCP_STATUS_MALLOC_FAILURE;
		goto bail;
	}

	ret = smcp_transaction_begin(
		node->interface,
		transaction,
		30*MSEC_PER_SEC
	);
	if(ret) {
		smcp_transaction_end(smcp_get_current_instance(),transaction);
		goto bail;
	}


bail:
	return ret;
}
예제 #7
0
bool
test_simple(smcp_t smcp, test_data_s *test_data, const char* url, const char* rel, coap_code_t outbound_code,coap_transaction_type_t outbound_tt,coap_code_t expected_code, int extra)
{
	smcp_cms_t timeout = 15*MSEC_PER_SEC;
	smcp_status_t status;
	smcp_transaction_t transaction = NULL;
	int t_flags = SMCP_TRANSACTION_ALWAYS_INVALIDATE | SMCP_TRANSACTION_NO_AUTO_END;
	smcp_timestamp_t expiry = smcp_plat_cms_to_timestamp(timeout+MSEC_PER_SEC);
	memset(test_data,0,sizeof(*test_data));
	test_data->outbound_code = outbound_code;
	test_data->outbound_tt = outbound_tt;
	test_data->expected_code = expected_code;
	test_data->extra = extra;
	test_data->outbound_content_type = COAP_CONTENT_TYPE_UNKNOWN;
	if (extra & EXT_BLOCK_01) {
		test_data->outbound_content_type = COAP_CONTENT_TYPE_TEXT_PLAIN;
		test_data->block1_option = (2 | (1<<3));	// 64 byte block size;
	}
	if(strlen(url) && (url[strlen(url)-1] == '/')) {
		snprintf(test_data->url,sizeof(test_data->url), "%s%s",url,rel);
	} else {
		snprintf(test_data->url,sizeof(test_data->url), "%s/%s",url,rel);
	}

	if (extra & EXT_OBS_01) {
		t_flags = SMCP_TRANSACTION_OBSERVE;
	}

	test_data->start_time = smcp_plat_cms_to_timestamp(0);
	transaction = smcp_transaction_init(
		transaction,
		t_flags,
		(void*)&resend_test_request,
		(void*)&response_test_handler,
		(void*)test_data
	);
	test_data->transaction = transaction;

	status = smcp_transaction_begin(
		smcp,
		transaction,
		timeout
	);

	require_noerr(status, bail);

	while(!test_data->finished && (smcp_plat_timestamp_to_cms(expiry)>0)) {
		status = smcp_plat_wait(smcp, smcp_plat_timestamp_to_cms(expiry));
		require((status==SMCP_STATUS_OK) || (status==SMCP_STATUS_TIMEOUT), bail);

		status = smcp_plat_process(smcp);
		require_noerr(status, bail);
	}

	test_data->stop_time = smcp_plat_cms_to_timestamp(0);

	test_data->failed = true;

	require(smcp_plat_timestamp_to_cms(expiry)>0, bail);
	require(test_data->inbound_code == test_data->expected_code,bail);
	if (expected_code == COAP_CODE_EMPTY) {
		require(test_data->error == SMCP_STATUS_RESET, bail);
	} else {
		require(test_data->error == SMCP_STATUS_OK, bail);
	}
	test_data->failed = false;

bail:
	if (transaction) {
		smcp_transaction_end(smcp, transaction);
	}
	return (status == SMCP_STATUS_OK) && !test_data->failed;
}
예제 #8
0
파일: cgi-node.c 프로젝트: robbie-cao/smcp
smcp_status_t
cgi_node_request_change_state(cgi_node_t node, cgi_node_request_t request, cgi_node_state_t new_state) {
	// TODO: Possibly do more later...?

	syslog(LOG_INFO, "cgi-node: %d -> %d", request->state, new_state);

	if(request->state == new_state) {
		// Same state, do nothing.
	} else

	if ( request->state == CGI_NODE_STATE_INACTIVE
	  && new_state == CGI_NODE_STATE_ACTIVE_BLOCK1_WAIT_REQ
	) {

	} else if ( request->state == CGI_NODE_STATE_ACTIVE_BLOCK1_WAIT_REQ
	         && new_state == CGI_NODE_STATE_ACTIVE_BLOCK1_WAIT_FD
	) {
		smcp_start_async_response(&request->async_response, 0);

	} else if ( request->state == CGI_NODE_STATE_ACTIVE_BLOCK1_WAIT_FD
	         && new_state == CGI_NODE_STATE_ACTIVE_BLOCK1_WAIT_ACK
	) {
		cgi_node_send_next_block(node,request);

	} else if ( request->state == CGI_NODE_STATE_ACTIVE_BLOCK1_WAIT_ACK
	         && new_state == CGI_NODE_STATE_ACTIVE_BLOCK1_WAIT_REQ
	) {
		if (request->transaction) {
			smcp_transaction_end(smcp_get_current_instance(),request->transaction);
			request->transaction = NULL;
		}

	} else if ( ( (request->state == CGI_NODE_STATE_ACTIVE_BLOCK2_WAIT_REQ)
	           || (request->state == CGI_NODE_STATE_ACTIVE_BLOCK1_WAIT_REQ)
	            )
	         && ( new_state == CGI_NODE_STATE_ACTIVE_BLOCK2_WAIT_FD)
	) {
		if(!request->stdin_buffer_len &&  request->fd_cmd_stdin>=0) {
			close(request->fd_cmd_stdin);
			request->fd_cmd_stdin = -1;
		}
		smcp_start_async_response(&request->async_response, 0);
	} else if(request->state == CGI_NODE_STATE_ACTIVE_BLOCK2_WAIT_FD
		&& new_state == CGI_NODE_STATE_ACTIVE_BLOCK2_WAIT_ACK
	) {
		if(!request->stdin_buffer_len &&  request->fd_cmd_stdin>=0) {
			close(request->fd_cmd_stdin);
			request->fd_cmd_stdin = -1;
		}
		cgi_node_send_next_block(node,request);
	} else if(request->state == CGI_NODE_STATE_ACTIVE_BLOCK2_WAIT_ACK
		&& new_state == CGI_NODE_STATE_ACTIVE_BLOCK2_WAIT_REQ
	) {
		if(!request->stdin_buffer_len &&  request->fd_cmd_stdin>=0) {
			close(request->fd_cmd_stdin);
			request->fd_cmd_stdin = -1;
		}
		//cgi_node_request_pop_bytes_from_stdout(request,(1<<((request->block2&0x7)+4)));
		if(request->transaction) {
			smcp_transaction_end(smcp_get_current_instance(),request->transaction);
			request->transaction = NULL;
		}
	} else if(new_state == CGI_NODE_STATE_FINISHED) {
		if(request->transaction) {
			smcp_transaction_end(smcp_get_current_instance(),request->transaction);
			request->transaction = NULL;
		}
		close(request->fd_cmd_stdin);
		request->fd_cmd_stdin = -1;
		close(request->fd_cmd_stdout);
		request->fd_cmd_stdout = -1;
		if(request->pid != 0 && request->pid != -1) {
			int status;
			kill(request->pid,SIGTERM);
			if(waitpid(request->pid, &status, WNOHANG) == request->pid) {
				request->pid = 0;
			}
		}
	} else {
		// INVALID STATE TRANSITION!
		syslog(LOG_ERR, "cgi-node: BAD STATE CHANGE: %d -> %d", request->state, new_state);
		abort();
	}

	request->state = new_state;

	return SMCP_STATUS_OK;
}