Exemplo n.º 1
0
static smcp_status_t
request_handler(void* context) {
	/*	This will respond to every GET request to `/hello-world' with
	**	"Hello world!". Everyone else gets a 4.04 Not Found. */

	printf("Got a request!\n");

	if(smcp_inbound_get_code() != COAP_METHOD_GET) {
		return SMCP_STATUS_NOT_IMPLEMENTED;
	}

	while(smcp_inbound_peek_option(NULL, NULL) != COAP_OPTION_URI_PATH)
		if(smcp_inbound_next_option(NULL, NULL) == COAP_OPTION_INVALID)
			break;

	if(smcp_inbound_option_strequal(COAP_OPTION_URI_PATH, "hello-world")) {

		smcp_outbound_begin_response(COAP_RESULT_205_CONTENT);

		smcp_outbound_add_option_uint(
			COAP_OPTION_CONTENT_TYPE,
			COAP_CONTENT_TYPE_TEXT_PLAIN
		);

		smcp_outbound_append_content("Hello world!", SMCP_CSTR_LEN);

		return smcp_outbound_send();
	}

	return SMCP_STATUS_NOT_FOUND;
}
Exemplo n.º 2
0
smcp_status_t
plugtest_test_handler(smcp_node_t node)
{
	smcp_status_t ret = SMCP_STATUS_NOT_ALLOWED;
	char* content = NULL;
	coap_size_t max_len = 0;
	smcp_method_t method = smcp_inbound_get_code();

	if(method==COAP_METHOD_GET) {
		ret = smcp_outbound_begin_response(COAP_RESULT_205_CONTENT);
	} else if(method==COAP_METHOD_POST) {
		ret = smcp_outbound_begin_response(COAP_RESULT_201_CREATED);
	} else if(method==COAP_METHOD_PUT) {
		ret = smcp_outbound_begin_response(COAP_RESULT_204_CHANGED);
	} else if(method==COAP_METHOD_DELETE) {
		ret = smcp_outbound_begin_response(COAP_RESULT_202_DELETED);
	}

	if(ret) goto bail;

	smcp_outbound_add_option_uint(COAP_OPTION_CONTENT_TYPE, COAP_CONTENT_TYPE_TEXT_PLAIN);

	content = smcp_outbound_get_content_ptr(&max_len);
	if(!content) {
		ret = SMCP_STATUS_FAILURE;
		goto bail;
	}

	smcp_inbound_get_path(content, SMCP_GET_PATH_LEADING_SLASH|SMCP_GET_PATH_INCLUDE_QUERY);
	strlcat(content,"\nPlugtest!\nMethod = ",max_len);
	strlcat(content,coap_code_to_cstr(method),max_len);
	strlcat(content,"\n",max_len);

	{
		const uint8_t* value;
		coap_size_t value_len;
		coap_option_key_t key;
		while((key=smcp_inbound_next_option(&value, &value_len))!=COAP_OPTION_INVALID) {
			strlcat(content,coap_option_key_to_cstr(key,1),max_len);
			strlcat(content,": ",max_len);
			if(coap_option_value_is_string(key)) {
				int argh = strlen(content)+value_len;
				strlcat(content,(char*)value,MIN(max_len,argh+1));
				content[argh] = 0;
			} else {
				strlcat(content,"<binary>",max_len);
			}
			strlcat(content,"\n",max_len);
		}
	}

	smcp_outbound_set_content_len((coap_size_t)strlen(content));

	ret = smcp_outbound_send();

bail:
	return ret;
}
Exemplo n.º 3
0
static smcp_status_t
request_handler(void* context) {
    smcp_status_t ret = SMCP_STATUS_OK;
    char* content = (char*)smcp_inbound_get_content_ptr();
    size_t content_length = smcp_inbound_get_content_len();
    char *path = NULL;
    FILE * pFile;

    path = smcp_inbound_get_path(NULL,0); // path must be free()'d after this!
    //require_action_string(path && path[0], (free((void*)path),ret = SMCP_STATUS_INVALID_ARGUMENT));
    if(smcp_inbound_get_code() != COAP_METHOD_POST) {
        return SMCP_STATUS_NOT_IMPLEMENTED;
    }

    // Skip to the URI path option
    while(smcp_inbound_peek_option(NULL, NULL) != COAP_OPTION_URI_PATH)
        if(smcp_inbound_next_option(NULL, NULL) == COAP_OPTION_INVALID)
            break;

    smcp_outbound_begin_response(COAP_RESULT_205_CONTENT);

    smcp_outbound_add_option_uint(
        COAP_OPTION_CONTENT_TYPE,
        COAP_CONTENT_TYPE_TEXT_PLAIN);

    if(content && content_length) {
        // if content exist then print and write on .txt file with "a" being append feature.
        pFile = fopen ("data-collect.txt","a");
        printf("%s", content);
        if (pFile!=NULL) {
            fputs (content,pFile);
            fclose (pFile);
        }

        /* Only print a newline if the content doesn't already print one. */
        if((content[content_length - 1] != '\n'))
            printf("\n");
    }

    ret = smcp_outbound_send();
    free((void*)path);
bail:
    return ret;
}
Exemplo n.º 4
0
static smcp_status_t
request_handler(void* context) {
	/*	This will respond to every GET request to `/hello-world' with
	**	"Hello world!". Everyone else gets a 4.04 Not Found. */

	printf("Got a request!\n");

	// Only handle GET requests for now. Returning SMCP_STATUS_NOT_IMPLEMENTED
	// here without sending a response will cause us to automatically
	// send a METHOD_NOT_IMPLEMENTED response.
	if(smcp_inbound_get_code() != COAP_METHOD_GET) {
		return SMCP_STATUS_NOT_IMPLEMENTED;
	}

	// Skip to the URI path option
	while(smcp_inbound_peek_option(NULL, NULL) != COAP_OPTION_URI_PATH)
		if(smcp_inbound_next_option(NULL, NULL) == COAP_OPTION_INVALID)
			break;

	// If our URI path matches what we are looking for...
	if(smcp_inbound_option_strequal(COAP_OPTION_URI_PATH, "hello-world")) {

		// Begin describing the response message. (2.05 CONTENT,
		// in this case)
		smcp_outbound_begin_response(COAP_RESULT_205_CONTENT);

		// Add an option describing the content type as plaintext.
		smcp_outbound_add_option_uint(
			COAP_OPTION_CONTENT_TYPE,
			COAP_CONTENT_TYPE_TEXT_PLAIN
		);

		// Set the content of our response to be "Hello world!".
		smcp_outbound_append_content("Hello world!", SMCP_CSTR_LEN);

		// Send the response we hae created, passing the return value
		// to our caller.
		return smcp_outbound_send();
	}

	return SMCP_STATUS_NOT_FOUND;
}
Exemplo n.º 5
0
smcp_status_t
smcp_auth_verify_request() {
	smcp_status_t ret = SMCP_STATUS_OK;
	coap_option_key_t key;
	const uint8_t* authvalue;
	size_t authvalue_len;

	// For testing purposes only!
	if(smcp_inbound_get_code() >1 && smcp_inbound_get_code()<COAP_RESULT_100) {
		ret = SMCP_STATUS_UNAUTHORIZED;
	}

	smcp_inbound_reset_next_option();

	while((key = smcp_inbound_next_option(&authvalue,&authvalue_len))!=COAP_OPTION_INVALID) {
		if(key==COAP_OPTION_PROXY_URI) {
			// For testing purposes only!
			ret = SMCP_STATUS_OK;
		}
		if(key==COAP_OPTION_AUTHENTICATE) {
			// For testing purposes only!
			ret = SMCP_STATUS_OK;
			// writeme!
		}
	}

	if(smcp_inbound_origin_is_local()) {
		ret = SMCP_STATUS_OK;
	}

	ret = SMCP_STATUS_OK;

	// For testing purposes only!
	if(ret==SMCP_STATUS_UNAUTHORIZED) {
		smcp_outbound_begin_response(COAP_RESULT_401_UNAUTHORIZED);
		smcp_outbound_add_option(COAP_OPTION_AUTHENTICATE,NULL,0);
		smcp_outbound_send();
	}

	return ret;
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
0
smcp_status_t
smcp_variable_node_request_handler(
	smcp_variable_node_t		node
) {
	// TODO: Make this function use less stack space!

	smcp_method_t method = smcp_inbound_get_code();
	smcp_status_t ret = SMCP_STATUS_NOT_FOUND;
	SMCP_NON_RECURSIVE coap_content_type_t content_type;
	SMCP_NON_RECURSIVE char* content_ptr;
	SMCP_NON_RECURSIVE size_t content_len;
	SMCP_NON_RECURSIVE char buffer[SMCP_VARIABLE_MAX_VALUE_LENGTH+1];
	SMCP_NON_RECURSIVE coap_content_type_t reply_content_type;
	uint8_t key_index = BAD_KEY_INDEX;
	size_t value_len;
	bool needs_prefix = true;
	char* prefix_name = "";

	content_type = smcp_inbound_get_content_type();
	content_ptr = (char*)smcp_inbound_get_content_ptr();
	content_len = smcp_inbound_get_content_len();

	reply_content_type = SMCP_CONTENT_TYPE_APPLICATION_FORM_URLENCODED;

	require(node, bail);

	// Look up the key index.
	if(smcp_inbound_peek_option(NULL,&value_len)==COAP_OPTION_URI_PATH) {
		if(!value_len) {
			needs_prefix = false;
			smcp_inbound_next_option(NULL,NULL);
		} else for(key_index=0;key_index<BAD_KEY_INDEX;key_index++) {
			ret = node->func(node,SMCP_VAR_GET_KEY,key_index,buffer);
			require_action(ret==0,bail,ret=SMCP_STATUS_NOT_FOUND);
			if(smcp_inbound_option_strequal(COAP_OPTION_URI_PATH, buffer)) {
				smcp_inbound_next_option(NULL,NULL);
				break;
			}
		}
	}

	{
		coap_option_key_t key;
		const uint8_t* value;
		while((key=smcp_inbound_next_option(&value, &value_len))!=COAP_OPTION_INVALID) {
			require_action(key!=COAP_OPTION_URI_PATH,bail,ret=SMCP_STATUS_NOT_FOUND);
			if(key==COAP_OPTION_URI_QUERY) {
				if(	method == COAP_METHOD_POST
					&& value_len>=2
					&& strhasprefix_const((const char*)value,"v=")
				) {
					DEBUG_PRINTF("variable-node: value is in the query.");
					content_type = COAP_CONTENT_TYPE_TEXT_PLAIN;
					content_ptr = (char*)value+2;
					content_len = value_len-2;
				}
//			} else if(key==COAP_OPTION_ETAG) {
//			} else if(key==COAP_OPTION_IF_MATCH) {
//			} else if(key==COAP_OPTION_IF_NONE_MATCH) {
			} else if(key==COAP_OPTION_ACCEPT) {
				reply_content_type = 0;
				if(value_len==1)
					reply_content_type = value[0];
				else {
					// Unsupported type.
				}
			} else if(COAP_OPTION_IS_CRITICAL(key)) {
				ret=SMCP_STATUS_BAD_OPTION;
				assert_printf("Unrecognized option %d, \"%s\"",
					key,
					coap_option_key_to_cstr(key, false)
				);
				goto bail;
			}
		}
	}

	// TODO: Implement me!
	if(method == COAP_METHOD_PUT)
		method = COAP_METHOD_POST;

	if(method == COAP_METHOD_POST) {
		require_action(!smcp_inbound_is_dupe(),bail,ret=0);

		require_action(
			key_index!=BAD_KEY_INDEX,
			bail,
			ret=SMCP_STATUS_NOT_ALLOWED
		);
		if(content_type==SMCP_CONTENT_TYPE_APPLICATION_FORM_URLENCODED) {
			char* key = NULL;
			char* value = NULL;
			content_len = 0;
			while(
				url_form_next_value(
					(char**)&content_ptr,
					&key,
					&value
				)
				&& key
				&& value
			) {
				if(strequal_const(key, "v")) {
					content_ptr = value;
					content_len = strlen(value);
					break;
				}
			}
		}

		// Make sure our content is zero terminated.
		((char*)content_ptr)[content_len] = 0;

		ret = node->func(node,SMCP_VAR_SET_VALUE,key_index,(char*)content_ptr);
		require_noerr(ret,bail);

		ret = smcp_outbound_begin_response(COAP_RESULT_204_CHANGED);
		require_noerr(ret,bail);

		ret = smcp_outbound_send();
		require_noerr(ret,bail);
	} else if(method == COAP_METHOD_GET) {

		if(key_index==BAD_KEY_INDEX) {
			char* content_end_ptr;

			ret = smcp_outbound_begin_response(COAP_RESULT_205_CONTENT);
			require_noerr(ret,bail);

			smcp_outbound_add_option_uint(COAP_OPTION_CONTENT_TYPE, COAP_CONTENT_TYPE_APPLICATION_LINK_FORMAT);

			ret = smcp_observable_update(&node->observable, SMCP_OBSERVABLE_BROADCAST_KEY);
			check_string(ret==0,smcp_status_to_cstr(ret));

			content_ptr = smcp_outbound_get_content_ptr(&content_len);
			content_end_ptr = content_ptr+content_len;

			for(key_index=0;key_index<BAD_KEY_INDEX;key_index++) {
				ret = node->func(node,SMCP_VAR_GET_KEY,key_index,buffer);
				if(ret) break;

				if(content_ptr+2>=content_end_ptr) {
					// No more room for content.
					break;
				}

				*content_ptr++ = '<';
				if(needs_prefix) {
					content_ptr += url_encode_cstr(content_ptr, prefix_name, (content_end_ptr-content_ptr)-1);
					content_ptr = stpncpy(content_ptr,"/",MIN(1,(content_end_ptr-content_ptr)-1));
				}
				content_ptr += url_encode_cstr(content_ptr, buffer, (content_end_ptr-content_ptr)-1);
				*content_ptr++ = '>';

				ret = node->func(node,SMCP_VAR_GET_VALUE,key_index,buffer);

				if(content_ptr+4>=content_end_ptr) {
					// No more room for content.
					break;
				}

				if(!ret) {
					strcpy(content_ptr,";v=");
					content_ptr += 3;
					content_ptr += quoted_cstr(content_ptr, buffer, (content_end_ptr-content_ptr)-1);
				}

				ret = node->func(node,SMCP_VAR_GET_LF_TITLE,key_index,buffer);

				if(content_ptr+8>=content_end_ptr) {
					// No more room for content.
					break;
				}

				if(!ret) {
					strcpy(content_ptr,";title=");
					content_ptr += 7;
					content_ptr += quoted_cstr(content_ptr, buffer, (content_end_ptr-content_ptr)-1);
				}

				// Observation flag
				if(0==node->func(node,SMCP_VAR_GET_OBSERVABLE,key_index,NULL)) {
					content_ptr = stpncpy(content_ptr,";obs",MIN(4,(content_end_ptr-content_ptr)-1));
				}

				*content_ptr++ = ',';
			}
			ret = smcp_outbound_set_content_len(content_len-(content_end_ptr-content_ptr));
			require_noerr(ret,bail);

			ret = smcp_outbound_send();
		} else {
			size_t replyContentLength = 0;
			char *replyContent;

			ret = smcp_outbound_begin_response(COAP_RESULT_205_CONTENT);
			require_noerr(ret,bail);

			if(0==node->func(node,SMCP_VAR_GET_OBSERVABLE,key_index,buffer)) {
				ret = smcp_observable_update(&node->observable, key_index);
				check_string(ret==0,smcp_status_to_cstr(ret));
			}

			if(reply_content_type == SMCP_CONTENT_TYPE_APPLICATION_FORM_URLENCODED) {
				uint32_t etag;

				if(0==node->func(node,SMCP_VAR_GET_MAX_AGE,key_index,buffer)) {
#if HAVE_STRTOL
					uint32_t max_age = strtol(buffer,NULL,0)&0xFFFFFF;
#else
					uint32_t max_age = atoi(buffer)&0xFFFFFF;
#endif
					smcp_outbound_add_option_uint(COAP_OPTION_MAX_AGE, max_age);
				}

				ret = node->func(node,SMCP_VAR_GET_VALUE,key_index,buffer);
				require_noerr(ret,bail);

				fasthash_start(0);
				fasthash_feed((const uint8_t*)buffer,strlen(buffer));
				etag = fasthash_finish_uint32();

				smcp_outbound_add_option_uint(COAP_OPTION_CONTENT_TYPE, SMCP_CONTENT_TYPE_APPLICATION_FORM_URLENCODED);

				smcp_outbound_add_option_uint(COAP_OPTION_ETAG, etag);

				replyContent = smcp_outbound_get_content_ptr(&replyContentLength);

				*replyContent++ = 'v';
				*replyContent++ = '=';
				replyContentLength -= 2;
				replyContentLength = url_encode_cstr(
					replyContent,
					buffer,
					replyContentLength
				);
				ret = smcp_outbound_set_content_len(replyContentLength+2);
			} else {
				ret = node->func(node,SMCP_VAR_GET_VALUE,key_index,buffer);
				require_noerr(ret,bail);

				ret = smcp_outbound_append_content(buffer, SMCP_CSTR_LEN);
			}

			require_noerr(ret,bail);

			ret = smcp_outbound_send();
		}
	} else {
		ret = smcp_default_request_handler(
			(void*)node
		);
		check_string(ret == SMCP_STATUS_OK, smcp_status_to_cstr(ret));
	}

bail:
	check_string(ret == SMCP_STATUS_OK, smcp_status_to_cstr(ret));
	return ret;
}
Exemplo n.º 8
0
smcp_status_t
plugtest_large_handler(
	smcp_node_t		node
) {
	smcp_status_t ret = SMCP_STATUS_NOT_ALLOWED;
	char* content = NULL;
	coap_size_t max_len = 0;
	smcp_method_t method = smcp_inbound_get_code();
	uint32_t block_option = 0x03;
	uint32_t block_start = 0;
	uint32_t block_stop = 0;
	uint32_t resource_length = 2000;

	if(method==COAP_METHOD_GET) {
		ret = 0;
	}

	require_noerr(ret,bail);

	{
		const uint8_t* value;
		coap_size_t value_len;
		coap_option_key_t key;
		while((key=smcp_inbound_next_option(&value, &value_len))!=COAP_OPTION_INVALID) {
			if(key == COAP_OPTION_BLOCK2) {
				uint8_t i;
				block_option = 0;
				for(i = 0; i < value_len; i++)
					block_option = (block_option << 8) + value[i];
			}
		}
	}

	ret = smcp_outbound_begin_response(COAP_RESULT_205_CONTENT);
	require_noerr(ret,bail);

	ret = smcp_outbound_add_option_uint(COAP_OPTION_CONTENT_TYPE, COAP_CONTENT_TYPE_TEXT_PLAIN);
	require_noerr(ret,bail);

	ret = smcp_outbound_add_option_uint(COAP_OPTION_MAX_AGE,60*60);
	require_noerr(ret,bail);

	max_len = smcp_outbound_get_space_remaining()-2;

	// Here we are making sure our data will fit,
	// and adjusting our block-option size accordingly.
	do {
		struct coap_block_info_s block_info;
		coap_decode_block(&block_info, block_option);
		block_start = block_info.block_offset;
		block_stop = block_info.block_offset + block_info.block_size;

		if(max_len<(block_stop-block_start) && block_option!=0 && !block_info.block_offset) {
			block_option--;
			block_stop = 0;
			continue;
		}
	} while(0==block_stop);

	require_action(block_start<resource_length,bail,ret=SMCP_STATUS_INVALID_ARGUMENT);

	if(block_stop>=resource_length)
		block_option &= ~(1<<3);
	else
		block_option |= (1<<3);

	ret = smcp_outbound_add_option_uint(COAP_OPTION_BLOCK2,block_option);
	require_noerr(ret,bail);

	content = smcp_outbound_get_content_ptr(&max_len);

	require_action(NULL!=content, bail, ret = SMCP_STATUS_FAILURE);
	require_action(max_len>(block_stop-block_start), bail, ret = SMCP_STATUS_MESSAGE_TOO_BIG);

	{
		uint32_t i;
		for(i=block_start;i<block_stop;i++) {
			if(!((i+1)%64))
				content[i-block_start] = '\n';
			else
				content[i-block_start] = '0'+(i%10);
		}
	}

	ret = smcp_outbound_set_content_len((coap_size_t)MIN(block_stop-block_start,resource_length-block_start));
	if(ret) goto bail;

	ret = smcp_outbound_send();

bail:
	return ret;
}
Exemplo n.º 9
0
smcp_status_t
smcp_node_route(smcp_node_t node, smcp_request_handler_func* func, void** context) {
	smcp_status_t ret = 0;
	smcp_t const self = smcp_get_current_instance();

	smcp_inbound_reset_next_option();

	{
		// TODO: Rewrite this to be more efficient.
		const uint8_t* prev_option_ptr = self->inbound.this_option;
		coap_option_key_t prev_key = 0;
		coap_option_key_t key;
		const uint8_t* value;
		coap_size_t value_len;
		while ((key = smcp_inbound_next_option(&value, &value_len)) != COAP_OPTION_INVALID) {
			if (key > COAP_OPTION_URI_PATH) {
				self->inbound.this_option = prev_option_ptr;
				self->inbound.last_option_key = prev_key;
				break;
			} else if (key == COAP_OPTION_URI_PATH) {
				smcp_node_t next = smcp_node_find(
					node,
					(const char*)value,
					(int)value_len
				);
				if (next) {
					node = next;
				} else {
					self->inbound.this_option = prev_option_ptr;
					self->inbound.last_option_key = prev_key;
					break;
				}
			} else if(key==COAP_OPTION_URI_HOST) {
				// Skip host at the moment,
				// because we don't do virtual hosting yet.
			} else if(key==COAP_OPTION_URI_PORT) {
				// Skip port at the moment,
				// because we don't do virtual hosting yet.
			} else if(key==COAP_OPTION_PROXY_URI) {
				// Skip the proxy URI for now.
			} else if(key==COAP_OPTION_CONTENT_TYPE) {
				// Skip.
			} else {
				if(COAP_OPTION_IS_CRITICAL(key)) {
					ret=SMCP_STATUS_BAD_OPTION;
					assert_printf("Unrecognized option %d, \"%s\"",
						key,
						coap_option_key_to_cstr(key, false)
					);
					goto bail;
				}
			}
			prev_option_ptr = self->inbound.this_option;
			prev_key = self->inbound.last_option_key;
		}
	}

	*func = (void*)node->request_handler;
	if(node->context) {
		*context = node->context;
	} else {
		*context = (void*)node;
	}

bail:
	return ret;
}
Exemplo n.º 10
0
smcp_status_t
smcp_group_mgr_request_handler(
	smcp_group_mgr_t self
) {
	smcp_status_t ret = 0;
	const smcp_method_t method = smcp_inbound_get_code();
	coap_option_key_t key;
	const uint8_t* value;
	coap_size_t value_len;
	smcp_group_t group;
	bool missing_trailing_slash = false;

	if (smcp_inbound_next_option(&value, &value_len) != COAP_OPTION_URI_PATH) {
		missing_trailing_slash = true;
	}

	if (value_len == 0) {
		// listing groups

		if (method == COAP_METHOD_GET) {
			if (missing_trailing_slash) {
				return smcp_outbound_quick_response(COAP_RESULT_400_BAD_REQUEST, "(400) Needs trailing slash");
			}
			return request_handler_get_listing_(self);

		} else if (method == COAP_METHOD_POST) {
			return request_handler_new_group_(self);

		} else {
			ret = SMCP_STATUS_NOT_ALLOWED;
			goto bail;
		}

	} else if (value_len == 2) {
		// Query on a specific group.
		const char str[3] = {value[0], value[1], 0};
		int i;

		errno = 0;

#if HAVE_STRTOL
		i = strtol(str, NULL, 16);
#else
		i = atoi(str); // TODO: This isn't base16!
#endif

		if (errno) {
			ret = SMCP_STATUS_NOT_FOUND;
			goto bail;
		}
		group = &self->group_table[i];

		key = smcp_inbound_peek_option(&value, &value_len);

		if ( (i < 0)
		  || (i >= SMCP_CONF_MAX_GROUPS)
		  || (!group->in_use)
		) {
			ret = SMCP_STATUS_NOT_FOUND;
			goto bail;
		}

		if (key != COAP_OPTION_URI_PATH) {
			value_len = 0;
		}

		if ( (method == COAP_METHOD_GET)
		  || (method == COAP_METHOD_PUT)
		  || (method == COAP_METHOD_POST)
		  || ( (method == COAP_METHOD_DELETE) && (value_len > 0) )
		) {
			// hand off handling of this to variable node.
			return smcp_variable_handler_request_handler(&group->var_handler);

		} else if (method == COAP_METHOD_DELETE) {
			// Delete this group.
			smcp_group_mgr_delete(self, group);
			return smcp_outbound_quick_response(COAP_RESULT_202_DELETED, NULL);
		}

	} else {
		ret = SMCP_STATUS_NOT_FOUND;
	}

bail:
	return ret;
}
Exemplo n.º 11
0
smcp_status_t
smcp_curl_proxy_request_handler(
    smcp_curl_proxy_node_t		node
) {
    smcp_status_t ret = SMCP_STATUS_NOT_ALLOWED;
    smcp_curl_request_t request = NULL;
    struct curl_slist *headerlist=NULL;
    smcp_method_t method = smcp_inbound_get_code();

    //require_action(method<=COAP_METHOD_DELETE,bail,ret = SMCP_STATUS_NOT_ALLOWED);

    //require_action(COAP_OPTION_URI_PATH!=smcp_inbound_peek_option(NULL,NULL),bail,ret=SMCP_STATUS_NOT_FOUND);

    node->interface = smcp_get_current_instance();

    smcp_inbound_reset_next_option();

    request = smcp_curl_request_create();
    request->proxy_node = node;

    require_action(request!=NULL,bail,ret = SMCP_STATUS_MALLOC_FAILURE);

    switch(method) {
    case COAP_METHOD_GET:
        curl_easy_setopt(request->curl, CURLOPT_CUSTOMREQUEST, "GET");
        break;
    case COAP_METHOD_PUT:
        curl_easy_setopt(request->curl, CURLOPT_PUT, 1L);
        break;
    case COAP_METHOD_POST:
        curl_easy_setopt(request->curl, CURLOPT_POST, 1L);
        break;
    case COAP_METHOD_DELETE:
        curl_easy_setopt(request->curl, CURLOPT_CUSTOMREQUEST, "DELETE");
        break;
    default:
        ret = SMCP_STATUS_NOT_ALLOWED;
        break;
    }

    {
        coap_option_key_t key;
        const uint8_t* value;
        coap_size_t value_len;
        while((key=smcp_inbound_next_option(&value, &value_len))!=COAP_OPTION_INVALID) {
            if(key==COAP_OPTION_PROXY_URI) {
                char uri[value_len+1];
                memcpy(uri,value,value_len);
                uri[value_len] = 0;
                curl_easy_setopt(request->curl, CURLOPT_URL, uri);
                assert_printf("CuRL URL: \"%s\"",uri);
                ret = 0;
            } else if(key==COAP_OPTION_URI_HOST) {
            } else if(key==COAP_OPTION_URI_PORT) {
            } else if(key==COAP_OPTION_URI_PATH) {
            } else if(key==COAP_OPTION_URI_QUERY) {
            } else if(key==COAP_OPTION_CONTENT_TYPE || key==COAP_OPTION_ACCEPT) {
                const char* option_name = coap_option_key_to_cstr(key, false);
                const char* value_string = coap_content_type_to_cstr(value[1]);
                char header[strlen(option_name)+strlen(value_string)+3];
                strcpy(header,option_name);
                strcat(header,": ");
                strcat(header,value_string);
                headerlist = curl_slist_append(headerlist, header);
                assert_printf("CuRL HEADER: \"%s\"",header);
            } else {
                if(coap_option_value_is_string(key)) {
                    const char* option_name = coap_option_key_to_cstr(key, false);
                    char header[strlen(option_name)+value_len+3];
                    strcpy(header,option_name);
                    strcat(header,": ");
                    strncat(header,(const char*)value,value_len);
                    assert_printf("CuRL HEADER: \"%s\"",header);
                    headerlist = curl_slist_append(headerlist, header);
                }
            }
        }
    }

    require_noerr(ret,bail);

    if(smcp_inbound_get_content_len()) {
        coap_size_t len = smcp_inbound_get_content_len();
        request->output_content = calloc(1,len+1);
        request->output_content_len = len;
        memcpy(request->output_content,smcp_inbound_get_content_ptr(),len);
        curl_easy_setopt(request->curl, CURLOPT_READFUNCTION, ReadMemoryCallback);
        curl_easy_setopt(request->curl, CURLOPT_READDATA, (void *)request);
    }

    curl_easy_setopt(request->curl, CURLOPT_USERAGENT, "smcp-curl-proxy/1.0");
    curl_easy_setopt(request->curl, CURLOPT_HTTPHEADER, headerlist),headerlist=NULL;
    curl_easy_setopt(request->curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
    curl_easy_setopt(request->curl, CURLOPT_WRITEDATA, (void *)request);

    ret = smcp_start_async_response(&request->async_response,0);
    require_noerr(ret,bail);

    if(node->curl_multi_handle)
        curl_multi_add_handle(node->curl_multi_handle, request->curl);
    else
        curl_easy_perform(request->curl);

bail:
    if(headerlist)
        curl_slist_free_all(headerlist);

    if(ret && request)
        smcp_curl_request_release(request);

    return ret;
}
Exemplo n.º 12
0
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;
}
Exemplo n.º 13
0
smcp_status_t
cgi_node_request_handler(
	cgi_node_t		node
) {
	smcp_status_t ret = 0;
	cgi_node_request_t request = NULL;
	uint32_t block2_option = BLOCK_OPTION_DEFAULT;
	uint32_t block1_option = BLOCK_OPTION_UNSPECIFIED;
	smcp_method_t	method = smcp_inbound_get_code();

	require(node,bail);

	node->interface = smcp_get_current_instance();

	if (method==COAP_METHOD_GET) {
		ret = 0;
	}

	require_noerr(ret,bail);

	{
		const uint8_t* value;
		coap_size_t value_len;
		coap_option_key_t key;
		while ((key=smcp_inbound_next_option(&value, &value_len))!=COAP_OPTION_INVALID) {
			if (key == COAP_OPTION_BLOCK2) {
				uint8_t i;
				block2_option = 0;
				for (i = 0; i < value_len; i++) {
					block2_option = (block2_option << 8) + value[i];
				}
			}
			if (key == COAP_OPTION_BLOCK1) {
				uint8_t i;
				block1_option = 0;
				for (i = 0; i < value_len; i++) {
					block1_option = (block1_option << 8) + value[i];
				}
			}
		}
	}


	// Make sure this is a supported method.
	switch (method) {
	case COAP_METHOD_GET:
	case COAP_METHOD_PUT:
	case COAP_METHOD_POST:
	case COAP_METHOD_DELETE:
		break;
	default:
		ret = SMCP_STATUS_NOT_IMPLEMENTED;
		goto bail;
		break;
	}

	request = cgi_node_get_associated_request(node);

	if (request == NULL) {
		// Possibly new request.
		// Assume new for now, but we may need to do additional checks.

		// We don't support non-zero block indexes on the first packet.
		require_action((block2_option>>4) == 0, bail, ret = SMCP_STATUS_INVALID_ARGUMENT);

		request = cgi_node_create_request(node);
		require_action(request != NULL, bail, ret = SMCP_STATUS_FAILURE);
		request->block2 = block2_option;
	}