static smcp_status_t delete_response_handler( int statuscode, void* context ) { if (statuscode >= 0) { char* content = (char*)smcp_inbound_get_content_ptr(); coap_size_t content_length = smcp_inbound_get_content_len(); if(content_length>(smcp_inbound_get_packet_length()-4)) { fprintf(stderr, "INTERNAL ERROR: CONTENT_LENGTH LARGER THAN PACKET_LENGTH-4! (content_length=%u, packet_length=%u)\n",content_length,smcp_inbound_get_packet_length()); gRet = ERRORCODE_UNKNOWN; goto bail; } if (delete_show_headers) { coap_dump_header( stdout, NULL, smcp_inbound_get_packet(), smcp_inbound_get_packet_length() ); } if(!coap_verify_packet((void*)smcp_inbound_get_packet(), smcp_inbound_get_packet_length())) { fprintf(stderr, "INTERNAL ERROR: CALLBACK GIVEN INVALID PACKET!\n"); gRet = ERRORCODE_UNKNOWN; goto bail; } if (statuscode != COAP_RESULT_202_DELETED) { fprintf(stderr, "delete: Result code = %d (%s)\n", statuscode, (statuscode < 0) ? smcp_status_to_cstr( statuscode) : coap_code_to_cstr(statuscode)); } if(content && content_length) { char contentBuffer[500]; content_length = ((content_length > sizeof(contentBuffer) - 2) ? sizeof(contentBuffer) - 2 : content_length); memcpy(contentBuffer, content, content_length); contentBuffer[content_length] = 0; if(content_length && (contentBuffer[content_length - 1] == '\n')) contentBuffer[--content_length] = 0; printf("%s\n", contentBuffer); } } bail: if (gRet == ERRORCODE_INPROGRESS) { gRet = 0; } return SMCP_STATUS_OK; }
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; }
static smcp_status_t pair_response_handler( int statuscode, void* context ) { // smcp_t const self = smcp_get_current_instance(); char* content = (char*)smcp_inbound_get_content_ptr(); coap_size_t content_length = smcp_inbound_get_content_len(); if((statuscode >= COAP_RESULT_100) && show_headers) { fprintf(stdout, "\n"); coap_dump_header( stdout, "NULL", smcp_inbound_get_packet(), 0 ); } if(((statuscode < COAP_RESULT_200) || (statuscode >= COAP_RESULT_300)) && (statuscode != SMCP_STATUS_TRANSACTION_INVALIDATED)) fprintf(stderr, "pair: Result code = %d (%s)\n", statuscode, (statuscode < 0) ? smcp_status_to_cstr( statuscode) : coap_code_to_cstr(statuscode)); if(content && content_length) { char contentBuffer[500]; content_length = ((content_length > sizeof(contentBuffer) - 2) ? sizeof(contentBuffer) - 2 : content_length); memcpy(contentBuffer, content, content_length); contentBuffer[content_length] = 0; if(content_length && (contentBuffer[content_length - 1] == '\n')) contentBuffer[--content_length] = 0; printf("%s\n", contentBuffer); } if(gRet == ERRORCODE_INPROGRESS) gRet = ERRORCODE_OK; free(context); return SMCP_STATUS_OK; }
static smcp_status_t response_test_handler(int statuscode, void* context) { test_data_s * const test_data = context; smcp_t interface = smcp_get_current_instance(); bool has_observe_option = false; smcp_status_t status = 0; if(!test_data->finished) { if (statuscode < 0) { test_data->finished = true; if (statuscode != SMCP_STATUS_TRANSACTION_INVALIDATED) { test_data->error = statuscode; } } else { const uint8_t* value; coap_size_t value_len; coap_option_key_t key; test_data->msg_id = smcp_inbound_get_packet()->msg_id; if (smcp_inbound_is_dupe()) { test_data->inbound_dupe_packets++; } else { test_data->inbound_packets++; } while ((key=smcp_inbound_next_option(&value, &value_len))!=COAP_OPTION_INVALID) { if (key == COAP_OPTION_BLOCK1) { test_data->block1_option = 0; test_data->has_block1_option = 1; test_data->block1_option = coap_decode_uint32(value,(uint8_t)value_len); if ( statuscode == COAP_RESULT_231_CONTINUE) { smcp_transaction_new_msg_id(interface, test_data->transaction, smcp_get_next_msg_id(interface)); smcp_transaction_tickle(interface, test_data->transaction); } } if (key == COAP_OPTION_BLOCK2) { test_data->block2_option = 0; test_data->has_block2_option = 1; test_data->block2_option = coap_decode_uint32(value,(uint8_t)value_len); if (!(test_data->block2_option & (1<<3))) { test_data->finished = true; } } if (key == COAP_OPTION_OBSERVE) { if (test_data->inbound_packets > 2) { test_data->finished = true; } has_observe_option = true; printf("\tobs-response: \"%s\"\n", smcp_inbound_get_content_ptr()); } } if ( !has_observe_option && !test_data->has_block2_option && statuscode != COAP_RESULT_231_CONTINUE ) { test_data->finished = true; } test_data->inbound_content_len += smcp_inbound_get_content_len(); test_data->inbound_code = (coap_code_t)statuscode; if (test_data->has_block2_option) { strncat(test_data->response, smcp_inbound_get_content_ptr(), smcp_inbound_get_content_len()); } else { strncpy(test_data->response, smcp_inbound_get_content_ptr(), smcp_inbound_get_content_len()); } } } return status; }
static smcp_status_t get_response_handler(int statuscode, void* context) { ThingMLCOAPContext * thingml_context = (ThingMLCOAPContext *) context; const char* content = (const char*)smcp_inbound_get_content_ptr(); coap_size_t content_length = smcp_inbound_get_content_len(); if(statuscode>=0) { if(content_length>(smcp_inbound_get_packet_length()-4)) { fprintf(stderr, "INTERNAL ERROR: CONTENT_LENGTH LARGER THAN PACKET_LENGTH-4! (content_length=%u, packet_length=%u)\n",content_length,smcp_inbound_get_packet_length()); gRet = ERRORCODE_UNKNOWN; thingml_context->fn_onerror_callback(thingml_context->thing_instance, gRet); goto bail; } if((statuscode >= 0) && get_show_headers) { if(next_len != ((coap_size_t)(-1))) fprintf(stdout, "\n\n"); coap_dump_header( stdout, NULL, smcp_inbound_get_packet(), smcp_inbound_get_packet_length() ); } if(!coap_verify_packet((void*)smcp_inbound_get_packet(), smcp_inbound_get_packet_length())) { fprintf(stderr, "INTERNAL ERROR: CALLBACK GIVEN INVALID PACKET!\n"); gRet = ERRORCODE_UNKNOWN; thingml_context->fn_onerror_callback(thingml_context->thing_instance, gRet); goto bail; } } if(statuscode == SMCP_STATUS_TRANSACTION_INVALIDATED) { gRet = 0; } if(observe_ignore_first) { observe_ignore_first = false; goto bail; } if( ((statuscode < COAP_RESULT_200) ||(statuscode >= COAP_RESULT_400)) && (statuscode != SMCP_STATUS_TRANSACTION_INVALIDATED) && (statuscode != HTTP_TO_COAP_CODE(HTTP_RESULT_CODE_PARTIAL_CONTENT)) ) { if(get_observe && statuscode == SMCP_STATUS_TIMEOUT) { gRet = 0; } else { gRet = (statuscode == SMCP_STATUS_TIMEOUT)?ERRORCODE_TIMEOUT:ERRORCODE_COAP_ERROR; fprintf(stderr, "get: Result code = %d (%s)\n", statuscode, (statuscode < 0) ? smcp_status_to_cstr( statuscode) : coap_code_to_cstr(statuscode)); thingml_context->fn_onerror_callback(thingml_context->thing_instance, gRet); } } if((statuscode>0) && content && content_length) { coap_option_key_t key; const uint8_t* value; coap_size_t value_len; bool last_block = true; int32_t observe_value = -1; while((key=smcp_inbound_next_option(&value, &value_len))!=COAP_OPTION_INVALID) { if(key == COAP_OPTION_BLOCK2) { last_block = !(value[value_len-1]&(1<<3)); } else if(key == COAP_OPTION_OBSERVE) { if(value_len) observe_value = value[0]; else observe_value = 0; } } thingml_context->fn_onmsgrcv_callback(thingml_context->thing_instance, content, content_length); last_observe_value = observe_value; } if(observe_once) { gRet = 0; goto bail; } bail: return SMCP_STATUS_OK; }
smcp_status_t device_func( smcp_variable_node_t node, uint8_t action, uint8_t i, char* value ) { smcp_status_t ret = 0; if(action==SMCP_VAR_GET_KEY) { switch(i) { case 0: strcpy(value,"loadavg"); break; case 1: strcpy(value,"clock"); break; case 2: strcpy(value,"action"); break; default: ret = SMCP_STATUS_NOT_FOUND; break; } } else if(action==SMCP_VAR_GET_MAX_AGE && i==0) { strcpy(value,"5"); } else if(action==SMCP_VAR_GET_VALUE) { switch(i) { case 0: { double loadavg[3] = { }; require_action( 0 < getloadavg(loadavg, sizeof(loadavg) / sizeof(*loadavg)), bail, ret = SMCP_STATUS_FAILURE ); require_action( (size_t)snprintf( value, SMCP_VARIABLE_MAX_VALUE_LENGTH, "%0.2f", loadavg[0] ) <= SMCP_VARIABLE_MAX_VALUE_LENGTH, bail, ret = SMCP_STATUS_FAILURE ); } break; case 1: require_action( (size_t)snprintf( value, SMCP_VARIABLE_MAX_VALUE_LENGTH, "%d", (int)clock() ) <= SMCP_VARIABLE_MAX_VALUE_LENGTH, bail, ret = SMCP_STATUS_FAILURE ); break; case 2: ret = SMCP_STATUS_NOT_ALLOWED; break; default: ret = SMCP_STATUS_NOT_FOUND; break; } } else if(action==SMCP_VAR_SET_VALUE) { switch(i) { case 0: ret = SMCP_STATUS_NOT_ALLOWED; break; case 1: ret = SMCP_STATUS_NOT_ALLOWED; break; case 2: fprintf(stdout," *** Received Action!\n"); coap_dump_header( stdout, " * ", smcp_inbound_get_packet(), 0 ); break; default: ret = SMCP_STATUS_NOT_FOUND; break; } } else { ret = SMCP_STATUS_NOT_IMPLEMENTED; } bail: return ret; }
cgi_node_request_t cgi_node_create_request(cgi_node_t node) { cgi_node_request_t ret = NULL; int i; int pipe_cmd_stdin[2]; int pipe_cmd_stdout[2]; for (i=0; i < CGI_NODE_MAX_REQUESTS; i++) { if (node->requests[i].state <= CGI_NODE_STATE_FINISHED) { ret = &node->requests[i]; if (node->requests[i].state == CGI_NODE_STATE_INACTIVE) { break; } } } require(ret,bail); ret->is_active = 1; ret->state = CGI_NODE_STATE_ACTIVE_BLOCK1_WAIT_REQ; if(ret->pid != 0 && ret->pid != -1) { int status; kill(ret->pid,SIGKILL); waitpid(ret->pid, &status, 0); } if(ret->fd_cmd_stdin>=0) { close(ret->fd_cmd_stdin); } if(ret->fd_cmd_stdout>=0) { close(ret->fd_cmd_stdout); } ret->pid = 0; ret->fd_cmd_stdin = -1; ret->fd_cmd_stdout = -1; ret->block1 = BLOCK_OPTION_UNSPECIFIED; ret->block2 = BLOCK_OPTION_DEFAULT; // Default value, overwrite with actual block ret->stdin_buffer_len = 0; ret->stdout_buffer_len = 0; ret->expiration = smcp_plat_cms_to_timestamp(30 * MSEC_PER_SEC); free(ret->stdin_buffer); ret->stdin_buffer = NULL; free(ret->stdout_buffer); ret->stdout_buffer = NULL; smcp_start_async_response(&ret->async_response, SMCP_ASYNC_RESPONSE_FLAG_DONT_ACK); pipe(pipe_cmd_stdin); pipe(pipe_cmd_stdout); if(!(ret->pid=fork())) { // We are the child! char path[2048]; // todo: this max should be a preprocessor macro // Update stdin and stdout. dup2(pipe_cmd_stdin[0],STDIN_FILENO); dup2(pipe_cmd_stdout[1],STDOUT_FILENO); close(pipe_cmd_stdin[0]); close(pipe_cmd_stdin[1]); close(pipe_cmd_stdout[0]); close(pipe_cmd_stdout[1]); path[0] = 0; smcp_node_get_path(&node->node,path,sizeof(path)); setenv("SCRIPT_NAME",path,1); setenv("SERVER_SOFTWARE","smcpd/"PACKAGE_VERSION,1); setenv("REQUEST_METHOD",coap_code_to_cstr(smcp_inbound_get_packet()->code),1); setenv("REQUEST_URI",smcp_inbound_get_path(path,2),1); setenv("GATEWAY_INTERFACE","CGI/1.1",1); setenv("SERVER_PROTOCOL","CoAP/1.0",1); setenv("REMOTE_ADDR","",1); setenv("REMOTE_PORT","",1); setenv("SERVER_NAME","",1); setenv("SERVER_ADDR","",1); setenv("SERVER_PORT","",1); if (0 == strncmp(path,getenv("SCRIPT_NAME"),strlen(getenv("SCRIPT_NAME")))) { setenv("PATH_INFO",path+strlen(getenv("SCRIPT_NAME")),1); } syslog(LOG_DEBUG, "cgi-node: About to execute \"%s\" using shell \"%s\"", node->cmd, node->shell); execl(node->shell,node->shell,"-c",node->cmd,NULL); syslog(LOG_ERR, "cgi-node: Failed to execute \"%s\" using shell \"%s\"", node->cmd, node->shell); // We should never get here... abort(); } if (ret->pid < 0) { // Oh hell. syslog(LOG_ERR,"Unable to fork!"); close(pipe_cmd_stdin[0]); close(pipe_cmd_stdin[1]); close(pipe_cmd_stdout[0]); close(pipe_cmd_stdout[1]); ret->is_active = 0; ret->state = CGI_NODE_STATE_INACTIVE; ret = NULL; goto bail; } ret->fd_cmd_stdin = pipe_cmd_stdin[1]; ret->fd_cmd_stdout = pipe_cmd_stdout[0]; close(pipe_cmd_stdin[0]); close(pipe_cmd_stdout[1]); bail: return ret; }