Factor out the session-terminate handler

This commit is contained in:
hrxi 2019-08-06 15:35:27 +02:00
parent 642dac9aa0
commit 94794666d7

View file

@ -102,16 +102,20 @@ ContentNode get_single_content_node(StanzaNode jingle) throws IqError {
}; };
} }
// This module can only be attached to one stream at a time.
public class Module : XmppStreamModule, Iq.Handler { public class Module : XmppStreamModule, Iq.Handler {
public static Xmpp.ModuleIdentity<Module> IDENTITY = new Xmpp.ModuleIdentity<Module>(NS_URI, "0166_jingle"); public static Xmpp.ModuleIdentity<Module> IDENTITY = new Xmpp.ModuleIdentity<Module>(NS_URI, "0166_jingle");
private HashMap<string, ContentType> content_types = new HashMap<string, ContentType>(); private HashMap<string, ContentType> content_types = new HashMap<string, ContentType>();
private HashMap<string, Transport> transports = new HashMap<string, Transport>(); private HashMap<string, Transport> transports = new HashMap<string, Transport>();
private XmppStream? current_stream = null;
public override void attach(XmppStream stream) { public override void attach(XmppStream stream) {
stream.add_flag(new Flag()); stream.add_flag(new Flag());
stream.get_module(ServiceDiscovery.Module.IDENTITY).add_feature(stream, NS_URI); stream.get_module(ServiceDiscovery.Module.IDENTITY).add_feature(stream, NS_URI);
stream.get_module(Iq.Module.IDENTITY).register_for_namespace(NS_URI, this); stream.get_module(Iq.Module.IDENTITY).register_for_namespace(NS_URI, this);
current_stream = stream;
} }
public override void detach(XmppStream stream) { } public override void detach(XmppStream stream) { }
@ -173,7 +177,7 @@ public class Module : XmppStreamModule, Iq.Handler {
throw new Error.GENERAL("Couldn't determine own JID"); throw new Error.GENERAL("Couldn't determine own JID");
} }
TransportParameters transport_params = transport.create_transport_parameters(stream, my_jid, receiver_full_jid); TransportParameters transport_params = transport.create_transport_parameters(stream, my_jid, receiver_full_jid);
Session session = new Session.initiate_sent(random_uuid(), type, transport_params, my_jid, receiver_full_jid, content_name, stream); Session session = new Session.initiate_sent(random_uuid(), type, transport_params, my_jid, receiver_full_jid, content_name, send_terminate_and_remove_session);
StanzaNode content = new StanzaNode.build("content", NS_URI) StanzaNode content = new StanzaNode.build("content", NS_URI)
.put_attribute("creator", "initiator") .put_attribute("creator", "initiator")
.put_attribute("name", content_name) .put_attribute("name", content_name)
@ -221,20 +225,34 @@ public class Module : XmppStreamModule, Iq.Handler {
ContentParameters content_params = content_type.parse_content_parameters(content.description); ContentParameters content_params = content_type.parse_content_parameters(content.description);
TransportType type = content_type.content_type_transport_type(); TransportType type = content_type.content_type_transport_type();
Session session = new Session.initiate_received(sid, type, transport_params, my_jid, iq.from, content.name, stream); Session session = new Session.initiate_received(sid, type, transport_params, my_jid, iq.from, content.name, send_terminate_and_remove_session);
stream.get_flag(Flag.IDENTITY).add_session(session); stream.get_flag(Flag.IDENTITY).add_session(session);
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, new Iq.Stanza.result(iq)); stream.get_module(Iq.Module.IDENTITY).send_iq(stream, new Iq.Stanza.result(iq));
if (transport == null || transport.transport_type() != type) { if (transport == null || transport.transport_type() != type) {
StanzaNode reason = new StanzaNode.build("reason", NS_URI) StanzaNode reason = new StanzaNode.build("reason", NS_URI)
.put_node(new StanzaNode.build("unsupported-transports", NS_URI)); .put_node(new StanzaNode.build("unsupported-transports", NS_URI));
session.terminate(stream, reason, "unsupported transports"); session.terminate(reason, "unsupported transports");
return; return;
} }
content_params.on_session_initiate(stream, session); content_params.on_session_initiate(stream, session);
} }
private void send_terminate_and_remove_session(Jid to, string sid, StanzaNode reason) {
StanzaNode jingle = new StanzaNode.build("jingle", NS_URI)
.add_self_xmlns()
.put_attribute("action", "session-terminate")
.put_attribute("sid", sid)
.put_node(reason);
Iq.Stanza iq = new Iq.Stanza.set(jingle) { to=to };
current_stream.get_module(Iq.Module.IDENTITY).send_iq(current_stream, iq);
// Immediately remove the session from the open sessions as per the
// XEP, don't wait for confirmation.
current_stream.get_flag(Flag.IDENTITY).remove_session(sid);
}
public void on_iq_set(XmppStream stream, Iq.Stanza iq) { public void on_iq_set(XmppStream stream, Iq.Stanza iq) {
try { try {
handle_iq_set(stream, iq); handle_iq_set(stream, iq);
@ -294,6 +312,8 @@ public enum Senders {
} }
} }
public delegate void SessionTerminate(Jid to, string sid, StanzaNode reason);
public interface Transport : Object { public interface Transport : Object {
public abstract string transport_ns_uri(); public abstract string transport_ns_uri();
public abstract bool is_transport_available(XmppStream stream, Jid full_jid); public abstract bool is_transport_available(XmppStream stream, Jid full_jid);
@ -372,9 +392,9 @@ public class Session {
// INITIATE_SENT | INITIATE_RECEIVED | CONNECTING // INITIATE_SENT | INITIATE_RECEIVED | CONNECTING
TransportParameters? transport = null; TransportParameters? transport = null;
XmppStream hack; SessionTerminate session_terminate_handler;
public Session.initiate_sent(string sid, Type type, TransportParameters transport, Jid local_full_jid, Jid peer_full_jid, string content_name, XmppStream hack) { public Session.initiate_sent(string sid, Type type, TransportParameters transport, Jid local_full_jid, Jid peer_full_jid, string content_name, owned SessionTerminate session_terminate_handler) {
this.state = State.INITIATE_SENT; this.state = State.INITIATE_SENT;
this.sid = sid; this.sid = sid;
this.type_ = type; this.type_ = type;
@ -384,10 +404,10 @@ public class Session {
this.content_name = content_name; this.content_name = content_name;
this.transport = transport; this.transport = transport;
this.connection = new Connection(this); this.connection = new Connection(this);
this.hack = hack; this.session_terminate_handler = (owned)session_terminate_handler;
} }
public Session.initiate_received(string sid, Type type, TransportParameters? transport, Jid local_full_jid, Jid peer_full_jid, string content_name, XmppStream hack) { public Session.initiate_received(string sid, Type type, TransportParameters? transport, Jid local_full_jid, Jid peer_full_jid, string content_name, owned SessionTerminate session_terminate_handler) {
this.state = State.INITIATE_RECEIVED; this.state = State.INITIATE_RECEIVED;
this.sid = sid; this.sid = sid;
this.type_ = type; this.type_ = type;
@ -397,7 +417,7 @@ public class Session {
this.content_name = content_name; this.content_name = content_name;
this.transport = transport; this.transport = transport;
this.connection = new Connection(this); this.connection = new Connection(this);
this.hack = hack; this.session_terminate_handler = (owned)session_terminate_handler;
} }
public void handle_iq_set(XmppStream stream, string action, StanzaNode jingle, Iq.Stanza iq) throws IqError { public void handle_iq_set(XmppStream stream, string action, StanzaNode jingle, Iq.Stanza iq) throws IqError {
@ -466,7 +486,7 @@ public class Session {
// TODO(hrxi): try negotiating other transports // TODO(hrxi): try negotiating other transports
StanzaNode reason = new StanzaNode.build("reason", NS_URI) StanzaNode reason = new StanzaNode.build("reason", NS_URI)
.put_node(new StanzaNode.build("failed-transport", NS_URI)); .put_node(new StanzaNode.build("failed-transport", NS_URI));
terminate(stream, reason, "failed transport"); terminate(reason, "failed transport");
} }
} }
void handle_session_terminate(XmppStream stream, StanzaNode jingle, Iq.Stanza iq) throws IqError { void handle_session_terminate(XmppStream stream, StanzaNode jingle, Iq.Stanza iq) throws IqError {
@ -544,7 +564,7 @@ public class Session {
} }
StanzaNode reason = new StanzaNode.build("reason", NS_URI) StanzaNode reason = new StanzaNode.build("reason", NS_URI)
.put_node(new StanzaNode.build("decline", NS_URI)); .put_node(new StanzaNode.build("decline", NS_URI));
terminate(stream, reason, "declined"); terminate(reason, "declined");
} }
public void set_application_error(XmppStream stream, StanzaNode? application_reason = null) { public void set_application_error(XmppStream stream, StanzaNode? application_reason = null) {
@ -553,7 +573,7 @@ public class Session {
if (application_reason != null) { if (application_reason != null) {
reason.put_node(application_reason); reason.put_node(application_reason);
} }
terminate(stream, reason, "application error"); terminate(reason, "application error");
} }
public void on_connection_error(IOError error) { public void on_connection_error(IOError error) {
@ -563,15 +583,15 @@ public class Session {
.put_node(new StanzaNode.build("text", NS_URI) .put_node(new StanzaNode.build("text", NS_URI)
.put_node(new StanzaNode.text(error.message)) .put_node(new StanzaNode.text(error.message))
); );
terminate(hack, reason, "transport error: $(error.message)"); terminate(reason, "transport error: $(error.message)");
} }
public void on_connection_close() { public void on_connection_close() {
StanzaNode reason = new StanzaNode.build("reason", NS_URI) StanzaNode reason = new StanzaNode.build("reason", NS_URI)
.put_node(new StanzaNode.build("success", NS_URI)); .put_node(new StanzaNode.build("success", NS_URI));
terminate(hack, reason, "success"); terminate(reason, "success");
} }
public void terminate(XmppStream stream, StanzaNode reason, string? local_reason) { public void terminate(StanzaNode reason, string? local_reason) {
if (state == State.ENDED) { if (state == State.ENDED) {
return; return;
} }
@ -583,18 +603,8 @@ public class Session {
} }
} }
StanzaNode jingle = new StanzaNode.build("jingle", NS_URI) session_terminate_handler(peer_full_jid, sid, reason);
.add_self_xmlns()
.put_attribute("action", "session-terminate")
.put_attribute("sid", sid)
.put_node(reason);
Iq.Stanza iq = new Iq.Stanza.set(jingle) { to=peer_full_jid };
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq);
state = State.ENDED; state = State.ENDED;
// Immediately remove the session from the open sessions as per the
// XEP, don't wait for confirmation.
stream.get_flag(Flag.IDENTITY).remove_session(sid);
} }
} }