mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
http: Add reference counting to the session object.
* common/http.c (http_session_t): Add field "refcount". (_my_socket_new, _my_socket_ref, _my_socket_unref): Add debug code. (send_request, my_npth_read, my_npth_write): Use SOCK object for the transport ptr. (http_session_release): Factor all code out to ... (session_unref): here. Deref SOCK. (http_session_new): Init refcount and transport ptr. (http_session_ref): New. Ref and unref all assignments. -- Having the reference counted session objects makes it easier for the application to pass around only an estream. Without that the application would need to implement an es_onclose machinery for the session object.
This commit is contained in:
parent
0e59195642
commit
ea0f5481f0
120
common/http.c
120
common/http.c
@ -222,6 +222,7 @@ typedef struct cookie_s *cookie_t;
|
||||
/* The session object. */
|
||||
struct http_session_s
|
||||
{
|
||||
int refcount; /* Number of references to this object. */
|
||||
#ifdef HTTP_USE_GNUTLS
|
||||
gnutls_certificate_credentials_t certcred;
|
||||
gnutls_session_t tls_session;
|
||||
@ -231,9 +232,7 @@ struct http_session_s
|
||||
unsigned int status; /* Verification status. */
|
||||
} verify;
|
||||
char *servername; /* Malloced server name. */
|
||||
#else
|
||||
int dummy;
|
||||
#endif
|
||||
#endif /*HTTP_USE_GNUTLS*/
|
||||
};
|
||||
|
||||
|
||||
@ -327,7 +326,7 @@ init_sockets (void)
|
||||
/* Create a new socket object. Returns NULL and closes FD if not
|
||||
enough memory is available. */
|
||||
static my_socket_t
|
||||
my_socket_new (int fd)
|
||||
_my_socket_new (int lnr, int fd)
|
||||
{
|
||||
my_socket_t so;
|
||||
|
||||
@ -341,34 +340,39 @@ my_socket_new (int fd)
|
||||
}
|
||||
so->fd = fd;
|
||||
so->refcount = 1;
|
||||
/* log_debug ("my_socket_new(%d): object %p for fd %d created\n", */
|
||||
/* log_debug ("http.c:socket_new(%d): object %p for fd %d created\n", */
|
||||
/* lnr, so, so->fd); */
|
||||
(void)lnr;
|
||||
return so;
|
||||
}
|
||||
/* #define my_socket_new(a) _my_socket_new ((a),__LINE__) */
|
||||
#define my_socket_new(a) _my_socket_new (__LINE__, (a))
|
||||
|
||||
/* Bump up the reference counter for the socket object SO. */
|
||||
static my_socket_t
|
||||
my_socket_ref (my_socket_t so)
|
||||
_my_socket_ref (int lnr, my_socket_t so)
|
||||
{
|
||||
so->refcount++;
|
||||
/* log_debug ("my_socket_ref(%d): object %p for fd %d refcount now %d\n", */
|
||||
/* log_debug ("http.c:socket_ref(%d) object %p for fd %d refcount now %d\n", */
|
||||
/* lnr, so, so->fd, so->refcount); */
|
||||
(void)lnr;
|
||||
return so;
|
||||
}
|
||||
/* #define my_socket_ref(a) _my_socket_ref ((a),__LINE__) */
|
||||
#define my_socket_ref(a) _my_socket_ref (__LINE__,(a))
|
||||
|
||||
|
||||
/* Bump down the reference counter for the socket object SO. If SO
|
||||
has no more references, close the socket and release the
|
||||
object. */
|
||||
static void
|
||||
my_socket_unref (my_socket_t so, void (*preclose)(void*), void *preclosearg)
|
||||
_my_socket_unref (int lnr, my_socket_t so,
|
||||
void (*preclose)(void*), void *preclosearg)
|
||||
{
|
||||
if (so)
|
||||
{
|
||||
so->refcount--;
|
||||
/* log_debug ("my_socket_unref(%d): object %p for fd %d ref now %d\n", */
|
||||
/* log_debug ("http.c:socket_unref(%d): object %p for fd %d ref now %d\n", */
|
||||
/* lnr, so, so->fd, so->refcount); */
|
||||
(void)lnr;
|
||||
if (!so->refcount)
|
||||
{
|
||||
if (preclose)
|
||||
@ -378,19 +382,21 @@ my_socket_unref (my_socket_t so, void (*preclose)(void*), void *preclosearg)
|
||||
}
|
||||
}
|
||||
}
|
||||
/* #define my_socket_unref(a) _my_socket_unref ((a),__LINE__) */
|
||||
#define my_socket_unref(a,b,c) _my_socket_unref (__LINE__,(a),(b),(c))
|
||||
|
||||
|
||||
#if defined (USE_NPTH) && defined(HTTP_USE_GNUTLS)
|
||||
static ssize_t
|
||||
my_npth_read (gnutls_transport_ptr_t ptr, void *buffer, size_t size)
|
||||
{
|
||||
return npth_read ((int)(unsigned long)ptr, buffer, size);
|
||||
my_socket_t sock = ptr;
|
||||
return npth_read (sock->fd, buffer, size);
|
||||
}
|
||||
static ssize_t
|
||||
my_npth_write (gnutls_transport_ptr_t ptr, const void *buffer, size_t size)
|
||||
{
|
||||
return npth_write ((int)(unsigned long)ptr, buffer, size);
|
||||
my_socket_t sock = ptr;
|
||||
return npth_write (sock->fd, buffer, size);
|
||||
}
|
||||
#endif /*USE_NPTH && HTTP_USE_GNUTLS*/
|
||||
|
||||
@ -498,6 +504,44 @@ http_register_tls_ca (const char *fname)
|
||||
}
|
||||
|
||||
|
||||
/* Release a session. Take care not to release it while it is being
|
||||
used by a http context object. */
|
||||
static void
|
||||
session_unref (int lnr, http_session_t sess)
|
||||
{
|
||||
if (!sess)
|
||||
return;
|
||||
|
||||
sess->refcount--;
|
||||
/* log_debug ("http.c:session_unref(%d): sess %p ref now %d\n", */
|
||||
/* lnr, sess, sess->refcount); */
|
||||
(void)lnr;
|
||||
if (sess->refcount)
|
||||
return;
|
||||
|
||||
#ifdef HTTP_USE_GNUTLS
|
||||
if (sess->tls_session)
|
||||
{
|
||||
my_socket_t sock = gnutls_transport_get_ptr (sess->tls_session);
|
||||
my_socket_unref (sock, NULL, NULL);
|
||||
gnutls_deinit (sess->tls_session);
|
||||
}
|
||||
if (sess->certcred)
|
||||
gnutls_certificate_free_credentials (sess->certcred);
|
||||
xfree (sess->servername);
|
||||
#endif /*HTTP_USE_GNUTLS*/
|
||||
|
||||
xfree (sess);
|
||||
}
|
||||
#define http_session_unref(a) session_unref (__LINE__, (a))
|
||||
|
||||
void
|
||||
http_session_release (http_session_t sess)
|
||||
{
|
||||
http_session_unref (sess);
|
||||
}
|
||||
|
||||
|
||||
/* Create a new session object which is currently used to enable TLS
|
||||
support. It may eventually allow reusing existing connections. */
|
||||
gpg_error_t
|
||||
@ -511,6 +555,7 @@ http_session_new (http_session_t *r_session, const char *tls_priority)
|
||||
sess = xtrycalloc (1, sizeof *sess);
|
||||
if (!sess)
|
||||
return gpg_error_from_syserror ();
|
||||
sess->refcount = 1;
|
||||
|
||||
#ifdef HTTP_USE_GNUTLS
|
||||
{
|
||||
@ -544,6 +589,10 @@ http_session_new (http_session_t *r_session, const char *tls_priority)
|
||||
err = gpg_error (GPG_ERR_GENERAL);
|
||||
goto leave;
|
||||
}
|
||||
/* A new session has the transport ptr set to (void*(-1), we need
|
||||
it to be NULL. */
|
||||
gnutls_transport_set_ptr (sess->tls_session, NULL);
|
||||
|
||||
rc = gnutls_priority_set_direct (sess->tls_session,
|
||||
tls_priority? tls_priority : "NORMAL",
|
||||
&errpos);
|
||||
@ -569,13 +618,14 @@ http_session_new (http_session_t *r_session, const char *tls_priority)
|
||||
(void)tls_priority;
|
||||
#endif /*!HTTP_USE_GNUTLS*/
|
||||
|
||||
/* log_debug ("http.c:session_new: sess %p created\n", sess); */
|
||||
err = 0;
|
||||
|
||||
#ifdef HTTP_USE_GNUTLS
|
||||
leave:
|
||||
#endif /*HTTP_USE_GNUTLS*/
|
||||
if (err)
|
||||
http_session_release (sess);
|
||||
http_session_unref (sess);
|
||||
else
|
||||
*r_session = sess;
|
||||
|
||||
@ -583,23 +633,13 @@ http_session_new (http_session_t *r_session, const char *tls_priority)
|
||||
}
|
||||
|
||||
|
||||
/* Release a session. Take care not to release it while it is beeing
|
||||
used by a http contect object. */
|
||||
void
|
||||
http_session_release (http_session_t sess)
|
||||
/* Increment the reference count for session SESS. */
|
||||
http_session_t
|
||||
http_session_ref (http_session_t sess)
|
||||
{
|
||||
if (!sess)
|
||||
return;
|
||||
|
||||
#ifdef HTTP_USE_GNUTLS
|
||||
if (sess->tls_session)
|
||||
gnutls_deinit (sess->tls_session);
|
||||
if (sess->certcred)
|
||||
gnutls_certificate_free_credentials (sess->certcred);
|
||||
xfree (sess->servername);
|
||||
#endif /*HTTP_USE_GNUTLS*/
|
||||
|
||||
xfree (sess);
|
||||
sess->refcount++;
|
||||
/* log_debug ("http.c:session_ref: sess %p ref now %d\n", sess, sess->refcount); */
|
||||
return sess;
|
||||
}
|
||||
|
||||
|
||||
@ -625,7 +665,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
|
||||
return gpg_error_from_syserror ();
|
||||
hd->req_type = reqtype;
|
||||
hd->flags = flags;
|
||||
hd->session = session;
|
||||
hd->session = http_session_ref (session);
|
||||
|
||||
err = parse_uri (&hd->uri, url, 0, !!(flags & HTTP_FLAG_FORCE_TLS));
|
||||
if (!err)
|
||||
@ -638,6 +678,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
|
||||
es_fclose (hd->fp_read);
|
||||
if (hd->fp_write)
|
||||
es_fclose (hd->fp_write);
|
||||
http_session_unref (hd->session);
|
||||
xfree (hd);
|
||||
}
|
||||
else
|
||||
@ -791,7 +832,7 @@ http_wait_response (http_t hd)
|
||||
if (!cookie)
|
||||
return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
|
||||
cookie->sock = my_socket_ref (hd->sock);
|
||||
cookie->session = hd->session;
|
||||
cookie->session = http_session_ref (hd->session);
|
||||
cookie->use_tls = hd->uri->use_tls;
|
||||
|
||||
hd->read_cookie = cookie;
|
||||
@ -800,6 +841,7 @@ http_wait_response (http_t hd)
|
||||
{
|
||||
err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
|
||||
my_socket_unref (cookie->sock, NULL, NULL);
|
||||
http_session_unref (cookie->session);
|
||||
xfree (cookie);
|
||||
hd->read_cookie = NULL;
|
||||
return err;
|
||||
@ -857,6 +899,7 @@ http_close (http_t hd, int keep_read_stream)
|
||||
es_fclose (hd->fp_read);
|
||||
if (hd->fp_write)
|
||||
es_fclose (hd->fp_write);
|
||||
http_session_unref (hd->session);
|
||||
http_release_parsed_uri (hd->uri);
|
||||
while (hd->headers)
|
||||
{
|
||||
@ -1431,12 +1474,7 @@ send_request (http_t hd, const char *auth,
|
||||
int rc;
|
||||
|
||||
my_socket_ref (hd->sock);
|
||||
#if GNUTLS_VERSION_NUMBER >= 0x030109
|
||||
gnutls_transport_set_int (hd->session->tls_session, hd->sock->fd);
|
||||
#else
|
||||
gnutls_transport_set_ptr (hd->session->tls_session,
|
||||
(gnutls_transport_ptr_t)(hd->sock->fd));
|
||||
#endif
|
||||
gnutls_transport_set_ptr (hd->session->tls_session, hd->sock);
|
||||
#ifdef USE_NPTH
|
||||
gnutls_transport_set_pull_function (hd->session->tls_session,
|
||||
my_npth_read);
|
||||
@ -1561,7 +1599,7 @@ send_request (http_t hd, const char *auth,
|
||||
cookie->sock = my_socket_ref (hd->sock);
|
||||
hd->write_cookie = cookie;
|
||||
cookie->use_tls = hd->uri->use_tls;
|
||||
cookie->session = hd->session;
|
||||
cookie->session = http_session_ref (hd->session);
|
||||
|
||||
hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
|
||||
if (!hd->fp_write)
|
||||
@ -2382,6 +2420,8 @@ cookie_close (void *cookie)
|
||||
if (c->sock)
|
||||
my_socket_unref (c->sock, NULL, NULL);
|
||||
|
||||
if (c->session)
|
||||
http_session_unref (c->session);
|
||||
xfree (c);
|
||||
return 0;
|
||||
}
|
||||
|
@ -95,6 +95,7 @@ void http_register_tls_ca (const char *fname);
|
||||
|
||||
gpg_error_t http_session_new (http_session_t *r_session,
|
||||
const char *tls_priority);
|
||||
http_session_t http_session_ref (http_session_t sess);
|
||||
void http_session_release (http_session_t sess);
|
||||
|
||||
|
||||
|
@ -144,6 +144,7 @@ main (int argc, char **argv)
|
||||
int c;
|
||||
unsigned int my_http_flags = 0;
|
||||
int no_out = 0;
|
||||
int tls_dbg = 0;
|
||||
const char *cafile = NULL;
|
||||
http_session_t session = NULL;
|
||||
|
||||
@ -165,6 +166,7 @@ main (int argc, char **argv)
|
||||
"Options:\n"
|
||||
" --verbose print timings etc.\n"
|
||||
" --debug flyswatter\n"
|
||||
" --gnutls-debug N use GNUTLS debug level N\n"
|
||||
" --cacert FNAME expect CA certificate in file FNAME\n"
|
||||
" --no-verify do not verify the certificate\n"
|
||||
" --force-tls use HTTP_FLAG_FORCE_TLS\n"
|
||||
@ -183,6 +185,15 @@ main (int argc, char **argv)
|
||||
debug++;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strcmp (*argv, "--gnutls-debug"))
|
||||
{
|
||||
argc--; argv++;
|
||||
if (argc)
|
||||
{
|
||||
tls_dbg = atoi (*argv);
|
||||
argc--; argv++;
|
||||
}
|
||||
}
|
||||
else if (!strcmp (*argv, "--cacert"))
|
||||
{
|
||||
argc--; argv++;
|
||||
@ -248,7 +259,8 @@ main (int argc, char **argv)
|
||||
/* gnutls_certificate_set_dh_params (certcred, dh_params); */
|
||||
|
||||
gnutls_global_set_log_function (my_gnutls_log);
|
||||
/* gnutls_global_set_log_level (2); */
|
||||
if (tls_dbg)
|
||||
gnutls_global_set_log_level (tls_dbg);
|
||||
|
||||
#endif /*HTTP_USE_GNUTLS*/
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user