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