9
9
// 3. _ensure_fd_no_transport
10
10
// 4. _ensure_resolve
11
11
12
+ #include < iostream>
12
13
#include < boost/asio.hpp>
13
14
#include < boost/bind.hpp>
14
15
#include < boost/python.hpp>
@@ -53,6 +54,7 @@ void _sock_connect_cb(object pymod_socket, std::promise<void>& prom, std::future
53
54
// TODO: print the address
54
55
PyErr_SetString (PyExc_OSError, " Connect call failed {address}" );
55
56
}
57
+ prom.set_value ();
56
58
}
57
59
catch (const error_already_set& e)
58
60
{
@@ -67,15 +69,10 @@ void _sock_connect_cb(object pymod_socket, std::promise<void>& prom, std::future
67
69
{
68
70
// raise
69
71
}
70
- else if (PyErr_ExceptionMatches (PyExc_BaseException))
71
- {
72
- PyErr_Clear ();
73
- prom.set_exception (std::current_exception ());
74
- }
75
72
else
76
73
{
77
74
PyErr_Clear ();
78
- prom.set_value ( );
75
+ prom.set_exception ( std::current_exception () );
79
76
}
80
77
}
81
78
}
@@ -91,6 +88,7 @@ void _sock_accept(event_loop& loop, std::promise<object>& prom, std::future<obje
91
88
conn = ret[0 ];
92
89
address = ret[1 ];
93
90
conn.attr (" setblocking" )(object (false ));
91
+ prom.set_value (make_tuple (conn, address));
94
92
}
95
93
catch (const error_already_set& e)
96
94
{
@@ -107,19 +105,27 @@ void _sock_accept(event_loop& loop, std::promise<object>& prom, std::future<obje
107
105
{
108
106
// raise
109
107
}
110
- else if (PyErr_ExceptionMatches (PyExc_BaseException))
111
- {
112
- PyErr_Clear ();
113
- prom.set_exception (std::current_exception ());
114
- }
115
108
else
116
109
{
117
110
PyErr_Clear ();
118
- prom.set_value ( make_tuple (conn, address ));
111
+ prom.set_exception ( std::current_exception ( ));
119
112
}
120
113
}
121
114
}
122
115
116
+ void _getaddrinfo_handler (object pymod_socket, std::promise<object>& prom,
117
+ object host, int port, int family, int type, int proto, int flags)
118
+ {
119
+ object res = pymod_socket.attr (" getaddrinfo" )(host, port, family, type, proto, flags);
120
+ prom.set_value (res);
121
+ }
122
+
123
+ void _getnameinfo_handler (object pymod_socket, std::promise<object>& prom, object sockaddr, int flags)
124
+ {
125
+ object res = pymod_socket.attr (" getnameinfo" )(sockaddr, flags);
126
+ prom.set_value (res);
127
+ }
128
+
123
129
}
124
130
125
131
void event_loop::_add_reader_or_writer (int fd, object f, int key)
@@ -237,6 +243,7 @@ void event_loop::sock_connect(object sock, object address)
237
243
try
238
244
{
239
245
sock.attr (" connect" )(address);
246
+ prom.set_value ();
240
247
}
241
248
catch (const error_already_set& e)
242
249
{
@@ -253,15 +260,10 @@ void event_loop::sock_connect(object sock, object address)
253
260
{
254
261
// raise
255
262
}
256
- else if (PyErr_ExceptionMatches (PyExc_BaseException))
257
- {
258
- PyErr_Clear ();
259
- prom.set_exception (std::current_exception ());
260
- }
261
263
else
262
264
{
263
265
PyErr_Clear ();
264
- prom.set_value ( );
266
+ prom.set_exception ( std::current_exception () );
265
267
}
266
268
}
267
269
fut.wait ();
@@ -281,4 +283,172 @@ void event_loop::sock_sendfile(object sock, object file, int offset, int count,
281
283
PyErr_SetString (PyExc_NotImplementedError, " Not implemented!" );
282
284
}
283
285
286
+ // TODO: implement this
287
+ void event_loop::start_tls (object transport, object protocol, object sslcontext,
288
+ bool server_side, object server_hostname, object ssl_handshake_timeout)
289
+ {
290
+ PyErr_SetString (PyExc_NotImplementedError, " Not implemented!" );
291
+ }
292
+
293
+ object event_loop::getaddrinfo (object host, int port, int family, int type, int proto, int flags)
294
+ {
295
+ std::promise<object> prom;
296
+ std::future<object> fut = prom.get_future ();
297
+ call_soon (make_function (
298
+ bind (_getaddrinfo_handler, _pymod_socket, boost::ref (prom), host, port, family, type, proto, flags),
299
+ default_call_policies (),
300
+ boost::mpl::vector<void , object>()));
301
+ return fut.get ();
302
+ }
303
+
304
+ object event_loop::getnameinfo (object sockaddr, int flags)
305
+ {
306
+ std::promise<object> prom;
307
+ std::future<object> fut = prom.get_future ();
308
+ call_soon (make_function (
309
+ bind (_getnameinfo_handler, _pymod_socket, boost::ref (prom), sockaddr, flags),
310
+ default_call_policies (),
311
+ boost::mpl::vector<void , object>()));
312
+ return fut.get ();
313
+ }
314
+
315
+ void event_loop::default_exception_handler (object context)
316
+ {
317
+ object message = context.attr (" get" )(str (" message" ));
318
+ if (message == object ())
319
+ {
320
+ message = str (" Unhandled exception in event loop" );
321
+ }
322
+
323
+ object exception = context.attr (" get" )(str (" exception" ));
324
+ object exc_info;
325
+ if (exception != object ())
326
+ {
327
+ exc_info = make_tuple (exception .attr (" __class__" ), exception , exception .attr (" __traceback__" ));
328
+ }
329
+ else
330
+ {
331
+ exc_info = object (false );
332
+ }
333
+ if (!PyObject_IsTrue (context.attr (" __contains__" )(str (" source_traceback" )).ptr ()) &&
334
+ _exception_handler != object () &&
335
+ _exception_handler.attr (" _source_traceback" ) != object ())
336
+ {
337
+ context[" handle_traceback" ] = _exception_handler.attr (" _source_traceback" );
338
+ }
339
+
340
+ list log_lines;
341
+ log_lines.append (message);
342
+ list context_keys (context.attr (" keys" ));
343
+ context_keys.sort ();
344
+ for (int i = 0 ; i < len (context_keys); i++)
345
+ {
346
+ std::string key = extract<std::string>(context_keys[i]);
347
+ if (key == " message" || key == " exception" )
348
+ continue ;
349
+ str value (context[key]);
350
+ if (key == " source_traceback" )
351
+ {
352
+ str tb = str (" " ).join (_pymod_traceback.attr (" format_list" )(value));
353
+ value = str (" Object created at (most recent call last):\n " );
354
+ value += tb.rstrip ();
355
+ }
356
+ else if (key == " handle_traceback" )
357
+ {
358
+ str tb = str (" " ).join (_pymod_traceback.attr (" format_list" )(value));
359
+ value = str (" Handle created at (most recent call last):\n " );
360
+ value += tb.rstrip ();
361
+ }
362
+ else
363
+ {
364
+ value = str (value.attr (" __str__" )());
365
+ }
366
+ std::ostringstream stringStream;
367
+ stringStream << key << " : " << value;
368
+ log_lines.append (str (stringStream.str ()));
369
+ }
370
+ list args;
371
+ dict kwargs;
372
+ args.append (str (" \n " ).join (log_lines));
373
+ kwargs[" exc_info" ] = exc_info;
374
+ _pymod_logger.attr (" error" )(tuple (args), **kwargs);
375
+ }
376
+
377
+ void event_loop::call_exception_handler (object context)
378
+ {
379
+ if (_exception_handler == object ())
380
+ {
381
+ try
382
+ {
383
+ default_exception_handler (context);
384
+ }
385
+ catch (const error_already_set& e)
386
+ {
387
+ if (PyErr_ExceptionMatches (PyExc_SystemExit)
388
+ || PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
389
+ {
390
+ // raise
391
+ }
392
+ else
393
+ {
394
+ PyErr_Clear ();
395
+ list args;
396
+ dict kwargs;
397
+ args.append (str (" Exception in default exception handler" ));
398
+ kwargs[" exc_info" ] = true ;
399
+ _pymod_logger.attr (" error" )(tuple (args), **kwargs);
400
+ }
401
+ }
402
+ }
403
+ else
404
+ {
405
+ try
406
+ {
407
+ _exception_handler (context);
408
+ }
409
+ catch (const error_already_set& e)
410
+ {
411
+ if (PyErr_ExceptionMatches (PyExc_SystemExit)
412
+ || PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
413
+ {
414
+ // raise
415
+ }
416
+ else
417
+ {
418
+ PyObject *ptype, *pvalue, *ptraceback;
419
+ PyErr_Fetch (&ptype, &pvalue, &ptraceback);
420
+ PyErr_NormalizeException (&ptype, &pvalue, &ptraceback);
421
+ object type (handle<>(ptype));
422
+ object value (handle<>(pvalue));
423
+ object traceback (handle<>(ptraceback));
424
+ try
425
+ {
426
+ dict tmp_dict;
427
+ tmp_dict[" message" ] = str (" Unhandled error in exception handler" );
428
+ tmp_dict[" exception" ] = value;
429
+ tmp_dict[" context" ] = context;
430
+ default_exception_handler (tmp_dict);
431
+ }
432
+ catch (const error_already_set& e)
433
+ {
434
+ if (PyErr_ExceptionMatches (PyExc_SystemExit)
435
+ || PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
436
+ {
437
+ // raise
438
+ }
439
+ else
440
+ {
441
+ boost::python::list args;
442
+ boost::python::dict kwargs;
443
+ args.append (str (" Exception in default exception handler" ));
444
+ kwargs[" exc_info" ] = true ;
445
+ _pymod_logger.attr (" error" )(tuple (args), **kwargs);
446
+ }
447
+ }
448
+ }
449
+ }
450
+ }
451
+ }
452
+
453
+
284
454
}}}
0 commit comments