1 /*
2  * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * 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
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include "extensions.h"
25 #include "bigreqscope.h"
26 #include "lbxscope.h"
27 #include "randrscope.h"
28 #include "renderscope.h"
29 #include "shmscope.h"
30 #include "wcpscope.h"
31 
32 /* Extensions we know how to decode */
33 struct extension_decoders {
34     const char *name;
35     void (*init_func) (const unsigned char *buf);
36 };
37 
38 static const struct extension_decoders decodable_extensions[] = {
39     {"BIG-REQUESTS", InitializeBIGREQ},
40     {"LBX", InitializeLBX},
41     {"MIT-SHM", InitializeMITSHM},
42     {"NCD-WinCenterPro", InitializeWCP},
43     {"RANDR", InitializeRANDR},
44     {"RENDER", InitializeRENDER},
45     {"GLX", InitializeGLX},
46     {NULL, NULL}                /* List terminator - keep last */
47 };
48 
49 /* all extensions we know about */
50 struct extension_info {
51     const char *name;
52     unsigned char request;
53     unsigned char event;
54     unsigned char error;
55     long query_seq;             /* sequence id of QueryExtension request */
56     struct extension_info *next;
57 };
58 
59 struct extension_info *query_list;
60 
61 struct extension_info *ext_by_request[NUM_EXTENSIONS];
62 
63 static void
DefineExtNameValue(int type,unsigned char value,const char * extname)64 DefineExtNameValue(int type, unsigned char value, const char *extname)
65 {
66     int namelen = strlen(extname) + 1;
67     const char *typename = NULL;
68     char *exttypename;
69 
70     switch (type) {
71     case REQUEST:
72         typename = "-Request";
73         break;
74     case REPLY:
75         typename = "-Reply";
76         break;
77     case EVENT:
78         typename = "-Event";
79         break;
80     case ERROR:
81         typename = "-Error";
82         break;
83     case EXTENSION:
84         typename = "";
85         break;
86     default:
87         panic("Impossible argument to DefineExtNameValue");
88     }
89     namelen += strlen(typename);
90     exttypename = malloc(namelen);
91     if (exttypename == NULL)
92         panic("Can't allocate memory for ExtNameValue");
93     snprintf(exttypename, namelen, "%s%s", extname, typename);
94     DefineEValue(&TD[type], (unsigned long) value, exttypename);
95 }
96 
97 void
ProcessQueryExtensionRequest(long seq,const unsigned char * buf)98 ProcessQueryExtensionRequest(long seq, const unsigned char *buf)
99 {
100     int namelen = IShort(&buf[4]);
101     char *extname = malloc(namelen + 1);
102     struct extension_info *qe;
103 
104     if (extname == NULL)
105         panic("Can't allocate memory for ExtensionRequest name");
106     memcpy(extname, &buf[8], namelen);
107     extname[namelen] = '\0';
108 
109     for (qe = query_list; qe != NULL; qe = qe->next) {
110         if (strcmp(extname, qe->name) == 0) {
111             /* already in list, no need to add */
112             free(extname);
113             return;
114         }
115     }
116 
117     /* add to list */
118     qe = malloc(sizeof(struct extension_info));
119     if (qe == NULL)
120         panic("Can't allocate memory for extension_info");
121     qe->name = extname;
122     qe->request = 0;
123     qe->event = 0;
124     qe->error = 0;
125     qe->query_seq = seq;
126     qe->next = query_list;
127     query_list = qe;
128 }
129 
130 void
ProcessQueryExtensionReply(long seq,const unsigned char * buf)131 ProcessQueryExtensionReply(long seq, const unsigned char *buf)
132 {
133     struct extension_info *qe;
134     int i;
135 
136     if (buf[8] == 0) {
137         /* Extension not present, nothing to record */
138         return;
139     }
140 
141     for (qe = query_list; qe != NULL; qe = qe->next) {
142         if (qe->query_seq == seq) {
143             qe->request = buf[9];
144             qe->event = buf[10];
145             qe->error = buf[11];
146 
147             ext_by_request[qe->request - EXTENSION_MIN_REQ] = qe;
148 
149             DefineExtNameValue(EXTENSION, qe->request, qe->name);
150 
151             for (i = 0; decodable_extensions[i].name != NULL; i++) {
152                 if (strcmp(qe->name, decodable_extensions[i].name) == 0) {
153                     decodable_extensions[i].init_func(buf);
154                     break;
155                 }
156             }
157             if (decodable_extensions[i].name == NULL) {
158                 /* Not found - initialize values as best we can generically */
159                 DefineExtNameValue(REQUEST, qe->request, qe->name);
160                 DefineExtNameValue(REPLY, qe->request, qe->name);
161                 if (qe->event != 0) {
162                     DefineExtNameValue(EVENT, qe->event, qe->name);
163                 }
164                 if (qe->error != 0) {
165                     DefineExtNameValue(ERROR, qe->error, qe->name);
166                 }
167             }
168 
169             return;
170         }
171     }
172 }
173 
174 /* Decoding for specific/known extensions */
175 
176 static extension_decode_req_ptr ExtensionRequestDecoder[NUM_EXTENSIONS];
177 static extension_decode_reply_ptr ExtensionReplyDecoder[NUM_EXTENSIONS];
178 static extension_decode_error_ptr ExtensionErrorDecoder[NUM_EXTENSIONS];
179 static extension_decode_event_ptr ExtensionEventDecoder[NUM_EXT_EVENTS];
180 static extension_decode_event_ptr GenericEventDecoder[NUM_EXTENSIONS];
181 
182 void
InitializeExtensionDecoder(int Request,extension_decode_req_ptr reqd,extension_decode_reply_ptr repd)183 InitializeExtensionDecoder(int Request, extension_decode_req_ptr reqd,
184                            extension_decode_reply_ptr repd)
185 {
186     if ((Request > EXTENSION_MAX_REQ) || (Request < EXTENSION_MIN_REQ)) {
187         char errmsg[128];
188 
189         snprintf(errmsg, sizeof(errmsg), "Failed to register decoder"
190                  " for invalid extension request code %d.", Request);
191         warn(errmsg);
192         return;
193     }
194     ExtensionRequestDecoder[Request - EXTENSION_MIN_REQ] = reqd;
195     ExtensionReplyDecoder[Request - EXTENSION_MIN_REQ] = repd;
196 }
197 
198 void
InitializeExtensionErrorDecoder(int Error,extension_decode_error_ptr errd)199 InitializeExtensionErrorDecoder(int Error, extension_decode_error_ptr errd)
200 {
201     if ((Error > EXTENSION_MAX_ERR) || (Error < EXTENSION_MIN_ERR)) {
202         char errmsg[128];
203 
204         snprintf(errmsg, sizeof(errmsg), "Failed to register decoder"
205                  " for invalid extension error code %d.", Error);
206         warn(errmsg);
207         return;
208     }
209     ExtensionErrorDecoder[Error - EXTENSION_MIN_ERR] = errd;
210 }
211 
212 void
InitializeExtensionEventDecoder(int Event,extension_decode_event_ptr evd)213 InitializeExtensionEventDecoder(int Event, extension_decode_event_ptr evd)
214 {
215     if ((Event > EXTENSION_MAX_EV) || (Event < EXTENSION_MIN_EV)) {
216         char errmsg[128];
217 
218         snprintf(errmsg, sizeof(errmsg), "Failed to register decoder"
219                  " for invalid extension event code %d.", Event);
220         warn(errmsg);
221         return;
222     }
223     ExtensionEventDecoder[Event - EXTENSION_MIN_EV] = evd;
224 }
225 
226 void
InitializeGenericEventDecoder(int Request,extension_decode_event_ptr evd)227 InitializeGenericEventDecoder(int Request, extension_decode_event_ptr evd)
228 {
229     if ((Request > EXTENSION_MAX_REQ) || (Request < EXTENSION_MIN_REQ)) {
230         char errmsg[128];
231 
232         snprintf(errmsg, sizeof(errmsg), "Failed to register decoder"
233                  " for invalid generic extension event code %d.", Request);
234         warn(errmsg);
235         return;
236     }
237     GenericEventDecoder[Request - EXTENSION_MIN_REQ] = evd;
238 }
239 
240 void
ExtensionRequest(FD fd,const unsigned char * buf,short Request)241 ExtensionRequest(FD fd, const unsigned char *buf, short Request)
242 {
243     extension_decode_req_ptr decode_req = NULL;
244 
245     if ((Request <= EXTENSION_MAX_REQ) && (Request >= EXTENSION_MIN_REQ)) {
246         decode_req = ExtensionRequestDecoder[Request - EXTENSION_MIN_REQ];
247     }
248 
249     if (decode_req != NULL) {
250         decode_req(fd, buf);
251     }
252     else {
253         ExtendedRequest(fd, buf);
254         ReplyExpected(fd, Request);
255     }
256 }
257 
258 void
ExtensionReply(FD fd,const unsigned char * buf,short Request,short RequestMinor)259 ExtensionReply(FD fd, const unsigned char *buf,
260                short Request, short RequestMinor)
261 {
262     extension_decode_reply_ptr decode_reply = NULL;
263 
264     if ((Request <= EXTENSION_MAX_REQ) && (Request >= EXTENSION_MIN_REQ)) {
265         decode_reply = ExtensionReplyDecoder[Request - EXTENSION_MIN_REQ];
266     }
267 
268     if (decode_reply != NULL) {
269         decode_reply(fd, buf, RequestMinor);
270     }
271     else {
272         UnknownReply(buf);
273     }
274 }
275 
276 void
ExtensionError(FD fd,const unsigned char * buf,short Error)277 ExtensionError(FD fd, const unsigned char *buf, short Error)
278 {
279     extension_decode_error_ptr decode_error = NULL;
280 
281     if ((Error <= EXTENSION_MAX_ERR) && (Error >= EXTENSION_MIN_ERR)) {
282         decode_error = ExtensionErrorDecoder[Error - EXTENSION_MIN_ERR];
283     }
284 
285     if (decode_error != NULL) {
286         decode_error(fd, buf);
287     }
288     else {
289         UnknownError(buf);
290     }
291 }
292 
293 void
ExtensionEvent(FD fd,const unsigned char * buf,short Event)294 ExtensionEvent(FD fd, const unsigned char *buf, short Event)
295 {
296     extension_decode_event_ptr decode_event = NULL;
297 
298     if ((Event <= EXTENSION_MAX_EV) && (Event >= EXTENSION_MIN_EV)) {
299         decode_event = ExtensionEventDecoder[Event - EXTENSION_MIN_EV];
300     }
301     else if (Event == Event_Type_Generic) {
302         int Request = IByte(&buf[1]);
303 
304         if ((Request <= EXTENSION_MAX_REQ) && (Request >= EXTENSION_MIN_REQ)) {
305             decode_event = GenericEventDecoder[Request - EXTENSION_MIN_REQ];
306         }
307     }
308 
309     if (decode_event != NULL) {
310         decode_event(fd, buf);
311     }
312     else if (Event == Event_Type_Generic) {
313         UnknownGenericEvent(buf);
314     }
315     else {
316         UnknownEvent(buf);
317     }
318 }
319