]> granicus.if.org Git - ejabberd/commitdiff
Add SQL as mod_bosh RAM backend
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>
Tue, 28 Mar 2017 17:33:57 +0000 (20:33 +0300)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Tue, 28 Mar 2017 17:33:57 +0000 (20:33 +0300)
sql/lite.sql
sql/mssql.sql
sql/mysql.sql
sql/pg.sql
src/mod_bosh_sql.erl [new file with mode: 0644]

index bc6a6e7066973a23b34eecfd4154dffeae1c1040..c17d80ec53f5aae4559af22e31aadda3ca016e4e 100644 (file)
@@ -330,3 +330,11 @@ CREATE TABLE route (
 
 CREATE UNIQUE INDEX i_route ON route(domain, server_host, node, pid);
 CREATE INDEX i_route_domain ON route(domain);
+
+CREATE TABLE bosh (
+    sid text NOT NULL,
+    node text NOT NULL,
+    pid text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_bosh_sid ON bosh(sid);
index 06f73aea91397bc96429fe088daca6a2ae7ddf55..7535da5acf685a8e5325365b63a11d934cbc43db 100644 (file)
@@ -504,3 +504,13 @@ WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW
 \r
 CREATE INDEX [route_domain] ON [route] (domain)\r
 WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);\r
+\r
+CREATE TABLE [dbo].[bosh] (\r
+    [sid] [varchar] (255) NOT NULL,\r
+    [node] [varchar] (255) NOT NULL,\r
+    [pid] [varchar](100) NOT NULL\r
+ CONSTRAINT [bosh_PRIMARY] PRIMARY KEY CLUSTERED \r
+(\r
+        [sid] ASC\r
+)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)\r
+) TEXTIMAGE_ON [PRIMARY];\r
index c4f3d1f0203ba93d83b0be21e3250a2b6f78b9fb..982df7ff539280d0be4efa9966c5606f8da46cac 100644 (file)
@@ -346,3 +346,11 @@ CREATE TABLE route (
 
 CREATE UNIQUE INDEX i_route ON route(domain(75), server_host(75), node(75), pid(75));
 CREATE INDEX i_route_domain ON route(domain(75));
+
+CREATE TABLE bosh (
+    sid text NOT NULL,
+    node text NOT NULL,
+    pid text NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_bosh_sid ON bosh(sid(75));
index fac806e8a6548ba64771332d0677b4478c05095b..8a8b77b1fb4f875bd4ec5e579bb4b394b7e0c357 100644 (file)
@@ -350,3 +350,11 @@ CREATE TABLE route (
 
 CREATE UNIQUE INDEX i_route ON route USING btree (domain, server_host, node, pid);
 CREATE INDEX i_route_domain ON route USING btree (domain);
+
+CREATE TABLE bosh (
+    sid text NOT NULL,
+    node text NOT NULL,
+    pid text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_bosh_sid ON bosh USING btree (sid);
diff --git a/src/mod_bosh_sql.erl b/src/mod_bosh_sql.erl
new file mode 100644 (file)
index 0000000..05df4dc
--- /dev/null
@@ -0,0 +1,98 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2017, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 28 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(mod_bosh_sql).
+-behaviour(mod_bosh).
+
+-compile([{parse_transform, ejabberd_sql_pt}]).
+
+%% API
+-export([init/0, open_session/2, close_session/1, find_session/1]).
+
+-include("ejabberd.hrl").
+-include("logger.hrl").
+-include("ejabberd_sql_pt.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+init() ->
+    Node = erlang:atom_to_binary(node(), latin1),
+    ?INFO_MSG("Cleaning SQL 'bosh' table...", []),
+    case ejabberd_sql:sql_query(
+          ?MYNAME, ?SQL("delete from bosh where node=%(Node)s")) of
+       {updated, _} ->
+           ok;
+       Err ->
+           ?ERROR_MSG("failed to clean 'route' table: ~p", [Err]),
+           Err
+    end.
+
+open_session(SID, Pid) ->
+    PidS = enc_pid(Pid),
+    Node = erlang:atom_to_binary(node(Pid), latin1),
+    case ?SQL_UPSERT(?MYNAME, "bosh",
+                    ["!sid=%(SID)s",
+                     "node=%(Node)s",
+                     "pid=%(PidS)s"]) of
+       ok ->
+           ok;
+       Err ->
+           ?ERROR_MSG("failed to update 'bosh' table: ~p", [Err]),
+           {error, Err}
+    end.
+
+close_session(SID) ->
+    %% TODO: report errors
+    ejabberd_sql:sql_query(
+      ?MYNAME, ?SQL("delete from bosh where sid=%(SID)s")).
+
+find_session(SID) ->
+    case ejabberd_sql:sql_query(
+          ?MYNAME,
+          ?SQL("select @(pid)s, @(node)s from bosh where sid=%(SID)s")) of
+       {selected, [{Pid, Node}]} ->
+           try {ok, dec_pid(Pid, Node)}
+           catch _:{node_down, _} -> error
+           end;
+       {selected, []} ->
+           error;
+       Err ->
+           ?ERROR_MSG("failed to select 'bosh' table: ~p", [Err]),
+           error
+    end.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+-spec enc_pid(pid()) -> binary().
+enc_pid(Pid) ->
+    list_to_binary(erlang:pid_to_list(Pid)).
+
+-spec dec_pid(binary(), binary()) -> pid().
+dec_pid(PidBin, NodeBin) ->
+    PidStr = binary_to_list(PidBin),
+    Pid = erlang:list_to_pid(PidStr),
+    case erlang:binary_to_atom(NodeBin, latin1) of
+       Node when Node == node() ->
+           Pid;
+       Node ->
+           try set_node_id(PidStr, NodeBin)
+           catch _:badarg ->
+                   erlang:error({node_down, Node})
+           end
+    end.
+
+-spec set_node_id(string(), binary()) -> pid().
+set_node_id(PidStr, NodeBin) ->
+    ExtPidStr = erlang:pid_to_list(
+                 binary_to_term(
+                   <<131,103,100,(size(NodeBin)):16,NodeBin/binary,0:72>>)),
+    [H|_] = string:tokens(ExtPidStr, "."),
+    [_|T] = string:tokens(PidStr, "."),
+    erlang:list_to_pid(string:join([H|T], ".")).