Commit cade1642 cade1642ae04e25b0326b2c8b97d200d25a1df30 by Sergey Poznyakoff

Use stream transport instead of fd

1 parent ccdc7d37
......@@ -88,14 +88,18 @@ struct _gsasl_stream {
Gsasl_session_ctx *sess_ctx; /* Context */
int last_err; /* Last Gsasl error code */
int fd; /* File descriptor */
stream_t stream; /* I/O stream */
struct _line_buffer *lb;
};
static void
_gsasl_destroy (stream_t stream)
{
int flags;
struct _gsasl_stream *s = stream_get_owner (stream);
stream_get_flags (stream, &flags);
if (!(flags & MU_STREAM_NO_CLOSE))
stream_destroy (&s->stream, stream_get_owner (s->stream));
_auth_lb_destroy (&s->lb);
}
......@@ -121,14 +125,13 @@ _gsasl_readline (stream_t stream, char *optr, size_t osize,
{
char buf[80];
size_t sz;
int status;
sz = read (s->fd, buf, sizeof (buf));
if (sz == (size_t) -1)
{
if (errno == EINTR)
status = stream_sequential_read (s->stream, buf, sizeof (buf), &sz);
if (status == EINTR)
continue;
return errno;
}
else if (status)
return status;
rc = _auth_lb_grow (s->lb, buf, sz);
if (rc)
......@@ -189,8 +192,8 @@ write_chunk (void *data, char *start, char *end)
struct _gsasl_stream *s = data;
size_t chunk_size = end - start + 1;
size_t len;
size_t wrsize;
char *buf = NULL;
int status;
len = UINT_MAX; /* override the bug in libgsasl */
gsasl_encode (s->sess_ctx, start, chunk_size, NULL, &len);
......@@ -200,24 +203,11 @@ write_chunk (void *data, char *start, char *end)
gsasl_encode (s->sess_ctx, start, chunk_size, buf, &len);
wrsize = 0;
do
{
size_t sz = write (s->fd, buf + wrsize, len - wrsize);
if (sz == (size_t)-1)
{
if (errno == EINTR)
continue;
free (buf);
return errno;
}
wrsize += sz;
}
while (wrsize < len);
status = stream_sequential_write (s->stream, buf, len);
free (buf);
return 0;
return status;
}
......@@ -239,7 +229,8 @@ _gsasl_write (stream_t stream, const char *iptr, size_t isize,
static int
_gsasl_flush (stream_t stream)
{
return 0;
struct _gsasl_stream *s = stream_get_owner (stream);
return stream_flush (s->stream);
}
static int
......@@ -250,16 +241,14 @@ _gsasl_close (stream_t stream)
stream_get_flags (stream, &flags);
if (!(flags & MU_STREAM_NO_CLOSE))
close (s->fd);
if (s->sess_ctx)
gsasl_server_finish (s->sess_ctx);
stream_close (s->stream);
return 0;
}
static int
_gsasl_open (stream_t stream)
{
struct _gsasl_stream *s = stream_get_owner (stream);
/* Nothing to do */
return 0;
}
......@@ -272,17 +261,29 @@ _gsasl_strerror (stream_t stream, char **pstr)
}
int
_gsasl_get_fd (stream_t stream, int *pfd, int *pfd2)
_gsasl_get_transport2 (stream_t stream, mu_transport_t *pt, mu_transport_t *pt2)
{
struct _gsasl_stream *s = stream_get_owner (stream);
if (pfd2)
return ENOSYS;
*pfd = s->fd;
*pt2 = NULL; /* FIXME 1 */
*pt = (mu_transport_t) s->stream;
return 0;
}
int
gsasl_stream_create (stream_t *stream, int fd,
_gsasl_wait (stream_t stream, int *pflags, struct timeval *tvp)
{
int flags;
struct _gsasl_stream *s = stream_get_owner (stream);
stream_get_flags (stream, &flags);
if (((*pflags & MU_STREAM_READY_RD) && !(flags & MU_STREAM_READ))
|| ((*pflags & MU_STREAM_READY_WR) && !(flags & MU_STREAM_WRITE)))
return EINVAL;
return stream_wait (s->stream, pflags, tvp);
}
int
gsasl_stream_create (stream_t *stream, stream_t transport,
Gsasl_session_ctx *ctx, int flags)
{
struct _gsasl_stream *s;
......@@ -300,7 +301,7 @@ gsasl_stream_create (stream_t *stream, int fd,
if (s == NULL)
return ENOMEM;
s->fd = fd;
s->stream = transport;
s->sess_ctx = ctx;
rc = stream_create (stream, flags|MU_STREAM_NO_CHECK, s);
......@@ -315,7 +316,8 @@ gsasl_stream_create (stream_t *stream, int fd,
stream_set_flush (*stream, _gsasl_flush, s);
stream_set_destroy (*stream, _gsasl_destroy, s);
stream_set_strerror (*stream, _gsasl_strerror, s);
stream_set_fd (*stream, _gsasl_get_fd, s);
stream_set_wait (*stream, _gsasl_wait, s);
stream_set_get_transport2 (*stream, _gsasl_get_transport2, s);
if (flags & MU_STREAM_READ)
stream_set_readline (*stream, _gsasl_readline, s);
else
......
......@@ -244,13 +244,12 @@ enum tls_stream_state {
};
struct _tls_stream {
int ifd;
int ofd;
stream_t strin; /* Input stream */
stream_t strout; /* Output stream */
int last_err;
struct _line_buffer *lb;
enum tls_stream_state state;
gnutls_session session;
stream_t tcp_str;
};
......@@ -265,8 +264,6 @@ _tls_destroy (stream_t stream)
gnutls_deinit (s->session);
s->state = state_destroyed;
}
if (s->tcp_str)
stream_destroy (&s->tcp_str, stream_get_owner (s->tcp_str));
_auth_lb_destroy (&s->lb);
free (s);
}
......@@ -365,8 +362,8 @@ _tls_write (stream_t stream, const char *iptr, size_t isize,
static int
_tls_flush (stream_t stream)
{
/* noop */
return 0;
struct _tls_stream *s = stream_get_owner (stream);
return stream_flush (s->strout);
}
static int
......@@ -381,6 +378,38 @@ _tls_close (stream_t stream)
return 0;
}
/* Push & pull functions */
static ssize_t
_tls_stream_pull (gnutls_transport_ptr fd, void *buf, size_t size)
{
stream_t stream = fd;
int rc;
size_t rdbytes;
while ((rc = stream_sequential_read (stream, buf, size, &rdbytes)) == EAGAIN)
;
if (rc)
return -1;
return rdbytes;
}
static ssize_t
_tls_stream_push (gnutls_transport_ptr fd, const void *buf, size_t size)
{
stream_t stream = fd;
int rc;
rc = stream_sequential_write (stream, buf, size);
if (rc)
return -1;
return size;
}
static int
_tls_open (stream_t stream)
{
......@@ -409,8 +438,11 @@ _tls_open (stream_t stream)
gnutls_certificate_set_dh_params (x509_cred, dh_params);
s->session = initialize_tls_session ();
gnutls_transport_set_ptr2 (s->session, (gnutls_transport_ptr) s->ifd,
(gnutls_transport_ptr) s->ofd);
gnutls_transport_set_ptr2 (s->session,
(gnutls_transport_ptr) s->strin,
(gnutls_transport_ptr) s->strout);
gnutls_transport_set_pull_function (s->session, _tls_stream_pull);
gnutls_transport_set_push_function (s->session, _tls_stream_push);
rc = gnutls_handshake (s->session);
if (rc < 0)
......@@ -457,8 +489,11 @@ prepare_client_session (struct _tls_stream *s)
gnutls_credentials_set (s->session, GNUTLS_CRD_CERTIFICATE, x509_cred);
gnutls_transport_set_ptr2 (s->session, (gnutls_transport_ptr) s->ifd,
(gnutls_transport_ptr) s->ofd);
gnutls_transport_set_ptr2 (s->session,
(gnutls_transport_ptr) s->strin,
(gnutls_transport_ptr) s->strout);
gnutls_transport_set_pull_function (s->session, _tls_stream_pull);
gnutls_transport_set_push_function (s->session, _tls_stream_push);
return 0;
}
......@@ -507,16 +542,35 @@ _tls_strerror (stream_t stream, char **pstr)
}
int
_tls_get_fd (stream_t stream, int *pfd1, int *pfd2)
_tls_get_transport2 (stream_t stream,
mu_transport_t *pin, mu_transport_t *pout)
{
struct _tls_stream *s = stream_get_owner (stream);
*pfd1 = s->ifd;
*pfd2 = s->ofd;
*pin = (mu_transport_t) s->strin;
*pout = (mu_transport_t) s->strout;
return 0;
}
int
tls_stream_create (stream_t *stream, int in_fd, int out_fd, int flags)
_tls_wait (stream_t stream, int *pflags, struct timeval *tvp)
{
struct _tls_stream *s = stream_get_owner (stream);
if ((*pflags & (MU_STREAM_READY_RD|MU_STREAM_READY_WR)) == (MU_STREAM_READY_RD|MU_STREAM_READY_WR))
return EINVAL; /* Sorry, can't wait for both input and output. */
if (*pflags & MU_STREAM_READY_RD)
return stream_wait (s->strin, pflags, tvp);
if (*pflags & MU_STREAM_READY_WR)
return stream_wait (s->strout, pflags, tvp);
return EINVAL;
}
/* FIXME: if strin == strout sequential reads may intefere with
sequential writes (they would share stream->offset). This should
be fixed either in stream.c or here. In particular, tls_stream_create_client
will malfunction */
int
tls_stream_create (stream_t *stream,
stream_t strin, stream_t strout, int flags)
{
struct _tls_stream *s;
int rc;
......@@ -528,8 +582,8 @@ tls_stream_create (stream_t *stream, int in_fd, int out_fd, int flags)
if (s == NULL)
return ENOMEM;
s->ifd = in_fd;
s->ofd = out_fd;
s->strin = strin;
s->strout = strout;
rc = stream_create (stream, flags|MU_STREAM_NO_CHECK, s);
if (rc)
......@@ -546,7 +600,8 @@ tls_stream_create (stream_t *stream, int in_fd, int out_fd, int flags)
stream_set_flush (*stream, _tls_flush, s);
stream_set_destroy (*stream, _tls_destroy, s);
stream_set_strerror (*stream, _tls_strerror, s);
stream_set_fd (*stream, _tls_get_fd, s);
stream_set_get_transport2 (*stream, _tls_get_transport2, s);
stream_set_wait (*stream, _tls_wait, s);
_auth_lb_create (&s->lb);
s->state = state_init;
......@@ -554,20 +609,21 @@ tls_stream_create (stream_t *stream, int in_fd, int out_fd, int flags)
}
int
tls_stream_create_client (stream_t *stream, int in_fd, int out_fd, int flags)
tls_stream_create_client (stream_t *stream,
stream_t strin, stream_t strout, int flags)
{
struct _tls_stream *s;
int rc;
if (stream == NULL)
return EINVAL;
return MU_ERR_OUT_PTR_NULL;
s = calloc (1, sizeof (*s));
if (s == NULL)
return ENOMEM;
s->ifd = in_fd;
s->ofd = out_fd;
s->strin = strin;
s->strout = strout;
rc = stream_create (stream, flags|MU_STREAM_NO_CHECK, s);
if (rc)
......@@ -584,7 +640,8 @@ tls_stream_create_client (stream_t *stream, int in_fd, int out_fd, int flags)
stream_set_flush (*stream, _tls_flush, s);
stream_set_destroy (*stream, _tls_destroy, s);
stream_set_strerror (*stream, _tls_strerror, s);
stream_set_fd (*stream, _tls_get_fd, s);
stream_set_get_transport2 (*stream, _tls_get_transport2, s);
stream_set_wait (*stream, _tls_wait, s);
_auth_lb_create (&s->lb);
s->state = state_init;
......@@ -595,16 +652,7 @@ int
tls_stream_create_client_from_tcp (stream_t *stream, stream_t tcp_str,
int flags)
{
int rc, fd;
stream_get_fd (tcp_str, &fd);
rc = tls_stream_create_client (stream, fd, fd, flags);
if (rc == 0)
{
struct _tls_stream *s = stream_get_owner (*stream);
s->tcp_str = tcp_str;
}
return rc;
return tls_stream_create_client (stream, tcp_str, tcp_str, flags);
}
#endif /* WITH_TLS */
......
......@@ -153,14 +153,9 @@ int
pop3d_init_tls_server ()
{
stream_t stream;
int in_fd;
int out_fd;
int rc;
if (stream_get_fd (istream, &in_fd)
|| stream_get_fd (ostream, &out_fd))
return 0;
rc = tls_stream_create (&stream, in_fd, out_fd, 0);
rc = tls_stream_create (&stream, istream, ostream, 0);
if (rc)
return 0;
......@@ -172,8 +167,6 @@ pop3d_init_tls_server ()
return 0;
}
stream_destroy (&istream, stream_get_owner (istream));
stream_destroy (&ostream, stream_get_owner (ostream));
istream = ostream = stream;
return 1;
}
......