diff options
Diffstat (limited to 'ejabberd-1.1.2/doc/dev.tex')
-rw-r--r-- | ejabberd-1.1.2/doc/dev.tex | 398 |
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} |