1 /******************************************************************************
2 
3 
4 Copyright 1993, 1998  The Open Group
5 
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
10 documentation.
11 
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14 
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22 Except as contained in this notice, the name of The Open Group shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from The Open Group.
25 
26 Author: 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 
49 char *
IceAllocScratch(IceConn iceConn,unsigned long size)50 IceAllocScratch (
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 
72 int
IceFlush(IceConn iceConn)73 IceFlush (
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 
86 int
IceGetOutBufSize(IceConn iceConn)87 IceGetOutBufSize (
88 	IceConn iceConn
89 )
90 {
91     return (iceConn->outbufmax - iceConn->outbuf);
92 }
93 
94 
95 int
IceGetInBufSize(IceConn iceConn)96 IceGetInBufSize (
97 	IceConn iceConn
98 )
99 {
100     return (iceConn->inbufmax - iceConn->inbuf);
101 }
102 
103 
104 
105 /*
106  * informational functions
107  */
108 
109 IceConnectStatus
IceConnectionStatus(IceConn iceConn)110 IceConnectionStatus (
111 	IceConn iceConn
112 )
113 {
114     return (iceConn->connection_status);
115 }
116 
117 
118 char *
IceVendor(IceConn iceConn)119 IceVendor (
120 	IceConn iceConn
121 )
122 {
123     return strdup(iceConn->vendor);
124 }
125 
126 
127 char *
IceRelease(IceConn iceConn)128 IceRelease (
129 	IceConn iceConn
130 )
131 {
132     return strdup(iceConn->release);
133 }
134 
135 
136 int
IceProtocolVersion(IceConn iceConn)137 IceProtocolVersion (
138 	IceConn iceConn
139 )
140 {
141     return (_IceVersions[iceConn->my_ice_version_index].major_version);
142 }
143 
144 
145 int
IceProtocolRevision(IceConn iceConn)146 IceProtocolRevision (
147 	IceConn iceConn
148 )
149 {
150     return (_IceVersions[iceConn->my_ice_version_index].minor_version);
151 }
152 
153 
154 int
IceConnectionNumber(IceConn iceConn)155 IceConnectionNumber (
156 	IceConn iceConn
157 )
158 {
159     return (_IceTransGetConnectionNumber (iceConn->trans_conn));
160 }
161 
162 
163 char *
IceConnectionString(IceConn iceConn)164 IceConnectionString (
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 
177 unsigned long
IceLastSentSequenceNumber(IceConn iceConn)178 IceLastSentSequenceNumber (
179 	IceConn iceConn
180 )
181 {
182     return (iceConn->send_sequence);
183 }
184 
185 
186 unsigned long
IceLastReceivedSequenceNumber(IceConn iceConn)187 IceLastReceivedSequenceNumber (
188 	IceConn iceConn
189 )
190 {
191     return (iceConn->receive_sequence);
192 }
193 
194 
195 Bool
IceSwapping(IceConn iceConn)196 IceSwapping (
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 
212 Status
_IceRead(register IceConn iceConn,unsigned long nbytes,register char * ptr)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 
310 void
_IceReadSkip(register IceConn iceConn,register unsigned long nbytes)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 
333 void
_IceWrite(register IceConn iceConn,unsigned long nbytes,register char * ptr)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 
409 void
_IceAddOpcodeMapping(IceConn iceConn,int hisOpcode,int myOpcode)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 
491 char *
IceGetPeerName(IceConn iceConn)492 IceGetPeerName (IceConn iceConn)
493 {
494     return (_IceTransGetPeerNetworkId (iceConn->trans_conn));
495 }
496 
497 
498 char *
_IceGetPeerName(IceConn iceConn)499 _IceGetPeerName (IceConn iceConn)
500 {
501     return (IceGetPeerName(iceConn));
502 }
503