I need a "Hello world!" example, that demonstrates how to use websocket
s and ejabberd
in bination. So, this is where I am:
ejabberd
installed and runningpsi plus
client under both users and I can send
messages to myselfejabberd
that it supports websockets
Strophe.js
that many people use to
connect to ejabberd
and this is the list of problems:
ejabberd
configuration
(I guess, I installed a fresh version of ejabberd and its
configuration is located in ejabberd.yml
)Apache
server (proxies, rewrites etc. - in many forums
I've seen some examples that involve such manipulations)Javascript
or C++
or Python
code will
match this puzzle, so that I could make a simple
connect
to or send
a messageWell, I spent two days and pletely in vain. Whatever configuration settings I have and whatever code I have, I always get from FF a message:
Firefox can't establish connection to the server
at ws://localhost:5280/http-ws
And, yes, I edited ejabberd.yml
, so that it has these lines:
requests_handlers:
"http-ws/": ejabberd_http_ws
I also edited apache configs, so that I have:
ProxyRequests off
ProxyPass /http-ws/ http://localhost:5280/http-ws/
ProxyPassReverse /http-ws/ http://localhost:5280/http-ws/
RewriteEngine on
RewriteRule http-ws/ http://localhost:5280/http-ws/
Indeed, I restarted both apache and ejabberd. And in my code I have:
var SocketUrl = 'ws://localhost:5280/http-ws'
...other standard stuff
I guess, I tried dozens * dozens of binations, but none of them works. So, I need a step-by-step instruction that will answer to these three questions:
ejabberd
Apache
JavaScript
) should look likeEDIT
This configuration I have now:
1. ejabberd.yml:
...
hosts:
- "localhost"
....
listen:
....
-
port: 5280
ip: "::"
module: ejabberd_http
request_handlers:
"/http-ws": ejabberd_http_ws
web_admin: true
http_poll: true
http_bind: true
....
acl:
admin:
user:
- "admin": "localhost"
access:
configure:
admin: allow
2. apache2.conf
<Directory />
AllowOverride All
Allow From All
</Directory>
<Directory /var/www/site>
AllowOverride All
Allow From All
</Directory>
3. apache2/sites-available/000-default.conf
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/site
<Directory /var/www/site>
Options +Indexes +MultiViews
</Directory>
ProxyRequests off
AddDefaultCharset UTF-8
ProxyPass /http-ws/ http://127.0.0.1:5280/http-ws/
ProxyPassReverse /http-ws/ http://127.0.0.1:5280/http-ws/
RewriteEngine on
RewriteRule /http-ws/http://127.0.0.1:5280/http-ws/
...
And finally this is the code I have:
window.onload = function(){
var SocketUrl = 'ws://localhost:5280/http-ws/';
var connection = null;
function onConnect(status){
if (status == Strophe.Status.CONNECTING) {
alert('Strophe is connecting.');
} else if (status == Strophe.Status.CONNFAIL) {
alert('Strophe failed to connect.');
} else if (status == Strophe.Status.DISCONNECTING) {
alert('Strophe is disconnecting.');
} else if (status == Strophe.Status.DISCONNECTED) {
alert('Strophe is disconnected.');
} else if (status == Strophe.Status.CONNECTED) {
alert('Strophe is connected.');
}
}
var button = document.getElementById("connect");
button.onclick = function(){
connection = new Strophe.Connection(SocketUrl);
var jid = document.getElementById("jid").value;
var pass = document.getElementById("pass").value;
connection.connect(jid, pass, onConnect);
}
}
As a result, while running this example I always get these alerts:
Strophe is connecting
Strophe failed to connect
Strophe is disconnected
And in the console I see this error message:
Firefox can't establish a connection to the server at ws://localhost:5280/http-ws/
Ejabberd log
This is what I have in ejabberd
log:
2015-08-20 12:52:40.558 [error] <0.448.0> CRASH REPORT Process <0.448.0> with 0 neighbours crashed with reason: call to undefined function ejabberd_http_ws:process([], {request,'GET',[<<"http-ws">>],[{nokey,<<>>}],{<<>>,<<>>},undefined,<<"en-US">>,<<>>,{{0,0,0,0,...},...},...})
2015-08-20 12:52:40.559 [error] <0.326.0> Supervisor ejabberd_http_sup had child undefined started with {ejabberd_http,start_link,undefined} at <0.448.0> exit with reason undef in context child_terminated
I think, I should stress this line from the log:
call to undefined function ejabberd_http_ws
I tried to enable this module under module
section in ejabberd.yml
like:
modules:
...
mod_http_ws: {}
which I think should work, if documentation is not lying. However, in this case I'm unable to restart ejabberd
and in its log file I now see this message:
initialization was aborted because a module start failed
Package
This is some information about ejabberd
package that I installed simply with the mand:
$ apt-get -y install ejabberd
So, $ dpkg -s ejabberd
returns
Package: ejabberd
Status: install ok installed
Priority: optional
Section: net
Installed-Size: 6405
Maintainer: Ubuntu Developers <[email protected]>
Architecture: amd64
Version: 14.07-4ubuntu1
Provides: xmpp-server
Depends: adduser, erlang-base (>= 1:15.b) | erlang-abi-17.0, erlang-asn1 (>= 1:17.3-dfsg), erlang-base (>= 1:17.3-dfsg) | erlang-base-hipe (>= 1:17.3-dfsg), erlang-crypto (>= 1:17.3-dfsg), erlang-inets (>= 1:17.3-dfsg), erlang-mnesia (>= 1:17.3-dfsg), erlang-odbc (>= 1:17.3-dfsg), erlang-public-key (>= 1:17.3-dfsg), erlang-ssl (>= 1:17.3-dfsg), erlang-syntax-tools (>= 1:17.3-dfsg), openssl, ucf, debconf (>= 0.5) | debconf-2.0, erlang-lager, erlang-jiffy, erlang-p1-cache-tab, erlang-p1-iconv, erlang-p1-mysql, erlang-p1-pam, erlang-p1-pgsql, erlang-p1-sip, erlang-p1-stringprep, erlang-p1-stun, erlang-p1-tls, erlang-p1-utils, erlang-p1-xml, erlang-p1-yaml, erlang-p1-zlib, erlang-xmlrpc
Remends: ejabberd-contrib
Suggests: libunix-syslog-perl, imagemagick | graphicsmagick-imagemagick- pat
Conflicts: ejabberd-mod-shared-roster-ldap
Conffiles:
/etc/default/ejabberd 49352468a39da545ad13586af05877f9
/etc/ejabberd/inetrc a8de3c20d2ac990c8f319907b340d6a2
/etc/init.d/ejabberd 58aa53c895ae2250e80ea16769db0417
/etc/logrotate.d/ejabberd d2a0a63e544aabfb797f718471c6d173
/etc/ufw/applications.d/ejabberd abc263fcde39ff65e9b5722be81db8ff
Description: distributed, fault-tolerant Jabber/XMPP server written in Erlang
ejabberd is a distributed, fault-tolerant Jabber/XMPP server written in Erlang.
And $ service ejabberd status
returns
● ejabberd.service - LSB: Starts ejabberd jabber server
Loaded: loaded (/etc/init.d/ejabberd)
Active: active (exited) since Thu 2015-08-20 13:32:27 PDT; 12h ago
Docs: man:systemd-sysv-generator(8)
Process: 12701 ExecStop=/etc/init.d/ejabberd stop (code=exited, status=0/SUCCESS)
Process: 13716 ExecStart=/etc/init.d/ejabberd start (code=exited, status=0/SUCCESS)
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 156: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 157: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 158: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 159: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 160: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 161: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 163: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 164: /etc/eja...d
Aug 20 13:32:27 ubuntu ejabberd[13716]: done.
Aug 20 13:32:27 ubuntu systemd[1]: Started LSB: Starts ejabberd jabber server.
I need a "Hello world!" example, that demonstrates how to use websocket
s and ejabberd
in bination. So, this is where I am:
ejabberd
installed and runningpsi plus
client under both users and I can send
messages to myselfejabberd
that it supports websockets
Strophe.js
that many people use to
connect to ejabberd
and this is the list of problems:
ejabberd
configuration
(I guess, I installed a fresh version of ejabberd and its
configuration is located in ejabberd.yml
)Apache
server (proxies, rewrites etc. - in many forums
I've seen some examples that involve such manipulations)Javascript
or C++
or Python
code will
match this puzzle, so that I could make a simple
connect
to or send
a messageWell, I spent two days and pletely in vain. Whatever configuration settings I have and whatever code I have, I always get from FF a message:
Firefox can't establish connection to the server
at ws://localhost:5280/http-ws
And, yes, I edited ejabberd.yml
, so that it has these lines:
requests_handlers:
"http-ws/": ejabberd_http_ws
I also edited apache configs, so that I have:
ProxyRequests off
ProxyPass /http-ws/ http://localhost:5280/http-ws/
ProxyPassReverse /http-ws/ http://localhost:5280/http-ws/
RewriteEngine on
RewriteRule http-ws/ http://localhost:5280/http-ws/
Indeed, I restarted both apache and ejabberd. And in my code I have:
var SocketUrl = 'ws://localhost:5280/http-ws'
...other standard stuff
I guess, I tried dozens * dozens of binations, but none of them works. So, I need a step-by-step instruction that will answer to these three questions:
ejabberd
Apache
JavaScript
) should look likeEDIT
This configuration I have now:
1. ejabberd.yml:
...
hosts:
- "localhost"
....
listen:
....
-
port: 5280
ip: "::"
module: ejabberd_http
request_handlers:
"/http-ws": ejabberd_http_ws
web_admin: true
http_poll: true
http_bind: true
....
acl:
admin:
user:
- "admin": "localhost"
access:
configure:
admin: allow
2. apache2.conf
<Directory />
AllowOverride All
Allow From All
</Directory>
<Directory /var/www/site>
AllowOverride All
Allow From All
</Directory>
3. apache2/sites-available/000-default.conf
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/site
<Directory /var/www/site>
Options +Indexes +MultiViews
</Directory>
ProxyRequests off
AddDefaultCharset UTF-8
ProxyPass /http-ws/ http://127.0.0.1:5280/http-ws/
ProxyPassReverse /http-ws/ http://127.0.0.1:5280/http-ws/
RewriteEngine on
RewriteRule /http-ws/http://127.0.0.1:5280/http-ws/
...
And finally this is the code I have:
window.onload = function(){
var SocketUrl = 'ws://localhost:5280/http-ws/';
var connection = null;
function onConnect(status){
if (status == Strophe.Status.CONNECTING) {
alert('Strophe is connecting.');
} else if (status == Strophe.Status.CONNFAIL) {
alert('Strophe failed to connect.');
} else if (status == Strophe.Status.DISCONNECTING) {
alert('Strophe is disconnecting.');
} else if (status == Strophe.Status.DISCONNECTED) {
alert('Strophe is disconnected.');
} else if (status == Strophe.Status.CONNECTED) {
alert('Strophe is connected.');
}
}
var button = document.getElementById("connect");
button.onclick = function(){
connection = new Strophe.Connection(SocketUrl);
var jid = document.getElementById("jid").value;
var pass = document.getElementById("pass").value;
connection.connect(jid, pass, onConnect);
}
}
As a result, while running this example I always get these alerts:
Strophe is connecting
Strophe failed to connect
Strophe is disconnected
And in the console I see this error message:
Firefox can't establish a connection to the server at ws://localhost:5280/http-ws/
Ejabberd log
This is what I have in ejabberd
log:
2015-08-20 12:52:40.558 [error] <0.448.0> CRASH REPORT Process <0.448.0> with 0 neighbours crashed with reason: call to undefined function ejabberd_http_ws:process([], {request,'GET',[<<"http-ws">>],[{nokey,<<>>}],{<<>>,<<>>},undefined,<<"en-US">>,<<>>,{{0,0,0,0,...},...},...})
2015-08-20 12:52:40.559 [error] <0.326.0> Supervisor ejabberd_http_sup had child undefined started with {ejabberd_http,start_link,undefined} at <0.448.0> exit with reason undef in context child_terminated
I think, I should stress this line from the log:
call to undefined function ejabberd_http_ws
I tried to enable this module under module
section in ejabberd.yml
like:
modules:
...
mod_http_ws: {}
which I think should work, if documentation is not lying. However, in this case I'm unable to restart ejabberd
and in its log file I now see this message:
initialization was aborted because a module start failed
Package
This is some information about ejabberd
package that I installed simply with the mand:
$ apt-get -y install ejabberd
So, $ dpkg -s ejabberd
returns
Package: ejabberd
Status: install ok installed
Priority: optional
Section: net
Installed-Size: 6405
Maintainer: Ubuntu Developers <[email protected]>
Architecture: amd64
Version: 14.07-4ubuntu1
Provides: xmpp-server
Depends: adduser, erlang-base (>= 1:15.b) | erlang-abi-17.0, erlang-asn1 (>= 1:17.3-dfsg), erlang-base (>= 1:17.3-dfsg) | erlang-base-hipe (>= 1:17.3-dfsg), erlang-crypto (>= 1:17.3-dfsg), erlang-inets (>= 1:17.3-dfsg), erlang-mnesia (>= 1:17.3-dfsg), erlang-odbc (>= 1:17.3-dfsg), erlang-public-key (>= 1:17.3-dfsg), erlang-ssl (>= 1:17.3-dfsg), erlang-syntax-tools (>= 1:17.3-dfsg), openssl, ucf, debconf (>= 0.5) | debconf-2.0, erlang-lager, erlang-jiffy, erlang-p1-cache-tab, erlang-p1-iconv, erlang-p1-mysql, erlang-p1-pam, erlang-p1-pgsql, erlang-p1-sip, erlang-p1-stringprep, erlang-p1-stun, erlang-p1-tls, erlang-p1-utils, erlang-p1-xml, erlang-p1-yaml, erlang-p1-zlib, erlang-xmlrpc
Remends: ejabberd-contrib
Suggests: libunix-syslog-perl, imagemagick | graphicsmagick-imagemagick- pat
Conflicts: ejabberd-mod-shared-roster-ldap
Conffiles:
/etc/default/ejabberd 49352468a39da545ad13586af05877f9
/etc/ejabberd/inetrc a8de3c20d2ac990c8f319907b340d6a2
/etc/init.d/ejabberd 58aa53c895ae2250e80ea16769db0417
/etc/logrotate.d/ejabberd d2a0a63e544aabfb797f718471c6d173
/etc/ufw/applications.d/ejabberd abc263fcde39ff65e9b5722be81db8ff
Description: distributed, fault-tolerant Jabber/XMPP server written in Erlang
ejabberd is a distributed, fault-tolerant Jabber/XMPP server written in Erlang.
And $ service ejabberd status
returns
● ejabberd.service - LSB: Starts ejabberd jabber server
Loaded: loaded (/etc/init.d/ejabberd)
Active: active (exited) since Thu 2015-08-20 13:32:27 PDT; 12h ago
Docs: man:systemd-sysv-generator(8)
Process: 12701 ExecStop=/etc/init.d/ejabberd stop (code=exited, status=0/SUCCESS)
Process: 13716 ExecStart=/etc/init.d/ejabberd start (code=exited, status=0/SUCCESS)
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 156: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 157: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 158: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 159: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 160: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 161: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 163: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 164: /etc/eja...d
Aug 20 13:32:27 ubuntu ejabberd[13716]: done.
Aug 20 13:32:27 ubuntu systemd[1]: Started LSB: Starts ejabberd jabber server.
Python
or C++
and can share some working code, I will accept this answer.
– Jacobian
Commented
Aug 19, 2015 at 4:48
Ejabberd supports websockets from version 15.03 onwards - which solved the answer above.
This has nothing to do with python or C++ - the puzzle is simply about configuring Ejabberd to support websockets, and optionally using a proxy to handle websockets traffic.
Under the ejabjjerd.yml section, module: ejabberd_http add
request_handlers:
"/http-ws": ejabberd_http_ws
This will then be available at port 5280:/http-ws
If this is not convenient, you can proxy from port 80 using apache or nginx.
For nginx, within the virtual host you need something like this, where JABBERIP is the ip address of ejabberd. This proxies the websocket connection from the standard http port 80 through to ejabberd, with the connection configured to handle websockets.
location /http-ws/ {
proxy_pass http://JABBERIP:5280; // this is
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
you might also need to adjust websocket settings in ejabberd.yml - I put these at the top of the file..
websocket_ping_interval: 60
websocket_timeout: 86400
Setting up strophe is beyond the scope of this answer, but the key bit is setting up the connection to use websockets IF the browser supports this. The following snippit is from an angularjs app - though you get the idea... the SocketUrl is public location of the /http-ws location as shown above.. this could be the :5280 version or the version as proxied to port 80.
if (window.WebSocket && (passwd != 'undefined' && passwd != null)) {
$this.connection = new Strophe.Connection($this.SocketUrl);
$this.connection.connect(user_info.username+'@'+$this.jabberUrl, passwd, $this.onConnect.bind($this));
} else {
UserService.getJabberData().then(function (response) {
var jabber = response.data;
$this.connection = new Strophe.Connection($this.BOSHUrl);
$this.connection.attach(jabber.jid, jabber.sid, jabber.rid, $this.onConnect.bind($this));
});
}
There are also xmpp libraries for python and other languages - though if you are looking at building an app to run in a web browser, strophe is an excellent choice.