#include "canl.h"
 #include "canl_locl.h"
 
+static int resolve_error(glb_ctx *cc, CANL_ERROR err_code, 
+        CANL_ERROR_ORIGIN err_orig);
+static int ger_error_string(glb_ctx *cc, char *code_str, int *code_len);
+
 /* Save error message into err_msg
  * use NULL for empty err_format */
 void update_error (glb_ctx *cc,  const char *err_format, ...)
 }
 
 /* If there was some error message in ctx, delete it and make new */
-void set_error (glb_ctx *cc, CANL_ERROR err_code, const char *err_format, ...)
+void set_error (glb_ctx *cc, CANL_ERROR err_code, CANL_ERROR_ORIGIN err_orig,
+        const char *err_format, ...)
 {
     va_list ap;
     /*check cc*/
     vasprintf(&cc->err_msg, err_format, ap);
     va_end(ap);
 
-    cc->err_code = err_code;
+    resolve_error(cc, err_code, err_orig);
 }
 
 /* Delete error message in ctx, suppose msg is not empty.Set pointer to NULL*/
         free(cc->err_msg);
     cc->err_msg = NULL;
     cc->err_code = no_error;
+    cc->err_orig = unknown_error;
 }
 
 /* Provide human readable information about errors */
 int canl_get_error(canl_ctx cc, char  **reason)
 {
     int err = 0;
+    int e_orig = unknown_error;
     int error_length = 0;
     char *new_error = NULL;
+    char *code_str = NULL;
+    int code_len = 0;
+
     glb_ctx *ctx = (glb_ctx*) cc;
 
     /*check cc*/
     if (!ctx->err_msg)
         goto end;
 
-    error_length = strlen(ctx->err_msg);
+    /* get human readable error code*/
+    err = ger_error_string(cc, code_str, &code_len);
+    if (err) {
+        e_orig = unknown_error;
+        goto end;
+    }
+
+    /* 1 for new line*/
+    error_length = strlen(ctx->err_msg) + code_len + 1;
     new_error = (char *) malloc ((error_length + 1) * sizeof (char));
     if (!new_error) {
         err = ENOMEM;
+        e_orig = posix_error;
         goto end;
     }
 
-    strncpy(new_error, ctx->err_msg, error_length + 1);
+    strncpy(new_error, code_str, code_len);
+    new_error[code_len] = '\n';
+    new_error[code_len + 1] = '\0';
+    strncat(new_error, ctx->err_msg, error_length + 1);
     *reason = new_error;
 
 end:
     if (err)
-        update_error(ctx, "cannot get error message (canl_get_error)");
+        set_error(ctx, err, e_orig, "cannot get error message (canl_get_error)");
     return err;
 }
+
+/*TODO ! map error codes to their human readable strings */
+static int ger_error_string(glb_ctx *cc, char *code_str, int *code_len)
+{
+    return 0;
+}
+
+/*if the error code is known to colin, assign appropriate colin code
+  TODO go through ssl errors and assign appr. colin code
+  ?preserve original one? */
+static int resolve_error(glb_ctx *cc, CANL_ERROR err_code, 
+        CANL_ERROR_ORIGIN err_orig)
+{
+    if (err_orig == colin_error) {
+        cc->err_code = err_code;
+        cc->err_orig = colin_error;
+        return colin_error;
+    }
+    if (err_orig == posix_error) {
+        cc->err_code = err_code;
+        cc->err_orig = posix_error;
+        return posix_error;
+    }
+
+    switch (err_code) {
+        default:
+            cc->err_code = unknown;
+            cc->err_orig = unknown_error;
+            break;
+    }
+
+    return cc->err_code;
+}
 
     loadCrlDistPointError,
     trustAnchorIssuerError
 } CANL_ERROR;
+
+typedef enum _CANL_ERROR_ORIGIN
+{
+    unknown_error = 0,
+    posix_error = 1,
+    ssl_error,
+    colin_error
+} CANL_ERROR_ORIGIN;
+
 #endif
 
     int opened_ios;
     char * err_msg;
     CANL_ERROR err_code;
+    CANL_ERROR_ORIGIN err_orig;
 } glb_ctx;
 
 typedef struct _ossl_ctx
     ossl_ctx * s_ctx;
 } io_handler;
 
-#endif
-
 void reset_error (glb_ctx *cc, CANL_ERROR err_code);
-void set_error (glb_ctx *cc, CANL_ERROR err_code, const char *err_format, ...);
+void set_error (glb_ctx *cc, CANL_ERROR err_code, CANL_ERROR_ORIGIN err_orig,
+        const char *err_format, ...);
 void update_error (glb_ctx *cc, const char *err_format, ...);
 void free_hostent(struct hostent *h); //TODO is there some standard funcion to free hostent?
 int asyn_getservbyname(int a_family, asyn_result *ares_result,char const *name, 
         struct timeval *tout);
 int ssl_write(glb_ctx *cc, io_handler *io, void *buffer, size_t size, 
         struct timeval *tout);
+
+#endif
 
 int ssl_init(glb_ctx *cc, io_handler *io)
 {
     int err = 0;
+    CANL_ERROR_ORIGIN e_orig = unknown_error;
 
     if (!cc) {
         return EINVAL;
     }
     if (!io) {
         err = EINVAL;
+        e_orig = posix_error;
         goto end;
     }
 
 
 end:
     if (err)
-        set_error(cc, err, "cannot initialize SSL context (ssl_init)");
+        set_error(cc, err, e_orig, "cannot initialize SSL context (ssl_init)");
     return err;
 
 }
             timeout->tv_sec=0;
             timeout->tv_usec=0;
             err = ETIMEDOUT; 
-            set_error (cc, err, "Connection stuck during handshake: timeout reached (do_ssl_connect)");
+            set_error (cc, err, posix_error, "Connection stuck during handshake: timeout reached (do_ssl_connect)");
         }
         else{
             err = -1; //TODO set approp. error message
-            set_error (cc, err, "Error during SSL handshake (do_ssl_connect)");
+            set_error (cc, err, unknown_error,"Error during SSL handshake (do_ssl_connect)");
         }
         return err;
     }
             timeout->tv_sec=0;
             timeout->tv_usec=0;
             err = ETIMEDOUT; 
-            set_error (cc, err, "Connection stuck during handshake: timeout reached (do_ssl_accept)");
+            set_error (cc, err, posix_error, "Connection stuck during handshake: timeout reached (do_ssl_accept)");
         }
         else{
             err = -1; //TODO set approp. error message
-            set_error (cc, err, "Error during SSL handshake (do_ssl_accept)");
+            set_error (cc, err, unknown_error, "Error during SSL handshake (do_ssl_accept)");
         }
         return err;
     }
 
     if (!buffer) {
         err = EINVAL; //TODO really?
-        set_error(cc, err, "Nothing to write (ssl_write)");
+        set_error(cc, err, posix_error, "Nothing to write (ssl_write)");
         errno = err;
         return -1;
     }
 end:
     if (err) {
         errno = err;
-        set_error (cc, err, "Error during SSL write (ssl_write)");
+        set_error (cc, err, posix_error, "Error during SSL write (ssl_write)");
         return -1;
     }
     if (touted){
        errno = err = ETIMEDOUT;
-       set_error(cc, err, "Connection stuck during write: timeout reached (ssl_write)");
+       set_error(cc, err, posix_error, "Connection stuck during write: timeout reached (ssl_write)");
        return -1;
     }
     if (ret <=0){
         err = -1;//TODO what to assign??????
-        set_error (cc, err, "Error during SSL write (ssl_write)");
+        set_error (cc, err, unknown_error, "Error during SSL write (ssl_write)");
     }
     return ret;
 }
 
     if (!buffer) {
         err = EINVAL; //TODO really?
-        set_error(cc, err, "Not enough memory to read to (ssl_read)");
+        set_error(cc, err, posix_error, "Not enough memory to read to (ssl_read)");
         errno = err;
         return -1;
     }
     if (ret <= 0 || ret2 <= 0) { //TODO ret2 < 0 originally
         err = -1; //TODO what to assign
         if (timeout != -1 && (curtime - starttime >= timeout)){
-            set_error(cc, ETIMEDOUT, "Connection stuck during read: timeout reached. (ssl_read)");
+            set_error(cc, ETIMEDOUT, posix_error, "Connection stuck during read: timeout reached. (ssl_read)");
         }
         else
-            set_error(cc, err, "Error during SSL read: (ssl_read)");
+            set_error(cc, err, unknown_error, "Error during SSL read: (ssl_read)");
     }
     else
         err = ret2;