Skip to content

Commit d95838b

Browse files
Fix ejabberd s2s
1 parent 9d17d7e commit d95838b

File tree

2 files changed

+52
-37
lines changed

2 files changed

+52
-37
lines changed

src/main.rs

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,10 @@ impl Config {
103103
}
104104
}
105105

106-
fn to_str(buf: &[u8]) -> &str {
107-
std::str::from_utf8(buf).unwrap_or("[invalid utf-8]")
106+
fn to_str(buf: &[u8]) -> std::borrow::Cow<'_, str> {
107+
//&str {
108+
//std::str::from_utf8(buf).unwrap_or("[invalid utf-8]")
109+
String::from_utf8_lossy(buf)
108110
}
109111

110112
async fn handle_connection(mut stream: tokio::net::TcpStream, client_addr: SocketAddr, local_addr: SocketAddr, config: CloneableConfig) -> Result<()> {
@@ -148,7 +150,11 @@ async fn handle_connection(mut stream: tokio::net::TcpStream, client_addr: Socke
148150
if !direct_tls {
149151
let mut stream_open = Vec::new();
150152

151-
while let Ok(n) = stream.read(in_filter.current_buf()).await {
153+
let (in_rd, mut in_wr) = stream.split();
154+
// we naively read 1 byte at a time, which buffering significantly speeds up
155+
let mut in_rd = tokio::io::BufReader::with_capacity(IN_BUFFER_SIZE, in_rd);
156+
157+
while let Ok(n) = in_rd.read(in_filter.current_buf()).await {
152158
if n == 0 {
153159
bail!("stream ended before open");
154160
}
@@ -160,32 +166,36 @@ async fn handle_connection(mut stream: tokio::net::TcpStream, client_addr: Socke
160166
continue;
161167
} else if buf.starts_with(b"<stream:stream ") {
162168
debug!("> {} '{}'", client_addr, to_str(&stream_open));
163-
stream.write_all(&stream_open).await?;
169+
in_wr.write_all(&stream_open).await?;
164170
stream_open.clear();
165171

166172
// gajim seems to REQUIRE an id here...
167173
let buf = if buf.contains_seq(b"id=") {
168-
buf.replace(b" id='", b" id='xmpp-proxy")
169-
.replace(br#" id=""#, br#" id="xmpp-proxy"#)
170-
.replace(b" to=", br#" bla toblala="#)
171-
.replace(b" from=", b" to=")
172-
.replace(br#" bla toblala="#, br#" from="#)
174+
buf.replace_first(b" id='", b" id='xmpp-proxy")
175+
.replace_first(br#" id=""#, br#" id="xmpp-proxy"#)
176+
.replace_first(b" to=", br#" bla toblala="#)
177+
.replace_first(b" from=", b" to=")
178+
.replace_first(br#" bla toblala="#, br#" from="#)
173179
} else {
174-
buf.replace(b" to=", br#" bla toblala="#)
175-
.replace(b" from=", b" to=")
176-
.replace(br#" bla toblala="#, br#" id='xmpp-proxy' from="#)
180+
buf.replace_first(b" to=", br#" bla toblala="#)
181+
.replace_first(b" from=", b" to=")
182+
.replace_first(br#" bla toblala="#, br#" id='xmpp-proxy' from="#)
177183
};
178184

179185
debug!("> {} '{}'", client_addr, to_str(&buf));
180-
stream.write_all(&buf).await?;
181-
182-
stream
183-
.write_all(br###"<features xmlns="http://etherx.jabber.org/streams"><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"><required/></starttls></features>"###)
184-
.await?;
185-
stream.flush().await?;
186+
in_wr.write_all(&buf).await?;
187+
188+
// ejabberd never sends <starttls/> with the first, only the second?
189+
//let buf = br###"<features xmlns="http://etherx.jabber.org/streams"><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"><required/></starttls></features>"###;
190+
let buf = br###"<stream:features><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"><required/></starttls></stream:features>"###;
191+
debug!("> {} '{}'", client_addr, to_str(buf));
192+
in_wr.write_all(buf).await?;
193+
in_wr.flush().await?;
186194
} else if buf.starts_with(b"<starttls ") {
187-
stream.write_all(br###"<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls" />"###).await?;
188-
stream.flush().await?;
195+
let buf = br###"<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls" />"###;
196+
debug!("> {} '{}'", client_addr, to_str(buf));
197+
in_wr.write_all(buf).await?;
198+
in_wr.flush().await?;
189199
break;
190200
} else {
191201
bail!("bad pre-tls stanza: {}", to_str(&buf));
@@ -197,7 +207,6 @@ async fn handle_connection(mut stream: tokio::net::TcpStream, client_addr: Socke
197207
let stream = config.acceptor.accept(stream).await?;
198208

199209
let (in_rd, mut in_wr) = tokio::io::split(stream);
200-
201210
// we naively read 1 byte at a time, which buffering significantly speeds up
202211
let mut in_rd = tokio::io::BufReader::with_capacity(IN_BUFFER_SIZE, in_rd);
203212

@@ -396,7 +405,7 @@ impl StanzaFilter {
396405
//println!("b: '{}', cnt: {}, tag_cnt: {}, self.buf.len(): {}", b as char, self.cnt, self.tag_cnt, self.buf.len());
397406
self.cnt += 1;
398407
if self.cnt == self.buf_size {
399-
bail!("stanza too big");
408+
bail!("stanza too big: {}", to_str(&self.buf));
400409
}
401410
Ok(None)
402411
}

src/slicesubsequence.rs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use anyhow::{anyhow, Result};
33
pub trait SliceSubsequence<T> {
44
fn trim_start(&self, needle: &[T]) -> &[T];
55
fn first_index_of(&self, needle: &[T]) -> Result<usize>;
6-
fn replace(self, needle: &[T], replacement: &[T]) -> Vec<T>;
6+
fn replace_first(self, needle: &[T], replacement: &[T]) -> Vec<T>;
77

88
fn contains_seq(&self, needle: &[T]) -> bool {
99
self.first_index_of(needle).is_ok()
@@ -36,8 +36,8 @@ impl<T: PartialEq + Clone> SliceSubsequence<T> for &[T] {
3636
Err(anyhow!("not found"))
3737
}
3838

39-
fn replace(self, needle: &[T], replacement: &[T]) -> Vec<T> {
40-
self.to_vec().replace(needle, replacement)
39+
fn replace_first(self, needle: &[T], replacement: &[T]) -> Vec<T> {
40+
self.to_vec().replace_first(needle, replacement)
4141
}
4242
}
4343

@@ -50,11 +50,17 @@ impl<T: PartialEq + Clone> SliceSubsequence<T> for Vec<T> {
5050
return (self.as_slice()).first_index_of(needle);
5151
}
5252

53-
fn replace(mut self, needle: &[T], replacement: &[T]) -> Vec<T> {
54-
while let Ok(idx) = self.first_index_of(needle) {
55-
self.splice(idx..(idx + needle.len()), replacement.iter().cloned());
53+
fn replace_first(self, needle: &[T], replacement: &[T]) -> Vec<T> {
54+
if let Ok(idx) = self.first_index_of(needle) {
55+
let second = &self[(idx + needle.len())..];
56+
let mut ret = Vec::with_capacity(idx + replacement.len() + second.len());
57+
ret.extend_from_slice(&self[..idx]);
58+
ret.extend_from_slice(replacement);
59+
ret.extend_from_slice(second);
60+
ret
61+
} else {
62+
self
5663
}
57-
self
5864
}
5965
}
6066

@@ -74,23 +80,23 @@ mod tests {
7480
assert_eq!(buf, b"bla");
7581
}
7682
#[test]
77-
fn replace() {
78-
let buf = b"bla to='tsnhaou' bla2".replace(b" to=", b" from=");
83+
fn replace_first() {
84+
let buf = b"bla to='tsnhaou' bla2".replace_first(b" to=", b" from=");
7985
assert_eq!(buf, b"bla from='tsnhaou' bla2");
8086

81-
let buf = buf.replace(b" from=", b" to=");
87+
let buf = buf.replace_first(b" from=", b" to=");
8288
assert_eq!(buf, b"bla to='tsnhaou' bla2");
8389

84-
let buf = buf.replace(b" to=", b" from=");
90+
let buf = buf.replace_first(b" to=", b" from=");
8591
assert_eq!(buf, b"bla from='tsnhaou' bla2");
8692

87-
let buf = b"bla to='tsnhaou' bla2".replace(b"bla", b"boo");
88-
assert_eq!(buf, b"boo to='tsnhaou' boo2");
93+
let buf = b"bla to='tsnhaou' bla2".replace_first(b"bla", b"boo");
94+
assert_eq!(buf, b"boo to='tsnhaou' bla2");
8995

90-
let buf = buf.replace(b"boo", b"bla");
96+
let buf = buf.replace_first(b"boo", b"bla");
9197
assert_eq!(buf, b"bla to='tsnhaou' bla2");
9298

93-
let buf = buf.replace(b" bla2", b"");
99+
let buf = buf.replace_first(b" bla2", b"");
94100
assert_eq!(buf, b"bla to='tsnhaou'");
95101
}
96102
}

0 commit comments

Comments
 (0)