diff options
author | Alexey Shchepin <alexey@process-one.net> | 2006-01-19 02:17:31 +0000 |
---|---|---|
committer | Alexey Shchepin <alexey@process-one.net> | 2006-01-19 02:17:31 +0000 |
commit | 568909d5bb454fab2023e7ab1a7cf62eff8dcd39 (patch) | |
tree | 562acb2d39d04393e19bda367791a2d8f04e6289 /src/ejabberd_zlib/ejabberd_zlib_drv.c | |
parent | * src/odbc/ejabberd_odbc.erl: Added a way to retry database (diff) |
* src/aclocal.m4: Updated for zlib support
* src/configure.ac: Likewise
* src/mod_muc/mod_muc_room.erl: Weakened presence filtering, added
warning in non-anonymous rooms, room destroying updated to latest
JEP-0045, added a number of occupants and room name in room's
disco#info reply, miscellaneous internal changes (thanks to Sergei
Golovan)
* src/mod_muc/mod_muc.erl: Better support for nick unregistration
(thanks to Sergei Golovan)
* src/ejabberd_zlib/ejabberd_zlib.erl: Zlib support (thanks to
Sergei Golovan)
* src/ejabberd_zlib/ejabberd_zlib_drv.c: Likewise
* src/ejabberd_zlib/Makefile.in: Likewise
* src/ejabberd_c2s.erl: Stream compression support (JEP-0138)
* src/ejabberd_receiver.erl: Likewise
* src/mod_disco.erl: Don't split node name before calling hooks
(thanks to Sergei Golovan)
* src/mod_configure.erl: Support for configuration using ad-hoc
commands (thanks to Sergei Golovan)
* src/mod_announce.erl: Support for sending announce messages
using ad-hoc commands (thanks to Sergei Golovan)
* src/mod_adhoc.erl: Ad-hoc support (JEP-0050) (thanks to Magnus
Henoch)
* src/adhoc.erl: Likewise
* src/adhoc.hrl: Likewise
* src/jlib.hrl: Updated (thanks to Sergei Golovan)
* src/gen_mod.erl: Added function is_loaded/2 (thanks to Sergei
Golovan)
* src/ejabberd_service.erl: Changed error message on handshake
error (thanks to Sergei Golovan)
* src/ejabberd.cfg.example: Updated (thanks to Sergei Golovan)
SVN Revision: 486
Diffstat (limited to 'src/ejabberd_zlib/ejabberd_zlib_drv.c')
-rw-r--r-- | src/ejabberd_zlib/ejabberd_zlib_drv.c | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/ejabberd_zlib/ejabberd_zlib_drv.c b/src/ejabberd_zlib/ejabberd_zlib_drv.c new file mode 100644 index 000000000..075e31176 --- /dev/null +++ b/src/ejabberd_zlib/ejabberd_zlib_drv.c @@ -0,0 +1,171 @@ +/* $Id$ */ + +#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 = 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 = 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 = 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 = 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; +} + + |