misc.c revision fb5e8d76
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 = malloc (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
410
411void
412_IceAddOpcodeMapping (
413	IceConn	iceConn,
414	int 	hisOpcode,
415	int 	myOpcode
416)
417{
418    if (hisOpcode <= 0 || hisOpcode > 255)
419    {
420	return;
421    }
422    else if (iceConn->process_msg_info == NULL)
423    {
424	iceConn->process_msg_info = malloc (sizeof (_IceProcessMsgInfo));
425	iceConn->his_min_opcode = iceConn->his_max_opcode = hisOpcode;
426    }
427    else if (hisOpcode < iceConn->his_min_opcode)
428    {
429	_IceProcessMsgInfo *oldVec = iceConn->process_msg_info;
430	int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1;
431	int newsize = iceConn->his_max_opcode - hisOpcode + 1;
432	int i;
433
434	iceConn->process_msg_info = malloc (
435	    newsize * sizeof (_IceProcessMsgInfo));
436
437	memcpy (&iceConn->process_msg_info[
438	    iceConn->his_min_opcode - hisOpcode], oldVec,
439	    oldsize * sizeof (_IceProcessMsgInfo));
440
441	free (oldVec);
442
443	for (i = hisOpcode + 1; i < iceConn->his_min_opcode; i++)
444	{
445	    iceConn->process_msg_info[i -
446		iceConn->his_min_opcode].in_use = False;
447
448	    iceConn->process_msg_info[i -
449		iceConn->his_min_opcode].protocol = NULL;
450	}
451
452	iceConn->his_min_opcode = hisOpcode;
453    }
454    else if (hisOpcode > iceConn->his_max_opcode)
455    {
456	_IceProcessMsgInfo *oldVec = iceConn->process_msg_info;
457	int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1;
458	int newsize = hisOpcode - iceConn->his_min_opcode + 1;
459	int i;
460
461	iceConn->process_msg_info = malloc (
462	    newsize * sizeof (_IceProcessMsgInfo));
463
464	memcpy (iceConn->process_msg_info, oldVec,
465	    oldsize * sizeof (_IceProcessMsgInfo));
466
467	free (oldVec);
468
469	for (i = iceConn->his_max_opcode + 1; i < hisOpcode; i++)
470	{
471	    iceConn->process_msg_info[i -
472		iceConn->his_min_opcode].in_use = False;
473
474	    iceConn->process_msg_info[i -
475		iceConn->his_min_opcode].protocol = NULL;
476	}
477
478	iceConn->his_max_opcode = hisOpcode;
479    }
480
481    iceConn->process_msg_info[hisOpcode -
482	iceConn->his_min_opcode].in_use = True;
483
484    iceConn->process_msg_info[hisOpcode -
485	iceConn->his_min_opcode].my_opcode = myOpcode;
486
487    iceConn->process_msg_info[hisOpcode -
488	iceConn->his_min_opcode].protocol = &_IceProtocols[myOpcode - 1];
489}
490
491
492
493char *
494IceGetPeerName (IceConn iceConn)
495{
496    return (_IceTransGetPeerNetworkId (iceConn->trans_conn));
497}
498
499
500char *
501_IceGetPeerName (IceConn iceConn)
502{
503    return (IceGetPeerName(iceConn));
504}
505