ERROR-ify sock_gnutls
authorTero Marttila <terom@fixme.fi>
Sun, 22 Feb 2009 07:08:57 +0200
changeset 5 a09a0797f6f0
parent 4 a3ca0f97a075
child 6 240ae8482d64
ERROR-ify sock_gnutls
src/error.h
src/nexus.c
src/sock.c
src/sock.h
src/sock_gnutls.c
src/sock_gnutls.h
--- a/src/error.h	Sun Feb 22 06:52:55 2009 +0200
+++ b/src/error.h	Sun Feb 22 07:08:57 2009 +0200
@@ -34,6 +34,10 @@
     /* GnuTLS errors */
     ERR_GNUTLS_CERT_ALLOC_CRED  = 0x010101,
     ERR_GNUTLS_GLOBAL_INIT      = 0x010102,
+    ERR_GNUTLS_INIT             = 0x010103,
+    ERR_GNUTLS_SET_DEFAULT_PRIORITY         = 0x010104,
+    ERR_GNUTLS_CRED_SET         = 0x010105,
+    ERR_GNUTLS_HANDSHAKE        = 0x010106,
 };
 
 /*
@@ -69,13 +73,20 @@
 #define _SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra) (err_info_ptr)->code = (err_code); (err_info_ptr)->extra = (err_extra)
 #define SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra) do { _SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra); } while (0)
 
-/* Set error.info.code to err_code, and .extra to errno. XXX: should evaulate to err_code */
+/* Set error_info.code to err_code, and .extra to errno. XXX: should evaulate to err_code */
 #define _SET_ERROR_ERRNO(err_info_ptr, err_code) _SET_ERROR_EXTRA(err_info_ptr, err_code, errno);
 #define SET_ERROR_ERRNO(err_info_ptr, err_code) SET_ERROR_EXTRA(err_info_ptr, err_code, errno);
 
-/* Ss above, but also return err_code from func. XXX: use 'return SET_ERROR...' instead */
-#define RETURN_SET_ERROR(err_info_ptr, err_code) do { _SET_ERROR(err_info_ptr, err_code); return (err_code); } while (0)
+/* Set error_info from another error_info. Evaluates to the new error_info */
+#define SET_ERROR_INFO(err_info_ptr, from_ptr) (*err_info_ptr = *from_ptr)
+
+/* Same as above, but also return err_code from func. XXX: use 'return SET_ERROR...' instead */
+#define RETURN_SET_ERROR(err_info_ptr, err_code) do { SET_ERROR(err_info_ptr, err_code); return (err_code); } while (0)
 #define RETURN_SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra) do { _SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra); return (err_code); } while (0)
 #define RETURN_SET_ERROR_ERRNO(err_info_ptr, err_code) do { _SET_ERROR_ERRNO(err_info_ptr, err_code); return (err_code); } while (0)
 
+/* Same as above, but also do a 'goto error' */
+#define JUMP_SET_ERROR(err_info_ptr, err_code) do { SET_ERROR(err_info_ptr, err_code); goto error; } while (0)
+#define JUMP_SET_ERROR_INFO(err_info_ptr, from_ptr) do { SET_ERROR_INFO(err_info_ptr, from_ptr); goto error; } while (0)
+
 #endif
--- a/src/nexus.c	Sun Feb 22 06:52:55 2009 +0200
+++ b/src/nexus.c	Sun Feb 22 07:08:57 2009 +0200
@@ -11,7 +11,7 @@
 #include "sock.h"
 
 #define CONNECT_HOST "irc.fixme.fi"
-#define CONNECT_SERV "6697"
+#define CONNECT_SERV "6667"
 #define LINE_LENGTH 512
 
 struct recvline_state {
@@ -118,7 +118,9 @@
     memset(&recvline_ctx, 0, sizeof(recvline_ctx));
     
     // over-simplified connect
-    sock = sock_ssl_connect(CONNECT_HOST, CONNECT_SERV);
+    if (sock_gnutls_connect(&sock, CONNECT_HOST, CONNECT_SERV, &err))
+        // XXX:
+        errx(1, "sock_gnutls_connect");
 
     // read lines and dump them out
     do {
--- a/src/sock.c	Sun Feb 22 06:52:55 2009 +0200
+++ b/src/sock.c	Sun Feb 22 07:08:57 2009 +0200
@@ -7,7 +7,7 @@
 err_t sock_init (struct error_info *err)
 {
     // XXX: just call these all directly for now
-    if (sock_gnutls_init(err))
+    if (sock_gnutls_global_init(err))
         return ERROR_CODE(err);
 
     // done
--- a/src/sock.h	Sun Feb 22 06:52:55 2009 +0200
+++ b/src/sock.h	Sun Feb 22 07:08:57 2009 +0200
@@ -19,7 +19,7 @@
 
 /*
  * A simple blocking TCP connect to the given host/service, using getaddrinfo. The connected socket is returned via
- * *sock_ptr. In case of errors, additional error information is stored in *err
+ * *sock_ptr. In case of errors, additional error information is stored in *err.
  *
  * @return zero on success, nonzero on error
  *
@@ -28,15 +28,13 @@
 err_t sock_tcp_connect (struct sock_stream **sock_ptr, const char *host, const char *service, struct error_info *err);
 
 /*
- * A simple blocking SSL connect to the given host/service.
+ * A simple blocking SSL connect to the given host/service. The connected/handshake'd SSL socket is returned via
+ * *sock_ptr. In case of errors, additional error information is stored in *err.
  *
  * XXX: blocking
  * XXX: doesn't do any certificate verification.
- * XXX: exits on error
- *
- * Returns the socket handle, or NULL on errors.
  */
-struct sock_stream *sock_ssl_connect (const char *host, const char *service);
+err_t sock_gnutls_connect (struct sock_stream **sock_ptr, const char *host, const char *service, struct error_info *err);
 
 /*
  * The generic read/write API for stream sockets.
--- a/src/sock_gnutls.c	Sun Feb 22 06:52:55 2009 +0200
+++ b/src/sock_gnutls.c	Sun Feb 22 07:08:57 2009 +0200
@@ -54,7 +54,7 @@
     return SUCCESS;
 }
 
-err_t sock_gnutls_init (struct error_info *err)
+err_t sock_gnutls_global_init (struct error_info *err)
 {
     // global init
     if ((ERROR_EXTRA(err) = gnutls_global_init()) < 0)
@@ -69,41 +69,49 @@
 }
 
 
-// XXX: errors
-struct sock_stream *sock_ssl_connect (const char *host, const char *service)
+err_t sock_gnutls_connect (struct sock_stream **sock_ptr, const char *host, const char *service, struct error_info *err)
 {
-    int _err;
-    struct sock_gnutls *sock;
+    struct sock_gnutls *sock = NULL;
     struct sock_gnutls_client_ctx *ctx = &_sock_gnutls_client_ctx;
 
     // alloc
     if ((sock = calloc(1, sizeof(*sock))) == NULL)
-        errx(1, "calloc");
+        return SET_ERROR(err, ERR_CALLOC);
 
-    // initialize
-    sock->base_tcp.base.type = &sock_gnutls_type;
+    // initialize base
+    sock_stream_init(SOCK_GNUTLS_BASE(sock), &sock_gnutls_type);
 
     // initialize client session
-    if ((_err = gnutls_init(&sock->session, GNUTLS_CLIENT)) < 0)
-        errx(1, "gnutls_init: %s", gnutls_strerror(_err));
+    if ((ERROR_EXTRA(err) = gnutls_init(&sock->session, GNUTLS_CLIENT)) < 0)
+        JUMP_SET_ERROR(err, ERR_GNUTLS_INIT);
 
     // ...default priority stuff
-    gnutls_set_default_priority(sock->session);
+    if ((ERROR_EXTRA(err) = gnutls_set_default_priority(sock->session)))
+        JUMP_SET_ERROR(err, ERR_GNUTLS_SET_DEFAULT_PRIORITY);
 
     // bind anon credentials
-    gnutls_credentials_set(sock->session, GNUTLS_CRD_CERTIFICATE, ctx->xcred);
+    if ((ERROR_EXTRA(err) = gnutls_credentials_set(sock->session, GNUTLS_CRD_CERTIFICATE, ctx->xcred)))
+        JUMP_SET_ERROR(err, ERR_GNUTLS_CRED_SET);
 
     // TCP connect
-    sock_tcp_init_connect(SOCK_GNUTLS_TCP(sock), host, service);
+    if (sock_tcp_init_connect(SOCK_GNUTLS_TCP(sock), host, service))
+        JUMP_SET_ERROR_INFO(err, SOCK_GNUTLS_ERR(sock));
 
     // bind default transport functions (recv/send) to use the TCP fd
     gnutls_transport_set_ptr(sock->session, (gnutls_transport_ptr_t) sock->base_tcp.fd);
 
     // perform the handshake
-    if ((_err = gnutls_handshake(sock->session)) < 0)
-        _sock_gnutls_error(sock, "gnutls_handshake", _err);
+    if ((ERROR_EXTRA(err) = gnutls_handshake(sock->session)) < 0)
+        JUMP_SET_ERROR(err, ERR_GNUTLS_HANDSHAKE);
 
     // done
-    return SOCK_GNUTLS_BASE(sock);
+    *sock_ptr = SOCK_GNUTLS_BASE(sock);
+
+    return SUCCESS;
+
+error:
+    // XXX: cleanup
+
+    return ERROR_CODE(err);    
 }
 
--- a/src/sock_gnutls.h	Sun Feb 22 06:52:55 2009 +0200
+++ b/src/sock_gnutls.h	Sun Feb 22 07:08:57 2009 +0200
@@ -40,6 +40,6 @@
 /*
  * Initialize the global gnutls state
  */
-err_t sock_gnutls_init (struct error_info *err);
+err_t sock_gnutls_global_init (struct error_info *err);
 
 #endif /* SOCK_GNUTLS_H */