misc.c revision 3bf3b463
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 * Fatal IO error.  First notify each protocol's IceIOErrorProc
68 * callback, then invoke the application IO error handler.
69 */
70
71static void _X_COLD
72IceFatalIOError (
73	IceConn	iceConn
74)
75{
76    iceConn->io_ok = False;
77
78    if (iceConn->connection_status == IceConnectPending)
79    {
80	/*
81	 * Don't invoke IO error handler if we are in the
82	 * middle of a connection setup.
83	 */
84
85	return;
86    }
87
88    if (iceConn->process_msg_info)
89    {
90	for (int i = iceConn->his_min_opcode;
91	     i <= iceConn->his_max_opcode; i++)
92	{
93	    _IceProcessMsgInfo *process;
94
95	    process = &iceConn->process_msg_info[i - iceConn->his_min_opcode];
96
97	    if ((process != NULL) && process->in_use)
98	    {
99		IceIOErrorProc IOErrProc = process->accept_flag ?
100		    process->protocol->accept_client->io_error_proc :
101		    process->protocol->orig_client->io_error_proc;
102
103		if (IOErrProc)
104		    (*IOErrProc) (iceConn);
105	    }
106	}
107    }
108
109    (*_IceIOErrorHandler) (iceConn);
110    return;
111}
112
113/*
114 * Output/Input buffer functions
115 */
116
117int
118IceFlush (
119	IceConn iceConn
120)
121{
122    /*
123     * Should be impossible, unless we messed up our buffer math somewhere,
124     * or one of our pointers has been corrupted.
125     */
126    if (_X_UNLIKELY(iceConn->outbufptr > iceConn->outbufmax))
127    {
128	IceFatalIOError (iceConn);
129	return 0;
130    }
131
132    _IceWrite (iceConn,
133	(unsigned long) (iceConn->outbufptr - iceConn->outbuf),
134	iceConn->outbuf);
135
136    iceConn->outbufptr = iceConn->outbuf;
137    return 1;
138}
139
140
141int
142IceGetOutBufSize (
143	IceConn iceConn
144)
145{
146    return (iceConn->outbufmax - iceConn->outbuf);
147}
148
149
150int
151IceGetInBufSize (
152	IceConn iceConn
153)
154{
155    return (iceConn->inbufmax - iceConn->inbuf);
156}
157
158
159
160/*
161 * informational functions
162 */
163
164IceConnectStatus
165IceConnectionStatus (
166	IceConn iceConn
167)
168{
169    return (iceConn->connection_status);
170}
171
172
173char *
174IceVendor (
175	IceConn iceConn
176)
177{
178    return strdup(iceConn->vendor);
179}
180
181
182char *
183IceRelease (
184	IceConn iceConn
185)
186{
187    return strdup(iceConn->release);
188}
189
190
191int
192IceProtocolVersion (
193	IceConn iceConn
194)
195{
196    return (_IceVersions[iceConn->my_ice_version_index].major_version);
197}
198
199
200int
201IceProtocolRevision (
202	IceConn iceConn
203)
204{
205    return (_IceVersions[iceConn->my_ice_version_index].minor_version);
206}
207
208
209int
210IceConnectionNumber (
211	IceConn iceConn
212)
213{
214    return (_IceTransGetConnectionNumber (iceConn->trans_conn));
215}
216
217
218char *
219IceConnectionString (
220	IceConn iceConn
221)
222{
223    if (iceConn->connection_string)
224    {
225	return strdup(iceConn->connection_string);
226    }
227    else
228	return (NULL);
229}
230
231
232unsigned long
233IceLastSentSequenceNumber (
234	IceConn iceConn
235)
236{
237    return (iceConn->send_sequence);
238}
239
240
241unsigned long
242IceLastReceivedSequenceNumber (
243	IceConn iceConn
244)
245{
246    return (iceConn->receive_sequence);
247}
248
249
250Bool
251IceSwapping (
252	IceConn iceConn
253)
254{
255    return (iceConn->swap);
256}
257
258
259
260/*
261 * Read "n" bytes from a connection.
262 *
263 * Return Status 0 if we detected an EXPECTED closed connection.
264 *
265 */
266
267Status
268_IceRead (
269	register IceConn iceConn,
270	unsigned long	 nbytes,
271	register char	 *ptr
272)
273{
274    register unsigned long nleft;
275
276    nleft = nbytes;
277    while (nleft > 0)
278    {
279	int nread;
280
281	if (iceConn->io_ok)
282	    nread = _IceTransRead (iceConn->trans_conn, ptr, (int) nleft);
283	else
284	    return (1);
285
286	if (nread <= 0)
287	{
288#ifdef WIN32
289	    errno = WSAGetLastError();
290#endif
291	    if (iceConn->want_to_close)
292	    {
293		/*
294		 * We sent a WantToClose message and now we detected that
295		 * the other side closed the connection.
296		 */
297
298		_IceConnectionClosed (iceConn);	    /* invoke watch procs */
299
300		return (0);
301	    }
302	    else
303	    {
304		IceFatalIOError (iceConn);
305		return (1);
306	    }
307	}
308
309	nleft -= nread;
310	ptr   += nread;
311    }
312
313    return (1);
314}
315
316
317
318/*
319 * If we read a message header with a bad major or minor opcode,
320 * we need to advance to the end of the message.  This way, the next
321 * message can be processed correctly.
322 */
323
324void
325_IceReadSkip (
326	register IceConn	iceConn,
327	register unsigned long	nbytes
328)
329{
330    char temp[512];
331
332    while (nbytes > 0)
333    {
334	unsigned long rbytes = nbytes > 512 ? 512 : nbytes;
335
336	_IceRead (iceConn, rbytes, temp);
337	nbytes -= rbytes;
338    }
339}
340
341
342
343/*
344 * Write "n" bytes to a connection.
345 */
346
347void
348_IceWrite (
349	register IceConn iceConn,
350	unsigned long	 nbytes,
351	register char	 *ptr
352)
353{
354    register unsigned long nleft;
355
356    nleft = nbytes;
357    while (nleft > 0)
358    {
359	int nwritten;
360
361	if (iceConn->io_ok)
362	    nwritten = _IceTransWrite (iceConn->trans_conn, ptr, (int) nleft);
363	else
364	    return;
365
366	if (nwritten <= 0)
367	{
368#ifdef WIN32
369	    errno = WSAGetLastError();
370#endif
371	    IceFatalIOError (iceConn);
372	    return;
373	}
374
375	nleft -= nwritten;
376	ptr   += nwritten;
377    }
378}
379
380
381
382void
383_IceAddOpcodeMapping (
384	IceConn	iceConn,
385	int 	hisOpcode,
386	int 	myOpcode
387)
388{
389    if (hisOpcode <= 0 || hisOpcode > 255)
390    {
391	return;
392    }
393    else if (iceConn->process_msg_info == NULL)
394    {
395	iceConn->process_msg_info = malloc (sizeof (_IceProcessMsgInfo));
396	iceConn->his_min_opcode = iceConn->his_max_opcode = hisOpcode;
397    }
398    else if (hisOpcode < iceConn->his_min_opcode)
399    {
400	_IceProcessMsgInfo *oldVec = iceConn->process_msg_info;
401	int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1;
402	int newsize = iceConn->his_max_opcode - hisOpcode + 1;
403	int i;
404
405	iceConn->process_msg_info = malloc (
406	    newsize * sizeof (_IceProcessMsgInfo));
407
408	if (iceConn->process_msg_info == NULL) {
409	    iceConn->process_msg_info = oldVec;
410	    return;
411	}
412
413	memcpy (&iceConn->process_msg_info[
414	    iceConn->his_min_opcode - hisOpcode], oldVec,
415	    oldsize * sizeof (_IceProcessMsgInfo));
416
417	free (oldVec);
418
419	for (i = hisOpcode + 1; i < iceConn->his_min_opcode; i++)
420	{
421	    iceConn->process_msg_info[i -
422		iceConn->his_min_opcode].in_use = False;
423
424	    iceConn->process_msg_info[i -
425		iceConn->his_min_opcode].protocol = NULL;
426	}
427
428	iceConn->his_min_opcode = hisOpcode;
429    }
430    else if (hisOpcode > iceConn->his_max_opcode)
431    {
432	_IceProcessMsgInfo *oldVec = iceConn->process_msg_info;
433	int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1;
434	int newsize = hisOpcode - iceConn->his_min_opcode + 1;
435	int i;
436
437	iceConn->process_msg_info = malloc (
438	    newsize * sizeof (_IceProcessMsgInfo));
439
440	if (iceConn->process_msg_info == NULL) {
441	    iceConn->process_msg_info = oldVec;
442	    return;
443	}
444
445	memcpy (iceConn->process_msg_info, oldVec,
446	    oldsize * sizeof (_IceProcessMsgInfo));
447
448	free (oldVec);
449
450	for (i = iceConn->his_max_opcode + 1; i < hisOpcode; i++)
451	{
452	    iceConn->process_msg_info[i -
453		iceConn->his_min_opcode].in_use = False;
454
455	    iceConn->process_msg_info[i -
456		iceConn->his_min_opcode].protocol = NULL;
457	}
458
459	iceConn->his_max_opcode = hisOpcode;
460    }
461
462    iceConn->process_msg_info[hisOpcode -
463	iceConn->his_min_opcode].in_use = True;
464
465    iceConn->process_msg_info[hisOpcode -
466	iceConn->his_min_opcode].my_opcode = myOpcode;
467
468    iceConn->process_msg_info[hisOpcode -
469	iceConn->his_min_opcode].protocol = &_IceProtocols[myOpcode - 1];
470}
471
472
473
474char *
475IceGetPeerName (IceConn iceConn)
476{
477    return (_IceTransGetPeerNetworkId (iceConn->trans_conn));
478}
479
480
481char *
482_IceGetPeerName (IceConn iceConn)
483{
484    return (IceGetPeerName(iceConn));
485}
486