1/****************************************************************************** 2 3 4Copyright 1993, 1998 The Open Group 5 6Permission to use, copy, modify, distribute, and sell this software and its 7documentation for any purpose is hereby granted without fee, provided that 8the above copyright notice appear in all copies and that both that 9copyright notice and this permission notice appear in supporting 10documentation. 11 12The above copyright notice and this permission notice shall be included in 13all copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall not be 23used in advertising or otherwise to promote the sale, use or other dealings 24in this Software without prior written authorization from The Open Group. 25 26Author: 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 36IceProtocolSetupStatus 37IceProtocolSetup ( 38 IceConn iceConn, 39 int myOpcode, 40 IcePointer clientData, 41 Bool mustAuthenticate, 42 int *majorVersionRet, 43 int *minorVersionRet, 44 char **vendorRet, 45 char **releaseRet, 46 int errorLength, 47 char *errorStringRet 48) 49{ 50 iceProtocolSetupMsg *pMsg; 51 char *pData; 52 _IceProtocol *myProtocol; 53 int extra; 54 Bool gotReply, ioErrorOccured; 55 int accepted, i; 56 int hisOpcode; 57 unsigned long setup_sequence; 58 IceReplyWaitInfo replyWait; 59 _IceReply reply; 60 IcePoVersionRec *versionRec = NULL; 61 int authCount; 62 int *authIndices; 63 64 if (errorStringRet && errorLength > 0) 65 *errorStringRet = '\0'; 66 67 *majorVersionRet = 0; 68 *minorVersionRet = 0; 69 *vendorRet = NULL; 70 *releaseRet = NULL; 71 72 if (myOpcode < 1 || myOpcode > _IceLastMajorOpcode) 73 { 74 if (errorStringRet && errorLength > 0) { 75 strncpy (errorStringRet, "myOpcode out of range", errorLength); 76 errorStringRet[errorLength - 1] = '\0'; 77 } 78 return (IceProtocolSetupFailure); 79 } 80 81 myProtocol = &_IceProtocols[myOpcode - 1]; 82 83 if (myProtocol->orig_client == NULL) 84 { 85 if (errorStringRet && errorLength > 0) { 86 strncpy (errorStringRet, 87 "IceRegisterForProtocolSetup was not called", errorLength); 88 errorStringRet[errorLength - 1] = '\0'; 89 } 90 return (IceProtocolSetupFailure); 91 } 92 93 94 /* 95 * Make sure this protocol hasn't been activated already. 96 */ 97 98 if (iceConn->process_msg_info) 99 { 100 for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++) 101 { 102 if (iceConn->process_msg_info[ 103 i - iceConn->his_min_opcode].in_use && 104 iceConn->process_msg_info[ 105 i - iceConn->his_min_opcode ].my_opcode == myOpcode) 106 break; 107 } 108 109 if (i <= iceConn->his_max_opcode) 110 { 111 return (IceProtocolAlreadyActive); 112 } 113 } 114 115 /* 116 * Generate the message. 117 */ 118 119 if (myProtocol->orig_client->auth_count > 0) 120 { 121 authIndices = malloc ( 122 myProtocol->orig_client->auth_count * sizeof (int)); 123 124 if (authIndices == NULL) 125 { 126 if (errorStringRet && errorLength > 0) { 127 strncpy (errorStringRet, 128 "malloc of authIndices failed", errorLength); 129 errorStringRet[errorLength - 1] = '\0'; 130 } 131 return (IceProtocolSetupFailure); 132 } 133 134 _IceGetPoValidAuthIndices (myProtocol->protocol_name, 135 iceConn->connection_string, 136 myProtocol->orig_client->auth_count, 137 (const char **) myProtocol->orig_client->auth_names, 138 &authCount, authIndices); 139 140 } 141 else 142 { 143 authCount = 0; 144 authIndices = NULL; 145 } 146 147 extra = STRING_BYTES (myProtocol->protocol_name) + 148 STRING_BYTES (myProtocol->orig_client->vendor) + 149 STRING_BYTES (myProtocol->orig_client->release); 150 151 for (i = 0; i < authCount; i++) 152 { 153 extra += STRING_BYTES (myProtocol->orig_client->auth_names[ 154 authIndices[i]]); 155 } 156 157 extra += (myProtocol->orig_client->version_count * 4); 158 159 IceGetHeaderExtra (iceConn, 0, ICE_ProtocolSetup, 160 SIZEOF (iceProtocolSetupMsg), WORD64COUNT (extra), 161 iceProtocolSetupMsg, pMsg, pData); 162 163 if (pData == NULL) { 164 iceConn->outbufptr -= SIZEOF (iceProtocolSetupMsg); 165 free(authIndices); 166 if (errorStringRet && errorLength > 0) { 167 strncpy (errorStringRet, 168 "Too much extra data for iceProtocolSetupMsg", errorLength); 169 errorStringRet[errorLength - 1] = '\0'; 170 } 171 return (IceProtocolSetupFailure); 172 } 173 174 setup_sequence = iceConn->send_sequence; 175 176 pMsg->protocolOpcode = myOpcode; 177 pMsg->versionCount = myProtocol->orig_client->version_count; 178 pMsg->authCount = authCount; 179 pMsg->mustAuthenticate = mustAuthenticate; 180 181 STORE_STRING (pData, myProtocol->protocol_name); 182 STORE_STRING (pData, myProtocol->orig_client->vendor); 183 STORE_STRING (pData, myProtocol->orig_client->release); 184 185 for (i = 0; i < authCount; i++) 186 { 187 STORE_STRING (pData, myProtocol->orig_client->auth_names[ 188 authIndices[i]]); 189 } 190 191 for (i = 0; i < myProtocol->orig_client->version_count; i++) 192 { 193 STORE_CARD16 (pData, 194 myProtocol->orig_client->version_recs[i].major_version); 195 STORE_CARD16 (pData, 196 myProtocol->orig_client->version_recs[i].minor_version); 197 } 198 199 IceFlush (iceConn); 200 201 202 /* 203 * Process messages until we get a Protocol Reply. 204 */ 205 206 replyWait.sequence_of_request = setup_sequence; 207 replyWait.major_opcode_of_request = 0; 208 replyWait.minor_opcode_of_request = ICE_ProtocolSetup; 209 replyWait.reply = (IcePointer) &reply; 210 211 iceConn->protosetup_to_you = malloc (sizeof (_IceProtoSetupToYouInfo)); 212 iceConn->protosetup_to_you->my_opcode = myOpcode; 213 iceConn->protosetup_to_you->my_auth_count = authCount; 214 iceConn->protosetup_to_you->auth_active = 0; 215 iceConn->protosetup_to_you->my_auth_indices = authIndices; 216 217 gotReply = False; 218 ioErrorOccured = False; 219 accepted = 0; 220 221 while (!gotReply && !ioErrorOccured) 222 { 223 ioErrorOccured = (IceProcessMessages ( 224 iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError); 225 226 if (ioErrorOccured) 227 { 228 if (errorStringRet && errorLength > 0) { 229 strncpy (errorStringRet, 230 "IO error occurred doing Protocol Setup on connection", 231 errorLength); 232 errorStringRet[errorLength - 1] = '\0'; 233 } 234 return (IceProtocolSetupIOError); 235 } 236 else if (gotReply) 237 { 238 if (reply.type == ICE_PROTOCOL_REPLY) 239 { 240 if (reply.protocol_reply.version_index >= 241 myProtocol->orig_client->version_count) 242 { 243 if (errorStringRet && errorLength > 0) { 244 strncpy (errorStringRet, 245 "Got a bad version index in the Protocol Reply", 246 errorLength); 247 errorStringRet[errorLength - 1] = '\0'; 248 } 249 250 free (reply.protocol_reply.vendor); 251 free (reply.protocol_reply.release); 252 } 253 else 254 { 255 versionRec = &(myProtocol->orig_client->version_recs[ 256 reply.protocol_reply.version_index]); 257 258 accepted = 1; 259 } 260 } 261 else /* reply.type == ICE_PROTOCOL_ERROR */ 262 { 263 /* Protocol Setup failed */ 264 265 if (errorStringRet && errorLength > 0) { 266 strncpy (errorStringRet, reply.protocol_error.error_message, 267 errorLength); 268 errorStringRet[errorLength - 1] = '\0'; 269 } 270 271 free (reply.protocol_error.error_message); 272 } 273 274 if (iceConn->protosetup_to_you->my_auth_indices) 275 free (iceConn->protosetup_to_you->my_auth_indices); 276 free (iceConn->protosetup_to_you); 277 iceConn->protosetup_to_you = NULL; 278 } 279 } 280 281 if (accepted) 282 { 283 _IceProcessMsgInfo *process_msg_info; 284 285 *majorVersionRet = versionRec->major_version; 286 *minorVersionRet = versionRec->minor_version; 287 *vendorRet = reply.protocol_reply.vendor; 288 *releaseRet = reply.protocol_reply.release; 289 290 291 /* 292 * Increase the reference count for the number of active protocols. 293 */ 294 295 iceConn->proto_ref_count++; 296 297 298 /* 299 * We may be using a different major opcode for this protocol 300 * than the other client. Whenever we get a message, we must 301 * map to our own major opcode. 302 */ 303 304 hisOpcode = reply.protocol_reply.major_opcode; 305 306 _IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode); 307 308 process_msg_info = &iceConn->process_msg_info[hisOpcode - 309 iceConn->his_min_opcode]; 310 311 process_msg_info->client_data = clientData; 312 process_msg_info->accept_flag = 0; 313 314 process_msg_info->process_msg_proc.orig_client = 315 versionRec->process_msg_proc; 316 317 return (IceProtocolSetupSuccess); 318 } 319 else 320 { 321 return (IceProtocolSetupFailure); 322 } 323} 324