25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-22 16:20:52 +01:00

Replace the full ejabberd_zlib into a simple exmpp_compress interface (EJAB-991)

This commit is contained in:
Badlop 2011-09-03 01:04:22 +02:00
parent adc4a7f67c
commit d1f1958dd4
12 changed files with 101 additions and 556 deletions

2
README
View File

@ -12,8 +12,6 @@ To compile ejabberd you need:
Avoid R14A and R14B. Avoid R14A and R14B.
- exmpp 0.9.6 or higher - exmpp 0.9.6 or higher
- OpenSSL 0.9.8 or higher, for STARTTLS, SASL and SSL encryption. - OpenSSL 0.9.8 or higher, for STARTTLS, SASL and SSL encryption.
- Zlib 1.2.3 or higher, for Stream Compression support
(XEP-0138). Optional.
- Erlang mysql library. Optional. MySQL authentication/storage. - Erlang mysql library. Optional. MySQL authentication/storage.
- Erlang pgsql library. Optional. PostgreSQL authentication/storage. - Erlang pgsql library. Optional. PostgreSQL authentication/storage.
- PAM library. Optional. For Pluggable Authentication Modules (PAM). - PAM library. Optional. For Pluggable Authentication Modules (PAM).

View File

@ -318,7 +318,6 @@ To compile \ejabberd{} on a `Unix-like' operating system, you need:
Don't use R14A or R14B because \footahref{http://www.erlang.org/cgi-bin/ezmlm-cgi/4/54598}{they have a bug}. Don't use R14A or R14B because \footahref{http://www.erlang.org/cgi-bin/ezmlm-cgi/4/54598}{they have a bug}.
\item exmpp 0.9.6 or higher \item exmpp 0.9.6 or higher
\item OpenSSL 0.9.8 or higher, for STARTTLS, SASL and SSL encryption. \item OpenSSL 0.9.8 or higher, for STARTTLS, SASL and SSL encryption.
\item Zlib 1.2.3 or higher, for Stream Compression support (\xepref{0138}). Optional.
\item Erlang mysql library. Optional. For MySQL authentication or storage. See section \ref{compilemysql}. \item Erlang mysql library. Optional. For MySQL authentication or storage. See section \ref{compilemysql}.
\item Erlang pgsql library. Optional. For PostgreSQL authentication or storage. See section \ref{compilepgsql}. \item Erlang pgsql library. Optional. For PostgreSQL authentication or storage. See section \ref{compilepgsql}.
\item PAM library. Optional. For Pluggable Authentication Modules (PAM). See section \ref{pam}. \item PAM library. Optional. For Pluggable Authentication Modules (PAM). See section \ref{pam}.
@ -524,7 +523,6 @@ To compile \ejabberd{} on a Microsoft Windows system, you need:
\item \footahref{http://support.process-one.net/doc/display/EXMPP}{exmpp 0.9.5 or higher} \item \footahref{http://support.process-one.net/doc/display/EXMPP}{exmpp 0.9.5 or higher}
\item \footahref{http://www.slproweb.com/products/Win32OpenSSL.html}{Shining Light OpenSSL 0.9.8d or higher} \item \footahref{http://www.slproweb.com/products/Win32OpenSSL.html}{Shining Light OpenSSL 0.9.8d or higher}
(to enable SSL connections) (to enable SSL connections)
\item \footahref{http://www.zlib.net/}{Zlib 1.2.3 or higher}
\end{itemize} \end{itemize}
@ -535,8 +533,6 @@ We assume that we will try to put as much library as possible into \verb|C:\sdk\
\begin{enumerate} \begin{enumerate}
\item Install Erlang emulator (for example, into \verb|C:\sdk\erl5.6.5|). \item Install Erlang emulator (for example, into \verb|C:\sdk\erl5.6.5|).
\item Install OpenSSL in \verb|C:\sdk\OpenSSL| and add \verb|C:\sdk\OpenSSL\lib\VC| to your path or copy the binaries to your system directory. \item Install OpenSSL in \verb|C:\sdk\OpenSSL| and add \verb|C:\sdk\OpenSSL\lib\VC| to your path or copy the binaries to your system directory.
\item Install ZLib in \verb|C:\sdk\gnuWin32|. Copy
\verb|C:\sdk\GnuWin32\bin\zlib1.dll| to your system directory.
\item Make sure the you can access Erlang binaries from your path. For example: \verb|set PATH=%PATH%;"C:\sdk\erl5.6.5\bin"| \item Make sure the you can access Erlang binaries from your path. For example: \verb|set PATH=%PATH%;"C:\sdk\erl5.6.5\bin"|
\item Depending on how you end up actually installing the library you might need to check and tweak the paths in the file configure.erl. \item Depending on how you end up actually installing the library you might need to check and tweak the paths in the file configure.erl.
\item While in the directory \verb|ejabberd\src| run: \item While in the directory \verb|ejabberd\src| run:

View File

@ -72,7 +72,7 @@ endif
prefix = @prefix@ prefix = @prefix@
exec_prefix = @exec_prefix@ exec_prefix = @exec_prefix@
SUBDIRS = stun @mod_pubsub@ @mod_muc@ @mod_proxy65@ @eldap@ @pam@ @web@ @tls@ @odbc@ @ejabberd_zlib@ SUBDIRS = stun @mod_pubsub@ @mod_muc@ @mod_proxy65@ @eldap@ @pam@ @web@ @tls@ @odbc@
ERLSHLIBS = ERLSHLIBS =
ERLBEHAVS = cyrsasl.erl gen_mod.erl p1_fsm.erl ERLBEHAVS = cyrsasl.erl gen_mod.erl p1_fsm.erl
SOURCES_ALL = $(wildcard *.erl) SOURCES_ALL = $(wildcard *.erl)

View File

@ -69,9 +69,6 @@ release : build release_clean
mkdir $(SRC_DIR)\tls mkdir $(SRC_DIR)\tls
copy tls\*.erl $(SRC_DIR)\tls copy tls\*.erl $(SRC_DIR)\tls
copy tls\*.c $(SRC_DIR)\tls copy tls\*.c $(SRC_DIR)\tls
mkdir $(SRC_DIR)\ejabberd_zlib
copy ejabberd_zlib\*.erl $(SRC_DIR)\ejabberd_zlib
copy ejabberd_zlib\*.c $(SRC_DIR)\ejabberd_zlib
mkdir $(SRC_DIR)\web mkdir $(SRC_DIR)\web
copy web\*.erl $(SRC_DIR)\web copy web\*.erl $(SRC_DIR)\web
mkdir $(SRC_DIR)\odbc mkdir $(SRC_DIR)\odbc
@ -103,8 +100,6 @@ all-recursive :
nmake -nologo -f Makefile.win32 nmake -nologo -f Makefile.win32
cd ..\tls cd ..\tls
nmake -nologo -f Makefile.win32 nmake -nologo -f Makefile.win32
cd ..\ejabberd_zlib
nmake -nologo -f Makefile.win32
cd ..\web cd ..\web
nmake -nologo -f Makefile.win32 nmake -nologo -f Makefile.win32
cd ..\odbc cd ..\odbc
@ -142,8 +137,6 @@ clean-recursive :
nmake -nologo -f Makefile.win32 clean nmake -nologo -f Makefile.win32 clean
cd ..\tls cd ..\tls
nmake -nologo -f Makefile.win32 clean nmake -nologo -f Makefile.win32 clean
cd ..\ejabberd_zlib
nmake -nologo -f Makefile.win32 clean
cd ..\web cd ..\web
nmake -nologo -f Makefile.win32 clean nmake -nologo -f Makefile.win32 clean
cd ..\odbc cd ..\odbc

View File

@ -1,39 +1,3 @@
AC_DEFUN([AM_WITH_ZLIB],
[ AC_ARG_WITH(zlib,
[AC_HELP_STRING([--with-zlib=PREFIX], [prefix where zlib is installed])])
if test x"$ejabberd_zlib" != x; then
ZLIB_CFLAGS=
ZLIB_LIBS=
if test x"$with_zlib" != x; then
ZLIB_CFLAGS="-I$with_zlib/include"
ZLIB_LIBS="-L$with_zlib/lib"
fi
AC_CHECK_LIB(z, gzgets,
[ ZLIB_LIBS="$ZLIB_LIBS -lz"
zlib_found=yes ],
[ zlib_found=no ],
"$ZLIB_LIBS")
if test $zlib_found = no; then
AC_MSG_ERROR([Could not find development files of zlib library. Install them or disable `ejabberd_zlib' with: --disable-ejabberd_zlib])
fi
zlib_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $ZLIB_CFLAGS"
zlib_save_CPPFLAGS="$CFLAGS"
CPPFLAGS="$CPPFLAGS $ZLIB_CFLAGS"
AC_CHECK_HEADERS(zlib.h, , zlib_found=no)
if test $zlib_found = no; then
AC_MSG_ERROR([Could not find zlib.h. Install it or disable `ejabberd_zlib' with: --disable-ejabberd_zlib])
fi
CFLAGS="$zlib_save_CFLAGS"
CPPFLAGS="$zlib_save_CPPFLAGS"
AC_SUBST(ZLIB_CFLAGS)
AC_SUBST(ZLIB_LIBS)
fi
])
AC_DEFUN([AM_WITH_PAM], AC_DEFUN([AM_WITH_PAM],
[ AC_ARG_WITH(pam, [ AC_ARG_WITH(pam,
[AC_HELP_STRING([--with-pam=PREFIX], [prefix where PAM is installed])]) [AC_HELP_STRING([--with-pam=PREFIX], [prefix where PAM is installed])])

View File

@ -36,10 +36,6 @@ AC_MOD_ENABLE(odbc, no)
AC_MOD_ENABLE(tls, yes) AC_MOD_ENABLE(tls, yes)
AC_MOD_ENABLE(web, yes) AC_MOD_ENABLE(web, yes)
AC_MOD_ENABLE(ejabberd_zlib, yes)
#locating zlib
AM_WITH_ZLIB
AC_MOD_ENABLE(pam, no) AC_MOD_ENABLE(pam, no)
#locating PAM #locating PAM
AM_WITH_PAM AM_WITH_PAM
@ -107,8 +103,7 @@ AC_CONFIG_FILES([Makefile
$make_web $make_web
stun/Makefile stun/Makefile
$make_tls $make_tls
$make_odbc $make_odbc])
$make_ejabberd_zlib])
#openssl #openssl
AM_WITH_OPENSSL AM_WITH_OPENSSL
# If ssl is kerberized it need krb5.h # If ssl is kerberized it need krb5.h

View File

@ -48,7 +48,6 @@
ejabberd_update, ejabberd_update,
ejabberd_web_admin, ejabberd_web_admin,
ejabberd_web, ejabberd_web,
ejabberd_zlib,
ejd2odbc, ejd2odbc,
eldap, eldap,
eldap_filter, eldap_filter,

99
src/ejabberd_zlib.erl Normal file
View File

@ -0,0 +1,99 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_zlib.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>
%%% Purpose : Interface to exmpp_compress
%%% Created : 19 Jan 2006 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
%%% published by the Free Software Foundation; either version 2 of the
%%% License, or (at your option) any later version.
%%%
%%% This program is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%%% General Public License for more details.
%%%
%%% You should have received a copy of the GNU General Public License
%%% along with this program; if not, write to the Free Software
%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
%%% 02111-1307 USA
%%%
%%%----------------------------------------------------------------------
-module(ejabberd_zlib).
-author('alexey@process-one.net').
-export([start/0, start_link/0,
enable_zlib/2, disable_zlib/1,
send/2,
recv/2, recv/3, recv_data/2,
setopts/2,
get_sockmod/1,
sockname/1, peername/1,
controlling_process/2,
close/1]).
-define(DEFLATE, 1).
-define(INFLATE, 2).
start() ->
exmpp_compress:start().
start_link() ->
exmpp_compress:start_link().
enable_zlib(SockMod, Socket) ->
try
ZlibSock = exmpp_compress:enable_compression({SockMod, Socket},
[{compress_method, zlib}]),
{ok, ZlibSock}
catch
Exception ->
{error, Exception}
end.
disable_zlib(ZlibSock) ->
exmpp_compress:disable_compression(ZlibSock).
recv(Socket, Length) ->
recv(Socket, Length, infinity).
recv(ZlibSock, _Length, Timeout) ->
exmpp_compress:recv(ZlibSock, Timeout).
recv_data(ZlibSock, Packet) ->
exmpp_compress:recv_data(ZlibSock, Packet).
send(ZlibSock, Packet) ->
exmpp_compress:send(ZlibSock, Packet).
setopts(ZlibSock, Opts) ->
exmpp_compress:setopts(ZlibSock, Opts).
%% Copied from exmpp/src/core/exmpp_compress.erl
-record(compress_socket, {socket,
packet_mode = binary,
port
}).
get_sockmod(#compress_socket{socket = {SockMod, _Port}}) ->
SockMod.
sockname(ZlibSock) ->
exmpp_compress:sockname(ZlibSock).
peername(ZlibSock) ->
exmpp_compress:peername(ZlibSock).
controlling_process(ZlibSock, Pid) ->
exmpp_compress:controlling_process(ZlibSock, Pid).
close(ZlibSock) ->
exmpp_compress:close(ZlibSock).

View File

@ -1,81 +0,0 @@
CC = @CC@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
ZLIB_CFLAGS = @ZLIB_CFLAGS@
ZLIB_LIBS = @ZLIB_LIBS@
ERLANG_CFLAGS = @ERLANG_CFLAGS@
ERLANG_LIBS = @ERLANG_LIBS@
# Assume Linux-style dynamic library flags
DYNAMIC_LIB_CFLAGS = -fpic -shared
ifeq ($(shell uname),Darwin)
DYNAMIC_LIB_CFLAGS = -fPIC -bundle -flat_namespace -undefined suppress
endif
ifeq ($(shell uname),SunOs)
DYNAMIC_LIB_CFLAGS = -KPIC -G -z text
endif
EFLAGS += -I ..
EFLAGS += -pz ..
# make debug=true to compile Erlang module with debug informations.
ifdef debug
EFLAGS+=+debug_info +export_all
endif
ERLSHLIBS = ../ejabberd_zlib_drv.so
OUTDIR = ..
SOURCES = $(wildcard *.erl)
BEAMS = $(addprefix $(OUTDIR)/,$(SOURCES:.erl=.beam))
all: $(BEAMS) $(ERLSHLIBS)
$(OUTDIR)/%.beam: %.erl
@ERLC@ -W $(EFLAGS) -o $(OUTDIR) $<
#all: $(ERLSHLIBS)
# erl -s make all report "{outdir, \"..\"}" -noinput -s erlang halt
$(ERLSHLIBS): ../%.so: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) \
$(subst ../,,$(subst .so,.c,$@)) \
$(LIBS) \
$(ZLIB_LIBS) \
$(ZLIB_CFLAGS) \
$(ERLANG_LIBS) \
$(ERLANG_CFLAGS) \
-o $@ \
$(DYNAMIC_LIB_CFLAGS)
clean:
rm -f $(BEAMS) $(ERLSHLIBS)
distclean: clean
rm -f Makefile
TAGS:
etags *.erl
DEVDOCDIR=../../doc/devdoc
DDTDIR=..
HTMLS = $(SOURCES:%.erl=../../doc/devdoc/%.html)
ERLHTMLS = $(SOURCES:%.erl=../../doc/devdoc/%.erl.html)
SVGS = $(SOURCES:%.erl=../../doc/devdoc/%.svg)
devdoc: $(HTMLS) $(ERLHTMLS) $(SVGS)
$(DEVDOCDIR)/%.erl.html: %.erl
@ERL@ -noshell -pa $(DEVDOCDIR) -run escobar_run file $< $(DDTDIR) -s init stop
$(DEVDOCDIR)/%.html: %.erl
@ERL@ -noshell -run edoc_run file $< \
'[{dir,"$(DDTDIR)"},{packages,false},{todo,true},{private,true},{def,{vsn,"$(VSN)"}},{stylesheet,"process-one.css"},{overview,"overview.edoc"}]' -s init stop
$(DEVDOCDIR)/%.svg: %.erl
@ERL@ -noshell -pa $(DEVDOCDIR) -run funrelg dir $< $(DDTDIR) -s init stop

View File

@ -1,36 +0,0 @@
include ..\Makefile.inc
EFLAGS = -I .. -pz ..
OUTDIR = ..
BEAMS = ..\ejabberd_zlib.beam
SOURCE = ejabberd_zlib_drv.c
OBJECT = ejabberd_zlib_drv.o
DLL = $(OUTDIR)\ejabberd_zlib_drv.dll
ALL : $(DLL) $(BEAMS)
CLEAN :
-@erase $(DLL)
-@erase $(OUTDIR)\ejabberd_zlib_drv.exp
-@erase $(OUTDIR)\ejabberd_zlib_drv.lib
-@erase $(OBJECT)
-@erase $(BEAMS)
$(OUTDIR)\ejabberd_zlib.beam : ejabberd_zlib.erl
erlc -W $(EFLAGS) -o $(OUTDIR) ejabberd_zlib.erl
CC=cl.exe
CC_FLAGS=-nologo -D__WIN32__ -DWIN32 -DWINDOWS -D_WIN32 -DNT -MD -Ox -I"$(ERLANG_DIR)\usr\include" -I"$(EI_DIR)\include" -I"$(ZLIB_DIR)\include"
LD=link.exe
LD_FLAGS=-release -nologo -incremental:no -dll "$(EI_DIR)\lib\ei_md.lib" "$(EI_DIR)\lib\erl_interface_md.lib" "$(ZLIB_LIB)" MSVCRT.LIB kernel32.lib advapi32.lib gdi32.lib user32.lib comctl32.lib comdlg32.lib shell32.lib
$(DLL) : $(OBJECT)
$(LD) $(LD_FLAGS) -out:$(DLL) $(OBJECT)
$(OBJECT) : $(SOURCE)
$(CC) $(CC_FLAGS) -c -Fo$(OBJECT) $(SOURCE)

View File

@ -1,193 +0,0 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_zlib.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>
%%% Purpose : Interface to zlib
%%% Created : 19 Jan 2006 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
%%% published by the Free Software Foundation; either version 2 of the
%%% License, or (at your option) any later version.
%%%
%%% This program is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%%% General Public License for more details.
%%%
%%% You should have received a copy of the GNU General Public License
%%% along with this program; if not, write to the Free Software
%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
%%% 02111-1307 USA
%%%
%%%----------------------------------------------------------------------
-module(ejabberd_zlib).
-author('alexey@process-one.net').
-behaviour(gen_server).
-export([start/0, start_link/0,
enable_zlib/2, disable_zlib/1,
send/2,
recv/2, recv/3, recv_data/2,
setopts/2,
sockname/1, peername/1,
get_sockmod/1,
controlling_process/2,
close/1]).
%% Internal exports, call-back functions.
-export([init/1,
handle_call/3,
handle_cast/2,
handle_info/2,
code_change/3,
terminate/2]).
-define(DEFLATE, 1).
-define(INFLATE, 2).
-record(zlibsock, {sockmod, socket, zlibport}).
start() ->
gen_server:start({local, ?MODULE}, ?MODULE, [], []).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
init([]) ->
case erl_ddll:load_driver(ejabberd:get_so_path(), ejabberd_zlib_drv) of
ok -> ok;
{error, already_loaded} -> ok
end,
Port = open_port({spawn, "ejabberd_zlib_drv"}, [binary]),
{ok, Port}.
%%% --------------------------------------------------------
%%% The call-back functions.
%%% --------------------------------------------------------
handle_call(_, _, State) ->
{noreply, State}.
handle_cast(_, State) ->
{noreply, State}.
handle_info({'EXIT', Port, Reason}, Port) ->
{stop, {port_died, Reason}, Port};
handle_info({'EXIT', _Pid, _Reason}, Port) ->
{noreply, Port};
handle_info(_, State) ->
{noreply, State}.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
terminate(_Reason, Port) ->
Port ! {self, close},
ok.
enable_zlib(SockMod, Socket) ->
case erl_ddll:load_driver(ejabberd:get_so_path(), ejabberd_zlib_drv) of
ok -> ok;
{error, already_loaded} -> ok
end,
Port = open_port({spawn, "ejabberd_zlib_drv"}, [binary]),
{ok, #zlibsock{sockmod = SockMod, socket = Socket, zlibport = Port}}.
disable_zlib(#zlibsock{sockmod = SockMod, socket = Socket, zlibport = Port}) ->
port_close(Port),
{SockMod, Socket}.
recv(Socket, Length) ->
recv(Socket, Length, infinity).
recv(#zlibsock{sockmod = SockMod, socket = Socket} = ZlibSock,
Length, Timeout) ->
case SockMod:recv(Socket, Length, Timeout) of
{ok, Packet} ->
recv_data(ZlibSock, Packet);
{error, _Reason} = Error ->
Error
end.
recv_data(#zlibsock{sockmod = SockMod, socket = Socket} = ZlibSock, Packet) ->
case SockMod of
gen_tcp ->
recv_data2(ZlibSock, Packet);
_ ->
case SockMod:recv_data(Socket, Packet) of
{ok, Packet2} ->
recv_data2(ZlibSock, Packet2);
Error ->
Error
end
end.
recv_data2(ZlibSock, Packet) ->
case catch recv_data1(ZlibSock, Packet) of
{'EXIT', Reason} ->
{error, Reason};
Res ->
Res
end.
recv_data1(#zlibsock{zlibport = Port} = _ZlibSock, Packet) ->
case port_control(Port, ?INFLATE, Packet) of
<<0, In/binary>> ->
{ok, In};
<<1, Error/binary>> ->
{error, binary_to_list(Error)}
end.
send(#zlibsock{sockmod = SockMod, socket = Socket, zlibport = Port},
Packet) ->
case port_control(Port, ?DEFLATE, Packet) of
<<0, Out/binary>> ->
SockMod:send(Socket, Out);
<<1, Error/binary>> ->
{error, binary_to_list(Error)}
end.
setopts(#zlibsock{sockmod = SockMod, socket = Socket}, Opts) ->
case SockMod of
gen_tcp ->
inet:setopts(Socket, Opts);
_ ->
SockMod:setopts(Socket, Opts)
end.
sockname(#zlibsock{sockmod = SockMod, socket = Socket}) ->
case SockMod of
gen_tcp ->
inet:sockname(Socket);
_ ->
SockMod:sockname(Socket)
end.
get_sockmod(#zlibsock{sockmod = SockMod}) ->
SockMod.
peername(#zlibsock{sockmod = SockMod, socket = Socket}) ->
case SockMod of
gen_tcp ->
inet:peername(Socket);
_ ->
SockMod:peername(Socket)
end.
controlling_process(#zlibsock{sockmod = SockMod, socket = Socket}, Pid) ->
SockMod:controlling_process(Socket, Pid).
close(#zlibsock{sockmod = SockMod, socket = Socket, zlibport = Port}) ->
SockMod:close(Socket),
port_close(Port).

View File

@ -1,189 +0,0 @@
/*
* ejabberd, Copyright (C) 2002-2011 ProcessOne
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
*/
#include <stdio.h>
#include <string.h>
#include <erl_driver.h>
#include <zlib.h>
#define BUF_SIZE 1024
typedef struct {
ErlDrvPort port;
z_stream *d_stream;
z_stream *i_stream;
} ejabberd_zlib_data;
static ErlDrvData ejabberd_zlib_drv_start(ErlDrvPort port, char *buff)
{
ejabberd_zlib_data *d =
(ejabberd_zlib_data *)driver_alloc(sizeof(ejabberd_zlib_data));
d->port = port;
d->d_stream = (z_stream *)malloc(sizeof(z_stream));
d->d_stream->zalloc = (alloc_func)0;
d->d_stream->zfree = (free_func)0;
d->d_stream->opaque = (voidpf)0;
deflateInit(d->d_stream, Z_DEFAULT_COMPRESSION);
d->i_stream = (z_stream *)malloc(sizeof(z_stream));
d->i_stream->zalloc = (alloc_func)0;
d->i_stream->zfree = (free_func)0;
d->i_stream->opaque = (voidpf)0;
inflateInit(d->i_stream);
set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
return (ErlDrvData)d;
}
static void ejabberd_zlib_drv_stop(ErlDrvData handle)
{
ejabberd_zlib_data *d = (ejabberd_zlib_data *)handle;
deflateEnd(d->d_stream);
free(d->d_stream);
inflateEnd(d->i_stream);
free(d->i_stream);
driver_free((char *)handle);
}
#define DEFLATE 1
#define INFLATE 2
#define die_unless(cond, errstr) \
if (!(cond)) \
{ \
rlen = strlen(errstr) + 1; \
b = driver_realloc_binary(b, rlen); \
b->orig_bytes[0] = 1; \
strncpy(b->orig_bytes + 1, errstr, rlen - 1); \
*rbuf = (char *)b; \
return rlen; \
}
static int ejabberd_zlib_drv_control(ErlDrvData handle,
unsigned int command,
char *buf, int len,
char **rbuf, int rlen)
{
ejabberd_zlib_data *d = (ejabberd_zlib_data *)handle;
int err;
int size;
ErlDrvBinary *b;
switch (command)
{
case DEFLATE:
size = BUF_SIZE + 1;
rlen = 1;
b = driver_alloc_binary(size);
b->orig_bytes[0] = 0;
d->d_stream->next_in = (unsigned char *)buf;
d->d_stream->avail_in = len;
d->d_stream->avail_out = 0;
err = Z_OK;
while (err == Z_OK && d->d_stream->avail_out == 0)
{
d->d_stream->next_out = (unsigned char *)b->orig_bytes + rlen;
d->d_stream->avail_out = BUF_SIZE;
err = deflate(d->d_stream, Z_SYNC_FLUSH);
die_unless((err == Z_OK) || (err == Z_STREAM_END),
"Deflate error");
rlen += (BUF_SIZE - d->d_stream->avail_out);
size += (BUF_SIZE - d->d_stream->avail_out);
b = driver_realloc_binary(b, size);
}
b = driver_realloc_binary(b, rlen);
*rbuf = (char *)b;
return rlen;
case INFLATE:
size = BUF_SIZE + 1;
rlen = 1;
b = driver_alloc_binary(size);
b->orig_bytes[0] = 0;
if (len > 0) {
d->i_stream->next_in = (unsigned char *)buf;
d->i_stream->avail_in = len;
d->i_stream->avail_out = 0;
err = Z_OK;
while (err == Z_OK && d->i_stream->avail_out == 0)
{
d->i_stream->next_out = (unsigned char *)b->orig_bytes + rlen;
d->i_stream->avail_out = BUF_SIZE;
err = inflate(d->i_stream, Z_SYNC_FLUSH);
die_unless((err == Z_OK) || (err == Z_STREAM_END),
"Inflate error");
rlen += (BUF_SIZE - d->i_stream->avail_out);
size += (BUF_SIZE - d->i_stream->avail_out);
b = driver_realloc_binary(b, size);
}
}
b = driver_realloc_binary(b, rlen);
*rbuf = (char *)b;
return rlen;
}
b = driver_alloc_binary(1);
b->orig_bytes[0] = 0;
*rbuf = (char *)b;
return 1;
}
ErlDrvEntry ejabberd_zlib_driver_entry = {
NULL, /* F_PTR init, N/A */
ejabberd_zlib_drv_start, /* L_PTR start, called when port is opened */
ejabberd_zlib_drv_stop, /* F_PTR stop, called when port is closed */
NULL, /* F_PTR output, called when erlang has sent */
NULL, /* F_PTR ready_input, called when input descriptor ready */
NULL, /* F_PTR ready_output, called when output descriptor ready */
"ejabberd_zlib_drv", /* char *driver_name, the argument to open_port */
NULL, /* F_PTR finish, called when unloaded */
NULL, /* handle */
ejabberd_zlib_drv_control, /* F_PTR control, port_command callback */
NULL, /* F_PTR timeout, reserved */
NULL /* F_PTR outputv, reserved */
};
DRIVER_INIT(ejabberd_zlib_drv) /* must match name in driver_entry */
{
return &ejabberd_zlib_driver_entry;
}