1 /******************************************************************************
2
3
4 Copyright 1993, 1998 The Open Group
5
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
10 documentation.
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of The Open Group shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from The Open Group.
25
26 Author: Ralph Mor, X Consortium
27 ******************************************************************************/
28
29 #ifdef WIN32
30 #define _WILLWINSOCK_
31 #endif
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35 #include <X11/ICE/ICElib.h>
36 #include "ICElibint.h"
37 #include <X11/Xtrans/Xtrans.h>
38 #include <stdio.h>
39 #ifdef WIN32
40 #include <X11/Xwinsock.h>
41 #include <X11/Xw32defs.h>
42 #endif
43
44
45 /*
46 * scratch buffer
47 */
48
49 char *
IceAllocScratch(IceConn iceConn,unsigned long size)50 IceAllocScratch (
51 IceConn iceConn,
52 unsigned long size
53 )
54 {
55 if (!iceConn->scratch || size > iceConn->scratch_size)
56 {
57 free (iceConn->scratch);
58
59 iceConn->scratch = malloc (size);
60 iceConn->scratch_size = size;
61 }
62
63 return (iceConn->scratch);
64 }
65
66
67
68 /*
69 * Output/Input buffer functions
70 */
71
72 int
IceFlush(IceConn iceConn)73 IceFlush (
74 IceConn iceConn
75 )
76 {
77 _IceWrite (iceConn,
78 (unsigned long) (iceConn->outbufptr - iceConn->outbuf),
79 iceConn->outbuf);
80
81 iceConn->outbufptr = iceConn->outbuf;
82 return 1;
83 }
84
85
86 int
IceGetOutBufSize(IceConn iceConn)87 IceGetOutBufSize (
88 IceConn iceConn
89 )
90 {
91 return (iceConn->outbufmax - iceConn->outbuf);
92 }
93
94
95 int
IceGetInBufSize(IceConn iceConn)96 IceGetInBufSize (
97 IceConn iceConn
98 )
99 {
100 return (iceConn->inbufmax - iceConn->inbuf);
101 }
102
103
104
105 /*
106 * informational functions
107 */
108
109 IceConnectStatus
IceConnectionStatus(IceConn iceConn)110 IceConnectionStatus (
111 IceConn iceConn
112 )
113 {
114 return (iceConn->connection_status);
115 }
116
117
118 char *
IceVendor(IceConn iceConn)119 IceVendor (
120 IceConn iceConn
121 )
122 {
123 return strdup(iceConn->vendor);
124 }
125
126
127 char *
IceRelease(IceConn iceConn)128 IceRelease (
129 IceConn iceConn
130 )
131 {
132 return strdup(iceConn->release);
133 }
134
135
136 int
IceProtocolVersion(IceConn iceConn)137 IceProtocolVersion (
138 IceConn iceConn
139 )
140 {
141 return (_IceVersions[iceConn->my_ice_version_index].major_version);
142 }
143
144
145 int
IceProtocolRevision(IceConn iceConn)146 IceProtocolRevision (
147 IceConn iceConn
148 )
149 {
150 return (_IceVersions[iceConn->my_ice_version_index].minor_version);
151 }
152
153
154 int
IceConnectionNumber(IceConn iceConn)155 IceConnectionNumber (
156 IceConn iceConn
157 )
158 {
159 return (_IceTransGetConnectionNumber (iceConn->trans_conn));
160 }
161
162
163 char *
IceConnectionString(IceConn iceConn)164 IceConnectionString (
165 IceConn iceConn
166 )
167 {
168 if (iceConn->connection_string)
169 {
170 return strdup(iceConn->connection_string);
171 }
172 else
173 return (NULL);
174 }
175
176
177 unsigned long
IceLastSentSequenceNumber(IceConn iceConn)178 IceLastSentSequenceNumber (
179 IceConn iceConn
180 )
181 {
182 return (iceConn->send_sequence);
183 }
184
185
186 unsigned long
IceLastReceivedSequenceNumber(IceConn iceConn)187 IceLastReceivedSequenceNumber (
188 IceConn iceConn
189 )
190 {
191 return (iceConn->receive_sequence);
192 }
193
194
195 Bool
IceSwapping(IceConn iceConn)196 IceSwapping (
197 IceConn iceConn
198 )
199 {
200 return (iceConn->swap);
201 }
202
203
204
205 /*
206 * Read "n" bytes from a connection.
207 *
208 * Return Status 0 if we detected an EXPECTED closed connection.
209 *
210 */
211
212 Status
_IceRead(register IceConn iceConn,unsigned long nbytes,register char * ptr)213 _IceRead (
214 register IceConn iceConn,
215 unsigned long nbytes,
216 register char *ptr
217 )
218 {
219 register unsigned long nleft;
220
221 nleft = nbytes;
222 while (nleft > 0)
223 {
224 int nread;
225
226 if (iceConn->io_ok)
227 nread = _IceTransRead (iceConn->trans_conn, ptr, (int) nleft);
228 else
229 return (1);
230
231 if (nread <= 0)
232 {
233 #ifdef WIN32
234 errno = WSAGetLastError();
235 #endif
236 if (iceConn->want_to_close)
237 {
238 /*
239 * We sent a WantToClose message and now we detected that
240 * the other side closed the connection.
241 */
242
243 _IceConnectionClosed (iceConn); /* invoke watch procs */
244
245 return (0);
246 }
247 else
248 {
249 /*
250 * Fatal IO error. First notify each protocol's IceIOErrorProc
251 * callback, then invoke the application IO error handler.
252 */
253
254 iceConn->io_ok = False;
255
256 if (iceConn->connection_status == IceConnectPending)
257 {
258 /*
259 * Don't invoke IO error handler if we are in the
260 * middle of a connection setup.
261 */
262
263 return (1);
264 }
265
266 if (iceConn->process_msg_info)
267 {
268 int i;
269
270 for (i = iceConn->his_min_opcode;
271 i <= iceConn->his_max_opcode; i++)
272 {
273 _IceProcessMsgInfo *process;
274
275 process = &iceConn->process_msg_info[
276 i - iceConn->his_min_opcode];
277
278 if ((process != NULL) && process->in_use)
279 {
280 IceIOErrorProc IOErrProc = process->accept_flag ?
281 process->protocol->accept_client->io_error_proc :
282 process->protocol->orig_client->io_error_proc;
283
284 if (IOErrProc)
285 (*IOErrProc) (iceConn);
286 }
287 }
288 }
289
290 (*_IceIOErrorHandler) (iceConn);
291 return (1);
292 }
293 }
294
295 nleft -= nread;
296 ptr += nread;
297 }
298
299 return (1);
300 }
301
302
303
304 /*
305 * If we read a message header with a bad major or minor opcode,
306 * we need to advance to the end of the message. This way, the next
307 * message can be processed correctly.
308 */
309
310 void
_IceReadSkip(register IceConn iceConn,register unsigned long nbytes)311 _IceReadSkip (
312 register IceConn iceConn,
313 register unsigned long nbytes
314 )
315 {
316 char temp[512];
317
318 while (nbytes > 0)
319 {
320 unsigned long rbytes = nbytes > 512 ? 512 : nbytes;
321
322 _IceRead (iceConn, rbytes, temp);
323 nbytes -= rbytes;
324 }
325 }
326
327
328
329 /*
330 * Write "n" bytes to a connection.
331 */
332
333 void
_IceWrite(register IceConn iceConn,unsigned long nbytes,register char * ptr)334 _IceWrite (
335 register IceConn iceConn,
336 unsigned long nbytes,
337 register char *ptr
338 )
339 {
340 register unsigned long nleft;
341
342 nleft = nbytes;
343 while (nleft > 0)
344 {
345 int nwritten;
346
347 if (iceConn->io_ok)
348 nwritten = _IceTransWrite (iceConn->trans_conn, ptr, (int) nleft);
349 else
350 return;
351
352 if (nwritten <= 0)
353 {
354 #ifdef WIN32
355 errno = WSAGetLastError();
356 #endif
357 /*
358 * Fatal IO error. First notify each protocol's IceIOErrorProc
359 * callback, then invoke the application IO error handler.
360 */
361
362 iceConn->io_ok = False;
363
364 if (iceConn->connection_status == IceConnectPending)
365 {
366 /*
367 * Don't invoke IO error handler if we are in the
368 * middle of a connection setup.
369 */
370
371 return;
372 }
373
374 if (iceConn->process_msg_info)
375 {
376 int i;
377
378 for (i = iceConn->his_min_opcode;
379 i <= iceConn->his_max_opcode; i++)
380 {
381 _IceProcessMsgInfo *process;
382
383 process = &iceConn->process_msg_info[
384 i - iceConn->his_min_opcode];
385
386 if (process->in_use)
387 {
388 IceIOErrorProc IOErrProc = process->accept_flag ?
389 process->protocol->accept_client->io_error_proc :
390 process->protocol->orig_client->io_error_proc;
391
392 if (IOErrProc)
393 (*IOErrProc) (iceConn);
394 }
395 }
396 }
397
398 (*_IceIOErrorHandler) (iceConn);
399 return;
400 }
401
402 nleft -= nwritten;
403 ptr += nwritten;
404 }
405 }
406
407
408
409 void
_IceAddOpcodeMapping(IceConn iceConn,int hisOpcode,int myOpcode)410 _IceAddOpcodeMapping (
411 IceConn iceConn,
412 int hisOpcode,
413 int myOpcode
414 )
415 {
416 if (hisOpcode <= 0 || hisOpcode > 255)
417 {
418 return;
419 }
420 else if (iceConn->process_msg_info == NULL)
421 {
422 iceConn->process_msg_info = malloc (sizeof (_IceProcessMsgInfo));
423 iceConn->his_min_opcode = iceConn->his_max_opcode = hisOpcode;
424 }
425 else if (hisOpcode < iceConn->his_min_opcode)
426 {
427 _IceProcessMsgInfo *oldVec = iceConn->process_msg_info;
428 int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1;
429 int newsize = iceConn->his_max_opcode - hisOpcode + 1;
430 int i;
431
432 iceConn->process_msg_info = malloc (
433 newsize * sizeof (_IceProcessMsgInfo));
434
435 memcpy (&iceConn->process_msg_info[
436 iceConn->his_min_opcode - hisOpcode], oldVec,
437 oldsize * sizeof (_IceProcessMsgInfo));
438
439 free (oldVec);
440
441 for (i = hisOpcode + 1; i < iceConn->his_min_opcode; i++)
442 {
443 iceConn->process_msg_info[i -
444 iceConn->his_min_opcode].in_use = False;
445
446 iceConn->process_msg_info[i -
447 iceConn->his_min_opcode].protocol = NULL;
448 }
449
450 iceConn->his_min_opcode = hisOpcode;
451 }
452 else if (hisOpcode > iceConn->his_max_opcode)
453 {
454 _IceProcessMsgInfo *oldVec = iceConn->process_msg_info;
455 int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1;
456 int newsize = hisOpcode - iceConn->his_min_opcode + 1;
457 int i;
458
459 iceConn->process_msg_info = malloc (
460 newsize * sizeof (_IceProcessMsgInfo));
461
462 memcpy (iceConn->process_msg_info, oldVec,
463 oldsize * sizeof (_IceProcessMsgInfo));
464
465 free (oldVec);
466
467 for (i = iceConn->his_max_opcode + 1; i < hisOpcode; i++)
468 {
469 iceConn->process_msg_info[i -
470 iceConn->his_min_opcode].in_use = False;
471
472 iceConn->process_msg_info[i -
473 iceConn->his_min_opcode].protocol = NULL;
474 }
475
476 iceConn->his_max_opcode = hisOpcode;
477 }
478
479 iceConn->process_msg_info[hisOpcode -
480 iceConn->his_min_opcode].in_use = True;
481
482 iceConn->process_msg_info[hisOpcode -
483 iceConn->his_min_opcode].my_opcode = myOpcode;
484
485 iceConn->process_msg_info[hisOpcode -
486 iceConn->his_min_opcode].protocol = &_IceProtocols[myOpcode - 1];
487 }
488
489
490
491 char *
IceGetPeerName(IceConn iceConn)492 IceGetPeerName (IceConn iceConn)
493 {
494 return (_IceTransGetPeerNetworkId (iceConn->trans_conn));
495 }
496
497
498 char *
_IceGetPeerName(IceConn iceConn)499 _IceGetPeerName (IceConn iceConn)
500 {
501 return (IceGetPeerName(iceConn));
502 }
503