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> 
@@ -52,7 +53,9 @@ void _sock_connect_cb(object pymod_socket, std::promise<void>& prom, std::future
5253        if  (err != object (0 )) {
5354            //  TODO: print the address
5455            PyErr_SetString (PyExc_OSError, " Connect call failed {address}"  );
56+             throw_error_already_set ();
5557        }
58+         prom.set_value ();
5659    }
5760    catch  (const  error_already_set& e)
5861    {
@@ -67,15 +70,10 @@ void _sock_connect_cb(object pymod_socket, std::promise<void>& prom, std::future
6770        {
6871            //  raise
6972        }
70-         else  if  (PyErr_ExceptionMatches (PyExc_BaseException))
71-         {
72-             PyErr_Clear ();
73-             prom.set_exception (std::current_exception ());
74-         }
7573        else 
7674        {
7775            PyErr_Clear ();
78-             prom.set_value ( );
76+             prom.set_exception ( std::current_exception () );
7977        }
8078    }
8179}
@@ -91,6 +89,7 @@ void _sock_accept(event_loop& loop, std::promise<object>& prom, std::future<obje
9189        conn = ret[0 ];
9290        address = ret[1 ];
9391        conn.attr (" setblocking"  )(object (false ));
92+         prom.set_value (make_tuple (conn, address));
9493    }
9594    catch  (const  error_already_set& e)
9695    {
@@ -107,19 +106,27 @@ void _sock_accept(event_loop& loop, std::promise<object>& prom, std::future<obje
107106        {
108107            //  raise
109108        }
110-         else  if  (PyErr_ExceptionMatches (PyExc_BaseException))
111-         {
112-             PyErr_Clear ();
113-             prom.set_exception (std::current_exception ());
114-         }
115109        else 
116110        {
117111            PyErr_Clear ();
118-             prom.set_value ( make_tuple (conn, address ));
112+             prom.set_exception ( std::current_exception ( ));
119113        }
120114    }  
121115}
122116
117+ void  _getaddrinfo_handler (object pymod_socket, std::promise<object>& prom, 
118+     object host, int  port, int  family, int  type, int  proto, int  flags)
119+ {
120+     object res = pymod_socket.attr (" getaddrinfo"  )(host, port, family, type, proto, flags);
121+     prom.set_value (res);
122+ }
123+ 
124+ void  _getnameinfo_handler (object pymod_socket, std::promise<object>& prom, object sockaddr, int  flags)
125+ {
126+     object res = pymod_socket.attr (" getnameinfo"  )(sockaddr, flags);
127+     prom.set_value (res);
128+ }
129+ 
123130}
124131
125132void  event_loop::_add_reader_or_writer (int  fd, object f, int  key)
@@ -237,6 +244,7 @@ void event_loop::sock_connect(object sock, object address)
237244    try  
238245    {
239246        sock.attr (" connect"  )(address);
247+         prom.set_value ();
240248    }
241249    catch  (const  error_already_set& e)
242250    {
@@ -253,15 +261,10 @@ void event_loop::sock_connect(object sock, object address)
253261        {
254262            //  raise
255263        }
256-         else  if  (PyErr_ExceptionMatches (PyExc_BaseException))
257-         {
258-             PyErr_Clear ();
259-             prom.set_exception (std::current_exception ());
260-         }
261264        else 
262265        {
263266            PyErr_Clear ();
264-             prom.set_value ( );
267+             prom.set_exception ( std::current_exception () );
265268        }
266269    }
267270    fut.wait ();
@@ -279,6 +282,176 @@ object event_loop::sock_accept(object sock)
279282void  event_loop::sock_sendfile (object sock, object file, int  offset, int  count, bool  fallback)
280283{
281284    PyErr_SetString (PyExc_NotImplementedError, " Not implemented!"  );
285+     throw_error_already_set ();
286+ }
287+ 
288+ //  TODO: implement this
289+ void  event_loop::start_tls (object transport, object protocol, object sslcontext, 
290+     bool  server_side, object server_hostname, object ssl_handshake_timeout)
291+ {
292+     PyErr_SetString (PyExc_NotImplementedError, " Not implemented!"  );
293+     throw_error_already_set ();
294+ }
295+ 
296+ object event_loop::getaddrinfo (object host, int  port, int  family, int  type, int  proto, int  flags)
297+ {
298+     std::promise<object> prom;
299+     std::future<object> fut = prom.get_future ();
300+     call_soon (make_function (
301+         bind (_getaddrinfo_handler, _pymod_socket, boost::ref (prom), host, port, family, type, proto, flags),
302+         default_call_policies (), 
303+         boost::mpl::vector<void , object>()));
304+     return  fut.get ();
305+ }
306+ 
307+ object event_loop::getnameinfo (object sockaddr, int  flags)
308+ {
309+     std::promise<object> prom;
310+     std::future<object> fut = prom.get_future ();
311+     call_soon (make_function (
312+         bind (_getnameinfo_handler, _pymod_socket, boost::ref (prom), sockaddr, flags),
313+         default_call_policies (),
314+         boost::mpl::vector<void , object>()));
315+     return  fut.get ();
316+ }
317+ 
318+ void  event_loop::default_exception_handler (object context)
319+ {
320+     object message = context.attr (" get"  )(str (" message"  ));
321+     if  (message == object ())
322+     {
323+         message = str (" Unhandled exception in event loop"  );
324+     }
325+ 
326+     object exception = context.attr (" get"  )(str (" exception"  ));
327+     object exc_info;
328+     if  (exception != object ())
329+     {
330+         exc_info = make_tuple (exception.attr (" __class__"  ), exception, exception.attr (" __traceback__"  ));
331+     }
332+     else 
333+     {
334+         exc_info = object (false );
335+     }
336+     if  (!PyObject_IsTrue (context.attr (" __contains__"  )(str (" source_traceback"  )).ptr ()) &&
337+         _exception_handler != object () &&
338+         _exception_handler.attr (" _source_traceback"  ) != object ())
339+     {
340+         context[" handle_traceback"  ] = _exception_handler.attr (" _source_traceback"  );
341+     }
342+ 
343+     list log_lines;
344+     log_lines.append (message);
345+     list context_keys (context.attr (" keys"  ));
346+     context_keys.sort ();
347+     for  (int  i = 0 ; i < len (context_keys); i++)
348+     {
349+         std::string key = extract<std::string>(context_keys[i]);
350+         if  (key == " message"   || key == " exception"  )
351+             continue ;
352+         str value (context[key]);
353+         if  (key == " source_traceback"  )
354+         {
355+             str tb = str (" "  ).join (_pymod_traceback.attr (" format_list"  )(value));
356+             value = str (" Object created at (most recent call last):\n "  );
357+             value += tb.rstrip ();
358+         }
359+         else  if  (key == " handle_traceback"  )
360+         {
361+             str tb = str (" "  ).join (_pymod_traceback.attr (" format_list"  )(value));
362+             value = str (" Handle created at (most recent call last):\n "  );
363+             value += tb.rstrip ();
364+         }
365+         else 
366+         {
367+             value = str (value.attr (" __str__"  )());
368+         }
369+         std::ostringstream stringStream;
370+         stringStream << key << " : "   << value;
371+         log_lines.append (str (stringStream.str ()));
372+     }
373+     list args;
374+     dict kwargs;
375+     args.append (str (" \n "  ).join (log_lines));
376+     kwargs[" exc_info"  ] = exc_info;
377+     _pymod_logger.attr (" error"  )(tuple (args), **kwargs);
378+ }
379+ 
380+ void  event_loop::call_exception_handler (object context)
381+ {
382+     if  (_exception_handler == object ())
383+     {
384+         try 
385+         {
386+             default_exception_handler (context);
387+         }
388+         catch  (const  error_already_set& e)
389+         {
390+             if  (PyErr_ExceptionMatches (PyExc_SystemExit)
391+                 || PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
392+             {
393+                 //  raise
394+             }
395+             else 
396+             {
397+                 PyErr_Clear ();
398+                 list args;
399+                 dict kwargs;
400+                 args.append (str (" Exception in default exception handler"  ));
401+                 kwargs[" exc_info"  ] = true ;
402+                 _pymod_logger.attr (" error"  )(tuple (args), **kwargs);
403+             }
404+         }
405+     }
406+     else 
407+     {
408+         try 
409+         {
410+             _exception_handler (context);
411+         }
412+         catch  (const  error_already_set& e)
413+         {
414+             if  (PyErr_ExceptionMatches (PyExc_SystemExit)
415+                 || PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
416+             {
417+                 //  raise
418+             }
419+             else 
420+             {
421+                 PyObject *ptype, *pvalue, *ptraceback;
422+                 PyErr_Fetch (&ptype, &pvalue, &ptraceback);
423+                 PyErr_NormalizeException (&ptype, &pvalue, &ptraceback);
424+                 object type (handle<>(ptype));
425+                 object value (handle<>(pvalue));
426+                 object traceback (handle<>(ptraceback));
427+                 try 
428+                 {
429+                     dict tmp_dict;
430+                     tmp_dict[" message"  ] = str (" Unhandled error in exception handler"  );
431+                     tmp_dict[" exception"  ] = value;
432+                     tmp_dict[" context"  ] = context;
433+                     default_exception_handler (tmp_dict);
434+                 }
435+                 catch  (const  error_already_set& e)
436+                 {
437+                     if  (PyErr_ExceptionMatches (PyExc_SystemExit)
438+                         || PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
439+                     {
440+                         //  raise
441+                     }
442+                     else 
443+                     {
444+                         boost::python::list args;
445+                         boost::python::dict kwargs;
446+                         args.append (str (" Exception in default exception handler"  ));
447+                         kwargs[" exc_info"  ] = true ;
448+                         _pymod_logger.attr (" error"  )(tuple (args), **kwargs);
449+                     }
450+                 }
451+             }
452+         }
453+     }
282454}
283455
456+ 
284457}}}
0 commit comments