Merge pull request #59731 from ajs124/ejabberd_test
ejabberd: refactor module, add test
This commit is contained in:
commit
77fb90d27e
|
@ -197,6 +197,11 @@
|
||||||
github = "aij";
|
github = "aij";
|
||||||
name = "Ivan Jager";
|
name = "Ivan Jager";
|
||||||
};
|
};
|
||||||
|
ajs124 = {
|
||||||
|
email = "nix@ajs124.de";
|
||||||
|
github = "ajs124";
|
||||||
|
name = "Andreas Schrägle";
|
||||||
|
};
|
||||||
ajgrf = {
|
ajgrf = {
|
||||||
email = "a@ajgrf.com";
|
email = "a@ajgrf.com";
|
||||||
github = "ajgrf";
|
github = "ajgrf";
|
||||||
|
|
|
@ -11,7 +11,7 @@ let
|
||||||
${cfg.ctlConfig}
|
${cfg.ctlConfig}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
ectl = ''${cfg.package}/bin/ejabberdctl ${if cfg.configFile == null then "" else "--config ${cfg.configFile}"} --ctl-config "${ctlcfg}" --spool "${cfg.spoolDir}" --logs "${cfg.logsDir}"'';
|
ectl = ''${cfg.package}/bin/ejabberdctl ${optionalString (cfg.configFile != null) "--config ${cfg.configFile}"} --ctl-config "${ctlcfg}" --spool "${cfg.spoolDir}" --logs "${cfg.logsDir}"'';
|
||||||
|
|
||||||
dumps = lib.escapeShellArgs cfg.loadDumps;
|
dumps = lib.escapeShellArgs cfg.loadDumps;
|
||||||
|
|
||||||
|
@ -111,28 +111,17 @@ in {
|
||||||
description = "ejabberd server";
|
description = "ejabberd server";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
path = [ pkgs.findutils pkgs.coreutils pkgs.runit ] ++ lib.optional cfg.imagemagick pkgs.imagemagick;
|
path = [ pkgs.findutils pkgs.coreutils ] ++ lib.optional cfg.imagemagick pkgs.imagemagick;
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = ''${ectl} foreground'';
|
|
||||||
# FIXME: runit is used for `chpst` -- can we get rid of this?
|
|
||||||
ExecStop = ''${pkgs.runit}/bin/chpst -u "${cfg.user}:${cfg.group}" ${ectl} stop'';
|
|
||||||
ExecReload = ''${pkgs.runit}/bin/chpst -u "${cfg.user}:${cfg.group}" ${ectl} reload_config'';
|
|
||||||
User = cfg.user;
|
User = cfg.user;
|
||||||
Group = cfg.group;
|
Group = cfg.group;
|
||||||
PermissionsStartOnly = true;
|
ExecStart = "${ectl} foreground";
|
||||||
|
ExecStop = "${ectl} stop";
|
||||||
|
ExecReload = "${ectl} reload_config";
|
||||||
};
|
};
|
||||||
|
|
||||||
preStart = ''
|
preStart = ''
|
||||||
mkdir -p -m750 "${cfg.logsDir}"
|
|
||||||
chown "${cfg.user}:${cfg.group}" "${cfg.logsDir}"
|
|
||||||
|
|
||||||
mkdir -p -m750 "/var/lock/ejabberdctl"
|
|
||||||
chown "${cfg.user}:${cfg.group}" "/var/lock/ejabberdctl"
|
|
||||||
|
|
||||||
mkdir -p -m750 "${cfg.spoolDir}"
|
|
||||||
chown -R "${cfg.user}:${cfg.group}" "${cfg.spoolDir}"
|
|
||||||
|
|
||||||
if [ -z "$(ls -A '${cfg.spoolDir}')" ]; then
|
if [ -z "$(ls -A '${cfg.spoolDir}')" ]; then
|
||||||
touch "${cfg.spoolDir}/.firstRun"
|
touch "${cfg.spoolDir}/.firstRun"
|
||||||
fi
|
fi
|
||||||
|
@ -149,13 +138,18 @@ in {
|
||||||
for src in ${dumps}; do
|
for src in ${dumps}; do
|
||||||
find "$src" -type f | while read dump; do
|
find "$src" -type f | while read dump; do
|
||||||
echo "Loading configuration dump at $dump"
|
echo "Loading configuration dump at $dump"
|
||||||
chpst -u "${cfg.user}:${cfg.group}" ${ectl} load "$dump"
|
${ectl} load "$dump"
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d '${cfg.logsDir}' 0750 ${cfg.user} ${cfg.group} -"
|
||||||
|
"d '${cfg.spoolDir}' 0700 ${cfg.user} ${cfg.group} -"
|
||||||
|
];
|
||||||
|
|
||||||
security.pam.services.ejabberd = {};
|
security.pam.services.ejabberd = {};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -72,6 +72,7 @@ in
|
||||||
#ec2-config = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-config or {};
|
#ec2-config = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-config or {};
|
||||||
ec2-nixops = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-nixops or {};
|
ec2-nixops = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-nixops or {};
|
||||||
ecryptfs = handleTest ./ecryptfs.nix {};
|
ecryptfs = handleTest ./ecryptfs.nix {};
|
||||||
|
ejabberd = handleTest ./ejabberd.nix {};
|
||||||
elk = handleTestOn ["x86_64-linux"] ./elk.nix {};
|
elk = handleTestOn ["x86_64-linux"] ./elk.nix {};
|
||||||
env = handleTest ./env.nix {};
|
env = handleTest ./env.nix {};
|
||||||
etcd = handleTestOn ["x86_64-linux"] ./etcd.nix {};
|
etcd = handleTestOn ["x86_64-linux"] ./etcd.nix {};
|
||||||
|
|
|
@ -0,0 +1,262 @@
|
||||||
|
import ./make-test.nix ({ pkgs, ... }: {
|
||||||
|
name = "ejabberd";
|
||||||
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
|
maintainers = [ ajs124 ];
|
||||||
|
};
|
||||||
|
nodes = {
|
||||||
|
client = { nodes, pkgs, ... }: {
|
||||||
|
environment.systemPackages = [
|
||||||
|
(pkgs.callPackage ./xmpp-sendmessage.nix { connectTo = nodes.server.config.networking.primaryIPAddress; })
|
||||||
|
];
|
||||||
|
};
|
||||||
|
server = { config, pkgs, ... }: {
|
||||||
|
networking.extraHosts = ''
|
||||||
|
${config.networking.primaryIPAddress} example.com
|
||||||
|
'';
|
||||||
|
|
||||||
|
services.ejabberd = {
|
||||||
|
enable = true;
|
||||||
|
configFile = "/etc/ejabberd.yml";
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.etc."ejabberd.yml" = {
|
||||||
|
user = "ejabberd";
|
||||||
|
mode = "0600";
|
||||||
|
text = ''
|
||||||
|
loglevel: 3
|
||||||
|
|
||||||
|
hosts:
|
||||||
|
- "example.com"
|
||||||
|
|
||||||
|
listen:
|
||||||
|
-
|
||||||
|
port: 5222
|
||||||
|
module: ejabberd_c2s
|
||||||
|
zlib: false
|
||||||
|
max_stanza_size: 65536
|
||||||
|
shaper: c2s_shaper
|
||||||
|
access: c2s
|
||||||
|
-
|
||||||
|
port: 5269
|
||||||
|
ip: "::"
|
||||||
|
module: ejabberd_s2s_in
|
||||||
|
-
|
||||||
|
port: 5347
|
||||||
|
ip: "127.0.0.1"
|
||||||
|
module: ejabberd_service
|
||||||
|
access: local
|
||||||
|
shaper_rule: fast
|
||||||
|
ip: "127.0.0.1"
|
||||||
|
|
||||||
|
## Disabling digest-md5 SASL authentication. digest-md5 requires plain-text
|
||||||
|
## password storage (see auth_password_format option).
|
||||||
|
disable_sasl_mechanisms: "digest-md5"
|
||||||
|
|
||||||
|
## Outgoing S2S options
|
||||||
|
## Preferred address families (which to try first) and connect timeout
|
||||||
|
## in seconds.
|
||||||
|
outgoing_s2s_families:
|
||||||
|
- ipv4
|
||||||
|
- ipv6
|
||||||
|
|
||||||
|
## auth_method: Method used to authenticate the users.
|
||||||
|
## The default method is the internal.
|
||||||
|
## If you want to use a different method,
|
||||||
|
## comment this line and enable the correct ones.
|
||||||
|
auth_method: internal
|
||||||
|
|
||||||
|
## Store the plain passwords or hashed for SCRAM:
|
||||||
|
## auth_password_format: plain
|
||||||
|
auth_password_format: scram
|
||||||
|
|
||||||
|
###' TRAFFIC SHAPERS
|
||||||
|
shaper:
|
||||||
|
# in B/s
|
||||||
|
normal: 1000000
|
||||||
|
fast: 50000000
|
||||||
|
|
||||||
|
## This option specifies the maximum number of elements in the queue
|
||||||
|
## of the FSM. Refer to the documentation for details.
|
||||||
|
max_fsm_queue: 1000
|
||||||
|
|
||||||
|
###' ACCESS CONTROL LISTS
|
||||||
|
acl:
|
||||||
|
## The 'admin' ACL grants administrative privileges to XMPP accounts.
|
||||||
|
## You can put here as many accounts as you want.
|
||||||
|
admin:
|
||||||
|
user:
|
||||||
|
- "root": "example.com"
|
||||||
|
|
||||||
|
## Local users: don't modify this.
|
||||||
|
local:
|
||||||
|
user_regexp: ""
|
||||||
|
|
||||||
|
## Loopback network
|
||||||
|
loopback:
|
||||||
|
ip:
|
||||||
|
- "127.0.0.0/8"
|
||||||
|
- "::1/128"
|
||||||
|
- "::FFFF:127.0.0.1/128"
|
||||||
|
|
||||||
|
###' SHAPER RULES
|
||||||
|
shaper_rules:
|
||||||
|
## Maximum number of simultaneous sessions allowed for a single user:
|
||||||
|
max_user_sessions: 10
|
||||||
|
## Maximum number of offline messages that users can have:
|
||||||
|
max_user_offline_messages:
|
||||||
|
- 5000: admin
|
||||||
|
- 1024
|
||||||
|
## For C2S connections, all users except admins use the "normal" shaper
|
||||||
|
c2s_shaper:
|
||||||
|
- none: admin
|
||||||
|
- normal
|
||||||
|
## All S2S connections use the "fast" shaper
|
||||||
|
s2s_shaper: fast
|
||||||
|
|
||||||
|
###' ACCESS RULES
|
||||||
|
access_rules:
|
||||||
|
## This rule allows access only for local users:
|
||||||
|
local:
|
||||||
|
- allow: local
|
||||||
|
## Only non-blocked users can use c2s connections:
|
||||||
|
c2s:
|
||||||
|
- deny: blocked
|
||||||
|
- allow
|
||||||
|
## Only admins can send announcement messages:
|
||||||
|
announce:
|
||||||
|
- allow: admin
|
||||||
|
## Only admins can use the configuration interface:
|
||||||
|
configure:
|
||||||
|
- allow: admin
|
||||||
|
## Only accounts of the local ejabberd server can create rooms:
|
||||||
|
muc_create:
|
||||||
|
- allow: local
|
||||||
|
## Only accounts on the local ejabberd server can create Pubsub nodes:
|
||||||
|
pubsub_createnode:
|
||||||
|
- allow: local
|
||||||
|
## In-band registration allows registration of any possible username.
|
||||||
|
## To disable in-band registration, replace 'allow' with 'deny'.
|
||||||
|
register:
|
||||||
|
- allow
|
||||||
|
## Only allow to register from localhost
|
||||||
|
trusted_network:
|
||||||
|
- allow: loopback
|
||||||
|
|
||||||
|
## ===============
|
||||||
|
## API PERMISSIONS
|
||||||
|
## ===============
|
||||||
|
##
|
||||||
|
## This section allows you to define who and using what method
|
||||||
|
## can execute commands offered by ejabberd.
|
||||||
|
##
|
||||||
|
## By default "console commands" section allow executing all commands
|
||||||
|
## issued using ejabberdctl command, and "admin access" section allows
|
||||||
|
## users in admin acl that connect from 127.0.0.1 to execute all
|
||||||
|
## commands except start and stop with any available access method
|
||||||
|
## (ejabberdctl, http-api, xmlrpc depending what is enabled on server).
|
||||||
|
##
|
||||||
|
## If you remove "console commands" there will be one added by
|
||||||
|
## default allowing executing all commands, but if you just change
|
||||||
|
## permissions in it, version from config file will be used instead
|
||||||
|
## of default one.
|
||||||
|
##
|
||||||
|
api_permissions:
|
||||||
|
"console commands":
|
||||||
|
from:
|
||||||
|
- ejabberd_ctl
|
||||||
|
who: all
|
||||||
|
what: "*"
|
||||||
|
|
||||||
|
language: "en"
|
||||||
|
|
||||||
|
###' MODULES
|
||||||
|
## Modules enabled in all ejabberd virtual hosts.
|
||||||
|
modules:
|
||||||
|
mod_adhoc: {}
|
||||||
|
mod_announce: # recommends mod_adhoc
|
||||||
|
access: announce
|
||||||
|
mod_blocking: {} # requires mod_privacy
|
||||||
|
mod_caps: {}
|
||||||
|
mod_carboncopy: {}
|
||||||
|
mod_client_state: {}
|
||||||
|
mod_configure: {} # requires mod_adhoc
|
||||||
|
## mod_delegation: {} # for xep0356
|
||||||
|
mod_echo: {}
|
||||||
|
#mod_irc:
|
||||||
|
# host: "irc.@HOST@"
|
||||||
|
# default_encoding: "utf-8"
|
||||||
|
## mod_bosh: {}
|
||||||
|
## mod_http_fileserver:
|
||||||
|
## docroot: "/var/www"
|
||||||
|
## accesslog: "/var/log/ejabberd/access.log"
|
||||||
|
#mod_http_upload:
|
||||||
|
# thumbnail: false # otherwise needs the identify command from ImageMagick installed
|
||||||
|
# put_url: "https://@HOST@:5444"
|
||||||
|
## # docroot: "@HOME@/upload"
|
||||||
|
#mod_http_upload_quota:
|
||||||
|
# max_days: 14
|
||||||
|
mod_last: {}
|
||||||
|
## XEP-0313: Message Archive Management
|
||||||
|
## You might want to setup a SQL backend for MAM because the mnesia database is
|
||||||
|
## limited to 2GB which might be exceeded on large servers
|
||||||
|
mod_mam: {}
|
||||||
|
mod_muc:
|
||||||
|
host: "muc.@HOST@"
|
||||||
|
access:
|
||||||
|
- allow
|
||||||
|
access_admin:
|
||||||
|
- allow: admin
|
||||||
|
access_create: muc_create
|
||||||
|
access_persistent: muc_create
|
||||||
|
mod_muc_admin: {}
|
||||||
|
mod_muc_log: {}
|
||||||
|
mod_offline:
|
||||||
|
access_max_user_messages: max_user_offline_messages
|
||||||
|
mod_ping: {}
|
||||||
|
## mod_pres_counter:
|
||||||
|
## count: 5
|
||||||
|
## interval: 60
|
||||||
|
mod_privacy: {}
|
||||||
|
mod_private: {}
|
||||||
|
mod_roster:
|
||||||
|
versioning: true
|
||||||
|
mod_shared_roster: {}
|
||||||
|
mod_stats: {}
|
||||||
|
mod_time: {}
|
||||||
|
mod_vcard:
|
||||||
|
search: false
|
||||||
|
mod_vcard_xupdate: {}
|
||||||
|
## Convert all avatars posted by Android clients from WebP to JPEG
|
||||||
|
mod_avatar: {}
|
||||||
|
# convert:
|
||||||
|
# webp: jpeg
|
||||||
|
mod_version: {}
|
||||||
|
mod_stream_mgmt: {}
|
||||||
|
## The module for S2S dialback (XEP-0220). Please note that you cannot
|
||||||
|
## rely solely on dialback if you want to federate with other servers,
|
||||||
|
## because a lot of servers have dialback disabled and instead rely on
|
||||||
|
## PKIX authentication. Make sure you have proper certificates installed
|
||||||
|
## and check your accessibility at https://check.messaging.one/
|
||||||
|
mod_s2s_dialback: {}
|
||||||
|
mod_pubsub:
|
||||||
|
plugins:
|
||||||
|
- "pep"
|
||||||
|
mod_push: {}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.enable = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testScript = { nodes, ... }: ''
|
||||||
|
$server->waitForUnit('ejabberd.service');
|
||||||
|
$server->succeed('su ejabberd -s $(which ejabberdctl) status|grep started') =~ /ejabberd is running/;
|
||||||
|
$server->succeed('su ejabberd -s $(which ejabberdctl) register azurediamond example.com hunter2');
|
||||||
|
$server->succeed('su ejabberd -s $(which ejabberdctl) register cthon98 example.com nothunter2');
|
||||||
|
$server->fail('su ejabberd -s $(which ejabberdctl) register asdf wrong.domain');
|
||||||
|
$client->succeed('send-message');
|
||||||
|
$server->succeed('su ejabberd -s $(which ejabberdctl) unregister cthon98 example.com');
|
||||||
|
$server->succeed('su ejabberd -s $(which ejabberdctl) unregister azurediamond example.com');
|
||||||
|
'';
|
||||||
|
})
|
|
@ -9,70 +9,30 @@ import ./make-test.nix {
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
storage = "sql"
|
storage = "sql"
|
||||||
'';
|
'';
|
||||||
|
virtualHosts.test = {
|
||||||
|
domain = "example.com";
|
||||||
|
enabled = true;
|
||||||
};
|
};
|
||||||
environment.systemPackages = let
|
};
|
||||||
sendMessage = pkgs.writeScriptBin "send-message" ''
|
environment.systemPackages = [
|
||||||
#!/usr/bin/env python3
|
(pkgs.callPackage ./xmpp-sendmessage.nix {})
|
||||||
# Based on the sleekxmpp send_client example, look there for more details:
|
];
|
||||||
# https://github.com/fritzy/SleekXMPP/blob/develop/examples/send_client.py
|
|
||||||
import sleekxmpp
|
|
||||||
|
|
||||||
class SendMsgBot(sleekxmpp.ClientXMPP):
|
|
||||||
"""
|
|
||||||
A basic SleekXMPP bot that will log in, send a message,
|
|
||||||
and then log out.
|
|
||||||
"""
|
|
||||||
def __init__(self, jid, password, recipient, message):
|
|
||||||
sleekxmpp.ClientXMPP.__init__(self, jid, password)
|
|
||||||
|
|
||||||
self.recipient = recipient
|
|
||||||
self.msg = message
|
|
||||||
|
|
||||||
self.add_event_handler("session_start", self.start, threaded=True)
|
|
||||||
|
|
||||||
def start(self, event):
|
|
||||||
self.send_presence()
|
|
||||||
self.get_roster()
|
|
||||||
|
|
||||||
self.send_message(mto=self.recipient,
|
|
||||||
mbody=self.msg,
|
|
||||||
mtype='chat')
|
|
||||||
|
|
||||||
self.disconnect(wait=True)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
xmpp = SendMsgBot("test1@localhost", "test1", "test2@localhost", "Hello World!")
|
|
||||||
xmpp.register_plugin('xep_0030') # Service Discovery
|
|
||||||
xmpp.register_plugin('xep_0199') # XMPP Ping
|
|
||||||
|
|
||||||
# TODO: verify certificate
|
|
||||||
# If you want to verify the SSL certificates offered by a server:
|
|
||||||
# xmpp.ca_certs = "path/to/ca/cert"
|
|
||||||
|
|
||||||
if xmpp.connect(('localhost', 5222)):
|
|
||||||
xmpp.process(block=True)
|
|
||||||
else:
|
|
||||||
print("Unable to connect.")
|
|
||||||
sys.exit(1)
|
|
||||||
'';
|
|
||||||
in [ (pkgs.python3.withPackages (ps: [ ps.sleekxmpp ])) sendMessage ];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
$machine->waitForUnit('prosody.service');
|
$machine->waitForUnit('prosody.service');
|
||||||
$machine->succeed('prosodyctl status') =~ /Prosody is running/;
|
$machine->succeed('prosodyctl status') =~ /Prosody is running/;
|
||||||
|
|
||||||
# set password to 'test' (it's asked twice)
|
# set password to 'nothunter2' (it's asked twice)
|
||||||
$machine->succeed('yes test1 | prosodyctl adduser test1@localhost');
|
$machine->succeed('yes nothunter2 | prosodyctl adduser cthon98@example.com');
|
||||||
# set password to 'y'
|
# set password to 'y'
|
||||||
$machine->succeed('yes | prosodyctl adduser test2@localhost');
|
$machine->succeed('yes | prosodyctl adduser azurediamond@example.com');
|
||||||
# correct password to 'test2'
|
# correct password to 'hunter2'
|
||||||
$machine->succeed('yes test2 | prosodyctl passwd test2@localhost');
|
$machine->succeed('yes hunter2 | prosodyctl passwd azurediamond@example.com');
|
||||||
|
|
||||||
$machine->succeed("send-message");
|
$machine->succeed("send-message");
|
||||||
|
|
||||||
$machine->succeed('prosodyctl deluser test1@localhost');
|
$machine->succeed('prosodyctl deluser cthon98@example.com');
|
||||||
$machine->succeed('prosodyctl deluser test2@localhost');
|
$machine->succeed('prosodyctl deluser azurediamond@example.com');
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
{ writeScriptBin, python3, connectTo ? "localhost" }:
|
||||||
|
writeScriptBin "send-message" ''
|
||||||
|
#!${(python3.withPackages (ps: [ ps.sleekxmpp ])).interpreter}
|
||||||
|
# Based on the sleekxmpp send_client example, look there for more details:
|
||||||
|
# https://github.com/fritzy/SleekXMPP/blob/develop/examples/send_client.py
|
||||||
|
import sleekxmpp
|
||||||
|
|
||||||
|
class SendMsgBot(sleekxmpp.ClientXMPP):
|
||||||
|
"""
|
||||||
|
A basic SleekXMPP bot that will log in, send a message,
|
||||||
|
and then log out.
|
||||||
|
"""
|
||||||
|
def __init__(self, jid, password, recipient, message):
|
||||||
|
sleekxmpp.ClientXMPP.__init__(self, jid, password)
|
||||||
|
|
||||||
|
self.recipient = recipient
|
||||||
|
self.msg = message
|
||||||
|
|
||||||
|
self.add_event_handler("session_start", self.start, threaded=True)
|
||||||
|
|
||||||
|
def start(self, event):
|
||||||
|
self.send_presence()
|
||||||
|
self.get_roster()
|
||||||
|
|
||||||
|
self.send_message(mto=self.recipient,
|
||||||
|
mbody=self.msg,
|
||||||
|
mtype='chat')
|
||||||
|
|
||||||
|
self.disconnect(wait=True)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
xmpp = SendMsgBot("cthon98@example.com", "nothunter2", "azurediamond@example.com", "hey, if you type in your pw, it will show as stars")
|
||||||
|
xmpp.register_plugin('xep_0030') # Service Discovery
|
||||||
|
xmpp.register_plugin('xep_0199') # XMPP Ping
|
||||||
|
|
||||||
|
# TODO: verify certificate
|
||||||
|
# If you want to verify the SSL certificates offered by a server:
|
||||||
|
# xmpp.ca_certs = "path/to/ca/cert"
|
||||||
|
|
||||||
|
if xmpp.connect(('${connectTo}', 5222)):
|
||||||
|
xmpp.process(block=True)
|
||||||
|
else:
|
||||||
|
print("Unable to connect.")
|
||||||
|
sys.exit(1)
|
||||||
|
''
|
Loading…
Reference in New Issue