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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }