New ZOOM connection options: targetImplementation{Id,Name,Version}
[yaz-moved-to-github.git] / zutil / zoom-c.c
index b220b01..1363725 100644 (file)
@@ -1,5 +1,8 @@
 /*
- * $Id: zoom-c.c,v 1.2 2002-09-24 08:05:42 adam Exp $
+ * Copyright (c) 2000-2002, Index Data
+ * See the file LICENSE for details.
+ *
+ * $Id: zoom-c.c,v 1.10 2002-12-09 23:32:29 adam Exp $
  *
  * ZOOM layer for C, connections, result sets, queries.
  */
@@ -8,6 +11,7 @@
 #include <yaz/otherinfo.h>
 #include <yaz/log.h>
 #include <yaz/pquery.h>
+#include <yaz/marcdisp.h>
 #include <yaz/diagbib1.h>
 #include <yaz/charneg.h>
 #include <yaz/ill.h>
@@ -76,6 +80,14 @@ static ZOOM_Event ZOOM_connection_get_event(ZOOM_connection c)
     return event;
 }
 
+static void set_bib1_error (ZOOM_connection c, int error)
+{
+    xfree (c->addinfo);
+    c->addinfo = 0;
+    c->error = error;
+    c->diagset = "Bib-1";
+}
+
 static void clear_error (ZOOM_connection c)
 {
 
@@ -89,9 +101,7 @@ static void clear_error (ZOOM_connection c)
     case ZOOM_ERROR_INTERNAL:
         break;
     default:
-        c->error = ZOOM_ERROR_NONE;
-        xfree (c->addinfo);
-        c->addinfo = 0;
+        set_bib1_error(c, ZOOM_ERROR_NONE);
     }
 }
 
@@ -168,8 +178,8 @@ ZOOM_connection_create (ZOOM_options options)
     c->mask = 0;
     c->reconnect_ok = 0;
     c->state = STATE_IDLE;
-    c->error = ZOOM_ERROR_NONE;
     c->addinfo = 0;
+    set_bib1_error(c, ZOOM_ERROR_NONE);
     c->buf_in = 0;
     c->len_in = 0;
     c->buf_out = 0;
@@ -323,7 +333,7 @@ ZOOM_connection_connect(ZOOM_connection c,
 
     c->async = ZOOM_options_get_bool (c->options, "async", 0);
  
-    c->error = ZOOM_ERROR_NONE;
+    set_bib1_error(c, ZOOM_ERROR_NONE);
 
     task = ZOOM_connection_add_task (c, ZOOM_TASK_CONNECT);
 
@@ -626,7 +636,7 @@ static zoom_ret do_connect (ZOOM_connection c)
        }
     }
     c->state = STATE_IDLE;
-    c->error = ZOOM_ERROR_CONNECT;
+    set_bib1_error(c, ZOOM_ERROR_CONNECT);
     return zoom_complete;
 }
 
@@ -705,7 +715,7 @@ static int encode_APDU(ZOOM_connection c, Z_APDU *a, ODR out)
            odr_destroy(odr_pr);
        }
         yaz_log (LOG_DEBUG, "encoding failed");
-       c->error = ZOOM_ERROR_ENCODE;
+        set_bib1_error(c, ZOOM_ERROR_ENCODE);
        odr_reset(out);
        return -1;
     }
@@ -961,6 +971,7 @@ static zoom_ret ZOOM_connection_send_search (ZOOM_connection c)
 
 static void response_diag (ZOOM_connection c, Z_DiagRec *p)
 {
+    int oclass;
     Z_DefaultDiagFormat *r;
     char *addinfo = 0;
     
@@ -968,10 +979,12 @@ static void response_diag (ZOOM_connection c, Z_DiagRec *p)
     c->addinfo = 0;
     if (p->which != Z_DiagRec_defaultFormat)
     {
-       c->error = ZOOM_ERROR_DECODE;
+        set_bib1_error(c, ZOOM_ERROR_DECODE);
        return;
     }
     r = p->u.defaultFormat;
+    c->diagset = yaz_z3950oid_to_str(r->diagnosticSetId, &oclass);
+
     switch (r->which)
     {
     case Z_DefaultDiagFormat_v2Addinfo:
@@ -1054,18 +1067,19 @@ ZOOM_record_get (ZOOM_record rec, const char *type, int *len)
     }
     else if (!strcmp (type, "syntax"))
     {
+        const char *desc = 0;  
        if (npr->which == Z_NamePlusRecord_databaseRecord)
        {
            Z_External *r = (Z_External *) npr->u.databaseRecord;
            oident *ent = oid_getentbyoid(r->direct_reference);
            if (ent)
-           {
-               if (len)
-                    *len = strlen(ent->desc);
-               return ent->desc;
-           }
+               desc = ent->desc;
        }
-       return "none";
+       if (!desc)
+            desc = "none";
+       if (len)
+            *len = strlen(desc);
+       return desc;
     }
     else if (!strcmp (type, "render") && 
              npr->which == Z_NamePlusRecord_databaseRecord)
@@ -1108,13 +1122,18 @@ ZOOM_record_get (ZOOM_record rec, const char *type, int *len)
         }
         else if (r->which == Z_External_grs1)
         {
-            if (len) *len = 5;
-            return "GRS-1";
+            if (!rec->wrbuf_marc)
+                rec->wrbuf_marc = wrbuf_alloc();
+            wrbuf_rewind (rec->wrbuf_marc);
+            yaz_display_grs1(rec->wrbuf_marc, r->u.grs1, 0);
+            if (len) 
+                *len = wrbuf_len(rec->wrbuf_marc);
+            return wrbuf_buf(rec->wrbuf_marc);
         }
        return 0;
     }
-    else if (!strcmp (type, "xml") && 
-             npr->which == Z_NamePlusRecord_databaseRecord)
+    else if (npr->which == Z_NamePlusRecord_databaseRecord &&
+             (!strcmp (type, "xml") || !strcmp(type, "MarcXML")))
     {
         Z_External *r = (Z_External *) npr->u.databaseRecord;
         oident *ent = oid_getentbyoid(r->direct_reference);
@@ -1126,6 +1145,10 @@ ZOOM_record_get (ZOOM_record rec, const char *type, int *len)
         }
         else if (r->which == Z_External_octet)
         {
+            int marc_decode_type = YAZ_MARC_OAIMARC;
+
+            if (!strcmp(type, "MarcXML"))
+                marc_decode_type = YAZ_MARC_MARCXML;
             switch (ent->value)
             {
             case VAL_SOIF:
@@ -1143,7 +1166,7 @@ ZOOM_record_get (ZOOM_record rec, const char *type, int *len)
                                      r->u.octet_aligned->buf,
                                      rec->wrbuf_marc, 0,
                                      r->u.octet_aligned->len,
-                                     1) > 0)
+                                     marc_decode_type) > 0)
                 {
                     if (len) *len = wrbuf_len(rec->wrbuf_marc);
                     return wrbuf_buf(rec->wrbuf_marc);
@@ -1297,7 +1320,7 @@ static void handle_records (ZOOM_connection c, Z_Records *sr,
        if (sr->u.multipleNonSurDiagnostics->num_diagRecs >= 1)
            response_diag(c, sr->u.multipleNonSurDiagnostics->diagRecs[0]);
        else
-           c->error = ZOOM_ERROR_DECODE;
+            set_bib1_error(c, ZOOM_ERROR_DECODE);
     }
     else 
     {
@@ -1328,7 +1351,7 @@ static void handle_records (ZOOM_connection c, Z_Records *sr,
        else if (present_phase)
        {
            /* present response and we didn't get any records! */
-           c->error = ZOOM_ERROR_DECODE;
+            set_bib1_error(c, ZOOM_ERROR_DECODE);
        }
     }
 }
@@ -2000,9 +2023,18 @@ static void handle_apdu (ZOOM_connection c, Z_APDU *apdu)
     {
     case Z_APDU_initResponse:
        initrs = apdu->u.initResponse;
+        ZOOM_connection_option_set(c, "targetImplementationId",
+                                   initrs->implementationId ?
+                                   initrs->implementationId : "");
+        ZOOM_connection_option_set(c, "targetImplementationName",
+                                   initrs->implementationName ?
+                                   initrs->implementationName : "");
+        ZOOM_connection_option_set(c, "targetImplementationVersion",
+                                   initrs->implementationVersion ?
+                                   initrs->implementationVersion : "");
        if (!*initrs->result)
        {
-           c->error = ZOOM_ERROR_INIT;
+            set_bib1_error(c, ZOOM_ERROR_INIT);
        }
        else
        {
@@ -2035,10 +2067,15 @@ static void handle_apdu (ZOOM_connection c, Z_APDU *apdu)
                 int sel;
                 
                 yaz_get_response_charneg(tmpmem, p, &charset, &lang, &sel);
-                yaz_log(LOG_DEBUG, "Target accepted: charset - %s,"
-                        "language - %s, select - %d",
-                        charset, lang, sel);
-                
+                yaz_log(LOG_DEBUG, "Target accepted: charset %s, "
+                        "language %s, select %d",
+                        charset ? charset : "none", lang ? lang : "none", sel);
+                if (charset)
+                    ZOOM_connection_option_set (c, "negotiation-charset",
+                                                charset);
+                if (lang)
+                    ZOOM_connection_option_set (c, "negotiation-lang",
+                                                lang);
                 nmem_destroy(tmpmem);
             }
        }       
@@ -2075,12 +2112,12 @@ static void handle_apdu (ZOOM_connection c, Z_APDU *apdu)
         }
         else
         {
-            c->error = ZOOM_ERROR_CONNECTION_LOST;
+            set_bib1_error(c, ZOOM_ERROR_CONNECTION_LOST);
             do_close(c);
         }
         break;
     default:
-        c->error = ZOOM_ERROR_DECODE;
+        set_bib1_error(c, ZOOM_ERROR_DECODE);
         do_close(c);
     }
 }
@@ -2124,7 +2161,7 @@ static int do_read (ZOOM_connection c)
         ZOOM_connection_put_event (c, event);
        if (!z_APDU (c->odr_in, &apdu, 0, 0))
        {
-           c->error = ZOOM_ERROR_DECODE;
+            set_bib1_error(c, ZOOM_ERROR_DECODE);
            do_close (c);
        }
        else
@@ -2155,9 +2192,9 @@ static zoom_ret do_write_ex (ZOOM_connection c, char *buf_out, int len_out)
             return zoom_complete;
         }
        if (c->state == STATE_CONNECTING)
-           c->error = ZOOM_ERROR_CONNECT;
+           set_bib1_error(c, ZOOM_ERROR_CONNECT);
        else
-           c->error = ZOOM_ERROR_CONNECTION_LOST;
+            set_bib1_error(c, ZOOM_ERROR_CONNECTION_LOST);
        do_close (c);
        return zoom_complete;
     }
@@ -2172,7 +2209,6 @@ static zoom_ret do_write_ex (ZOOM_connection c, char *buf_out, int len_out)
     }
     else
     {
-        // c->reconnect_ok = 0;
         c->mask = ZOOM_SELECT_READ|ZOOM_SELECT_EXCEPT;
         yaz_log (LOG_DEBUG, "do_write_ex 2 mask=%d", c->mask);
     }
@@ -2234,47 +2270,57 @@ ZOOM_connection_addinfo (ZOOM_connection c)
     return addinfo;
 }
 
+ZOOM_API(const char *)
+ZOOM_diag_str (int error)
+{
+    switch (error)
+    {
+    case ZOOM_ERROR_NONE:
+       return "No error";
+    case ZOOM_ERROR_CONNECT:
+       return "Connect failed";
+    case ZOOM_ERROR_MEMORY:
+       return "Out of memory";
+    case ZOOM_ERROR_ENCODE:
+       return "Encoding failed";
+    case ZOOM_ERROR_DECODE:
+       return "Decoding failed";
+    case ZOOM_ERROR_CONNECTION_LOST:
+       return "Connection lost";
+    case ZOOM_ERROR_INIT:
+       return "Init rejected";
+    case ZOOM_ERROR_INTERNAL:
+       return "Internal failure";
+    case ZOOM_ERROR_TIMEOUT:
+       return "Timeout";
+    default:
+       return diagbib1_str (error);
+    }
+}
+
 ZOOM_API(int)
-ZOOM_connection_error (ZOOM_connection c, const char **cp,
-                           const char **addinfo)
+ZOOM_connection_error_x (ZOOM_connection c, const char **cp,
+                         const char **addinfo, const char **diagset)
 {
     int error = c->error;
     if (cp)
     {
-       switch (error)
-       {
-       case ZOOM_ERROR_NONE:
-           *cp = "No error"; break;
-       case ZOOM_ERROR_CONNECT:
-           *cp = "Connect failed"; break;
-       case ZOOM_ERROR_MEMORY:
-           *cp = "Out of memory"; break;
-       case ZOOM_ERROR_ENCODE:
-           *cp = "Encoding failed"; break;
-       case ZOOM_ERROR_DECODE:
-           *cp = "Decoding failed"; break;
-       case ZOOM_ERROR_CONNECTION_LOST:
-           *cp = "Connection lost"; break;
-       case ZOOM_ERROR_INIT:
-           *cp = "Init rejected"; break;
-       case ZOOM_ERROR_INTERNAL:
-           *cp = "Internal failure"; break;
-       case ZOOM_ERROR_TIMEOUT:
-           *cp = "Timeout"; break;
-       default:
-           *cp = diagbib1_str (error);
-       }
+       *cp = ZOOM_diag_str(error);
     }
     if (addinfo)
-    {
-       if (c->addinfo)
-           *addinfo = c->addinfo;
-       else
-           *addinfo = "";
-    }
+        *addinfo = c->addinfo ? c->addinfo : "";
+    if (diagset)
+        *diagset = c->diagset ? c->diagset : "";
     return c->error;
 }
 
+ZOOM_API(int)
+ZOOM_connection_error (ZOOM_connection c, const char **cp,
+                       const char **addinfo)
+{
+    return ZOOM_connection_error_x(c, cp, addinfo, 0);
+}
+
 static int ZOOM_connection_do_io(ZOOM_connection c, int mask)
 {
     ZOOM_Event event = 0;
@@ -2285,7 +2331,7 @@ static int ZOOM_connection_do_io(ZOOM_connection c, int mask)
     if (r == CS_NONE)
     {
         event = ZOOM_Event_create (ZOOM_EVENT_CONNECT);
-       c->error = ZOOM_ERROR_CONNECT;
+       set_bib1_error(c, ZOOM_ERROR_CONNECT);
        do_close (c);
         ZOOM_connection_put_event (c, event);
     }
@@ -2313,7 +2359,7 @@ static int ZOOM_connection_do_io(ZOOM_connection c, int mask)
         }
         else
         {
-            c->error = ZOOM_ERROR_CONNECT;
+            set_bib1_error(c, ZOOM_ERROR_CONNECT);
             do_close (c);
             ZOOM_connection_put_event (c, event);
         }
@@ -2462,7 +2508,7 @@ ZOOM_event (int no, ZOOM_connection *cs)
         {
             ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_TIMEOUT);
            /* timeout and this connection was waiting */
-           c->error = ZOOM_ERROR_TIMEOUT;
+           set_bib1_error(c, ZOOM_ERROR_TIMEOUT);
             do_close (c);
             ZOOM_connection_put_event(c, event);
         }
@@ -2498,7 +2544,7 @@ ZOOM_event (int no, ZOOM_connection *cs)
        {
             ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_TIMEOUT);
            /* timeout and this connection was waiting */
-           c->error = ZOOM_ERROR_TIMEOUT;
+           set_bib1_error(c, ZOOM_ERROR_TIMEOUT);
             do_close (c);
             yaz_log (LOG_DEBUG, "timeout");
             ZOOM_connection_put_event(c, event);