Changes
3 changed files (+96/-0)
-
-
@@ -195,6 +195,17 @@ self.servers_ptr = servers.ptr;self.servers_len = servers.len; } pub fn initFindResult(self: *ScanResult, found: *Server) std.mem.Allocator.Error!void { const servers = try allocator.alloc(*Server, 1); errdefer allocator.free(servers); servers[0] = found; self.internal.servers = servers; self.servers_ptr = servers.ptr; self.servers_len = 1; } pub fn retain(ptr: ?*ScanResult) callconv(.C) *ScanResult { var self = ptr orelse @panic(std.fmt.comptimePrint( "Received null pointer on {s}_{s}",
-
@@ -247,6 +258,25 @@return result.retain(); } pub fn find(server_id: [*:0]const u8) callconv(.C) ?*ScanResult { const result = ScanResult.make() catch { return null; }; const id = std.mem.span(server_id); findInternal(id, result) catch |err| { result.code = switch (err) { error.OutOfMemory => .out_of_memory, ScanError.NetworkUnavailable => .network_unavailable, ScanError.SocketPermissionDenied => .socket_permission_denied, ScanError.SocketError => .socket_error, }; }; return result.retain(); } const ScanError = error{ NetworkUnavailable, SocketPermissionDenied,
-
@@ -316,6 +346,67 @@ try result.setServers(&servers);result.code = .ok; } fn findInternal(server_id: []const u8, result: *ScanResult) !void { const sockfd = try createSocket(); defer std.posix.close(sockfd); for (0..udp_send_tries) |_| { try sendDiscoveryQuery(sockfd); while (true) { std.log.debug("Waiting for UDP message...", .{}); // Discovery response from servers usually fits under 300 bytes. // Extra bytes for safety. var received: [512]u8 = undefined; var src: std.net.Address = undefined; var src_len: std.posix.socklen_t = udp_dst.getOsSockLen(); const size = std.posix.recvfrom( sockfd, &received, 0, &src.any, &src_len, ) catch |err| switch (err) { std.posix.RecvFromError.WouldBlock => { std.log.debug("UDP read timeout.", .{}); break; }, std.posix.RecvFromError.MessageTooBig => { std.log.warn("Unable to read UDP message (message too big)", .{}); continue; }, else => return ScanError.SocketError, }; std.log.debug("Got UDP message.", .{}); const response = sood.discovery.Response.parse(received[0..size]) catch |err| { std.log.warn( "Unable to parse received UDP message as SOOD message: {s}", .{@errorName(err)}, ); // Non-SOOD message. Unlikely but technically possible. continue; }; if (!std.mem.eql(u8, response.unique_id, server_id)) { continue; } var server = try Server.make(&response, &src); errdefer server.release(); try result.initFindResult(server); return; } } result.code = .ok; 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| {
-
@@ -406,4 +497,5 @@ Server.export_capi();ScanResult.export_capi(); @export(&scan, .{ .name = "plac_discovery_scan" }); @export(&find, .{ .name = "plac_discovery_find" }); }
-
-
-
@@ -61,6 +61,7 @@ void plac_discovery_scan_result_release(plac_discovery_scan_result*);// discovery plac_discovery_scan_result *plac_discovery_scan(); plac_discovery_scan_result *plac_discovery_find(char *server_id); // transport.PlaybackState typedef enum {
-
-
-
@@ -74,6 +74,9 @@ public ScanResultCode code;} [CCode (cname = "plac_discovery_scan")] public ScanResult? scan(); [CCode (cname = "plac_discovery_find")] public ScanResult? find(string server_id); } namespace Transport {
-