-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Migrate from NetServiceBrowser to NWBrowser; prepare CastSocket!
- Loading branch information
Showing
9 changed files
with
1,098 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// Copyright 2014 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
syntax = "proto2"; | ||
|
||
option optimize_for = LITE_RUNTIME; | ||
|
||
package cast_channel; | ||
|
||
message CastMessage { | ||
// Always pass a version of the protocol for future compatibility | ||
// requirements. | ||
enum ProtocolVersion { CASTV2_1_0 = 0; } | ||
required ProtocolVersion protocol_version = 1; | ||
|
||
// source and destination ids identify the origin and destination of the | ||
// message. They are used to route messages between endpoints that share a | ||
// device-to-device channel. | ||
// | ||
// For messages between applications: | ||
// - The sender application id is a unique identifier generated on behalf of | ||
// the sender application. | ||
// - The receiver id is always the the session id for the application. | ||
// | ||
// For messages to or from the sender or receiver platform, the special ids | ||
// 'sender-0' and 'receiver-0' can be used. | ||
// | ||
// For messages intended for all endpoints using a given channel, the | ||
// wildcard destination_id '*' can be used. | ||
required string source_id = 2; | ||
required string destination_id = 3; | ||
|
||
// This is the core multiplexing key. All messages are sent on a namespace | ||
// and endpoints sharing a channel listen on one or more namespaces. The | ||
// namespace defines the protocol and semantics of the message. | ||
required string namespace = 4; | ||
|
||
// Encoding and payload info follows. | ||
|
||
// What type of data do we have in this message. | ||
enum PayloadType { | ||
STRING = 0; | ||
BINARY = 1; | ||
} | ||
required PayloadType payload_type = 5; | ||
|
||
// Depending on payload_type, exactly one of the following optional fields | ||
// will always be set. | ||
optional string payload_utf8 = 6; | ||
optional bytes payload_binary = 7; | ||
} | ||
|
||
enum SignatureAlgorithm { | ||
UNSPECIFIED = 0; | ||
RSASSA_PKCS1v15 = 1; | ||
RSASSA_PSS = 2; | ||
} | ||
|
||
enum HashAlgorithm { | ||
SHA1 = 0; | ||
SHA256 = 1; | ||
} | ||
|
||
// Messages for authentication protocol between a sender and a receiver. | ||
message AuthChallenge { | ||
optional SignatureAlgorithm signature_algorithm = 1 | ||
[default = RSASSA_PKCS1v15]; | ||
optional bytes sender_nonce = 2; | ||
optional HashAlgorithm hash_algorithm = 3 [default = SHA1]; | ||
} | ||
|
||
message AuthResponse { | ||
required bytes signature = 1; | ||
required bytes client_auth_certificate = 2; | ||
repeated bytes intermediate_certificate = 3; | ||
optional SignatureAlgorithm signature_algorithm = 4 | ||
[default = RSASSA_PKCS1v15]; | ||
optional bytes sender_nonce = 5; | ||
optional HashAlgorithm hash_algorithm = 6 [default = SHA1]; | ||
optional bytes crl = 7; | ||
} | ||
|
||
message AuthError { | ||
enum ErrorType { | ||
INTERNAL_ERROR = 0; | ||
NO_TLS = 1; // The underlying connection is not TLS | ||
SIGNATURE_ALGORITHM_UNAVAILABLE = 2; | ||
} | ||
required ErrorType error_type = 1; | ||
} | ||
|
||
message DeviceAuthMessage { | ||
// Request fields | ||
optional AuthChallenge challenge = 1; | ||
// Response fields | ||
optional AuthResponse response = 2; | ||
optional AuthError error = 3; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// | ||
// CastSocket.swift | ||
// castable | ||
// | ||
// Created by Daniel Leong on 12/5/20. | ||
// | ||
|
||
import Foundation | ||
import Network | ||
|
||
/// Low-level communication with a Chromecast device | ||
class CastSocket { | ||
|
||
private var address: NWEndpoint | ||
|
||
private var connection: NWConnection? = nil | ||
|
||
init(withAddress address: NWEndpoint) { | ||
self.address = address | ||
} | ||
|
||
func open() { | ||
NSLog("castable: open()") | ||
if let old = connection { | ||
NSLog("castable: WARN: duplicate open()") | ||
old.cancel() | ||
} | ||
|
||
let address = self.address | ||
let conn = NWConnection(to: address, using: insecureTLSParameters()) | ||
connection = conn | ||
|
||
conn.start(queue: DispatchQueue.main) | ||
conn.stateUpdateHandler = { state in | ||
NSLog("castable: connection(\(address)) state <- \(state)") | ||
switch state { | ||
case .ready: | ||
NSLog("castable: connection(\(address)) READY") | ||
self.close() | ||
|
||
case .failed(let error): | ||
NSLog("castable: connection(\(address)) FAILED: \(error)") | ||
self.close() | ||
break | ||
|
||
default: | ||
break // nop | ||
} | ||
} | ||
|
||
NSLog("castable: connected") | ||
} | ||
|
||
func close() { | ||
connection?.cancel() | ||
connection = nil | ||
} | ||
|
||
private func insecureTLSParameters() -> NWParameters { | ||
let opts = NWProtocolTLS.Options() | ||
let address = self.address | ||
|
||
// borrowed from: https://stackoverflow.com/a/54467228 | ||
sec_protocol_options_set_verify_block(opts.securityProtocolOptions, { (sec_protocol_metadata, sec_trust, sec_protocol_verify_complete) in | ||
let trust = sec_trust_copy_ref(sec_trust).takeRetainedValue() | ||
var error: CFError? | ||
if SecTrustEvaluateWithError(trust, &error) { | ||
sec_protocol_verify_complete(true) | ||
} else { | ||
NSLog("castable: allowing insecure: \(trust) for \(address)") | ||
sec_protocol_verify_complete(true) | ||
} | ||
}, DispatchQueue.main) | ||
|
||
return NWParameters(tls: opts) | ||
} | ||
} |
Oops, something went wrong.