Home | History | Annotate | Line # | Download | only in src
      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 *
     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  * Fatal IO error.  First notify each protocol's IceIOErrorProc
     68  * callback, then invoke the application IO error handler.
     69  */
     70 
     71 static void _X_COLD
     72 IceFatalIOError (
     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 
    117 int
    118 IceFlush (
    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 
    141 int
    142 IceGetOutBufSize (
    143 	IceConn iceConn
    144 )
    145 {
    146     return (iceConn->outbufmax - iceConn->outbuf);
    147 }
    148 
    149 
    150 int
    151 IceGetInBufSize (
    152 	IceConn iceConn
    153 )
    154 {
    155     return (iceConn->inbufmax - iceConn->inbuf);
    156 }
    157 
    158 
    159 
    160 /*
    161  * informational functions
    162  */
    163 
    164 IceConnectStatus
    165 IceConnectionStatus (
    166 	IceConn iceConn
    167 )
    168 {
    169     return (iceConn->connection_status);
    170 }
    171 
    172 
    173 char *
    174 IceVendor (
    175 	IceConn iceConn
    176 )
    177 {
    178     return strdup(iceConn->vendor);
    179 }
    180 
    181 
    182 char *
    183 IceRelease (
    184 	IceConn iceConn
    185 )
    186 {
    187     return strdup(iceConn->release);
    188 }
    189 
    190 
    191 int
    192 IceProtocolVersion (
    193 	IceConn iceConn
    194 )
    195 {
    196     return (_IceVersions[iceConn->my_ice_version_index].major_version);
    197 }
    198 
    199 
    200 int
    201 IceProtocolRevision (
    202 	IceConn iceConn
    203 )
    204 {
    205     return (_IceVersions[iceConn->my_ice_version_index].minor_version);
    206 }
    207 
    208 
    209 int
    210 IceConnectionNumber (
    211 	IceConn iceConn
    212 )
    213 {
    214     return (_IceTransGetConnectionNumber (iceConn->trans_conn));
    215 }
    216 
    217 
    218 char *
    219 IceConnectionString (
    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 
    232 unsigned long
    233 IceLastSentSequenceNumber (
    234 	IceConn iceConn
    235 )
    236 {
    237     return (iceConn->send_sequence);
    238 }
    239 
    240 
    241 unsigned long
    242 IceLastReceivedSequenceNumber (
    243 	IceConn iceConn
    244 )
    245 {
    246     return (iceConn->receive_sequence);
    247 }
    248 
    249 
    250 Bool
    251 IceSwapping (
    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 
    267 Status
    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 
    324 void
    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 
    347 void
    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 
    382 void
    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 
    474 char *
    475 IceGetPeerName (IceConn iceConn)
    476 {
    477     return (_IceTransGetPeerNetworkId (iceConn->trans_conn));
    478 }
    479 
    480 
    481 char *
    482 _IceGetPeerName (IceConn iceConn)
    483 {
    484     return (IceGetPeerName(iceConn));
    485 }
    486