@@ -8,16 +8,17 @@ mod _overlapped {
88 // straight-forward port of Modules/overlapped.c
99
1010 use crate :: vm:: {
11- Py , PyObjectRef , PyPayload , PyResult , VirtualMachine ,
11+ AsObject , Py , PyObjectRef , PyPayload , PyResult , VirtualMachine ,
1212 builtins:: { PyBaseExceptionRef , PyBytesRef , PyType } ,
1313 common:: lock:: PyMutex ,
1414 convert:: { ToPyException , ToPyObject } ,
15+ function:: OptionalArg ,
1516 protocol:: PyBuffer ,
1617 types:: Constructor ,
1718 } ;
1819 use windows_sys:: Win32 :: {
1920 Foundation :: { self , GetLastError , HANDLE } ,
20- Networking :: WinSock :: SOCKADDR_IN6 ,
21+ Networking :: WinSock :: { AF_INET , AF_INET6 , SOCKADDR_IN , SOCKADDR_IN6 } ,
2122 System :: IO :: OVERLAPPED ,
2223 } ;
2324
@@ -153,6 +154,51 @@ mod _overlapped {
153154 overlapped. Internal != ( Foundation :: STATUS_PENDING as usize )
154155 }
155156
157+ /// Parse a SOCKADDR_IN6 (which can also hold IPv4 addresses) to a Python address tuple
158+ fn unparse_address (
159+ addr : & SOCKADDR_IN6 ,
160+ _addr_len : libc:: c_int ,
161+ vm : & VirtualMachine ,
162+ ) -> PyObjectRef {
163+ use crate :: vm:: convert:: ToPyObject ;
164+
165+ unsafe {
166+ let family = addr. sin6_family ;
167+ if family == AF_INET {
168+ // IPv4 address stored in SOCKADDR_IN6 structure
169+ let addr_in = & * ( addr as * const SOCKADDR_IN6 as * const SOCKADDR_IN ) ;
170+ let ip_bytes = addr_in. sin_addr . S_un . S_un_b ;
171+ let ip_str = format ! (
172+ "{}.{}.{}.{}" ,
173+ ip_bytes. s_b1, ip_bytes. s_b2, ip_bytes. s_b3, ip_bytes. s_b4
174+ ) ;
175+ let port = u16:: from_be ( addr_in. sin_port ) ;
176+ ( ip_str, port) . to_pyobject ( vm)
177+ } else if family == AF_INET6 {
178+ // IPv6 address
179+ let ip_bytes = addr. sin6_addr . u . Byte ;
180+ let ip_str = format ! (
181+ "{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}" ,
182+ u16 :: from_be_bytes( [ ip_bytes[ 0 ] , ip_bytes[ 1 ] ] ) ,
183+ u16 :: from_be_bytes( [ ip_bytes[ 2 ] , ip_bytes[ 3 ] ] ) ,
184+ u16 :: from_be_bytes( [ ip_bytes[ 4 ] , ip_bytes[ 5 ] ] ) ,
185+ u16 :: from_be_bytes( [ ip_bytes[ 6 ] , ip_bytes[ 7 ] ] ) ,
186+ u16 :: from_be_bytes( [ ip_bytes[ 8 ] , ip_bytes[ 9 ] ] ) ,
187+ u16 :: from_be_bytes( [ ip_bytes[ 10 ] , ip_bytes[ 11 ] ] ) ,
188+ u16 :: from_be_bytes( [ ip_bytes[ 12 ] , ip_bytes[ 13 ] ] ) ,
189+ u16 :: from_be_bytes( [ ip_bytes[ 14 ] , ip_bytes[ 15 ] ] ) ,
190+ ) ;
191+ let port = u16:: from_be ( addr. sin6_port ) ;
192+ let flowinfo = addr. sin6_flowinfo ;
193+ let scope_id = addr. Anonymous . sin6_scope_id ;
194+ ( ip_str, port, flowinfo, scope_id) . to_pyobject ( vm)
195+ } else {
196+ // Unknown address family, return None
197+ vm. ctx . none ( )
198+ }
199+ }
200+ }
201+
156202 #[ pyclass( with( Constructor ) ) ]
157203 impl Overlapped {
158204 #[ pygetset]
@@ -259,6 +305,139 @@ mod _overlapped {
259305 }
260306 Ok ( ( ) )
261307 }
308+
309+ #[ pymethod]
310+ fn getresult ( zelf : & Py < Self > , wait : OptionalArg < bool > , vm : & VirtualMachine ) -> PyResult {
311+ use windows_sys:: Win32 :: Foundation :: {
312+ ERROR_BROKEN_PIPE , ERROR_IO_PENDING , ERROR_MORE_DATA , ERROR_SUCCESS ,
313+ } ;
314+ use windows_sys:: Win32 :: System :: IO :: GetOverlappedResult ;
315+
316+ let mut inner = zelf. inner . lock ( ) ;
317+ let wait = wait. unwrap_or ( false ) ;
318+
319+ // Check operation state
320+ if matches ! ( inner. data, OverlappedData :: None ) {
321+ return Err ( vm. new_value_error ( "operation not yet attempted" . to_owned ( ) ) ) ;
322+ }
323+ if matches ! ( inner. data, OverlappedData :: NotStarted ) {
324+ return Err ( vm. new_value_error ( "operation failed to start" . to_owned ( ) ) ) ;
325+ }
326+
327+ // Get the result
328+ let mut transferred: u32 = 0 ;
329+ let ret = unsafe {
330+ GetOverlappedResult (
331+ inner. handle ,
332+ & inner. overlapped ,
333+ & mut transferred,
334+ if wait { 1 } else { 0 } ,
335+ )
336+ } ;
337+
338+ let err = if ret != 0 {
339+ ERROR_SUCCESS
340+ } else {
341+ unsafe { GetLastError ( ) }
342+ } ;
343+ inner. error = err;
344+
345+ // Handle errors
346+ match err {
347+ ERROR_SUCCESS | ERROR_MORE_DATA => { }
348+ ERROR_BROKEN_PIPE => {
349+ // For read operations, broken pipe is acceptable
350+ match & inner. data {
351+ OverlappedData :: Read ( _) | OverlappedData :: ReadInto ( _) => { }
352+ OverlappedData :: ReadFrom ( rf)
353+ if rf. result . is ( & vm. ctx . none ( ) )
354+ || rf. allocated_buffer . is ( & vm. ctx . none ( ) ) =>
355+ {
356+ return Err ( from_windows_err ( err, vm) ) ;
357+ }
358+ OverlappedData :: ReadFrom ( _) => { }
359+ OverlappedData :: ReadFromInto ( rfi) if rfi. result . is ( & vm. ctx . none ( ) ) => {
360+ return Err ( from_windows_err ( err, vm) ) ;
361+ }
362+ OverlappedData :: ReadFromInto ( _) => { }
363+ _ => return Err ( from_windows_err ( err, vm) ) ,
364+ }
365+ }
366+ ERROR_IO_PENDING => {
367+ return Err ( from_windows_err ( err, vm) ) ;
368+ }
369+ _ => return Err ( from_windows_err ( err, vm) ) ,
370+ }
371+
372+ // Return result based on operation type
373+ match & inner. data {
374+ OverlappedData :: Read ( buf) => {
375+ // Resize buffer to actual bytes read
376+ let bytes = buf. as_bytes ( ) ;
377+ let result = if transferred as usize != bytes. len ( ) {
378+ vm. ctx . new_bytes ( bytes[ ..transferred as usize ] . to_vec ( ) )
379+ } else {
380+ buf. clone ( )
381+ } ;
382+ Ok ( result. into ( ) )
383+ }
384+ OverlappedData :: ReadInto ( _) => {
385+ // Return number of bytes read
386+ Ok ( vm. ctx . new_int ( transferred) . into ( ) )
387+ }
388+ OverlappedData :: Write ( _) => {
389+ // Return number of bytes written
390+ Ok ( vm. ctx . new_int ( transferred) . into ( ) )
391+ }
392+ OverlappedData :: Accept ( _) => {
393+ // Return None for accept
394+ Ok ( vm. ctx . none ( ) )
395+ }
396+ OverlappedData :: Connect => {
397+ // Return None for connect
398+ Ok ( vm. ctx . none ( ) )
399+ }
400+ OverlappedData :: Disconnect => {
401+ // Return None for disconnect
402+ Ok ( vm. ctx . none ( ) )
403+ }
404+ OverlappedData :: ConnectNamedPipe => {
405+ // Return None for connect named pipe
406+ Ok ( vm. ctx . none ( ) )
407+ }
408+ OverlappedData :: WaitNamedPipeAndConnect => {
409+ // Return None
410+ Ok ( vm. ctx . none ( ) )
411+ }
412+ OverlappedData :: ReadFrom ( rf) => {
413+ // Return (resized_buffer, (host, port)) tuple
414+ let buf = rf
415+ . allocated_buffer
416+ . downcast_ref :: < crate :: vm:: builtins:: PyBytes > ( )
417+ . unwrap ( ) ;
418+ let bytes = buf. as_bytes ( ) ;
419+ let resized_buf = if transferred as usize != bytes. len ( ) {
420+ vm. ctx . new_bytes ( bytes[ ..transferred as usize ] . to_vec ( ) )
421+ } else {
422+ buf. to_owned ( )
423+ } ;
424+ let addr_tuple = unparse_address ( & rf. address , rf. address_length , vm) ;
425+ Ok ( vm
426+ . ctx
427+ . new_tuple ( vec ! [ resized_buf. into( ) , addr_tuple] )
428+ . into ( ) )
429+ }
430+ OverlappedData :: ReadFromInto ( rfi) => {
431+ // Return (transferred, (host, port)) tuple
432+ let addr_tuple = unparse_address ( & rfi. address , rfi. address_length , vm) ;
433+ Ok ( vm
434+ . ctx
435+ . new_tuple ( vec ! [ vm. ctx. new_int( transferred) . into( ) , addr_tuple] )
436+ . into ( ) )
437+ }
438+ _ => Ok ( vm. ctx . none ( ) ) ,
439+ }
440+ }
262441 }
263442
264443 impl Constructor for Overlapped {
0 commit comments