int main(void) { smcp_t instance; SMCP_LIBRARY_VERSION_CHECK(); // Create our instance on the default CoAP port. If the port // is already in use, we will pick the next available port number. instance = smcp_create(); if (!instance) { perror("Unable to create SMCP instance"); exit(EXIT_FAILURE); } smcp_plat_bind_to_port(instance, SMCP_SESSION_TYPE_UDP, COAP_DEFAULT_PORT); printf("Listening on port %d\n",smcp_plat_get_port(instance)); // SMCP will always respond to requests with METHOD_NOT_IMPLEMENTED // unless a request handler is set. Unless your program is only // making CoAP requests, you'll need a line like the following // in your program. The request handler may either handle the // request itself or route the request to the appropriate handler. smcp_set_default_request_handler(instance, &request_handler, NULL); // Loop forever. This is the most simple kind of main loop you // can haave with SMCP. It is appropriate for simple CoAP servers // and clients which do not need asynchronous I/O. while (1) { smcp_plat_wait(instance, CMS_DISTANT_FUTURE); smcp_plat_process(instance); } // We won't actually get to this line with the above loop, but it // is always a good idea to clean up when you are done. If you // provide a way to gracefully exit from your own main loop, you // can tear down the SMCP instance using the following command. smcp_release(instance); return EXIT_SUCCESS; }
int main(int argc, char * argv[]) { smcp_t smcp; const char* url = "coap://localhost/"; int errorcount = 0; int round_count = 1; int round = 0; test_data_s test_data; SMCP_LIBRARY_VERSION_CHECK(); smcp = smcp_create(); smcp_plat_bind_to_port(smcp, SMCP_SESSION_TYPE_UDP, 0); // url = "coap://contiki.local./"; // url = "coap://coap.me/"; // url = "coap://vs0.inf.ethz.ch/"; if (argc > 1) url = argv[1]; if (!smcp) { fprintf(stderr,"Unable to allocate smcp instance\n"); exit(-1); } if (argc > 2) { round_count = atoi(argv[2]); } printf("Client using port %d. Will test %d rounds.\n", smcp_plat_get_port(smcp), round_count); #define do_test(x) do { printf("%s: Testing...\n",#x); if(test_ ## x(smcp,url,&test_data)) { dump_test_results(&test_data); printf("\tresult = OK\n"); } else { dump_test_results(&test_data); printf("\tresult = FAIL\n"); errorcount++; } } while(0) #define do_test_expect_fail(x) do { printf("%s: Testing...\n",#x); if(test_ ## x(smcp,url,&test_data)) { dump_test_results(&test_data); printf("\tresult = OK (Unexpected)\n"); } else { dump_test_results(&test_data); printf("\tresult = FAIL (Expected)\n"); } } while(0) for(round = 0;round<round_count && errorcount==0;round++) { printf("\n## Round %d...\n",round+1); do_test(TD_COAP_CORE_01); do_test(TD_COAP_CORE_02); do_test(TD_COAP_CORE_03); do_test(TD_COAP_CORE_04); do_test(TD_COAP_CORE_05); do_test(TD_COAP_CORE_06); do_test(TD_COAP_CORE_07); do_test(TD_COAP_CORE_08); do_test(TD_COAP_CORE_09); do_test(TD_COAP_CORE_13); do_test(TD_COAP_CORE_14); do_test(TD_COAP_CORE_17); do_test(TD_COAP_CORE_31); do_test(TD_COAP_LINK_01); do_test(TD_COAP_BLOCK_01); do_test(TD_COAP_BLOCK_02); do_test_expect_fail(TD_COAP_BLOCK_03); do_test_expect_fail(TD_COAP_BLOCK_04); do_test_expect_fail(TD_COAP_BLOCK_05); do_test(TD_COAP_OBS_01); } if (errorcount == 0) { printf("\nPASS\n"); } else { printf("\nFAIL\n"); } return errorcount; }
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; }