Fix InspIRCd UID and message-tag parsing; add irctest controller
The UID introduction omitted the second user field (insp sends both a real and a displayed user), and the parser didn't strip IRCv3 message-tag prefixes, so tagged PRIVMSGs addressed to a service were dropped. With both fixed a service links to a real insp4 uplink and answers commands. Adds an irctest services controller so this is verified against an isolated, throwaway ircd.
This commit is contained in:
parent
f82ab0c70a
commit
7929f5f9f4
2 changed files with 66 additions and 1 deletions
|
|
@ -32,6 +32,12 @@ impl Protocol for InspIrcd {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse(&mut self, line: &str) -> Vec<NetEvent> {
|
fn parse(&mut self, line: &str) -> Vec<NetEvent> {
|
||||||
|
// Strip an optional IRCv3 message-tag prefix (@k=v;… ) — insp tags PRIVMSGs
|
||||||
|
// with time/msgid, and it sits before the :source.
|
||||||
|
let line = match line.strip_prefix('@') {
|
||||||
|
Some(rest) => rest.splitn(2, ' ').nth(1).unwrap_or(""),
|
||||||
|
None => line,
|
||||||
|
};
|
||||||
let (source, rest) = match line.strip_prefix(':') {
|
let (source, rest) = match line.strip_prefix(':') {
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
let mut it = s.splitn(2, ' ');
|
let mut it = s.splitn(2, ' ');
|
||||||
|
|
@ -76,8 +82,10 @@ impl Protocol for InspIrcd {
|
||||||
let dest = from.clone().unwrap_or_else(|| self.sid.clone());
|
let dest = from.clone().unwrap_or_else(|| self.sid.clone());
|
||||||
vec![self.from_us(format!("PONG {} {}", dest, token))]
|
vec![self.from_us(format!("PONG {} {}", dest, token))]
|
||||||
}
|
}
|
||||||
|
// insp4 UID: uuid nickts nick realhost disphost realuser dispuser ip signonts +modes :gecos
|
||||||
|
// (both a real AND a displayed user field — see m_spanningtree/uid.cpp Builder).
|
||||||
NetAction::IntroduceUser { uid, nick, ident, host, gecos } => vec![self.from_us(format!(
|
NetAction::IntroduceUser { uid, nick, ident, host, gecos } => vec![self.from_us(format!(
|
||||||
"UID {uid} {ts} {nick} {host} {host} {ident} 0.0.0.0 {ts} +ioS :{gecos}",
|
"UID {uid} {ts} {nick} {host} {host} {ident} {ident} 0.0.0.0 {ts} +i :{gecos}",
|
||||||
uid = uid, ts = self.ts, nick = nick, host = host, ident = ident, gecos = gecos
|
uid = uid, ts = self.ts, nick = nick, host = host, ident = ident, gecos = gecos
|
||||||
))],
|
))],
|
||||||
NetAction::Privmsg { from, to, text } => {
|
NetAction::Privmsg { from, to, text } => {
|
||||||
|
|
|
||||||
57
testing/fedserv_services.py
Normal file
57
testing/fedserv_services.py
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
"""irctest controller for fedserv.
|
||||||
|
|
||||||
|
Copy (or symlink) this file into irctest's ``irctest/controllers/`` directory,
|
||||||
|
then run the services tests against an isolated InspIRCd + fedserv:
|
||||||
|
|
||||||
|
FEDSERV_BIN=/path/to/federated-services/target/release/fedserv \\
|
||||||
|
PATH=/path/to/inspircd/run/bin:$PATH \\
|
||||||
|
python -m pytest \\
|
||||||
|
--controller=irctest.controllers.inspircd \\
|
||||||
|
--services-controller=irctest.controllers.fedserv_services \\
|
||||||
|
irctest/server_tests/account_registration.py
|
||||||
|
|
||||||
|
irctest spawns its own ircd + services on random ports, so this never touches a
|
||||||
|
real network. See https://github.com/progval/irctest
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
from typing import Type
|
||||||
|
|
||||||
|
from irctest.basecontrollers import BaseServicesController, DirectoryBasedController
|
||||||
|
|
||||||
|
CONFIG = """\
|
||||||
|
[uplink]
|
||||||
|
host = "{server_hostname}"
|
||||||
|
port = {server_port}
|
||||||
|
password = "password"
|
||||||
|
|
||||||
|
[server]
|
||||||
|
name = "My.Little.Services"
|
||||||
|
sid = "42S"
|
||||||
|
description = "Federated Services"
|
||||||
|
protocol = 1206
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class FedservController(BaseServicesController, DirectoryBasedController):
|
||||||
|
software_name = "fedserv"
|
||||||
|
saslserv = "NickServ"
|
||||||
|
|
||||||
|
def run(self, protocol: str, server_hostname: str, server_port: int) -> None:
|
||||||
|
self.create_config()
|
||||||
|
assert protocol in ("inspircd", "inspircd3"), f"fedserv speaks inspircd, not {protocol}"
|
||||||
|
|
||||||
|
binary = (
|
||||||
|
os.environ.get("FEDSERV_BIN")
|
||||||
|
or shutil.which("fedserv")
|
||||||
|
or "target/release/fedserv"
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.open_file("config.toml") as fd:
|
||||||
|
fd.write(CONFIG.format(server_hostname=server_hostname, server_port=server_port))
|
||||||
|
|
||||||
|
self.proc = self.execute([binary, "config.toml"], cwd=self.directory)
|
||||||
|
|
||||||
|
|
||||||
|
def get_irctest_controller_class() -> Type[FedservController]:
|
||||||
|
return FedservController
|
||||||
Loading…
Add table
Add a link
Reference in a new issue