1266e564dSmrg/****************************************************************************** 2266e564dSmrg 3266e564dSmrg 4266e564dSmrgCopyright 1993, 1998 The Open Group 5266e564dSmrg 6266e564dSmrgPermission to use, copy, modify, distribute, and sell this software and its 7266e564dSmrgdocumentation for any purpose is hereby granted without fee, provided that 8266e564dSmrgthe above copyright notice appear in all copies and that both that 9266e564dSmrgcopyright notice and this permission notice appear in supporting 10266e564dSmrgdocumentation. 11266e564dSmrg 12266e564dSmrgThe above copyright notice and this permission notice shall be included in 13266e564dSmrgall copies or substantial portions of the Software. 14266e564dSmrg 15266e564dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16266e564dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17266e564dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18266e564dSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 19266e564dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20266e564dSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21266e564dSmrg 22266e564dSmrgExcept as contained in this notice, the name of The Open Group shall not be 23266e564dSmrgused in advertising or otherwise to promote the sale, use or other dealings 24266e564dSmrgin this Software without prior written authorization from The Open Group. 25266e564dSmrg 26266e564dSmrgAuthor: Ralph Mor, X Consortium 27266e564dSmrg******************************************************************************/ 28266e564dSmrg 29266e564dSmrg#ifdef HAVE_CONFIG_H 30266e564dSmrg#include <config.h> 31266e564dSmrg#endif 32266e564dSmrg#include <X11/ICE/ICElib.h> 33266e564dSmrg#include "ICElibint.h" 34266e564dSmrg 35266e564dSmrg 36266e564dSmrgIceProtocolSetupStatus 37c5629e66SmrgIceProtocolSetup ( 38c5629e66Smrg IceConn iceConn, 39c5629e66Smrg int myOpcode, 40c5629e66Smrg IcePointer clientData, 41c5629e66Smrg Bool mustAuthenticate, 42c5629e66Smrg int *majorVersionRet, 43c5629e66Smrg int *minorVersionRet, 44c5629e66Smrg char **vendorRet, 45c5629e66Smrg char **releaseRet, 46c5629e66Smrg int errorLength, 47c5629e66Smrg char *errorStringRet 48c5629e66Smrg) 49266e564dSmrg{ 50266e564dSmrg iceProtocolSetupMsg *pMsg; 51266e564dSmrg char *pData; 52266e564dSmrg _IceProtocol *myProtocol; 53266e564dSmrg int extra; 54266e564dSmrg Bool gotReply, ioErrorOccured; 55266e564dSmrg int accepted, i; 56266e564dSmrg int hisOpcode; 57266e564dSmrg unsigned long setup_sequence; 58266e564dSmrg IceReplyWaitInfo replyWait; 59266e564dSmrg _IceReply reply; 60266e564dSmrg IcePoVersionRec *versionRec = NULL; 61266e564dSmrg int authCount; 62266e564dSmrg int *authIndices; 63266e564dSmrg 64266e564dSmrg if (errorStringRet && errorLength > 0) 65266e564dSmrg *errorStringRet = '\0'; 66266e564dSmrg 67266e564dSmrg *majorVersionRet = 0; 68266e564dSmrg *minorVersionRet = 0; 69266e564dSmrg *vendorRet = NULL; 70266e564dSmrg *releaseRet = NULL; 71266e564dSmrg 72266e564dSmrg if (myOpcode < 1 || myOpcode > _IceLastMajorOpcode) 73266e564dSmrg { 74a3129944Smrg if (errorStringRet && errorLength > 0) { 75a3129944Smrg strncpy (errorStringRet, "myOpcode out of range", errorLength); 76a3129944Smrg errorStringRet[errorLength - 1] = '\0'; 77a3129944Smrg } 78266e564dSmrg return (IceProtocolSetupFailure); 79266e564dSmrg } 80266e564dSmrg 81266e564dSmrg myProtocol = &_IceProtocols[myOpcode - 1]; 82266e564dSmrg 83266e564dSmrg if (myProtocol->orig_client == NULL) 84266e564dSmrg { 85a3129944Smrg if (errorStringRet && errorLength > 0) { 86a3129944Smrg strncpy (errorStringRet, 87a3129944Smrg "IceRegisterForProtocolSetup was not called", errorLength); 88a3129944Smrg errorStringRet[errorLength - 1] = '\0'; 89a3129944Smrg } 90266e564dSmrg return (IceProtocolSetupFailure); 91266e564dSmrg } 92266e564dSmrg 93266e564dSmrg 94266e564dSmrg /* 95266e564dSmrg * Make sure this protocol hasn't been activated already. 96266e564dSmrg */ 97266e564dSmrg 98266e564dSmrg if (iceConn->process_msg_info) 99266e564dSmrg { 100266e564dSmrg for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++) 101266e564dSmrg { 102266e564dSmrg if (iceConn->process_msg_info[ 103266e564dSmrg i - iceConn->his_min_opcode].in_use && 104266e564dSmrg iceConn->process_msg_info[ 105266e564dSmrg i - iceConn->his_min_opcode ].my_opcode == myOpcode) 106266e564dSmrg break; 107266e564dSmrg } 108266e564dSmrg 109266e564dSmrg if (i <= iceConn->his_max_opcode) 110266e564dSmrg { 111266e564dSmrg return (IceProtocolAlreadyActive); 112266e564dSmrg } 113266e564dSmrg } 114266e564dSmrg 115266e564dSmrg /* 116266e564dSmrg * Generate the message. 117266e564dSmrg */ 118266e564dSmrg 119266e564dSmrg if (myProtocol->orig_client->auth_count > 0) 120266e564dSmrg { 121fb5e8d76Smrg authIndices = malloc ( 122266e564dSmrg myProtocol->orig_client->auth_count * sizeof (int)); 123266e564dSmrg 1243bf3b463Smrg if (authIndices == NULL) 1253bf3b463Smrg { 1263bf3b463Smrg if (errorStringRet && errorLength > 0) { 1273bf3b463Smrg strncpy (errorStringRet, 1283bf3b463Smrg "malloc of authIndices failed", errorLength); 1293bf3b463Smrg errorStringRet[errorLength - 1] = '\0'; 1303bf3b463Smrg } 1313bf3b463Smrg return (IceProtocolSetupFailure); 1323bf3b463Smrg } 1333bf3b463Smrg 134266e564dSmrg _IceGetPoValidAuthIndices (myProtocol->protocol_name, 135266e564dSmrg iceConn->connection_string, 136266e564dSmrg myProtocol->orig_client->auth_count, 1379ef0b394Smrg (const char **) myProtocol->orig_client->auth_names, 138266e564dSmrg &authCount, authIndices); 139266e564dSmrg 140266e564dSmrg } 141266e564dSmrg else 142266e564dSmrg { 143266e564dSmrg authCount = 0; 144266e564dSmrg authIndices = NULL; 145266e564dSmrg } 146266e564dSmrg 147266e564dSmrg extra = STRING_BYTES (myProtocol->protocol_name) + 148266e564dSmrg STRING_BYTES (myProtocol->orig_client->vendor) + 149266e564dSmrg STRING_BYTES (myProtocol->orig_client->release); 150266e564dSmrg 151266e564dSmrg for (i = 0; i < authCount; i++) 152266e564dSmrg { 153266e564dSmrg extra += STRING_BYTES (myProtocol->orig_client->auth_names[ 154266e564dSmrg authIndices[i]]); 155266e564dSmrg } 156266e564dSmrg 157266e564dSmrg extra += (myProtocol->orig_client->version_count * 4); 158266e564dSmrg 159266e564dSmrg IceGetHeaderExtra (iceConn, 0, ICE_ProtocolSetup, 160266e564dSmrg SIZEOF (iceProtocolSetupMsg), WORD64COUNT (extra), 161266e564dSmrg iceProtocolSetupMsg, pMsg, pData); 162266e564dSmrg 1631009a292Smrg if (pData == NULL) { 1641009a292Smrg iceConn->outbufptr -= SIZEOF (iceProtocolSetupMsg); 1651009a292Smrg free(authIndices); 1661009a292Smrg if (errorStringRet && errorLength > 0) { 1671009a292Smrg strncpy (errorStringRet, 1681009a292Smrg "Too much extra data for iceProtocolSetupMsg", errorLength); 1691009a292Smrg errorStringRet[errorLength - 1] = '\0'; 1701009a292Smrg } 1711009a292Smrg return (IceProtocolSetupFailure); 1721009a292Smrg } 1731009a292Smrg 174266e564dSmrg setup_sequence = iceConn->send_sequence; 175266e564dSmrg 176266e564dSmrg pMsg->protocolOpcode = myOpcode; 177266e564dSmrg pMsg->versionCount = myProtocol->orig_client->version_count; 178266e564dSmrg pMsg->authCount = authCount; 179266e564dSmrg pMsg->mustAuthenticate = mustAuthenticate; 180266e564dSmrg 181266e564dSmrg STORE_STRING (pData, myProtocol->protocol_name); 182266e564dSmrg STORE_STRING (pData, myProtocol->orig_client->vendor); 183266e564dSmrg STORE_STRING (pData, myProtocol->orig_client->release); 184266e564dSmrg 185266e564dSmrg for (i = 0; i < authCount; i++) 186266e564dSmrg { 187266e564dSmrg STORE_STRING (pData, myProtocol->orig_client->auth_names[ 188266e564dSmrg authIndices[i]]); 189266e564dSmrg } 190266e564dSmrg 191266e564dSmrg for (i = 0; i < myProtocol->orig_client->version_count; i++) 192266e564dSmrg { 193266e564dSmrg STORE_CARD16 (pData, 194266e564dSmrg myProtocol->orig_client->version_recs[i].major_version); 195266e564dSmrg STORE_CARD16 (pData, 196266e564dSmrg myProtocol->orig_client->version_recs[i].minor_version); 197266e564dSmrg } 198266e564dSmrg 199266e564dSmrg IceFlush (iceConn); 200266e564dSmrg 201266e564dSmrg 202266e564dSmrg /* 203266e564dSmrg * Process messages until we get a Protocol Reply. 204266e564dSmrg */ 205266e564dSmrg 206266e564dSmrg replyWait.sequence_of_request = setup_sequence; 207266e564dSmrg replyWait.major_opcode_of_request = 0; 208266e564dSmrg replyWait.minor_opcode_of_request = ICE_ProtocolSetup; 209266e564dSmrg replyWait.reply = (IcePointer) &reply; 210266e564dSmrg 211fb5e8d76Smrg iceConn->protosetup_to_you = malloc (sizeof (_IceProtoSetupToYouInfo)); 212266e564dSmrg iceConn->protosetup_to_you->my_opcode = myOpcode; 213266e564dSmrg iceConn->protosetup_to_you->my_auth_count = authCount; 214266e564dSmrg iceConn->protosetup_to_you->auth_active = 0; 215266e564dSmrg iceConn->protosetup_to_you->my_auth_indices = authIndices; 216266e564dSmrg 217266e564dSmrg gotReply = False; 218266e564dSmrg ioErrorOccured = False; 219266e564dSmrg accepted = 0; 220266e564dSmrg 221266e564dSmrg while (!gotReply && !ioErrorOccured) 222266e564dSmrg { 223266e564dSmrg ioErrorOccured = (IceProcessMessages ( 224266e564dSmrg iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError); 225266e564dSmrg 226266e564dSmrg if (ioErrorOccured) 227266e564dSmrg { 228a3129944Smrg if (errorStringRet && errorLength > 0) { 229a3129944Smrg strncpy (errorStringRet, 2301009a292Smrg "IO error occurred doing Protocol Setup on connection", 231a3129944Smrg errorLength); 232a3129944Smrg errorStringRet[errorLength - 1] = '\0'; 233a3129944Smrg } 234266e564dSmrg return (IceProtocolSetupIOError); 235266e564dSmrg } 236266e564dSmrg else if (gotReply) 237266e564dSmrg { 238266e564dSmrg if (reply.type == ICE_PROTOCOL_REPLY) 239266e564dSmrg { 240266e564dSmrg if (reply.protocol_reply.version_index >= 241266e564dSmrg myProtocol->orig_client->version_count) 242266e564dSmrg { 243a3129944Smrg if (errorStringRet && errorLength > 0) { 244a3129944Smrg strncpy (errorStringRet, 245a3129944Smrg "Got a bad version index in the Protocol Reply", 246a3129944Smrg errorLength); 247a3129944Smrg errorStringRet[errorLength - 1] = '\0'; 248a3129944Smrg } 249266e564dSmrg 250266e564dSmrg free (reply.protocol_reply.vendor); 251266e564dSmrg free (reply.protocol_reply.release); 252266e564dSmrg } 253266e564dSmrg else 254266e564dSmrg { 255266e564dSmrg versionRec = &(myProtocol->orig_client->version_recs[ 256266e564dSmrg reply.protocol_reply.version_index]); 257266e564dSmrg 258266e564dSmrg accepted = 1; 259266e564dSmrg } 260266e564dSmrg } 261266e564dSmrg else /* reply.type == ICE_PROTOCOL_ERROR */ 262266e564dSmrg { 263266e564dSmrg /* Protocol Setup failed */ 2649ef0b394Smrg 265a3129944Smrg if (errorStringRet && errorLength > 0) { 266a3129944Smrg strncpy (errorStringRet, reply.protocol_error.error_message, 267a3129944Smrg errorLength); 268a3129944Smrg errorStringRet[errorLength - 1] = '\0'; 269a3129944Smrg } 270266e564dSmrg 271266e564dSmrg free (reply.protocol_error.error_message); 272266e564dSmrg } 273266e564dSmrg 274266e564dSmrg if (iceConn->protosetup_to_you->my_auth_indices) 275fb5e8d76Smrg free (iceConn->protosetup_to_you->my_auth_indices); 276fb5e8d76Smrg free (iceConn->protosetup_to_you); 277266e564dSmrg iceConn->protosetup_to_you = NULL; 278266e564dSmrg } 279266e564dSmrg } 280266e564dSmrg 281266e564dSmrg if (accepted) 282266e564dSmrg { 283266e564dSmrg _IceProcessMsgInfo *process_msg_info; 284266e564dSmrg 285266e564dSmrg *majorVersionRet = versionRec->major_version; 286266e564dSmrg *minorVersionRet = versionRec->minor_version; 287266e564dSmrg *vendorRet = reply.protocol_reply.vendor; 288266e564dSmrg *releaseRet = reply.protocol_reply.release; 2899ef0b394Smrg 290266e564dSmrg 291266e564dSmrg /* 292266e564dSmrg * Increase the reference count for the number of active protocols. 293266e564dSmrg */ 294266e564dSmrg 295266e564dSmrg iceConn->proto_ref_count++; 296266e564dSmrg 297266e564dSmrg 298266e564dSmrg /* 299266e564dSmrg * We may be using a different major opcode for this protocol 300266e564dSmrg * than the other client. Whenever we get a message, we must 301266e564dSmrg * map to our own major opcode. 302266e564dSmrg */ 303266e564dSmrg 304266e564dSmrg hisOpcode = reply.protocol_reply.major_opcode; 305266e564dSmrg 306266e564dSmrg _IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode); 307266e564dSmrg 308266e564dSmrg process_msg_info = &iceConn->process_msg_info[hisOpcode - 309266e564dSmrg iceConn->his_min_opcode]; 310266e564dSmrg 311266e564dSmrg process_msg_info->client_data = clientData; 312266e564dSmrg process_msg_info->accept_flag = 0; 313266e564dSmrg 314266e564dSmrg process_msg_info->process_msg_proc.orig_client = 315266e564dSmrg versionRec->process_msg_proc; 316266e564dSmrg 317266e564dSmrg return (IceProtocolSetupSuccess); 318266e564dSmrg } 319266e564dSmrg else 320266e564dSmrg { 321266e564dSmrg return (IceProtocolSetupFailure); 322266e564dSmrg } 323266e564dSmrg} 324