smcp_status_t
resend_get_request(void* context) {
    ThingMLCOAPContext * thingml_context = (ThingMLCOAPContext*) context;
    smcp_status_t status = 0;

    status = smcp_outbound_begin(smcp_get_current_instance(),COAP_METHOD_GET, get_tt);
    require_noerr(status,bail);

    status = smcp_outbound_set_uri(thingml_context->url, 0);
    require_noerr(status,bail);

    if(request_accept_type!=COAP_CONTENT_TYPE_UNKNOWN) {
        status = smcp_outbound_add_option_uint(COAP_OPTION_ACCEPT, request_accept_type);
        require_noerr(status,bail);
    }

    status = smcp_outbound_send();

    if(status) {
        check_noerr(status);
        fprintf(stderr,
                "smcp_outbound_send() returned error %d(%s).\n",
                status,
                smcp_status_to_cstr(status));
        goto bail;
    }

bail:
    return status;
}
Beispiel #2
0
smcp_status_t
resend_pair_request(char* url[2]) {
	smcp_status_t status;
#if SMCP_ENABLE_PAIRING
	coap_size_t len = 8;
	bool did_mutate = false;
	while(url[0][len] && url[0][len]!='/') {
		len++;
	}

	// Temporarily mutate the input url because I'm lazy.
	if(url[0][len]) {
		did_mutate = true;
		url[0][len] = 0;
	}

	status = smcp_outbound_begin(
		smcp_get_current_instance(),
		COAP_METHOD_PUT,
		COAP_TRANS_TYPE_CONFIRMABLE
	);
	require_noerr(status,bail);

	status = smcp_outbound_set_uri(url[0],0);
	require_noerr(status,bail);

	// Root pairings object path
	status = smcp_outbound_add_option(COAP_OPTION_URI_PATH,SMCP_PAIRING_DEFAULT_ROOT_PATH,SMCP_CSTR_LEN);
	require_noerr(status,bail);

	// Path to pair with
	status = smcp_outbound_add_option(COAP_OPTION_URI_PATH,url[0]+len+1,SMCP_CSTR_LEN);
	require_noerr(status,bail);

	// Remote target
	status = smcp_outbound_add_option(COAP_OPTION_URI_PATH,url[1],SMCP_CSTR_LEN);
	require_noerr(status,bail);

	status = smcp_outbound_send();
	require_noerr(status,bail);
bail:
	if(did_mutate) {
		url[0][len] = '/';
	}
#else
	status = SMCP_STATUS_NOT_IMPLEMENTED;
#endif
	return status;
}
Beispiel #3
0
smcp_status_t
resend_delete_request(const char* url) {
	smcp_status_t status = 0;

	status = smcp_outbound_begin(smcp_get_current_instance(), COAP_METHOD_DELETE, COAP_TRANS_TYPE_CONFIRMABLE);
	require_noerr(status,bail);

	status = smcp_outbound_set_uri(url, 0);
	require_noerr(status,bail);

	status = smcp_outbound_send();
	require_noerr(status,bail);

	gRet = ERRORCODE_INPROGRESS;

bail:
	return status;
}
Beispiel #4
0
smcp_status_t
resend_test_request(void* context) {
	test_data_s* test_data = context;
	smcp_status_t status = 0;

	status = smcp_outbound_begin(smcp_get_current_instance(),test_data->outbound_code, test_data->outbound_tt);
	require_noerr(status,bail);

	status = smcp_outbound_set_uri(test_data->url, 0);
	require_noerr(status,bail);

	if (test_data->outbound_content_type != COAP_CONTENT_TYPE_UNKNOWN) {
		status = smcp_outbound_add_option_uint(COAP_OPTION_CONTENT_TYPE, test_data->outbound_content_type);
		require_noerr(status,bail);
	}

	if (test_data->extra & EXT_BLOCK_01) {
		struct coap_block_info_s block1_info;
		uint32_t resource_length = 200;
		uint32_t block_stop;

		coap_decode_block(&block1_info, test_data->block1_option + (1<<4));

		block_stop = block1_info.block_offset+block1_info.block_size;

		if (block1_info.block_offset < resource_length) {
			if (block_stop >= resource_length) {
				test_data->block1_option &= ~(1<<3);
			} else {
				test_data->block1_option |= (1<<3);
			}

			if (test_data->has_block1_option) {
				test_data->block1_option += (1<<4);
			}

			smcp_outbound_add_option_uint(COAP_OPTION_BLOCK1, test_data->block1_option);

			if (block1_info.block_m) {
				coap_size_t max_len = 0;
				uint32_t i;
				uint32_t block_stop;
				char* content = NULL;
				content = smcp_outbound_get_content_ptr(&max_len);

				if (!content) {
					status = SMCP_STATUS_FAILURE;
					goto bail;
				}

				block_stop = block1_info.block_offset+block1_info.block_size;

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

				status = smcp_outbound_set_content_len(MIN((coap_code_t)(block_stop-block1_info.block_offset),(coap_code_t)(resource_length-block1_info.block_offset)));
				require_noerr(status,bail);
			}
		}
	}

	if(test_data->extra & EXT_BLOCK_02) {
		smcp_outbound_add_option_uint(COAP_OPTION_BLOCK2, 1);	// 32 byte block size.
	}

	status = smcp_outbound_send();

	if(status) {
		check_noerr(status);
		fprintf(stderr,
			"smcp_outbound_send() returned error %d(%s).\n",
			status,
			smcp_status_to_cstr(status));
		goto bail;
	} else {
		test_data->outbound_attempts++;
	}

bail:
	return status;
}
Beispiel #5
0
smcp_status_t
smcp_outbound_set_uri(
	const char* uri, char flags
) {
	smcp_status_t ret = SMCP_STATUS_OK;
	smcp_t const self = smcp_get_current_instance();
	SMCP_NON_RECURSIVE struct url_components_s components;
	SMCP_NON_RECURSIVE uint16_t toport;
	SMCP_NON_RECURSIVE char* uri_copy;

	memset((void*)&components, 0, sizeof(components));
	toport = COAP_DEFAULT_PORT;
	smcp_plat_set_session_type(SMCP_SESSION_TYPE_UDP);
	uri_copy = NULL;

	require_action(uri, bail, ret = SMCP_STATUS_INVALID_ARGUMENT);

	{
#if HAVE_ALLOCA
		uri_copy = alloca(strlen(uri) + 1);
		strcpy(uri_copy, uri);
#elif SMCP_AVOID_MALLOC
		// Well, we can't use the stack and we can't
		// use malloc. Let's use what room we have left
		// in the packet buffer, since this is temporary anyway...
		// It helps a bunch that we know the user hasn't written
		// any content yet (because that would be an API violation)
		if (smcp_outbound_get_space_remaining() > strlen(uri) + 8) {
			uri_copy = self->outbound.content_ptr + self->outbound.content_len;

			// The options section may be expanding as we parse this, so
			// we should move ahead by a few bytes. We are helped out
			// by the fact that we will be writing the options in the
			// same order they appear in the URL.
			uri_copy += 8;

			strcpy(uri_copy, uri);
		}
#else
		uri_copy = strdup(uri);
#endif

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

		// Parse the URI.
		require_action_string(
			url_parse(
				uri_copy,
				&components
			),
			bail,
			ret = SMCP_STATUS_URI_PARSE_FAILURE,
			"Unable to parse URL"
		);

		if(!components.protocol && !components.host) {
			// Talking to ourself.
			components.protocol = "coap";
			components.host = "::1";
			toport = smcp_plat_get_port(smcp_get_current_instance());
			flags |= SMCP_MSG_SKIP_AUTHORITY;
		} else if(components.port) {
			toport = (uint16_t)atoi(components.port);
		}

		DEBUG_PRINTF(
			"URI Parse: \"%s\" -> host=\"%s\" port=\"%u\" path=\"%s\"",
			uri,
			components.host,
			toport,
			components.path
		);
	}

	if (components.protocol) {
		smcp_session_type_t session_type = smcp_session_type_from_uri_scheme(components.protocol);
		smcp_plat_set_session_type(session_type);

		if (NULL == components.port) {
			toport = smcp_default_port_from_session_type(session_type);
		}

		if (session_type == SMCP_SESSION_TYPE_NIL) {
			require_action_string(
				self->proxy_url,
				bail,
				ret=SMCP_STATUS_INVALID_ARGUMENT,
				"No proxy URL configured"
			);
			require_action(uri != self->proxy_url,bail,ret = SMCP_STATUS_INVALID_ARGUMENT);

			ret = smcp_outbound_add_option(COAP_OPTION_PROXY_URI, uri, SMCP_CSTR_LEN);
			require_noerr(ret, bail);
			ret = smcp_outbound_set_uri(self->proxy_url,flags);
			goto bail;
		}
	}

	if (!(flags & SMCP_MSG_SKIP_AUTHORITY)) {
		if(components.host && !string_contains_colons(components.host)) {
			ret = smcp_outbound_add_option(COAP_OPTION_URI_HOST, components.host, SMCP_CSTR_LEN);
			require_noerr(ret, bail);
		}
		if(components.port) {
			ret = smcp_outbound_add_option_uint(COAP_OPTION_URI_PORT, toport);
			require_noerr(ret, bail);
		}
	}


	if ( !(flags & SMCP_MSG_SKIP_DESTADDR)
	  && components.host && components.host[0]!=0
	) {
		ret = smcp_set_remote_sockaddr_from_host_and_port(
			components.host,
			toport
		);
		require_noerr(ret, bail);
	}

	if (components.path) {
		SMCP_NON_RECURSIVE char* component;
		const bool has_trailing_slash = components.path[0]?('/' == components.path[strlen(components.path)-1]):false;

		// Move past any preceding slashes.
		while (components.path[0] == '/') {
			components.path++;
		}

		while (url_path_next_component(&components.path,&component)) {
			ret = smcp_outbound_add_option(COAP_OPTION_URI_PATH, component, SMCP_CSTR_LEN);
			require_noerr(ret,bail);
		}

		if (has_trailing_slash) {
			ret = smcp_outbound_add_option(COAP_OPTION_URI_PATH, NULL, 0);
			require_noerr(ret,bail);
		}
	}

	if (components.query) {
		SMCP_NON_RECURSIVE char* key;

		while (url_form_next_value(&components.query, &key, NULL)) {
			coap_size_t len = (coap_size_t)strlen(key);

			if (len) {
				ret = smcp_outbound_add_option(COAP_OPTION_URI_QUERY, key, len);
			}
			require_noerr(ret,bail);
		}
	}

bail:
	if(ret) {
		DEBUG_PRINTF("URI Parse failed for URI: \"%s\"",uri);
	}

#if !HAVE_ALLOCA && !SMCP_AVOID_MALLOC
	free(uri_copy);
#endif

	return ret;
}
Beispiel #6
0
int
tool_cmd_test(
	smcp_t smcp_instance, int argc, char* argv[]
) {
	if((2 == argc) && (0 == strcmp(argv[1], "--help"))) {
		printf("Help not yet implemented for this command.\n");
		return ERRORCODE_HELP;
	}

	smcp_t smcp;
	smcp_t smcp2;

	struct smcp_timer_node_s timer_node = {};
	struct smcp_variable_node_s device_node = {};
	struct smcp_node_s async_response_node = {};

	smcp2 = smcp_create(12345);
	if(smcp_get_port(smcp_instance) == SMCP_DEFAULT_PORT)
		smcp = smcp_instance;
	else
		smcp = smcp_create(SMCP_DEFAULT_PORT);

	//printf(__FILE__":%d: root node child count = %d\n",__LINE__,(int)bt_count(&smcp_get_root_node(smcp)->children));

#if HAVE_LIBCURL
	struct smcp_curl_proxy_node_s proxy_node = {};
//	curl_global_init(CURL_GLOBAL_ALL);

//	CURLM* curl_multi_handle = curl_multi_init();
	smcp_curl_proxy_node_init(
		&proxy_node,
		smcp_get_root_node(smcp),
		"proxy"
	);
#endif

	//printf(__FILE__":%d: root node child count = %d\n",__LINE__,(int)bt_count(&smcp_get_root_node(smcp)->children));

//	smcp_pairing_init(
//		smcp_get_root_node(smcp),
//		SMCP_PAIRING_DEFAULT_ROOT_PATH
//	);
//
//	smcp_pairing_init(
//		smcp_get_root_node(smcp2),
//		SMCP_PAIRING_DEFAULT_ROOT_PATH
//	);

	//printf(__FILE__":%d: root node child count = %d\n",__LINE__,(int)bt_count(&smcp_get_root_node(smcp)->children));

	smcp_variable_node_init(
		&device_node,
		smcp_get_root_node(smcp),
		"device"
	);
	device_node.func = device_func;

	//printf(__FILE__":%d: root node child count = %d\n",__LINE__,(int)bt_count(&smcp_get_root_node(smcp)->children));

	smcp_variable_node_init(
		NULL,
		smcp_get_root_node(smcp2),
		"device"
	)->func = device_func;

	//printf(__FILE__":%d: root node child count = %d\n",__LINE__,(int)bt_count(&smcp_get_root_node(smcp)->children));

	smcp_timer_node_init(
		&timer_node,
		smcp_get_root_node(smcp),
		"timer"
	);

	//printf(__FILE__":%d: root node child count = %d\n",__LINE__,(int)bt_count(&smcp_get_root_node(smcp)->children));

	smcp_node_init((smcp_node_t)&async_response_node,
		smcp_get_root_node(smcp),
		"async_response"
	);
	async_response_node.request_handler = &async_request_handler;

	//printf(__FILE__":%d: root node child count = %d\n",__LINE__,(int)bt_count(&smcp_get_root_node(smcp)->children));

#if !SMCP_CONF_OBSERVING_ONLY
	{
		char url[256];
		snprintf(url,
			sizeof(url),
			"smcp://127.0.0.1:%d/device/action",
			smcp_get_port(smcp2));
		smcp_pair_with_uri(smcp,
			"device/loadavg",
			url,
			0,
			NULL);
		printf("EVENT_NODE PAIRED WITH %s\n", url);
	}

	{
		char url[256];
		snprintf(url,
			sizeof(url),
			"smcp://[::1]:%d/device/loadavg",
			smcp_get_port(smcp));
		smcp_pair_with_uri(smcp2, "device/action", url, 0, NULL);
		printf("ACTION_NODE PAIRED WITH %s\n", url);
	}
#endif

	//printf(__FILE__":%d: root node child count = %d\n",__LINE__,(int)bt_count(&smcp_get_root_node(smcp)->children));

	// Just adding some random nodes so we can browse thru them with another process...
	{
		smcp_node_t subdevice = smcp_node_init(NULL,
			smcp_get_root_node(smcp),
			"lots_of_devices");
		unsigned char i = 0;
#if 1
		for(i = i * 97 + 101; i; i = i * 97 + 101) {
#else
		for(i = 0; i != 255; i++) {
#endif
			char *name = NULL;
			asprintf(&name, "subdevice_%d", i); // Will leak, but we don't care.
			smcp_node_init(NULL, (smcp_node_t)subdevice, name);
		}
//		{
//			unsigned int i = bt_rebalance(
//				    (void**)&((smcp_node_t)subdevice)->children);
//			printf("Balance operation took %u rotations\n", i);
//		}
//		{
//			unsigned int i = bt_rebalance(
//				    (void**)&((smcp_node_t)subdevice)->children);
//			printf("Second balance operation took %u rotations\n", i);
//		}
//		{
//			unsigned int i = bt_rebalance(
//				    (void**)&((smcp_node_t)subdevice)->children);
//			printf("Third balance operation took %u rotations\n", i);
//		}
//		{
//			unsigned int i = bt_rebalance(
//				    (void**)&((smcp_node_t)subdevice)->children);
//			printf("Fourth balance operation took %u rotations\n", i);
//		}
	}

	//printf(__FILE__":%d: root node child count = %d\n",__LINE__,(int)bt_count(&smcp_get_root_node(smcp)->children));

	{
		coap_msg_id_t tid = smcp_get_next_msg_id(smcp2);

		char url[256];

#if 0
		snprintf(url,
			sizeof(url),
			"smcp://["COAP_MULTICAST_IP6_ALLDEVICES"]:%d/device/",
			smcp_get_port(smcp));
#else
		snprintf(url,
			sizeof(url),
			"smcp://[::1]:%d/device/",
			smcp_get_port(smcp));
#endif

		smcp_begin_transaction_old(
			smcp2,
			tid,
			5 * MSEC_PER_SEC,
			0, // Flags
			NULL,
			&list_response_handler,
			NULL
		);

		smcp_outbound_begin(smcp2,COAP_METHOD_GET,COAP_TRANS_TYPE_CONFIRMABLE);
			smcp_outbound_set_msg_id(tid);
			smcp_outbound_set_uri(url, 0);
		smcp_outbound_send();

		fprintf(stderr, " *** Sent LIST request...\n");
	}

	//printf(__FILE__":%d: root node child count = %d\n",__LINE__,(int)bt_count(&smcp_get_root_node(smcp)->children));

	int i;
	for(i = 0; 1/*i < 3000000*/; i++) {
#if 1
		if((i - 1) % 250 == 0) {
			fprintf(stderr, " *** Forcing variable refresh...\n");
			smcp_variable_node_did_change(&device_node,0,NULL);
		}
#endif
		smcp_process(smcp);
		smcp_process(smcp2);
#if HAVE_LIBCURL
		smcp_curl_proxy_node_process(&proxy_node);
#endif
	}

bail:

	return 0;
}