protosetup.c revision c5629e66
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
39c5629e66SmrgIceProtocolSetup (
40c5629e66Smrg	IceConn	   iceConn,
41c5629e66Smrg	int 	   myOpcode,
42c5629e66Smrg	IcePointer clientData,
43c5629e66Smrg	Bool       mustAuthenticate,
44c5629e66Smrg	int	   *majorVersionRet,
45c5629e66Smrg	int	   *minorVersionRet,
46c5629e66Smrg	char	   **vendorRet,
47c5629e66Smrg	char	   **releaseRet,
48c5629e66Smrg	int  	   errorLength,
49c5629e66Smrg	char 	   *errorStringRet
50c5629e66Smrg)
51266e564dSmrg{
52266e564dSmrg    iceProtocolSetupMsg	*pMsg;
53266e564dSmrg    char		*pData;
54266e564dSmrg    _IceProtocol	*myProtocol;
55266e564dSmrg    int			extra;
56266e564dSmrg    Bool		gotReply, ioErrorOccured;
57266e564dSmrg    int			accepted, i;
58266e564dSmrg    int			hisOpcode;
59266e564dSmrg    unsigned long	setup_sequence;
60266e564dSmrg    IceReplyWaitInfo 	replyWait;
61266e564dSmrg    _IceReply		reply;
62266e564dSmrg    IcePoVersionRec	*versionRec = NULL;
63266e564dSmrg    int			authCount;
64266e564dSmrg    int			*authIndices;
65266e564dSmrg
66266e564dSmrg    if (errorStringRet && errorLength > 0)
67266e564dSmrg	*errorStringRet = '\0';
68266e564dSmrg
69266e564dSmrg    *majorVersionRet = 0;
70266e564dSmrg    *minorVersionRet = 0;
71266e564dSmrg    *vendorRet = NULL;
72266e564dSmrg    *releaseRet = NULL;
73266e564dSmrg
74266e564dSmrg    if (myOpcode < 1 || myOpcode > _IceLastMajorOpcode)
75266e564dSmrg    {
76266e564dSmrg	strncpy (errorStringRet, "myOpcode out of range", errorLength);
77266e564dSmrg	return (IceProtocolSetupFailure);
78266e564dSmrg    }
79266e564dSmrg
80266e564dSmrg    myProtocol = &_IceProtocols[myOpcode - 1];
81266e564dSmrg
82266e564dSmrg    if (myProtocol->orig_client == NULL)
83266e564dSmrg    {
84266e564dSmrg	strncpy (errorStringRet,
85266e564dSmrg	    "IceRegisterForProtocolSetup was not called", errorLength);
86266e564dSmrg	return (IceProtocolSetupFailure);
87266e564dSmrg    }
88266e564dSmrg
89266e564dSmrg
90266e564dSmrg    /*
91266e564dSmrg     * Make sure this protocol hasn't been activated already.
92266e564dSmrg     */
93266e564dSmrg
94266e564dSmrg    if (iceConn->process_msg_info)
95266e564dSmrg    {
96266e564dSmrg	for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++)
97266e564dSmrg	{
98266e564dSmrg	    if (iceConn->process_msg_info[
99266e564dSmrg		i - iceConn->his_min_opcode].in_use &&
100266e564dSmrg                iceConn->process_msg_info[
101266e564dSmrg		i - iceConn->his_min_opcode ].my_opcode == myOpcode)
102266e564dSmrg		break;
103266e564dSmrg	}
104266e564dSmrg
105266e564dSmrg	if (i <= iceConn->his_max_opcode)
106266e564dSmrg	{
107266e564dSmrg	    return (IceProtocolAlreadyActive);
108266e564dSmrg	}
109266e564dSmrg    }
110266e564dSmrg
111266e564dSmrg    /*
112266e564dSmrg     * Generate the message.
113266e564dSmrg     */
114266e564dSmrg
115266e564dSmrg    if (myProtocol->orig_client->auth_count > 0)
116266e564dSmrg    {
117266e564dSmrg	authIndices = (int *) malloc (
118266e564dSmrg	    myProtocol->orig_client->auth_count * sizeof (int));
119266e564dSmrg
120266e564dSmrg	_IceGetPoValidAuthIndices (myProtocol->protocol_name,
121266e564dSmrg	    iceConn->connection_string,
122266e564dSmrg	    myProtocol->orig_client->auth_count,
123266e564dSmrg	    myProtocol->orig_client->auth_names,
124266e564dSmrg            &authCount, authIndices);
125266e564dSmrg
126266e564dSmrg    }
127266e564dSmrg    else
128266e564dSmrg    {
129266e564dSmrg	authCount = 0;
130266e564dSmrg	authIndices = NULL;
131266e564dSmrg    }
132266e564dSmrg
133266e564dSmrg    extra = STRING_BYTES (myProtocol->protocol_name) +
134266e564dSmrg            STRING_BYTES (myProtocol->orig_client->vendor) +
135266e564dSmrg            STRING_BYTES (myProtocol->orig_client->release);
136266e564dSmrg
137266e564dSmrg    for (i = 0; i < authCount; i++)
138266e564dSmrg    {
139266e564dSmrg	extra += STRING_BYTES (myProtocol->orig_client->auth_names[
140266e564dSmrg	    authIndices[i]]);
141266e564dSmrg    }
142266e564dSmrg
143266e564dSmrg    extra += (myProtocol->orig_client->version_count * 4);
144266e564dSmrg
145266e564dSmrg    IceGetHeaderExtra (iceConn, 0, ICE_ProtocolSetup,
146266e564dSmrg	SIZEOF (iceProtocolSetupMsg), WORD64COUNT (extra),
147266e564dSmrg	iceProtocolSetupMsg, pMsg, pData);
148266e564dSmrg
149266e564dSmrg    setup_sequence = iceConn->send_sequence;
150266e564dSmrg
151266e564dSmrg    pMsg->protocolOpcode = myOpcode;
152266e564dSmrg    pMsg->versionCount = myProtocol->orig_client->version_count;
153266e564dSmrg    pMsg->authCount = authCount;
154266e564dSmrg    pMsg->mustAuthenticate = mustAuthenticate;
155266e564dSmrg
156266e564dSmrg    STORE_STRING (pData, myProtocol->protocol_name);
157266e564dSmrg    STORE_STRING (pData, myProtocol->orig_client->vendor);
158266e564dSmrg    STORE_STRING (pData, myProtocol->orig_client->release);
159266e564dSmrg
160266e564dSmrg    for (i = 0; i < authCount; i++)
161266e564dSmrg    {
162266e564dSmrg	STORE_STRING (pData, myProtocol->orig_client->auth_names[
163266e564dSmrg	    authIndices[i]]);
164266e564dSmrg    }
165266e564dSmrg
166266e564dSmrg    for (i = 0; i < myProtocol->orig_client->version_count; i++)
167266e564dSmrg    {
168266e564dSmrg	STORE_CARD16 (pData,
169266e564dSmrg	    myProtocol->orig_client->version_recs[i].major_version);
170266e564dSmrg	STORE_CARD16 (pData,
171266e564dSmrg	    myProtocol->orig_client->version_recs[i].minor_version);
172266e564dSmrg    }
173266e564dSmrg
174266e564dSmrg    IceFlush (iceConn);
175266e564dSmrg
176266e564dSmrg
177266e564dSmrg    /*
178266e564dSmrg     * Process messages until we get a Protocol Reply.
179266e564dSmrg     */
180266e564dSmrg
181266e564dSmrg    replyWait.sequence_of_request = setup_sequence;
182266e564dSmrg    replyWait.major_opcode_of_request = 0;
183266e564dSmrg    replyWait.minor_opcode_of_request = ICE_ProtocolSetup;
184266e564dSmrg    replyWait.reply = (IcePointer) &reply;
185266e564dSmrg
186266e564dSmrg    iceConn->protosetup_to_you = (_IceProtoSetupToYouInfo *) malloc (
187266e564dSmrg	sizeof (_IceProtoSetupToYouInfo));
188266e564dSmrg    iceConn->protosetup_to_you->my_opcode = myOpcode;
189266e564dSmrg    iceConn->protosetup_to_you->my_auth_count = authCount;
190266e564dSmrg    iceConn->protosetup_to_you->auth_active = 0;
191266e564dSmrg    iceConn->protosetup_to_you->my_auth_indices = authIndices;
192266e564dSmrg
193266e564dSmrg    gotReply = False;
194266e564dSmrg    ioErrorOccured = False;
195266e564dSmrg    accepted = 0;
196266e564dSmrg
197266e564dSmrg    while (!gotReply && !ioErrorOccured)
198266e564dSmrg    {
199266e564dSmrg	ioErrorOccured = (IceProcessMessages (
200266e564dSmrg	    iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError);
201266e564dSmrg
202266e564dSmrg	if (ioErrorOccured)
203266e564dSmrg	{
204266e564dSmrg	    strncpy (errorStringRet,
205266e564dSmrg		"IO error occured doing Protocol Setup on connection",
206266e564dSmrg		errorLength);
207266e564dSmrg	    return (IceProtocolSetupIOError);
208266e564dSmrg	}
209266e564dSmrg	else if (gotReply)
210266e564dSmrg	{
211266e564dSmrg	    if (reply.type == ICE_PROTOCOL_REPLY)
212266e564dSmrg	    {
213266e564dSmrg		if (reply.protocol_reply.version_index >=
214266e564dSmrg		    myProtocol->orig_client->version_count)
215266e564dSmrg		{
216266e564dSmrg		    strncpy (errorStringRet,
217266e564dSmrg	                "Got a bad version index in the Protocol Reply",
218266e564dSmrg		        errorLength);
219266e564dSmrg
220266e564dSmrg		    free (reply.protocol_reply.vendor);
221266e564dSmrg		    free (reply.protocol_reply.release);
222266e564dSmrg		}
223266e564dSmrg		else
224266e564dSmrg		{
225266e564dSmrg		    versionRec = &(myProtocol->orig_client->version_recs[
226266e564dSmrg		        reply.protocol_reply.version_index]);
227266e564dSmrg
228266e564dSmrg		    accepted = 1;
229266e564dSmrg		}
230266e564dSmrg	    }
231266e564dSmrg	    else /* reply.type == ICE_PROTOCOL_ERROR */
232266e564dSmrg	    {
233266e564dSmrg		/* Protocol Setup failed */
234266e564dSmrg
235266e564dSmrg		strncpy (errorStringRet, reply.protocol_error.error_message,
236266e564dSmrg		    errorLength);
237266e564dSmrg
238266e564dSmrg		free (reply.protocol_error.error_message);
239266e564dSmrg	    }
240266e564dSmrg
241266e564dSmrg	    if (iceConn->protosetup_to_you->my_auth_indices)
242266e564dSmrg		free ((char *) iceConn->protosetup_to_you->my_auth_indices);
243266e564dSmrg	    free ((char *) iceConn->protosetup_to_you);
244266e564dSmrg	    iceConn->protosetup_to_you = NULL;
245266e564dSmrg	}
246266e564dSmrg    }
247266e564dSmrg
248266e564dSmrg    if (accepted)
249266e564dSmrg    {
250266e564dSmrg	_IceProcessMsgInfo *process_msg_info;
251266e564dSmrg
252266e564dSmrg	*majorVersionRet = versionRec->major_version;
253266e564dSmrg	*minorVersionRet = versionRec->minor_version;
254266e564dSmrg	*vendorRet = reply.protocol_reply.vendor;
255266e564dSmrg	*releaseRet = reply.protocol_reply.release;
256266e564dSmrg
257266e564dSmrg
258266e564dSmrg	/*
259266e564dSmrg	 * Increase the reference count for the number of active protocols.
260266e564dSmrg	 */
261266e564dSmrg
262266e564dSmrg	iceConn->proto_ref_count++;
263266e564dSmrg
264266e564dSmrg
265266e564dSmrg	/*
266266e564dSmrg	 * We may be using a different major opcode for this protocol
267266e564dSmrg	 * than the other client.  Whenever we get a message, we must
268266e564dSmrg	 * map to our own major opcode.
269266e564dSmrg	 */
270266e564dSmrg
271266e564dSmrg	hisOpcode = reply.protocol_reply.major_opcode;
272266e564dSmrg
273266e564dSmrg	_IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode);
274266e564dSmrg
275266e564dSmrg	process_msg_info = &iceConn->process_msg_info[hisOpcode -
276266e564dSmrg	    iceConn->his_min_opcode];
277266e564dSmrg
278266e564dSmrg	process_msg_info->client_data = clientData;
279266e564dSmrg	process_msg_info->accept_flag = 0;
280266e564dSmrg
281266e564dSmrg	process_msg_info->process_msg_proc.orig_client =
282266e564dSmrg		versionRec->process_msg_proc;
283266e564dSmrg
284266e564dSmrg	return (IceProtocolSetupSuccess);
285266e564dSmrg    }
286266e564dSmrg    else
287266e564dSmrg    {
288266e564dSmrg	return (IceProtocolSetupFailure);
289266e564dSmrg    }
290266e564dSmrg}
291