aboutsummaryrefslogtreecommitdiff
path: root/ejabberd-1.1.2/doc/dev.tex
diff options
context:
space:
mode:
Diffstat (limited to 'ejabberd-1.1.2/doc/dev.tex')
-rw-r--r--ejabberd-1.1.2/doc/dev.tex398
1 files changed, 398 insertions, 0 deletions
diff --git a/ejabberd-1.1.2/doc/dev.tex b/ejabberd-1.1.2/doc/dev.tex
new file mode 100644
index 000000000..3b0764311
--- /dev/null
+++ b/ejabberd-1.1.2/doc/dev.tex
@@ -0,0 +1,398 @@
+\documentclass[a4paper,10pt]{article}
+
+%% Packages
+\usepackage{graphics}
+\usepackage{hevea}
+\usepackage{makeidx}
+\usepackage{verbatim}
+
+%% Index
+\makeindex
+% Remove the index anchors from the HTML version to save size and bandwith.
+\newcommand{\ind}[1]{\begin{latexonly}\index{#1}\end{latexonly}}
+
+%% Images
+\newcommand{\logoscale}{0.7}
+\newcommand{\imgscale}{0.58}
+\newcommand{\insimg}[1]{\insscaleimg{\imgscale}{#1}}
+\newcommand{\insscaleimg}[2]{
+ \imgsrc{#2}{}
+ \begin{latexonly}
+ \scalebox{#1}{\includegraphics{#2}}
+ \end{latexonly}
+}
+
+%% Various
+\newcommand{\ns}[1]{\texttt{#1}}
+\newcommand{\ejabberd}{\texttt{ejabberd}}
+\newcommand{\Jabber}{Jabber}
+
+%% Modules
+\newcommand{\module}[1]{\texttt{#1}}
+\newcommand{\modadhoc}{\module{mod\_adhoc}}
+\newcommand{\modannounce}{\module{mod\_announce}}
+\newcommand{\modconfigure}{\module{mod\_configure}}
+\newcommand{\moddisco}{\module{mod\_disco}}
+\newcommand{\modecho}{\module{mod\_echo}}
+\newcommand{\modirc}{\module{mod\_irc}}
+\newcommand{\modlast}{\module{mod\_last}}
+\newcommand{\modlastodbc}{\module{mod\_last\_odbc}}
+\newcommand{\modmuc}{\module{mod\_muc}}
+\newcommand{\modmuclog}{\module{mod\_muc\_log}}
+\newcommand{\modoffline}{\module{mod\_offline}}
+\newcommand{\modofflineodbc}{\module{mod\_offline\_odbc}}
+\newcommand{\modprivacy}{\module{mod\_privacy}}
+\newcommand{\modprivate}{\module{mod\_private}}
+\newcommand{\modpubsub}{\module{mod\_pubsub}}
+\newcommand{\modregister}{\module{mod\_register}}
+\newcommand{\modroster}{\module{mod\_roster}}
+\newcommand{\modrosterodbc}{\module{mod\_roster\_odbc}}
+\newcommand{\modservicelog}{\module{mod\_service\_log}}
+\newcommand{\modsharedroster}{\module{mod\_shared\_roster}}
+\newcommand{\modstats}{\module{mod\_stats}}
+\newcommand{\modtime}{\module{mod\_time}}
+\newcommand{\modvcard}{\module{mod\_vcard}}
+\newcommand{\modvcardldap}{\module{mod\_vcard\_ldap}}
+\newcommand{\modvcardodbc}{\module{mod\_vcard\_odbc}}
+\newcommand{\modversion}{\module{mod\_version}}
+
+%% Title page
+\include{version}
+\title{Ejabberd \version\ Developers Guide}
+\author{Alexey Shchepin \\
+ \ahrefurl{mailto:alexey@sevcom.net} \\
+ \ahrefurl{xmpp:aleksey@jabber.ru}}
+
+%% Options
+\newcommand{\marking}[1]{#1} % Marking disabled
+\newcommand{\quoting}[2][yozhik]{} % Quotes disabled
+\newcommand{\new}{\begin{latexonly}\marginpar{\textsc{new}}\end{latexonly}} % Highlight new features
+\newcommand{\improved}{\begin{latexonly}\marginpar{\textsc{improved}}\end{latexonly}} % Highlight improved features
+\newcommand{\moreinfo}[1]{} % Hide details
+
+%% Footnotes
+\newcommand{\tjepref}[2]{\footahref{http://www.jabber.org/jeps/jep-#1.html}{#2}}
+\newcommand{\jepref}[1]{\tjepref{#1}{JEP-#1}}
+
+\begin{document}
+
+\label{sec:titlepage}
+\begin{titlepage}
+ \maketitle{}
+
+ \begin{center}
+ {\insscaleimg{\logoscale}{logo.png}
+ \par
+ }
+ \end{center}
+
+ \begin{quotation}\textit{I can thoroughly recommend ejabberd for ease of setup --
+ Kevin Smith, Current maintainer of the Psi project}\end{quotation}
+
+\end{titlepage}
+
+\tableofcontents{}
+
+% Input introduction.tex
+\input{introduction}
+
+\section{How it Works}
+\label{sec:howitworks}
+
+
+A \Jabber{} domain is served by one or more \ejabberd{} nodes. These nodes can
+be run on different machines that are connected via a network. They all must
+have the ability to connect to port 4369 of all another nodes, and must have
+the same magic cookie (see Erlang/OTP documentation, in other words the file
+\texttt{\~{}ejabberd/.erlang.cookie} must be the same on all nodes). This is
+needed because all nodes exchange information about connected users, S2S
+connections, registered services, etc\ldots
+
+
+
+Each \ejabberd{} node have following modules:
+\begin{itemize}
+\item router;
+\item local router.
+\item session manager;
+\item S2S manager;
+\end{itemize}
+
+
+\subsection{Router}
+
+This module is the main router of \Jabber{} packets on each node. It routes
+them based on their destinations domains. It has two tables: local and global
+routes. First, domain of packet destination searched in local table, and if it
+found, then the packet is routed to appropriate process. If no, then it
+searches in global table, and is routed to the appropriate \ejabberd{} node or
+process. If it does not exists in either tables, then it sent to the S2S
+manager.
+
+
+\subsection{Local Router}
+
+This module routes packets which have a destination domain equal to this server
+name. If destination JID has a non-empty user part, then it routed to the
+session manager, else it is processed depending on it's content.
+
+
+\subsection{Session Manager}
+
+This module routes packets to local users. It searches for what user resource
+packet must be sended via presence table. If this resource is connected to
+this node, it is routed to C2S process, if it connected via another node, then
+the packet is sent to session manager on that node.
+
+
+\subsection{S2S Manager}
+
+This module routes packets to other \Jabber{} servers. First, it checks if an
+open S2S connection from the domain of the packet source to the domain of
+packet destination already exists. If it is open on another node, then it
+routes the packet to S2S manager on that node, if it is open on this node, then
+it is routed to the process that serves this connection, and if a connection
+does not exist, then it is opened and registered.
+
+
+
+
+\section{XML Representation}
+\label{sec:xmlrepr}
+
+Each XML stanza is represented as the following tuple:
+\begin{verbatim}
+XMLElement = {xmlelement, Name, Attrs, [ElementOrCDATA]}
+ Name = string()
+ Attrs = [Attr]
+ Attr = {Key, Val}
+ Key = string()
+ Val = string()
+ ElementOrCDATA = XMLElement | CDATA
+ CDATA = {xmlcdata, string()}
+\end{verbatim}
+E.\,g. this stanza:
+\begin{verbatim}
+<message to='test@conference.example.org' type='groupchat'>
+ <body>test</body>
+</message>
+\end{verbatim}
+is represented as the following structure:
+\begin{verbatim}
+{xmlelement, "message",
+ [{"to", "test@conference.example.org"},
+ {"type", "groupchat"}],
+ [{xmlelement, "body",
+ [],
+ [{xmlcdata, "test"}]}]}}
+\end{verbatim}
+
+
+
+\section{Module \texttt{xml}}
+\label{sec:xmlmod}
+
+\begin{description}
+\item{\verb|element_to_string(El) -> string()|}
+\begin{verbatim}
+El = XMLElement
+\end{verbatim}
+ Returns string representation of XML stanza \texttt{El}.
+
+\item{\verb|crypt(S) -> string()|}
+\begin{verbatim}
+S = string()
+\end{verbatim}
+ Returns string which correspond to \texttt{S} with encoded XML special
+ characters.
+
+\item{\verb|remove_cdata(ECList) -> EList|}
+\begin{verbatim}
+ECList = [ElementOrCDATA]
+EList = [XMLElement]
+\end{verbatim}
+ \texttt{EList} is a list of all non-CDATA elements of ECList.
+
+
+
+\item{\verb|get_path_s(El, Path) -> Res|}
+\begin{verbatim}
+El = XMLElement
+Path = [PathItem]
+PathItem = PathElem | PathAttr | PathCDATA
+PathElem = {elem, Name}
+PathAttr = {attr, Name}
+PathCDATA = cdata
+Name = string()
+Res = string() | XMLElement
+\end{verbatim}
+ If \texttt{Path} is empty, then returns \texttt{El}. Else sequentially
+ consider elements of \texttt{Path}. Each element is one of:
+ \begin{description}
+ \item{\verb|{elem, Name}|} \texttt{Name} is name of subelement of
+ \texttt{El}, if such element exists, then this element considered in
+ following steps, else returns empty string.
+ \item{\verb|{attr, Name}|} If \texttt{El} have attribute \texttt{Name}, then
+ returns value of this attribute, else returns empty string.
+ \item{\verb|cdata|} Returns CDATA of \texttt{El}.
+ \end{description}
+
+\item{TODO:}
+\begin{verbatim}
+ get_cdata/1, get_tag_cdata/1
+ get_attr/2, get_attr_s/2
+ get_tag_attr/2, get_tag_attr_s/2
+ get_subtag/2
+\end{verbatim}
+\end{description}
+
+
+\section{Module \texttt{xml\_stream}}
+\label{sec:xmlstreammod}
+
+\begin{description}
+\item{\verb!parse_element(Str) -> XMLElement | {error, Err}!}
+\begin{verbatim}
+Str = string()
+Err = term()
+\end{verbatim}
+ Parses \texttt{Str} using XML parser, returns either parsed element or error
+ tuple.
+\end{description}
+
+
+\section{Modules}
+\label{sec:emods}
+
+
+%\subsection{gen\_mod behaviour}
+%\label{sec:genmod}
+
+%TBD
+
+\subsection{Module gen\_iq\_handler}
+\label{sec:geniqhandl}
+
+The module \verb|gen_iq_handler| allows to easily write handlers for IQ packets
+of particular XML namespaces that addressed to server or to users bare JIDs.
+
+In this module the following functions are defined:
+\begin{description}
+\item{\verb|add_iq_handler(Component, Host, NS, Module, Function, Type)|}
+\begin{verbatim}
+Component = Module = Function = atom()
+Host = NS = string()
+Type = no_queue | one_queue | parallel
+\end{verbatim}
+ Registers function \verb|Module:Function| as handler for IQ packets on
+ virtual host \verb|Host| that contain child of namespace \verb|NS| in
+ \verb|Component|. Queueing discipline is \verb|Type|. There are at least
+ two components defined:
+ \begin{description}
+ \item{\verb|ejabberd_local|} Handles packets that addressed to server JID;
+ \item{\verb|ejabberd_sm|} Handles packets that addressed to users bare JIDs.
+ \end{description}
+\item{\verb|remove_iq_handler(Component, Host, NS)|}
+\begin{verbatim}
+Component = atom()
+Host = NS = string()
+\end{verbatim}
+ Removes IQ handler on virtual host \verb|Host| for namespace \verb|NS| from
+ \verb|Component|.
+\end{description}
+
+Handler function must have the following type:
+\begin{description}
+\item{\verb|Module:Function(From, To, IQ)|}
+\begin{verbatim}
+From = To = jid()
+\end{verbatim}
+\end{description}
+
+
+
+\begin{verbatim}
+-module(mod_cputime).
+
+-behaviour(gen_mod).
+
+-export([start/2,
+ stop/1,
+ process_local_iq/3]).
+
+-include("ejabberd.hrl").
+-include("jlib.hrl").
+
+-define(NS_CPUTIME, "ejabberd:cputime").
+
+start(Host, Opts) ->
+ IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_CPUTIME,
+ ?MODULE, process_local_iq, IQDisc).
+
+stop(Host) ->
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_CPUTIME).
+
+process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
+ case Type of
+ set ->
+ {iq, ID, error, XMLNS,
+ [SubEl, ?ERR_NOT_ALLOWED]};
+ get ->
+ CPUTime = element(1, erlang:statistics(runtime))/1000,
+ SCPUTime = lists:flatten(io_lib:format("~.3f", CPUTime)),
+ {iq, ID, result, XMLNS,
+ [{xmlelement, "query",
+ [{"xmlns", ?NS_CPUTIME}],
+ [{xmlelement, "cputime", [], [{xmlcdata, SCPUTime}]}]}]}
+ end.
+\end{verbatim}
+
+
+\subsection{Services}
+\label{sec:services}
+
+%TBD
+
+
+%TODO: use \verb|proc_lib|
+\begin{verbatim}
+-module(mod_echo).
+
+-behaviour(gen_mod).
+
+-export([start/2, init/1, stop/1]).
+
+-include("ejabberd.hrl").
+-include("jlib.hrl").
+
+start(Host, Opts) ->
+ MyHost = gen_mod:get_opt(host, Opts, "echo." ++ Host),
+ register(gen_mod:get_module_proc(Host, ?PROCNAME),
+ spawn(?MODULE, init, [MyHost])).
+
+init(Host) ->
+ ejabberd_router:register_local_route(Host),
+ loop(Host).
+
+loop(Host) ->
+ receive
+ {route, From, To, Packet} ->
+ ejabberd_router:route(To, From, Packet),
+ loop(Host);
+ stop ->
+ ejabberd_router:unregister_route(Host),
+ ok;
+ _ ->
+ loop(Host)
+ end.
+
+stop(Host) ->
+ Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
+ Proc ! stop,
+ {wait, Proc}.
+\end{verbatim}
+
+
+
+\end{document}