@@ -20,6 +20,7 @@ cdef class _UDPSendContext:
20
20
self .closed = 1
21
21
PyBuffer_Release(& self .py_buf) # void
22
22
self .req.data = NULL
23
+ self .uv_buf.base = NULL
23
24
Py_DECREF(self )
24
25
self .udp = None
25
26
@@ -34,7 +35,8 @@ cdef class _UDPSendContext:
34
35
Py_INCREF(ctx)
35
36
36
37
PyObject_GetBuffer(data, & ctx.py_buf, PyBUF_SIMPLE)
37
- ctx.uv_buf = uv.uv_buf_init(< char * > ctx.py_buf.buf, ctx.py_buf.len)
38
+ ctx.uv_buf.base = < char * > ctx.py_buf.buf
39
+ ctx.uv_buf.len = ctx.py_buf.len
38
40
ctx.udp = udp
39
41
40
42
ctx.closed = 0
@@ -193,37 +195,63 @@ cdef class UDPTransport(UVBaseTransport):
193
195
_UDPSendContext ctx
194
196
system.sockaddr_storage saddr_st
195
197
system.sockaddr * saddr
198
+ Py_buffer try_pybuf
199
+ uv.uv_buf_t try_uvbuf
200
+
201
+ self ._ensure_alive()
196
202
197
203
if self ._family not in (uv.AF_INET, uv.AF_INET6, uv.AF_UNIX):
198
204
raise RuntimeError (' UDPTransport.family is undefined; cannot send' )
199
205
200
- if addr is not None and self ._family != uv.AF_UNIX:
201
- validate_address(addr, self ._family, uv.SOCK_DGRAM, 0 )
202
-
203
- ctx = _UDPSendContext.new(self , data)
204
- try :
205
- if addr is None :
206
- saddr = NULL
207
- else :
206
+ if addr is None :
207
+ saddr = NULL
208
+ else :
209
+ try :
208
210
__convert_pyaddr_to_sockaddr(self ._family, addr,
209
211
< system.sockaddr* > & saddr_st)
210
- saddr = < system.sockaddr* > (& saddr_st)
211
- except Exception :
212
- ctx.close()
213
- raise
214
-
215
- err = uv.uv_udp_send(& ctx.req,
216
- < uv.uv_udp_t* > self ._handle,
217
- & ctx.uv_buf,
218
- 1 ,
219
- saddr,
220
- __uv_udp_on_send)
221
-
222
- if err < 0 :
223
- ctx.close()
212
+ except (ValueError , TypeError ):
213
+ raise
214
+ except Exception :
215
+ raise ValueError (
216
+ f' {addr!r}: socket family mismatch or '
217
+ f' a DNS lookup is required' )
218
+ saddr = < system.sockaddr* > (& saddr_st)
219
+
220
+ if self ._get_write_buffer_size() == 0 :
221
+ PyObject_GetBuffer(data, & try_pybuf, PyBUF_SIMPLE)
222
+ try_uvbuf.base = < char * > try_pybuf.buf
223
+ try_uvbuf.len = try_pybuf.len
224
+ err = uv.uv_udp_try_send(< uv.uv_udp_t* > self ._handle,
225
+ & try_uvbuf,
226
+ 1 ,
227
+ saddr)
228
+ PyBuffer_Release(& try_pybuf)
229
+ else :
230
+ err = uv.UV_EAGAIN
231
+
232
+ if err == uv.UV_EAGAIN:
233
+ ctx = _UDPSendContext.new(self , data)
234
+ err = uv.uv_udp_send(& ctx.req,
235
+ < uv.uv_udp_t* > self ._handle,
236
+ & ctx.uv_buf,
237
+ 1 ,
238
+ saddr,
239
+ __uv_udp_on_send)
240
+
241
+ if err < 0 :
242
+ ctx.close()
243
+
244
+ exc = convert_error(err)
245
+ self ._fatal_error(exc, True )
246
+ else :
247
+ self ._maybe_pause_protocol()
224
248
225
- exc = convert_error(err)
226
- self ._fatal_error(exc, True )
249
+ else :
250
+ if err < 0 :
251
+ exc = convert_error(err)
252
+ self ._fatal_error(exc, True )
253
+ else :
254
+ self ._on_sent(None )
227
255
228
256
cdef _on_receive(self , bytes data, object exc, object addr):
229
257
if exc is None :
@@ -248,15 +276,17 @@ cdef class UDPTransport(UVBaseTransport):
248
276
249
277
def sendto (self , data , addr = None ):
250
278
if not data:
279
+ # Replicating asyncio logic here.
251
280
return
252
281
253
282
if self ._conn_lost:
254
- # TODO add warning
283
+ # Replicating asyncio logic here.
284
+ if self ._conn_lost >= LOG_THRESHOLD_FOR_CONNLOST_WRITES:
285
+ aio_logger.warning(' socket.send() raised exception.' )
255
286
self ._conn_lost += 1
256
287
return
257
288
258
289
self ._send(data, addr)
259
- self ._maybe_pause_protocol()
260
290
261
291
262
292
cdef void __uv_udp_on_receive(uv.uv_udp_t* handle,
@@ -357,17 +387,3 @@ cdef void __uv_udp_on_send(uv.uv_udp_send_t* req, int status) with gil:
357
387
udp._on_sent(exc)
358
388
except BaseException as exc:
359
389
udp._error(exc, False )
360
-
361
-
362
- @ ft_lru_cache ()
363
- def validate_address (object addr , int sock_family , int sock_type ,
364
- int sock_proto ):
365
- addrinfo = __static_getaddrinfo_pyaddr(
366
- addr[0 ], addr[1 ],
367
- uv.AF_UNSPEC, sock_type, sock_proto, 0 )
368
- if addrinfo is None :
369
- raise ValueError (
370
- ' UDP.sendto(): address {!r} requires a DNS lookup' .format(addr))
371
- if addrinfo[0 ] != sock_family:
372
- raise ValueError (
373
- ' UDP.sendto(): {!r} socket family mismatch' .format(addr))
0 commit comments