Added referenceId handling for server.
[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  * $Log: yaz-z-server.cpp,v $
6  * Revision 1.11  2001-04-12 15:12:10  heikki
7  * minor ursula stuff
8  *
9  * Revision 1.10  2001/04/04 14:02:49  adam
10  * URSULA / Z-ruth service.
11  *
12  * Revision 1.9  2001/03/29 15:14:26  adam
13  * Minor updates.
14  *
15  * Revision 1.8  2001/03/27 14:47:45  adam
16  * New server facility scheme.
17  *
18  * Revision 1.7  2001/03/26 14:43:49  adam
19  * New threaded PDU association.
20  *
21  * Revision 1.6  2001/01/29 11:18:24  adam
22  * Server sets OPTIONS search and present.
23  *
24  * Revision 1.5  2000/10/24 12:29:57  adam
25  * Fixed bug in proxy where a Yaz_ProxyClient could be owned by
26  * two Yaz_Proxy's (fatal).
27  *
28  * Revision 1.4  2000/10/11 11:58:17  adam
29  * Moved header files to include/yaz++. Switched to libtool and automake.
30  * Configure script creates yaz++-config script.
31  *
32  * Revision 1.3  2000/09/21 21:43:20  adam
33  * Better high-level server API.
34  *
35  * Revision 1.2  2000/09/12 12:09:53  adam
36  * More work on high-level server.
37  *
38  * Revision 1.1  2000/09/08 10:23:42  adam
39  * Added skeleton of yaz-z-server.
40  *
41  */
42
43 #include <yaz/log.h>
44 #include <yaz++/yaz-z-server.h>
45
46 Yaz_Z_Server::Yaz_Z_Server(IYaz_PDU_Observable *the_PDU_Observable)
47     : Yaz_Z_Assoc(the_PDU_Observable)
48 {
49     m_facilities = 0;
50 }
51
52 Yaz_Z_Server::~Yaz_Z_Server()
53 {
54     facility_reset();
55 }
56
57 void Yaz_Z_Server::facility_reset ()
58 {
59     Yaz_Z_Server_Facility_Info *p = m_facilities;
60     while (p)
61     {
62         Yaz_Z_Server_Facility_Info *p_next = p->m_next;
63
64         delete [] p->m_name;
65         delete p;
66         p = p_next;
67     }
68     m_facilities = 0;
69 }
70
71 void Yaz_Z_Server::facility_add(IYaz_Server_Facility *facility,
72                                 const char *name)
73 {
74     Yaz_Z_Server_Facility_Info **p = &m_facilities;
75     while (*p)
76         p = &(*p)->m_next;
77
78     *p = new Yaz_Z_Server_Facility_Info;
79
80     (*p)->m_next = 0;
81     (*p)->m_name = new char [strlen(name)+1];
82     strcpy ((*p)->m_name, name);
83     (*p)->m_facility = facility;
84 }
85
86 void Yaz_Z_Server::recv_Z_PDU (Z_APDU *apdu_request)
87 {   
88     Yaz_Z_Server_Facility_Info *f = m_facilities;
89     
90     if (apdu_request->which == Z_APDU_initRequest)
91     {
92         Z_APDU *apdu_response = create_Z_PDU(Z_APDU_initResponse);
93
94         Z_InitRequest *req = apdu_request->u.initRequest;
95         Z_InitResponse *resp = apdu_response->u.initResponse;
96         
97         if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_1))
98         {
99             ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_1);
100         }
101         if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_2))
102         {
103             ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_2);
104         }
105         if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_3))
106         {
107             ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_3);
108         }
109         while (f)
110         {
111             f->m_facility->init(this, req, resp);
112             f = f->m_next;
113         }
114         send_Z_PDU(apdu_response);
115     }
116     else
117     {
118         f = m_facilities;
119         int taken = 0;
120         while (f)
121         {
122             taken = f->m_facility->recv(this, apdu_request);
123             if (taken)
124                 break;
125             f = f->m_next;
126         }
127         if (!taken)
128         {
129             yaz_log (LOG_LOG, "unhandled request = %d", apdu_request->which);
130             delete this;
131         }
132     }
133 }
134
135 /*
136  * database record.
137  */
138 void Yaz_Z_ServerUtility::create_databaseRecord (
139     ODR odr, Z_NamePlusRecord *rec, const char *dbname, int format,
140     const void *buf, int len)
141 {
142     rec->databaseName = dbname ? odr_strdup (odr, dbname) : 0;
143     rec->which = Z_NamePlusRecord_databaseRecord;
144     rec->u.databaseRecord = z_ext_record (odr, format,
145                                           (const char *) buf, len);
146 }
147
148 /*
149  * surrogate diagnostic.
150  */
151 void Yaz_Z_ServerUtility::create_surrogateDiagnostics(
152     ODR odr, Z_NamePlusRecord *rec, const char *dbname,
153     int error, char *const addinfo)
154 {
155     int oid[OID_SIZE];
156     int *err = (int *)odr_malloc (odr, sizeof(*err));
157     oident bib1;
158     Z_DiagRec *drec = (Z_DiagRec *)odr_malloc (odr, sizeof(*drec));
159     Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *)
160         odr_malloc (odr, sizeof(*dr));
161     
162     bib1.proto = PROTO_Z3950;
163     bib1.oclass = CLASS_DIAGSET;
164     bib1.value = VAL_BIB1;
165
166     yaz_log(LOG_DEBUG, "SurrogateDiagnotic: %d -- %s", error, addinfo);
167     *err = error;
168     rec->databaseName = dbname ? odr_strdup (odr, dbname) : 0;
169     rec->which = Z_NamePlusRecord_surrogateDiagnostic;
170     rec->u.surrogateDiagnostic = drec;
171     drec->which = Z_DiagRec_defaultFormat;
172     drec->u.defaultFormat = dr;
173     dr->diagnosticSetId = odr_oiddup (odr,
174                                       oid_ent_to_oid(&bib1, oid));
175     dr->condition = err;
176     dr->which = Z_DefaultDiagFormat_v2Addinfo;
177     dr->u.v2Addinfo = odr_strdup (odr, addinfo ? addinfo : "");
178 }
179
180 Z_Records *Yaz_Z_ServerUtility::create_nonSurrogateDiagnostics (
181     ODR odr, int error, const char *addinfo)
182 {
183     int oid[OID_SIZE];
184     Z_Records *rec = (Z_Records *)
185         odr_malloc (odr, sizeof(*rec));
186     oident bib1;
187     int *err = (int *)
188         odr_malloc (odr, sizeof(*err));
189     Z_DiagRec *drec = (Z_DiagRec *)
190         odr_malloc (odr, sizeof(*drec));
191     Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *)
192         odr_malloc (odr, sizeof(*dr));
193
194     bib1.proto = PROTO_Z3950;
195     bib1.oclass = CLASS_DIAGSET;
196     bib1.value = VAL_BIB1;
197
198     *err = error;
199     rec->which = Z_Records_NSD;
200     rec->u.nonSurrogateDiagnostic = dr;
201     dr->diagnosticSetId =
202         odr_oiddup (odr, oid_ent_to_oid(&bib1, oid));
203     dr->condition = err;
204     dr->which = Z_DefaultDiagFormat_v2Addinfo;
205     dr->u.v2Addinfo = odr_strdup (odr, addinfo ? addinfo : "");
206     return rec;
207 }