99// 3. _ensure_fd_no_transport
1010// 4. _ensure_resolve
1111
12+ #include < iostream>
1213#include < boost/asio.hpp>
1314#include < boost/bind.hpp>
1415#include < boost/python.hpp>
@@ -53,6 +54,7 @@ void _sock_connect_cb(object pymod_socket, std::promise<void>& prom, std::future
5354 // TODO: print the address
5455 PyErr_SetString (PyExc_OSError, " Connect call failed {address}" );
5556 }
57+ prom.set_value ();
5658 }
5759 catch (const error_already_set& e)
5860 {
@@ -67,15 +69,10 @@ void _sock_connect_cb(object pymod_socket, std::promise<void>& prom, std::future
6769 {
6870 // raise
6971 }
70- else if (PyErr_ExceptionMatches (PyExc_BaseException))
71- {
72- PyErr_Clear ();
73- prom.set_exception (std::current_exception ());
74- }
7572 else
7673 {
7774 PyErr_Clear ();
78- prom.set_value ( );
75+ prom.set_exception ( std::current_exception () );
7976 }
8077 }
8178}
@@ -91,6 +88,7 @@ void _sock_accept(event_loop& loop, std::promise<object>& prom, std::future<obje
9188 conn = ret[0 ];
9289 address = ret[1 ];
9390 conn.attr (" setblocking" )(object (false ));
91+ prom.set_value (make_tuple (conn, address));
9492 }
9593 catch (const error_already_set& e)
9694 {
@@ -107,19 +105,27 @@ void _sock_accept(event_loop& loop, std::promise<object>& prom, std::future<obje
107105 {
108106 // raise
109107 }
110- else if (PyErr_ExceptionMatches (PyExc_BaseException))
111- {
112- PyErr_Clear ();
113- prom.set_exception (std::current_exception ());
114- }
115108 else
116109 {
117110 PyErr_Clear ();
118- prom.set_value ( make_tuple (conn, address ));
111+ prom.set_exception ( std::current_exception ( ));
119112 }
120113 }
121114}
122115
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+
123129}
124130
125131void 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)
237243 try
238244 {
239245 sock.attr (" connect" )(address);
246+ prom.set_value ();
240247 }
241248 catch (const error_already_set& e)
242249 {
@@ -253,15 +260,10 @@ void event_loop::sock_connect(object sock, object address)
253260 {
254261 // raise
255262 }
256- else if (PyErr_ExceptionMatches (PyExc_BaseException))
257- {
258- PyErr_Clear ();
259- prom.set_exception (std::current_exception ());
260- }
261263 else
262264 {
263265 PyErr_Clear ();
264- prom.set_value ( );
266+ prom.set_exception ( std::current_exception () );
265267 }
266268 }
267269 fut.wait ();
@@ -281,4 +283,164 @@ void event_loop::sock_sendfile(object sock, object file, int offset, int count,
281283 PyErr_SetString (PyExc_NotImplementedError, " Not implemented!" );
282284}
283285
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+ call_soon (make_function (bind (_getaddrinfo_handler, host, port, family, type, proto, flags),
296+ default_call_policies (), boost::mpl::vector<void , object>()));
297+ return object ();
298+ }
299+
300+ object event_loop::getnameinfo (object sockaddr, int flags)
301+ {
302+ call_soon (make_function (bind (_getnameinfo_handler, sockaddr, flags),
303+ default_call_policies (), boost::mpl::vector<void , object>()));
304+ return object ();
305+ }
306+
307+ void event_loop::default_exception_handler (object context)
308+ {
309+ object message = context.attr (" get" )(str (" message" ));
310+ if (message == object ())
311+ {
312+ message = str (" Unhandled exception in event loop" );
313+ }
314+
315+ object exception = context.attr (" get" )(str (" exception" ));
316+ object exc_info;
317+ if (exception != object ())
318+ {
319+ exc_info = make_tuple (exception.attr (" __class__" ), exception, exception.attr (" __traceback__" ));
320+ }
321+ else
322+ {
323+ exc_info = object (false );
324+ }
325+ if (!PyObject_IsTrue (context.attr (" __contains__" )(str (" source_traceback" )).ptr ()) &&
326+ _exception_handler != object () &&
327+ _exception_handler.attr (" _source_traceback" ) != object ())
328+ {
329+ context[" handle_traceback" ] = _exception_handler.attr (" _source_traceback" );
330+ }
331+
332+ list log_lines;
333+ log_lines.append (message);
334+ list context_keys (context.attr (" keys" ));
335+ context_keys.sort ();
336+ for (int i = 0 ; i < len (context_keys); i++)
337+ {
338+ std::string key = extract<std::string>(context_keys[i]);
339+ if (key == " message" || key == " exception" )
340+ continue ;
341+ str value (context[key]);
342+ if (key == " source_traceback" )
343+ {
344+ str tb = str (" " ).join (_pymod_traceback.attr (" format_list" )(value));
345+ value = str (" Object created at (most recent call last):\n " );
346+ value += tb.rstrip ();
347+ }
348+ else if (key == " handle_traceback" )
349+ {
350+ str tb = str (" " ).join (_pymod_traceback.attr (" format_list" )(value));
351+ value = str (" Handle created at (most recent call last):\n " );
352+ value += tb.rstrip ();
353+ }
354+ else
355+ {
356+ value = str (value.attr (" __str__" )());
357+ }
358+ std::ostringstream stringStream;
359+ stringStream << key << " : " << value;
360+ log_lines.append (str (stringStream.str ()));
361+ }
362+ list args;
363+ dict kwargs;
364+ args.append (str (" \n " ).join (log_lines));
365+ kwargs[" exc_info" ] = exc_info;
366+ _pymod_logger.attr (" error" )(tuple (args), **kwargs);
367+ }
368+
369+ void event_loop::call_exception_handler (object context)
370+ {
371+ if (_exception_handler == object ())
372+ {
373+ try
374+ {
375+ default_exception_handler (context);
376+ }
377+ catch (const error_already_set& e)
378+ {
379+ if (PyErr_ExceptionMatches (PyExc_SystemExit)
380+ || PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
381+ {
382+ // raise
383+ }
384+ else
385+ {
386+ PyErr_Clear ();
387+ list args;
388+ dict kwargs;
389+ args.append (str (" Exception in default exception handler" ));
390+ kwargs[" exc_info" ] = true ;
391+ _pymod_logger.attr (" error" )(tuple (args), **kwargs);
392+ }
393+ }
394+ }
395+ else
396+ {
397+ try
398+ {
399+ _exception_handler (context);
400+ }
401+ catch (const error_already_set& e)
402+ {
403+ if (PyErr_ExceptionMatches (PyExc_SystemExit)
404+ || PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
405+ {
406+ // raise
407+ }
408+ else
409+ {
410+ PyObject *ptype, *pvalue, *ptraceback;
411+ PyErr_Fetch (&ptype, &pvalue, &ptraceback);
412+ PyErr_NormalizeException (&ptype, &pvalue, &ptraceback);
413+ object type (handle<>(ptype));
414+ object value (handle<>(pvalue));
415+ object traceback (handle<>(ptraceback));
416+ try
417+ {
418+ dict tmp_dict;
419+ tmp_dict[" message" ] = str (" Unhandled error in exception handler" );
420+ tmp_dict[" exception" ] = value;
421+ tmp_dict[" context" ] = context;
422+ default_exception_handler (tmp_dict);
423+ }
424+ catch (const error_already_set& e)
425+ {
426+ if (PyErr_ExceptionMatches (PyExc_SystemExit)
427+ || PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
428+ {
429+ // raise
430+ }
431+ else
432+ {
433+ boost::python::list args;
434+ boost::python::dict kwargs;
435+ args.append (str (" Exception in default exception handler" ));
436+ kwargs[" exc_info" ] = true ;
437+ _pymod_logger.attr (" error" )(tuple (args), **kwargs);
438+ }
439+ }
440+ }
441+ }
442+ }
443+ }
444+
445+
284446}}}
0 commit comments