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