aboutsummaryrefslogtreecommitdiff
path: root/src/ejabberd_zlib/ejabberd_zlib_drv.c
diff options
context:
space:
mode:
authorAlexey Shchepin <alexey@process-one.net>2006-01-19 02:17:31 +0000
committerAlexey Shchepin <alexey@process-one.net>2006-01-19 02:17:31 +0000
commit568909d5bb454fab2023e7ab1a7cf62eff8dcd39 (patch)
tree562acb2d39d04393e19bda367791a2d8f04e6289 /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.c171
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;
+}
+
+