mirror of
https://github.com/processone/ejabberd.git
synced 2024-10-13 15:16:49 +02:00
* src/ejabberd_listener.erl: New way to configure IP address and
IP version of listener. Support for definition of IP address in string format, and implicit definition of IP version (EJAB-388). Support for defining several listeners: all with same port number but different IP addresses (EJAB-389)(thanks to Fabrice Colliot and Sergei Golovan). Better report in WebAdmin of problem when starting a listener. The old configuration method of ip tuple and inet6 is fully supported for backwards compatibility, but is not documented in the Guide anymore. * src/ejabberd_config.erl: Likewise * src/mod_proxy65/mod_proxy65_stream.erl: Likewise * src/mod_proxy65/mod_proxy65_service.erl: Likewise * src/web/ejabberd_web_admin.erl: Likewise * doc/guide.tex: Document the new way to configure IP address and IP version of listener, undocument options ip and inet6 * doc/guide.html: Likewise SVN Revision: 1812
This commit is contained in:
parent
55db20d4b7
commit
ba2eb35590
17
ChangeLog
17
ChangeLog
@ -1,5 +1,22 @@
|
||||
2009-01-12 Badlop <badlop@process-one.net>
|
||||
|
||||
* src/ejabberd_listener.erl: New way to configure IP address and
|
||||
IP version of listener. Support for definition of IP address in
|
||||
string format, and implicit definition of IP
|
||||
version (EJAB-388). Support for defining several listeners: all
|
||||
with same port number but different IP addresses (EJAB-389)(thanks
|
||||
to Fabrice Colliot and Sergei Golovan). Better report in WebAdmin
|
||||
of problem when starting a listener. The old configuration method
|
||||
of ip tuple and inet6 is fully supported for backwards
|
||||
compatibility, but is not documented in the Guide anymore.
|
||||
* src/ejabberd_config.erl: Likewise
|
||||
* src/mod_proxy65/mod_proxy65_stream.erl: Likewise
|
||||
* src/mod_proxy65/mod_proxy65_service.erl: Likewise
|
||||
* src/web/ejabberd_web_admin.erl: Likewise
|
||||
* doc/guide.tex: Document the new way to configure IP address and
|
||||
IP version of listener, undocument options ip and inet6
|
||||
* doc/guide.html: Likewise
|
||||
|
||||
* src/web/ejabberd_web_admin.erl: New appearance of WebAdmin logo,
|
||||
fixed logo-fill.
|
||||
|
||||
|
144
doc/guide.html
144
doc/guide.html
@ -622,31 +622,59 @@ other different modules for some specific virtual hosts:
|
||||
will listen and what services will be run on them. Each element of the list is a
|
||||
tuple with the following elements:
|
||||
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
Port number.
|
||||
</LI><LI CLASS="li-itemize">Module that serves this port.
|
||||
</LI><LI CLASS="li-itemize">Options to this module.
|
||||
</LI></UL><P>
|
||||
Port number. Optionally also the IP address.
|
||||
</LI><LI CLASS="li-itemize">Listening module that serves this port.
|
||||
</LI><LI CLASS="li-itemize">Options for the TCP socket and for the listening module.
|
||||
</LI></UL><P>With the basic syntax the ports will listen on all IPv4 network addresses:
|
||||
</P><PRE CLASS="verbatim">{listen, [
|
||||
{<port-number>, <module>, [<options>]},
|
||||
{<port-number>, <module>, [<options>]},
|
||||
...
|
||||
{<port-number>, <module>, [<options>]}
|
||||
]}.
|
||||
</PRE><P>It is possible to specify the IP address for a port using the full syntax:
|
||||
</P><PRE CLASS="verbatim"> {{<port-number>, <ip-address>}, <module>, [<options>]}
|
||||
</PRE><P> <A NAME="listened-port"></A> </P><!--TOC subsubsection Port Number and IP Address-->
|
||||
<H4 CLASS="subsubsection"><!--SEC ANCHOR --><A HREF="#listened-port">Port Number and IP Address</A></H4><!--SEC END --><P> <A NAME="listened-port"></A> </P><P>The port number defines which port to listen for incoming connections.
|
||||
It can be a Jabber/XMPP standard port
|
||||
(see section <A HREF="#firewall">5.1</A>) or any other valid port number.</P><P>The IP address can be represented with a string
|
||||
or an Erlang tuple with decimal or hexadecimal numbers.
|
||||
The socket will listen only in that network interface.
|
||||
It is possible to specify a generic address,
|
||||
so <TT>ejabberd</TT> will listen in all addresses.
|
||||
Depending in the type of the IP address, IPv4 or IPv6 will be used.</P><P>Some example values for IP address:
|
||||
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
<CODE>"0.0.0.0"</CODE> to listen in all IPv4 network interfaces. This is the default value when no IP is specified.
|
||||
</LI><LI CLASS="li-itemize"><CODE>"::"</CODE> to listen in all IPv6 network interfaces
|
||||
</LI><LI CLASS="li-itemize"><CODE>"10.11.12.13"</CODE> is the IPv4 address <CODE>10.11.12.13</CODE>
|
||||
</LI><LI CLASS="li-itemize"><CODE>"::FFFF:127.0.0.1"</CODE> is the IPv6 address <CODE>::FFFF:127.0.0.1/128</CODE>
|
||||
</LI><LI CLASS="li-itemize"><CODE>{10, 11, 12, 13}</CODE> is the IPv4 address <CODE>10.11.12.13</CODE>
|
||||
</LI><LI CLASS="li-itemize"><CODE>{0, 0, 0, 0, 0, 65535, 32512, 1}</CODE> is the IPv6 address <CODE>::FFFF:127.0.0.1/128</CODE>
|
||||
</LI><LI CLASS="li-itemize"><CODE>{16#fdca, 16#8ab6, 16#a243, 16#75ef, 0, 0, 0, 1}</CODE> is the IPv6 address <CODE>FDCA:8AB6:A243:75EF::1/128</CODE>
|
||||
</LI></UL><P> <A NAME="listened-module"></A> </P><!--TOC subsubsection Listening Module-->
|
||||
<H4 CLASS="subsubsection"><!--SEC ANCHOR --><A HREF="#listened-module">Listening Module</A></H4><!--SEC END --><P> <A NAME="listened-module"></A> </P><P>
|
||||
The available modules, their purpose and the options allowed by each one are:
|
||||
</P><DL CLASS="description"><DT CLASS="dt-description">
|
||||
<B><TT>ejabberd_c2s</TT></B></DT><DD CLASS="dd-description">
|
||||
Handles c2s connections.<BR>
|
||||
Options: <TT>access</TT>, <TT>certfile</TT>, <TT>inet6</TT>,
|
||||
<TT>ip</TT>, <TT>max_stanza_size</TT>, <TT>shaper</TT>,
|
||||
Options: <TT>access</TT>, <TT>certfile</TT>,
|
||||
<TT>max_stanza_size</TT>, <TT>shaper</TT>,
|
||||
<TT>starttls</TT>, <TT>starttls_required</TT>, <TT>tls</TT>,
|
||||
<TT>zlib</TT>
|
||||
</DD><DT CLASS="dt-description"><B><TT>ejabberd_s2s_in</TT></B></DT><DD CLASS="dd-description">
|
||||
Handles incoming s2s connections.<BR>
|
||||
Options: <TT>inet6</TT>, <TT>ip</TT>, <TT>max_stanza_size</TT>
|
||||
Options: <TT>max_stanza_size</TT>
|
||||
</DD><DT CLASS="dt-description"><B><TT>ejabberd_service</TT></B></DT><DD CLASS="dd-description">
|
||||
Interacts with an <A HREF="http://www.ejabberd.im/tutorials-transports">external component</A>
|
||||
(as defined in the Jabber Component Protocol (<A HREF="http://www.xmpp.org/extensions/xep-0114.html">XEP-0114</A>).<BR>
|
||||
Options: <TT>access</TT>, <TT>hosts</TT>, <TT>inet6</TT>,
|
||||
<TT>ip</TT>, <TT>shaper</TT>, <TT>service_check_from</TT>
|
||||
Options: <TT>access</TT>, <TT>hosts</TT>,
|
||||
<TT>shaper</TT>, <TT>service_check_from</TT>
|
||||
</DD><DT CLASS="dt-description"><B><TT>ejabberd_http</TT></B></DT><DD CLASS="dd-description">
|
||||
Handles incoming HTTP connections.<BR>
|
||||
Options: <TT>certfile</TT>, <TT>http_bind</TT>, <TT>http_poll</TT>,
|
||||
<TT>inet6</TT>, <TT>ip</TT>, <TT>request_handlers</TT>, <TT>tls</TT>, <TT>web_admin</TT><BR>
|
||||
</DD></DL><P>This is a detailed description of each option allowed by the listening modules:
|
||||
<TT>request_handlers</TT>, <TT>tls</TT>, <TT>web_admin</TT><BR>
|
||||
</DD></DL><P> <A NAME="listened-options"></A> </P><!--TOC subsubsection Options-->
|
||||
<H4 CLASS="subsubsection"><!--SEC ANCHOR --><A HREF="#listened-options">Options</A></H4><!--SEC END --><P> <A NAME="listened-options"></A> </P><P>This is a detailed description of each option allowed by the listening modules:
|
||||
</P><DL CLASS="description"><DT CLASS="dt-description">
|
||||
<B><TT>{access, <access rule>}</TT></B></DT><DD CLASS="dd-description"> This option defines
|
||||
access to the port. The default value is <TT>all</TT>.
|
||||
@ -685,13 +713,7 @@ do not allow outgoing sockets on port 5222.<P>If HTTP Polling is enabled, it wil
|
||||
is also needed in the Jabber client. Remark also that HTTP Polling can be
|
||||
interesting to host a web-based Jabber client such as
|
||||
<A HREF="http://jwchat.sourceforge.net/">JWChat</A>.
|
||||
</P></DD><DT CLASS="dt-description"><B><TT>inet6</TT></B></DT><DD CLASS="dd-description"> Set up the socket for IPv6 instead of IPv4.
|
||||
Note: this option is not required for S2S outgoing connections,
|
||||
because when ejabberd attempts to establish a S2S outgoing connection
|
||||
it first tries IPv4, and if that fails it attempts with IPv6.
|
||||
</DD><DT CLASS="dt-description"><B><TT>{ip, IPAddress}</TT></B></DT><DD CLASS="dd-description"> This option specifies which network
|
||||
interface to listen for. For example <CODE>{ip, {192, 168, 1, 1}}</CODE>.
|
||||
</DD><DT CLASS="dt-description"><B><TT>{max_stanza_size, Size}</TT></B></DT><DD CLASS="dd-description">
|
||||
</P></DD><DT CLASS="dt-description"><B><TT>{max_stanza_size, Size}</TT></B></DT><DD CLASS="dd-description">
|
||||
This option specifies an
|
||||
approximate maximum size in bytes of XML stanzas. Approximate,
|
||||
because it is calculated with the precision of one block of readed
|
||||
@ -736,7 +758,7 @@ is available on connections to the port. Client connections cannot use
|
||||
stream compression and stream encryption simultaneously. Hence, if you
|
||||
specify both <TT>tls</TT> (or <TT>ssl</TT>) and <TT>zlib</TT>, the latter
|
||||
option will not affect connections (there will be no stream compression).
|
||||
</DD></DL><P>There are some additional global options:
|
||||
</DD></DL><P>There are some additional global options that can be specified in the ejabberd configuration file (outside <TT>listen</TT>):
|
||||
</P><DL CLASS="description"><DT CLASS="dt-description">
|
||||
<B><TT>{s2s_use_starttls, true|false}</TT></B></DT><DD CLASS="dd-description">
|
||||
This option defines whether to
|
||||
@ -759,17 +781,18 @@ with a small list of trusted servers, or to block some specific servers.
|
||||
</DD><DT CLASS="dt-description"><B><TT>{s2s_max_retry_delay, Seconds}</TT></B></DT><DD CLASS="dd-description">
|
||||
The maximum allowed delay for retry to connect after a failed connection attempt.
|
||||
Specified in seconds. The default value is 300 seconds (5 minutes).
|
||||
</DD></DL><P>For example, the following simple configuration defines:
|
||||
</DD></DL><P> <A NAME="listened-examples"></A> </P><!--TOC subsubsection Examples-->
|
||||
<H4 CLASS="subsubsection"><!--SEC ANCHOR --><A HREF="#listened-examples">Examples</A></H4><!--SEC END --><P> <A NAME="listened-examples"></A> </P><P>For example, the following simple configuration defines:
|
||||
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
There are three domains. The default certificate file is <TT>server.pem</TT>.
|
||||
However, the c2s and s2s connections to the domain <TT>example.com</TT> use the file <TT>example_com.pem</TT>.
|
||||
</LI><LI CLASS="li-itemize">Port 5222 listens for c2s connections with STARTTLS,
|
||||
and also allows plain connections for old clients.
|
||||
</LI><LI CLASS="li-itemize">Port 5223 listens for c2s connections with the old SSL.
|
||||
</LI><LI CLASS="li-itemize">Port 5269 listens for s2s connections with STARTTLS.
|
||||
</LI><LI CLASS="li-itemize">Port 5269 listens for s2s connections with STARTTLS. The socket is set for IPv6 instead of IPv4.
|
||||
</LI><LI CLASS="li-itemize">Port 5280 listens for HTTP requests, and serves the HTTP Poll service.
|
||||
</LI><LI CLASS="li-itemize">Port 5281 listens for HTTP requests, and serves the Web Admin using HTTPS as explained in
|
||||
section <A HREF="#webadmin">4.2</A>.
|
||||
section <A HREF="#webadmin">4.2</A>. The socket only listens connections to the IP address 127.0.0.1.
|
||||
</LI></UL><PRE CLASS="verbatim">{hosts, ["example.com", "example.org", "example.net"]}.
|
||||
{listen,
|
||||
[
|
||||
@ -785,17 +808,17 @@ section <A HREF="#webadmin">4.2</A>.
|
||||
tls, {certfile, "/etc/ejabberd/server.pem"},
|
||||
{max_stanza_size, 65536}
|
||||
]},
|
||||
{5269, ejabberd_s2s_in, [
|
||||
{shaper, s2s_shaper},
|
||||
{max_stanza_size, 131072}
|
||||
]},
|
||||
{{5269, "::"}, ejabberd_s2s_in, [
|
||||
{shaper, s2s_shaper},
|
||||
{max_stanza_size, 131072}
|
||||
]},
|
||||
{5280, ejabberd_http, [
|
||||
http_poll
|
||||
]},
|
||||
{5281, ejabberd_http, [
|
||||
web_admin,
|
||||
tls, {certfile, "/etc/ejabberd/server.pem"},
|
||||
]}
|
||||
{{5281, "127.0.0.1"}, ejabberd_http, [
|
||||
web_admin,
|
||||
tls, {certfile, "/etc/ejabberd/server.pem"},
|
||||
]}
|
||||
]
|
||||
}.
|
||||
{s2s_use_starttls, true}.
|
||||
@ -803,21 +826,23 @@ section <A HREF="#webadmin">4.2</A>.
|
||||
{domain_certfile, "example.com", "/etc/ejabberd/example_com.pem"}.
|
||||
</PRE><P>In this example, the following configuration defines that:
|
||||
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
c2s connections are listened for on port 5222 and 5223 (SSL) and denied
|
||||
c2s connections are listened for on port 5222 (all IPv4 addresses) and
|
||||
on port 5223 (SSL, IP 192.168.0.1 and fdca:8ab6:a243:75ef::1) and denied
|
||||
for the user called ‘<TT>bad</TT>’.
|
||||
</LI><LI CLASS="li-itemize">s2s connections are listened for on port 5269 with STARTTLS for secured
|
||||
traffic enabled.
|
||||
</LI><LI CLASS="li-itemize">s2s connections are listened for on port 5269 (all IPv4 addresses)
|
||||
with STARTTLS for secured traffic enabled.
|
||||
Incoming and outgoing connections of remote Jabber servers are denied,
|
||||
only two servers can connect: "jabber.example.org" and "example.com".
|
||||
</LI><LI CLASS="li-itemize">Port 5280 is serving the Web Admin and the HTTP Polling service. Note
|
||||
</LI><LI CLASS="li-itemize">Port 5280 is serving the Web Admin and the HTTP Polling service
|
||||
in all the IPv4 addresses. Note
|
||||
that it is also possible to serve them on different ports. The second
|
||||
example in section <A HREF="#webadmin">4.2</A> shows how exactly this can be done.
|
||||
</LI><LI CLASS="li-itemize">All users except for the administrators have a traffic of limit
|
||||
</LI><LI CLASS="li-itemize">All users except for the administrators have a traffic of limit
|
||||
1,000 Bytes/second
|
||||
</LI><LI CLASS="li-itemize">The
|
||||
<A HREF="http://www.ejabberd.im/pyaimt">AIM transport</A>
|
||||
<TT>aim.example.org</TT> is connected to port 5233 with password
|
||||
‘<TT>aimsecret</TT>’.
|
||||
<TT>aim.example.org</TT> is connected to port 5233 on localhost IP addresses
|
||||
(127.0.0.1 and ::1) with password ‘<TT>aimsecret</TT>’.
|
||||
</LI><LI CLASS="li-itemize">The ICQ transport JIT (<TT>icq.example.org</TT> and
|
||||
<TT>sms.example.org</TT>) is connected to port 5234 with password
|
||||
‘<TT>jitsecret</TT>’.
|
||||
@ -843,13 +868,32 @@ connected to port 5237 with password ‘<TT>ggsecret</TT>’.
|
||||
{access, c2s_shaper, [{none, admin},
|
||||
{normal, all}]}.
|
||||
{listen,
|
||||
[{5222, ejabberd_c2s, [{access, c2s}, {shaper, c2s_shaper}]},
|
||||
{5223, ejabberd_c2s, [{access, c2s},
|
||||
ssl, {certfile, "/path/to/ssl.pem"}]},
|
||||
{5269, ejabberd_s2s_in, []},
|
||||
{5280, ejabberd_http, [http_poll, web_admin]},
|
||||
{5233, ejabberd_service, [{hosts, ["aim.example.org"],
|
||||
[{password, "aimsecret"}]}]},
|
||||
[{5222, ejabberd_c2s, [
|
||||
{access, c2s},
|
||||
{shaper, c2s_shaper}
|
||||
]},
|
||||
{{5223, {192, 168, 0, 1}}, ejabberd_c2s, [
|
||||
{access, c2s},
|
||||
ssl, {certfile, "/path/to/ssl.pem"}
|
||||
]},
|
||||
{{5223, {16#fdca, 16#8ab6, 16#a243, 16#75ef, 0, 0, 0, 1}},
|
||||
ejabberd_c2s, [
|
||||
{access, c2s},
|
||||
ssl, {certfile, "/path/to/ssl.pem"}
|
||||
]},
|
||||
{5269, ejabberd_s2s_in, []},
|
||||
{{5280, {0, 0, 0, 0}}, ejabberd_http, [
|
||||
http_poll,
|
||||
web_admin
|
||||
]},
|
||||
{{5233, {127, 0, 0, 1}}, ejabberd_service, [
|
||||
{hosts, ["aim.example.org"],
|
||||
[{password, "aimsecret"}]}
|
||||
]},
|
||||
{{5233, "::1"}, ejabberd_service, [
|
||||
{hosts, ["aim.example.org"],
|
||||
[{password, "aimsecret"}]}
|
||||
]},
|
||||
{5234, ejabberd_service, [{hosts, ["icq.example.org", "sms.example.org"],
|
||||
[{password, "jitsecret"}]}]},
|
||||
{5235, ejabberd_service, [{hosts, ["msn.example.org"],
|
||||
@ -3073,16 +3117,20 @@ administer the virtual host <TT>example.com</TT>.
|
||||
</PRE></LI><LI CLASS="li-itemize">For security reasons, you can serve the Web Admin on a secured
|
||||
connection, on a port differing from the HTTP Polling interface, and bind it
|
||||
to the internal LAN IP. The Web Admin will be accessible by pointing your
|
||||
web browser to <CODE>https://192.168.1.1:5280/admin/</CODE>:
|
||||
web browser to <CODE>https://192.168.1.1:5282/admin/</CODE>:
|
||||
<PRE CLASS="verbatim">
|
||||
{hosts, ["example.org"]}.
|
||||
|
||||
{listen,
|
||||
[
|
||||
...
|
||||
{5270, ejabberd_http, [http_poll]},
|
||||
{5280, ejabberd_http, [web_admin, {ip, {192, 168, 1, 1}},
|
||||
tls, {certfile, "/usr/local/etc/server.pem"}]},
|
||||
{5280, ejabberd_http, [
|
||||
http_poll
|
||||
]},
|
||||
{{5282, "192.168.1.1"}, ejabberd_http, [
|
||||
web_admin,
|
||||
tls, {certfile, "/usr/local/etc/server.pem"}
|
||||
]},
|
||||
...
|
||||
]}.
|
||||
</PRE></LI></UL><P>Certain pages in the ejabberd Web Admin contain a link to a related
|
||||
|
157
doc/guide.tex
157
doc/guide.tex
@ -735,34 +735,80 @@ The option \option{listen} defines for which addresses and ports \ejabberd{}
|
||||
will listen and what services will be run on them. Each element of the list is a
|
||||
tuple with the following elements:
|
||||
\begin{itemize}
|
||||
\item Port number.
|
||||
\item Module that serves this port.
|
||||
\item Options to this module.
|
||||
\item Port number. Optionally also the IP address.
|
||||
\item Listening module that serves this port.
|
||||
\item Options for the TCP socket and for the listening module.
|
||||
\end{itemize}
|
||||
|
||||
With the basic syntax the ports will listen on all IPv4 network addresses:
|
||||
\begin{verbatim}
|
||||
{listen, [
|
||||
{<port-number>, <module>, [<options>]},
|
||||
{<port-number>, <module>, [<options>]},
|
||||
...
|
||||
{<port-number>, <module>, [<options>]}
|
||||
]}.
|
||||
\end{verbatim}
|
||||
|
||||
It is possible to specify the IP address for a port using the full syntax:
|
||||
\begin{verbatim}
|
||||
{{<port-number>, <ip-address>}, <module>, [<options>]}
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
\makesubsubsection{listened-port}{Port Number and IP Address}
|
||||
|
||||
The port number defines which port to listen for incoming connections.
|
||||
It can be a Jabber/XMPP standard port
|
||||
(see section \ref{firewall}) or any other valid port number.
|
||||
|
||||
The IP address can be represented with a string
|
||||
or an Erlang tuple with decimal or hexadecimal numbers.
|
||||
The socket will listen only in that network interface.
|
||||
It is possible to specify a generic address,
|
||||
so \ejabberd{} will listen in all addresses.
|
||||
Depending in the type of the IP address, IPv4 or IPv6 will be used.
|
||||
|
||||
Some example values for IP address:
|
||||
\begin{itemize}
|
||||
\item \verb|"0.0.0.0"| to listen in all IPv4 network interfaces. This is the default value when no IP is specified.
|
||||
\item \verb|"::"| to listen in all IPv6 network interfaces
|
||||
\item \verb|"10.11.12.13"| is the IPv4 address \verb|10.11.12.13|
|
||||
\item \verb|"::FFFF:127.0.0.1"| is the IPv6 address \verb|::FFFF:127.0.0.1/128|
|
||||
\item \verb|{10, 11, 12, 13}| is the IPv4 address \verb|10.11.12.13|
|
||||
\item \verb|{0, 0, 0, 0, 0, 65535, 32512, 1}| is the IPv6 address \verb|::FFFF:127.0.0.1/128|
|
||||
\item \verb|{16#fdca, 16#8ab6, 16#a243, 16#75ef, 0, 0, 0, 1}| is the IPv6 address \verb|FDCA:8AB6:A243:75EF::1/128|
|
||||
\end{itemize}
|
||||
|
||||
|
||||
\makesubsubsection{listened-module}{Listening Module}
|
||||
|
||||
\ind{modules!ejabberd\_c2s}\ind{modules!ejabberd\_s2s\_in}\ind{modules!ejabberd\_service}\ind{modules!ejabberd\_http}\ind{protocols!XEP-0114: Jabber Component Protocol}
|
||||
The available modules, their purpose and the options allowed by each one are:
|
||||
\begin{description}
|
||||
\titem{\texttt{ejabberd\_c2s}}
|
||||
Handles c2s connections.\\
|
||||
Options: \texttt{access}, \texttt{certfile}, \texttt{inet6},
|
||||
\texttt{ip}, \texttt{max\_stanza\_size}, \texttt{shaper},
|
||||
Options: \texttt{access}, \texttt{certfile},
|
||||
\texttt{max\_stanza\_size}, \texttt{shaper},
|
||||
\texttt{starttls}, \texttt{starttls\_required}, \texttt{tls},
|
||||
\texttt{zlib}
|
||||
\titem{\texttt{ejabberd\_s2s\_in}}
|
||||
Handles incoming s2s connections.\\
|
||||
Options: \texttt{inet6}, \texttt{ip}, \texttt{max\_stanza\_size}
|
||||
Options: \texttt{max\_stanza\_size}
|
||||
\titem{\texttt{ejabberd\_service}}
|
||||
Interacts with an \footahref{http://www.ejabberd.im/tutorials-transports}{external component}
|
||||
(as defined in the Jabber Component Protocol (\xepref{0114}).\\
|
||||
Options: \texttt{access}, \texttt{hosts}, \texttt{inet6},
|
||||
\texttt{ip}, \texttt{shaper}, \texttt{service\_check\_from}
|
||||
Options: \texttt{access}, \texttt{hosts},
|
||||
\texttt{shaper}, \texttt{service\_check\_from}
|
||||
\titem{\texttt{ejabberd\_http}}
|
||||
Handles incoming HTTP connections.\\
|
||||
Options: \texttt{certfile}, \texttt{http\_bind}, \texttt{http\_poll},
|
||||
\texttt{inet6}, \texttt{ip}, \texttt{request\_handlers}, \texttt{tls}, \texttt{web\_admin}\\
|
||||
\texttt{request\_handlers}, \texttt{tls}, \texttt{web\_admin}\\
|
||||
\end{description}
|
||||
|
||||
|
||||
\makesubsubsection{listened-options}{Options}
|
||||
|
||||
This is a detailed description of each option allowed by the listening modules:
|
||||
\begin{description}
|
||||
\titem{\{access, <access rule>\}} \ind{options!access}This option defines
|
||||
@ -808,13 +854,7 @@ This is a detailed description of each option allowed by the listening modules:
|
||||
is also needed in the \Jabber{} client. Remark also that HTTP Polling can be
|
||||
interesting to host a web-based \Jabber{} client such as
|
||||
\footahref{http://jwchat.sourceforge.net/}{JWChat}.
|
||||
\titem{inet6} \ind{options!inet6}\ind{IPv6}Set up the socket for IPv6 instead of IPv4.
|
||||
Note: this option is not required for S2S outgoing connections,
|
||||
because when ejabberd attempts to establish a S2S outgoing connection
|
||||
it first tries IPv4, and if that fails it attempts with IPv6.
|
||||
\titem{\{ip, IPAddress\}} \ind{options!ip}This option specifies which network
|
||||
interface to listen for. For example \verb|{ip, {192, 168, 1, 1}}|.
|
||||
\titem{\{max\_stanza\_size, Size\}}
|
||||
\titem{\{max\_stanza\_size, Size\}}
|
||||
\ind{options!max\_stanza\_size}This option specifies an
|
||||
approximate maximum size in bytes of XML stanzas. Approximate,
|
||||
because it is calculated with the precision of one block of readed
|
||||
@ -861,7 +901,7 @@ This is a detailed description of each option allowed by the listening modules:
|
||||
option will not affect connections (there will be no stream compression).
|
||||
\end{description}
|
||||
|
||||
There are some additional global options:
|
||||
There are some additional global options that can be specified in the ejabberd configuration file (outside \term{listen}):
|
||||
\begin{description}
|
||||
\titem{\{s2s\_use\_starttls, true|false\}}
|
||||
\ind{options!s2s\_use\_starttls}\ind{STARTTLS}This option defines whether to
|
||||
@ -886,6 +926,8 @@ There are some additional global options:
|
||||
Specified in seconds. The default value is 300 seconds (5 minutes).
|
||||
\end{description}
|
||||
|
||||
\makesubsubsection{listened-examples}{Examples}
|
||||
|
||||
For example, the following simple configuration defines:
|
||||
\begin{itemize}
|
||||
\item There are three domains. The default certificate file is \term{server.pem}.
|
||||
@ -893,10 +935,10 @@ However, the c2s and s2s connections to the domain \term{example.com} use the fi
|
||||
\item Port 5222 listens for c2s connections with STARTTLS,
|
||||
and also allows plain connections for old clients.
|
||||
\item Port 5223 listens for c2s connections with the old SSL.
|
||||
\item Port 5269 listens for s2s connections with STARTTLS.
|
||||
\item Port 5269 listens for s2s connections with STARTTLS. The socket is set for IPv6 instead of IPv4.
|
||||
\item Port 5280 listens for HTTP requests, and serves the HTTP Poll service.
|
||||
\item Port 5281 listens for HTTP requests, and serves the Web Admin using HTTPS as explained in
|
||||
section~\ref{webadmin}.
|
||||
section~\ref{webadmin}. The socket only listens connections to the IP address 127.0.0.1.
|
||||
\end{itemize}
|
||||
\begin{verbatim}
|
||||
{hosts, ["example.com", "example.org", "example.net"]}.
|
||||
@ -914,17 +956,17 @@ However, the c2s and s2s connections to the domain \term{example.com} use the fi
|
||||
tls, {certfile, "/etc/ejabberd/server.pem"},
|
||||
{max_stanza_size, 65536}
|
||||
]},
|
||||
{5269, ejabberd_s2s_in, [
|
||||
{shaper, s2s_shaper},
|
||||
{max_stanza_size, 131072}
|
||||
]},
|
||||
{{5269, "::"}, ejabberd_s2s_in, [
|
||||
{shaper, s2s_shaper},
|
||||
{max_stanza_size, 131072}
|
||||
]},
|
||||
{5280, ejabberd_http, [
|
||||
http_poll
|
||||
]},
|
||||
{5281, ejabberd_http, [
|
||||
web_admin,
|
||||
tls, {certfile, "/etc/ejabberd/server.pem"},
|
||||
]}
|
||||
{{5281, "127.0.0.1"}, ejabberd_http, [
|
||||
web_admin,
|
||||
tls, {certfile, "/etc/ejabberd/server.pem"},
|
||||
]}
|
||||
]
|
||||
}.
|
||||
{s2s_use_starttls, true}.
|
||||
@ -934,21 +976,23 @@ However, the c2s and s2s connections to the domain \term{example.com} use the fi
|
||||
|
||||
In this example, the following configuration defines that:
|
||||
\begin{itemize}
|
||||
\item c2s connections are listened for on port 5222 and 5223 (SSL) and denied
|
||||
\item c2s connections are listened for on port 5222 (all IPv4 addresses) and
|
||||
on port 5223 (SSL, IP 192.168.0.1 and fdca:8ab6:a243:75ef::1) and denied
|
||||
for the user called `\term{bad}'.
|
||||
\item s2s connections are listened for on port 5269 with STARTTLS for secured
|
||||
traffic enabled.
|
||||
\item s2s connections are listened for on port 5269 (all IPv4 addresses)
|
||||
with STARTTLS for secured traffic enabled.
|
||||
Incoming and outgoing connections of remote Jabber servers are denied,
|
||||
only two servers can connect: "jabber.example.org" and "example.com".
|
||||
\item Port 5280 is serving the Web Admin and the HTTP Polling service. Note
|
||||
\item Port 5280 is serving the Web Admin and the HTTP Polling service
|
||||
in all the IPv4 addresses. Note
|
||||
that it is also possible to serve them on different ports. The second
|
||||
example in section~\ref{webadmin} shows how exactly this can be done.
|
||||
\item All users except for the administrators have a traffic of limit
|
||||
\item All users except for the administrators have a traffic of limit
|
||||
1,000\,Bytes/second
|
||||
\item \ind{transports!AIM}The
|
||||
\footahref{http://www.ejabberd.im/pyaimt}{AIM transport}
|
||||
\jid{aim.example.org} is connected to port 5233 with password
|
||||
`\term{aimsecret}'.
|
||||
\jid{aim.example.org} is connected to port 5233 on localhost IP addresses
|
||||
(127.0.0.1 and ::1) with password `\term{aimsecret}'.
|
||||
\item \ind{transports!ICQ}The ICQ transport JIT (\jid{icq.example.org} and
|
||||
\jid{sms.example.org}) is connected to port 5234 with password
|
||||
`\term{jitsecret}'.
|
||||
@ -976,13 +1020,32 @@ In this example, the following configuration defines that:
|
||||
{access, c2s_shaper, [{none, admin},
|
||||
{normal, all}]}.
|
||||
{listen,
|
||||
[{5222, ejabberd_c2s, [{access, c2s}, {shaper, c2s_shaper}]},
|
||||
{5223, ejabberd_c2s, [{access, c2s},
|
||||
ssl, {certfile, "/path/to/ssl.pem"}]},
|
||||
{5269, ejabberd_s2s_in, []},
|
||||
{5280, ejabberd_http, [http_poll, web_admin]},
|
||||
{5233, ejabberd_service, [{hosts, ["aim.example.org"],
|
||||
[{password, "aimsecret"}]}]},
|
||||
[{5222, ejabberd_c2s, [
|
||||
{access, c2s},
|
||||
{shaper, c2s_shaper}
|
||||
]},
|
||||
{{5223, {192, 168, 0, 1}}, ejabberd_c2s, [
|
||||
{access, c2s},
|
||||
ssl, {certfile, "/path/to/ssl.pem"}
|
||||
]},
|
||||
{{5223, {16#fdca, 16#8ab6, 16#a243, 16#75ef, 0, 0, 0, 1}},
|
||||
ejabberd_c2s, [
|
||||
{access, c2s},
|
||||
ssl, {certfile, "/path/to/ssl.pem"}
|
||||
]},
|
||||
{5269, ejabberd_s2s_in, []},
|
||||
{{5280, {0, 0, 0, 0}}, ejabberd_http, [
|
||||
http_poll,
|
||||
web_admin
|
||||
]},
|
||||
{{5233, {127, 0, 0, 1}}, ejabberd_service, [
|
||||
{hosts, ["aim.example.org"],
|
||||
[{password, "aimsecret"}]}
|
||||
]},
|
||||
{{5233, "::1"}, ejabberd_service, [
|
||||
{hosts, ["aim.example.org"],
|
||||
[{password, "aimsecret"}]}
|
||||
]},
|
||||
{5234, ejabberd_service, [{hosts, ["icq.example.org", "sms.example.org"],
|
||||
[{password, "jitsecret"}]}]},
|
||||
{5235, ejabberd_service, [{hosts, ["msn.example.org"],
|
||||
@ -3940,7 +4003,7 @@ Examples:
|
||||
\item For security reasons, you can serve the Web Admin on a secured
|
||||
connection, on a port differing from the HTTP Polling interface, and bind it
|
||||
to the internal LAN IP. The Web Admin will be accessible by pointing your
|
||||
web browser to \verb|https://192.168.1.1:5280/admin/|:
|
||||
web browser to \verb|https://192.168.1.1:5282/admin/|:
|
||||
\begin{verbatim}
|
||||
|
||||
{hosts, ["example.org"]}.
|
||||
@ -3948,9 +4011,13 @@ Examples:
|
||||
{listen,
|
||||
[
|
||||
...
|
||||
{5270, ejabberd_http, [http_poll]},
|
||||
{5280, ejabberd_http, [web_admin, {ip, {192, 168, 1, 1}},
|
||||
tls, {certfile, "/usr/local/etc/server.pem"}]},
|
||||
{5280, ejabberd_http, [
|
||||
http_poll
|
||||
]},
|
||||
{{5282, "192.168.1.1"}, ejabberd_http, [
|
||||
web_admin,
|
||||
tls, {certfile, "/usr/local/etc/server.pem"}
|
||||
]},
|
||||
...
|
||||
]}.
|
||||
\end{verbatim}
|
||||
|
@ -324,8 +324,16 @@ process_term(Term, State) ->
|
||||
{host_config, Host, Terms} ->
|
||||
lists:foldl(fun(T, S) -> process_host_term(T, Host, S) end,
|
||||
State, Terms);
|
||||
{listen, Val} ->
|
||||
add_option(listen, Val, State);
|
||||
{listen, Listeners} ->
|
||||
Listeners2 =
|
||||
lists:map(
|
||||
fun({PortIP, Module, Opts}) ->
|
||||
{Port, IPT, _, _, OptsClean} =
|
||||
ejabberd_listener:parse_listener_portip(PortIP, Opts),
|
||||
{{Port, IPT}, Module, OptsClean}
|
||||
end,
|
||||
Listeners),
|
||||
add_option(listen, Listeners2, State);
|
||||
{language, Val} ->
|
||||
add_option(language, Val, State);
|
||||
{outgoing_s2s_port, Port} ->
|
||||
|
@ -32,6 +32,7 @@
|
||||
start_listeners/0,
|
||||
start_listener/3,
|
||||
stop_listener/2,
|
||||
parse_listener_portip/2,
|
||||
add_listener/3,
|
||||
delete_listener/2
|
||||
]).
|
||||
@ -53,12 +54,25 @@ start_listeners() ->
|
||||
undefined ->
|
||||
ignore;
|
||||
Ls ->
|
||||
lists:map(
|
||||
fun({Port, Module, Opts}) ->
|
||||
start_listener(Port, Module, Opts)
|
||||
end, Ls)
|
||||
Ls2 = lists:map(
|
||||
fun({Port, Module, Opts}) ->
|
||||
start_listener(Port, Module, Opts)
|
||||
end, Ls),
|
||||
report_duplicated_portips(Ls),
|
||||
{ok, {{one_for_one, 10, 1}, Ls2}}
|
||||
end.
|
||||
|
||||
report_duplicated_portips(L) ->
|
||||
LKeys = [Port || {Port, _, _} <- L],
|
||||
LNoDupsKeys = proplists:get_keys(L),
|
||||
case LKeys -- LNoDupsKeys of
|
||||
[] -> ok;
|
||||
Dups ->
|
||||
?CRITICAL_MSG("In the ejabberd configuration there are duplicated "
|
||||
"Port number + IP address:~n ~p",
|
||||
[Dups])
|
||||
end.
|
||||
|
||||
start(Port, Module, Opts) ->
|
||||
%% Check if the module is an ejabberd listener or an independent listener
|
||||
ModuleRaw = strip_frontend(Module),
|
||||
@ -67,11 +81,11 @@ start(Port, Module, Opts) ->
|
||||
_ -> start_dependent(Port, Module, Opts)
|
||||
end.
|
||||
|
||||
%% -> {ok, Pid} | {error, ErrorMessage}
|
||||
start_dependent(Port, Module, Opts) ->
|
||||
case includes_deprecated_ssl_option(Opts) of
|
||||
false ->
|
||||
{ok, proc_lib:spawn_link(?MODULE, init,
|
||||
[Port, Module, Opts])};
|
||||
proc_lib:start_link(?MODULE, init, [Port, Module, Opts]);
|
||||
true ->
|
||||
SSLErr="There is a problem with your ejabberd configuration file: "
|
||||
"the option 'ssl' for listening sockets is no longer available."
|
||||
@ -91,13 +105,16 @@ includes_deprecated_ssl_option(Opts) ->
|
||||
lists:member(ssl, Opts)
|
||||
end.
|
||||
|
||||
init(Port, Module, Opts) ->
|
||||
init(PortIP, Module, Opts1) ->
|
||||
{Port, IPT, IPS, IPV, OptsClean} = parse_listener_portip(PortIP, Opts1),
|
||||
%% The first inet|inet6 and the last {ip, _} work,
|
||||
%% so overriding those in Opts
|
||||
Opts = [IPV | OptsClean] ++ [{ip, IPT}],
|
||||
SockOpts = lists:filter(fun({ip, _}) -> true;
|
||||
(inet6) -> true;
|
||||
(inet) -> true;
|
||||
(_) -> false
|
||||
end, Opts),
|
||||
|
||||
Res = gen_tcp:listen(Port, [binary,
|
||||
{packet, 0},
|
||||
{active, false},
|
||||
@ -108,13 +125,82 @@ init(Port, Module, Opts) ->
|
||||
SockOpts]),
|
||||
case Res of
|
||||
{ok, ListenSocket} ->
|
||||
%% Inform my parent that this port was opened succesfully
|
||||
proc_lib:init_ack({ok, self()}),
|
||||
%% And now start accepting connection attempts
|
||||
accept(ListenSocket, Module, Opts);
|
||||
{error, Reason} ->
|
||||
?ERROR_MSG("Failed to open socket for ~p: ~p",
|
||||
[{Port, Module, Opts}, Reason]),
|
||||
error
|
||||
ReasonT = case Reason of
|
||||
eaddrnotavail -> "IP address not available: " ++ IPS;
|
||||
_ -> atom_to_list(Reason)
|
||||
end,
|
||||
?ERROR_MSG("Failed to open socket:~n ~p~nReason: ~s",
|
||||
[{Port, Module, SockOpts}, ReasonT]),
|
||||
throw(ReasonT)
|
||||
end.
|
||||
|
||||
%% @spec (PortIP, Opts) -> {Port, IPT, IPS, IPV, OptsClean}
|
||||
%% where
|
||||
%% PortIP = Port | {Port, IPT | IPS}
|
||||
%% Port = integer()
|
||||
%% IPT = tuple()
|
||||
%% IPS = string()
|
||||
%% IPV = inet | inet6
|
||||
%% Opts = [IPV | {ip, IPT} | atom() | tuple()]
|
||||
%% OptsClean = [atom() | tuple()]
|
||||
%% @doc Parse any kind of ejabberd listener specification.
|
||||
%% The parsed options are returned in several formats.
|
||||
%% OptsClean does not include inet/inet6 or ip options.
|
||||
%% Opts can include the options inet6 and {ip, Tuple},
|
||||
%% but they are only used when no IP address was specified in the PortIP.
|
||||
%% The IP version (either IPv4 or IPv6) is inferred from the IP address type,
|
||||
%% so the option inet/inet6 is only used when no IP is specified at all.
|
||||
parse_listener_portip(PortIP, Opts) ->
|
||||
{IPOpt, Opts2} = strip_ip_option(Opts),
|
||||
{IPVOpt, OptsClean} = case lists:member(inet6, Opts2) of
|
||||
true -> {inet6, Opts2 -- [inet6]};
|
||||
false -> {inet, Opts2}
|
||||
end,
|
||||
{Port, IPT, IPS} = case PortIP of
|
||||
P when is_integer(P) ->
|
||||
T = get_ip_tuple(IPOpt, IPVOpt),
|
||||
S = inet_parse:ntoa(T),
|
||||
{P, T, S};
|
||||
{P, T} when is_integer(P) and is_tuple(T) ->
|
||||
S = inet_parse:ntoa(T),
|
||||
{P, T, S};
|
||||
{P, S} when is_integer(P) and is_list(S) ->
|
||||
[S | _] = string:tokens(S, "/"),
|
||||
{ok, T} = inet_parse:address(S),
|
||||
{P, T, S}
|
||||
end,
|
||||
IPV = case size(IPT) of
|
||||
4 -> inet;
|
||||
8 -> inet6
|
||||
end,
|
||||
{Port, IPT, IPS, IPV, OptsClean}.
|
||||
|
||||
strip_ip_option(Opts) ->
|
||||
{IPL, OptsNoIP} = lists:partition(
|
||||
fun({ip, _}) -> true;
|
||||
(_) -> false
|
||||
end,
|
||||
Opts),
|
||||
case IPL of
|
||||
%% Only the first ip option is considered
|
||||
[{ip, T1} | _] when is_tuple(T1) ->
|
||||
{T1, OptsNoIP};
|
||||
[] ->
|
||||
{no_ip_option, OptsNoIP}
|
||||
end.
|
||||
|
||||
get_ip_tuple(no_ip_option, inet) ->
|
||||
{0, 0, 0, 0};
|
||||
get_ip_tuple(no_ip_option, inet6) ->
|
||||
{0, 0, 0, 0, 0, 0, 0, 0};
|
||||
get_ip_tuple(IPOpt, _IPVOpt) ->
|
||||
IPOpt.
|
||||
|
||||
accept(ListenSocket, Module, Opts) ->
|
||||
case gen_tcp:accept(ListenSocket) of
|
||||
{ok, Socket} ->
|
||||
@ -137,11 +223,14 @@ accept(ListenSocket, Module, Opts) ->
|
||||
accept(ListenSocket, Module, Opts)
|
||||
end.
|
||||
|
||||
%% @spec (Port, Module, Opts) -> {ok, Pid} | {error, Error}
|
||||
start_listener(Port, Module, Opts) ->
|
||||
%% It is only required to start the supervisor in some cases.
|
||||
%% But it doesn't hurt to attempt to start it for any listener.
|
||||
%% So, it's normal (and harmless) that in most cases this call returns: {error, {already_started, pid()}}
|
||||
start_module_sup(Port, Module),
|
||||
start_listener_sup(Port, Module, Opts).
|
||||
|
||||
%% Only required for some listeners, but doing for all doesn't hurt
|
||||
start_module_sup(_Port, Module) ->
|
||||
Proc1 = gen_mod:get_module_proc("sup", Module),
|
||||
ChildSpec1 =
|
||||
@ -151,7 +240,7 @@ start_module_sup(_Port, Module) ->
|
||||
infinity,
|
||||
supervisor,
|
||||
[ejabberd_tmp_sup]},
|
||||
catch supervisor:start_child(ejabberd_sup, ChildSpec1).
|
||||
supervisor:start_child(ejabberd_sup, ChildSpec1).
|
||||
|
||||
start_listener_sup(Port, Module, Opts) ->
|
||||
ChildSpec = {Port,
|
||||
@ -165,33 +254,55 @@ start_listener_sup(Port, Module, Opts) ->
|
||||
stop_listener(Port, Module) ->
|
||||
supervisor:terminate_child(ejabberd_listeners, Port),
|
||||
supervisor:delete_child(ejabberd_listeners, Port),
|
||||
|
||||
Proc1 = gen_mod:get_module_proc("sup", Module),
|
||||
supervisor:terminate_child(ejabberd_sup, Proc1),
|
||||
supervisor:delete_child(ejabberd_sup, Proc1).
|
||||
|
||||
add_listener(Port, Module, Opts) ->
|
||||
%% @spec (PortIP, Module, Opts) -> {ok, Pid} | {error, Error}
|
||||
%% where
|
||||
%% PortIP = {Port, IPT | IPS}
|
||||
%% Port = integer()
|
||||
%% IPT = tuple()
|
||||
%% IPS = string()
|
||||
%% IPV = inet | inet6
|
||||
%% Module = atom()
|
||||
%% Opts = [IPV | {ip, IPT} | atom() | tuple()]
|
||||
%% @doc Add a listener and store in config if success
|
||||
add_listener(PortIP, Module, Opts) ->
|
||||
case start_listener(PortIP, Module, Opts) of
|
||||
{ok, _Pid} ->
|
||||
Ports = case ejabberd_config:get_local_option(listen) of
|
||||
undefined ->
|
||||
[];
|
||||
Ls ->
|
||||
Ls
|
||||
end,
|
||||
Ports1 = lists:keydelete(PortIP, 1, Ports),
|
||||
Ports2 = [{PortIP, Module, Opts} | Ports1],
|
||||
ejabberd_config:add_local_option(listen, Ports2),
|
||||
ok;
|
||||
{error, {already_started, _Pid}} ->
|
||||
{error, {already_started, PortIP}};
|
||||
{error, Error} ->
|
||||
{error, Error}
|
||||
end.
|
||||
|
||||
%% @spec (PortIP) -> ok
|
||||
%% where
|
||||
%% PortIP = {Port, IPT | IPS}
|
||||
%% Port = integer()
|
||||
%% IPT = tuple()
|
||||
%% IPS = string()
|
||||
delete_listener(PortIP, Module) ->
|
||||
Ports = case ejabberd_config:get_local_option(listen) of
|
||||
undefined ->
|
||||
[];
|
||||
Ls ->
|
||||
Ls
|
||||
end,
|
||||
Ports1 = lists:keydelete(Port, 1, Ports),
|
||||
Ports2 = [{Port, Module, Opts} | Ports1],
|
||||
ejabberd_config:add_local_option(listen, Ports2),
|
||||
start_listener(Port, Module, Opts).
|
||||
|
||||
delete_listener(Port, Module) ->
|
||||
Ports = case ejabberd_config:get_local_option(listen) of
|
||||
undefined ->
|
||||
[];
|
||||
Ls ->
|
||||
Ls
|
||||
end,
|
||||
Ports1 = lists:keydelete(Port, 1, Ports),
|
||||
Ports1 = lists:keydelete(PortIP, 1, Ports),
|
||||
ejabberd_config:add_local_option(listen, Ports1),
|
||||
stop_listener(Port, Module).
|
||||
stop_listener(PortIP, Module).
|
||||
|
||||
is_frontend({frontend, _Module}) -> true;
|
||||
is_frontend(_) -> false.
|
||||
|
@ -52,6 +52,7 @@
|
||||
name,
|
||||
stream_addr,
|
||||
port,
|
||||
ip,
|
||||
acl
|
||||
}).
|
||||
|
||||
@ -65,7 +66,7 @@ start_link(Host, Opts) ->
|
||||
gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []).
|
||||
|
||||
init([Host, Opts]) ->
|
||||
{_IP, State} = parse_options(Host, Opts),
|
||||
State = parse_options(Host, Opts),
|
||||
ejabberd_router:register_route(State#state.myhost),
|
||||
{ok, State}.
|
||||
|
||||
@ -89,8 +90,8 @@ handle_info({route, From, To, {xmlelement, "iq", _, _} = Packet}, State) ->
|
||||
handle_info(_Info, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
handle_call(get_port, _From, State) ->
|
||||
{reply, {port, State#state.port}, State};
|
||||
handle_call(get_port_ip, _From, State) ->
|
||||
{reply, {port_ip, State#state.port, State#state.ip}, State};
|
||||
handle_call(_Request, _From, State) ->
|
||||
{reply, ok, State}.
|
||||
|
||||
@ -105,14 +106,14 @@ code_change(_OldVsn, State, _Extra) ->
|
||||
%%%------------------------
|
||||
|
||||
add_listener(Host, Opts) ->
|
||||
{IP, State} = parse_options(Host, Opts),
|
||||
NewOpts = [Host, {ip, IP} | Opts],
|
||||
ejabberd_listener:add_listener(State#state.port,mod_proxy65_stream,NewOpts).
|
||||
State = parse_options(Host, Opts),
|
||||
NewOpts = [Host | Opts],
|
||||
ejabberd_listener:add_listener({State#state.port, State#state.ip}, mod_proxy65_stream, NewOpts).
|
||||
|
||||
delete_listener(Host) ->
|
||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||
{port, Port} = gen_server:call(Proc, get_port),
|
||||
catch ejabberd_listener:delete_listener(Port, mod_proxy65_stream).
|
||||
{port_ip, Port, IP} = gen_server:call(Proc, get_port_ip),
|
||||
catch ejabberd_listener:delete_listener({Port, IP}, mod_proxy65_stream).
|
||||
|
||||
%%%------------------------
|
||||
%%% IQ Processing
|
||||
@ -219,12 +220,13 @@ parse_options(ServerHost, Opts) ->
|
||||
end,
|
||||
StrIP = inet_parse:ntoa(IP),
|
||||
StreamAddr = [{"jid", MyHost}, {"host", StrIP}, {"port", integer_to_list(Port)}],
|
||||
{IP, #state{myhost = MyHost,
|
||||
#state{myhost = MyHost,
|
||||
serverhost = ServerHost,
|
||||
name = Name,
|
||||
port = Port,
|
||||
ip = IP,
|
||||
stream_addr = StreamAddr,
|
||||
acl = ACL}}.
|
||||
acl = ACL}.
|
||||
|
||||
%% Return the IP of the proxy host, or if not found, the ip of the xmpp domain
|
||||
get_proxy_or_domainip(ServerHost, MyHost) ->
|
||||
|
@ -78,7 +78,8 @@ code_change(_OldVsn, StateName, StateData, _Extra) ->
|
||||
{ok, StateName, StateData}.
|
||||
%%-------------------------------
|
||||
|
||||
start({gen_tcp, Socket}, [Host | Opts]) ->
|
||||
start({gen_tcp, Socket}, Opts1) ->
|
||||
{[Host], Opts} = lists:partition(fun(O) -> is_list(O) end, Opts1),
|
||||
Supervisor = gen_mod:get_module_proc(Host, ejabberd_mod_proxy65_sup),
|
||||
supervisor:start_child(Supervisor, [Socket, Host, Opts]).
|
||||
|
||||
|
@ -1809,9 +1809,14 @@ get_node(global, Node, ["ports"], Query, Lang) ->
|
||||
ok;
|
||||
{'EXIT', _Reason} ->
|
||||
error;
|
||||
{is_added, ok} ->
|
||||
ok;
|
||||
{is_added, {error, Reason}} ->
|
||||
{error, io_lib:format("~p", [Reason])};
|
||||
_ ->
|
||||
nothing
|
||||
end,
|
||||
%% TODO: This sorting does not work when [{{Port, IP}, Module, Opts}]
|
||||
NewPorts = lists:sort(
|
||||
rpc:call(Node, ejabberd_config, get_local_option, [listen])),
|
||||
H1String = ?T("Listened Ports at ") ++ atom_to_list(Node),
|
||||
@ -1819,6 +1824,7 @@ get_node(global, Node, ["ports"], Query, Lang) ->
|
||||
case Res of
|
||||
ok -> [?CT("Submitted"), ?P];
|
||||
error -> [?CT("Bad format"), ?P];
|
||||
{error, ReasonT} -> [?CT("Problem: "), ?C(ReasonT), ?P];
|
||||
nothing -> []
|
||||
end ++
|
||||
[?XAE("form", [{"action", ""}, {"method", "post"}],
|
||||
@ -2057,58 +2063,77 @@ node_ports_to_xhtml(Ports, Lang) ->
|
||||
[?XE("thead",
|
||||
[?XE("tr",
|
||||
[?XCT("td", "Port"),
|
||||
?XCT("td", "IP"),
|
||||
?XCT("td", "Module"),
|
||||
?XCT("td", "Options")
|
||||
])]),
|
||||
?XE("tbody",
|
||||
lists:map(
|
||||
fun({Port, Module, Opts} = _E) ->
|
||||
SPort = integer_to_list(Port),
|
||||
fun({PortIP, Module, Opts} = _E) ->
|
||||
{_Port, SPort, _TIP, SIP, SSPort, OptsClean} =
|
||||
get_port_data(PortIP, Opts),
|
||||
SModule = atom_to_list(Module),
|
||||
%%ID = term_to_id(E),
|
||||
?XE("tr",
|
||||
[?XC("td", SPort),
|
||||
?XE("td", [?INPUT("text", "module" ++ SPort,
|
||||
SModule)]),
|
||||
?XE("td", [?INPUTS("text", "opts" ++ SPort,
|
||||
term_to_string(Opts), "40")]),
|
||||
?XE("td", [?INPUTT("submit", "add" ++ SPort,
|
||||
[?XAE("td", [{"size", "6"}], [?C(SPort)]),
|
||||
?XAE("td", [{"size", "15"}], [?C(SIP)]),
|
||||
?XE("td", [?INPUTS("text", "module" ++ SSPort,
|
||||
SModule, "15")]),
|
||||
?XE("td", [?INPUTS("text", "opts" ++ SSPort,
|
||||
term_to_string(OptsClean), "40")]),
|
||||
?XE("td", [?INPUTT("submit", "add" ++ SSPort,
|
||||
"Update")]),
|
||||
?XE("td", [?INPUTT("submit", "delete" ++ SPort,
|
||||
?XE("td", [?INPUTT("submit", "delete" ++ SSPort,
|
||||
"Delete")])
|
||||
]
|
||||
)
|
||||
end, Ports) ++
|
||||
[?XE("tr",
|
||||
[?XE("td", [?INPUTS("text", "portnew", "", "6")]),
|
||||
?XE("td", [?INPUT("text", "modulenew", "")]),
|
||||
?XE("td", [?INPUTS("text", "optsnew", "", "40")]),
|
||||
?XE("td", [?INPUTS("text", "ipnew", "0.0.0.0", "15")]),
|
||||
?XE("td", [?INPUTS("text", "modulenew", "", "17")]),
|
||||
?XE("td", [?INPUTS("text", "optsnew", "[]", "40")]),
|
||||
?XAE("td", [{"colspan", "2"}],
|
||||
[?INPUTT("submit", "addnew", "Add New")])
|
||||
]
|
||||
)]
|
||||
)]).
|
||||
|
||||
get_port_data(PortIP, Opts) ->
|
||||
{Port, IPT, IPS, _IPV, OptsClean} = ejabberd_listener:parse_listener_portip(PortIP, Opts),
|
||||
SPort = io_lib:format("~p", [Port]),
|
||||
|
||||
SSPort = lists:flatten(
|
||||
lists:map(
|
||||
fun(N) -> io_lib:format("~.16b", [N]) end,
|
||||
binary_to_list(crypto:md5(SPort++IPS)))),
|
||||
{Port, SPort, IPT, IPS, SSPort, OptsClean}.
|
||||
|
||||
|
||||
node_ports_parse_query(Node, Ports, Query) ->
|
||||
lists:foreach(
|
||||
fun({Port, Module1, _Opts1}) ->
|
||||
SPort = integer_to_list(Port),
|
||||
case lists:keysearch("add" ++ SPort, 1, Query) of
|
||||
fun({PortIP, Module1, Opts1}) ->
|
||||
{Port, _SPort, TIP, _SIP, SSPort, _OptsClean} =
|
||||
get_port_data(PortIP, Opts1),
|
||||
case lists:keysearch("add" ++ SSPort, 1, Query) of
|
||||
{value, _} ->
|
||||
PortIP2 = {Port, TIP},
|
||||
{{value, {_, SModule}}, {value, {_, SOpts}}} =
|
||||
{lists:keysearch("module" ++ SPort, 1, Query),
|
||||
lists:keysearch("opts" ++ SPort, 1, Query)},
|
||||
{lists:keysearch("module" ++ SSPort, 1, Query),
|
||||
lists:keysearch("opts" ++ SSPort, 1, Query)},
|
||||
Module = list_to_atom(SModule),
|
||||
{ok, Tokens, _} = erl_scan:string(SOpts ++ "."),
|
||||
{ok, Opts} = erl_parse:parse_term(Tokens),
|
||||
rpc:call(Node, ejabberd_listener, delete_listener, [Port, Module]),
|
||||
rpc:call(Node, ejabberd_listener, add_listener, [Port, Module, Opts]),
|
||||
throw(submitted);
|
||||
rpc:call(Node, ejabberd_listener, delete_listener,
|
||||
[PortIP2, Module1]),
|
||||
R=rpc:call(Node, ejabberd_listener, add_listener,
|
||||
[PortIP2, Module, Opts]),
|
||||
throw({is_added, R});
|
||||
_ ->
|
||||
case lists:keysearch("delete" ++ SPort, 1, Query) of
|
||||
case lists:keysearch("delete" ++ SSPort, 1, Query) of
|
||||
{value, _} ->
|
||||
rpc:call(Node, ejabberd_listener, delete_listener, [Port, Module1]),
|
||||
rpc:call(Node, ejabberd_listener, delete_listener,
|
||||
[PortIP, Module1]),
|
||||
throw(submitted);
|
||||
_ ->
|
||||
ok
|
||||
@ -2118,17 +2143,28 @@ node_ports_parse_query(Node, Ports, Query) ->
|
||||
case lists:keysearch("addnew", 1, Query) of
|
||||
{value, _} ->
|
||||
{{value, {_, SPort}},
|
||||
{value, {_, STIP}}, %% It is a string that may represent a tuple
|
||||
{value, {_, SModule}},
|
||||
{value, {_, SOpts}}} =
|
||||
{lists:keysearch("portnew", 1, Query),
|
||||
lists:keysearch("ipnew", 1, Query),
|
||||
lists:keysearch("modulenew", 1, Query),
|
||||
lists:keysearch("optsnew", 1, Query)},
|
||||
Port = list_to_integer(SPort),
|
||||
{ok, Toks, _} = erl_scan:string(SPort ++ "."),
|
||||
{ok, Port2} = erl_parse:parse_term(Toks),
|
||||
{ok, ToksIP, _} = erl_scan:string(STIP ++ "."),
|
||||
STIP2 = case erl_parse:parse_term(ToksIP) of
|
||||
{ok, IPTParsed} -> IPTParsed;
|
||||
{error, _} -> STIP
|
||||
end,
|
||||
Module = list_to_atom(SModule),
|
||||
{ok, Tokens, _} = erl_scan:string(SOpts ++ "."),
|
||||
{ok, Opts} = erl_parse:parse_term(Tokens),
|
||||
rpc:call(Node, ejabberd_listener, add_listener, [Port, Module, Opts]),
|
||||
throw(submitted);
|
||||
{Port2, _SPort, IP2, _SIP, _SSPort, OptsClean} =
|
||||
get_port_data({Port2, STIP2}, Opts),
|
||||
R=rpc:call(Node, ejabberd_listener, add_listener,
|
||||
[{Port2, IP2}, Module, OptsClean]),
|
||||
throw({is_added, R});
|
||||
_ ->
|
||||
ok
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user