upload tizen2.0 source
[framework/uifw/xorg/lib/libice.git] / src / process.c
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 HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32 #include <X11/ICE/ICElib.h>
33 #include "ICElibint.h"
34
35 #include <stdio.h> /* sprintf */
36
37 /*
38  * Check for bad length
39  */
40
41 #define CHECK_SIZE_MATCH(_iceConn, _opcode, _expected_len, _actual_len, _severity, _return) \
42     if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) != _expected_len) \
43     { \
44        _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
45        return (_return); \
46     }
47
48 #define CHECK_AT_LEAST_SIZE(_iceConn, _opcode, _expected_len, _actual_len, _severity) \
49     if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) > _expected_len) \
50     { \
51        _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
52        return (0); \
53     }
54
55 #define CHECK_COMPLETE_SIZE(_iceConn, _opcode, _expected_len, _actual_len, _pStart, _severity) \
56     if (((PADDED_BYTES64((_actual_len)) - SIZEOF (iceMsg)) >> 3) \
57         != _expected_len) \
58     { \
59        _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
60        IceDisposeCompleteMessage (iceConn, _pStart); \
61        return (0); \
62     }
63
64 #define BAIL_STRING(_iceConn, _opcode, _pStart) {\
65     _IceErrorBadLength (_iceConn, 0, _opcode, IceFatalToConnection);\
66     IceDisposeCompleteMessage (_iceConn, _pStart);\
67     return (0);\
68 }
69
70 #ifndef HAVE_ASPRINTF
71 # include <stdarg.h>
72
73 /* sprintf variant found in newer libc's which allocates string to print to */
74 static int _X_ATTRIBUTE_PRINTF(2,3)
75 asprintf(char ** ret, const char *format, ...)
76 {
77     char buf[256];
78     int len;
79     va_list ap;
80
81     va_start(ap, format);
82     len = vsnprintf(buf, sizeof(buf), format, ap);
83     va_end(ap);
84
85     if (len < 0)
86         return -1;
87
88     if (len < sizeof(buf))
89     {
90         *ret = strdup(buf);
91     }
92     else
93     {
94         *ret = malloc(len + 1); /* snprintf doesn't count trailing '\0' */
95         if (*ret != NULL)
96         {
97             va_start(ap, format);
98             len = vsnprintf(*ret, len + 1, format, ap);
99             va_end(ap);
100             if (len < 0) {
101                 free(*ret);
102                 *ret = NULL;
103             }
104         }
105     }
106
107     if (*ret == NULL)
108         return -1;
109
110     return len;
111 }
112 #endif
113
114 \f
115 /*
116  * IceProcessMessages:
117  *
118  * If replyWait == NULL, the client is not waiting for a reply.
119  *
120  * If replyWait != NULL, the client is waiting for a reply...
121  *
122  *    - replyWait->sequence_of_request is the sequence number of the
123  *      message for which the client is waiting a reply.  This is needed
124  *      to determine if an error matches a replyWait.
125  *
126  *    - replyWait->major_opcode_of_request is the major opcode of the
127  *      message for which we are waiting a reply.
128  *
129  *    - replyWait->minor_opcode_of_request is the minor opcode of the
130  *      message for which we are waiting a reply.
131  *
132  *    - replyWait->reply is a pointer to the reply message which will be
133  *      filled in when the reply is ready (the protocol library should
134  *      cast this IcePointer to the appropriate reply type).  In most cases,
135  *      the reply will have some fixed-size part, and the sender function
136  *      will have provided a pointer to a structure (e.g.) to hold this
137  *      fixed-size data.  If there is variable-length data, it would be
138  *      expected that the reply function will have to allocate additional
139  *      memory and store pointer(s) to that memory in the fixed-size
140  *      structure.  If the entire data is variable length (e.g., a single
141  *      variable-length string), then the sender function would probably
142  *      just pass a pointer to fixed-size space to hold a pointer, and the
143  *      reply function would allocate the storage and store the pointer.
144  *      It is the responsibility of the client receiving the reply to
145  *      free up any memory allocated on it's behalf.
146  *
147  * We might be waiting for several different replies (a function can wait
148  * for a reply, and while calling IceProcessMessages, a callback can be
149  * invoked which will wait for another reply).  We take advantage of the
150  * fact that for a given protocol, we are guaranteed that messages are
151  * processed in the order we sent them.  So, everytime we have a new
152  * replyWait, we add it to the END of the 'saved_reply_waits' list.  When
153  * we read a message and want to see if it matches a replyWait, we use the
154  * FIRST replyWait in the list with the major opcode of the message.  If the
155  * reply is ready, we remove that replyWait from the list.
156  *
157  * If the reply/error is ready for the replyWait passed in to
158  * IceProcessMessages, *replyReadyRet is set to True.
159  *
160  * The return value of IceProcessMessages is one of the following:
161  *
162  * IceProcessMessagesSuccess - the message was processed successfully.
163  * IceProcessMessagesIOError - an IO error occured.  The caller should
164  *                             invoked IceCloseConnection.
165  * IceProcessMessagesConnectionClosed - the connection was closed as a
166  *                                      result of shutdown negotiation.
167  */
168
169 IceProcessMessagesStatus
170 IceProcessMessages (
171         IceConn          iceConn,
172         IceReplyWaitInfo *replyWait,
173         Bool             *replyReadyRet
174 )
175 {
176     iceMsg              *header;
177     Bool                replyReady = False;
178     IceReplyWaitInfo    *useThisReplyWait = NULL;
179     IceProcessMessagesStatus retStatus = IceProcessMessagesSuccess;
180
181     if (replyWait)
182         *replyReadyRet = False;
183
184     /*
185      * Each time IceProcessMessages is entered, we increment the dispatch
186      * level.  Each time we leave it, we decrement the dispatch level.
187      */
188
189     iceConn->dispatch_level++;
190
191
192     /*
193      * Read the ICE message header.
194      */
195
196     if (!_IceRead (iceConn, (unsigned long) SIZEOF (iceMsg), iceConn->inbuf))
197     {
198         /*
199          * If we previously sent a WantToClose and now we detected
200          * that the connection was closed, _IceRead returns status 0.
201          * Since the connection was closed, we just want to return here.
202          */
203
204         return (IceProcessMessagesConnectionClosed);
205     }
206
207     if (!iceConn->io_ok)
208     {
209         /*
210          * An unexpected IO error occured.  The caller of IceProcessMessages
211          * should call IceCloseConnection which will cause the watch procedures
212          * to be invoked and the ICE connection to be freed.
213          */
214
215         iceConn->dispatch_level--;
216         iceConn->connection_status = IceConnectIOError;
217         return (IceProcessMessagesIOError);
218     }
219
220     header = (iceMsg *) iceConn->inbuf;
221     iceConn->inbufptr = iceConn->inbuf + SIZEOF (iceMsg);
222
223     iceConn->receive_sequence++;
224
225     if (iceConn->waiting_for_byteorder)
226     {
227         if (header->majorOpcode == 0 &&
228             header->minorOpcode == ICE_ByteOrder)
229         {
230             char byteOrder = ((iceByteOrderMsg *) header)->byteOrder;
231             int endian = 1;
232
233             CHECK_SIZE_MATCH (iceConn, ICE_ByteOrder,
234                 header->length, SIZEOF (iceByteOrderMsg),
235                 IceFatalToConnection, IceProcessMessagesIOError);
236
237             if (byteOrder != IceMSBfirst && byteOrder != IceLSBfirst)
238             {
239                 _IceErrorBadValue (iceConn, 0,
240                     ICE_ByteOrder, 2, 1, &byteOrder);
241
242                 iceConn->connection_status = IceConnectRejected;
243             }
244             else
245             {
246                 iceConn->swap =
247                     (((*(char *) &endian) && byteOrder == IceMSBfirst) ||
248                      (!(*(char *) &endian) && byteOrder == IceLSBfirst));
249
250                 iceConn->waiting_for_byteorder = 0;
251             }
252         }
253         else
254         {
255             if (header->majorOpcode != 0)
256             {
257                 _IceErrorBadMajor (iceConn, header->majorOpcode,
258                     header->minorOpcode, IceFatalToConnection);
259             }
260             else
261             {
262                 _IceErrorBadState (iceConn, 0,
263                     header->minorOpcode, IceFatalToConnection);
264             }
265
266             iceConn->connection_status = IceConnectRejected;
267         }
268
269         iceConn->dispatch_level--;
270         if (!iceConn->io_ok)
271         {
272             iceConn->connection_status = IceConnectIOError;
273             retStatus = IceProcessMessagesIOError;
274         }
275
276         return (retStatus);
277     }
278
279     if (iceConn->swap)
280     {
281         /* swap the length field */
282
283         header->length = lswapl (header->length);
284     }
285
286     if (replyWait)
287     {
288         /*
289          * Add to the list of replyWaits (only if it doesn't exist
290          * in the list already.
291          */
292
293         _IceAddReplyWait (iceConn, replyWait);
294
295         /*
296          * Note that there are two different replyWaits.  The first is
297          * the one passed into IceProcessMessages, and is the replyWait
298          * for the message the client is blocking on.  The second is
299          * the replyWait for the message currently being processed
300          * by IceProcessMessages.  We call it "useThisReplyWait".
301          *
302          * Also, when two hosts communicate over an ICE connection and use
303          * different major opcodes for a subprotocol, it is impossible
304          * to use message replies unless we translate opcodes before
305          * comparing them.
306          */
307
308         {
309             int op;
310
311             if (header->majorOpcode == 0)
312             {
313                 op = 0;
314             }
315             else
316             {
317                 int idx = header->majorOpcode - iceConn->his_min_opcode;
318                 op = iceConn->process_msg_info[idx].my_opcode;
319             }
320             useThisReplyWait = _IceSearchReplyWaits (iceConn, op);
321         }
322     }
323
324     if (header->majorOpcode == 0)
325     {
326         /*
327          * ICE protocol
328          */
329
330         Bool connectionClosed;
331
332         _IceProcessCoreMsgProc processIce =
333             _IceVersions[iceConn->my_ice_version_index].process_core_msg_proc;
334
335         (*processIce) (iceConn, header->minorOpcode,
336             header->length, iceConn->swap,
337             useThisReplyWait, &replyReady, &connectionClosed);
338
339         if (connectionClosed)
340         {
341             /*
342              * As a result of shutdown negotiation, the connection was closed.
343              */
344
345             return (IceProcessMessagesConnectionClosed);
346         }
347     }
348     else
349     {
350         /*
351          * Sub protocol
352          */
353
354         if ((int) header->majorOpcode < iceConn->his_min_opcode ||
355             (int) header->majorOpcode > iceConn->his_max_opcode ||
356             !(iceConn->process_msg_info[header->majorOpcode -
357             iceConn->his_min_opcode].in_use))
358         {
359             /*
360              * The protocol of the message we just read is not supported.
361              */
362
363             _IceErrorBadMajor (iceConn, header->majorOpcode,
364                 header->minorOpcode, IceCanContinue);
365
366             _IceReadSkip (iceConn, header->length << 3);
367         }
368         else
369         {
370             _IceProcessMsgInfo *processMsgInfo = &iceConn->process_msg_info[
371                 header->majorOpcode - iceConn->his_min_opcode];
372
373             if (processMsgInfo->accept_flag)
374             {
375                 IcePaProcessMsgProc processProc =
376                     processMsgInfo->process_msg_proc.accept_client;
377
378                 (*processProc) (iceConn, processMsgInfo->client_data,
379                     header->minorOpcode, header->length, iceConn->swap);
380             }
381             else
382             {
383                 IcePoProcessMsgProc processProc =
384                     processMsgInfo->process_msg_proc.orig_client;
385
386                 (*processProc) (iceConn,
387                     processMsgInfo->client_data, header->minorOpcode,
388                     header->length, iceConn->swap,
389                     useThisReplyWait, &replyReady);
390             }
391         }
392     }
393
394     if (replyReady)
395     {
396         _IceSetReplyReady (iceConn, useThisReplyWait);
397     }
398
399
400     /*
401      * Now we check if the reply is ready for the replyWait passed
402      * into IceProcessMessages.  The replyWait is removed from the
403      * replyWait list if it is ready.
404      */
405
406     if (replyWait)
407         *replyReadyRet = _IceCheckReplyReady (iceConn, replyWait);
408
409
410     /*
411      * Decrement the dispatch level.  If we reach level 0, and the
412      * free_asap bit is set, free the connection now.  Also check for
413      * possible bad IO status.
414      */
415
416     iceConn->dispatch_level--;
417
418     if (iceConn->dispatch_level == 0 && iceConn->free_asap)
419     {
420         _IceFreeConnection (iceConn);
421         retStatus = IceProcessMessagesConnectionClosed;
422     }
423     else if (!iceConn->io_ok)
424     {
425         iceConn->connection_status = IceConnectIOError;
426         retStatus = IceProcessMessagesIOError;
427     }
428
429     return (retStatus);
430 }
431
432
433 \f
434 static void
435 AuthRequired (
436         IceConn         iceConn,
437         int             authIndex,
438         int             authDataLen,
439         IcePointer      authData
440 )
441 {
442     iceAuthRequiredMsg *pMsg;
443
444     IceGetHeader (iceConn, 0, ICE_AuthRequired,
445         SIZEOF (iceAuthRequiredMsg), iceAuthRequiredMsg, pMsg);
446
447     pMsg->authIndex = authIndex;
448     pMsg->authDataLength = authDataLen;
449     pMsg->length += WORD64COUNT (authDataLen);
450
451     IceWriteData (iceConn, authDataLen, (char *) authData);
452
453     if (PAD64 (authDataLen))
454         IceWritePad (iceConn, PAD64 (authDataLen));
455
456     IceFlush (iceConn);
457 }
458
459
460 \f
461 static void
462 AuthReply (
463         IceConn         iceConn,
464         int             authDataLen,
465         IcePointer      authData
466 )
467 {
468     iceAuthReplyMsg *pMsg;
469
470     IceGetHeader (iceConn, 0, ICE_AuthReply,
471         SIZEOF (iceAuthReplyMsg), iceAuthReplyMsg, pMsg);
472
473     pMsg->authDataLength = authDataLen;
474     pMsg->length +=  WORD64COUNT (authDataLen);
475
476     IceWriteData (iceConn, authDataLen, (char *) authData);
477
478     if (PAD64 (authDataLen))
479         IceWritePad (iceConn, PAD64 (authDataLen));
480
481     IceFlush (iceConn);
482 }
483
484
485 \f
486 static void
487 AuthNextPhase (
488         IceConn         iceConn,
489         int             authDataLen,
490         IcePointer      authData
491 )
492 {
493     iceAuthNextPhaseMsg *pMsg;
494
495     IceGetHeader (iceConn, 0, ICE_AuthNextPhase,
496         SIZEOF (iceAuthNextPhaseMsg), iceAuthNextPhaseMsg, pMsg);
497
498     pMsg->authDataLength = authDataLen;
499     pMsg->length += WORD64COUNT (authDataLen);
500
501     IceWriteData (iceConn, authDataLen, (char *) authData);
502
503     if (PAD64 (authDataLen))
504         IceWritePad (iceConn, PAD64 (authDataLen));
505
506     IceFlush (iceConn);
507 }
508
509
510 \f
511 static void
512 AcceptConnection (
513         IceConn iceConn,
514         int     versionIndex
515 )
516 {
517     iceConnectionReplyMsg       *pMsg;
518     char                        *pData;
519     int                         extra;
520
521     extra = STRING_BYTES (IceVendorString) + STRING_BYTES (IceReleaseString);
522
523     IceGetHeaderExtra (iceConn, 0, ICE_ConnectionReply,
524         SIZEOF (iceConnectionReplyMsg), WORD64COUNT (extra),
525         iceConnectionReplyMsg, pMsg, pData);
526
527     pMsg->versionIndex = versionIndex;
528
529     STORE_STRING (pData, IceVendorString);
530     STORE_STRING (pData, IceReleaseString);
531
532     IceFlush (iceConn);
533
534     iceConn->connection_status = IceConnectAccepted;
535 }
536
537
538 \f
539 static void
540 AcceptProtocol (
541         IceConn iceConn,
542         int     hisOpcode,
543         int     myOpcode,
544         int     versionIndex,
545         char    *vendor,
546         char    *release
547 )
548 {
549     iceProtocolReplyMsg *pMsg;
550     char                *pData;
551     int                 extra;
552
553     extra = STRING_BYTES (vendor) + STRING_BYTES (release);
554
555     IceGetHeaderExtra (iceConn, 0, ICE_ProtocolReply,
556         SIZEOF (iceProtocolReplyMsg), WORD64COUNT (extra),
557         iceProtocolReplyMsg, pMsg, pData);
558
559     pMsg->protocolOpcode = myOpcode;
560     pMsg->versionIndex = versionIndex;
561
562     STORE_STRING (pData, vendor);
563     STORE_STRING (pData, release);
564
565     IceFlush (iceConn);
566
567
568     /*
569      * We may be using a different major opcode for this protocol
570      * than the other client.  Whenever we get a message, we must
571      * map to our own major opcode.
572      */
573
574     _IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode);
575 }
576
577
578 \f
579 static void
580 PingReply (
581         IceConn iceConn
582 )
583 {
584     IceSimpleMessage (iceConn, 0, ICE_PingReply);
585     IceFlush (iceConn);
586 }
587
588
589 \f
590 static Bool
591 ProcessError (
592         IceConn          iceConn,
593         unsigned long    length,
594         Bool             swap,
595         IceReplyWaitInfo *replyWait
596 )
597 {
598     int         invokeHandler = 0;
599     Bool        errorReturned = False;
600     iceErrorMsg *message;
601     char        *pData, *pStart;
602     char        severity;
603
604     CHECK_AT_LEAST_SIZE (iceConn, ICE_Error,
605         length, SIZEOF (iceErrorMsg),
606         (iceConn->connect_to_you || iceConn->connect_to_me) ?
607         IceFatalToConnection : IceFatalToProtocol);
608
609     IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
610         iceErrorMsg, message, pStart);
611
612     if (!IceValidIO (iceConn))
613     {
614         IceDisposeCompleteMessage (iceConn, pStart);
615         return (0);
616     }
617
618     severity = message->severity;
619
620     if (severity != IceCanContinue && severity != IceFatalToProtocol &&
621         severity != IceFatalToConnection)
622     {
623         _IceErrorBadValue (iceConn, 0,
624             ICE_Error, 9, 1, &severity);
625         IceDisposeCompleteMessage (iceConn, pStart);
626         return (0);
627     }
628
629     pData = pStart;
630
631     if (swap)
632     {
633         message->errorClass = lswaps (message->errorClass);
634         message->offendingSequenceNum = lswapl (message->offendingSequenceNum);
635     }
636
637     if (!replyWait ||
638         message->offendingSequenceNum != replyWait->sequence_of_request)
639     {
640         invokeHandler = 1;
641     }
642     else
643     {
644         if (iceConn->connect_to_you &&
645             ((!iceConn->connect_to_you->auth_active &&
646             message->offendingMinorOpcode == ICE_ConnectionSetup) ||
647             (iceConn->connect_to_you->auth_active &&
648             message->offendingMinorOpcode == ICE_AuthReply)))
649         {
650             _IceConnectionError *errorReply =
651                 &(((_IceReply *) (replyWait->reply))->connection_error);
652             char *errorStr = NULL;
653             const char *tempstr, *prefix;
654             char *temp;
655
656             invokeHandler = 0;
657             errorReturned = True;
658
659             switch (message->errorClass)
660             {
661             case IceNoVersion:
662
663                 tempstr =
664                     "None of the ICE versions specified are supported";
665                 errorStr = strdup(tempstr);
666                 break;
667
668             case IceNoAuth:
669
670                 tempstr =
671                     "None of the authentication protocols specified are supported";
672                 errorStr = strdup(tempstr);
673                 break;
674
675             case IceSetupFailed:
676
677                 prefix = "Connection Setup Failed, reason : ";
678
679                 EXTRACT_STRING (pData, swap, temp);
680                 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
681                     errorStr = NULL;
682                 free (temp);
683                 break;
684
685             case IceAuthRejected:
686
687                 prefix = "Authentication Rejected, reason : ";
688                 EXTRACT_STRING (pData, swap, temp);
689                 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
690                     errorStr = NULL;
691                 free (temp);
692                 break;
693
694             case IceAuthFailed:
695
696                 prefix = "Authentication Failed, reason : ";
697                 EXTRACT_STRING (pData, swap, temp);
698                 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
699                     errorStr = NULL;
700                 free (temp);
701                 break;
702
703             default:
704                 invokeHandler = 1;
705             }
706
707             errorReply->type = ICE_CONNECTION_ERROR;
708             errorReply->error_message = errorStr;
709         }
710         else if (iceConn->protosetup_to_you &&
711             ((!iceConn->protosetup_to_you->auth_active &&
712             message->offendingMinorOpcode == ICE_ProtocolSetup) ||
713             (iceConn->protosetup_to_you->auth_active &&
714             message->offendingMinorOpcode == ICE_AuthReply)))
715         {
716             _IceProtocolError *errorReply =
717                 &(((_IceReply *) (replyWait->reply))->protocol_error);
718             char *errorStr = "";
719             const char *prefix;
720             char *temp;
721
722             invokeHandler = 0;
723             errorReturned = True;
724
725             switch (message->errorClass)
726             {
727             case IceNoVersion:
728
729                 errorStr = strdup(
730                     "None of the protocol versions specified are supported");
731                 break;
732
733             case IceNoAuth:
734
735                 errorStr = strdup(
736                     "None of the authentication protocols specified are supported");
737
738                 break;
739
740             case IceSetupFailed:
741
742                 prefix = "Protocol Setup Failed, reason : ";
743
744                 EXTRACT_STRING (pData, swap, temp);
745                 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
746                     errorStr = NULL;
747                 free (temp);
748                 break;
749
750             case IceAuthRejected:
751
752                 prefix = "Authentication Rejected, reason : ";
753                 EXTRACT_STRING (pData, swap, temp);
754                 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
755                     errorStr = NULL;
756                 free (temp);
757                 break;
758
759             case IceAuthFailed:
760
761                 prefix = "Authentication Failed, reason : ";
762                 EXTRACT_STRING (pData, swap, temp);
763                 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
764                     errorStr = NULL;
765                 free (temp);
766                 break;
767
768             case IceProtocolDuplicate:
769
770                 prefix = "Protocol was already registered : ";
771                 EXTRACT_STRING (pData, swap, temp);
772                 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
773                     errorStr = NULL;
774                 free (temp);
775                 break;
776
777             case IceMajorOpcodeDuplicate:
778
779                 prefix = "The major opcode was already used : ";
780                 if (asprintf (&errorStr, "%s%d", prefix, (int) *pData) == -1)
781                     errorStr = NULL;
782                 break;
783
784             case IceUnknownProtocol:
785
786                 prefix = "Unknown Protocol : ";
787                 EXTRACT_STRING (pData, swap, temp);
788                 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
789                     errorStr = NULL;
790                 free (temp);
791                 break;
792
793             default:
794                 invokeHandler = 1;
795             }
796
797             errorReply->type = ICE_PROTOCOL_ERROR;
798             errorReply->error_message = errorStr;
799         }
800
801         if (errorReturned == True)
802         {
803             /*
804              * If we tried to authenticate, tell the authentication
805              * procedure to clean up.
806              */
807
808             IcePoAuthProc authProc;
809
810             if (iceConn->connect_to_you &&
811                 iceConn->connect_to_you->auth_active)
812             {
813                 authProc = _IcePoAuthProcs[(int)
814                     (iceConn->connect_to_you->my_auth_index)];
815
816                 (*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state,
817                     True /* clean up */, False /* swap */,
818                     0, NULL, NULL, NULL, NULL);
819             }
820             else if (iceConn->protosetup_to_you &&
821                 iceConn->protosetup_to_you->auth_active)
822             {
823                 _IcePoProtocol *protocol = _IceProtocols[
824                     iceConn->protosetup_to_you->my_opcode - 1].orig_client;
825
826                 authProc = protocol->auth_procs[(int)(iceConn->
827                     protosetup_to_you->my_auth_index)];
828
829                 (*authProc) (iceConn,
830                     &iceConn->protosetup_to_you->my_auth_state,
831                     True /* clean up */, False /* swap */,
832                     0, NULL, NULL, NULL, NULL);
833             }
834         }
835     }
836
837     if (invokeHandler)
838     {
839         (*_IceErrorHandler) (iceConn, swap, message->offendingMinorOpcode,
840             message->offendingSequenceNum, message->errorClass,
841             message->severity, (IcePointer) pData);
842     }
843
844     IceDisposeCompleteMessage (iceConn, pStart);
845
846     return (errorReturned);
847 }
848
849
850 \f
851 static int
852 ProcessConnectionSetup (
853         IceConn         iceConn,
854         unsigned long   length,
855         Bool            swap
856 )
857 {
858     iceConnectionSetupMsg *message;
859     int  myVersionCount, hisVersionCount;
860     int  myVersionIndex, hisVersionIndex;
861     int  hisMajorVersion, hisMinorVersion;
862     int  myAuthCount, hisAuthCount;
863     int  found, i, j;
864     char **hisAuthNames = NULL;
865     char *pData, *pStart, *pEnd;
866     char *vendor = NULL;
867     char *release = NULL;
868     int myAuthIndex = 0;
869     int hisAuthIndex = 0;
870     int accept_setup_now = 0;
871     char mustAuthenticate;
872     int authUsableCount;
873     int authUsableFlags[MAX_ICE_AUTH_NAMES];
874     int authIndices[MAX_ICE_AUTH_NAMES];
875
876     CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionSetup,
877         length, SIZEOF (iceConnectionSetupMsg), IceFatalToConnection);
878
879     IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionSetupMsg),
880         iceConnectionSetupMsg, message, pStart);
881
882     if (!IceValidIO (iceConn))
883     {
884         IceDisposeCompleteMessage (iceConn, pStart);
885         return (0);
886     }
887
888     pData = pStart;
889     pEnd = pStart + (length << 3);
890
891     SKIP_STRING (pData, swap, pEnd,
892                  BAIL_STRING(iceConn, ICE_ConnectionSetup,
893                              pStart));                         /* vendor */
894     SKIP_STRING (pData, swap, pEnd,
895                  BAIL_STRING(iceConn, ICE_ConnectionSetup,
896                             pStart));                          /* release */
897     SKIP_LISTOF_STRING (pData, swap, (int) message->authCount, pEnd,
898                         BAIL_STRING(iceConn, ICE_ConnectionSetup,
899                                    pStart));                   /* auth names */
900
901     pData += (message->versionCount * 4);                      /* versions */
902
903     CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionSetup,
904         length, pData - pStart + SIZEOF (iceConnectionSetupMsg),
905         pStart, IceFatalToConnection);
906
907     mustAuthenticate = message->mustAuthenticate;
908     if (mustAuthenticate != 0 && mustAuthenticate != 1)
909     {
910         _IceErrorBadValue (iceConn, 0,
911             ICE_ConnectionSetup, 8, 1, &mustAuthenticate);
912         iceConn->connection_status = IceConnectRejected;
913         IceDisposeCompleteMessage (iceConn, pStart);
914         return (0);
915     }
916
917     pData = pStart;
918
919     EXTRACT_STRING (pData, swap, vendor);
920     EXTRACT_STRING (pData, swap, release);
921
922     if ((hisAuthCount = message->authCount) > 0)
923     {
924         hisAuthNames = (char **) malloc (hisAuthCount * sizeof (char *));
925         EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames);
926     }
927
928     hisVersionCount = message->versionCount;
929     myVersionCount = _IceVersionCount;
930
931     hisVersionIndex = myVersionIndex = found = 0;
932
933     for (i = 0; i < hisVersionCount && !found; i++)
934     {
935         EXTRACT_CARD16 (pData, swap, hisMajorVersion);
936         EXTRACT_CARD16 (pData, swap, hisMinorVersion);
937
938         for (j = 0; j < myVersionCount && !found; j++)
939         {
940             if (_IceVersions[j].major_version == hisMajorVersion &&
941                 _IceVersions[j].minor_version == hisMinorVersion)
942             {
943                 hisVersionIndex = i;
944                 myVersionIndex = j;
945                 found = 1;
946             }
947         }
948     }
949
950     if (!found)
951     {
952         _IceErrorNoVersion (iceConn, ICE_ConnectionSetup);
953         iceConn->connection_status = IceConnectRejected;
954
955         free (vendor);
956         free (release);
957
958         if (hisAuthCount > 0)
959         {
960             for (i = 0; i < hisAuthCount; i++)
961                 free (hisAuthNames[i]);
962
963             free ((char *) hisAuthNames);
964         }
965
966         IceDisposeCompleteMessage (iceConn, pStart);
967         return (0);
968     }
969
970     _IceGetPaValidAuthIndices ("ICE", iceConn->connection_string,
971         _IceAuthCount, _IceAuthNames, &authUsableCount, authIndices);
972
973     for (i = 0; i < _IceAuthCount; i++)
974     {
975         authUsableFlags[i] = 0;
976         for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)
977             authUsableFlags[i] = (authIndices[j] == i);
978     }
979
980     myAuthCount = _IceAuthCount;
981
982     for (i = found = 0; i < myAuthCount && !found; i++)
983     {
984         if (authUsableFlags[i])
985         {
986             const char *myAuthName = _IceAuthNames[i];
987
988             for (j = 0; j < hisAuthCount && !found; j++)
989                 if (strcmp (myAuthName, hisAuthNames[j]) == 0)
990                 {
991                     myAuthIndex = i;
992                     hisAuthIndex = j;
993                     found = 1;
994                 }
995         }
996     }
997
998     if (!found)
999     {
1000         /*
1001          * None of the authentication methods specified by the
1002          * other client is supported.  If the other client requires
1003          * authentication, we must reject the connection now.
1004          * Otherwise, we can invoke the host-based authentication callback
1005          * to see if we can accept this connection.
1006          */
1007
1008         if (mustAuthenticate || !iceConn->listen_obj->host_based_auth_proc)
1009         {
1010             _IceErrorNoAuthentication (iceConn, ICE_ConnectionSetup);
1011             iceConn->connection_status = IceConnectRejected;
1012         }
1013         else
1014         {
1015             char *hostname = _IceGetPeerName (iceConn);
1016
1017             if ((*iceConn->listen_obj->host_based_auth_proc) (hostname))
1018             {
1019                 accept_setup_now = 1;
1020             }
1021             else
1022             {
1023                 _IceErrorAuthenticationRejected (iceConn,
1024                     ICE_ConnectionSetup, "None of the authentication protocols specified are supported and host-based authentication failed");
1025
1026                 iceConn->connection_status = IceConnectRejected;
1027             }
1028
1029             if (hostname)
1030                 free (hostname);
1031         }
1032
1033         if (iceConn->connection_status == IceConnectRejected)
1034         {
1035             free (vendor);
1036             free (release);
1037         }
1038     }
1039     else
1040     {
1041         IcePaAuthStatus status;
1042         int             authDataLen;
1043         IcePointer      authData = NULL;
1044         IcePointer      authState;
1045         char            *errorString = NULL;
1046         IcePaAuthProc   authProc = _IcePaAuthProcs[myAuthIndex];
1047
1048         authState = NULL;
1049
1050         status = (*authProc) (iceConn, &authState,
1051             swap, 0, NULL, &authDataLen, &authData, &errorString);
1052
1053         if (status == IcePaAuthContinue)
1054         {
1055             _IceConnectToMeInfo *setupInfo;
1056
1057             AuthRequired (iceConn, hisAuthIndex, authDataLen, authData);
1058
1059             iceConn->connect_to_me = setupInfo = (_IceConnectToMeInfo *)
1060                 malloc (sizeof (_IceConnectToMeInfo));
1061
1062             setupInfo->my_version_index = myVersionIndex;
1063             setupInfo->his_version_index = hisVersionIndex;
1064             setupInfo->his_vendor = vendor;
1065             setupInfo->his_release = release;
1066             setupInfo->my_auth_index = myAuthIndex;
1067             setupInfo->my_auth_state = authState;
1068             setupInfo->must_authenticate = mustAuthenticate;
1069         }
1070         else if (status == IcePaAuthAccepted)
1071         {
1072             accept_setup_now = 1;
1073         }
1074         else
1075         {
1076             free (vendor);
1077             free (release);
1078         }
1079
1080         if (authData && authDataLen > 0)
1081             free ((char *) authData);
1082
1083         if (errorString)
1084             free (errorString);
1085     }
1086
1087     if (accept_setup_now)
1088     {
1089         AcceptConnection (iceConn, hisVersionIndex);
1090
1091         iceConn->vendor = vendor;
1092         iceConn->release = release;
1093         iceConn->my_ice_version_index = myVersionIndex;
1094     }
1095
1096     if (hisAuthCount > 0)
1097     {
1098         for (i = 0; i < hisAuthCount; i++)
1099             free (hisAuthNames[i]);
1100
1101         free ((char *) hisAuthNames);
1102     }
1103
1104     IceDisposeCompleteMessage (iceConn, pStart);
1105     return (0);
1106 }
1107
1108
1109 \f
1110 static Bool
1111 ProcessAuthRequired (
1112         IceConn                 iceConn,
1113         unsigned long           length,
1114         Bool                    swap,
1115         IceReplyWaitInfo        *replyWait
1116 )
1117 {
1118     iceAuthRequiredMsg  *message;
1119     int                 authDataLen;
1120     IcePointer          authData;
1121     int                 replyDataLen;
1122     IcePointer          replyData = NULL;
1123     char                *errorString = NULL;
1124     IcePoAuthProc       authProc;
1125     IcePoAuthStatus     status;
1126     IcePointer          authState;
1127     int                 realAuthIndex = 0;
1128
1129     CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthRequired,
1130         length, SIZEOF (iceAuthRequiredMsg),
1131         iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
1132
1133     IceReadCompleteMessage (iceConn, SIZEOF (iceAuthRequiredMsg),
1134         iceAuthRequiredMsg, message, authData);
1135
1136     if (!IceValidIO (iceConn))
1137     {
1138         IceDisposeCompleteMessage (iceConn, authData);
1139         return (0);
1140     }
1141
1142     if (swap)
1143     {
1144         message->authDataLength = lswaps (message->authDataLength);
1145     }
1146
1147     CHECK_COMPLETE_SIZE (iceConn, ICE_AuthRequired, length,
1148         message->authDataLength + SIZEOF (iceAuthRequiredMsg), authData,
1149         iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
1150
1151     if (iceConn->connect_to_you)
1152     {
1153         if ((int) message->authIndex >= _IceAuthCount)
1154         {
1155             _IceConnectionError *errorReply =
1156                 &(((_IceReply *) (replyWait->reply))->connection_error);
1157
1158             const char *tempstr
1159                 = "Received bad authIndex in the AuthRequired message";
1160             char errIndex = (int) message->authIndex;
1161
1162             errorString = strdup(tempstr);
1163
1164             errorReply->type = ICE_CONNECTION_ERROR;
1165             errorReply->error_message = errorString;
1166
1167             _IceErrorBadValue (iceConn, 0,
1168                 ICE_AuthRequired, 2, 1, &errIndex);
1169
1170             IceDisposeCompleteMessage (iceConn, authData);
1171             return (1);
1172         }
1173         else
1174         {
1175             authProc = _IcePoAuthProcs[message->authIndex];
1176
1177             iceConn->connect_to_you->auth_active = 1;
1178         }
1179     }
1180     else if (iceConn->protosetup_to_you)
1181     {
1182         if ((int) message->authIndex >=
1183             iceConn->protosetup_to_you->my_auth_count)
1184         {
1185             _IceProtocolError *errorReply =
1186                 &(((_IceReply *) (replyWait->reply))->protocol_error);
1187
1188             const char *tempstr
1189                 = "Received bad authIndex in the AuthRequired message";
1190             char errIndex = (int) message->authIndex;
1191
1192             errorString = strdup(tempstr);
1193
1194             errorReply->type = ICE_PROTOCOL_ERROR;
1195             errorReply->error_message = errorString;
1196
1197             _IceErrorBadValue (iceConn, 0,
1198                 ICE_AuthRequired, 2, 1, &errIndex);
1199
1200             IceDisposeCompleteMessage (iceConn, authData);
1201             return (1);
1202         }
1203         else
1204         {
1205             _IcePoProtocol *myProtocol = _IceProtocols[
1206                 iceConn->protosetup_to_you->my_opcode - 1].orig_client;
1207
1208             realAuthIndex = iceConn->protosetup_to_you->
1209                 my_auth_indices[message->authIndex];
1210
1211             authProc = myProtocol->auth_procs[realAuthIndex];
1212
1213             iceConn->protosetup_to_you->auth_active = 1;
1214         }
1215     }
1216     else
1217     {
1218         /*
1219          * Unexpected message
1220          */
1221
1222         _IceErrorBadState (iceConn, 0, ICE_AuthRequired, IceCanContinue);
1223
1224         IceDisposeCompleteMessage (iceConn, authData);
1225         return (0);
1226     }
1227
1228     authState = NULL;
1229     authDataLen = message->authDataLength;
1230
1231     status = (*authProc) (iceConn, &authState, False /* don't clean up */,
1232         swap, authDataLen, authData, &replyDataLen, &replyData, &errorString);
1233
1234     if (status == IcePoAuthHaveReply)
1235     {
1236         AuthReply (iceConn, replyDataLen, replyData);
1237
1238         replyWait->sequence_of_request = iceConn->send_sequence;
1239         replyWait->minor_opcode_of_request = ICE_AuthReply;
1240
1241         if (iceConn->connect_to_you)
1242         {
1243             iceConn->connect_to_you->my_auth_state = authState;
1244             iceConn->connect_to_you->my_auth_index = message->authIndex;
1245         }
1246         else if (iceConn->protosetup_to_you)
1247         {
1248             iceConn->protosetup_to_you->my_auth_state = authState;
1249             iceConn->protosetup_to_you->my_auth_index = realAuthIndex;
1250         }
1251     }
1252     else if (status == IcePoAuthRejected || status == IcePoAuthFailed)
1253     {
1254         const char *prefix;
1255         char *returnErrorString;
1256
1257         if (status == IcePoAuthRejected)
1258         {
1259             _IceErrorAuthenticationRejected (iceConn,
1260                 ICE_AuthRequired, errorString);
1261
1262             prefix = "Authentication Rejected, reason : ";
1263         }
1264         else
1265         {
1266             _IceErrorAuthenticationFailed (iceConn,
1267                ICE_AuthRequired, errorString);
1268
1269             prefix = "Authentication Failed, reason : ";
1270         }
1271
1272         if (asprintf (&returnErrorString, "%s%s", prefix, errorString) == -1)
1273             returnErrorString = NULL;
1274         free (errorString);
1275
1276         if (iceConn->connect_to_you)
1277         {
1278             _IceConnectionError *errorReply =
1279                 &(((_IceReply *) (replyWait->reply))->connection_error);
1280
1281             errorReply->type = ICE_CONNECTION_ERROR;
1282             errorReply->error_message = returnErrorString;
1283         }
1284         else
1285         {
1286             _IceProtocolError *errorReply =
1287                 &(((_IceReply *) (replyWait->reply))->protocol_error);
1288
1289             errorReply->type = ICE_PROTOCOL_ERROR;
1290             errorReply->error_message = returnErrorString;
1291         }
1292     }
1293
1294     if (replyData && replyDataLen > 0)
1295         free ((char *) replyData);
1296
1297     IceDisposeCompleteMessage (iceConn, authData);
1298
1299     return (status != IcePoAuthHaveReply);
1300 }
1301
1302
1303 \f
1304 static int
1305 ProcessAuthReply (
1306         IceConn         iceConn,
1307         unsigned long   length,
1308         Bool            swap
1309 )
1310 {
1311     iceAuthReplyMsg     *message;
1312     int                 replyDataLen;
1313     IcePointer          replyData;
1314     int                 authDataLen;
1315     IcePointer          authData = NULL;
1316     char                *errorString = NULL;
1317
1318     CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthReply,
1319         length, SIZEOF (iceAuthReplyMsg),
1320         iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol);
1321
1322     IceReadCompleteMessage (iceConn, SIZEOF (iceAuthReplyMsg),
1323         iceAuthReplyMsg, message, replyData);
1324
1325     if (!IceValidIO (iceConn))
1326     {
1327         IceDisposeCompleteMessage (iceConn, replyData);
1328         return (0);
1329     }
1330
1331     if (swap)
1332     {
1333         message->authDataLength = lswaps (message->authDataLength);
1334     }
1335
1336     CHECK_COMPLETE_SIZE (iceConn, ICE_AuthReply, length,
1337         message->authDataLength + SIZEOF (iceAuthReplyMsg), replyData,
1338         iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol);
1339
1340     replyDataLen = message->authDataLength;
1341
1342     if (iceConn->connect_to_me)
1343     {
1344         IcePaAuthProc authProc = _IcePaAuthProcs[(int)
1345             (iceConn->connect_to_me->my_auth_index)];
1346         IcePaAuthStatus status =
1347             (*authProc) (iceConn, &iceConn->connect_to_me->my_auth_state, swap,
1348             replyDataLen, replyData, &authDataLen, &authData, &errorString);
1349
1350         if (status == IcePaAuthContinue)
1351         {
1352             AuthNextPhase (iceConn, authDataLen, authData);
1353         }
1354         else if (status == IcePaAuthRejected || status == IcePaAuthFailed)
1355         {
1356             /*
1357              * Before we reject, invoke host-based authentication callback
1358              * and give it a chance to accept the connection (only if the
1359              * other client doesn't require authentication).
1360              */
1361
1362             if (!iceConn->connect_to_me->must_authenticate &&
1363                 iceConn->listen_obj->host_based_auth_proc)
1364             {
1365                 char *hostname = _IceGetPeerName (iceConn);
1366
1367                 if ((*iceConn->listen_obj->host_based_auth_proc) (hostname))
1368                 {
1369                     status = IcePaAuthAccepted;
1370                 }
1371
1372                 if (hostname)
1373                     free (hostname);
1374             }
1375
1376             if (status != IcePaAuthAccepted)
1377             {
1378                 free (iceConn->connect_to_me->his_vendor);
1379                 free (iceConn->connect_to_me->his_release);
1380                 free ((char *) iceConn->connect_to_me);
1381                 iceConn->connect_to_me = NULL;
1382
1383                 iceConn->connection_status = IceConnectRejected;
1384
1385                 if (status == IcePaAuthRejected)
1386                 {
1387                     _IceErrorAuthenticationRejected (iceConn,
1388                         ICE_AuthReply, errorString);
1389                 }
1390                 else
1391                 {
1392                     _IceErrorAuthenticationFailed (iceConn,
1393                         ICE_AuthReply, errorString);
1394                 }
1395             }
1396         }
1397
1398         if (status == IcePaAuthAccepted)
1399         {
1400             AcceptConnection (iceConn,
1401                 iceConn->connect_to_me->his_version_index);
1402
1403             iceConn->vendor = iceConn->connect_to_me->his_vendor;
1404             iceConn->release = iceConn->connect_to_me->his_release;
1405             iceConn->my_ice_version_index =
1406                 iceConn->connect_to_me->my_version_index;
1407
1408             free ((char *) iceConn->connect_to_me);
1409             iceConn->connect_to_me = NULL;
1410         }
1411     }
1412     else if (iceConn->protosetup_to_me)
1413     {
1414         _IcePaProtocol *myProtocol = _IceProtocols[iceConn->protosetup_to_me->
1415             my_opcode - 1].accept_client;
1416         IcePaAuthProc authProc = myProtocol->auth_procs[(int)
1417             (iceConn->protosetup_to_me->my_auth_index)];
1418         IcePaAuthStatus status =
1419             (*authProc) (iceConn, &iceConn->protosetup_to_me->my_auth_state,
1420             swap, replyDataLen, replyData,
1421             &authDataLen, &authData, &errorString);
1422         int free_setup_info = 1;
1423
1424         if (status == IcePaAuthContinue)
1425         {
1426             AuthNextPhase (iceConn, authDataLen, authData);
1427             free_setup_info = 0;
1428         }
1429         else if (status == IcePaAuthRejected || status == IcePaAuthFailed)
1430         {
1431             /*
1432              * Before we reject, invoke host-based authentication callback
1433              * and give it a chance to accept the Protocol Setup (only if the
1434              * other client doesn't require authentication).
1435              */
1436
1437             if (!iceConn->protosetup_to_me->must_authenticate &&
1438                 myProtocol->host_based_auth_proc)
1439             {
1440                 char *hostname = _IceGetPeerName (iceConn);
1441
1442                 if ((*myProtocol->host_based_auth_proc) (hostname))
1443                 {
1444                     status = IcePaAuthAccepted;
1445                 }
1446
1447                 if (hostname)
1448                     free (hostname);
1449             }
1450
1451             if (status == IcePaAuthRejected)
1452             {
1453                 _IceErrorAuthenticationRejected (iceConn,
1454                     ICE_AuthReply, errorString);
1455             }
1456             else
1457             {
1458                 _IceErrorAuthenticationFailed (iceConn,
1459                     ICE_AuthReply, errorString);
1460             }
1461         }
1462
1463         if (status == IcePaAuthAccepted)
1464         {
1465             IcePaProcessMsgProc processMsgProc;
1466             IceProtocolSetupProc protocolSetupProc;
1467             IceProtocolActivateProc protocolActivateProc;
1468             _IceProcessMsgInfo *process_msg_info;
1469             IcePointer clientData = NULL;
1470             char *failureReason = NULL;
1471             Status status = 1;
1472
1473             protocolSetupProc = myProtocol->protocol_setup_proc;
1474             protocolActivateProc = myProtocol->protocol_activate_proc;
1475
1476             if (protocolSetupProc)
1477             {
1478                 /*
1479                  * Notify the client of the Protocol Setup.
1480                  */
1481
1482                 status = (*protocolSetupProc) (iceConn,
1483                     myProtocol->version_recs[iceConn->protosetup_to_me->
1484                         my_version_index].major_version,
1485                     myProtocol->version_recs[iceConn->protosetup_to_me->
1486                         my_version_index].minor_version,
1487                     iceConn->protosetup_to_me->his_vendor,
1488                     iceConn->protosetup_to_me->his_release,
1489                     &clientData, &failureReason);
1490
1491                 /*
1492                  * Set vendor and release pointers to NULL, so it won't
1493                  * get freed below.  The ProtocolSetupProc should
1494                  * free it.
1495                  */
1496
1497                 iceConn->protosetup_to_me->his_vendor = NULL;
1498                 iceConn->protosetup_to_me->his_release = NULL;
1499             }
1500
1501             if (status != 0)
1502             {
1503                 /*
1504                  * Send the Protocol Reply
1505                  */
1506
1507                 AcceptProtocol (iceConn,
1508                     iceConn->protosetup_to_me->his_opcode,
1509                     iceConn->protosetup_to_me->my_opcode,
1510                     iceConn->protosetup_to_me->his_version_index,
1511                     myProtocol->vendor, myProtocol->release);
1512
1513
1514                 /*
1515                  * Set info for this protocol.
1516                  */
1517
1518                 processMsgProc = myProtocol->version_recs[
1519                     iceConn->protosetup_to_me->
1520                     my_version_index].process_msg_proc;
1521
1522                 process_msg_info = &iceConn->process_msg_info[
1523                     iceConn->protosetup_to_me->
1524                     his_opcode -iceConn->his_min_opcode];
1525
1526                 process_msg_info->client_data = clientData;
1527                 process_msg_info->accept_flag = 1;
1528                 process_msg_info->process_msg_proc.
1529                     accept_client = processMsgProc;
1530
1531
1532                 /*
1533                  * Increase the reference count for the number
1534                  * of active protocols.
1535                  */
1536
1537                 iceConn->proto_ref_count++;
1538
1539
1540                 /*
1541                  * Notify the client that the protocol is active.  The reason
1542                  * we have this 2nd callback invoked is because the client
1543                  * may wish to immediately generate a message for this
1544                  * protocol, but it must wait until we send the Protocol Reply.
1545                  */
1546
1547                 if (protocolActivateProc)
1548                 {
1549                     (*protocolActivateProc) (iceConn,
1550                         process_msg_info->client_data);
1551                 }
1552             }
1553             else
1554             {
1555                 /*
1556                  * An error was encountered.
1557                  */
1558
1559                 _IceErrorSetupFailed (iceConn, ICE_ProtocolSetup,
1560                     failureReason);
1561
1562                 if (failureReason)
1563                     free (failureReason);
1564             }
1565         }
1566
1567
1568         if (free_setup_info)
1569         {
1570             if (iceConn->protosetup_to_me->his_vendor)
1571                 free (iceConn->protosetup_to_me->his_vendor);
1572             if (iceConn->protosetup_to_me->his_release)
1573                 free (iceConn->protosetup_to_me->his_release);
1574             free ((char *) iceConn->protosetup_to_me);
1575             iceConn->protosetup_to_me = NULL;
1576         }
1577     }
1578     else
1579     {
1580         /*
1581          * Unexpected message
1582          */
1583
1584         _IceErrorBadState (iceConn, 0, ICE_AuthReply, IceCanContinue);
1585     }
1586
1587     if (authData && authDataLen > 0)
1588         free ((char *) authData);
1589
1590     if (errorString)
1591         free (errorString);
1592
1593     IceDisposeCompleteMessage (iceConn, replyData);
1594     return (0);
1595 }
1596
1597
1598 \f
1599 static Bool
1600 ProcessAuthNextPhase (
1601         IceConn                 iceConn,
1602         unsigned long           length,
1603         Bool                    swap,
1604         IceReplyWaitInfo        *replyWait
1605 )
1606 {
1607     iceAuthNextPhaseMsg *message;
1608     int                 authDataLen;
1609     IcePointer          authData;
1610     int                 replyDataLen;
1611     IcePointer          replyData = NULL;
1612     char                *errorString = NULL;
1613     IcePoAuthProc       authProc;
1614     IcePoAuthStatus     status;
1615     IcePointer          *authState;
1616
1617     CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthNextPhase,
1618         length, SIZEOF (iceAuthNextPhaseMsg),
1619         iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
1620
1621     IceReadCompleteMessage (iceConn, SIZEOF (iceAuthNextPhaseMsg),
1622         iceAuthNextPhaseMsg, message, authData);
1623
1624     if (!IceValidIO (iceConn))
1625     {
1626         IceDisposeCompleteMessage (iceConn, authData);
1627         return (0);
1628     }
1629
1630     if (swap)
1631     {
1632         message->authDataLength = lswaps (message->authDataLength);
1633     }
1634
1635     CHECK_COMPLETE_SIZE (iceConn, ICE_AuthNextPhase, length,
1636         message->authDataLength + SIZEOF (iceAuthNextPhaseMsg), authData,
1637         iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
1638
1639     if (iceConn->connect_to_you)
1640     {
1641         authProc = _IcePoAuthProcs[(int)
1642             (iceConn->connect_to_you->my_auth_index)];
1643
1644         authState = &iceConn->connect_to_you->my_auth_state;
1645     }
1646     else if (iceConn->protosetup_to_you)
1647     {
1648         _IcePoProtocol *myProtocol =
1649           _IceProtocols[iceConn->protosetup_to_you->my_opcode - 1].orig_client;
1650
1651         authProc = myProtocol->auth_procs[(int)
1652             (iceConn->protosetup_to_you->my_auth_index)];
1653
1654         authState = &iceConn->protosetup_to_you->my_auth_state;
1655     }
1656     else
1657     {
1658         /*
1659          * Unexpected message
1660          */
1661
1662         _IceErrorBadState (iceConn, 0, ICE_AuthNextPhase, IceCanContinue);
1663
1664         IceDisposeCompleteMessage (iceConn, authData);
1665         return (0);
1666     }
1667
1668     authDataLen = message->authDataLength;
1669
1670     status = (*authProc) (iceConn, authState, False /* don't clean up */,
1671         swap, authDataLen, authData, &replyDataLen, &replyData, &errorString);
1672
1673     if (status == IcePoAuthHaveReply)
1674     {
1675         AuthReply (iceConn, replyDataLen, replyData);
1676
1677         replyWait->sequence_of_request = iceConn->send_sequence;
1678     }
1679     else if (status == IcePoAuthRejected || status == IcePoAuthFailed)
1680     {
1681         const char *prefix = NULL;
1682         char *returnErrorString;
1683
1684         if (status == IcePoAuthRejected)
1685         {
1686             _IceErrorAuthenticationRejected (iceConn,
1687                ICE_AuthNextPhase, errorString);
1688
1689             prefix = "Authentication Rejected, reason : ";
1690         }
1691         else if (status == IcePoAuthFailed)
1692         {
1693             _IceErrorAuthenticationFailed (iceConn,
1694                ICE_AuthNextPhase, errorString);
1695
1696             prefix = "Authentication Failed, reason : ";
1697         }
1698
1699         if (asprintf (&returnErrorString, "%s%s", prefix, errorString) == -1)
1700             returnErrorString = NULL;
1701         free (errorString);
1702
1703         if (iceConn->connect_to_you)
1704         {
1705             _IceConnectionError *errorReply =
1706                 &(((_IceReply *) (replyWait->reply))->connection_error);
1707
1708             errorReply->type = ICE_CONNECTION_ERROR;
1709             errorReply->error_message = returnErrorString;
1710         }
1711         else
1712         {
1713             _IceProtocolError *errorReply =
1714                 &(((_IceReply *) (replyWait->reply))->protocol_error);
1715
1716             errorReply->type = ICE_PROTOCOL_ERROR;
1717             errorReply->error_message = returnErrorString;
1718         }
1719     }
1720
1721     if (replyData && replyDataLen > 0)
1722         free ((char *) replyData);
1723
1724     IceDisposeCompleteMessage (iceConn, authData);
1725
1726     return (status != IcePoAuthHaveReply);
1727 }
1728
1729
1730 \f
1731 static Bool
1732 ProcessConnectionReply (
1733         IceConn                 iceConn,
1734         unsigned long           length,
1735         Bool                    swap,
1736         IceReplyWaitInfo        *replyWait
1737 )
1738 {
1739     iceConnectionReplyMsg       *message;
1740     char                        *pData, *pStart, *pEnd;
1741     Bool                        replyReady;
1742
1743 #if 0 /* No-op */
1744     CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionReply,
1745         length, SIZEOF (iceConnectionReplyMsg), IceFatalToConnection);
1746 #endif
1747
1748     IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionReplyMsg),
1749         iceConnectionReplyMsg, message, pStart);
1750
1751     if (!IceValidIO (iceConn))
1752     {
1753         IceDisposeCompleteMessage (iceConn, pStart);
1754         return (0);
1755     }
1756
1757     pData = pStart;
1758     pEnd = pStart + (length << 3);
1759
1760     SKIP_STRING (pData, swap, pEnd,
1761                  BAIL_STRING (iceConn, ICE_ConnectionReply,
1762                               pStart));                      /* vendor */
1763     SKIP_STRING (pData, swap, pEnd,
1764                  BAIL_STRING (iceConn, ICE_ConnectionReply,
1765                               pStart));                      /* release */
1766
1767     CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionReply,
1768         length, pData - pStart + SIZEOF (iceConnectionReplyMsg),
1769         pStart, IceFatalToConnection);
1770
1771     pData = pStart;
1772
1773     if (iceConn->connect_to_you)
1774     {
1775         if (iceConn->connect_to_you->auth_active)
1776         {
1777             /*
1778              * Tell the authentication procedure to clean up.
1779              */
1780
1781             IcePoAuthProc authProc = _IcePoAuthProcs[(int)
1782                 (iceConn->connect_to_you->my_auth_index)];
1783
1784             (*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state,
1785                 True /* clean up */, False /* swap */,
1786                 0, NULL, NULL, NULL, NULL);
1787         }
1788
1789         if ((int) message->versionIndex >= _IceVersionCount)
1790         {
1791             _IceConnectionError *errorReply =
1792                 &(((_IceReply *) (replyWait->reply))->connection_error);
1793             char errIndex = message->versionIndex;
1794
1795             _IceErrorBadValue (iceConn, 0,
1796                 ICE_ConnectionReply, 2, 1, &errIndex);
1797
1798             errorReply->type = ICE_CONNECTION_ERROR;
1799             errorReply->error_message =
1800                 "Received bad version index in Connection Reply";
1801         }
1802         else
1803         {
1804             _IceReply *reply = (_IceReply *) (replyWait->reply);
1805
1806             reply->type = ICE_CONNECTION_REPLY;
1807             reply->connection_reply.version_index = message->versionIndex;
1808
1809             EXTRACT_STRING (pData, swap, reply->connection_reply.vendor);
1810             EXTRACT_STRING (pData, swap, reply->connection_reply.release);
1811         }
1812
1813         replyReady = True;
1814     }
1815     else
1816     {
1817         /*
1818          * Unexpected message
1819          */
1820
1821         _IceErrorBadState (iceConn, 0, ICE_ConnectionReply, IceCanContinue);
1822
1823         replyReady = False;
1824     }
1825
1826     IceDisposeCompleteMessage (iceConn, pStart);
1827
1828     return (replyReady);
1829 }
1830
1831
1832 \f
1833 static int
1834 ProcessProtocolSetup (
1835         IceConn         iceConn,
1836         unsigned long   length,
1837         Bool            swap
1838 )
1839 {
1840     iceProtocolSetupMsg *message;
1841     _IcePaProtocol      *myProtocol;
1842     int                 myVersionCount, hisVersionCount;
1843     int                 myVersionIndex, hisVersionIndex;
1844     int                 hisMajorVersion, hisMinorVersion;
1845     int                 myAuthCount, hisAuthCount;
1846     int                 myOpcode, hisOpcode;
1847     int                 found, i, j;
1848     char                **hisAuthNames = NULL;
1849     char                *protocolName;
1850     char                *pData, *pStart, *pEnd;
1851     char                *vendor = NULL;
1852     char                *release = NULL;
1853     int                 accept_setup_now = 0;
1854     int                 myAuthIndex = 0;
1855     int                 hisAuthIndex = 0;
1856     char                mustAuthenticate;
1857     int                 authUsableCount;
1858     int                 authUsableFlags[MAX_ICE_AUTH_NAMES];
1859     int                 authIndices[MAX_ICE_AUTH_NAMES];
1860
1861     CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolSetup,
1862         length, SIZEOF (iceProtocolSetupMsg), IceFatalToProtocol);
1863
1864     if (iceConn->want_to_close)
1865     {
1866         /*
1867          * If we sent a WantToClose message, but just got a ProtocolSetup,
1868          * we must cancel our WantToClose.  It is the responsiblity of the
1869          * other client to send a WantToClose later on.
1870          */
1871
1872         iceConn->want_to_close = 0;
1873     }
1874
1875     IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolSetupMsg),
1876         iceProtocolSetupMsg, message, pStart);
1877
1878     if (!IceValidIO (iceConn))
1879     {
1880         IceDisposeCompleteMessage (iceConn, pStart);
1881         return (0);
1882     }
1883
1884     pData = pStart;
1885     pEnd = pStart + (length << 3);
1886
1887     SKIP_STRING (pData, swap, pEnd,
1888                  BAIL_STRING(iceConn, ICE_ProtocolSetup,
1889                              pStart));                         /* proto name */
1890     SKIP_STRING (pData, swap, pEnd,
1891                  BAIL_STRING(iceConn, ICE_ProtocolSetup,
1892                              pStart));                         /* vendor */
1893     SKIP_STRING (pData, swap, pEnd,
1894                  BAIL_STRING(iceConn, ICE_ProtocolSetup,
1895                              pStart));                         /* release */
1896     SKIP_LISTOF_STRING (pData, swap, (int) message->authCount, pEnd,
1897                         BAIL_STRING(iceConn, ICE_ProtocolSetup,
1898                                     pStart));                  /* auth names */
1899     pData += (message->versionCount * 4);                      /* versions */
1900
1901     CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolSetup,
1902         length, pData - pStart + SIZEOF (iceProtocolSetupMsg),
1903         pStart, IceFatalToProtocol);
1904
1905     mustAuthenticate = message->mustAuthenticate;
1906
1907     if (mustAuthenticate != 0 && mustAuthenticate != 1)
1908     {
1909         _IceErrorBadValue (iceConn, 0,
1910             ICE_ProtocolSetup, 4, 1, &mustAuthenticate);
1911         IceDisposeCompleteMessage (iceConn, pStart);
1912         return (0);
1913     }
1914
1915     pData = pStart;
1916
1917     if (iceConn->process_msg_info &&
1918         (int) message->protocolOpcode >= iceConn->his_min_opcode &&
1919         (int) message->protocolOpcode <= iceConn->his_max_opcode &&
1920         iceConn->process_msg_info[
1921         message->protocolOpcode - iceConn->his_min_opcode].in_use)
1922     {
1923         _IceErrorMajorOpcodeDuplicate (iceConn, message->protocolOpcode);
1924         IceDisposeCompleteMessage (iceConn, pStart);
1925         return (0);
1926     }
1927
1928     EXTRACT_STRING (pData, swap, protocolName);
1929
1930     if (iceConn->process_msg_info)
1931     {
1932         for (i = 0;
1933             i <= (iceConn->his_max_opcode - iceConn->his_min_opcode); i++)
1934         {
1935             if (iceConn->process_msg_info[i].in_use && strcmp (protocolName,
1936                 iceConn->process_msg_info[i].protocol->protocol_name) == 0)
1937             {
1938                 _IceErrorProtocolDuplicate (iceConn, protocolName);
1939                 free (protocolName);
1940                 IceDisposeCompleteMessage (iceConn, pStart);
1941                 return (0);
1942             }
1943         }
1944     }
1945
1946     for (i = 0; i < _IceLastMajorOpcode; i++)
1947         if (strcmp (protocolName, _IceProtocols[i].protocol_name) == 0)
1948             break;
1949
1950     if (i < _IceLastMajorOpcode &&
1951         (myProtocol = _IceProtocols[i].accept_client) != NULL)
1952     {
1953         hisOpcode = message->protocolOpcode;
1954         myOpcode = i + 1;
1955         free (protocolName);
1956     }
1957     else
1958     {
1959         _IceErrorUnknownProtocol (iceConn, protocolName);
1960         free (protocolName);
1961         IceDisposeCompleteMessage (iceConn, pStart);
1962         return (0);
1963     }
1964
1965     EXTRACT_STRING (pData, swap, vendor);
1966     EXTRACT_STRING (pData, swap, release);
1967
1968     if ((hisAuthCount = message->authCount) > 0)
1969     {
1970         hisAuthNames = (char **) malloc (hisAuthCount * sizeof (char *));
1971         EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames);
1972     }
1973
1974     hisVersionCount = message->versionCount;
1975     myVersionCount = myProtocol->version_count;
1976
1977     hisVersionIndex = myVersionIndex = found = 0;
1978
1979     for (i = 0; i < hisVersionCount && !found; i++)
1980     {
1981         EXTRACT_CARD16 (pData, swap, hisMajorVersion);
1982         EXTRACT_CARD16 (pData, swap, hisMinorVersion);
1983
1984         for (j = 0; j < myVersionCount && !found; j++)
1985         {
1986             if (myProtocol->version_recs[j].major_version == hisMajorVersion &&
1987                 myProtocol->version_recs[j].minor_version == hisMinorVersion)
1988             {
1989                 hisVersionIndex = i;
1990                 myVersionIndex = j;
1991                 found = 1;
1992             }
1993         }
1994     }
1995
1996     if (!found)
1997     {
1998         _IceErrorNoVersion (iceConn, ICE_ProtocolSetup);
1999
2000         free (vendor);
2001         free (release);
2002
2003         if (hisAuthCount > 0)
2004         {
2005             for (i = 0; i < hisAuthCount; i++)
2006                 free (hisAuthNames[i]);
2007
2008             free ((char *) hisAuthNames);
2009         }
2010
2011         IceDisposeCompleteMessage (iceConn, pStart);
2012         return (0);
2013     }
2014
2015     myAuthCount = myProtocol->auth_count;
2016
2017     _IceGetPaValidAuthIndices (
2018         _IceProtocols[myOpcode - 1].protocol_name,
2019         iceConn->connection_string, myAuthCount,
2020         (const char **) myProtocol->auth_names,
2021         &authUsableCount, authIndices);
2022
2023     for (i = 0; i < myAuthCount; i++)
2024     {
2025         authUsableFlags[i] = 0;
2026         for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)
2027             authUsableFlags[i] = (authIndices[j] == i);
2028     }
2029
2030     for (i = found = 0; i < myAuthCount && !found; i++)
2031     {
2032         if (authUsableFlags[i])
2033         {
2034             const char *myAuthName = myProtocol->auth_names[i];
2035
2036             for (j = 0; j < hisAuthCount && !found; j++)
2037                 if (strcmp (myAuthName, hisAuthNames[j]) == 0)
2038                 {
2039                     myAuthIndex = i;
2040                     hisAuthIndex = j;
2041                     found = 1;
2042                 }
2043         }
2044     }
2045
2046     if (!found)
2047     {
2048         /*
2049          * None of the authentication methods specified by the
2050          * other client is supported.  If the other client requires
2051          * authentication, we must reject the Protocol Setup now.
2052          * Otherwise, we can invoke the host-based authentication callback
2053          * to see if we can accept this Protocol Setup.
2054          */
2055
2056         if (mustAuthenticate || !myProtocol->host_based_auth_proc)
2057         {
2058             _IceErrorNoAuthentication (iceConn, ICE_ProtocolSetup);
2059         }
2060         else
2061         {
2062             char *hostname = _IceGetPeerName (iceConn);
2063
2064             if ((*myProtocol->host_based_auth_proc) (hostname))
2065             {
2066                 accept_setup_now = 1;
2067             }
2068             else
2069             {
2070                 _IceErrorAuthenticationRejected (iceConn,
2071                     ICE_ProtocolSetup, "None of the authentication protocols specified are supported and host-based authentication failed");
2072             }
2073
2074             if (hostname)
2075                 free (hostname);
2076         }
2077     }
2078     else
2079     {
2080         IcePaAuthStatus status;
2081         int             authDataLen;
2082         IcePointer      authData = NULL;
2083         IcePointer      authState;
2084         char            *errorString = NULL;
2085         IcePaAuthProc   authProc =
2086                 myProtocol->auth_procs[myAuthIndex];
2087
2088         authState = NULL;
2089
2090         status = (*authProc) (iceConn, &authState, swap, 0, NULL,
2091             &authDataLen, &authData, &errorString);
2092
2093         if (status == IcePaAuthContinue)
2094         {
2095             _IceProtoSetupToMeInfo *setupInfo;
2096
2097             AuthRequired (iceConn, hisAuthIndex, authDataLen, authData);
2098
2099             iceConn->protosetup_to_me = setupInfo =
2100                 (_IceProtoSetupToMeInfo *) malloc (
2101                 sizeof (_IceProtoSetupToMeInfo));
2102
2103             setupInfo->his_opcode = hisOpcode;
2104             setupInfo->my_opcode = myOpcode;
2105             setupInfo->my_version_index = myVersionIndex;
2106             setupInfo->his_version_index = hisVersionIndex;
2107             setupInfo->his_vendor = vendor;
2108             setupInfo->his_release = release;
2109             vendor = release = NULL;   /* so we don't free it */
2110             setupInfo->my_auth_index = myAuthIndex;
2111             setupInfo->my_auth_state = authState;
2112             setupInfo->must_authenticate = mustAuthenticate;
2113         }
2114         else if (status == IcePaAuthAccepted)
2115         {
2116             accept_setup_now = 1;
2117         }
2118
2119         if (authData && authDataLen > 0)
2120             free ((char *) authData);
2121
2122         if (errorString)
2123             free (errorString);
2124     }
2125
2126     if (accept_setup_now)
2127     {
2128         IcePaProcessMsgProc             processMsgProc;
2129         IceProtocolSetupProc            protocolSetupProc;
2130         IceProtocolActivateProc         protocolActivateProc;
2131         _IceProcessMsgInfo              *process_msg_info;
2132         IcePointer                      clientData = NULL;
2133         char                            *failureReason = NULL;
2134         Status                          status = 1;
2135
2136         protocolSetupProc = myProtocol->protocol_setup_proc;
2137         protocolActivateProc = myProtocol->protocol_activate_proc;
2138
2139         if (protocolSetupProc)
2140         {
2141             /*
2142              * Notify the client of the Protocol Setup.
2143              */
2144
2145             status = (*protocolSetupProc) (iceConn,
2146                 myProtocol->version_recs[myVersionIndex].major_version,
2147                 myProtocol->version_recs[myVersionIndex].minor_version,
2148                 vendor, release, &clientData, &failureReason);
2149
2150             vendor = release = NULL;   /* so we don't free it */
2151         }
2152
2153         if (status != 0)
2154         {
2155             /*
2156              * Send the Protocol Reply
2157              */
2158
2159             AcceptProtocol (iceConn, hisOpcode, myOpcode, hisVersionIndex,
2160                 myProtocol->vendor, myProtocol->release);
2161
2162
2163             /*
2164              * Set info for this protocol.
2165              */
2166
2167             processMsgProc = myProtocol->version_recs[
2168                 myVersionIndex].process_msg_proc;
2169
2170             process_msg_info = &iceConn->process_msg_info[hisOpcode -
2171                 iceConn->his_min_opcode];
2172
2173             process_msg_info->client_data = clientData;
2174             process_msg_info->accept_flag = 1;
2175             process_msg_info->process_msg_proc.accept_client = processMsgProc;
2176
2177
2178             /*
2179              * Increase the reference count for the number of active protocols.
2180              */
2181
2182             iceConn->proto_ref_count++;
2183
2184
2185             /*
2186              * Notify the client that the protocol is active.  The reason
2187              * we have this 2nd callback invoked is because the client
2188              * may wish to immediately generate a message for this
2189              * protocol, but it must wait until we send the Protocol Reply.
2190              */
2191
2192             if (protocolActivateProc)
2193             {
2194                 (*protocolActivateProc) (iceConn,
2195                     process_msg_info->client_data);
2196             }
2197         }
2198         else
2199         {
2200             /*
2201              * An error was encountered.
2202              */
2203
2204             _IceErrorSetupFailed (iceConn, ICE_ProtocolSetup, failureReason);
2205
2206             if (failureReason)
2207                 free (failureReason);
2208         }
2209     }
2210
2211     if (vendor)
2212         free (vendor);
2213
2214     if (release)
2215         free (release);
2216
2217     if (hisAuthCount > 0)
2218     {
2219         for (i = 0; i < hisAuthCount; i++)
2220             free (hisAuthNames[i]);
2221
2222         free ((char *) hisAuthNames);
2223     }
2224
2225     IceDisposeCompleteMessage (iceConn, pStart);
2226     return (0);
2227 }
2228
2229
2230 \f
2231 static Bool
2232 ProcessProtocolReply (
2233         IceConn                 iceConn,
2234         unsigned long           length,
2235         Bool                    swap,
2236         IceReplyWaitInfo        *replyWait
2237 )
2238 {
2239     iceProtocolReplyMsg *message;
2240     char                *pData, *pStart, *pEnd;
2241     Bool                replyReady;
2242
2243 #if 0 /* No-op */
2244     CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolReply,
2245         length, SIZEOF (iceProtocolReplyMsg), IceFatalToProtocol);
2246 #endif
2247
2248     IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolReplyMsg),
2249         iceProtocolReplyMsg, message, pStart);
2250
2251     if (!IceValidIO (iceConn))
2252     {
2253         IceDisposeCompleteMessage (iceConn, pStart);
2254         return (0);
2255     }
2256
2257     pData = pStart;
2258     pEnd = pStart + (length << 3);
2259
2260     SKIP_STRING (pData, swap, pEnd,
2261                  BAIL_STRING(iceConn, ICE_ProtocolReply,
2262                              pStart));                       /* vendor */
2263     SKIP_STRING (pData, swap, pEnd,
2264                  BAIL_STRING(iceConn, ICE_ProtocolReply,
2265                              pStart));                       /* release */
2266
2267     CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolReply,
2268         length, pData - pStart + SIZEOF (iceProtocolReplyMsg),
2269         pStart, IceFatalToProtocol);
2270
2271     pData = pStart;
2272
2273     if (iceConn->protosetup_to_you)
2274     {
2275         if (iceConn->protosetup_to_you->auth_active)
2276         {
2277             /*
2278              * Tell the authentication procedure to clean up.
2279              */
2280
2281             _IcePoProtocol *myProtocol = _IceProtocols[
2282                 iceConn->protosetup_to_you->my_opcode - 1].orig_client;
2283
2284             IcePoAuthProc authProc = myProtocol->auth_procs[(int)
2285                 (iceConn->protosetup_to_you->my_auth_index)];
2286
2287             (*authProc) (iceConn,
2288                 &iceConn->protosetup_to_you->my_auth_state,
2289                 True /* clean up */, False /* swap */,
2290                 0, NULL, NULL, NULL, NULL);
2291         }
2292
2293         if ((int) message->versionIndex >= _IceVersionCount)
2294         {
2295             _IceProtocolError *errorReply =
2296                 &(((_IceReply *) (replyWait->reply))->protocol_error);
2297             char errIndex = message->versionIndex;
2298
2299             _IceErrorBadValue (iceConn, 0,
2300                 ICE_ProtocolReply, 2, 1, &errIndex);
2301
2302             errorReply->type = ICE_PROTOCOL_ERROR;
2303             errorReply->error_message =
2304                 "Received bad version index in Protocol Reply";
2305         }
2306         else
2307         {
2308             _IceProtocolReply *reply =
2309                 &(((_IceReply *) (replyWait->reply))->protocol_reply);
2310
2311             reply->type = ICE_PROTOCOL_REPLY;
2312             reply->major_opcode = message->protocolOpcode;
2313             reply->version_index = message->versionIndex;
2314
2315             EXTRACT_STRING (pData, swap, reply->vendor);
2316             EXTRACT_STRING (pData, swap, reply->release);
2317         }
2318
2319         replyReady = True;
2320     }
2321     else
2322     {
2323         _IceErrorBadState (iceConn, 0, ICE_ProtocolReply, IceCanContinue);
2324
2325         replyReady = False;
2326     }
2327
2328     IceDisposeCompleteMessage (iceConn, pStart);
2329
2330     return (replyReady);
2331 }
2332
2333
2334 \f
2335 static int
2336 ProcessPing (
2337         IceConn         iceConn,
2338         unsigned long   length
2339 )
2340 {
2341     CHECK_SIZE_MATCH (iceConn, ICE_Ping,
2342         length, SIZEOF (icePingMsg), IceFatalToConnection, 0);
2343
2344     PingReply (iceConn);
2345
2346     return (0);
2347 }
2348
2349
2350 \f
2351 static int
2352 ProcessPingReply (
2353         IceConn         iceConn,
2354         unsigned long   length
2355 )
2356 {
2357     CHECK_SIZE_MATCH (iceConn, ICE_PingReply,
2358         length, SIZEOF (icePingReplyMsg), IceFatalToConnection, 0);
2359
2360     if (iceConn->ping_waits)
2361     {
2362         _IcePingWait *next = iceConn->ping_waits->next;
2363
2364         (*iceConn->ping_waits->ping_reply_proc) (iceConn,
2365             iceConn->ping_waits->client_data);
2366
2367         free ((char *) iceConn->ping_waits);
2368         iceConn->ping_waits = next;
2369     }
2370     else
2371     {
2372         _IceErrorBadState (iceConn, 0, ICE_PingReply, IceCanContinue);
2373     }
2374
2375     return (0);
2376 }
2377
2378
2379 \f
2380 static int
2381 ProcessWantToClose (
2382         IceConn         iceConn,
2383         unsigned long   length,
2384         Bool            *connectionClosedRet
2385 )
2386 {
2387     *connectionClosedRet = False;
2388
2389     CHECK_SIZE_MATCH (iceConn, ICE_WantToClose,
2390         length, SIZEOF (iceWantToCloseMsg), IceFatalToConnection, 0);
2391
2392     if (iceConn->want_to_close || iceConn->open_ref_count == 0)
2393     {
2394         /*
2395          * We just received a WantToClose.  Either we also sent a
2396          * WantToClose, so we close the connection, or the iceConn
2397          * is not being used, so we close the connection.  This
2398          * second case is possible if we sent a WantToClose because
2399          * the iceConn->open_ref_count reached zero, but then we
2400          * received a NoClose.
2401          */
2402
2403         _IceConnectionClosed (iceConn);         /* invoke watch procs */
2404         _IceFreeConnection (iceConn);
2405         *connectionClosedRet = True;
2406     }
2407     else if (iceConn->proto_ref_count > 0)
2408     {
2409         /*
2410          * We haven't shut down all of our protocols yet.  We send a NoClose,
2411          * and it's up to us to generate a WantToClose later on.
2412          */
2413
2414         IceSimpleMessage (iceConn, 0, ICE_NoClose);
2415         IceFlush (iceConn);
2416     }
2417     else
2418     {
2419         /*
2420          * The reference count on this iceConn is zero.  This means that
2421          * there are no active protocols, but the client didn't explicitly
2422          * close the connection yet.  If we didn't just send a Protocol Setup,
2423          * we send a NoClose, and it's up to us to generate a WantToClose
2424          * later on.
2425          */
2426
2427         if (!iceConn->protosetup_to_you)
2428         {
2429             IceSimpleMessage (iceConn, 0, ICE_NoClose);
2430             IceFlush (iceConn);
2431         }
2432     }
2433
2434     return (0);
2435 }
2436
2437
2438 \f
2439 static int
2440 ProcessNoClose (
2441         IceConn         iceConn,
2442         unsigned long   length
2443 )
2444 {
2445     CHECK_SIZE_MATCH (iceConn, ICE_NoClose,
2446         length, SIZEOF (iceNoCloseMsg), IceFatalToConnection, 0);
2447
2448     if (iceConn->want_to_close)
2449     {
2450         /*
2451          * The other side can't close now.  We cancel our WantToClose,
2452          * and we can expect a WantToClose from the other side.
2453          */
2454
2455         iceConn->want_to_close = 0;
2456     }
2457     else
2458     {
2459         _IceErrorBadState (iceConn, 0, ICE_NoClose, IceCanContinue);
2460     }
2461
2462     return (0);
2463 }
2464
2465
2466 \f
2467 static void
2468 _IceProcessCoreMessage (
2469         IceConn          iceConn,
2470         int              opcode,
2471         unsigned long    length,
2472         Bool             swap,
2473         IceReplyWaitInfo *replyWait,
2474         Bool             *replyReadyRet,
2475         Bool             *connectionClosedRet
2476 )
2477 {
2478     Bool replyReady = False;
2479
2480     *connectionClosedRet = False;
2481
2482     switch (opcode)
2483     {
2484     case ICE_Error:
2485
2486         replyReady = ProcessError (iceConn, length, swap, replyWait);
2487         break;
2488
2489     case ICE_ConnectionSetup:
2490
2491         ProcessConnectionSetup (iceConn, length, swap);
2492         break;
2493
2494     case ICE_AuthRequired:
2495
2496         replyReady = ProcessAuthRequired (iceConn, length, swap, replyWait);
2497         break;
2498
2499     case ICE_AuthReply:
2500
2501         ProcessAuthReply (iceConn, length, swap);
2502         break;
2503
2504     case ICE_AuthNextPhase:
2505
2506         replyReady = ProcessAuthNextPhase (iceConn, length, swap, replyWait);
2507         break;
2508
2509     case ICE_ConnectionReply:
2510
2511         replyReady = ProcessConnectionReply (iceConn, length, swap, replyWait);
2512         break;
2513
2514     case ICE_ProtocolSetup:
2515
2516         ProcessProtocolSetup (iceConn, length, swap);
2517         break;
2518
2519     case ICE_ProtocolReply:
2520
2521         replyReady = ProcessProtocolReply (iceConn, length, swap, replyWait);
2522         break;
2523
2524     case ICE_Ping:
2525
2526         ProcessPing (iceConn, length);
2527         break;
2528
2529     case ICE_PingReply:
2530
2531         ProcessPingReply (iceConn, length);
2532         break;
2533
2534     case ICE_WantToClose:
2535
2536         ProcessWantToClose (iceConn, length, connectionClosedRet);
2537         break;
2538
2539     case ICE_NoClose:
2540
2541         ProcessNoClose (iceConn, length);
2542         break;
2543
2544     default:
2545
2546         _IceErrorBadMinor (iceConn, 0, opcode, IceCanContinue);
2547         _IceReadSkip (iceConn, length << 3);
2548         break;
2549     }
2550
2551     if (replyWait)
2552         *replyReadyRet = replyReady;
2553 }
2554
2555 int             _IceVersionCount = 1;
2556 _IceVersion     _IceVersions[] = {
2557                     {IceProtoMajor, IceProtoMinor, _IceProcessCoreMessage}};
2558