@@ -64,96 +64,252 @@ translator node_connection_t <node_dtrace_connection_t *nc> {
6464 & ((node_dtrace_connection64_t * )nc )-> buffered , sizeof (int32_t ));
6565};
6666
67+ /*
68+ * 32-bit and 64-bit structures received from node for HTTP client request
69+ * probe.
70+ */
71+ typedef struct {
72+ uint32_t url ;
73+ uint32_t method ;
74+ } node_dtrace_http_client_request_t ;
75+
76+ typedef struct {
77+ uint64_t url ;
78+ uint64_t method ;
79+ } node_dtrace_http_client_request64_t ;
80+
81+ /*
82+ * The following structures are never used directly, but must exist to bind the
83+ * types specified in the provider to the translators defined here.
84+ * Ultimately, they always get cast to a more specific type inside the
85+ * translator. To add to the confusion, the DTrace compiler does not allow
86+ * declaring two translators with the same destination type if the source types
87+ * are structures with the same size (because libctf says they're compatible,
88+ * so dtrace considers them equivalent). Since we must define translators from
89+ * node_dtrace_http_client_request_t (above), node_dtrace_http_request_t, and
90+ * node_dtrace_http_server_request_t (both below), each of these three structs
91+ * must be declared with a different size.
92+ */
6793typedef struct {
6894 uint32_t version ;
95+ uint64_t dummy1 ;
6996} node_dtrace_http_request_t ;
7097
98+ typedef struct {
99+ uint32_t version ;
100+ uint64_t dummy2 ;
101+ uint64_t dummy3 ;
102+ } node_dtrace_http_server_request_t ;
103+
104+ /*
105+ * Actual 32-bit and 64-bit, v0 and v1 structures received from node for the
106+ * HTTP server request probe.
107+ */
71108typedef struct {
72109 uint32_t url ;
73110 uint32_t method ;
74- } node_dtrace_http_request_v0_t ;
111+ } node_dtrace_http_server_request_v0_t ;
75112
76113typedef struct {
77114 uint32_t version ;
78115 uint32_t url ;
79116 uint32_t method ;
80117 uint32_t forwardedFor ;
81- } node_dtrace_http_request_v1_t ;
118+ } node_dtrace_http_server_request_v1_t ;
82119
83120typedef struct {
84121 uint64_t url ;
85122 uint64_t method ;
86- } node_dtrace_http_request64_v0_t ;
123+ } node_dtrace_http_server_request64_v0_t ;
87124
88125typedef struct {
89126 uint32_t version ;
90127 uint32_t pad ;
91128 uint64_t url ;
92129 uint64_t method ;
93130 uint64_t forwardedFor ;
94- } node_dtrace_http_request64_v1_t ;
131+ } node_dtrace_http_server_request64_v1_t ;
95132
133+ /*
134+ * In the end, both client and server request probes from both old and new
135+ * binaries translate their arguments to node_http_request_t, which is what the
136+ * user's D script ultimately sees.
137+ */
96138typedef struct {
97139 string url ;
98140 string method ;
99141 string forwardedFor ;
100142} node_http_request_t ;
101143
102144/*
103- * This translator is even filthier than usual owing to our attempts to
104- * maintain backwards compatibility. Previous versions of node used an
105- * http_request struct that had fields for "url" and "method". The current
106- * version also provides a "forwardedFor" field. To distinguish the binary
107- * representations of these structs, the new version also prepends a "version"
108- * member (where the old one has a "url" pointer). So each field that we're
109- * translating below first switches on the value of this "version" field: if
110- * it's larger than 4096, we know we must be looking at the "url" pointer of
111- * the older structure version. Otherwise, we must be looking at the new
112- * version. Besides this, we have the usual switch based on the userland
113- * process data model. This would all be simpler with macros, but those aren't
114- * available in delivered D library files since that would make DTrace
115- * dependent on cpp, which isn't always available.
145+ * The following translators are particularly filthy for reasons of backwards
146+ * compatibility. Stable versions of node prior to 0.6 used a single
147+ * http_request struct with fields for "url" and "method" for both client and
148+ * server probes. 0.6 added a "forwardedFor" field intended for the server
149+ * probe only, and the http_request struct passed by the application was split
150+ * first into client_http_request and server_http_request and the latter was
151+ * again split for v0 (the old struct) and v1.
152+ *
153+ * To distinguish the binary representations of the two versions of these
154+ * structs, the new version prepends a "version" member (where the old one has
155+ * a "url" pointer). Each field that we're translating below first switches on
156+ * the value of this "version" field: if it's larger than 4096, we know we must
157+ * be looking at the "url" pointer of the older structure version. Otherwise,
158+ * we must be looking at the new version. Besides this, we have the usual
159+ * switch based on the userland process data model. This would all be simpler
160+ * with macros, but those aren't available in D library files since we cannot
161+ * rely on cpp being present at runtime.
162+ *
163+ * In retrospect, the versioning bit might have been unnecessary since the type
164+ * of the object passed in should allow DTrace to select which translator to
165+ * use. However, DTrace does sometimes use translators whose source types
166+ * don't quite match, and since we know this versioning logic works, we just
167+ * leave it alone. Each of the translators below is functionally identical
168+ * (except that the client -> client translator doesn't bother translating
169+ * forwardedFor) and should actually work with any version of any of the client
170+ * or server structs transmitted by the application up to this point.
116171 */
117- translator node_http_request_t < node_dtrace_http_request_t * nd > {
118- url = (* (uint32_t * )copyin ((uintptr_t )& nd -> version , sizeof (uint32_t ))) >= 4096 ?
172+
173+ /*
174+ * Translate from node_dtrace_http_server_request_t (received from node 0.6 and
175+ * later versions) to node_http_request_t.
176+ */
177+ translator node_http_request_t < node_dtrace_http_server_request_t * nd > {
178+ url = (* (uint32_t * )copyin ((uintptr_t )(uint32_t * )nd ,
179+ sizeof (uint32_t ))) >= 4096 ?
180+ (curpsinfo -> pr_dmodel == PR_MODEL_ILP32 ?
181+ copyinstr (* (uint32_t * )copyin ((uintptr_t )
182+ & ((node_dtrace_http_server_request_v0_t * )nd )-> url ,
183+ sizeof (uint32_t ))) :
184+ copyinstr (* (uint64_t * )copyin ((uintptr_t )
185+ & ((node_dtrace_http_server_request64_v0_t * )nd )-> url ,
186+ sizeof (uint64_t )))) :
187+ (curpsinfo -> pr_dmodel == PR_MODEL_ILP32 ?
188+ copyinstr (* (uint32_t * )copyin ((uintptr_t )
189+ & ((node_dtrace_http_server_request_v1_t * )nd )-> url ,
190+ sizeof (uint32_t ))) :
191+ copyinstr (* (uint64_t * )copyin ((uintptr_t )
192+ & ((node_dtrace_http_server_request64_v1_t * )nd )-> url ,
193+ sizeof (uint64_t )))) ;
194+
195+ method = (* (uint32_t * )copyin ((uintptr_t )(uint32_t * )nd ,
196+ sizeof (uint32_t ))) >= 4096 ?
197+ (curpsinfo -> pr_dmodel == PR_MODEL_ILP32 ?
198+ copyinstr (* (uint32_t * )copyin ((uintptr_t )
199+ & ((node_dtrace_http_server_request_v0_t * )nd )-> method ,
200+ sizeof (uint32_t ))) :
201+ copyinstr (* (uint64_t * )copyin ((uintptr_t )
202+ & ((node_dtrace_http_server_request64_v0_t * )nd )-> method ,
203+ sizeof (uint64_t )))) :
119204 (curpsinfo -> pr_dmodel == PR_MODEL_ILP32 ?
120205 copyinstr (* (uint32_t * )copyin ((uintptr_t )
121- & ((node_dtrace_http_request_v0_t * )nd )-> url ,
206+ & ((node_dtrace_http_server_request_v1_t * )nd )-> method ,
122207 sizeof (uint32_t ))) :
123208 copyinstr (* (uint64_t * )copyin ((uintptr_t )
124- & ((node_dtrace_http_request64_v0_t * )nd )-> url ,
209+ & ((node_dtrace_http_server_request64_v1_t * )nd )-> method ,
210+ sizeof (uint64_t ))));
211+
212+ forwardedFor = (* (uint32_t * )copyin ((uintptr_t )(uint32_t * )nd ,
213+ sizeof (uint32_t ))) >= 4096 ? "" :
214+ (curpsinfo -> pr_dmodel == PR_MODEL_ILP32 ?
215+ copyinstr (* (uint32_t * )copyin ((uintptr_t )
216+ & ((node_dtrace_http_server_request_v1_t * )nd )-> forwardedFor ,
217+ sizeof (uint32_t ))) :
218+ copyinstr (* (uint64_t * )copyin ((uintptr_t )
219+ & ((node_dtrace_http_server_request64_v1_t * )nd )->
220+ forwardedFor , sizeof (uint64_t ))));
221+ };
222+
223+ /*
224+ * Translate from node_dtrace_http_client_request_t (received from node 0.6 and
225+ * later versions) to node_http_request_t.
226+ */
227+ translator node_http_request_t < node_dtrace_http_client_request_t * nd > {
228+ url = (* (uint32_t * )copyin ((uintptr_t )(uint32_t * )nd ,
229+ sizeof (uint32_t ))) >= 4096 ?
230+ (curpsinfo -> pr_dmodel == PR_MODEL_ILP32 ?
231+ copyinstr (* (uint32_t * )copyin ((uintptr_t )
232+ & ((node_dtrace_http_server_request_v0_t * )nd )-> url ,
233+ sizeof (uint32_t ))) :
234+ copyinstr (* (uint64_t * )copyin ((uintptr_t )
235+ & ((node_dtrace_http_server_request64_v0_t * )nd )-> url ,
125236 sizeof (uint64_t )))) :
126237 (curpsinfo -> pr_dmodel == PR_MODEL_ILP32 ?
127238 copyinstr (* (uint32_t * )copyin ((uintptr_t )
128- & ((node_dtrace_http_request_v1_t * )nd )-> url ,
239+ & ((node_dtrace_http_server_request_v1_t * )nd )-> url ,
129240 sizeof (uint32_t ))) :
130241 copyinstr (* (uint64_t * )copyin ((uintptr_t )
131- & ((node_dtrace_http_request64_v1_t * )nd )-> url ,
242+ & ((node_dtrace_http_server_request64_v1_t * )nd )-> url ,
132243 sizeof (uint64_t )))) ;
133244
134- method = (* (uint32_t * )copyin ((uintptr_t )& nd -> version , sizeof (uint32_t ))) >= 4096 ?
245+ method = (* (uint32_t * )copyin ((uintptr_t )(uint32_t * )nd ,
246+ sizeof (uint32_t ))) >= 4096 ?
135247 (curpsinfo -> pr_dmodel == PR_MODEL_ILP32 ?
136248 copyinstr (* (uint32_t * )copyin ((uintptr_t )
137- & ((node_dtrace_http_request_v0_t * )nd )-> method ,
249+ & ((node_dtrace_http_server_request_v0_t * )nd )-> method ,
138250 sizeof (uint32_t ))) :
139251 copyinstr (* (uint64_t * )copyin ((uintptr_t )
140- & ((node_dtrace_http_request64_v0_t * )nd )-> method ,
252+ & ((node_dtrace_http_server_request64_v0_t * )nd )-> method ,
141253 sizeof (uint64_t )))) :
142254 (curpsinfo -> pr_dmodel == PR_MODEL_ILP32 ?
143255 copyinstr (* (uint32_t * )copyin ((uintptr_t )
144- & ((node_dtrace_http_request_v1_t * )nd )-> method ,
256+ & ((node_dtrace_http_server_request_v1_t * )nd )-> method ,
145257 sizeof (uint32_t ))) :
146258 copyinstr (* (uint64_t * )copyin ((uintptr_t )
147- & ((node_dtrace_http_request64_v1_t * )nd )-> method ,
259+ & ((node_dtrace_http_server_request64_v1_t * )nd )-> method ,
148260 sizeof (uint64_t ))));
149-
150- forwardedFor = (* (uint32_t * )
151- copyin ((uintptr_t )& nd -> version , sizeof (uint32_t ))) >= 4096 ? "" :
261+
262+ forwardedFor = "" ;
263+ };
264+
265+ /*
266+ * Translate from node_dtrace_http_request_t (received from versions of node
267+ * prior to 0.6) to node_http_request_t. This is used for both the server and
268+ * client probes since these versions of node didn't distinguish between the
269+ * types used in these probes.
270+ */
271+ translator node_http_request_t < node_dtrace_http_request_t * nd > {
272+ url = (* (uint32_t * )copyin ((uintptr_t )(uint32_t * )nd ,
273+ sizeof (uint32_t ))) >= 4096 ?
152274 (curpsinfo -> pr_dmodel == PR_MODEL_ILP32 ?
153275 copyinstr (* (uint32_t * )copyin ((uintptr_t )
154- & ((node_dtrace_http_request_v1_t * )nd )-> forwardedFor ,
276+ & ((node_dtrace_http_server_request_v0_t * )nd )-> url ,
155277 sizeof (uint32_t ))) :
156278 copyinstr (* (uint64_t * )copyin ((uintptr_t )
157- & ((node_dtrace_http_request64_v1_t * )nd )-> forwardedFor ,
279+ & ((node_dtrace_http_server_request64_v0_t * )nd )-> url ,
280+ sizeof (uint64_t )))) :
281+ (curpsinfo -> pr_dmodel == PR_MODEL_ILP32 ?
282+ copyinstr (* (uint32_t * )copyin ((uintptr_t )
283+ & ((node_dtrace_http_server_request_v1_t * )nd )-> url ,
284+ sizeof (uint32_t ))) :
285+ copyinstr (* (uint64_t * )copyin ((uintptr_t )
286+ & ((node_dtrace_http_server_request64_v1_t * )nd )-> url ,
287+ sizeof (uint64_t )))) ;
288+
289+ method = (* (uint32_t * )copyin ((uintptr_t )(uint32_t * )nd ,
290+ sizeof (uint32_t ))) >= 4096 ?
291+ (curpsinfo -> pr_dmodel == PR_MODEL_ILP32 ?
292+ copyinstr (* (uint32_t * )copyin ((uintptr_t )
293+ & ((node_dtrace_http_server_request_v0_t * )nd )-> method ,
294+ sizeof (uint32_t ))) :
295+ copyinstr (* (uint64_t * )copyin ((uintptr_t )
296+ & ((node_dtrace_http_server_request64_v0_t * )nd )-> method ,
297+ sizeof (uint64_t )))) :
298+ (curpsinfo -> pr_dmodel == PR_MODEL_ILP32 ?
299+ copyinstr (* (uint32_t * )copyin ((uintptr_t )
300+ & ((node_dtrace_http_server_request_v1_t * )nd )-> method ,
301+ sizeof (uint32_t ))) :
302+ copyinstr (* (uint64_t * )copyin ((uintptr_t )
303+ & ((node_dtrace_http_server_request64_v1_t * )nd )-> method ,
158304 sizeof (uint64_t ))));
305+
306+ forwardedFor = (* (uint32_t * ) copyin ((uintptr_t )(uint32_t * )nd ,
307+ sizeof (uint32_t ))) >= 4096 ? "" :
308+ (curpsinfo -> pr_dmodel == PR_MODEL_ILP32 ?
309+ copyinstr (* (uint32_t * )copyin ((uintptr_t )
310+ & ((node_dtrace_http_server_request_v1_t * )nd )-> forwardedFor ,
311+ sizeof (uint32_t ))) :
312+ copyinstr (* (uint64_t * )copyin ((uintptr_t )
313+ & ((node_dtrace_http_server_request64_v1_t * )nd )->
314+ forwardedFor , sizeof (uint64_t ))));
159315};
0 commit comments