misc.c revision 3bf3b463
1266e564dSmrg/******************************************************************************
2266e564dSmrg
3266e564dSmrg
4266e564dSmrgCopyright 1993, 1998  The Open Group
5266e564dSmrg
6266e564dSmrgPermission to use, copy, modify, distribute, and sell this software and its
7266e564dSmrgdocumentation for any purpose is hereby granted without fee, provided that
8266e564dSmrgthe above copyright notice appear in all copies and that both that
9266e564dSmrgcopyright notice and this permission notice appear in supporting
10266e564dSmrgdocumentation.
11266e564dSmrg
12266e564dSmrgThe above copyright notice and this permission notice shall be included in
13266e564dSmrgall copies or substantial portions of the Software.
14266e564dSmrg
15266e564dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16266e564dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17266e564dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18266e564dSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19266e564dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20266e564dSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21266e564dSmrg
22266e564dSmrgExcept as contained in this notice, the name of The Open Group shall not be
23266e564dSmrgused in advertising or otherwise to promote the sale, use or other dealings
24266e564dSmrgin this Software without prior written authorization from The Open Group.
25266e564dSmrg
26266e564dSmrgAuthor: Ralph Mor, X Consortium
27266e564dSmrg******************************************************************************/
28266e564dSmrg
29266e564dSmrg#ifdef WIN32
30266e564dSmrg#define _WILLWINSOCK_
31266e564dSmrg#endif
32266e564dSmrg#ifdef HAVE_CONFIG_H
33266e564dSmrg#include <config.h>
34266e564dSmrg#endif
35266e564dSmrg#include <X11/ICE/ICElib.h>
36266e564dSmrg#include "ICElibint.h"
37266e564dSmrg#include <X11/Xtrans/Xtrans.h>
38266e564dSmrg#include <stdio.h>
39266e564dSmrg#ifdef WIN32
40266e564dSmrg#include <X11/Xwinsock.h>
41266e564dSmrg#include <X11/Xw32defs.h>
42266e564dSmrg#endif
43266e564dSmrg
44a3129944Smrg
45266e564dSmrg/*
46266e564dSmrg * scratch buffer
47266e564dSmrg */
48266e564dSmrg
49266e564dSmrgchar *
50c5629e66SmrgIceAllocScratch (
51c5629e66Smrg	IceConn		iceConn,
52c5629e66Smrg	unsigned long	size
53c5629e66Smrg)
54266e564dSmrg{
55266e564dSmrg    if (!iceConn->scratch || size > iceConn->scratch_size)
56266e564dSmrg    {
57a3129944Smrg	free (iceConn->scratch);
58266e564dSmrg
59fb5e8d76Smrg	iceConn->scratch = malloc (size);
60266e564dSmrg	iceConn->scratch_size = size;
61266e564dSmrg    }
62266e564dSmrg
63266e564dSmrg    return (iceConn->scratch);
64266e564dSmrg}
65266e564dSmrg
661009a292Smrg/*
671009a292Smrg * Fatal IO error.  First notify each protocol's IceIOErrorProc
681009a292Smrg * callback, then invoke the application IO error handler.
691009a292Smrg */
701009a292Smrg
711009a292Smrgstatic void _X_COLD
721009a292SmrgIceFatalIOError (
731009a292Smrg	IceConn	iceConn
741009a292Smrg)
751009a292Smrg{
761009a292Smrg    iceConn->io_ok = False;
771009a292Smrg
781009a292Smrg    if (iceConn->connection_status == IceConnectPending)
791009a292Smrg    {
801009a292Smrg	/*
811009a292Smrg	 * Don't invoke IO error handler if we are in the
821009a292Smrg	 * middle of a connection setup.
831009a292Smrg	 */
841009a292Smrg
851009a292Smrg	return;
861009a292Smrg    }
87266e564dSmrg
881009a292Smrg    if (iceConn->process_msg_info)
891009a292Smrg    {
901009a292Smrg	for (int i = iceConn->his_min_opcode;
911009a292Smrg	     i <= iceConn->his_max_opcode; i++)
921009a292Smrg	{
931009a292Smrg	    _IceProcessMsgInfo *process;
941009a292Smrg
951009a292Smrg	    process = &iceConn->process_msg_info[i - iceConn->his_min_opcode];
961009a292Smrg
971009a292Smrg	    if ((process != NULL) && process->in_use)
981009a292Smrg	    {
991009a292Smrg		IceIOErrorProc IOErrProc = process->accept_flag ?
1001009a292Smrg		    process->protocol->accept_client->io_error_proc :
1011009a292Smrg		    process->protocol->orig_client->io_error_proc;
1021009a292Smrg
1031009a292Smrg		if (IOErrProc)
1041009a292Smrg		    (*IOErrProc) (iceConn);
1051009a292Smrg	    }
1061009a292Smrg	}
1071009a292Smrg    }
1081009a292Smrg
1091009a292Smrg    (*_IceIOErrorHandler) (iceConn);
1101009a292Smrg    return;
1111009a292Smrg}
112a3129944Smrg
113266e564dSmrg/*
114266e564dSmrg * Output/Input buffer functions
115266e564dSmrg */
116266e564dSmrg
117266e564dSmrgint
118c5629e66SmrgIceFlush (
119c5629e66Smrg	IceConn iceConn
120c5629e66Smrg)
121266e564dSmrg{
1221009a292Smrg    /*
1231009a292Smrg     * Should be impossible, unless we messed up our buffer math somewhere,
1241009a292Smrg     * or one of our pointers has been corrupted.
1251009a292Smrg     */
1261009a292Smrg    if (_X_UNLIKELY(iceConn->outbufptr > iceConn->outbufmax))
1271009a292Smrg    {
1281009a292Smrg	IceFatalIOError (iceConn);
1291009a292Smrg	return 0;
1301009a292Smrg    }
1311009a292Smrg
132266e564dSmrg    _IceWrite (iceConn,
133266e564dSmrg	(unsigned long) (iceConn->outbufptr - iceConn->outbuf),
134266e564dSmrg	iceConn->outbuf);
135266e564dSmrg
136266e564dSmrg    iceConn->outbufptr = iceConn->outbuf;
137266e564dSmrg    return 1;
138266e564dSmrg}
139266e564dSmrg
140266e564dSmrg
141266e564dSmrgint
142c5629e66SmrgIceGetOutBufSize (
143c5629e66Smrg	IceConn iceConn
144c5629e66Smrg)
145266e564dSmrg{
146266e564dSmrg    return (iceConn->outbufmax - iceConn->outbuf);
147266e564dSmrg}
148266e564dSmrg
149266e564dSmrg
150266e564dSmrgint
151c5629e66SmrgIceGetInBufSize (
152c5629e66Smrg	IceConn iceConn
153c5629e66Smrg)
154266e564dSmrg{
155266e564dSmrg    return (iceConn->inbufmax - iceConn->inbuf);
156266e564dSmrg}
157266e564dSmrg
158266e564dSmrg
159a3129944Smrg
160266e564dSmrg/*
161266e564dSmrg * informational functions
162266e564dSmrg */
163266e564dSmrg
164266e564dSmrgIceConnectStatus
165c5629e66SmrgIceConnectionStatus (
166c5629e66Smrg	IceConn iceConn
167c5629e66Smrg)
168266e564dSmrg{
169266e564dSmrg    return (iceConn->connection_status);
170266e564dSmrg}
171266e564dSmrg
172266e564dSmrg
173266e564dSmrgchar *
174c5629e66SmrgIceVendor (
175c5629e66Smrg	IceConn iceConn
176c5629e66Smrg)
177266e564dSmrg{
178266e564dSmrg    return strdup(iceConn->vendor);
179266e564dSmrg}
180266e564dSmrg
181266e564dSmrg
182266e564dSmrgchar *
183c5629e66SmrgIceRelease (
184c5629e66Smrg	IceConn iceConn
185c5629e66Smrg)
186266e564dSmrg{
187266e564dSmrg    return strdup(iceConn->release);
188266e564dSmrg}
189266e564dSmrg
190266e564dSmrg
191266e564dSmrgint
192c5629e66SmrgIceProtocolVersion (
193c5629e66Smrg	IceConn iceConn
194c5629e66Smrg)
195266e564dSmrg{
196266e564dSmrg    return (_IceVersions[iceConn->my_ice_version_index].major_version);
197266e564dSmrg}
198266e564dSmrg
199266e564dSmrg
200266e564dSmrgint
201c5629e66SmrgIceProtocolRevision (
202c5629e66Smrg	IceConn iceConn
203c5629e66Smrg)
204266e564dSmrg{
205266e564dSmrg    return (_IceVersions[iceConn->my_ice_version_index].minor_version);
206266e564dSmrg}
207266e564dSmrg
208266e564dSmrg
209266e564dSmrgint
210c5629e66SmrgIceConnectionNumber (
211c5629e66Smrg	IceConn iceConn
212c5629e66Smrg)
213266e564dSmrg{
214266e564dSmrg    return (_IceTransGetConnectionNumber (iceConn->trans_conn));
215266e564dSmrg}
216266e564dSmrg
217266e564dSmrg
218266e564dSmrgchar *
219c5629e66SmrgIceConnectionString (
220c5629e66Smrg	IceConn iceConn
221c5629e66Smrg)
222266e564dSmrg{
223266e564dSmrg    if (iceConn->connection_string)
224266e564dSmrg    {
225266e564dSmrg	return strdup(iceConn->connection_string);
226266e564dSmrg    }
227266e564dSmrg    else
228266e564dSmrg	return (NULL);
229266e564dSmrg}
230266e564dSmrg
231266e564dSmrg
232266e564dSmrgunsigned long
233c5629e66SmrgIceLastSentSequenceNumber (
234c5629e66Smrg	IceConn iceConn
235c5629e66Smrg)
236266e564dSmrg{
237266e564dSmrg    return (iceConn->send_sequence);
238266e564dSmrg}
239266e564dSmrg
240266e564dSmrg
241266e564dSmrgunsigned long
242c5629e66SmrgIceLastReceivedSequenceNumber (
243c5629e66Smrg	IceConn iceConn
244c5629e66Smrg)
245266e564dSmrg{
246266e564dSmrg    return (iceConn->receive_sequence);
247266e564dSmrg}
248266e564dSmrg
249266e564dSmrg
250266e564dSmrgBool
251c5629e66SmrgIceSwapping (
252c5629e66Smrg	IceConn iceConn
253c5629e66Smrg)
254266e564dSmrg{
255266e564dSmrg    return (iceConn->swap);
256266e564dSmrg}
257266e564dSmrg
258266e564dSmrg
259a3129944Smrg
260266e564dSmrg/*
261266e564dSmrg * Read "n" bytes from a connection.
262266e564dSmrg *
263266e564dSmrg * Return Status 0 if we detected an EXPECTED closed connection.
264266e564dSmrg *
265266e564dSmrg */
266266e564dSmrg
267266e564dSmrgStatus
268c5629e66Smrg_IceRead (
269c5629e66Smrg	register IceConn iceConn,
270c5629e66Smrg	unsigned long	 nbytes,
271c5629e66Smrg	register char	 *ptr
272c5629e66Smrg)
273266e564dSmrg{
274266e564dSmrg    register unsigned long nleft;
275266e564dSmrg
276266e564dSmrg    nleft = nbytes;
277266e564dSmrg    while (nleft > 0)
278266e564dSmrg    {
279266e564dSmrg	int nread;
280266e564dSmrg
281266e564dSmrg	if (iceConn->io_ok)
282266e564dSmrg	    nread = _IceTransRead (iceConn->trans_conn, ptr, (int) nleft);
283266e564dSmrg	else
284266e564dSmrg	    return (1);
285266e564dSmrg
286266e564dSmrg	if (nread <= 0)
287266e564dSmrg	{
288266e564dSmrg#ifdef WIN32
289266e564dSmrg	    errno = WSAGetLastError();
290266e564dSmrg#endif
291266e564dSmrg	    if (iceConn->want_to_close)
292266e564dSmrg	    {
293266e564dSmrg		/*
294266e564dSmrg		 * We sent a WantToClose message and now we detected that
295266e564dSmrg		 * the other side closed the connection.
296266e564dSmrg		 */
297266e564dSmrg
298266e564dSmrg		_IceConnectionClosed (iceConn);	    /* invoke watch procs */
299266e564dSmrg
300266e564dSmrg		return (0);
301266e564dSmrg	    }
3029ef0b394Smrg	    else
303266e564dSmrg	    {
3041009a292Smrg		IceFatalIOError (iceConn);
305266e564dSmrg		return (1);
306266e564dSmrg	    }
307266e564dSmrg	}
308266e564dSmrg
309266e564dSmrg	nleft -= nread;
310266e564dSmrg	ptr   += nread;
311266e564dSmrg    }
312266e564dSmrg
313266e564dSmrg    return (1);
314266e564dSmrg}
315266e564dSmrg
316266e564dSmrg
317a3129944Smrg
318266e564dSmrg/*
319266e564dSmrg * If we read a message header with a bad major or minor opcode,
320266e564dSmrg * we need to advance to the end of the message.  This way, the next
321266e564dSmrg * message can be processed correctly.
322266e564dSmrg */
323266e564dSmrg
324266e564dSmrgvoid
325c5629e66Smrg_IceReadSkip (
326c5629e66Smrg	register IceConn	iceConn,
327c5629e66Smrg	register unsigned long	nbytes
328c5629e66Smrg)
329266e564dSmrg{
330266e564dSmrg    char temp[512];
331266e564dSmrg
332266e564dSmrg    while (nbytes > 0)
333266e564dSmrg    {
334266e564dSmrg	unsigned long rbytes = nbytes > 512 ? 512 : nbytes;
335266e564dSmrg
336266e564dSmrg	_IceRead (iceConn, rbytes, temp);
337266e564dSmrg	nbytes -= rbytes;
338266e564dSmrg    }
339266e564dSmrg}
340266e564dSmrg
341266e564dSmrg
342a3129944Smrg
343266e564dSmrg/*
344266e564dSmrg * Write "n" bytes to a connection.
345266e564dSmrg */
346266e564dSmrg
347266e564dSmrgvoid
348c5629e66Smrg_IceWrite (
349c5629e66Smrg	register IceConn iceConn,
350c5629e66Smrg	unsigned long	 nbytes,
351c5629e66Smrg	register char	 *ptr
352c5629e66Smrg)
353266e564dSmrg{
354266e564dSmrg    register unsigned long nleft;
355266e564dSmrg
356266e564dSmrg    nleft = nbytes;
357266e564dSmrg    while (nleft > 0)
358266e564dSmrg    {
359266e564dSmrg	int nwritten;
360266e564dSmrg
361266e564dSmrg	if (iceConn->io_ok)
362266e564dSmrg	    nwritten = _IceTransWrite (iceConn->trans_conn, ptr, (int) nleft);
363266e564dSmrg	else
364266e564dSmrg	    return;
365266e564dSmrg
366266e564dSmrg	if (nwritten <= 0)
367266e564dSmrg	{
368266e564dSmrg#ifdef WIN32
369266e564dSmrg	    errno = WSAGetLastError();
370266e564dSmrg#endif
3711009a292Smrg	    IceFatalIOError (iceConn);
372266e564dSmrg	    return;
373266e564dSmrg	}
374266e564dSmrg
375266e564dSmrg	nleft -= nwritten;
376266e564dSmrg	ptr   += nwritten;
377266e564dSmrg    }
378266e564dSmrg}
379266e564dSmrg
380266e564dSmrg
381a3129944Smrg
382266e564dSmrgvoid
383c5629e66Smrg_IceAddOpcodeMapping (
384c5629e66Smrg	IceConn	iceConn,
385c5629e66Smrg	int 	hisOpcode,
386c5629e66Smrg	int 	myOpcode
387c5629e66Smrg)
388266e564dSmrg{
389266e564dSmrg    if (hisOpcode <= 0 || hisOpcode > 255)
390266e564dSmrg    {
391266e564dSmrg	return;
392266e564dSmrg    }
393266e564dSmrg    else if (iceConn->process_msg_info == NULL)
394266e564dSmrg    {
395fb5e8d76Smrg	iceConn->process_msg_info = malloc (sizeof (_IceProcessMsgInfo));
396266e564dSmrg	iceConn->his_min_opcode = iceConn->his_max_opcode = hisOpcode;
397266e564dSmrg    }
398266e564dSmrg    else if (hisOpcode < iceConn->his_min_opcode)
399266e564dSmrg    {
400266e564dSmrg	_IceProcessMsgInfo *oldVec = iceConn->process_msg_info;
401266e564dSmrg	int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1;
402266e564dSmrg	int newsize = iceConn->his_max_opcode - hisOpcode + 1;
403266e564dSmrg	int i;
404266e564dSmrg
405fb5e8d76Smrg	iceConn->process_msg_info = malloc (
406266e564dSmrg	    newsize * sizeof (_IceProcessMsgInfo));
407266e564dSmrg
4083bf3b463Smrg	if (iceConn->process_msg_info == NULL) {
4093bf3b463Smrg	    iceConn->process_msg_info = oldVec;
4103bf3b463Smrg	    return;
4113bf3b463Smrg	}
4123bf3b463Smrg
413266e564dSmrg	memcpy (&iceConn->process_msg_info[
414266e564dSmrg	    iceConn->his_min_opcode - hisOpcode], oldVec,
415266e564dSmrg	    oldsize * sizeof (_IceProcessMsgInfo));
416266e564dSmrg
417fb5e8d76Smrg	free (oldVec);
418266e564dSmrg
419266e564dSmrg	for (i = hisOpcode + 1; i < iceConn->his_min_opcode; i++)
420266e564dSmrg	{
421266e564dSmrg	    iceConn->process_msg_info[i -
422266e564dSmrg		iceConn->his_min_opcode].in_use = False;
423266e564dSmrg
424266e564dSmrg	    iceConn->process_msg_info[i -
425266e564dSmrg		iceConn->his_min_opcode].protocol = NULL;
426266e564dSmrg	}
427266e564dSmrg
428266e564dSmrg	iceConn->his_min_opcode = hisOpcode;
429266e564dSmrg    }
430266e564dSmrg    else if (hisOpcode > iceConn->his_max_opcode)
431266e564dSmrg    {
432266e564dSmrg	_IceProcessMsgInfo *oldVec = iceConn->process_msg_info;
433266e564dSmrg	int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1;
434266e564dSmrg	int newsize = hisOpcode - iceConn->his_min_opcode + 1;
435266e564dSmrg	int i;
436266e564dSmrg
437fb5e8d76Smrg	iceConn->process_msg_info = malloc (
438266e564dSmrg	    newsize * sizeof (_IceProcessMsgInfo));
439266e564dSmrg
4403bf3b463Smrg	if (iceConn->process_msg_info == NULL) {
4413bf3b463Smrg	    iceConn->process_msg_info = oldVec;
4423bf3b463Smrg	    return;
4433bf3b463Smrg	}
4443bf3b463Smrg
445266e564dSmrg	memcpy (iceConn->process_msg_info, oldVec,
446266e564dSmrg	    oldsize * sizeof (_IceProcessMsgInfo));
447266e564dSmrg
448fb5e8d76Smrg	free (oldVec);
449266e564dSmrg
450266e564dSmrg	for (i = iceConn->his_max_opcode + 1; i < hisOpcode; i++)
451266e564dSmrg	{
452266e564dSmrg	    iceConn->process_msg_info[i -
453266e564dSmrg		iceConn->his_min_opcode].in_use = False;
454266e564dSmrg
455266e564dSmrg	    iceConn->process_msg_info[i -
456266e564dSmrg		iceConn->his_min_opcode].protocol = NULL;
457266e564dSmrg	}
458266e564dSmrg
459266e564dSmrg	iceConn->his_max_opcode = hisOpcode;
460266e564dSmrg    }
461266e564dSmrg
462266e564dSmrg    iceConn->process_msg_info[hisOpcode -
463266e564dSmrg	iceConn->his_min_opcode].in_use = True;
464266e564dSmrg
465266e564dSmrg    iceConn->process_msg_info[hisOpcode -
466266e564dSmrg	iceConn->his_min_opcode].my_opcode = myOpcode;
467266e564dSmrg
468266e564dSmrg    iceConn->process_msg_info[hisOpcode -
469266e564dSmrg	iceConn->his_min_opcode].protocol = &_IceProtocols[myOpcode - 1];
470266e564dSmrg}
471266e564dSmrg
472266e564dSmrg
473a3129944Smrg
474266e564dSmrgchar *
475266e564dSmrgIceGetPeerName (IceConn iceConn)
476266e564dSmrg{
477266e564dSmrg    return (_IceTransGetPeerNetworkId (iceConn->trans_conn));
478266e564dSmrg}
479266e564dSmrg
480a3129944Smrg
481266e564dSmrgchar *
482266e564dSmrg_IceGetPeerName (IceConn iceConn)
483266e564dSmrg{
484266e564dSmrg    return (IceGetPeerName(iceConn));
485266e564dSmrg}
486