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