Fixed problem processEvent which in rare cases return 0.
[yazpp-moved-to-github.git] / src / yaz-z-server.cpp
1 /*
2  * Copyright (c) 2000-2001, Index Data.
3  * See the file LICENSE for details.
4  * 
5  * $Id: yaz-z-server.cpp,v 1.13 2001-11-04 22:36:21 adam Exp $
6  */
7
8 #include <yaz/log.h>
9 #include <yaz++/yaz-z-server.h>
10
11 Yaz_Z_Server::Yaz_Z_Server(IYaz_PDU_Observable *the_PDU_Observable)
12     : Yaz_Z_Assoc(the_PDU_Observable)
13 {
14     m_facilities = 0;
15 }
16
17 Yaz_Z_Server::~Yaz_Z_Server()
18 {
19     facility_reset();
20 }
21
22 void Yaz_Z_Server::facility_reset ()
23 {
24     Yaz_Z_Server_Facility_Info *p = m_facilities;
25     while (p)
26     {
27         Yaz_Z_Server_Facility_Info *p_next = p->m_next;
28
29         delete [] p->m_name;
30         delete p;
31         p = p_next;
32     }
33     m_facilities = 0;
34 }
35
36 void Yaz_Z_Server::facility_add(IYaz_Server_Facility *facility,
37                                 const char *name)
38 {
39     Yaz_Z_Server_Facility_Info **p = &m_facilities;
40     while (*p)
41         p = &(*p)->m_next;
42
43     *p = new Yaz_Z_Server_Facility_Info;
44
45     (*p)->m_next = 0;
46     (*p)->m_name = new char [strlen(name)+1];
47     strcpy ((*p)->m_name, name);
48     (*p)->m_facility = facility;
49 }
50
51 void Yaz_Z_Server::recv_Z_PDU (Z_APDU *apdu_request)
52 {   
53     Yaz_Z_Server_Facility_Info *f = m_facilities;
54     
55     if (apdu_request->which == Z_APDU_initRequest)
56     {
57         Z_APDU *apdu_response = create_Z_PDU(Z_APDU_initResponse);
58
59         Z_InitRequest *req = apdu_request->u.initRequest;
60         Z_InitResponse *resp = apdu_response->u.initResponse;
61         
62         if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_1))
63         {
64             ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_1);
65         }
66         if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_2))
67         {
68             ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_2);
69         }
70         if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_3))
71         {
72             ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_3);
73         }
74         while (f)
75         {
76             f->m_facility->init(this, req, resp);
77             f = f->m_next;
78         }
79         transfer_referenceId(apdu_request, apdu_response);
80         send_Z_PDU(apdu_response);
81     }
82     else
83     {
84         f = m_facilities;
85         int taken = 0;
86         while (f)
87         {
88             taken = f->m_facility->recv(this, apdu_request);
89             if (taken)
90                 break;
91             f = f->m_next;
92         }
93         if (!taken)
94         {
95             yaz_log (LOG_WARN, "unhandled request = %d", apdu_request->which);
96             delete this;
97         }
98     }
99 }
100
101 /*
102  * database record.
103  */
104 void Yaz_Z_ServerUtility::create_databaseRecord (
105     ODR odr, Z_NamePlusRecord *rec, const char *dbname, int format,
106     const void *buf, int len)
107 {
108     rec->databaseName = dbname ? odr_strdup (odr, dbname) : 0;
109     rec->which = Z_NamePlusRecord_databaseRecord;
110     rec->u.databaseRecord = z_ext_record (odr, format,
111                                           (const char *) buf, len);
112 }
113
114 /*
115  * surrogate diagnostic.
116  */
117 void Yaz_Z_ServerUtility::create_surrogateDiagnostics(
118     ODR odr, Z_NamePlusRecord *rec, const char *dbname,
119     int error, char *const addinfo)
120 {
121     int oid[OID_SIZE];
122     int *err = (int *)odr_malloc (odr, sizeof(*err));
123     oident bib1;
124     Z_DiagRec *drec = (Z_DiagRec *)odr_malloc (odr, sizeof(*drec));
125     Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *)
126         odr_malloc (odr, sizeof(*dr));
127     
128     bib1.proto = PROTO_Z3950;
129     bib1.oclass = CLASS_DIAGSET;
130     bib1.value = VAL_BIB1;
131
132     yaz_log(LOG_DEBUG, "SurrogateDiagnotic: %d -- %s", error, addinfo);
133     *err = error;
134     rec->databaseName = dbname ? odr_strdup (odr, dbname) : 0;
135     rec->which = Z_NamePlusRecord_surrogateDiagnostic;
136     rec->u.surrogateDiagnostic = drec;
137     drec->which = Z_DiagRec_defaultFormat;
138     drec->u.defaultFormat = dr;
139     dr->diagnosticSetId = odr_oiddup (odr,
140                                       oid_ent_to_oid(&bib1, oid));
141     dr->condition = err;
142     dr->which = Z_DefaultDiagFormat_v2Addinfo;
143     dr->u.v2Addinfo = odr_strdup (odr, addinfo ? addinfo : "");
144 }
145
146 Z_Records *Yaz_Z_ServerUtility::create_nonSurrogateDiagnostics (
147     ODR odr, int error, const char *addinfo)
148 {
149     int oid[OID_SIZE];
150     Z_Records *rec = (Z_Records *)
151         odr_malloc (odr, sizeof(*rec));
152     oident bib1;
153     int *err = (int *)
154         odr_malloc (odr, sizeof(*err));
155     Z_DiagRec *drec = (Z_DiagRec *)
156         odr_malloc (odr, sizeof(*drec));
157     Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *)
158         odr_malloc (odr, sizeof(*dr));
159
160     bib1.proto = PROTO_Z3950;
161     bib1.oclass = CLASS_DIAGSET;
162     bib1.value = VAL_BIB1;
163
164     *err = error;
165     rec->which = Z_Records_NSD;
166     rec->u.nonSurrogateDiagnostic = dr;
167     dr->diagnosticSetId =
168         odr_oiddup (odr, oid_ent_to_oid(&bib1, oid));
169     dr->condition = err;
170     dr->which = Z_DefaultDiagFormat_v2Addinfo;
171     dr->u.v2Addinfo = odr_strdup (odr, addinfo ? addinfo : "");
172     return rec;
173 }