protosetup.c revision 266e564d
1266e564dSmrg/* $Xorg: protosetup.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
2266e564dSmrg/******************************************************************************
3266e564dSmrg
4266e564dSmrg
5266e564dSmrgCopyright 1993, 1998  The Open Group
6266e564dSmrg
7266e564dSmrgPermission to use, copy, modify, distribute, and sell this software and its
8266e564dSmrgdocumentation for any purpose is hereby granted without fee, provided that
9266e564dSmrgthe above copyright notice appear in all copies and that both that
10266e564dSmrgcopyright notice and this permission notice appear in supporting
11266e564dSmrgdocumentation.
12266e564dSmrg
13266e564dSmrgThe above copyright notice and this permission notice shall be included in
14266e564dSmrgall copies or substantial portions of the Software.
15266e564dSmrg
16266e564dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17266e564dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18266e564dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19266e564dSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20266e564dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21266e564dSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22266e564dSmrg
23266e564dSmrgExcept as contained in this notice, the name of The Open Group shall not be
24266e564dSmrgused in advertising or otherwise to promote the sale, use or other dealings
25266e564dSmrgin this Software without prior written authorization from The Open Group.
26266e564dSmrg
27266e564dSmrgAuthor: Ralph Mor, X Consortium
28266e564dSmrg******************************************************************************/
29266e564dSmrg/* $XFree86: xc/lib/ICE/protosetup.c,v 1.2 2001/10/28 03:32:28 tsi Exp $ */
30266e564dSmrg
31266e564dSmrg#ifdef HAVE_CONFIG_H
32266e564dSmrg#include <config.h>
33266e564dSmrg#endif
34266e564dSmrg#include <X11/ICE/ICElib.h>
35266e564dSmrg#include "ICElibint.h"
36266e564dSmrg
37266e564dSmrg
38266e564dSmrgIceProtocolSetupStatus
39266e564dSmrgIceProtocolSetup (iceConn, myOpcode, clientData, mustAuthenticate,
40266e564dSmrg    majorVersionRet, minorVersionRet, vendorRet, releaseRet,
41266e564dSmrg    errorLength, errorStringRet)
42266e564dSmrg
43266e564dSmrgIceConn	   iceConn;
44266e564dSmrgint 	   myOpcode;
45266e564dSmrgIcePointer clientData;
46266e564dSmrgBool       mustAuthenticate;
47266e564dSmrgint	   *majorVersionRet;
48266e564dSmrgint	   *minorVersionRet;
49266e564dSmrgchar	   **vendorRet;
50266e564dSmrgchar	   **releaseRet;
51266e564dSmrgint  	   errorLength;
52266e564dSmrgchar 	   *errorStringRet;
53266e564dSmrg
54266e564dSmrg{
55266e564dSmrg    iceProtocolSetupMsg	*pMsg;
56266e564dSmrg    char		*pData;
57266e564dSmrg    _IceProtocol	*myProtocol;
58266e564dSmrg    int			extra;
59266e564dSmrg    Bool		gotReply, ioErrorOccured;
60266e564dSmrg    int			accepted, i;
61266e564dSmrg    int			hisOpcode;
62266e564dSmrg    unsigned long	setup_sequence;
63266e564dSmrg    IceReplyWaitInfo 	replyWait;
64266e564dSmrg    _IceReply		reply;
65266e564dSmrg    IcePoVersionRec	*versionRec = NULL;
66266e564dSmrg    int			authCount;
67266e564dSmrg    int			*authIndices;
68266e564dSmrg
69266e564dSmrg    if (errorStringRet && errorLength > 0)
70266e564dSmrg	*errorStringRet = '\0';
71266e564dSmrg
72266e564dSmrg    *majorVersionRet = 0;
73266e564dSmrg    *minorVersionRet = 0;
74266e564dSmrg    *vendorRet = NULL;
75266e564dSmrg    *releaseRet = NULL;
76266e564dSmrg
77266e564dSmrg    if (myOpcode < 1 || myOpcode > _IceLastMajorOpcode)
78266e564dSmrg    {
79266e564dSmrg	strncpy (errorStringRet, "myOpcode out of range", errorLength);
80266e564dSmrg	return (IceProtocolSetupFailure);
81266e564dSmrg    }
82266e564dSmrg
83266e564dSmrg    myProtocol = &_IceProtocols[myOpcode - 1];
84266e564dSmrg
85266e564dSmrg    if (myProtocol->orig_client == NULL)
86266e564dSmrg    {
87266e564dSmrg	strncpy (errorStringRet,
88266e564dSmrg	    "IceRegisterForProtocolSetup was not called", errorLength);
89266e564dSmrg	return (IceProtocolSetupFailure);
90266e564dSmrg    }
91266e564dSmrg
92266e564dSmrg
93266e564dSmrg    /*
94266e564dSmrg     * Make sure this protocol hasn't been activated already.
95266e564dSmrg     */
96266e564dSmrg
97266e564dSmrg    if (iceConn->process_msg_info)
98266e564dSmrg    {
99266e564dSmrg	for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++)
100266e564dSmrg	{
101266e564dSmrg	    if (iceConn->process_msg_info[
102266e564dSmrg		i - iceConn->his_min_opcode].in_use &&
103266e564dSmrg                iceConn->process_msg_info[
104266e564dSmrg		i - iceConn->his_min_opcode ].my_opcode == myOpcode)
105266e564dSmrg		break;
106266e564dSmrg	}
107266e564dSmrg
108266e564dSmrg	if (i <= iceConn->his_max_opcode)
109266e564dSmrg	{
110266e564dSmrg	    return (IceProtocolAlreadyActive);
111266e564dSmrg	}
112266e564dSmrg    }
113266e564dSmrg
114266e564dSmrg    /*
115266e564dSmrg     * Generate the message.
116266e564dSmrg     */
117266e564dSmrg
118266e564dSmrg    if (myProtocol->orig_client->auth_count > 0)
119266e564dSmrg    {
120266e564dSmrg	authIndices = (int *) malloc (
121266e564dSmrg	    myProtocol->orig_client->auth_count * sizeof (int));
122266e564dSmrg
123266e564dSmrg	_IceGetPoValidAuthIndices (myProtocol->protocol_name,
124266e564dSmrg	    iceConn->connection_string,
125266e564dSmrg	    myProtocol->orig_client->auth_count,
126266e564dSmrg	    myProtocol->orig_client->auth_names,
127266e564dSmrg            &authCount, authIndices);
128266e564dSmrg
129266e564dSmrg    }
130266e564dSmrg    else
131266e564dSmrg    {
132266e564dSmrg	authCount = 0;
133266e564dSmrg	authIndices = NULL;
134266e564dSmrg    }
135266e564dSmrg
136266e564dSmrg    extra = STRING_BYTES (myProtocol->protocol_name) +
137266e564dSmrg            STRING_BYTES (myProtocol->orig_client->vendor) +
138266e564dSmrg            STRING_BYTES (myProtocol->orig_client->release);
139266e564dSmrg
140266e564dSmrg    for (i = 0; i < authCount; i++)
141266e564dSmrg    {
142266e564dSmrg	extra += STRING_BYTES (myProtocol->orig_client->auth_names[
143266e564dSmrg	    authIndices[i]]);
144266e564dSmrg    }
145266e564dSmrg
146266e564dSmrg    extra += (myProtocol->orig_client->version_count * 4);
147266e564dSmrg
148266e564dSmrg    IceGetHeaderExtra (iceConn, 0, ICE_ProtocolSetup,
149266e564dSmrg	SIZEOF (iceProtocolSetupMsg), WORD64COUNT (extra),
150266e564dSmrg	iceProtocolSetupMsg, pMsg, pData);
151266e564dSmrg
152266e564dSmrg    setup_sequence = iceConn->send_sequence;
153266e564dSmrg
154266e564dSmrg    pMsg->protocolOpcode = myOpcode;
155266e564dSmrg    pMsg->versionCount = myProtocol->orig_client->version_count;
156266e564dSmrg    pMsg->authCount = authCount;
157266e564dSmrg    pMsg->mustAuthenticate = mustAuthenticate;
158266e564dSmrg
159266e564dSmrg    STORE_STRING (pData, myProtocol->protocol_name);
160266e564dSmrg    STORE_STRING (pData, myProtocol->orig_client->vendor);
161266e564dSmrg    STORE_STRING (pData, myProtocol->orig_client->release);
162266e564dSmrg
163266e564dSmrg    for (i = 0; i < authCount; i++)
164266e564dSmrg    {
165266e564dSmrg	STORE_STRING (pData, myProtocol->orig_client->auth_names[
166266e564dSmrg	    authIndices[i]]);
167266e564dSmrg    }
168266e564dSmrg
169266e564dSmrg    for (i = 0; i < myProtocol->orig_client->version_count; i++)
170266e564dSmrg    {
171266e564dSmrg	STORE_CARD16 (pData,
172266e564dSmrg	    myProtocol->orig_client->version_recs[i].major_version);
173266e564dSmrg	STORE_CARD16 (pData,
174266e564dSmrg	    myProtocol->orig_client->version_recs[i].minor_version);
175266e564dSmrg    }
176266e564dSmrg
177266e564dSmrg    IceFlush (iceConn);
178266e564dSmrg
179266e564dSmrg
180266e564dSmrg    /*
181266e564dSmrg     * Process messages until we get a Protocol Reply.
182266e564dSmrg     */
183266e564dSmrg
184266e564dSmrg    replyWait.sequence_of_request = setup_sequence;
185266e564dSmrg    replyWait.major_opcode_of_request = 0;
186266e564dSmrg    replyWait.minor_opcode_of_request = ICE_ProtocolSetup;
187266e564dSmrg    replyWait.reply = (IcePointer) &reply;
188266e564dSmrg
189266e564dSmrg    iceConn->protosetup_to_you = (_IceProtoSetupToYouInfo *) malloc (
190266e564dSmrg	sizeof (_IceProtoSetupToYouInfo));
191266e564dSmrg    iceConn->protosetup_to_you->my_opcode = myOpcode;
192266e564dSmrg    iceConn->protosetup_to_you->my_auth_count = authCount;
193266e564dSmrg    iceConn->protosetup_to_you->auth_active = 0;
194266e564dSmrg    iceConn->protosetup_to_you->my_auth_indices = authIndices;
195266e564dSmrg
196266e564dSmrg    gotReply = False;
197266e564dSmrg    ioErrorOccured = False;
198266e564dSmrg    accepted = 0;
199266e564dSmrg
200266e564dSmrg    while (!gotReply && !ioErrorOccured)
201266e564dSmrg    {
202266e564dSmrg	ioErrorOccured = (IceProcessMessages (
203266e564dSmrg	    iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError);
204266e564dSmrg
205266e564dSmrg	if (ioErrorOccured)
206266e564dSmrg	{
207266e564dSmrg	    strncpy (errorStringRet,
208266e564dSmrg		"IO error occured doing Protocol Setup on connection",
209266e564dSmrg		errorLength);
210266e564dSmrg	    return (IceProtocolSetupIOError);
211266e564dSmrg	}
212266e564dSmrg	else if (gotReply)
213266e564dSmrg	{
214266e564dSmrg	    if (reply.type == ICE_PROTOCOL_REPLY)
215266e564dSmrg	    {
216266e564dSmrg		if (reply.protocol_reply.version_index >=
217266e564dSmrg		    myProtocol->orig_client->version_count)
218266e564dSmrg		{
219266e564dSmrg		    strncpy (errorStringRet,
220266e564dSmrg	                "Got a bad version index in the Protocol Reply",
221266e564dSmrg		        errorLength);
222266e564dSmrg
223266e564dSmrg		    free (reply.protocol_reply.vendor);
224266e564dSmrg		    free (reply.protocol_reply.release);
225266e564dSmrg		}
226266e564dSmrg		else
227266e564dSmrg		{
228266e564dSmrg		    versionRec = &(myProtocol->orig_client->version_recs[
229266e564dSmrg		        reply.protocol_reply.version_index]);
230266e564dSmrg
231266e564dSmrg		    accepted = 1;
232266e564dSmrg		}
233266e564dSmrg	    }
234266e564dSmrg	    else /* reply.type == ICE_PROTOCOL_ERROR */
235266e564dSmrg	    {
236266e564dSmrg		/* Protocol Setup failed */
237266e564dSmrg
238266e564dSmrg		strncpy (errorStringRet, reply.protocol_error.error_message,
239266e564dSmrg		    errorLength);
240266e564dSmrg
241266e564dSmrg		free (reply.protocol_error.error_message);
242266e564dSmrg	    }
243266e564dSmrg
244266e564dSmrg	    if (iceConn->protosetup_to_you->my_auth_indices)
245266e564dSmrg		free ((char *) iceConn->protosetup_to_you->my_auth_indices);
246266e564dSmrg	    free ((char *) iceConn->protosetup_to_you);
247266e564dSmrg	    iceConn->protosetup_to_you = NULL;
248266e564dSmrg	}
249266e564dSmrg    }
250266e564dSmrg
251266e564dSmrg    if (accepted)
252266e564dSmrg    {
253266e564dSmrg	_IceProcessMsgInfo *process_msg_info;
254266e564dSmrg
255266e564dSmrg	*majorVersionRet = versionRec->major_version;
256266e564dSmrg	*minorVersionRet = versionRec->minor_version;
257266e564dSmrg	*vendorRet = reply.protocol_reply.vendor;
258266e564dSmrg	*releaseRet = reply.protocol_reply.release;
259266e564dSmrg
260266e564dSmrg
261266e564dSmrg	/*
262266e564dSmrg	 * Increase the reference count for the number of active protocols.
263266e564dSmrg	 */
264266e564dSmrg
265266e564dSmrg	iceConn->proto_ref_count++;
266266e564dSmrg
267266e564dSmrg
268266e564dSmrg	/*
269266e564dSmrg	 * We may be using a different major opcode for this protocol
270266e564dSmrg	 * than the other client.  Whenever we get a message, we must
271266e564dSmrg	 * map to our own major opcode.
272266e564dSmrg	 */
273266e564dSmrg
274266e564dSmrg	hisOpcode = reply.protocol_reply.major_opcode;
275266e564dSmrg
276266e564dSmrg	_IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode);
277266e564dSmrg
278266e564dSmrg	process_msg_info = &iceConn->process_msg_info[hisOpcode -
279266e564dSmrg	    iceConn->his_min_opcode];
280266e564dSmrg
281266e564dSmrg	process_msg_info->client_data = clientData;
282266e564dSmrg	process_msg_info->accept_flag = 0;
283266e564dSmrg
284266e564dSmrg	process_msg_info->process_msg_proc.orig_client =
285266e564dSmrg		versionRec->process_msg_proc;
286266e564dSmrg
287266e564dSmrg	return (IceProtocolSetupSuccess);
288266e564dSmrg    }
289266e564dSmrg    else
290266e564dSmrg    {
291266e564dSmrg	return (IceProtocolSetupFailure);
292266e564dSmrg    }
293266e564dSmrg}
294