77#define NODE_HTTP_SERVER_REQUEST_ENABLED () (0 )
88#define NODE_HTTP_SERVER_RESPONSE (arg0 )
99#define NODE_HTTP_SERVER_RESPONSE_ENABLED () (0 )
10+ #define NODE_HTTP_CLIENT_REQUEST (arg0, arg1 )
11+ #define NODE_HTTP_CLIENT_REQUEST_ENABLED () (0 )
12+ #define NODE_HTTP_CLIENT_RESPONSE (arg0 )
13+ #define NODE_HTTP_CLIENT_RESPONSE_ENABLED () (0 )
1014#define NODE_NET_SERVER_CONNECTION (arg0 )
1115#define NODE_NET_SERVER_CONNECTION_ENABLED () (0 )
1216#define NODE_NET_STREAM_END (arg0 )
1317#define NODE_NET_STREAM_END_ENABLED () (0 )
18+ #define NODE_NET_SOCKET_READ (arg0, arg1 )
19+ #define NODE_NET_SOCKET_READ_ENABLED () (0 )
20+ #define NODE_NET_SOCKET_WRITE (arg0, arg1 )
21+ #define NODE_NET_SOCKET_WRITE_ENABLED () (0 )
22+ #define NODE_GC_START (arg0, arg1 )
23+ #define NODE_GC_DONE (arg0, arg1 )
1424#endif
1525
1626namespace node {
1727
1828using namespace v8 ;
1929
2030#define SLURP_STRING (obj, member, valp ) \
31+ if (!(obj)->IsObject ()) { \
32+ return (ThrowException (Exception::Error (String::New (" expected " \
33+ " object for " #obj " to contain string member " #member)))); \
34+ } \
2135 String::Utf8Value _##member(obj->Get (String::New(#member))->ToString()); \
2236 if ((*(const char **)valp = *_##member) == NULL ) \
2337 *(const char **)valp = " <unknown>" ;
2438
2539#define SLURP_INT (obj, member, valp ) \
40+ if (!(obj)->IsObject ()) { \
41+ return (ThrowException (Exception::Error (String::New (" expected " \
42+ " object for " #obj " to contain integer member " #member)))); \
43+ } \
2644 *valp = obj->Get (String::New(#member))->ToInteger()->Value();
2745
46+ #define SLURP_OBJECT (obj, member, valp ) \
47+ if (!(obj)->IsObject ()) { \
48+ return (ThrowException (Exception::Error (String::New (" expected " \
49+ " object for " #obj " to contain object member " #member)))); \
50+ } \
51+ *valp = Local<Object>::Cast(obj->Get (String::New(#member)));
52+
2853#define SLURP_CONNECTION (arg, conn ) \
54+ if (!(arg)->IsObject ()) { \
55+ return (ThrowException (Exception::Error (String::New (" expected " \
56+ " argument " #arg " to be a connection object" )))); \
57+ } \
2958 node_dtrace_connection_t conn; \
3059 Local<Object> _##conn = Local<Object>::Cast(arg); \
3160 SLURP_INT (_##conn, fd, &conn.fd); \
3261 SLURP_STRING (_##conn, remoteAddress, &conn.remote); \
33- SLURP_INT (_##conn, remotePort, &conn.port);
62+ SLURP_INT (_##conn, remotePort, &conn.port); \
63+ SLURP_INT (_##conn, bufferSize, &conn.buffered);
64+
65+ #define SLURP_CONNECTION_HTTP_CLIENT (arg, conn ) \
66+ if (!(arg)->IsObject ()) { \
67+ return (ThrowException (Exception::Error (String::New (" expected " \
68+ " argument " #arg " to be a connection object" )))); \
69+ } \
70+ node_dtrace_connection_t conn; \
71+ Local<Object> _##conn = Local<Object>::Cast(arg); \
72+ SLURP_INT (_##conn, fd, &conn.fd); \
73+ SLURP_STRING (_##conn, host, &conn.remote); \
74+ SLURP_INT (_##conn, port, &conn.port); \
75+ SLURP_INT (_##conn, bufferSize, &conn.buffered);
76+
77+ #define SLURP_CONNECTION_HTTP_CLIENT_RESPONSE (arg0, arg1, conn ) \
78+ if (!(arg0)->IsObject ()) { \
79+ return (ThrowException (Exception::Error (String::New (" expected " \
80+ " argument " #arg0 " to be a connection object" )))); \
81+ } \
82+ if (!(arg1)->IsObject ()) { \
83+ return (ThrowException (Exception::Error (String::New (" expected " \
84+ " argument " #arg1 " to be a connection object" )))); \
85+ } \
86+ node_dtrace_connection_t conn; \
87+ Local<Object> _##conn = Local<Object>::Cast(arg0); \
88+ SLURP_INT (_##conn, fd, &conn.fd); \
89+ SLURP_INT (_##conn, bufferSize, &conn.buffered); \
90+ _##conn = Local<Object>::Cast(arg1); \
91+ SLURP_STRING (_##conn, host, &conn.remote); \
92+ SLURP_INT (_##conn, port, &conn.port);
93+
3494
3595Handle<Value> DTRACE_NET_SERVER_CONNECTION (const Arguments& args) {
3696 if (!NODE_NET_SERVER_CONNECTION_ENABLED ())
@@ -56,6 +116,48 @@ Handle<Value> DTRACE_NET_STREAM_END(const Arguments& args) {
56116 return Undefined ();
57117}
58118
119+ Handle<Value> DTRACE_NET_SOCKET_READ (const Arguments& args) {
120+ if (!NODE_NET_SOCKET_READ_ENABLED ())
121+ return Undefined ();
122+
123+ HandleScope scope;
124+ int nbytes;
125+
126+ SLURP_CONNECTION (args[0 ], conn);
127+
128+ if (!args[1 ]->IsNumber ()) {
129+ return (ThrowException (Exception::Error (String::New (" expected "
130+ " argument 1 to be number of bytes" ))));
131+ }
132+
133+ nbytes = args[1 ]->Int32Value ();
134+
135+ NODE_NET_SOCKET_READ (&conn, nbytes);
136+
137+ return Undefined ();
138+ }
139+
140+ Handle<Value> DTRACE_NET_SOCKET_WRITE (const Arguments& args) {
141+ if (!NODE_NET_SOCKET_WRITE_ENABLED ())
142+ return Undefined ();
143+
144+ HandleScope scope;
145+ int nbytes;
146+
147+ SLURP_CONNECTION (args[0 ], conn);
148+
149+ if (!args[1 ]->IsNumber ()) {
150+ return (ThrowException (Exception::Error (String::New (" expected "
151+ " argument 1 to be number of bytes" ))));
152+ }
153+
154+ nbytes = args[1 ]->Int32Value ();
155+
156+ NODE_NET_SOCKET_WRITE (&conn, nbytes);
157+
158+ return Undefined ();
159+ }
160+
59161Handle<Value> DTRACE_HTTP_SERVER_REQUEST (const Arguments& args) {
60162 node_dtrace_http_request_t req;
61163
@@ -65,7 +167,6 @@ Handle<Value> DTRACE_HTTP_SERVER_REQUEST(const Arguments& args) {
65167 HandleScope scope;
66168
67169 Local<Object> arg0 = Local<Object>::Cast (args[0 ]);
68- Local<Object> arg1 = Local<Object>::Cast (args[1 ]);
69170
70171 SLURP_STRING (arg0, url, &req.url );
71172 SLURP_STRING (arg0, method, &req.method );
@@ -88,8 +189,72 @@ Handle<Value> DTRACE_HTTP_SERVER_RESPONSE(const Arguments& args) {
88189 return Undefined ();
89190}
90191
192+ Handle<Value> DTRACE_HTTP_CLIENT_REQUEST (const Arguments& args) {
193+ node_dtrace_http_request_t req;
194+ char *header;
195+
196+ if (!NODE_HTTP_CLIENT_REQUEST_ENABLED ())
197+ return Undefined ();
198+
199+ HandleScope scope;
200+
201+ /*
202+ * For the method and URL, we're going to dig them out of the header. This
203+ * is not as efficient as it could be, but we would rather not force the
204+ * caller here to retain their method and URL until the time at which
205+ * DTRACE_HTTP_CLIENT_REQUEST can be called.
206+ */
207+ Local<Object> arg0 = Local<Object>::Cast (args[0 ]);
208+ SLURP_STRING (arg0, _header, &header);
209+
210+ req.method = header;
211+
212+ while (*header != ' \0 ' && *header != ' ' )
213+ header++;
214+
215+ if (*header != ' \0 ' )
216+ *header++ = ' \0 ' ;
217+
218+ req.url = header;
219+
220+ while (*header != ' \0 ' && *header != ' ' )
221+ header++;
222+
223+ *header = ' \0 ' ;
224+
225+ SLURP_CONNECTION_HTTP_CLIENT (args[1 ], conn);
226+ NODE_HTTP_CLIENT_REQUEST (&req, &conn);
227+ return Undefined ();
228+ }
229+
230+ Handle<Value> DTRACE_HTTP_CLIENT_RESPONSE (const Arguments& args) {
231+ if (!NODE_HTTP_CLIENT_RESPONSE_ENABLED ())
232+ return Undefined ();
233+
234+ HandleScope scope;
235+
236+ SLURP_CONNECTION_HTTP_CLIENT_RESPONSE (args[0 ], args[1 ], conn);
237+ NODE_HTTP_CLIENT_RESPONSE (&conn);
238+
239+ return Undefined ();
240+ }
241+
91242#define NODE_PROBE (name ) #name, name
92243
244+ static int dtrace_gc_start (GCType type, GCCallbackFlags flags) {
245+ NODE_GC_START (type, flags);
246+ /*
247+ * We avoid the tail-call elimination of the USDT probe (which screws up
248+ * args) by forcing a return of 0.
249+ */
250+ return 0 ;
251+ }
252+
253+ static int dtrace_gc_done (GCType type, GCCallbackFlags flags) {
254+ NODE_GC_DONE (type, flags);
255+ return 0 ;
256+ }
257+
93258void InitDTrace (Handle<Object> target) {
94259 static struct {
95260 const char *name;
@@ -98,8 +263,12 @@ void InitDTrace(Handle<Object> target) {
98263 } tab[] = {
99264 { NODE_PROBE (DTRACE_NET_SERVER_CONNECTION) },
100265 { NODE_PROBE (DTRACE_NET_STREAM_END) },
266+ { NODE_PROBE (DTRACE_NET_SOCKET_READ) },
267+ { NODE_PROBE (DTRACE_NET_SOCKET_WRITE) },
101268 { NODE_PROBE (DTRACE_HTTP_SERVER_REQUEST) },
102269 { NODE_PROBE (DTRACE_HTTP_SERVER_RESPONSE) },
270+ { NODE_PROBE (DTRACE_HTTP_CLIENT_REQUEST) },
271+ { NODE_PROBE (DTRACE_HTTP_CLIENT_RESPONSE) },
103272 { NULL }
104273 };
105274
@@ -108,6 +277,11 @@ void InitDTrace(Handle<Object> target) {
108277 FunctionTemplate::New (tab[i].func ));
109278 target->Set (String::NewSymbol (tab[i].name ), tab[i].templ ->GetFunction ());
110279 }
280+
281+ #ifdef HAVE_DTRACE
282+ v8::V8::AddGCPrologueCallback ((GCPrologueCallback)dtrace_gc_start);
283+ v8::V8::AddGCEpilogueCallback ((GCEpilogueCallback)dtrace_gc_done);
284+ #endif
111285}
112286
113287}
0 commit comments