Example #1
0
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;
}
Example #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;
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #6
0
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;
}
Example #7
0
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;
}