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; }
smcp_status_t smcp_outbound_add_option_uint(coap_option_key_t key,uint32_t value) { uint8_t size; value = htonl(value); size = smcp_calc_uint32_option_size(value); return smcp_outbound_add_option(key, ((char*)&value)+(4-size), size); }
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; }
smcp_status_t smcp_auth_outbound_set_credentials(const char* username, const char* password) { smcp_status_t ret = SMCP_STATUS_OK; // TODO: Writeme! smcp_auth_user_t auth_user = smcp_auth_get_remote_user(username); //struct smcp_auth_nonce_s *auth_nonce; if(!auth_user) { require(username,bail); // Just do something stupid for now. ret = smcp_outbound_add_option(COAP_OPTION_AUTHENTICATE, NULL, 0); require(password,bail); auth_user = &global_temp_auth_user; smcp_auth_user_set(auth_user,username,password,""); } bail: return ret; }
smcp_status_t smcp_outbound_add_option_uint(coap_option_key_t key,uint32_t value) { if(value>>24) return value = htonl(value),smcp_outbound_add_option(key, ((char*)&value)+0, 4); else if(value>>16)
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; }
static smcp_status_t request_handler_new_group_( smcp_group_mgr_t self ) { smcp_status_t ret = SMCP_STATUS_OK; coap_content_type_t content_type; coap_size_t content_len; char* fqdn = NULL; char* addr_cstr = NULL; smcp_sockaddr_t saddr = { }; char* content_ptr = NULL; char* key = NULL; char* value = NULL; smcp_group_t group = NULL; char name_str[3] = { }; content_type = smcp_inbound_get_content_type(); content_ptr = (char*)smcp_inbound_get_content_ptr(); content_len = smcp_inbound_get_content_len(); switch (content_type) { case COAP_CONTENT_TYPE_UNKNOWN: case COAP_CONTENT_TYPE_TEXT_PLAIN: case SMCP_CONTENT_TYPE_APPLICATION_FORM_URLENCODED: content_len = 0; while( url_form_next_value( (char**)&content_ptr, &key, &value ) && key && value ) { if (strequal_const(key, names[I_FQDN])) { fqdn = value; DEBUG_PRINTF("new_group: fqdn=\"%s\"", value); } else if (strequal_const(key, names[I_ADDR])) { addr_cstr = value; DEBUG_PRINTF("new_group: addr=\"%s\"", value); } } break; default: return smcp_outbound_quick_response(HTTP_RESULT_CODE_UNSUPPORTED_MEDIA_TYPE, NULL); break; } if (NULL == addr_cstr) { require_action(NULL != fqdn, bail, ret = SMCP_STATUS_INVALID_ARGUMENT); addr_cstr = fqdn; } else if (NULL == fqdn) { fqdn = addr_cstr; } smcp_plat_lookup_hostname(addr_cstr, &saddr, SMCP_LOOKUP_HOSTNAME_FLAG_DEFAULT); group = smcp_group_mgr_new_group( self, fqdn, &saddr.smcp_addr, 0 ); if (!group) { return smcp_outbound_quick_response(COAP_RESULT_400_BAD_REQUEST, "(400) Failed to create group"); } // Default to enabled. smcp_group_set_enabled(group, true); name_str[0] = get_hex_char(group->index >> 4); name_str[1] = get_hex_char(group->index >> 0); smcp_outbound_begin_response(COAP_RESULT_201_CREATED); smcp_outbound_add_option(COAP_OPTION_LOCATION_PATH, name_str, SMCP_CSTR_LEN); smcp_outbound_append_content(name_str, SMCP_CSTR_LEN); smcp_outbound_send(); bail: return ret; }