Port crates to use new XSO-based xmlstream
This commit is contained in:
parent
7cfda820a6
commit
ab10e30ac0
26 changed files with 623 additions and 973 deletions
|
|
@ -1,9 +1,8 @@
|
|||
use futures::stream::StreamExt;
|
||||
use minidom::Element;
|
||||
use std::env::args;
|
||||
use std::process::exit;
|
||||
use std::str::FromStr;
|
||||
use tokio_xmpp::Client;
|
||||
use tokio_xmpp::{Client, Stanza};
|
||||
use xmpp_parsers::{
|
||||
disco::{DiscoInfoQuery, DiscoInfoResult},
|
||||
iq::{Iq, IqType},
|
||||
|
|
@ -41,24 +40,21 @@ async fn main() {
|
|||
let target_jid: Jid = target.clone().parse().unwrap();
|
||||
let iq = make_disco_iq(target_jid);
|
||||
println!("Sending disco#info request to {}", target.clone());
|
||||
println!(">> {}", String::from(&iq));
|
||||
client.send_stanza(iq).await.unwrap();
|
||||
} else if let Some(stanza) = event.into_stanza() {
|
||||
if stanza.is("iq", "jabber:client") {
|
||||
let iq = Iq::try_from(stanza).unwrap();
|
||||
if let IqType::Result(Some(payload)) = iq.payload {
|
||||
if payload.is("query", ns::DISCO_INFO) {
|
||||
if let Ok(disco_info) = DiscoInfoResult::try_from(payload) {
|
||||
for ext in disco_info.extensions {
|
||||
if let Ok(server_info) = ServerInfo::try_from(ext) {
|
||||
print_server_info(server_info);
|
||||
}
|
||||
println!(">> {:?}", iq);
|
||||
client.send_stanza(iq.into()).await.unwrap();
|
||||
} else if let Some(Stanza::Iq(iq)) = event.into_stanza() {
|
||||
if let IqType::Result(Some(payload)) = iq.payload {
|
||||
if payload.is("query", ns::DISCO_INFO) {
|
||||
if let Ok(disco_info) = DiscoInfoResult::try_from(payload) {
|
||||
for ext in disco_info.extensions {
|
||||
if let Ok(server_info) = ServerInfo::try_from(ext) {
|
||||
print_server_info(server_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
wait_for_stream_end = true;
|
||||
client.send_end().await.unwrap();
|
||||
}
|
||||
wait_for_stream_end = true;
|
||||
client.send_end().await.unwrap();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -67,11 +63,10 @@ async fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
fn make_disco_iq(target: Jid) -> Element {
|
||||
fn make_disco_iq(target: Jid) -> Iq {
|
||||
Iq::from_get("disco", DiscoInfoQuery { node: None })
|
||||
.with_id(String::from("contact"))
|
||||
.with_to(target)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn convert_field(field: Vec<String>) -> String {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
use futures::stream::StreamExt;
|
||||
use minidom::Element;
|
||||
use std::env::args;
|
||||
use std::fs::{create_dir_all, File};
|
||||
use std::io::{self, Write};
|
||||
use std::process::exit;
|
||||
use std::str::FromStr;
|
||||
use tokio_xmpp::Client;
|
||||
use tokio_xmpp::{Client, Stanza};
|
||||
use xmpp_parsers::{
|
||||
avatar::{Data as AvatarData, Metadata as AvatarMetadata},
|
||||
caps::{compute_disco, hash_caps, Caps},
|
||||
|
|
@ -13,7 +12,6 @@ use xmpp_parsers::{
|
|||
hashes::Algo,
|
||||
iq::{Iq, IqType},
|
||||
jid::{BareJid, Jid},
|
||||
message::Message,
|
||||
ns,
|
||||
presence::{Presence, Type as PresenceType},
|
||||
pubsub::{
|
||||
|
|
@ -55,100 +53,107 @@ async fn main() {
|
|||
let presence = make_presence(caps);
|
||||
client.send_stanza(presence.into()).await.unwrap();
|
||||
} else if let Some(stanza) = event.into_stanza() {
|
||||
if stanza.is("iq", "jabber:client") {
|
||||
let iq = Iq::try_from(stanza).unwrap();
|
||||
if let IqType::Get(payload) = iq.payload {
|
||||
if payload.is("query", ns::DISCO_INFO) {
|
||||
let query = DiscoInfoQuery::try_from(payload);
|
||||
match query {
|
||||
Ok(query) => {
|
||||
let mut disco = disco_info.clone();
|
||||
disco.node = query.node;
|
||||
let iq = Iq::from_result(iq.id, Some(disco))
|
||||
.with_to(iq.from.unwrap());
|
||||
client.send_stanza(iq.into()).await.unwrap();
|
||||
match stanza {
|
||||
Stanza::Iq(iq) => {
|
||||
if let IqType::Get(payload) = iq.payload {
|
||||
if payload.is("query", ns::DISCO_INFO) {
|
||||
let query = DiscoInfoQuery::try_from(payload);
|
||||
match query {
|
||||
Ok(query) => {
|
||||
let mut disco = disco_info.clone();
|
||||
disco.node = query.node;
|
||||
let iq = Iq::from_result(iq.id, Some(disco))
|
||||
.with_to(iq.from.unwrap());
|
||||
client.send_stanza(iq.into()).await.unwrap();
|
||||
}
|
||||
Err(err) => client
|
||||
.send_stanza(
|
||||
make_error(
|
||||
iq.from.unwrap(),
|
||||
iq.id,
|
||||
ErrorType::Modify,
|
||||
DefinedCondition::BadRequest,
|
||||
&format!("{}", err),
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
}
|
||||
Err(err) => client
|
||||
.send_stanza(make_error(
|
||||
} else {
|
||||
// We MUST answer unhandled get iqs with a service-unavailable error.
|
||||
client
|
||||
.send_stanza(
|
||||
make_error(
|
||||
iq.from.unwrap(),
|
||||
iq.id,
|
||||
ErrorType::Cancel,
|
||||
DefinedCondition::ServiceUnavailable,
|
||||
"No handler defined for this kind of iq.",
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
} else if let IqType::Result(Some(payload)) = iq.payload {
|
||||
if payload.is("pubsub", ns::PUBSUB) {
|
||||
let pubsub = PubSub::try_from(payload).unwrap();
|
||||
let from = iq.from.clone().unwrap_or(jid.clone().into());
|
||||
handle_iq_result(pubsub, &from);
|
||||
}
|
||||
} else if let IqType::Set(_) = iq.payload {
|
||||
// We MUST answer unhandled set iqs with a service-unavailable error.
|
||||
client
|
||||
.send_stanza(
|
||||
make_error(
|
||||
iq.from.unwrap(),
|
||||
iq.id,
|
||||
ErrorType::Modify,
|
||||
DefinedCondition::BadRequest,
|
||||
&format!("{}", err),
|
||||
))
|
||||
.await
|
||||
.unwrap(),
|
||||
}
|
||||
} else {
|
||||
// We MUST answer unhandled get iqs with a service-unavailable error.
|
||||
client
|
||||
.send_stanza(make_error(
|
||||
iq.from.unwrap(),
|
||||
iq.id,
|
||||
ErrorType::Cancel,
|
||||
DefinedCondition::ServiceUnavailable,
|
||||
"No handler defined for this kind of iq.",
|
||||
))
|
||||
ErrorType::Cancel,
|
||||
DefinedCondition::ServiceUnavailable,
|
||||
"No handler defined for this kind of iq.",
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
} else if let IqType::Result(Some(payload)) = iq.payload {
|
||||
if payload.is("pubsub", ns::PUBSUB) {
|
||||
let pubsub = PubSub::try_from(payload).unwrap();
|
||||
let from = iq.from.clone().unwrap_or(jid.clone().into());
|
||||
handle_iq_result(pubsub, &from);
|
||||
}
|
||||
} else if let IqType::Set(_) = iq.payload {
|
||||
// We MUST answer unhandled set iqs with a service-unavailable error.
|
||||
client
|
||||
.send_stanza(make_error(
|
||||
iq.from.unwrap(),
|
||||
iq.id,
|
||||
ErrorType::Cancel,
|
||||
DefinedCondition::ServiceUnavailable,
|
||||
"No handler defined for this kind of iq.",
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
} else if stanza.is("message", "jabber:client") {
|
||||
let message = Message::try_from(stanza).unwrap();
|
||||
let from = message.from.clone().unwrap();
|
||||
if let Some(body) = message.get_best_body(vec!["en"]) {
|
||||
if body.0 == "die" {
|
||||
println!("Secret die command triggered by {}", from);
|
||||
wait_for_stream_end = true;
|
||||
client.send_end().await.unwrap();
|
||||
Stanza::Message(message) => {
|
||||
let from = message.from.clone().unwrap();
|
||||
if let Some(body) = message.get_best_body(vec!["en"]) {
|
||||
if body.0 == "die" {
|
||||
println!("Secret die command triggered by {}", from);
|
||||
wait_for_stream_end = true;
|
||||
client.send_end().await.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
for child in message.payloads {
|
||||
if child.is("event", ns::PUBSUB_EVENT) {
|
||||
let event = PubSubEvent::try_from(child).unwrap();
|
||||
if let PubSubEvent::PublishedItems { node, items } = event {
|
||||
if node.0 == ns::AVATAR_METADATA {
|
||||
for item in items.into_iter() {
|
||||
let payload = item.payload.clone().unwrap();
|
||||
if payload.is("metadata", ns::AVATAR_METADATA) {
|
||||
// TODO: do something with these metadata.
|
||||
let _metadata =
|
||||
AvatarMetadata::try_from(payload).unwrap();
|
||||
println!(
|
||||
"[1m{}[0m has published an avatar, downloading...",
|
||||
from.clone()
|
||||
);
|
||||
let iq = download_avatar(from.clone());
|
||||
client.send_stanza(iq.into()).await.unwrap();
|
||||
for child in message.payloads {
|
||||
if child.is("event", ns::PUBSUB_EVENT) {
|
||||
let event = PubSubEvent::try_from(child).unwrap();
|
||||
if let PubSubEvent::PublishedItems { node, items } = event {
|
||||
if node.0 == ns::AVATAR_METADATA {
|
||||
for item in items.into_iter() {
|
||||
let payload = item.payload.clone().unwrap();
|
||||
if payload.is("metadata", ns::AVATAR_METADATA) {
|
||||
// TODO: do something with these metadata.
|
||||
let _metadata =
|
||||
AvatarMetadata::try_from(payload).unwrap();
|
||||
println!(
|
||||
"[1m{}[0m has published an avatar, downloading...",
|
||||
from.clone()
|
||||
);
|
||||
let iq = download_avatar(from.clone());
|
||||
client.send_stanza(iq.into()).await.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if stanza.is("presence", "jabber:client") {
|
||||
// Nothing to do here.
|
||||
()
|
||||
} else {
|
||||
panic!("Unknown stanza: {}", String::from(&stanza));
|
||||
Stanza::Presence(_) => (),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -164,10 +169,9 @@ fn make_error(
|
|||
type_: ErrorType,
|
||||
condition: DefinedCondition,
|
||||
text: &str,
|
||||
) -> Element {
|
||||
) -> Iq {
|
||||
let error = StanzaError::new(type_, condition, "en", text);
|
||||
let iq = Iq::from_error(id, error).with_to(to);
|
||||
iq.into()
|
||||
Iq::from_error(id, error).with_to(to)
|
||||
}
|
||||
|
||||
fn make_disco() -> DiscoInfoResult {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use futures::stream::StreamExt;
|
||||
use minidom::Element;
|
||||
use std::env::args;
|
||||
use std::process::exit;
|
||||
use std::str::FromStr;
|
||||
|
|
@ -40,7 +39,7 @@ async fn main() {
|
|||
println!("Online at {}", jid);
|
||||
|
||||
let presence = make_presence();
|
||||
client.send_stanza(presence).await.unwrap();
|
||||
client.send_stanza(presence.into()).await.unwrap();
|
||||
} else if let Some(message) = event
|
||||
.into_stanza()
|
||||
.and_then(|stanza| Message::try_from(stanza).ok())
|
||||
|
|
@ -55,7 +54,7 @@ async fn main() {
|
|||
if message.type_ != MessageType::Error {
|
||||
// This is a message we'll echo
|
||||
let reply = make_reply(from.clone(), &body.0);
|
||||
client.send_stanza(reply).await.unwrap();
|
||||
client.send_stanza(reply.into()).await.unwrap();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
@ -69,18 +68,18 @@ async fn main() {
|
|||
}
|
||||
|
||||
// Construct a <presence/>
|
||||
fn make_presence() -> Element {
|
||||
fn make_presence() -> Presence {
|
||||
let mut presence = Presence::new(PresenceType::None);
|
||||
presence.show = Some(PresenceShow::Chat);
|
||||
presence
|
||||
.statuses
|
||||
.insert(String::from("en"), String::from("Echoing messages."));
|
||||
presence.into()
|
||||
presence
|
||||
}
|
||||
|
||||
// Construct a chat <message/>
|
||||
fn make_reply(to: Jid, body: &str) -> Element {
|
||||
fn make_reply(to: Jid, body: &str) -> Message {
|
||||
let mut message = Message::new(Some(to));
|
||||
message.bodies.insert(String::new(), Body(body.to_owned()));
|
||||
message.into()
|
||||
message
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use futures::stream::StreamExt;
|
||||
use minidom::Element;
|
||||
use std::env::args;
|
||||
use std::process::exit;
|
||||
use std::str::FromStr;
|
||||
|
|
@ -45,7 +44,7 @@ async fn main() {
|
|||
Jid::from_str("test@component.linkmauve.fr/coucou").unwrap(),
|
||||
Jid::from_str("linkmauve@linkmauve.fr").unwrap(),
|
||||
);
|
||||
component.send_stanza(presence).await.unwrap();
|
||||
component.send_stanza(presence.into()).await.unwrap();
|
||||
|
||||
// Main loop, processes events
|
||||
loop {
|
||||
|
|
@ -56,7 +55,7 @@ async fn main() {
|
|||
(Some(from), Some(body)) => {
|
||||
if message.type_ != MessageType::Error {
|
||||
let reply = make_reply(from, &body.0);
|
||||
component.send_stanza(reply).await.unwrap();
|
||||
component.send_stanza(reply.into()).await.unwrap();
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
|
|
@ -69,7 +68,7 @@ async fn main() {
|
|||
}
|
||||
|
||||
// Construct a <presence/>
|
||||
fn make_presence(from: Jid, to: Jid) -> Element {
|
||||
fn make_presence(from: Jid, to: Jid) -> Presence {
|
||||
let mut presence = Presence::new(PresenceType::None);
|
||||
presence.from = Some(from);
|
||||
presence.to = Some(to);
|
||||
|
|
@ -77,12 +76,12 @@ fn make_presence(from: Jid, to: Jid) -> Element {
|
|||
presence
|
||||
.statuses
|
||||
.insert(String::from("en"), String::from("Echoing messages."));
|
||||
presence.into()
|
||||
presence
|
||||
}
|
||||
|
||||
// Construct a chat <message/>
|
||||
fn make_reply(to: Jid, body: &str) -> Element {
|
||||
fn make_reply(to: Jid, body: &str) -> Message {
|
||||
let mut message = Message::new(Some(to));
|
||||
message.bodies.insert(String::new(), Body(body.to_owned()));
|
||||
message.into()
|
||||
message
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use futures::{SinkExt, StreamExt};
|
||||
use tokio::{self, io, net::TcpSocket};
|
||||
use tokio_util::codec::Framed;
|
||||
|
||||
use tokio_xmpp::proto::XmppCodec;
|
||||
use tokio_xmpp::parsers::stream_features::StreamFeatures;
|
||||
use tokio_xmpp::xmlstream::{accept_stream, StreamHeader};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), io::Error> {
|
||||
|
|
@ -16,16 +16,22 @@ async fn main() -> Result<(), io::Error> {
|
|||
// Main loop, accepts incoming connections
|
||||
loop {
|
||||
let (stream, _addr) = listener.accept().await?;
|
||||
|
||||
// Use the `XMPPCodec` to encode and decode frames
|
||||
let mut framed = Framed::new(stream, XmppCodec::new());
|
||||
let stream = accept_stream(
|
||||
tokio::io::BufStream::new(stream),
|
||||
tokio_xmpp::parsers::ns::DEFAULT_NS,
|
||||
)
|
||||
.await?;
|
||||
let stream = stream.send_header(StreamHeader::default()).await?;
|
||||
let mut stream = stream
|
||||
.send_features::<minidom::Element>(&StreamFeatures::default())
|
||||
.await?;
|
||||
|
||||
tokio::spawn(async move {
|
||||
while let Some(packet) = framed.next().await {
|
||||
while let Some(packet) = stream.next().await {
|
||||
match packet {
|
||||
Ok(packet) => {
|
||||
println!("Received packet: {:?}", packet);
|
||||
framed.send(packet).await.unwrap();
|
||||
stream.send(&packet).await.unwrap();
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error: {:?}", e);
|
||||
|
|
|
|||
Loading…
Reference in a new issue