static inline bool do_relative_http_request(struct update_info *info, const char *url, const char *file) { long response_code; char *full_url = get_path(url, file); bool success = do_http_request(info, full_url, &response_code); bfree(full_url); return success && response_code == 200; }
static bool delete_tep_from_packet_reflectors( transaction_entry *entry, uint32_t vni, const char *address ) { debug( "Deleting a tunnel endpoint from packet reflectors ( entry = %p, vni = %#x, address = %s ).", entry, vni, address != NULL ? address : "" ); assert( entry != NULL ); assert( address != NULL ); if ( !valid_vni( vni ) ) { return false; } char *delete_uri = NULL; list_element *reflectors = NULL; bool ret = get_reflectors_to_update( &reflectors, vni ); if ( !ret ) { error( "Failed to retrieve reflectors information ( vni = %#x ).", vni ); goto error; } for ( list_element *e = reflectors; e != NULL; e = e->next ) { char *base_uri = e->data; size_t delete_uri_length = strlen( base_uri ) + strlen( "reflector/" ) + MAX_VNI_STRLEN + INET_ADDRSTRLEN; delete_uri = xmalloc( delete_uri_length ); memset( delete_uri, '\0', delete_uri_length ); snprintf( delete_uri, delete_uri_length, "%sreflector/%u/%s", base_uri, vni & VNI_MASK, address ); ret = do_http_request( HTTP_METHOD_DELETE, delete_uri, NULL, http_transaction_completed, entry ); if ( !ret ) { error( "Failed to send a HTTP request." ); entry->n_failed_http_requests++; goto error; } entry->n_ongoing_http_requests++; xfree( delete_uri ); } free_list( reflectors ); return true; error: if ( reflectors != NULL ) { free_list( reflectors ); } if ( delete_uri != NULL ) { xfree( delete_uri ); } return false; }
static bool delete_tunnel_from_tep( transaction_entry *entry, uint32_t vni, uint64_t datapath_id ) { debug( "Deleting a virtual network from a tunnel endpoint ( entry = %p, vni = %#x, datapath_id = %#" PRIx64 ").", entry, vni, datapath_id ); assert( entry != NULL ); char *base_uri = NULL; char *delete_uri = NULL; bool ret = get_agent_uri( datapath_id, &base_uri ); if ( !ret ) { error( "Failed to retrieve agent information ( datapath_id = %#" PRIx64 " ).", datapath_id ); goto error; } size_t delete_uri_length = strlen( base_uri ) + strlen( "overlay_networks/" ) + MAX_VNI_STRLEN; delete_uri = xmalloc( delete_uri_length ); memset( delete_uri, '\0', delete_uri_length ); snprintf( delete_uri, delete_uri_length, "%soverlay_networks/%u", base_uri, vni & VNI_MASK ); ret = do_http_request( HTTP_METHOD_DELETE, delete_uri, NULL, http_transaction_completed, entry ); if ( !ret ) { error( "Failed to send a HTTP request to HTTP client thread ( datapath_id = %" PRIx64 " ).", datapath_id ); entry->n_failed_http_requests++; goto error; } entry->n_ongoing_http_requests++; xfree( base_uri ); xfree( delete_uri ); return true; error: if ( base_uri != NULL ) { xfree( base_uri ); } if ( delete_uri != NULL ) { xfree( delete_uri ); } return false; }
static bool add_tunnel_to_tep( transaction_entry *entry, uint32_t vni, uint64_t datapath_id, const char *broadcast_address, uint16_t broadcast_port ) { debug( "Adding a virtual network to a tunnel endpoint ( entry = %p, vni = %#x, datapath_id = %#" PRIx64 ", broadcast_address = %s, broadcast_port = %u ).", entry, vni, datapath_id, broadcast_address != NULL ? broadcast_address : "", broadcast_port ); assert( entry != NULL ); assert( broadcast_address != NULL ); char *base_uri = NULL; char *post_uri = NULL; char *json_string = NULL; http_content content; memset( &content, 0 , sizeof( http_content ) ); bool ret = get_agent_uri( datapath_id, &base_uri ); if ( !ret ) { error( "Failed to retrieve agent information ( datapath_id = %#" PRIx64 " ).", datapath_id ); goto error; } ret = create_json_to_add_tunnel( &json_string, vni, broadcast_address, broadcast_port ); if ( !ret || json_string == NULL || ( json_string != NULL && strlen( json_string ) == 0 ) ) { error( "Failed to create json string for Gate Switch." ); goto error; } size_t post_uri_length = strlen( base_uri ) + strlen( "overlay_networks" ) + 1; post_uri = xmalloc( post_uri_length ); memset( post_uri, '\0', post_uri_length ); snprintf( post_uri, post_uri_length, "%soverlay_networks", base_uri ); memset( content.content_type, '\0', sizeof( content.content_type ) ); snprintf( content.content_type, sizeof( content.content_type ), "application/json" ); size_t json_string_length = strlen( json_string ) + 1; content.body = alloc_buffer_with_length( json_string_length ); void *p = append_back_buffer( content.body, json_string_length ); memcpy( p, json_string, json_string_length ); ret = do_http_request( HTTP_METHOD_POST, post_uri, &content, http_transaction_completed, entry ); if ( !ret ) { error( "Failed to send a HTTP request to HTTP client thread ( datapath_id = %" PRIx64 " ).", datapath_id ); entry->n_failed_http_requests++; goto error; } entry->n_ongoing_http_requests++; xfree( base_uri ); xfree( post_uri ); xfree( json_string ); free_buffer( content.body ); return true; error: if ( base_uri != NULL ) { xfree( base_uri ); } if ( post_uri != NULL ) { xfree( post_uri ); } if ( json_string != NULL) { xfree( json_string ); } if ( content.body != NULL ) { free_buffer( content.body ); } return false; }
static bool add_tep_to_packet_reflectors( transaction_entry *entry, uint32_t vni, const char *address, uint16_t port ) { debug( "Adding a tunnel endpoint to packet reflectors ( entry = %p, vni = %#x, address = %s, port = %u ).", entry, vni, address != NULL ? address : "", port ); assert( entry != NULL ); assert( address != NULL ); assert( port > 0 ); if ( !valid_vni( vni ) ) { return false; } char *post_uri = NULL; char *json_string = NULL; list_element *reflectors = NULL; http_content content; memset( &content, 0, sizeof( http_content ) ); bool ret = get_reflectors_to_update( &reflectors, vni ); if ( !ret ) { error( "Failed to retrieve reflectors information ( vni = %#x ).", vni ); goto error; } ret = create_json_to_add_tep( &json_string, address, port ); if ( !ret || json_string == NULL || ( json_string != NULL && strlen( json_string ) == 0 ) ) { error( "Failed to create json string for packet reflector." ); goto error; } memset( content.content_type, '\0', sizeof( content.content_type ) ); snprintf( content.content_type, sizeof( content.content_type ), "application/json" ); size_t json_string_length = strlen( json_string ) + 1; content.body = alloc_buffer_with_length( json_string_length ); void *p = append_back_buffer( content.body, json_string_length ); memcpy( p, json_string, json_string_length ); for ( list_element *e = reflectors; e != NULL; e = e->next ) { char *base_uri = e->data; size_t post_uri_length = strlen( base_uri ) + strlen( "reflector/" ) + MAX_VNI_STRLEN; post_uri = xmalloc( post_uri_length ); memset( post_uri, '\0', post_uri_length ); snprintf( post_uri, post_uri_length, "%sreflector/%u", base_uri, vni & VNI_MASK ); ret = do_http_request( HTTP_METHOD_POST, post_uri, &content, http_transaction_completed, entry ); if ( !ret ) { error( "Failed to send a HTTP request." ); entry->n_failed_http_requests++; goto error; } entry->n_ongoing_http_requests++; xfree( post_uri ); } free_list( reflectors ); xfree( json_string ); free_buffer( content.body ); return true; error: if ( reflectors != NULL ) { free_list( reflectors ); } if ( json_string != NULL ) { xfree( json_string ); } if ( post_uri != NULL ) { xfree( post_uri ); } if ( content.body != NULL ) { free_buffer( content.body ); } return false; }
static bool update_remote_files(void *param, obs_data_t *remote_file) { struct update_info *info = param; struct file_update_data data = { .name = obs_data_get_string(remote_file, "name"), .version = (int)obs_data_get_int(remote_file, "version") }; enum_files(info->cache_package, newer_than_cache, &data); if (!data.newer && data.found) return true; if (!do_relative_http_request(info, info->remote_url, data.name)) return true; if (info->callback) { struct file_download_data download_data; bool confirm; download_data.name = data.name; download_data.version = data.version; download_data.buffer.da = info->file_data.da; confirm = info->callback(info->param, &download_data); info->file_data.da = download_data.buffer.da; if (!confirm) { info("Update file '%s' (version %d) rejected", data.name, data.version); return true; } } write_file_data(info, info->temp, data.name); replace_file(info->temp, info->cache, data.name); info("Successfully updated file '%s' (version %d)", data.name, data.version); return true; } static void update_save_metadata(struct update_info *info) { struct dstr path = { 0 }; if (!info->etag_remote) return; dstr_copy(&path, info->cache); dstr_cat(&path, "meta.json"); obs_data_t *data; data = obs_data_create(); obs_data_set_string(data, "etag", info->etag_remote); obs_data_save_json(data, path.array); obs_data_release(data); } static void update_remote_version(struct update_info *info, int cur_version) { int remote_version; long response_code; if (!do_http_request(info, info->url, &response_code)) return; if (response_code == 304) return; if (!info->file_data.array || info->file_data.array[0] != '{') { warn("Remote package does not exist or is not valid json"); return; } update_save_metadata(info); info->remote_package = obs_data_create_from_json( (char*)info->file_data.array); if (!info->remote_package) { warn("Failed to initialize remote package json"); return; } remote_version = (int)obs_data_get_int(info->remote_package, "version"); if (remote_version <= cur_version) return; write_file_data(info, info->temp, "package.json"); info->remote_url = obs_data_get_string(info->remote_package, "url"); if (!info->remote_url) { warn("No remote url in package file"); return; } /* download new files */ enum_files(info->remote_package, update_remote_files, info); replace_file(info->temp, info->cache, "package.json"); info("Successfully updated package (version %d)", remote_version); return; }