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
36 IceProtocolSetupStatus
IceProtocolSetup(IceConn iceConn,int myOpcode,IcePointer clientData,Bool mustAuthenticate,int * majorVersionRet,int * minorVersionRet,char ** vendorRet,char ** releaseRet,int errorLength,char * errorStringRet)37 IceProtocolSetup (
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 _IceGetPoValidAuthIndices (myProtocol->protocol_name,
125 iceConn->connection_string,
126 myProtocol->orig_client->auth_count,
127 (const char **) myProtocol->orig_client->auth_names,
128 &authCount, authIndices);
129
130 }
131 else
132 {
133 authCount = 0;
134 authIndices = NULL;
135 }
136
137 extra = STRING_BYTES (myProtocol->protocol_name) +
138 STRING_BYTES (myProtocol->orig_client->vendor) +
139 STRING_BYTES (myProtocol->orig_client->release);
140
141 for (i = 0; i < authCount; i++)
142 {
143 extra += STRING_BYTES (myProtocol->orig_client->auth_names[
144 authIndices[i]]);
145 }
146
147 extra += (myProtocol->orig_client->version_count * 4);
148
149 IceGetHeaderExtra (iceConn, 0, ICE_ProtocolSetup,
150 SIZEOF (iceProtocolSetupMsg), WORD64COUNT (extra),
151 iceProtocolSetupMsg, pMsg, pData);
152
153 setup_sequence = iceConn->send_sequence;
154
155 pMsg->protocolOpcode = myOpcode;
156 pMsg->versionCount = myProtocol->orig_client->version_count;
157 pMsg->authCount = authCount;
158 pMsg->mustAuthenticate = mustAuthenticate;
159
160 STORE_STRING (pData, myProtocol->protocol_name);
161 STORE_STRING (pData, myProtocol->orig_client->vendor);
162 STORE_STRING (pData, myProtocol->orig_client->release);
163
164 for (i = 0; i < authCount; i++)
165 {
166 STORE_STRING (pData, myProtocol->orig_client->auth_names[
167 authIndices[i]]);
168 }
169
170 for (i = 0; i < myProtocol->orig_client->version_count; i++)
171 {
172 STORE_CARD16 (pData,
173 myProtocol->orig_client->version_recs[i].major_version);
174 STORE_CARD16 (pData,
175 myProtocol->orig_client->version_recs[i].minor_version);
176 }
177
178 IceFlush (iceConn);
179
180
181 /*
182 * Process messages until we get a Protocol Reply.
183 */
184
185 replyWait.sequence_of_request = setup_sequence;
186 replyWait.major_opcode_of_request = 0;
187 replyWait.minor_opcode_of_request = ICE_ProtocolSetup;
188 replyWait.reply = (IcePointer) &reply;
189
190 iceConn->protosetup_to_you = malloc (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 if (errorStringRet && errorLength > 0) {
208 strncpy (errorStringRet,
209 "IO error occured doing Protocol Setup on connection",
210 errorLength);
211 errorStringRet[errorLength - 1] = '\0';
212 }
213 return (IceProtocolSetupIOError);
214 }
215 else if (gotReply)
216 {
217 if (reply.type == ICE_PROTOCOL_REPLY)
218 {
219 if (reply.protocol_reply.version_index >=
220 myProtocol->orig_client->version_count)
221 {
222 if (errorStringRet && errorLength > 0) {
223 strncpy (errorStringRet,
224 "Got a bad version index in the Protocol Reply",
225 errorLength);
226 errorStringRet[errorLength - 1] = '\0';
227 }
228
229 free (reply.protocol_reply.vendor);
230 free (reply.protocol_reply.release);
231 }
232 else
233 {
234 versionRec = &(myProtocol->orig_client->version_recs[
235 reply.protocol_reply.version_index]);
236
237 accepted = 1;
238 }
239 }
240 else /* reply.type == ICE_PROTOCOL_ERROR */
241 {
242 /* Protocol Setup failed */
243
244 if (errorStringRet && errorLength > 0) {
245 strncpy (errorStringRet, reply.protocol_error.error_message,
246 errorLength);
247 errorStringRet[errorLength - 1] = '\0';
248 }
249
250 free (reply.protocol_error.error_message);
251 }
252
253 if (iceConn->protosetup_to_you->my_auth_indices)
254 free (iceConn->protosetup_to_you->my_auth_indices);
255 free (iceConn->protosetup_to_you);
256 iceConn->protosetup_to_you = NULL;
257 }
258 }
259
260 if (accepted)
261 {
262 _IceProcessMsgInfo *process_msg_info;
263
264 *majorVersionRet = versionRec->major_version;
265 *minorVersionRet = versionRec->minor_version;
266 *vendorRet = reply.protocol_reply.vendor;
267 *releaseRet = reply.protocol_reply.release;
268
269
270 /*
271 * Increase the reference count for the number of active protocols.
272 */
273
274 iceConn->proto_ref_count++;
275
276
277 /*
278 * We may be using a different major opcode for this protocol
279 * than the other client. Whenever we get a message, we must
280 * map to our own major opcode.
281 */
282
283 hisOpcode = reply.protocol_reply.major_opcode;
284
285 _IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode);
286
287 process_msg_info = &iceConn->process_msg_info[hisOpcode -
288 iceConn->his_min_opcode];
289
290 process_msg_info->client_data = clientData;
291 process_msg_info->accept_flag = 0;
292
293 process_msg_info->process_msg_proc.orig_client =
294 versionRec->process_msg_proc;
295
296 return (IceProtocolSetupSuccess);
297 }
298 else
299 {
300 return (IceProtocolSetupFailure);
301 }
302 }
303