Changes
3 changed files (+103/-0)
-
-
@@ -16,10 +16,13 @@ // SPDX-License-Identifier: Apache-2.0const std = @import("std"); const moo = @import("moo"); const sood = @import("sood"); const websocket = @import("websocket"); const Arc = @import("./Arc.zig"); const freelog = @import("./log.zig").freelog; const RegistryService = @import("./services/registry.zig").RegistryService; const udp_dst = std.net.Address.initIp4( sood.discovery.multicast_ipv4_address,
-
@@ -271,6 +274,27 @@return result.retain(); } pub fn resolve(server_id: [*:0]const u8, ip_addr: [*:0]const u8, http_port: u16) callconv(.C) ?*ScanResult { var arena = std.heap.ArenaAllocator.init(std.heap.c_allocator); defer arena.deinit(); const result = ScanResult.make() catch { return null; }; const id = std.mem.span(server_id); const addr = std.mem.span(ip_addr); resolveInternal(arena.allocator(), id, addr, http_port, result) catch |err| { result.code = switch (err) { error.OutOfMemory => .out_of_memory, else => .unknown, }; }; return result.retain(); } const ScanError = error{ NetworkUnavailable, SocketPermissionDenied,
-
@@ -403,6 +427,76 @@ result.code = .ok;return; } fn resolveInternal( allocator: std.mem.Allocator, server_id: []const u8, ip_addr: []const u8, http_port: u16, result: *ScanResult, ) !void { std.log.debug("Establishing WebSocket connection to {s}:{d}...", .{ ip_addr, http_port, }); var ws = try websocket.Client.init(allocator, .{ .host = ip_addr, .port = http_port, .max_size = std.math.maxInt(u32), }); defer ws.deinit(); std.log.debug("Performing WebSocket handshake...", .{}); ws.handshake("/api", .{ .timeout_ms = 1_000 }) catch |err| { std.log.warn("Failed to perform WebSocket handshake, fallback to scan: {s}", .{@errorName(err)}); result.code = .ok; return; }; std.log.debug("Requesting server info...", .{}); { const req = try RegistryService.Info.request(allocator, 0); defer allocator.free(req); try ws.writeBin(req); } const msg = (try ws.read()) orelse { return error.ConnectionClosed; }; defer ws.done(msg); _, const header_ctx = try moo.Metadata.parse(msg.data); const resp = try RegistryService.Info.response(allocator, header_ctx, msg.data); defer resp.deinit(); if (!std.mem.eql(u8, server_id, resp.value.core_id)) { std.log.info( "Found Roon Server on saved IP address, got different server instance, fallback to scan: saved ID={s}, found ID={s}", .{ server_id, resp.value.core_id, }, ); result.code = .ok; return; } const addr = try std.net.Address.parseIp4(ip_addr, http_port); const sood_resp = sood.discovery.Response{ .display_version = resp.value.display_version, .name = resp.value.display_name, .unique_id = server_id, .http_port = http_port, }; var server = try Server.make(&sood_resp, &addr); errdefer server.release(); try result.initFindResult(server); return; } fn createSocket() !std.posix.socket_t { std.log.debug("Opening UDP socket...", .{}); const sockfd = std.posix.socket(std.posix.AF.INET, std.posix.SOCK.DGRAM, 0) catch |err| {
-
@@ -539,4 +633,5 @@ ScanResult.export_capi();@export(&scan, .{ .name = "plac_discovery_scan" }); @export(&find, .{ .name = "plac_discovery_find" }); @export(&resolve, .{ .name = "plac_discovery_resolve" }); }
-
-
-
@@ -63,6 +63,11 @@// discovery plac_discovery_scan_result *plac_discovery_scan(); plac_discovery_scan_result *plac_discovery_find(const char *server_id); plac_discovery_scan_result *plac_discovery_resolve( const char *server_id, const char *ip_addr, uint16_t http_port ); // transport.NowPlaying typedef struct {
-
-
-
@@ -77,6 +77,9 @@ public ScanResult? scan();[CCode (cname = "plac_discovery_find")] public ScanResult? find(string server_id); [CCode (cname = "plac_discovery_resolve")] public ScanResult? resolve(string server_id, string ip_addr, uint16 http_port); } namespace Transport {
-