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