6
6
// TODO:
7
7
// 1. posix::stream_descriptor need windows version
8
8
// 2. call_* need return async.Handle
9
+ // 3. _ensure_fd_no_transport
10
+ // 4. _ensure_resolve
9
11
10
12
#include < boost/asio.hpp>
11
13
#include < boost/bind.hpp>
12
14
#include < boost/python.hpp>
13
15
#include < boost/python/eventloop.hpp>
16
+ #include < boost/mpl/vector.hpp>
17
+ #include < Python.h>
14
18
15
19
16
20
namespace boost { namespace python { namespace asio {
21
+ namespace
22
+ {
23
+
24
+ bool _hasattr (object o, const char * name)
25
+ {
26
+ return PyObject_HasAttrString (o.ptr (), name);
27
+ }
28
+
29
+ void _sock_recv_handler (
30
+ std::promise<std::vector<char >>& prom_data,
31
+ std::promise<size_t >& prom_nbytes_read,
32
+ size_t nbytes,
33
+ int fd)
34
+ {
35
+ std::vector<char > buffer (nbytes);
36
+ prom_nbytes_read.set_value (read (fd, buffer.data (), nbytes));
37
+ prom_data.set_value (std::move (buffer));
38
+ }
39
+
40
+ void _sock_send_handler (std::promise<size_t >& prom, int fd, const char *py_str, ssize_t len)
41
+ {
42
+ size_t nwrite = write (fd, py_str, len);
43
+ prom.set_value (nwrite);
44
+ }
45
+
46
+ }
17
47
18
48
void event_loop::_add_reader_or_writer (int fd, object f, int key)
19
49
{
@@ -50,6 +80,85 @@ void event_loop::_remove_reader_or_writer(int key)
50
80
}
51
81
}
52
82
83
+ void event_loop::_sock_connect_cb (
84
+ event_loop& loop, std::promise<void >& prom, std::future<void >& fut, object sock, object addr)
85
+ {
86
+ try
87
+ {
88
+ object err = sock.attr (" getsockopt" )(
89
+ loop._pymod_socket .attr (" SOL_SOCKET" ), loop._pymod_socket .attr (" SO_ERROR" ));
90
+ if (err != object (0 )) {
91
+ // TODO: print the address
92
+ PyErr_SetString (PyExc_OSError, " Connect call failed {address}" );
93
+ }
94
+ }
95
+ catch (const error_already_set& e)
96
+ {
97
+ if (PyErr_ExceptionMatches (PyExc_BlockingIOError)
98
+ || PyErr_ExceptionMatches (PyExc_InterruptedError))
99
+ {
100
+ PyErr_Clear ();
101
+ // pass
102
+ }
103
+ else if (PyErr_ExceptionMatches (PyExc_SystemExit)
104
+ || PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
105
+ {
106
+ // raise
107
+ }
108
+ else if (PyErr_ExceptionMatches (PyExc_BaseException))
109
+ {
110
+ PyErr_Clear ();
111
+ prom.set_exception (std::current_exception ());
112
+ }
113
+ else
114
+ {
115
+ PyErr_Clear ();
116
+ prom.set_value ();
117
+ }
118
+ }
119
+ }
120
+
121
+ void event_loop::_sock_accept (
122
+ event_loop& loop, std::promise<object>& prom, std::future<object>& fut, object sock)
123
+ {
124
+ int fd = extract<int >(sock.attr (" fileno" )());
125
+ object conn;
126
+ object address;
127
+ try
128
+ {
129
+ object ret = sock.attr (" accept" )();
130
+ conn = ret[0 ];
131
+ address = ret[1 ];
132
+ conn.attr (" setblocking" )(object (false ));
133
+ }
134
+ catch (const error_already_set& e)
135
+ {
136
+ if (PyErr_ExceptionMatches (PyExc_BlockingIOError)
137
+ || PyErr_ExceptionMatches (PyExc_InterruptedError))
138
+ {
139
+ PyErr_Clear ();
140
+ loop.add_reader (fd, make_function (bind (
141
+ _sock_accept, boost::ref (loop), boost::ref (prom), boost::ref (fut), sock),
142
+ default_call_policies (), boost::mpl::vector<void , object>()));
143
+ }
144
+ else if (PyErr_ExceptionMatches (PyExc_SystemExit)
145
+ || PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
146
+ {
147
+ // raise
148
+ }
149
+ else if (PyErr_ExceptionMatches (PyExc_BaseException))
150
+ {
151
+ PyErr_Clear ();
152
+ prom.set_exception (std::current_exception ());
153
+ }
154
+ else
155
+ {
156
+ PyErr_Clear ();
157
+ prom.set_value (make_tuple (conn, address));
158
+ }
159
+ }
160
+ }
161
+
53
162
void event_loop::call_later (double delay, object f)
54
163
{
55
164
// add timer
@@ -76,34 +185,102 @@ void event_loop::call_at(double when, object f)
76
185
return call_soon (f);
77
186
}
78
187
79
- void event_loop::sock_recv (object sock, int bytes )
188
+ object event_loop::sock_recv (object sock, size_t nbytes )
80
189
{
81
-
190
+ int fd = extract<int >(sock.attr (" fileno" )());
191
+ std::promise<std::vector<char >> prom_data;
192
+ std::future<std::vector<char >> fut_data = prom_data.get_future ();
193
+ std::promise<size_t > prom_nbytes_read;
194
+ std::future<size_t > fut_nbytes_read = prom_nbytes_read.get_future ();
195
+ add_reader (fd, make_function (bind (_sock_recv_handler,
196
+ boost::ref (prom_data), boost::ref (prom_nbytes_read), nbytes, fd),
197
+ default_call_policies (), boost::mpl::vector<void , object>()));
198
+ return object (handle<>(PyBytes_FromStringAndSize (fut_data.get ().data (), nbytes)));
82
199
}
83
200
84
- void event_loop::sock_recv_into (object sock, object buffer)
201
+ size_t event_loop::sock_recv_into (object sock, object buffer)
85
202
{
86
-
203
+ int fd = extract<int >(sock.attr (" fileno" )());
204
+ ssize_t nbytes = len (buffer);
205
+ std::promise<std::vector<char >> prom_data;
206
+ std::future<std::vector<char >> fut_data = prom_data.get_future ();
207
+ std::promise<size_t > prom_nbytes_read;
208
+ std::future<size_t > fut_nbytes_read = prom_nbytes_read.get_future ();
209
+ add_reader (fd, make_function (bind (_sock_recv_handler,
210
+ boost::ref (prom_data), boost::ref (prom_nbytes_read), nbytes, fd),
211
+ default_call_policies (), boost::mpl::vector<void , object>()));
212
+ buffer = object (handle<>(PyBytes_FromStringAndSize (fut_data.get ().data (), nbytes)));
213
+ return fut_nbytes_read.get ();
87
214
}
88
215
89
- void event_loop::sock_sendall (object sock, object data)
216
+ object event_loop::sock_sendall (object sock, object data)
90
217
{
91
-
218
+ int fd = extract<int >(sock.attr (" fileno" )());
219
+ char const * py_str = extract<char const *>(data.attr (" decode" )());
220
+ ssize_t py_str_len = len (data);
221
+ std::promise<size_t > prom;
222
+ std::future<size_t > fut = prom.get_future ();
223
+ add_writer (fd, make_function (bind (_sock_send_handler, std::ref (prom), fd, py_str, py_str_len),
224
+ default_call_policies (), boost::mpl::vector<void , object>()));
225
+ fut.wait ();
226
+ return object ();
92
227
}
93
228
94
229
void event_loop::sock_connect (object sock, object address)
95
230
{
96
-
231
+
232
+ if (!_hasattr (_pymod_socket, " AF_UNIX" ) || sock.attr (" family" ) != _pymod_socket.attr (" AF_UNIX" ))
233
+ {
234
+ // TODO: _ensure_resolve
235
+ }
236
+ std::promise<void > prom;
237
+ std::future<void > fut = prom.get_future ();
238
+ int fd = extract<int >(sock.attr (" fileno" )());
239
+ try
240
+ {
241
+ sock.attr (" connect" )(address);
242
+ }
243
+ catch (const error_already_set& e)
244
+ {
245
+ if (PyErr_ExceptionMatches (PyExc_BlockingIOError)
246
+ || PyErr_ExceptionMatches (PyExc_InterruptedError))
247
+ {
248
+ PyErr_Clear ();
249
+ add_writer (fd, make_function (bind (
250
+ _sock_connect_cb, boost::ref (*this ), boost::ref (prom), boost::ref (fut), sock, address),
251
+ default_call_policies (), boost::mpl::vector<void , object>()));
252
+ }
253
+ else if (PyErr_ExceptionMatches (PyExc_SystemExit)
254
+ || PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
255
+ {
256
+ // raise
257
+ }
258
+ else if (PyErr_ExceptionMatches (PyExc_BaseException))
259
+ {
260
+ PyErr_Clear ();
261
+ prom.set_exception (std::current_exception ());
262
+ }
263
+ else
264
+ {
265
+ PyErr_Clear ();
266
+ prom.set_value ();
267
+ }
268
+ }
269
+ fut.wait ();
97
270
}
98
271
99
- void event_loop::sock_accept (object sock)
272
+ object event_loop::sock_accept (object sock)
100
273
{
101
-
274
+ std::promise<object> prom;
275
+ std::future<object> fut = prom.get_future ();
276
+ _sock_accept (*this , prom, fut, sock);
277
+ return fut.get ();
102
278
}
103
279
280
+ // TODO: implement this
104
281
void event_loop::sock_sendfile (object sock, object file, int offset, int count, bool fallback)
105
282
{
106
-
283
+ PyErr_SetString (PyExc_NotImplementedError, " Not implemented! " );
107
284
}
108
285
109
286
}}}
0 commit comments