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