admin管理员组

文章数量:1432006

I need a "Hello world!" example, that demonstrates how to use websockets and ejabberd in bination. So, this is where I am:

  1. I have ejabberd installed and running
  2. I have two accounts: "user1" and "user2" with passwords "123"
  3. I'm able to run psi plus client under both users and I can send messages to myself
  4. I know from the official site of ejabberd that it supports websockets
  5. I know there is popular plugin Strophe.js that many people use to connect to ejabberd

and this is the list of problems:

  1. I do not know what is the right way to set ejabberd configuration (I guess, I installed a fresh version of ejabberd and its configuration is located in ejabberd.yml)
  2. I do not know whether I should make specific configuration of Apache server (proxies, rewrites etc. - in many forums I've seen some examples that involve such manipulations)
  3. I do not know what Javascript or C++ or Python code will match this puzzle, so that I could make a simple connect to or send a message

Well, 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:

  1. How to set ejabberd
  2. How to set Apache
  3. How primitive example (in JavaScript) should look like

EDIT

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 websockets and ejabberd in bination. So, this is where I am:

  1. I have ejabberd installed and running
  2. I have two accounts: "user1" and "user2" with passwords "123"
  3. I'm able to run psi plus client under both users and I can send messages to myself
  4. I know from the official site of ejabberd that it supports websockets
  5. I know there is popular plugin Strophe.js that many people use to connect to ejabberd

and this is the list of problems:

  1. I do not know what is the right way to set ejabberd configuration (I guess, I installed a fresh version of ejabberd and its configuration is located in ejabberd.yml)
  2. I do not know whether I should make specific configuration of Apache server (proxies, rewrites etc. - in many forums I've seen some examples that involve such manipulations)
  3. I do not know what Javascript or C++ or Python code will match this puzzle, so that I could make a simple connect to or send a message

Well, 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:

  1. How to set ejabberd
  2. How to set Apache
  3. How primitive example (in JavaScript) should look like

EDIT

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.
Share Improve this question edited Aug 21, 2015 at 8:42 Jacobian asked Aug 18, 2015 at 11:06 JacobianJacobian 10.9k32 gold badges140 silver badges233 bronze badges 2
  • I will start a really BIG bounty tomorrow, since I need a step-by-step fresh and deep instruction on this topic. So, hurry up to get some huge karma :) – Jacobian Commented Aug 19, 2015 at 4:43
  • By the way, if you know how to implement the similar thing in Python or C++ and can share some working code, I will accept this answer. – Jacobian Commented Aug 19, 2015 at 4:48
Add a ment  | 

1 Answer 1

Reset to default 4 +200

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.

本文标签: javascriptWebsockets and XMPP client How to make them work togetherStack Overflow