misc.c revision a3129944
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	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
72int
73IceFlush (
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
86int
87IceGetOutBufSize (
88	IceConn iceConn
89)
90{
91    return (iceConn->outbufmax - iceConn->outbuf);
92}
93
94
95int
96IceGetInBufSize (
97	IceConn iceConn
98)
99{
100    return (iceConn->inbufmax - iceConn->inbuf);
101}
102
103
104
105/*
106 * informational functions
107 */
108
109IceConnectStatus
110IceConnectionStatus (
111	IceConn iceConn
112)
113{
114    return (iceConn->connection_status);
115}
116
117
118char *
119IceVendor (
120	IceConn iceConn
121)
122{
123    return strdup(iceConn->vendor);
124}
125
126
127char *
128IceRelease (
129	IceConn iceConn
130)
131{
132    return strdup(iceConn->release);
133}
134
135
136int
137IceProtocolVersion (
138	IceConn iceConn
139)
140{
141    return (_IceVersions[iceConn->my_ice_version_index].major_version);
142}
143
144
145int
146IceProtocolRevision (
147	IceConn iceConn
148)
149{
150    return (_IceVersions[iceConn->my_ice_version_index].minor_version);
151}
152
153
154int
155IceConnectionNumber (
156	IceConn iceConn
157)
158{
159    return (_IceTransGetConnectionNumber (iceConn->trans_conn));
160}
161
162
163char *
164IceConnectionString (
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
177unsigned long
178IceLastSentSequenceNumber (
179	IceConn iceConn
180)
181{
182    return (iceConn->send_sequence);
183}
184
185
186unsigned long
187IceLastReceivedSequenceNumber (
188	IceConn iceConn
189)
190{
191    return (iceConn->receive_sequence);
192}
193
194
195Bool
196IceSwapping (
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
212Status
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
310void
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
333void
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
409void
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
491char *
492IceGetPeerName (IceConn iceConn)
493{
494    return (_IceTransGetPeerNetworkId (iceConn->trans_conn));
495}
496
497
498char *
499_IceGetPeerName (IceConn iceConn)
500{
501    return (IceGetPeerName(iceConn));
502}
503