upload tizen2.0 source
[framework/uifw/xorg/lib/libice.git] / src / protosetup.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
36 IceProtocolSetupStatus
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         strncpy (errorStringRet, "myOpcode out of range", errorLength);
75         return (IceProtocolSetupFailure);
76     }
77
78     myProtocol = &_IceProtocols[myOpcode - 1];
79
80     if (myProtocol->orig_client == NULL)
81     {
82         strncpy (errorStringRet,
83             "IceRegisterForProtocolSetup was not called", errorLength);
84         return (IceProtocolSetupFailure);
85     }
86
87
88     /*
89      * Make sure this protocol hasn't been activated already.
90      */
91
92     if (iceConn->process_msg_info)
93     {
94         for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++)
95         {
96             if (iceConn->process_msg_info[
97                 i - iceConn->his_min_opcode].in_use &&
98                 iceConn->process_msg_info[
99                 i - iceConn->his_min_opcode ].my_opcode == myOpcode)
100                 break;
101         }
102
103         if (i <= iceConn->his_max_opcode)
104         {
105             return (IceProtocolAlreadyActive);
106         }
107     }
108
109     /*
110      * Generate the message.
111      */
112
113     if (myProtocol->orig_client->auth_count > 0)
114     {
115         authIndices = (int *) malloc (
116             myProtocol->orig_client->auth_count * sizeof (int));
117
118         _IceGetPoValidAuthIndices (myProtocol->protocol_name,
119             iceConn->connection_string,
120             myProtocol->orig_client->auth_count,
121             (const char **) myProtocol->orig_client->auth_names,
122             &authCount, authIndices);
123
124     }
125     else
126     {
127         authCount = 0;
128         authIndices = NULL;
129     }
130
131     extra = STRING_BYTES (myProtocol->protocol_name) +
132             STRING_BYTES (myProtocol->orig_client->vendor) +
133             STRING_BYTES (myProtocol->orig_client->release);
134
135     for (i = 0; i < authCount; i++)
136     {
137         extra += STRING_BYTES (myProtocol->orig_client->auth_names[
138             authIndices[i]]);
139     }
140
141     extra += (myProtocol->orig_client->version_count * 4);
142
143     IceGetHeaderExtra (iceConn, 0, ICE_ProtocolSetup,
144         SIZEOF (iceProtocolSetupMsg), WORD64COUNT (extra),
145         iceProtocolSetupMsg, pMsg, pData);
146
147     setup_sequence = iceConn->send_sequence;
148
149     pMsg->protocolOpcode = myOpcode;
150     pMsg->versionCount = myProtocol->orig_client->version_count;
151     pMsg->authCount = authCount;
152     pMsg->mustAuthenticate = mustAuthenticate;
153
154     STORE_STRING (pData, myProtocol->protocol_name);
155     STORE_STRING (pData, myProtocol->orig_client->vendor);
156     STORE_STRING (pData, myProtocol->orig_client->release);
157
158     for (i = 0; i < authCount; i++)
159     {
160         STORE_STRING (pData, myProtocol->orig_client->auth_names[
161             authIndices[i]]);
162     }
163
164     for (i = 0; i < myProtocol->orig_client->version_count; i++)
165     {
166         STORE_CARD16 (pData,
167             myProtocol->orig_client->version_recs[i].major_version);
168         STORE_CARD16 (pData,
169             myProtocol->orig_client->version_recs[i].minor_version);
170     }
171
172     IceFlush (iceConn);
173
174
175     /*
176      * Process messages until we get a Protocol Reply.
177      */
178
179     replyWait.sequence_of_request = setup_sequence;
180     replyWait.major_opcode_of_request = 0;
181     replyWait.minor_opcode_of_request = ICE_ProtocolSetup;
182     replyWait.reply = (IcePointer) &reply;
183
184     iceConn->protosetup_to_you = (_IceProtoSetupToYouInfo *) malloc (
185         sizeof (_IceProtoSetupToYouInfo));
186     iceConn->protosetup_to_you->my_opcode = myOpcode;
187     iceConn->protosetup_to_you->my_auth_count = authCount;
188     iceConn->protosetup_to_you->auth_active = 0;
189     iceConn->protosetup_to_you->my_auth_indices = authIndices;
190
191     gotReply = False;
192     ioErrorOccured = False;
193     accepted = 0;
194
195     while (!gotReply && !ioErrorOccured)
196     {
197         ioErrorOccured = (IceProcessMessages (
198             iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError);
199
200         if (ioErrorOccured)
201         {
202             strncpy (errorStringRet,
203                 "IO error occured doing Protocol Setup on connection",
204                 errorLength);
205             return (IceProtocolSetupIOError);
206         }
207         else if (gotReply)
208         {
209             if (reply.type == ICE_PROTOCOL_REPLY)
210             {
211                 if (reply.protocol_reply.version_index >=
212                     myProtocol->orig_client->version_count)
213                 {
214                     strncpy (errorStringRet,
215                         "Got a bad version index in the Protocol Reply",
216                         errorLength);
217
218                     free (reply.protocol_reply.vendor);
219                     free (reply.protocol_reply.release);
220                 }
221                 else
222                 {
223                     versionRec = &(myProtocol->orig_client->version_recs[
224                         reply.protocol_reply.version_index]);
225
226                     accepted = 1;
227                 }
228             }
229             else /* reply.type == ICE_PROTOCOL_ERROR */
230             {
231                 /* Protocol Setup failed */
232
233                 strncpy (errorStringRet, reply.protocol_error.error_message,
234                     errorLength);
235
236                 free (reply.protocol_error.error_message);
237             }
238
239             if (iceConn->protosetup_to_you->my_auth_indices)
240                 free ((char *) iceConn->protosetup_to_you->my_auth_indices);
241             free ((char *) iceConn->protosetup_to_you);
242             iceConn->protosetup_to_you = NULL;
243         }
244     }
245
246     if (accepted)
247     {
248         _IceProcessMsgInfo *process_msg_info;
249
250         *majorVersionRet = versionRec->major_version;
251         *minorVersionRet = versionRec->minor_version;
252         *vendorRet = reply.protocol_reply.vendor;
253         *releaseRet = reply.protocol_reply.release;
254
255
256         /*
257          * Increase the reference count for the number of active protocols.
258          */
259
260         iceConn->proto_ref_count++;
261
262
263         /*
264          * We may be using a different major opcode for this protocol
265          * than the other client.  Whenever we get a message, we must
266          * map to our own major opcode.
267          */
268
269         hisOpcode = reply.protocol_reply.major_opcode;
270
271         _IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode);
272
273         process_msg_info = &iceConn->process_msg_info[hisOpcode -
274             iceConn->his_min_opcode];
275
276         process_msg_info->client_data = clientData;
277         process_msg_info->accept_flag = 0;
278
279         process_msg_info->process_msg_proc.orig_client =
280                 versionRec->process_msg_proc;
281
282         return (IceProtocolSetupSuccess);
283     }
284     else
285     {
286         return (IceProtocolSetupFailure);
287     }
288 }