added support for IMAP DEFLATE
initial patch by Jesse Weaver <pianohacker@gmail.com>, but mostly rewritten by me.
This commit is contained in:
parent
f0b80e7d35
commit
139b90be29
2
NEWS
2
NEWS
|
@ -10,6 +10,8 @@ Support for SASL (flexible authentication) has been added.
|
||||||
|
|
||||||
Support for Windows file systems has been added.
|
Support for Windows file systems has been added.
|
||||||
|
|
||||||
|
Support for compressed data transfer has been added.
|
||||||
|
|
||||||
[1.1.0]
|
[1.1.0]
|
||||||
|
|
||||||
Support for hierarchical mailboxes in Patterns.
|
Support for hierarchical mailboxes in Patterns.
|
||||||
|
|
14
configure.ac
14
configure.ac
|
@ -150,6 +150,15 @@ if test "x$ac_cv_berkdb4" = xno; then
|
||||||
AC_MSG_ERROR([Berkley DB >= 4.2 not found.])
|
AC_MSG_ERROR([Berkley DB >= 4.2 not found.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
have_zlib=
|
||||||
|
AC_CHECK_LIB([z], [deflate],
|
||||||
|
[AC_CHECK_HEADER(zlib.h,
|
||||||
|
[have_zlib=1
|
||||||
|
AC_SUBST([Z_LIBS], ["-lz"])
|
||||||
|
AC_DEFINE([HAVE_LIBZ], 1, [if you have the zlib library])]
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
|
||||||
AC_ARG_ENABLE(compat,
|
AC_ARG_ENABLE(compat,
|
||||||
AC_HELP_STRING([--disable-compat], [don't include isync compatibility wrapper [no]]),
|
AC_HELP_STRING([--disable-compat], [don't include isync compatibility wrapper [no]]),
|
||||||
[ob_cv_enable_compat=$enableval])
|
[ob_cv_enable_compat=$enableval])
|
||||||
|
@ -172,4 +181,9 @@ if test -n "$have_sasl_paths"; then
|
||||||
else
|
else
|
||||||
AC_MSG_RESULT([Not using SASL])
|
AC_MSG_RESULT([Not using SASL])
|
||||||
fi
|
fi
|
||||||
|
if test -n "$have_zlib"; then
|
||||||
|
AC_MSG_RESULT([Using zlib])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([Not using zlib])
|
||||||
|
fi
|
||||||
AC_MSG_RESULT()
|
AC_MSG_RESULT()
|
||||||
|
|
|
@ -6,7 +6,7 @@ SUBDIRS = $(compat_dir)
|
||||||
bin_PROGRAMS = mbsync mdconvert
|
bin_PROGRAMS = mbsync mdconvert
|
||||||
|
|
||||||
mbsync_SOURCES = main.c sync.c config.c util.c socket.c driver.c drv_imap.c drv_maildir.c
|
mbsync_SOURCES = main.c sync.c config.c util.c socket.c driver.c drv_imap.c drv_maildir.c
|
||||||
mbsync_LDADD = -ldb $(SSL_LIBS) $(SOCK_LIBS) $(SASL_LIBS)
|
mbsync_LDADD = -ldb $(SSL_LIBS) $(SOCK_LIBS) $(SASL_LIBS) $(Z_LIBS)
|
||||||
noinst_HEADERS = common.h config.h driver.h sync.h socket.h
|
noinst_HEADERS = common.h config.h driver.h sync.h socket.h
|
||||||
|
|
||||||
mdconvert_SOURCES = mdconvert.c
|
mdconvert_SOURCES = mdconvert.c
|
||||||
|
|
|
@ -196,7 +196,8 @@ enum CAPABILITY {
|
||||||
UIDPLUS,
|
UIDPLUS,
|
||||||
LITERALPLUS,
|
LITERALPLUS,
|
||||||
MOVE,
|
MOVE,
|
||||||
NAMESPACE
|
NAMESPACE,
|
||||||
|
COMPRESS_DEFLATE
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *cap_list[] = {
|
static const char *cap_list[] = {
|
||||||
|
@ -210,7 +211,8 @@ static const char *cap_list[] = {
|
||||||
"UIDPLUS",
|
"UIDPLUS",
|
||||||
"LITERAL+",
|
"LITERAL+",
|
||||||
"MOVE",
|
"MOVE",
|
||||||
"NAMESPACE"
|
"NAMESPACE",
|
||||||
|
"COMPRESS=DEFLATE"
|
||||||
};
|
};
|
||||||
|
|
||||||
#define RESP_OK 0
|
#define RESP_OK 0
|
||||||
|
@ -1486,6 +1488,9 @@ static void imap_open_store_authenticate2_p2( imap_store_t *, struct imap_cmd *,
|
||||||
static void imap_open_store_namespace( imap_store_t * );
|
static void imap_open_store_namespace( imap_store_t * );
|
||||||
static void imap_open_store_namespace_p2( imap_store_t *, struct imap_cmd *, int );
|
static void imap_open_store_namespace_p2( imap_store_t *, struct imap_cmd *, int );
|
||||||
static void imap_open_store_namespace2( imap_store_t * );
|
static void imap_open_store_namespace2( imap_store_t * );
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
static void imap_open_store_compress_p2( imap_store_t *, struct imap_cmd *, int );
|
||||||
|
#endif
|
||||||
static void imap_open_store_finalize( imap_store_t * );
|
static void imap_open_store_finalize( imap_store_t * );
|
||||||
#ifdef HAVE_LIBSSL
|
#ifdef HAVE_LIBSSL
|
||||||
static void imap_open_store_ssl_bail( imap_store_t * );
|
static void imap_open_store_ssl_bail( imap_store_t * );
|
||||||
|
@ -2041,12 +2046,32 @@ imap_open_store_namespace2( imap_store_t *ctx )
|
||||||
ctx->prefix = nsp_1st_ns->val;
|
ctx->prefix = nsp_1st_ns->val;
|
||||||
if (!ctx->delimiter)
|
if (!ctx->delimiter)
|
||||||
ctx->delimiter = nfstrdup( nsp_1st_dl->val );
|
ctx->delimiter = nfstrdup( nsp_1st_dl->val );
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
if (CAP(COMPRESS_DEFLATE)) { /* XXX make that configurable */
|
||||||
|
imap_exec( ctx, 0, imap_open_store_compress_p2, "COMPRESS DEFLATE" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
imap_open_store_finalize( ctx );
|
imap_open_store_finalize( ctx );
|
||||||
} else {
|
} else {
|
||||||
imap_open_store_bail( ctx );
|
imap_open_store_bail( ctx );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
static void
|
||||||
|
imap_open_store_compress_p2( imap_store_t *ctx, struct imap_cmd *cmd ATTR_UNUSED, int response )
|
||||||
|
{
|
||||||
|
if (response == RESP_NO) {
|
||||||
|
/* We already reported an error, but it's not fatal to us. */
|
||||||
|
imap_open_store_finalize( ctx );
|
||||||
|
} else if (response == RESP_OK) {
|
||||||
|
socket_start_deflate( &ctx->conn );
|
||||||
|
imap_open_store_finalize( ctx );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
imap_open_store_finalize( imap_store_t *ctx )
|
imap_open_store_finalize( imap_store_t *ctx )
|
||||||
{
|
{
|
||||||
|
|
232
src/socket.c
232
src/socket.c
|
@ -280,6 +280,43 @@ static void start_tls_p3( conn_t *conn, int ok )
|
||||||
|
|
||||||
#endif /* HAVE_LIBSSL */
|
#endif /* HAVE_LIBSSL */
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
|
||||||
|
static void z_fake_cb( void * );
|
||||||
|
|
||||||
|
void
|
||||||
|
socket_start_deflate( conn_t *conn )
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
conn->in_z = nfcalloc( sizeof(*conn->in_z) );
|
||||||
|
result = inflateInit2(
|
||||||
|
conn->in_z,
|
||||||
|
-15 /* Use raw deflate */
|
||||||
|
);
|
||||||
|
if (result != Z_OK) {
|
||||||
|
error( "Fatal: Cannot initialize decompression: %s\n", conn->in_z->msg );
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->out_z = nfcalloc( sizeof(*conn->out_z) );
|
||||||
|
result = deflateInit2(
|
||||||
|
conn->out_z,
|
||||||
|
Z_DEFAULT_COMPRESSION, /* Compression level */
|
||||||
|
Z_DEFLATED, /* Only valid value */
|
||||||
|
-15, /* Use raw deflate */
|
||||||
|
8, /* Default memory usage */
|
||||||
|
Z_DEFAULT_STRATEGY /* Don't try to do anything fancy */
|
||||||
|
);
|
||||||
|
if (result != Z_OK) {
|
||||||
|
error( "Fatal: Cannot initialize compression: %s\n", conn->out_z->msg );
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
init_wakeup( &conn->z_fake, z_fake_cb, conn );
|
||||||
|
}
|
||||||
|
#endif /* HAVE_LIBZ */
|
||||||
|
|
||||||
static void socket_fd_cb( int, void * );
|
static void socket_fd_cb( int, void * );
|
||||||
static void socket_fake_cb( void * );
|
static void socket_fake_cb( void * );
|
||||||
|
|
||||||
|
@ -500,6 +537,17 @@ socket_close( conn_t *sock )
|
||||||
sock->ssl = 0;
|
sock->ssl = 0;
|
||||||
wipe_wakeup( &sock->ssl_fake );
|
wipe_wakeup( &sock->ssl_fake );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
if (sock->in_z) {
|
||||||
|
inflateEnd( sock->in_z );
|
||||||
|
free( sock->in_z );
|
||||||
|
sock->in_z = 0;
|
||||||
|
deflateEnd( sock->out_z );
|
||||||
|
free( sock->out_z );
|
||||||
|
sock->out_z = 0;
|
||||||
|
wipe_wakeup( &sock->z_fake );
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
while (sock->write_buf)
|
while (sock->write_buf)
|
||||||
dispose_chunk( sock );
|
dispose_chunk( sock );
|
||||||
|
@ -507,23 +555,30 @@ socket_close( conn_t *sock )
|
||||||
sock->append_buf = 0;
|
sock->append_buf = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
socket_fill( conn_t *sock )
|
prepare_read( conn_t *sock, char **buf, int *len )
|
||||||
{
|
{
|
||||||
char *buf;
|
|
||||||
int n = sock->offset + sock->bytes;
|
int n = sock->offset + sock->bytes;
|
||||||
int len = sizeof(sock->buf) - n;
|
if (!(*len = sizeof(sock->buf) - n)) {
|
||||||
if (!len) {
|
|
||||||
error( "Socket error: receive buffer full. Probably protocol error.\n" );
|
error( "Socket error: receive buffer full. Probably protocol error.\n" );
|
||||||
socket_fail( sock );
|
socket_fail( sock );
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
*buf = sock->buf + n;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_read( conn_t *sock, char *buf, int len )
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
assert( sock->fd >= 0 );
|
assert( sock->fd >= 0 );
|
||||||
buf = sock->buf + n;
|
|
||||||
#ifdef HAVE_LIBSSL
|
#ifdef HAVE_LIBSSL
|
||||||
if (sock->ssl) {
|
if (sock->ssl) {
|
||||||
if ((n = ssl_return( "read from", sock, SSL_read( sock->ssl, buf, len ) )) <= 0)
|
if ((n = ssl_return( "read from", sock, SSL_read( sock->ssl, buf, len ) )) <= 0)
|
||||||
return;
|
return n;
|
||||||
|
|
||||||
if (n == len && SSL_pending( sock->ssl ))
|
if (n == len && SSL_pending( sock->ssl ))
|
||||||
conf_wakeup( &sock->ssl_fake, 0 );
|
conf_wakeup( &sock->ssl_fake, 0 );
|
||||||
} else
|
} else
|
||||||
|
@ -532,16 +587,72 @@ socket_fill( conn_t *sock )
|
||||||
if ((n = read( sock->fd, buf, len )) < 0) {
|
if ((n = read( sock->fd, buf, len )) < 0) {
|
||||||
sys_error( "Socket error: read from %s", sock->name );
|
sys_error( "Socket error: read from %s", sock->name );
|
||||||
socket_fail( sock );
|
socket_fail( sock );
|
||||||
return;
|
|
||||||
} else if (!n) {
|
} else if (!n) {
|
||||||
error( "Socket error: read from %s: unexpected EOF\n", sock->name );
|
error( "Socket error: read from %s: unexpected EOF\n", sock->name );
|
||||||
socket_fail( sock );
|
socket_fail( sock );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
static void
|
||||||
|
socket_fill_z( conn_t *sock )
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (prepare_read( sock, &buf, &len ) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sock->in_z->avail_out = len;
|
||||||
|
sock->in_z->next_out = (unsigned char *)buf;
|
||||||
|
|
||||||
|
if (inflate( sock->in_z, Z_SYNC_FLUSH ) != Z_OK) {
|
||||||
|
error( "Error decompressing data from %s: %s\n", sock->name, sock->in_z->msg );
|
||||||
|
socket_fail( sock );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
sock->bytes += n;
|
if (!sock->in_z->avail_out)
|
||||||
|
conf_wakeup( &sock->z_fake, 0 );
|
||||||
|
|
||||||
|
if ((len = (char *)sock->in_z->next_out - buf)) {
|
||||||
|
sock->bytes += len;
|
||||||
sock->read_callback( sock->callback_aux );
|
sock->read_callback( sock->callback_aux );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
socket_fill( conn_t *sock )
|
||||||
|
{
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
if (sock->in_z) {
|
||||||
|
/* The timer will preempt reads until the buffer is empty. */
|
||||||
|
assert( !sock->in_z->avail_in );
|
||||||
|
sock->in_z->next_in = (uchar *)sock->z_buf;
|
||||||
|
if ((sock->in_z->avail_in = do_read( sock, sock->z_buf, sizeof(sock->z_buf) )) <= 0)
|
||||||
|
return;
|
||||||
|
socket_fill_z( sock );
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (prepare_read( sock, &buf, &len ) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((len = do_read( sock, buf, len )) <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sock->bytes += len;
|
||||||
|
sock->read_callback( sock->callback_aux );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
socket_read( conn_t *conn, char *buf, int len )
|
socket_read( conn_t *conn, char *buf, int len )
|
||||||
|
@ -655,6 +766,49 @@ do_append( conn_t *conn, buff_chunk_t *bc )
|
||||||
* sufficiently small to keep SSL latency low with a slow uplink. */
|
* sufficiently small to keep SSL latency low with a slow uplink. */
|
||||||
#define WRITE_CHUNK_SIZE 1024
|
#define WRITE_CHUNK_SIZE 1024
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_flush( conn_t *conn )
|
||||||
|
{
|
||||||
|
buff_chunk_t *bc = conn->append_buf;
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
if (conn->out_z) {
|
||||||
|
int buf_avail = conn->append_avail;
|
||||||
|
do {
|
||||||
|
if (!bc) {
|
||||||
|
buf_avail = WRITE_CHUNK_SIZE;
|
||||||
|
bc = nfmalloc( offsetof(buff_chunk_t, data) + buf_avail );
|
||||||
|
bc->len = 0;
|
||||||
|
}
|
||||||
|
conn->out_z->next_in = Z_NULL;
|
||||||
|
conn->out_z->avail_in = 0;
|
||||||
|
conn->out_z->next_out = (uchar *)bc->data + bc->len;
|
||||||
|
conn->out_z->avail_out = buf_avail;
|
||||||
|
if (deflate( conn->out_z, Z_PARTIAL_FLUSH ) != Z_OK) {
|
||||||
|
error( "Fatal: Compression error: %s\n", conn->out_z->msg );
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
bc->len = (char *)conn->out_z->next_out - bc->data;
|
||||||
|
if (bc->len) {
|
||||||
|
do_append( conn, bc );
|
||||||
|
bc = 0;
|
||||||
|
buf_avail = 0;
|
||||||
|
} else {
|
||||||
|
buf_avail = conn->out_z->avail_out;
|
||||||
|
}
|
||||||
|
} while (!conn->out_z->avail_out);
|
||||||
|
conn->append_buf = bc;
|
||||||
|
conn->append_avail = buf_avail;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if (bc) {
|
||||||
|
do_append( conn, bc );
|
||||||
|
conn->append_buf = 0;
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
conn->append_avail = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
socket_write( conn_t *conn, conn_iovec_t *iov, int iovcnt )
|
socket_write( conn_t *conn, conn_iovec_t *iov, int iovcnt )
|
||||||
{
|
{
|
||||||
|
@ -663,29 +817,54 @@ socket_write( conn_t *conn, conn_iovec_t *iov, int iovcnt )
|
||||||
|
|
||||||
for (i = 0; i < iovcnt; i++)
|
for (i = 0; i < iovcnt; i++)
|
||||||
total += iov[i].len;
|
total += iov[i].len;
|
||||||
bc = conn->append_buf;
|
if (total >= WRITE_CHUNK_SIZE) {
|
||||||
if (bc && total >= WRITE_CHUNK_SIZE) {
|
|
||||||
/* If the new data is too big, queue the pending buffer to avoid latency. */
|
/* If the new data is too big, queue the pending buffer to avoid latency. */
|
||||||
do_append( conn, bc );
|
do_flush( conn );
|
||||||
bc = 0;
|
|
||||||
}
|
}
|
||||||
|
bc = conn->append_buf;
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
buf_avail = conn->append_avail;
|
||||||
|
#endif
|
||||||
while (total) {
|
while (total) {
|
||||||
if (!bc) {
|
if (!bc) {
|
||||||
|
/* We don't do anything special when compressing, as there is no way to
|
||||||
|
* predict a reasonable output buffer size anyway - deflatePending() does
|
||||||
|
* not account for consumed but not yet compressed input, and adding up
|
||||||
|
* the deflateBound()s would be a tad *too* pessimistic. */
|
||||||
buf_avail = total > WRITE_CHUNK_SIZE ? total : WRITE_CHUNK_SIZE;
|
buf_avail = total > WRITE_CHUNK_SIZE ? total : WRITE_CHUNK_SIZE;
|
||||||
bc = nfmalloc( offsetof(buff_chunk_t, data) + buf_avail );
|
bc = nfmalloc( offsetof(buff_chunk_t, data) + buf_avail );
|
||||||
bc->len = 0;
|
bc->len = 0;
|
||||||
|
#ifndef HAVE_LIBZ
|
||||||
} else {
|
} else {
|
||||||
/* A pending buffer will always be of standard size - over-sized
|
/* A pending buffer will always be of standard size - over-sized
|
||||||
* buffers are immediately filled and queued. */
|
* buffers are immediately filled and queued. */
|
||||||
buf_avail = WRITE_CHUNK_SIZE - bc->len;
|
buf_avail = WRITE_CHUNK_SIZE - bc->len;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
while (total) {
|
while (total) {
|
||||||
len = iov->len - offset;
|
len = iov->len - offset;
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
if (conn->out_z) {
|
||||||
|
conn->out_z->next_in = (uchar *)iov->buf + offset;
|
||||||
|
conn->out_z->avail_in = len;
|
||||||
|
conn->out_z->next_out = (uchar *)bc->data + bc->len;
|
||||||
|
conn->out_z->avail_out = buf_avail;
|
||||||
|
if (deflate( conn->out_z, Z_NO_FLUSH ) != Z_OK) {
|
||||||
|
error( "Fatal: Compression error: %s\n", conn->out_z->msg );
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
bc->len = (char *)conn->out_z->next_out - bc->data;
|
||||||
|
buf_avail = conn->out_z->avail_out;
|
||||||
|
len -= conn->out_z->avail_in;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
if (len > buf_avail)
|
if (len > buf_avail)
|
||||||
len = buf_avail;
|
len = buf_avail;
|
||||||
memcpy( bc->data + bc->len, iov->buf + offset, len );
|
memcpy( bc->data + bc->len, iov->buf + offset, len );
|
||||||
bc->len += len;
|
bc->len += len;
|
||||||
buf_avail -= len;
|
buf_avail -= len;
|
||||||
|
}
|
||||||
offset += len;
|
offset += len;
|
||||||
total -= len;
|
total -= len;
|
||||||
if (offset == iov->len) {
|
if (offset == iov->len) {
|
||||||
|
@ -702,8 +881,16 @@ socket_write( conn_t *conn, conn_iovec_t *iov, int iovcnt )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conn->append_buf = bc;
|
conn->append_buf = bc;
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
conn->append_avail = buf_avail;
|
||||||
|
#endif
|
||||||
/* Queue the pending write once the main loop goes idle. */
|
/* Queue the pending write once the main loop goes idle. */
|
||||||
conf_wakeup( &conn->fd_fake, bc ? 0 : -1 );
|
conf_wakeup( &conn->fd_fake,
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
/* Always give zlib a chance to flush its internal buffer. */
|
||||||
|
conn->out_z ||
|
||||||
|
#endif
|
||||||
|
bc ? 0 : -1 );
|
||||||
/* If no writes were queued before, ensure that flushing commences. */
|
/* If no writes were queued before, ensure that flushing commences. */
|
||||||
if (!exwb)
|
if (!exwb)
|
||||||
return do_queued_write( conn );
|
return do_queued_write( conn );
|
||||||
|
@ -763,13 +950,22 @@ socket_fake_cb( void *aux )
|
||||||
conn_t *conn = (conn_t *)aux;
|
conn_t *conn = (conn_t *)aux;
|
||||||
|
|
||||||
buff_chunk_t *exwb = conn->write_buf;
|
buff_chunk_t *exwb = conn->write_buf;
|
||||||
do_append( conn, conn->append_buf );
|
do_flush( conn );
|
||||||
conn->append_buf = 0;
|
|
||||||
/* If no writes were queued before, ensure that flushing commences. */
|
/* If no writes were queued before, ensure that flushing commences. */
|
||||||
if (!exwb)
|
if (!exwb)
|
||||||
do_queued_write( conn );
|
do_queued_write( conn );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
static void
|
||||||
|
z_fake_cb( void *aux )
|
||||||
|
{
|
||||||
|
conn_t *conn = (conn_t *)aux;
|
||||||
|
|
||||||
|
socket_fill_z( conn );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LIBSSL
|
#ifdef HAVE_LIBSSL
|
||||||
static void
|
static void
|
||||||
ssl_fake_cb( void *aux )
|
ssl_fake_cb( void *aux )
|
||||||
|
|
15
src/socket.h
15
src/socket.h
|
@ -25,6 +25,10 @@
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
#include <zlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LIBSSL
|
#ifdef HAVE_LIBSSL
|
||||||
typedef struct ssl_st SSL;
|
typedef struct ssl_st SSL;
|
||||||
typedef struct ssl_ctx_st SSL_CTX;
|
typedef struct ssl_ctx_st SSL_CTX;
|
||||||
|
@ -76,6 +80,10 @@ typedef struct {
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
wakeup_t ssl_fake;
|
wakeup_t ssl_fake;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
z_streamp in_z, out_z;
|
||||||
|
wakeup_t z_fake;
|
||||||
|
#endif
|
||||||
|
|
||||||
void (*bad_callback)( void *aux ); /* async fail while sending or listening */
|
void (*bad_callback)( void *aux ); /* async fail while sending or listening */
|
||||||
void (*read_callback)( void *aux ); /* data available for reading */
|
void (*read_callback)( void *aux ); /* data available for reading */
|
||||||
|
@ -92,6 +100,9 @@ typedef struct {
|
||||||
/* writing */
|
/* writing */
|
||||||
buff_chunk_t *append_buf; /* accumulating buffer */
|
buff_chunk_t *append_buf; /* accumulating buffer */
|
||||||
buff_chunk_t *write_buf, **write_buf_append; /* buffer head & tail */
|
buff_chunk_t *write_buf, **write_buf_append; /* buffer head & tail */
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
int append_avail; /* space left in accumulating buffer */
|
||||||
|
#endif
|
||||||
int write_offset; /* offset into buffer head */
|
int write_offset; /* offset into buffer head */
|
||||||
|
|
||||||
/* reading */
|
/* reading */
|
||||||
|
@ -99,6 +110,9 @@ typedef struct {
|
||||||
int bytes; /* number of filled bytes in buffer */
|
int bytes; /* number of filled bytes in buffer */
|
||||||
int scanoff; /* offset to continue scanning for newline at, relative to 'offset' */
|
int scanoff; /* offset to continue scanning for newline at, relative to 'offset' */
|
||||||
char buf[100000];
|
char buf[100000];
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
char z_buf[100000];
|
||||||
|
#endif
|
||||||
} conn_t;
|
} conn_t;
|
||||||
|
|
||||||
/* call this before doing anything with the socket */
|
/* call this before doing anything with the socket */
|
||||||
|
@ -120,6 +134,7 @@ static INLINE void socket_init( conn_t *conn,
|
||||||
}
|
}
|
||||||
void socket_connect( conn_t *conn, void (*cb)( int ok, void *aux ) );
|
void socket_connect( conn_t *conn, void (*cb)( int ok, void *aux ) );
|
||||||
void socket_start_tls(conn_t *conn, void (*cb)( int ok, void *aux ) );
|
void socket_start_tls(conn_t *conn, void (*cb)( int ok, void *aux ) );
|
||||||
|
void socket_start_deflate( conn_t *conn );
|
||||||
void socket_close( conn_t *sock );
|
void socket_close( conn_t *sock );
|
||||||
int socket_read( conn_t *sock, char *buf, int len ); /* never waits */
|
int socket_read( conn_t *sock, char *buf, int len ); /* never waits */
|
||||||
char *socket_read_line( conn_t *sock ); /* don't free return value; never waits */
|
char *socket_read_line( conn_t *sock ); /* don't free return value; never waits */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user