Improve call wording, cleanup
This commit is contained in:
parent
0409f55426
commit
7d2e647690
|
@ -25,7 +25,6 @@ public class Dino.Ui.CallBottomBar : Gtk.Box {
|
||||||
private MenuButton video_settings_button = new MenuButton() { halign=Align.END, valign=Align.END };
|
private MenuButton video_settings_button = new MenuButton() { halign=Align.END, valign=Align.END };
|
||||||
public VideoSettingsPopover? video_settings_popover;
|
public VideoSettingsPopover? video_settings_popover;
|
||||||
|
|
||||||
private EventBox encryption_event_box = new EventBox() { visible=true };
|
|
||||||
private MenuButton encryption_button = new MenuButton() { relief=ReliefStyle.NONE, height_request=30, width_request=30, margin_start=20, margin_bottom=25, halign=Align.START, valign=Align.END };
|
private MenuButton encryption_button = new MenuButton() { relief=ReliefStyle.NONE, height_request=30, width_request=30, margin_start=20, margin_bottom=25, halign=Align.START, valign=Align.END };
|
||||||
private Image encryption_image = new Image.from_icon_name("changes-allow-symbolic", IconSize.BUTTON) { visible=true };
|
private Image encryption_image = new Image.from_icon_name("changes-allow-symbolic", IconSize.BUTTON) { visible=true };
|
||||||
|
|
||||||
|
|
|
@ -158,13 +158,13 @@ namespace Dino.Ui {
|
||||||
public void set_status(string state) {
|
public void set_status(string state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case "requested":
|
case "requested":
|
||||||
header_bar.subtitle = _("Sending a call request…");
|
header_bar.subtitle = _("Calling…");
|
||||||
break;
|
break;
|
||||||
case "ringing":
|
case "ringing":
|
||||||
header_bar.subtitle = _("Ringing…");
|
header_bar.subtitle = _("Ringing…");
|
||||||
break;
|
break;
|
||||||
case "establishing":
|
case "establishing":
|
||||||
header_bar.subtitle = _("Establishing a (peer-to-peer) connection…");
|
header_bar.subtitle = _("Connecting…");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
header_bar.subtitle = null;
|
header_bar.subtitle = null;
|
||||||
|
|
|
@ -3,8 +3,6 @@ using Gtk;
|
||||||
|
|
||||||
public class Dino.Ui.CallWindowController : Object {
|
public class Dino.Ui.CallWindowController : Object {
|
||||||
|
|
||||||
public signal void terminated();
|
|
||||||
|
|
||||||
private CallWindow call_window;
|
private CallWindow call_window;
|
||||||
private Call call;
|
private Call call;
|
||||||
private Conversation conversation;
|
private Conversation conversation;
|
||||||
|
@ -40,8 +38,16 @@ public class Dino.Ui.CallWindowController : Object {
|
||||||
call_window.set_status("requested");
|
call_window.set_status("requested");
|
||||||
}
|
}
|
||||||
|
|
||||||
call_window.bottom_bar.hang_up.connect(end_call);
|
call_window.bottom_bar.hang_up.connect(() => {
|
||||||
call_window.destroy.connect(end_call);
|
calls.end_call(conversation, call);
|
||||||
|
call_window.close();
|
||||||
|
call_window.destroy();
|
||||||
|
this.dispose();
|
||||||
|
});
|
||||||
|
call_window.destroy.connect(() => {
|
||||||
|
calls.end_call(conversation, call);
|
||||||
|
this.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
call_window.bottom_bar.notify["audio-enabled"].connect(() => {
|
call_window.bottom_bar.notify["audio-enabled"].connect(() => {
|
||||||
calls.mute_own_audio(call, !call_window.bottom_bar.audio_enabled);
|
calls.mute_own_audio(call, !call_window.bottom_bar.audio_enabled);
|
||||||
|
@ -116,16 +122,6 @@ public class Dino.Ui.CallWindowController : Object {
|
||||||
this.window_width = this.call_window.get_allocated_width();
|
this.window_width = this.call_window.get_allocated_width();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void end_call() {
|
|
||||||
call.notify["state"].disconnect(on_call_state_changed);
|
|
||||||
calls.call_terminated.disconnect(on_call_terminated);
|
|
||||||
|
|
||||||
calls.end_call(conversation, call);
|
|
||||||
call_window.close();
|
|
||||||
call_window.destroy();
|
|
||||||
terminated();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void on_call_state_changed() {
|
private void on_call_state_changed() {
|
||||||
if (call.state == Call.State.IN_PROGRESS) {
|
if (call.state == Call.State.IN_PROGRESS) {
|
||||||
call_window.set_status("");
|
call_window.set_status("");
|
||||||
|
@ -234,4 +230,10 @@ public class Dino.Ui.CallWindowController : Object {
|
||||||
call_window.unset_own_video();
|
call_window.unset_own_video();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void dispose() {
|
||||||
|
base.dispose();
|
||||||
|
call.notify["state"].disconnect(on_call_state_changed);
|
||||||
|
calls.call_terminated.disconnect(on_call_terminated);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -154,7 +154,7 @@ namespace Dino.Ui {
|
||||||
case Call.State.FAILED:
|
case Call.State.FAILED:
|
||||||
image.set_from_icon_name("dino-phone-hangup-symbolic", IconSize.LARGE_TOOLBAR);
|
image.set_from_icon_name("dino-phone-hangup-symbolic", IconSize.LARGE_TOOLBAR);
|
||||||
title_label.label = _("Call failed");
|
title_label.label = _("Call failed");
|
||||||
subtitle_label.label = "This call failed to establish";
|
subtitle_label.label = "Call failed to establish";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,9 +92,6 @@ namespace Dino.Ui {
|
||||||
call_window.present();
|
call_window.present();
|
||||||
|
|
||||||
update_button_state();
|
update_button_state();
|
||||||
call_controller.terminated.connect(() => {
|
|
||||||
update_button_state();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public new void set_conversation(Conversation conversation) {
|
public new void set_conversation(Conversation conversation) {
|
||||||
|
@ -119,7 +116,7 @@ namespace Dino.Ui {
|
||||||
if (conversation.type_ == Conversation.Type.CHAT) {
|
if (conversation.type_ == Conversation.Type.CHAT) {
|
||||||
Conversation conv_bak = conversation;
|
Conversation conv_bak = conversation;
|
||||||
bool audio_works = yield stream_interactor.get_module(Calls.IDENTITY).can_do_audio_calls_async(conversation);
|
bool audio_works = yield stream_interactor.get_module(Calls.IDENTITY).can_do_audio_calls_async(conversation);
|
||||||
bool video_works = yield stream_interactor.get_module(Calls.IDENTITY).can_do_audio_calls_async(conversation);
|
bool video_works = yield stream_interactor.get_module(Calls.IDENTITY).can_do_video_calls_async(conversation);
|
||||||
if (conv_bak != conversation) return;
|
if (conv_bak != conversation) return;
|
||||||
|
|
||||||
visible = audio_works;
|
visible = audio_works;
|
||||||
|
|
|
@ -65,7 +65,6 @@ namespace Dino.Plugins.Omemo.DtlsSrtpVerificationDraft {
|
||||||
|
|
||||||
stream.get_flag(Xep.Jingle.Flag.IDENTITY).get_session.begin(jingle_sid, (_, res) => {
|
stream.get_flag(Xep.Jingle.Flag.IDENTITY).get_session.begin(jingle_sid, (_, res) => {
|
||||||
Xep.Jingle.Session? session = stream.get_flag(Xep.Jingle.Flag.IDENTITY).get_session.end(res);
|
Xep.Jingle.Session? session = stream.get_flag(Xep.Jingle.Flag.IDENTITY).get_session.end(res);
|
||||||
if (session != null) print(@"$(session.contents_map.has_key(content_name))\n");
|
|
||||||
if (session == null || !session.contents_map.has_key(content_name)) return;
|
if (session == null || !session.contents_map.has_key(content_name)) return;
|
||||||
var encryption = new OmemoContentEncryption() { encryption_ns=NS_URI, encryption_name="OMEMO", our_key=new uint8[0], peer_key=new uint8[0], peer_device_id=device_id_by_jingle_sid[jingle_sid] };
|
var encryption = new OmemoContentEncryption() { encryption_ns=NS_URI, encryption_name="OMEMO", our_key=new uint8[0], peer_key=new uint8[0], peer_device_id=device_id_by_jingle_sid[jingle_sid] };
|
||||||
session.contents_map[content_name].encryptions[NS_URI] = encryption;
|
session.contents_map[content_name].encryptions[NS_URI] = encryption;
|
||||||
|
|
|
@ -216,9 +216,9 @@ public class Dino.Plugins.Rtp.Module : JingleRtp.Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override JingleRtp.Crypto? generate_local_crypto() {
|
public override JingleRtp.Crypto? generate_local_crypto() {
|
||||||
uint8[] keyAndSalt = new uint8[30];
|
uint8[] key_and_salt = new uint8[30];
|
||||||
Crypto.randomize(keyAndSalt);
|
Crypto.randomize(key_and_salt);
|
||||||
return JingleRtp.Crypto.create(JingleRtp.Crypto.AES_CM_128_HMAC_SHA1_80, keyAndSalt);
|
return JingleRtp.Crypto.create(JingleRtp.Crypto.AES_CM_128_HMAC_SHA1_80, key_and_salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override JingleRtp.Crypto? pick_remote_crypto(Gee.List<JingleRtp.Crypto> cryptos) {
|
public override JingleRtp.Crypto? pick_remote_crypto(Gee.List<JingleRtp.Crypto> cryptos) {
|
||||||
|
@ -230,8 +230,8 @@ public class Dino.Plugins.Rtp.Module : JingleRtp.Module {
|
||||||
|
|
||||||
public override JingleRtp.Crypto? pick_local_crypto(JingleRtp.Crypto? remote) {
|
public override JingleRtp.Crypto? pick_local_crypto(JingleRtp.Crypto? remote) {
|
||||||
if (remote == null || !remote.is_valid) return null;
|
if (remote == null || !remote.is_valid) return null;
|
||||||
uint8[] keyAndSalt = new uint8[30];
|
uint8[] key_and_salt = new uint8[30];
|
||||||
Crypto.randomize(keyAndSalt);
|
Crypto.randomize(key_and_salt);
|
||||||
return remote.rekey(keyAndSalt);
|
return remote.rekey(key_and_salt);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -256,7 +256,7 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepare_local_crypto() {
|
private void prepare_local_crypto() {
|
||||||
if (local_crypto != null && !crypto_session.has_encrypt) {
|
if (local_crypto != null && local_crypto.is_valid && !crypto_session.has_encrypt) {
|
||||||
crypto_session.set_encryption_key(local_crypto.crypto_suite, local_crypto.key, local_crypto.salt);
|
crypto_session.set_encryption_key(local_crypto.crypto_suite, local_crypto.key, local_crypto.salt);
|
||||||
debug("Setting up encryption with key params %s", local_crypto.key_params);
|
debug("Setting up encryption with key params %s", local_crypto.key_params);
|
||||||
}
|
}
|
||||||
|
@ -396,7 +396,7 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepare_remote_crypto() {
|
private void prepare_remote_crypto() {
|
||||||
if (remote_crypto != null && !crypto_session.has_decrypt) {
|
if (remote_crypto != null && remote_crypto.is_valid && !crypto_session.has_decrypt) {
|
||||||
crypto_session.set_decryption_key(remote_crypto.crypto_suite, remote_crypto.key, remote_crypto.salt);
|
crypto_session.set_decryption_key(remote_crypto.crypto_suite, remote_crypto.key, remote_crypto.salt);
|
||||||
debug("Setting up decryption with key params %s", remote_crypto.key_params);
|
debug("Setting up decryption with key params %s", remote_crypto.key_params);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,11 @@ namespace Xmpp.Xep.Jingle {
|
||||||
protected Gee.Promise<IOStream> promise = new Gee.Promise<IOStream>();
|
protected Gee.Promise<IOStream> promise = new Gee.Promise<IOStream>();
|
||||||
private string? terminated = null;
|
private string? terminated = null;
|
||||||
|
|
||||||
public async void init(IOStream stream) {
|
public async void set_stream(IOStream? stream) {
|
||||||
|
if (stream == null) {
|
||||||
|
promise.set_exception(new IOError.FAILED("Jingle connection failed"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
assert(!this.stream.ready);
|
assert(!this.stream.ready);
|
||||||
promise.set_value(stream);
|
promise.set_value(stream);
|
||||||
if (terminated != null) {
|
if (terminated != null) {
|
||||||
|
@ -39,11 +43,17 @@ namespace Xmpp.Xep.Jingle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void set_error(GLib.Error? e) {
|
||||||
|
promise.set_exception(e);
|
||||||
|
}
|
||||||
|
|
||||||
public override async void terminate(bool we_terminated, string? reason_name = null, string? reason_text = null) {
|
public override async void terminate(bool we_terminated, string? reason_name = null, string? reason_text = null) {
|
||||||
if (terminated == null) {
|
if (terminated == null) {
|
||||||
terminated = (reason_name ?? "") + " - " + (reason_text ?? "") + @"we terminated? $we_terminated";
|
terminated = (reason_name ?? "") + " - " + (reason_text ?? "") + @"we terminated? $we_terminated";
|
||||||
if (stream.ready) {
|
if (stream.ready) {
|
||||||
yield stream.value.close_async();
|
yield stream.value.close_async();
|
||||||
|
} else {
|
||||||
|
promise.set_exception(new IOError.FAILED("Jingle connection failed"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ public class Xmpp.Xep.Jingle.Content : Object {
|
||||||
|
|
||||||
public HashMap<string, ContentEncryption> encryptions = new HashMap<string, ContentEncryption>();
|
public HashMap<string, ContentEncryption> encryptions = new HashMap<string, ContentEncryption>();
|
||||||
|
|
||||||
public Set<string> tried_transport_methods = new HashSet<string>();
|
private Set<string> tried_transport_methods = new HashSet<string>();
|
||||||
|
|
||||||
|
|
||||||
public Content.initiate_sent(string content_name, Senders senders,
|
public Content.initiate_sent(string content_name, Senders senders,
|
||||||
|
@ -109,7 +109,7 @@ public class Xmpp.Xep.Jingle.Content : Object {
|
||||||
transport_params.dispose();
|
transport_params.dispose();
|
||||||
|
|
||||||
foreach (ComponentConnection connection in component_connections.values) {
|
foreach (ComponentConnection connection in component_connections.values) {
|
||||||
connection.terminate(we_terminated, reason_name, reason_text);
|
connection.terminate.begin(we_terminated, reason_name, reason_text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ public abstract class Module : XmppStreamModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Jingle.Content add_outgoing_video_content(XmppStream stream, Jingle.Session session) {
|
public async Jingle.Content add_outgoing_video_content(XmppStream stream, Jingle.Session session) throws Jingle.Error {
|
||||||
Jid my_jid = session.local_full_jid;
|
Jid my_jid = session.local_full_jid;
|
||||||
Jid receiver_full_jid = session.peer_full_jid;
|
Jid receiver_full_jid = session.peer_full_jid;
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ public class Crypto {
|
||||||
public string? session_params { get; private set; }
|
public string? session_params { get; private set; }
|
||||||
public string tag { get; private set; }
|
public string tag { get; private set; }
|
||||||
|
|
||||||
public uint8[] key_and_salt { owned get {
|
public uint8[]? key_and_salt { owned get {
|
||||||
if (!key_params.has_prefix("inline:")) return null;
|
if (!key_params.has_prefix("inline:")) return null;
|
||||||
int endIndex = key_params.index_of("|");
|
int endIndex = key_params.index_of("|");
|
||||||
if (endIndex < 0) endIndex = key_params.length;
|
if (endIndex < 0) endIndex = key_params.length;
|
||||||
|
@ -221,30 +221,30 @@ public class Crypto {
|
||||||
case AES_CM_128_HMAC_SHA1_80:
|
case AES_CM_128_HMAC_SHA1_80:
|
||||||
case AES_CM_128_HMAC_SHA1_32:
|
case AES_CM_128_HMAC_SHA1_32:
|
||||||
case F8_128_HMAC_SHA1_80:
|
case F8_128_HMAC_SHA1_80:
|
||||||
return key_and_salt.length == 30;
|
return key_and_salt != null && key_and_salt.length == 30;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
public uint8[] key { owned get {
|
public uint8[]? key { owned get {
|
||||||
uint8[] key_and_salt = key_and_salt;
|
uint8[]? key_and_salt = key_and_salt;
|
||||||
switch(crypto_suite) {
|
switch(crypto_suite) {
|
||||||
case AES_CM_128_HMAC_SHA1_80:
|
case AES_CM_128_HMAC_SHA1_80:
|
||||||
case AES_CM_128_HMAC_SHA1_32:
|
case AES_CM_128_HMAC_SHA1_32:
|
||||||
case F8_128_HMAC_SHA1_80:
|
case F8_128_HMAC_SHA1_80:
|
||||||
if (key_and_salt.length >= 16) return key_and_salt[0:16];
|
if (key_and_salt != null && key_and_salt.length >= 16) return key_and_salt[0:16];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
public uint8[] salt { owned get {
|
public uint8[]? salt { owned get {
|
||||||
uint8[] keyAndSalt = key_and_salt;
|
uint8[]? key_and_salt = key_and_salt;
|
||||||
switch(crypto_suite) {
|
switch(crypto_suite) {
|
||||||
case AES_CM_128_HMAC_SHA1_80:
|
case AES_CM_128_HMAC_SHA1_80:
|
||||||
case AES_CM_128_HMAC_SHA1_32:
|
case AES_CM_128_HMAC_SHA1_32:
|
||||||
case F8_128_HMAC_SHA1_80:
|
case F8_128_HMAC_SHA1_80:
|
||||||
if (keyAndSalt.length >= 30) return keyAndSalt[16:30];
|
if (key_and_salt != null && key_and_salt.length >= 30) return key_and_salt[16:30];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -152,7 +152,7 @@ public abstract class Xmpp.Xep.JingleIceUdp.IceUdpTransportParameters : Jingle.T
|
||||||
return sb.str;
|
return sb.str;
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint8[] fingerprint_to_bytes(string? fingerprint_) {
|
private uint8[]? fingerprint_to_bytes(string? fingerprint_) {
|
||||||
if (fingerprint_ == null) return null;
|
if (fingerprint_ == null) return null;
|
||||||
|
|
||||||
string fingerprint = fingerprint_.replace(":", "").up();
|
string fingerprint = fingerprint_.replace(":", "").up();
|
||||||
|
|
|
@ -268,13 +268,19 @@ public class FileTransfer : Object {
|
||||||
content.accept();
|
content.accept();
|
||||||
|
|
||||||
Jingle.StreamingConnection connection = content.component_connections.values.to_array()[0] as Jingle.StreamingConnection;
|
Jingle.StreamingConnection connection = content.component_connections.values.to_array()[0] as Jingle.StreamingConnection;
|
||||||
IOStream? io_stream = yield connection.stream.wait_async();
|
try {
|
||||||
|
IOStream io_stream = yield connection.stream.wait_async();
|
||||||
FileTransferInputStream ft_stream = new FileTransferInputStream(io_stream.input_stream, size);
|
FileTransferInputStream ft_stream = new FileTransferInputStream(io_stream.input_stream, size);
|
||||||
io_stream.output_stream.close();
|
io_stream.output_stream.close();
|
||||||
ft_stream.closed.connect(() => {
|
ft_stream.closed.connect(() => {
|
||||||
session.terminate(Jingle.ReasonElement.SUCCESS, null, null);
|
session.terminate(Jingle.ReasonElement.SUCCESS, null, null);
|
||||||
});
|
});
|
||||||
this.stream = ft_stream;
|
this.stream = ft_stream;
|
||||||
|
} catch (FutureError.EXCEPTION e) {
|
||||||
|
warning("Error accepting Jingle file-transfer: %s", connection.stream.exception.message);
|
||||||
|
} catch (FutureError e) {
|
||||||
|
warning("FutureError accepting Jingle file-transfer: %s", e.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reject(XmppStream stream) {
|
public void reject(XmppStream stream) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ public class Module : Jingle.Transport, XmppStreamModule {
|
||||||
public string ns_uri { get { return NS_URI; } }
|
public string ns_uri { get { return NS_URI; } }
|
||||||
public Jingle.TransportType type_ { get { return Jingle.TransportType.STREAMING; } }
|
public Jingle.TransportType type_ { get { return Jingle.TransportType.STREAMING; } }
|
||||||
public int priority { get { return 1; } }
|
public int priority { get { return 1; } }
|
||||||
|
|
||||||
private Gee.List<Candidate> get_proxies(XmppStream stream) {
|
private Gee.List<Candidate> get_proxies(XmppStream stream) {
|
||||||
Gee.List<Candidate> result = new ArrayList<Candidate>();
|
Gee.List<Candidate> result = new ArrayList<Candidate>();
|
||||||
int i = 1 << 15;
|
int i = 1 << 15;
|
||||||
|
@ -37,6 +38,7 @@ public class Module : Jingle.Transport, XmppStreamModule {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Gee.List<Candidate> start_local_listeners(XmppStream stream, Jid local_full_jid, string dstaddr, out LocalListener? local_listener) {
|
private Gee.List<Candidate> start_local_listeners(XmppStream stream, Jid local_full_jid, string dstaddr, out LocalListener? local_listener) {
|
||||||
Gee.List<Candidate> result = new ArrayList<Candidate>();
|
Gee.List<Candidate> result = new ArrayList<Candidate>();
|
||||||
SocketListener listener = new SocketListener();
|
SocketListener listener = new SocketListener();
|
||||||
|
@ -62,15 +64,17 @@ public class Module : Jingle.Transport, XmppStreamModule {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void select_candidates(XmppStream stream, Jid local_full_jid, string dstaddr, Parameters result) {
|
private void select_candidates(XmppStream stream, Jid local_full_jid, string dstaddr, Parameters result) {
|
||||||
result.local_candidates.add_all(get_proxies(stream));
|
result.local_candidates.add_all(get_proxies(stream));
|
||||||
//result.local_candidates.add_all(start_local_listeners(stream, local_full_jid, dstaddr, out result.listener));
|
result.local_candidates.add_all(start_local_listeners(stream, local_full_jid, dstaddr, out result.listener));
|
||||||
result.local_candidates.sort((c1, c2) => {
|
result.local_candidates.sort((c1, c2) => {
|
||||||
if (c1.priority < c2.priority) { return 1; }
|
if (c1.priority < c2.priority) { return 1; }
|
||||||
if (c1.priority > c2.priority) { return -1; }
|
if (c1.priority > c2.priority) { return -1; }
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Jingle.TransportParameters create_transport_parameters(XmppStream stream, uint8 components, Jid local_full_jid, Jid peer_full_jid) {
|
public Jingle.TransportParameters create_transport_parameters(XmppStream stream, uint8 components, Jid local_full_jid, Jid peer_full_jid) {
|
||||||
assert(components == 1);
|
assert(components == 1);
|
||||||
Parameters result = new Parameters.create(local_full_jid, peer_full_jid, random_uuid());
|
Parameters result = new Parameters.create(local_full_jid, peer_full_jid, random_uuid());
|
||||||
|
@ -78,6 +82,7 @@ public class Module : Jingle.Transport, XmppStreamModule {
|
||||||
select_candidates(stream, local_full_jid, dstaddr, result);
|
select_candidates(stream, local_full_jid, dstaddr, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Jingle.TransportParameters parse_transport_parameters(XmppStream stream, uint8 components, Jid local_full_jid, Jid peer_full_jid, StanzaNode transport) throws Jingle.IqError {
|
public Jingle.TransportParameters parse_transport_parameters(XmppStream stream, uint8 components, Jid local_full_jid, Jid peer_full_jid, StanzaNode transport) throws Jingle.IqError {
|
||||||
Parameters result = Parameters.parse(local_full_jid, peer_full_jid, transport);
|
Parameters result = Parameters.parse(local_full_jid, peer_full_jid, transport);
|
||||||
string dstaddr = calculate_dstaddr(result.sid, local_full_jid, peer_full_jid);
|
string dstaddr = calculate_dstaddr(result.sid, local_full_jid, peer_full_jid);
|
||||||
|
@ -146,6 +151,7 @@ public class Candidate : Socks5Bytestreams.Proxy {
|
||||||
public Candidate.build(string cid, string host, Jid jid, int port, int local_priority, CandidateType type) {
|
public Candidate.build(string cid, string host, Jid jid, int port, int local_priority, CandidateType type) {
|
||||||
this(cid, host, jid, port, type.type_preference() + local_priority, type);
|
this(cid, host, jid, port, type.type_preference() + local_priority, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Candidate.proxy(string cid, Socks5Bytestreams.Proxy proxy, int local_priority) {
|
public Candidate.proxy(string cid, Socks5Bytestreams.Proxy proxy, int local_priority) {
|
||||||
this.build(cid, proxy.host, proxy.jid, proxy.port, local_priority, CandidateType.PROXY);
|
this.build(cid, proxy.host, proxy.jid, proxy.port, local_priority, CandidateType.PROXY);
|
||||||
}
|
}
|
||||||
|
@ -170,6 +176,7 @@ public class Candidate : Socks5Bytestreams.Proxy {
|
||||||
|
|
||||||
return new Candidate(cid, host, jid, port, priority, type);
|
return new Candidate(cid, host, jid, port, priority, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StanzaNode to_xml() {
|
public StanzaNode to_xml() {
|
||||||
return new StanzaNode.build("candidate", NS_URI)
|
return new StanzaNode.build("candidate", NS_URI)
|
||||||
.put_attribute("cid", cid)
|
.put_attribute("cid", cid)
|
||||||
|
@ -210,6 +217,7 @@ class LocalListener {
|
||||||
this.inner = inner;
|
this.inner = inner;
|
||||||
this.dstaddr = dstaddr;
|
this.dstaddr = dstaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalListener.empty() {
|
public LocalListener.empty() {
|
||||||
this.inner = null;
|
this.inner = null;
|
||||||
this.dstaddr = "";
|
this.dstaddr = "";
|
||||||
|
@ -233,6 +241,7 @@ class LocalListener {
|
||||||
handle_conn.begin(((StringWrapper)cid).str, conn);
|
handle_conn.begin(((StringWrapper)cid).str, conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async void handle_conn(string cid, SocketConnection conn) {
|
async void handle_conn(string cid, SocketConnection conn) {
|
||||||
conn.socket.timeout = NEGOTIATION_TIMEOUT;
|
conn.socket.timeout = NEGOTIATION_TIMEOUT;
|
||||||
size_t read;
|
size_t read;
|
||||||
|
@ -418,39 +427,39 @@ class Parameters : Jingle.TransportParameters, Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle_transport_info(StanzaNode transport) throws Jingle.IqError {
|
public void handle_transport_info(StanzaNode transport) throws Jingle.IqError {
|
||||||
StanzaNode? candidate_error = transport.get_subnode("candidate-error", NS_URI);
|
ArrayList<StanzaNode> socks5_nodes = new ArrayList<StanzaNode>();
|
||||||
StanzaNode? candidate_used = transport.get_subnode("candidate-used", NS_URI);
|
foreach (StanzaNode node in transport.sub_nodes) {
|
||||||
StanzaNode? activated = transport.get_subnode("activated", NS_URI);
|
if (node.ns_uri == NS_URI) socks5_nodes.add(node);
|
||||||
StanzaNode? proxy_error = transport.get_subnode("proxy-error", NS_URI);
|
|
||||||
int num_children = 0;
|
|
||||||
if (candidate_error != null) { num_children += 1; }
|
|
||||||
if (candidate_used != null) { num_children += 1; }
|
|
||||||
if (activated != null) { num_children += 1; }
|
|
||||||
if (proxy_error != null) { num_children += 1; }
|
|
||||||
if (num_children == 0) {
|
|
||||||
throw new Jingle.IqError.UNSUPPORTED_INFO("unknown transport-info");
|
|
||||||
} else if (num_children > 1) {
|
|
||||||
throw new Jingle.IqError.BAD_REQUEST("transport-info with more than one child");
|
|
||||||
}
|
}
|
||||||
if (candidate_error != null) {
|
if (socks5_nodes.is_empty) { warning("No socks5 subnodes in transport node"); return; }
|
||||||
handle_remote_candidate(null);
|
if (socks5_nodes.size > 1) { warning("Too many socks5 subnodes in transport node"); return; }
|
||||||
}
|
|
||||||
if (candidate_used != null) {
|
StanzaNode node = socks5_nodes[0];
|
||||||
string? cid = candidate_used.get_attribute("cid");
|
|
||||||
if (cid == null) {
|
switch (node.name) {
|
||||||
throw new Jingle.IqError.BAD_REQUEST("missing cid");
|
case "activated":
|
||||||
}
|
string? cid = node.get_attribute("cid");
|
||||||
handle_remote_candidate(cid);
|
|
||||||
}
|
|
||||||
if (activated != null) {
|
|
||||||
string? cid = activated.get_attribute("cid");
|
|
||||||
if (cid == null) {
|
if (cid == null) {
|
||||||
throw new Jingle.IqError.BAD_REQUEST("missing cid");
|
throw new Jingle.IqError.BAD_REQUEST("missing cid");
|
||||||
}
|
}
|
||||||
handle_activated(cid);
|
handle_activated(cid);
|
||||||
|
break;
|
||||||
|
case "candidate-used":
|
||||||
|
string? cid = node.get_attribute("cid");
|
||||||
|
if (cid == null) {
|
||||||
|
throw new Jingle.IqError.BAD_REQUEST("missing cid");
|
||||||
}
|
}
|
||||||
if (proxy_error != null) {
|
handle_remote_candidate(cid);
|
||||||
|
break;
|
||||||
|
case "candidate-error":
|
||||||
|
handle_remote_candidate(null);
|
||||||
|
break;
|
||||||
|
case "proxy-error":
|
||||||
handle_proxy_error();
|
handle_proxy_error();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
warning("Unknown transport-info: %s", transport.to_string());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,32 +508,22 @@ class Parameters : Jingle.TransportParameters, Object {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Candidate? remote = remote_selected_candidate;
|
if (remote_selected_candidate == null && local_selected_candidate == null) {
|
||||||
Candidate? local = local_selected_candidate;
|
content_set_transport_connection_error(new IOError.FAILED("No candidates"));
|
||||||
|
|
||||||
int num_candidates = 0;
|
|
||||||
if (remote != null) { num_candidates += 1; }
|
|
||||||
if (local != null) { num_candidates += 1; }
|
|
||||||
|
|
||||||
if (num_candidates == 0) {
|
|
||||||
// Notify Jingle of the failed transport.
|
|
||||||
content_set_transport_connection(null);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool remote_wins;
|
bool remote_wins;
|
||||||
if (num_candidates == 1) {
|
if (remote_selected_candidate != null && local_selected_candidate != null) {
|
||||||
remote_wins = remote != null;
|
if (local_selected_candidate.priority == remote_selected_candidate.priority) {
|
||||||
} else {
|
|
||||||
if (local.priority < remote.priority) {
|
|
||||||
remote_wins = true;
|
|
||||||
} else if (local.priority > remote.priority) {
|
|
||||||
remote_wins = false;
|
|
||||||
} else {
|
|
||||||
// equal priority -> XEP-0260 says that the candidate offered
|
// equal priority -> XEP-0260 says that the candidate offered
|
||||||
// by the initiator wins, so the one that the remote chose
|
// by the initiator wins, so the one that the remote chose
|
||||||
remote_wins = role == Jingle.Role.INITIATOR;
|
remote_wins = role == Jingle.Role.INITIATOR;
|
||||||
|
} else {
|
||||||
|
remote_wins = local_selected_candidate.priority < remote_selected_candidate.priority;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
remote_wins = remote_selected_candidate != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!remote_wins) {
|
if (!remote_wins) {
|
||||||
|
@ -545,8 +544,7 @@ class Parameters : Jingle.TransportParameters, Object {
|
||||||
}
|
}
|
||||||
SocketConnection? conn = listener.get_connection(remote_selected_candidate.cid);
|
SocketConnection? conn = listener.get_connection(remote_selected_candidate.cid);
|
||||||
if (conn == null) {
|
if (conn == null) {
|
||||||
// Remote hasn't actually connected to us?!
|
content_set_transport_connection_error(new IOError.FAILED("Remote hasn't actually connected to us?!"));
|
||||||
content_set_transport_connection(null);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
content_set_transport_connection(conn);
|
content_set_transport_connection(conn);
|
||||||
|
@ -569,7 +567,7 @@ class Parameters : Jingle.TransportParameters, Object {
|
||||||
if (!waiting_for_activation_error) {
|
if (!waiting_for_activation_error) {
|
||||||
content_set_transport_connection(conn);
|
content_set_transport_connection(conn);
|
||||||
} else {
|
} else {
|
||||||
content_set_transport_connection(null);
|
content_set_transport_connection_error(new IOError.FAILED("waiting_for_activation_error"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -620,7 +618,7 @@ class Parameters : Jingle.TransportParameters, Object {
|
||||||
.put_attribute("sid", sid)
|
.put_attribute("sid", sid)
|
||||||
.put_node(new StanzaNode.build("proxy-error", NS_URI))
|
.put_node(new StanzaNode.build("proxy-error", NS_URI))
|
||||||
);
|
);
|
||||||
content_set_transport_connection(null);
|
content_set_transport_connection_error(new IOError.FAILED("Connect to local candidate error: %s", e.message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -745,15 +743,19 @@ class Parameters : Jingle.TransportParameters, Object {
|
||||||
|
|
||||||
private Jingle.StreamingConnection connection = new Jingle.StreamingConnection();
|
private Jingle.StreamingConnection connection = new Jingle.StreamingConnection();
|
||||||
|
|
||||||
private void content_set_transport_connection(IOStream? ios) {
|
private void content_set_transport_connection(IOStream ios) {
|
||||||
IOStream? iostream = ios;
|
IOStream iostream = ios;
|
||||||
Jingle.Content? strong_content = content;
|
Jingle.Content? strong_content = content;
|
||||||
if (strong_content == null) return;
|
if (strong_content == null) return;
|
||||||
|
|
||||||
if (strong_content.security_params != null) {
|
if (strong_content.security_params != null) {
|
||||||
iostream = strong_content.security_params.wrap_stream(iostream);
|
iostream = strong_content.security_params.wrap_stream(iostream);
|
||||||
}
|
}
|
||||||
connection.init.begin(iostream);
|
connection.set_stream.begin(iostream);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void content_set_transport_connection_error(Error e) {
|
||||||
|
connection.set_error(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void create_transport_connection(XmppStream stream, Jingle.Content content) {
|
public void create_transport_connection(XmppStream stream, Jingle.Content content) {
|
||||||
|
|
|
@ -98,7 +98,7 @@ class Parameters : Jingle.TransportParameters, Object {
|
||||||
if (content.security_params != null) {
|
if (content.security_params != null) {
|
||||||
iostream = content.security_params.wrap_stream(iostream);
|
iostream = content.security_params.wrap_stream(iostream);
|
||||||
}
|
}
|
||||||
connection.init.begin(iostream);
|
connection.set_stream.begin(iostream);
|
||||||
debug("set transport conn ibb");
|
debug("set transport conn ibb");
|
||||||
content.set_transport_connection(connection, 1);
|
content.set_transport_connection(connection, 1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue