2020-11-16 14:55:33 +00:00
|
|
|
using Gee;
|
|
|
|
|
|
|
|
public interface Xmpp.WriteNodeFunc : Object {
|
2023-01-31 14:12:39 +00:00
|
|
|
public abstract async void write_stanza(XmppStream stream, StanzaNode node) throws IOError;
|
2020-11-16 14:55:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public abstract class Xmpp.IoXmppStream : XmppStream {
|
|
|
|
private IOStream? stream;
|
|
|
|
internal StanzaReader? reader;
|
|
|
|
internal StanzaWriter? writer;
|
|
|
|
|
|
|
|
internal WriteNodeFunc? write_obj = null;
|
|
|
|
|
2020-12-31 18:00:54 +00:00
|
|
|
protected IoXmppStream(Jid remote_name) {
|
|
|
|
base(remote_name);
|
|
|
|
}
|
|
|
|
|
2023-01-31 14:12:39 +00:00
|
|
|
public override async void disconnect() throws IOError {
|
2020-11-16 14:55:33 +00:00
|
|
|
disconnected = true;
|
|
|
|
if (writer == null || reader == null || stream == null) {
|
2023-01-31 14:12:39 +00:00
|
|
|
throw new IOError.CLOSED("trying to disconnect, but no stream open");
|
2020-11-16 14:55:33 +00:00
|
|
|
}
|
|
|
|
log.str("OUT", "</stream:stream>", this);
|
|
|
|
yield writer.write("</stream:stream>");
|
|
|
|
reader.cancel();
|
|
|
|
yield stream.close_async();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void reset_stream(IOStream stream) {
|
|
|
|
this.stream = stream;
|
|
|
|
reader = new StanzaReader.for_stream(stream.input_stream);
|
|
|
|
writer = new StanzaWriter.for_stream(stream.output_stream);
|
|
|
|
|
|
|
|
writer.cancel.connect(reader.cancel);
|
|
|
|
require_setup();
|
|
|
|
}
|
|
|
|
|
2023-01-31 14:12:39 +00:00
|
|
|
public override async StanzaNode read() throws IOError {
|
2020-11-16 14:55:33 +00:00
|
|
|
StanzaReader? reader = this.reader;
|
2023-01-31 14:12:39 +00:00
|
|
|
if (reader == null) throw new IOError.NOT_CONNECTED("trying to read, but no stream open");
|
|
|
|
StanzaNode node = yield ((!)reader).read_node();
|
|
|
|
log.node("IN", node, this);
|
|
|
|
return node;
|
2020-11-16 14:55:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
[Version (deprecated = true, deprecated_since = "0.1", replacement = "write_async")]
|
|
|
|
public override void write(StanzaNode node) {
|
|
|
|
write_async.begin(node, (obj, res) => {
|
|
|
|
try {
|
|
|
|
write_async.end(res);
|
|
|
|
} catch (Error e) { }
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-01-31 14:12:39 +00:00
|
|
|
public override async void write_async(StanzaNode node) throws IOError {
|
2020-11-16 14:55:33 +00:00
|
|
|
if (write_obj != null) {
|
|
|
|
yield write_obj.write_stanza(this, node);
|
|
|
|
} else {
|
|
|
|
StanzaWriter? writer = this.writer;
|
2023-01-31 14:12:39 +00:00
|
|
|
if (writer == null) throw new IOError.NOT_CONNECTED("trying to write, but no stream open");
|
|
|
|
log.node("OUT", node, this);
|
|
|
|
yield ((!)writer).write_node(node);
|
2020-11-16 14:55:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal IOStream? get_stream() {
|
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
|
2023-01-31 14:12:39 +00:00
|
|
|
public override async void setup() throws IOError {
|
2020-11-16 14:55:33 +00:00
|
|
|
StanzaNode outs = new StanzaNode.build("stream", "http://etherx.jabber.org/streams")
|
|
|
|
.put_attribute("to", remote_name.to_string())
|
|
|
|
.put_attribute("version", "1.0")
|
|
|
|
.put_attribute("xmlns", "jabber:client")
|
|
|
|
.put_attribute("stream", "http://etherx.jabber.org/streams", XMLNS_URI);
|
|
|
|
outs.has_nodes = true;
|
|
|
|
log.node("OUT ROOT", outs, this);
|
|
|
|
write(outs);
|
|
|
|
received_root_node(this, yield read_root());
|
|
|
|
|
|
|
|
setup_needed = false;
|
|
|
|
}
|
|
|
|
|
2023-01-31 14:12:39 +00:00
|
|
|
private async StanzaNode read_root() throws IOError {
|
2020-11-16 14:55:33 +00:00
|
|
|
StanzaReader? reader = this.reader;
|
2023-01-31 14:12:39 +00:00
|
|
|
if (reader == null) throw new IOError.NOT_CONNECTED("trying to read, but no stream open");
|
|
|
|
StanzaNode node = yield ((!)reader).read_root_node();
|
|
|
|
log.node("IN ROOT", node, this);
|
|
|
|
return node;
|
2020-11-16 14:55:33 +00:00
|
|
|
}
|
|
|
|
}
|