1 /*
2 * Copyright (c) 2001 Tommy Bohlin <tommy@gatespace.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26 /* iasclt.c
27 */
28
29 #include <irda.h>
30 #include <ias.h>
31
32 #include <string.h>
33
34 /**********************************************************************
35 * Constants
36 **********************************************************************/
37
38 static const char id_client[]="ias client";
39 static const char id_inbuf[]="ias client inbuf";
40
41 /**********************************************************************
42 * Data structures
43 **********************************************************************/
44
45 typedef struct IASClientPrivate {
46 IASClient ias;
47 Connection* con;
48
49 bool busy;
50 int op;
51
52 int outOfs;
53 int outLength;
54 u_char outBuf[256];
55
56 int inOfs;
57 int inLength;
58 int inMax;
59 u_char* inBuf;
60 } IASClientPrivate;
61
62 /**********************************************************************
63 * Internal functions
64 **********************************************************************/
65
sendACK(Connection * con,int op)66 static void sendACK(Connection* con, int op)
67 {
68 u_char hdr[1];
69
70 hdr[0]=op|IAS_ACK|IAS_LAST;
71 connWrite(con,hdr,1);
72 }
73
status(Connection * con,int event,void * buf,int len)74 static void status(Connection* con, int event, void* buf, int len)
75 {
76 IASClientPrivate* iasp=(IASClientPrivate*)con->handle;
77
78 if(event==CONN_CLOSED) {
79 if(iasp->ias.debug&IAS_DEBUG_INFO) birda_log("ias connection closed\n");
80 connClose(con);
81 iasp->con=0;
82
83 if(iasp->busy) {
84 iasp->busy=FALSE;
85 freeMem(iasp->inBuf);
86 iasp->inBuf=0;
87 if(iasp->ias.status) iasp->ias.status(&iasp->ias,IAS_QUERY_FAILED);
88 }
89 }
90 }
91
sendChunk(IASClientPrivate * iasp)92 static void sendChunk(IASClientPrivate* iasp)
93 {
94 int n=iasp->outLength-iasp->outOfs;
95 int k=connGetSendDataSize(iasp->con)-1;
96 u_char hdr[1];
97 if(k>n) k=n;
98 hdr[0]=iasp->op;
99 if(k==n) hdr[0]|=IAS_LAST;
100 connWrite2(iasp->con,hdr,1,iasp->outBuf,k);
101 iasp->outOfs+=k;
102 }
103
data(Connection * con,void * buf0,int len)104 static void data(Connection* con, void* buf0, int len)
105 {
106 u_char* buf=(u_char*)buf0;
107 IASClientPrivate* iasp=(IASClientPrivate*)con->handle;
108 u_char op;
109
110 /* Just ignore null input, OK? */
111 if(len<1) return;
112 op=buf[0]&~(IAS_LAST|IAS_ACK);
113
114 if(!iasp->busy || op!=iasp->op) {
115 status(con,CONN_CLOSED,0,0);
116 return;
117 }
118
119 if(iasp->outOfs<iasp->outLength) {
120 if((buf[0]&IAS_ACK) && op==iasp->op) sendChunk(iasp);
121 else {
122 status(con,CONN_CLOSED,0,0);
123 }
124 return;
125 }
126 if(buf[0]&IAS_ACK) return;
127
128 while(iasp->inMax<iasp->inLength+len-1) {
129 iasp->inMax*=2;
130 iasp->inBuf=growMem(iasp->inBuf,iasp->inMax);
131 }
132
133 memcpy(iasp->inBuf+iasp->inLength,buf+1,len-1);
134 iasp->inLength+=len-1;
135
136 if(buf[0]&IAS_LAST) {
137 iasp->busy=FALSE;
138
139 iasp->inOfs=3;
140 if(iasp->inLength>0 && iasp->inBuf[0]!=IAS_SUCCESS) iasp->inLength=0;
141
142 if(iasp->ias.status) iasp->ias.status(&iasp->ias,IAS_QUERY_COMPLETE);
143 } else {
144 sendACK(con,op);
145 }
146 }
147
148 /**********************************************************************
149 * External functions
150 **********************************************************************/
151
iasCltGetValueByClass(IASClient * ias,const char * class,const char * name)152 bool iasCltGetValueByClass(IASClient* ias, const char* class, const char* name)
153 {
154 IASClientPrivate* iasp=(IASClientPrivate*)ias;
155
156 if(iasp->con && !iasp->busy) {
157 int clen=strlen(class);
158 int nlen=strlen(name);
159 if(clen>60) clen=60;
160 if(nlen>60) nlen=60;
161 iasp->outBuf[0]=clen;
162 memcpy(iasp->outBuf+1,class,clen);
163 iasp->outBuf[1+clen]=nlen;
164 memcpy(iasp->outBuf+2+clen,name,nlen);
165
166 iasp->busy=TRUE;
167 iasp->op=OP_GetValueByClass;
168 iasp->outOfs=0;
169 iasp->outLength=2+clen+nlen;
170 iasp->inLength=0;
171
172 sendChunk(iasp);
173 return TRUE;
174 }
175 return FALSE;
176 }
177
iasCltClose(IASClient * ias)178 void iasCltClose(IASClient* ias)
179 {
180 IASClientPrivate* iasp=(IASClientPrivate*)ias;
181
182 if(iasp->con) connClose(iasp->con);
183 if(iasp->inBuf) freeMem(iasp->inBuf);
184 freeMem(iasp);
185 }
186
iasCltShowResult(IASClient * ias)187 void iasCltShowResult(IASClient* ias)
188 {
189 int type,id;
190
191 while((type=iasCltResType(ias))!=IAS_NONE) {
192 id=iasCltResId(ias);
193 switch(type) {
194 case IAS_INT:
195 birda_log(" %d. int %d\n",id,iasCltResInt(ias));
196 break;
197 case IAS_OCTETS:
198 birda_log(" %d. octets ",id);
199 showBytes(iasCltResPtr(ias),iasCltResLength(ias));
200 break;
201 case IAS_STRING:
202 birda_log(" %d. string %.*s\n",id,
203 iasCltResLength(ias),(char*)iasCltResPtr(ias));
204 break;
205 }
206 iasCltResNext(ias);
207 }
208 }
209
iasCltResType(IASClient * ias)210 int iasCltResType(IASClient* ias)
211 {
212 IASClientPrivate* iasp=(IASClientPrivate*)ias;
213
214 if(iasp->busy || !iasp->inBuf) return IAS_NONE;
215 for(;;) {
216 int i=iasp->inOfs;
217 int n=iasp->inLength-i;
218
219 if(n<3) return IAS_NONE;
220 switch(iasp->inBuf[i+2]) {
221 case IAS_NONE:
222 iasp->inOfs+=3;
223 continue;
224 case IAS_INT:
225 if(n>=7) return IAS_INT;
226 break;
227 case IAS_OCTETS:
228 if(n>=5 && n>=getBEShort(iasp->inBuf+i+3)+5) return IAS_OCTETS;
229 break;
230 case IAS_STRING:
231 if(n>=5 && n>=iasp->inBuf[i+4]+5) return IAS_STRING;
232 break;
233 }
234 iasp->inOfs=iasp->inLength;
235 return IAS_NONE;
236 }
237 }
238
iasCltResId(IASClient * ias)239 int iasCltResId(IASClient* ias)
240 {
241 IASClientPrivate* iasp=(IASClientPrivate*)ias;
242
243 return getBEShort(iasp->inBuf+iasp->inOfs);
244 }
245
iasCltResInt(IASClient * ias)246 int iasCltResInt(IASClient* ias)
247 {
248 IASClientPrivate* iasp=(IASClientPrivate*)ias;
249
250 return getBELong(iasp->inBuf+iasp->inOfs+3);
251 }
252
iasCltResCharSet(IASClient * ias)253 int iasCltResCharSet(IASClient* ias)
254 {
255 IASClientPrivate* iasp=(IASClientPrivate*)ias;
256
257 return iasp->inBuf[iasp->inOfs+3];
258 }
259
iasCltResLength(IASClient * ias)260 int iasCltResLength(IASClient* ias)
261 {
262 IASClientPrivate* iasp=(IASClientPrivate*)ias;
263
264 switch(iasp->inBuf[iasp->inOfs+2]) {
265 case IAS_INT: return 4;
266 case IAS_OCTETS: return getBEShort(iasp->inBuf+iasp->inOfs+3);
267 case IAS_STRING: return iasp->inBuf[iasp->inOfs+4];
268 default: return 0;
269 }
270 }
271
iasCltResPtr(IASClient * ias)272 void* iasCltResPtr(IASClient* ias)
273 {
274 IASClientPrivate* iasp=(IASClientPrivate*)ias;
275
276 return iasp->inBuf+iasp->inOfs+5;
277 }
278
iasCltResNext(IASClient * ias)279 void iasCltResNext(IASClient* ias)
280 {
281 IASClientPrivate* iasp=(IASClientPrivate*)ias;
282 int i=iasp->inOfs;
283
284 switch(iasp->inBuf[i+2]) {
285 case IAS_INT:
286 iasp->inOfs+=7;
287 break;
288 case IAS_OCTETS:
289 iasp->inOfs+=5+getBEShort(iasp->inBuf+i+3);
290 break;
291 case IAS_STRING:
292 iasp->inOfs+=5+iasp->inBuf[i+4];
293 break;
294 }
295 }
296
createIASClient(LAP * lap)297 IASClient* createIASClient(LAP* lap)
298 {
299 IASClientPrivate* iasp;
300 Connection* con=lapNewConnection(lap,IAS_LSAPSEL,0,0,0);
301 if(!con) return 0;
302
303 iasp=allocMem(id_client,sizeof(IASClientPrivate));
304 iasp->ias.handle=0;
305 iasp->ias.status=0;
306 iasp->con=con;
307 iasp->con->handle=iasp;
308 iasp->con->status=status;
309 iasp->con->data=data;
310 iasp->busy=FALSE;
311 iasp->outOfs=0;
312 iasp->outLength=0;
313 iasp->inLength=0;
314 iasp->inMax=256;
315 iasp->inBuf=allocMem(id_inbuf,iasp->inMax);
316
317 return &iasp->ias;
318 }
319