wincwifi/client/
tcp_stack.rs

1use embedded_nal::TcpClientStack;
2use embedded_nal::TcpFullStack;
3
4use super::ClientSocketOp;
5use super::Handle;
6use super::StackError;
7use super::WincClient;
8
9use super::Xfer;
10use crate::manager::SocketError;
11use crate::stack::socket_callbacks::SendRequest;
12use crate::stack::socket_callbacks::{AsyncOp, AsyncState};
13use crate::{debug, info};
14use embedded_nal::nb;
15
16use crate::stack::sock_holder::SocketStore;
17
18impl<X: Xfer> WincClient<'_, X> {
19    /// Todo: actually implement this
20    pub fn set_socket_option(
21        &mut self,
22        socket: &Handle,
23        option: u8,
24        value: u32,
25    ) -> Result<(), StackError> {
26        let (sock, _op) = self.callbacks.tcp_sockets.get(*socket).unwrap();
27        self.manager
28            .send_setsockopt(*sock, option, value)
29            .map_err(StackError::WincWifiFail)?;
30        Ok(())
31    }
32}
33
34impl<X: Xfer> embedded_nal::TcpClientStack for WincClient<'_, X> {
35    type TcpSocket = Handle;
36    type Error = StackError;
37    fn socket(
38        &mut self,
39    ) -> Result<<Self as TcpClientStack>::TcpSocket, <Self as TcpClientStack>::Error> {
40        self.dispatch_events()?;
41        let s = self.get_next_session_id();
42        let handle = self
43            .callbacks
44            .tcp_sockets
45            .add(s)
46            .ok_or(StackError::OutOfSockets)?;
47        Ok(handle)
48    }
49    fn connect(
50        &mut self,
51        socket: &mut <Self as TcpClientStack>::TcpSocket,
52        remote: core::net::SocketAddr,
53    ) -> Result<(), nb::Error<<Self as TcpClientStack>::Error>> {
54        let res = match remote {
55            core::net::SocketAddr::V4(addr) => Self::async_op(
56                true,
57                socket,
58                &mut self.callbacks,
59                &mut self.manager,
60                self.poll_loop_delay_us,
61                |op| matches!(op, AsyncOp::Connect(..)),
62                |sock, manager| -> Result<ClientSocketOp, StackError> {
63                    debug!("<> Sending send_socket_connect to {:?}", sock);
64                    manager
65                        .send_socket_connect(*sock, addr)
66                        .map_err(StackError::ConnectSendFailed)?;
67                    Ok(ClientSocketOp::AsyncOp(
68                        AsyncOp::Connect(None),
69                        AsyncState::Pending(Some(Self::CONNECT_TIMEOUT)),
70                    ))
71                },
72                |_, _, _, asyncop| {
73                    if let AsyncOp::Connect(Some(connect_result)) = asyncop {
74                        if connect_result.error == SocketError::NoError {
75                            Ok(())
76                        } else {
77                            Err(StackError::OpFailed(connect_result.error))
78                        }
79                    } else {
80                        Err(StackError::Unexpected)
81                    }
82                },
83            ),
84            core::net::SocketAddr::V6(_) => unimplemented!("IPv6 not supported"),
85        };
86        self.test_hook();
87        res
88    }
89    fn send(
90        &mut self,
91        socket: &mut <Self as TcpClientStack>::TcpSocket,
92        data: &[u8],
93    ) -> Result<usize, nb::Error<<Self as TcpClientStack>::Error>> {
94        let res = Self::async_op(
95            true,
96            socket,
97            &mut self.callbacks,
98            &mut self.manager,
99            self.poll_loop_delay_us,
100            |op| matches!(op, AsyncOp::Send(..)),
101            |sock, manager| -> Result<ClientSocketOp, StackError> {
102                let to_send = data.len().min(Self::MAX_SEND_LENGTH);
103                let req = SendRequest {
104                    offset: 0,
105                    grand_total_sent: 0,
106                    total_sent: 0,
107                    remaining: to_send as i16,
108                };
109                debug!(
110                    "Sending INITIAL send_send to {:?} len:{}/{} req:{:?}",
111                    sock,
112                    to_send,
113                    data.len(),
114                    req
115                );
116                manager
117                    .send_send(*sock, &data[..to_send])
118                    .map_err(StackError::SendSendFailed)?;
119                Ok(ClientSocketOp::AsyncOp(
120                    AsyncOp::Send(req, None),
121                    AsyncState::Pending(None),
122                ))
123            },
124            |sock, manager, _, asyncop| {
125                if let AsyncOp::Send(req, Some(_len)) = asyncop {
126                    let total_sent = req.total_sent;
127                    let grand_total_sent = req.grand_total_sent + total_sent;
128                    let offset = req.offset + total_sent as usize;
129                    if offset >= data.len() {
130                        Ok(grand_total_sent as usize)
131                    } else {
132                        let to_send = data[offset..].len().min(Self::MAX_SEND_LENGTH);
133                        let new_req = SendRequest {
134                            offset,
135                            grand_total_sent,
136                            total_sent: 0,
137                            remaining: to_send as i16,
138                        };
139                        *asyncop = AsyncOp::Send(new_req, None);
140                        manager
141                            .send_send(*sock, &data[offset..offset + to_send])
142                            .map_err(StackError::SendSendFailed)?;
143                        Err(StackError::ContinueOperation)
144                    }
145                } else {
146                    Err(StackError::Unexpected)
147                }
148            },
149        );
150        self.test_hook();
151        res
152    }
153
154    // Nb:: Blocking call, returns nb::Result when no data
155    // Handles partial reads properly - returns available data from previous packet first,
156    // then requests new packets when needed
157    fn receive(
158        &mut self,
159        socket: &mut <Self as TcpClientStack>::TcpSocket,
160        data: &mut [u8],
161    ) -> Result<usize, nb::Error<<Self as TcpClientStack>::Error>> {
162        // Check if we have a previous operation with remaining data
163        let store = &mut self.callbacks.tcp_sockets;
164        if let Some((_sock, op)) = store.get(*socket) {
165            if let ClientSocketOp::AsyncOp(
166                AsyncOp::Recv(Some(ref mut recv_result)),
167                AsyncState::Done,
168            ) = op
169            {
170                if recv_result.return_offset < recv_result.recv_len {
171                    let remaining_data = recv_result.recv_len - recv_result.return_offset;
172                    let copy_len = remaining_data.min(data.len());
173
174                    // Copy remaining data from recv_buffer
175                    data[..copy_len].copy_from_slice(
176                        &self.callbacks.recv_buffer
177                            [recv_result.return_offset..recv_result.return_offset + copy_len],
178                    );
179
180                    recv_result.return_offset += copy_len;
181
182                    // Clear operation if all data consumed
183                    if recv_result.return_offset >= recv_result.recv_len {
184                        debug!(
185                            "All {} bytes returned, ready for next packet",
186                            recv_result.recv_len
187                        );
188                        *op = ClientSocketOp::None;
189                    } else {
190                        debug!(
191                            "Partial read: returned {} of {} bytes (offset now {})",
192                            copy_len, recv_result.recv_len, recv_result.return_offset
193                        );
194                    }
195
196                    self.test_hook();
197                    return Ok(copy_len);
198                }
199            }
200        }
201
202        // No remaining data, proceed with normal receive operation
203        let res = Self::async_op(
204            true,
205            socket,
206            &mut self.callbacks,
207            &mut self.manager,
208            self.poll_loop_delay_us,
209            |op| matches!(op, AsyncOp::Recv(..)),
210            |sock, manager| -> Result<ClientSocketOp, StackError> {
211                debug!("<> Sending socket send_recv to {:?}", sock);
212                manager
213                    .send_recv(*sock, Self::RECV_TIMEOUT)
214                    .map_err(StackError::ReceiveFailed)?;
215                Ok(ClientSocketOp::AsyncOp(
216                    AsyncOp::Recv(None),
217                    AsyncState::Pending(None),
218                ))
219            },
220            |sock, manager, recv_buffer, asyncop| {
221                if let AsyncOp::Recv(Some(ref mut recv_result)) = asyncop {
222                    match recv_result.error {
223                        SocketError::NoError => {
224                            let recv_len = recv_result.recv_len;
225
226                            if recv_len == 0 {
227                                // No data available
228                                Ok(0)
229                            } else {
230                                // This is a new packet, return_offset should be 0
231                                let copy_len = recv_len.min(data.len());
232
233                                // Copy from recv_buffer
234                                let dest_slice = &mut data[..copy_len];
235                                dest_slice.copy_from_slice(&recv_buffer[..copy_len]);
236
237                                // Update return_offset for potential future calls
238                                recv_result.return_offset = copy_len;
239
240                                if copy_len < recv_len {
241                                    debug!(
242                                        "Partial read: returned {} of {} bytes, {} remaining",
243                                        copy_len,
244                                        recv_len,
245                                        recv_len - copy_len
246                                    );
247                                } else {
248                                    debug!("Complete read: returned all {} bytes", recv_len);
249                                }
250
251                                Ok(copy_len)
252                            }
253                        }
254                        SocketError::Timeout => {
255                            debug!("Timeout on receive, re-sending receive command");
256                            // Re-send the receive command with the same timeout
257                            manager
258                                .send_recv(*sock, Self::RECV_TIMEOUT)
259                                .map_err(StackError::ReceiveFailed)?;
260                            Err(StackError::ContinueOperation)
261                        }
262                        _ => {
263                            debug!("Error in receive: {:?}", recv_result.error);
264                            Err(StackError::OpFailed(recv_result.error))
265                        }
266                    }
267                } else {
268                    Err(StackError::Unexpected)
269                }
270            },
271        );
272        self.test_hook();
273        res
274    }
275    fn close(&mut self, socket: <Self as TcpClientStack>::TcpSocket) -> Result<(), Self::Error> {
276        debug!("Closing socket {:?}", socket);
277        self.dispatch_events()?;
278        let (sock, _op) = self.callbacks.tcp_sockets.get(socket).unwrap();
279        let socket_id = sock.v as usize;
280        self.callbacks.listening_sockets[socket_id] = false;
281        self.callbacks.accept_backlog[socket_id] = None;
282        self.manager
283            .send_close(*sock)
284            .map_err(StackError::SendCloseFailed)?;
285        self.callbacks
286            .tcp_sockets
287            .get(socket)
288            .ok_or(StackError::CloseFailed)?;
289        self.callbacks.tcp_sockets.remove(socket);
290        Ok(())
291    }
292}
293
294impl<X: Xfer> TcpFullStack for WincClient<'_, X> {
295    fn bind(&mut self, socket: &mut Self::TcpSocket, local_port: u16) -> Result<(), Self::Error> {
296        // Local server ports needs to be bound to 0.0.0.0
297        let server_addr =
298            core::net::SocketAddrV4::new(core::net::Ipv4Addr::new(0, 0, 0, 0), local_port);
299        let (sock, op) = self.callbacks.tcp_sockets.get(*socket).unwrap();
300        *op = ClientSocketOp::Bind(None);
301        debug!("<> Sending TCP socket bind to {:?}", sock);
302        self.manager
303            .send_bind(*sock, server_addr)
304            .map_err(StackError::BindFailed)?;
305        self.wait_with_timeout(Self::BIND_TIMEOUT, |client, _| {
306            let (_, op) = client.callbacks.tcp_sockets.get(*socket).unwrap();
307            let res = match op {
308                ClientSocketOp::Bind(Some(bind_result)) => match bind_result.error {
309                    SocketError::NoError => Some(Ok(())),
310                    _ => Some(Err(StackError::OpFailed(bind_result.error))),
311                },
312                _ => None,
313            };
314            if res.is_some() {
315                *op = ClientSocketOp::None;
316            }
317            res
318        })
319    }
320
321    fn listen(&mut self, socket: &mut Self::TcpSocket) -> Result<(), Self::Error> {
322        let (sock, op) = self.callbacks.tcp_sockets.get(*socket).unwrap();
323        let sock_index = sock.v as usize;
324        *op = ClientSocketOp::Listen(None);
325        debug!("<> Sending TCP socket listen to {:?}", sock);
326        self.manager.send_listen(*sock, Self::TCP_SOCKET_BACKLOG)?;
327        let res = self.wait_with_timeout(Self::LISTEN_TIMEOUT, |client, _| {
328            let (_, op) = client.callbacks.tcp_sockets.get(*socket).unwrap();
329            let res = match op {
330                ClientSocketOp::Listen(Some(listen_result)) => match listen_result.error {
331                    // todo: here we have to mark successfully listening sockets, to deal with accept backlog
332                    SocketError::NoError => Some(Ok(())),
333                    _ => Some(Err(StackError::OpFailed(listen_result.error))),
334                },
335                _ => None,
336            };
337            if res.is_some() {
338                *op = ClientSocketOp::None;
339            }
340            res
341        });
342        if res.is_ok() {
343            self.callbacks.listening_sockets[sock_index] = true;
344        }
345        res
346    }
347
348    // This is a blocking call, return WouldBlock if no connection has been accepted
349    fn accept(
350        &mut self,
351        socket: &mut Handle,
352    ) -> nb::Result<(Handle, core::net::SocketAddr), StackError> {
353        // Check if anything is backlogged
354        for backlog in self.callbacks.accept_backlog.iter_mut() {
355            if let Some((accepted_socket, addr)) = backlog.take() {
356                info!("Accepting backlogged socket {:?}", accepted_socket);
357                return Ok((Handle(accepted_socket.v), core::net::SocketAddr::V4(addr)));
358            }
359        }
360
361        let res = Self::async_op(
362            true,
363            socket,
364            &mut self.callbacks,
365            &mut self.manager,
366            self.poll_loop_delay_us,
367            |op| matches!(op, AsyncOp::Accept(..)),
368            |_, _| -> Result<ClientSocketOp, StackError> {
369                debug!("<> accept called on socket {:?}", socket);
370                // There's no manager.send_accept
371                Ok(ClientSocketOp::AsyncOp(
372                    AsyncOp::Accept(None),
373                    AsyncState::Pending(None),
374                ))
375            },
376            |_, _, _, asyncop| {
377                if let AsyncOp::Accept(Some(accept_result)) = asyncop {
378                    debug!("Accept result: {:?} on socket {:?}", accept_result, socket);
379                    let accepted_socket = accept_result.accepted_socket;
380                    let addr = accept_result.accept_addr;
381                    Ok((accepted_socket, core::net::SocketAddr::V4(addr)))
382                } else {
383                    Err(StackError::Unexpected)
384                }
385            },
386        );
387        self.test_hook();
388        match res {
389            Ok((raw_socket, addr)) => {
390                let handle = self
391                    .callbacks
392                    .tcp_sockets
393                    .put(Handle(raw_socket.v), raw_socket.s)
394                    .ok_or(StackError::SocketAlreadyInUse)?;
395                Ok((handle, addr))
396            }
397            Err(err) => Err(err),
398        }
399    }
400}
401
402#[cfg(test)]
403mod test {
404
405    use super::*;
406    use crate::client::{self, test_shared::*};
407    use crate::{client::SocketCallbacks, manager::EventListener, socket::Socket};
408    use core::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4};
409    use embedded_nal::{TcpClientStack, TcpFullStack};
410
411    #[test]
412    fn test_tcp_socket_open() {
413        let mut client = make_test_client();
414        let tcp_socket = client.socket();
415        assert!(tcp_socket.is_ok());
416    }
417
418    #[test]
419    fn test_tcp_connect() {
420        let mut client = make_test_client();
421        let mut tcp_socket = client.socket().unwrap();
422
423        let mut my_debug = |callbacks: &mut SocketCallbacks| {
424            callbacks.on_connect(Socket::new(0, 0), SocketError::NoError);
425        };
426
427        client.debug_callback = Some(&mut my_debug);
428        let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 80);
429
430        let result = nb::block!(client.connect(&mut tcp_socket, socket_addr));
431
432        assert!(result.is_ok());
433    }
434
435    #[test]
436    fn test_tcp_connect_check_blocking() {
437        let mut client = make_test_client();
438        let mut tcp_socket = client.socket().unwrap();
439        let mut counter: u8 = 0;
440
441        let mut my_debug = |callbacks: &mut SocketCallbacks| {
442            callbacks.on_connect(Socket::new(0, 0), SocketError::NoError);
443        };
444
445        let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 80);
446
447        while counter != 5 {
448            let result = client.connect(&mut tcp_socket, socket_addr);
449            assert!(matches!(result, Err(nb::Error::WouldBlock)));
450            counter += 1;
451        }
452
453        client.debug_callback = Some(&mut my_debug);
454
455        let result = nb::block!(client.connect(&mut tcp_socket, socket_addr));
456        assert_eq!(result, Ok(()));
457    }
458
459    #[test]
460    fn test_tcp_send() {
461        let mut client = make_test_client();
462        let mut tcp_socket = client.socket().unwrap();
463        let packet = "Hello, World";
464
465        let mut my_debug = |callbacks: &mut SocketCallbacks| {
466            callbacks.on_send(
467                Socket::new(0, 0),
468                client::WincClient::<'_, MockTransfer>::MAX_SEND_LENGTH as i16,
469            );
470        };
471
472        client.debug_callback = Some(&mut my_debug);
473
474        let result = nb::block!(client.send(&mut tcp_socket, packet.as_bytes()));
475
476        assert_eq!(result.ok(), Some(packet.len()));
477    }
478
479    #[test]
480    fn test_tcp_receive() {
481        let mut client = make_test_client();
482        let mut tcp_socket = client.socket().unwrap();
483        let socket_addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80);
484        let mut recv_buff = [0u8; 32];
485        let test_data = "Hello, World";
486
487        let mut my_debug = |callbacks: &mut SocketCallbacks| {
488            callbacks.on_recv(
489                Socket::new(0, 0),
490                socket_addr,
491                test_data.as_bytes(),
492                SocketError::NoError,
493            );
494        };
495
496        client.debug_callback = Some(&mut my_debug);
497
498        let result = nb::block!(client.receive(&mut tcp_socket, &mut recv_buff));
499
500        assert_eq!(result.ok(), Some(test_data.len()));
501        assert_eq!(&recv_buff[..test_data.len()], test_data.as_bytes());
502    }
503
504    #[test]
505    fn test_tcp_close() {
506        let mut client = make_test_client();
507        let tcp_socket = client.socket().unwrap();
508
509        let result = client.close(tcp_socket);
510
511        assert!(result.is_ok());
512    }
513
514    #[test]
515    fn test_tcp_bind() {
516        let mut client = make_test_client();
517        let mut tcp_socket = client.socket().unwrap();
518
519        let mut my_debug = |callbacks: &mut SocketCallbacks| {
520            callbacks.on_bind(Socket::new(0, 0), SocketError::NoError);
521        };
522
523        client.debug_callback = Some(&mut my_debug);
524
525        let result = client.bind(&mut tcp_socket, 8080);
526
527        assert!(result.is_ok());
528    }
529
530    #[test]
531    fn test_tcp_listen() {
532        let mut client = make_test_client();
533        let mut tcp_socket = client.socket().unwrap();
534
535        let mut my_debug = |callbacks: &mut SocketCallbacks| {
536            callbacks.on_listen(Socket::new(0, 0), SocketError::NoError);
537        };
538
539        client.debug_callback = Some(&mut my_debug);
540
541        let result = client.listen(&mut tcp_socket);
542
543        assert!(result.is_ok());
544    }
545
546    #[test]
547    fn test_tcp_accept() {
548        let mut client = make_test_client();
549        let mut tcp_socket = client.socket().unwrap();
550        let socket_addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80);
551
552        let mut my_debug = |callbacks: &mut SocketCallbacks| {
553            callbacks.on_accept(socket_addr, Socket::new(0, 0), Socket::new(1, 0), 0);
554        };
555
556        client.debug_callback = Some(&mut my_debug);
557
558        let result = nb::block!(client.accept(&mut tcp_socket));
559
560        assert!(result.is_ok());
561    }
562
563    #[test]
564    fn test_tcp_check_max_send_buffer() {
565        let mut client = make_test_client();
566        let mut tcp_socket = client.socket().unwrap();
567        let packet = "Hello, World";
568        let socket = Socket::new(0, 0);
569        let valid_len: i16 = client::WincClient::<'_, MockTransfer>::MAX_SEND_LENGTH as i16;
570
571        let mut my_debug = |callbacks: &mut SocketCallbacks| {
572            callbacks.on_send(socket, valid_len);
573        };
574
575        client.debug_callback = Some(&mut my_debug);
576
577        let result = client.send(&mut tcp_socket, packet.as_bytes());
578
579        assert_eq!(result, Err(nb::Error::WouldBlock));
580
581        if let Some((_, ClientSocketOp::AsyncOp(AsyncOp::Send(req, _), _))) =
582            client.callbacks.resolve(socket)
583        {
584            assert!((req.total_sent == valid_len) && (req.remaining == 0 as i16));
585        } else {
586            assert!(false, "Expected Some value, but it returned None");
587        }
588    }
589
590    #[test]
591    fn test_tcp_check_receive_timeout() {
592        let mut client = make_test_client();
593        let mut tcp_socket = client.socket().unwrap();
594        let socket_addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80);
595        let mut recv_buff = [0u8; 32];
596        let mut counter = 5;
597
598        let mut my_debug = |callbacks: &mut SocketCallbacks| {
599            callbacks.on_recv(Socket::new(0, 0), socket_addr, &[], SocketError::Timeout);
600        };
601
602        client.debug_callback = Some(&mut my_debug);
603
604        while counter != 0 {
605            let result = client.receive(&mut tcp_socket, &mut recv_buff);
606
607            assert_eq!(result.err(), Some(nb::Error::WouldBlock));
608            counter -= 1;
609        }
610    }
611
612    #[test]
613    fn test_tcp_check_receive_err() {
614        let mut client = make_test_client();
615        let mut tcp_socket = client.socket().unwrap();
616        let socket_addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80);
617        let mut recv_buff = [0u8; 32];
618
619        let mut my_debug = |callbacks: &mut SocketCallbacks| {
620            callbacks.on_recv(
621                Socket::new(0, 0),
622                socket_addr,
623                &[],
624                SocketError::ConnAborted,
625            );
626        };
627
628        client.debug_callback = Some(&mut my_debug);
629
630        let result = nb::block!(client.receive(&mut tcp_socket, &mut recv_buff));
631
632        assert_eq!(
633            result.err(),
634            Some(StackError::OpFailed(SocketError::ConnAborted))
635        );
636    }
637
638    #[test]
639    fn test_tcp_check_bind_error() {
640        let mut client = make_test_client();
641        let mut tcp_socket = client.socket().unwrap();
642
643        let mut my_debug = |callbacks: &mut SocketCallbacks| {
644            callbacks.on_bind(Socket::new(0, 0), SocketError::InvalidAddress);
645        };
646
647        client.debug_callback = Some(&mut my_debug);
648
649        let result = client.bind(&mut tcp_socket, 8080);
650
651        assert_eq!(
652            result.err(),
653            Some(StackError::OpFailed(SocketError::InvalidAddress))
654        );
655    }
656
657    #[test]
658    fn test_tcp_check_accept_backlog() {
659        let mut client = make_test_client();
660        let mut tcp_socket = client.socket().unwrap();
661        let socket_addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80);
662        let socket = Socket::new(0, 0);
663
664        client.callbacks.accept_backlog[0] = Some((socket, socket_addr));
665
666        let result = nb::block!(client.accept(&mut tcp_socket));
667
668        assert_eq!(
669            result.ok(),
670            Some((Handle(0), core::net::SocketAddr::V4(socket_addr)))
671        );
672    }
673
674    #[test]
675    fn test_tcp_check_listen_error() {
676        let mut client = make_test_client();
677        let mut tcp_socket = client.socket().unwrap();
678
679        let mut my_debug = |callbacks: &mut SocketCallbacks| {
680            callbacks.on_listen(Socket::new(0, 0), SocketError::ConnAborted);
681        };
682
683        client.debug_callback = Some(&mut my_debug);
684
685        let result = client.listen(&mut tcp_socket);
686
687        assert!(result.is_err());
688    }
689
690    #[test]
691    fn test_tcp_connect_error() {
692        let mut client = make_test_client();
693        let mut tcp_socket = client.socket().unwrap();
694
695        let mut my_debug = |callbacks: &mut SocketCallbacks| {
696            callbacks.on_connect(Socket::new(0, 0), SocketError::ConnAborted);
697        };
698
699        client.debug_callback = Some(&mut my_debug);
700        let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 80);
701
702        let result = nb::block!(client.connect(&mut tcp_socket, socket_addr));
703
704        assert_eq!(
705            result.err(),
706            Some(StackError::OpFailed(SocketError::ConnAborted))
707        );
708    }
709
710    #[test]
711    #[should_panic]
712    fn test_tcp_connect_ipv6() {
713        let mut client = make_test_client();
714        let mut tcp_socket = client.socket().unwrap();
715
716        let socket_addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), 80);
717
718        let _ = client.connect(&mut tcp_socket, socket_addr);
719    }
720
721    #[test]
722    fn test_tcp_large_payload_receive() {
723        let mut client = make_test_client();
724        let mut tcp_socket = client.socket().unwrap();
725        let socket_addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80);
726        let mut recv_buffer = [0u8; 350]; // Small caller buffer
727
728        // Large packet from SPI - 1400 bytes, all 0xAA
729        let mut my_debug = |callbacks: &mut SocketCallbacks| {
730            callbacks.on_recv(
731                Socket::new(0, 0),
732                socket_addr,
733                &[0xAA; 1400], // Large packet from SPI (within buffer limit)
734                SocketError::NoError,
735            );
736        };
737        client.debug_callback = Some(&mut my_debug);
738
739        // First read should return 350 bytes (partial)
740        let first_read = nb::block!(client.receive(&mut tcp_socket, &mut recv_buffer)).unwrap();
741        assert_eq!(first_read, 350);
742        assert!(recv_buffer.iter().all(|&x| x == 0xAA));
743
744        // Second read should return next 350 bytes (partial)
745        let second_read = nb::block!(client.receive(&mut tcp_socket, &mut recv_buffer)).unwrap();
746        assert_eq!(second_read, 350);
747        assert!(recv_buffer.iter().all(|&x| x == 0xAA));
748
749        // Third read should return next 350 bytes (partial)
750        let third_read = nb::block!(client.receive(&mut tcp_socket, &mut recv_buffer)).unwrap();
751        assert_eq!(third_read, 350);
752        assert!(recv_buffer.iter().all(|&x| x == 0xAA));
753
754        // Fourth read should return remaining 350 bytes (complete)
755        let fourth_read = nb::block!(client.receive(&mut tcp_socket, &mut recv_buffer)).unwrap();
756        assert_eq!(fourth_read, 350);
757        assert!(recv_buffer.iter().all(|&x| x == 0xAA));
758
759        // Fifth read should initiate a new packet - different pattern
760        let mut my_debug = |callbacks: &mut SocketCallbacks| {
761            callbacks.on_recv(
762                Socket::new(0, 0),
763                socket_addr,
764                &[0x55; 700], // Smaller large packet
765                SocketError::NoError,
766            );
767        };
768        client.debug_callback = Some(&mut my_debug);
769
770        let fifth_read = nb::block!(client.receive(&mut tcp_socket, &mut recv_buffer)).unwrap();
771        assert_eq!(fifth_read, 350);
772        assert!(recv_buffer.iter().all(|&x| x == 0x55));
773
774        // Sixth read should return remaining 350 bytes
775        let sixth_read = nb::block!(client.receive(&mut tcp_socket, &mut recv_buffer)).unwrap();
776        assert_eq!(sixth_read, 350);
777        assert!(recv_buffer.iter().all(|&x| x == 0x55));
778
779        // No more data
780        let mut my_debug = |callbacks: &mut SocketCallbacks| {
781            callbacks.on_recv(Socket::new(0, 0), socket_addr, &[], SocketError::NoError);
782        };
783        client.debug_callback = Some(&mut my_debug);
784
785        let seventh_read = nb::block!(client.receive(&mut tcp_socket, &mut recv_buffer)).unwrap();
786        assert_eq!(seventh_read, 0);
787    }
788
789    #[test]
790    fn partial_receive_full_test() {
791        // Test case 1: 10KB data, small SPI buffer (31 bytes), large receiver buffer (2KB)
792        // This tests the scenario where SPI delivers small chunks but app has large buffers
793        run_partial_read_test(10240, 31, 2048);
794
795        // Test case 2: 10KB data, small SPI buffer (100 bytes), small receiver buffer (100 bytes)
796        // This tests equal sized buffers under the builtin buffer sizes
797        run_partial_read_test(10240, 100, 100);
798
799        // Test case 3: 10KB data, equal SPI and receiver buffers (64 bytes)
800        // Another equal size test with smaller buffers
801        run_partial_read_test(10240, 64, 64);
802
803        // Test case 4: 10KB data, large SPI buffer (1024 bytes), small receiver buffer (31 bytes)
804        // This tests large SPI chunks but tiny app reads
805        run_partial_read_test(10240, 1024, 31);
806
807        // Test case 5: 10KB data, large SPI buffer (1024 bytes), small receiver buffer (100 bytes)
808        // Large SPI with medium app reads
809        run_partial_read_test(10240, 1024, 100);
810
811        // Test case 6: 10KB data, equal larger buffers (1024 bytes each)
812        // This tests equal sized large buffers
813        run_partial_read_test(10240, 1024, 1024);
814
815        // Test case 7: 10KB data, equal large buffers (1400 bytes each - near MTU limit)
816        // This tests the largest practical equal buffer sizes
817        run_partial_read_test(10240, 1400, 1400);
818
819        // Test case 8: Edge case - tiny data, large buffers
820        run_partial_read_test(64, 1024, 1400);
821
822        // Test case 9: Edge case - data that doesn't align with 4-byte boundaries nicely
823        run_partial_read_test(9996, 97, 131); // Non-round numbers to test edge cases
824    }
825
826    fn run_partial_read_test(total_size: usize, spi_chunk_size: usize, receive_buffer_size: usize) {
827        let mut client = make_test_client();
828        let mut socket_handle = client.socket().unwrap();
829        let socket_addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80);
830
831        // Prepare test data pattern
832        let mut source_data = [0u8; 10240];
833        assert!(total_size <= source_data.len());
834        let source_slice = &mut source_data[0..total_size];
835        crate::client::tests::generate_test_pattern(source_slice);
836        let expected_checksum = crate::client::tests::compute_crc16(source_slice);
837
838        // Storage for received data
839        let mut received_data = [0u8; 10240];
840        let mut app_receive_buffer = [0u8; 2048];
841        assert!(receive_buffer_size <= app_receive_buffer.len());
842
843        // Start the initial receive call to put socket in pending state
844        let initial_result = client.receive(
845            &mut socket_handle,
846            &mut app_receive_buffer[0..receive_buffer_size],
847        );
848        assert_eq!(initial_result, Err(nb::Error::WouldBlock));
849
850        let mut total_bytes_received = 0;
851        let mut spi_offset = 0;
852
853        // Simulate SPI data arriving in chunks
854        while spi_offset < total_size {
855            let chunk_end = (spi_offset + spi_chunk_size).min(total_size);
856            let chunk = &source_slice[spi_offset..chunk_end];
857
858            // Copy chunk to internal buffer and trigger callback
859            client.callbacks.recv_buffer[..chunk.len()].copy_from_slice(chunk);
860            client
861                .callbacks
862                .on_recv(Socket::new(0, 0), socket_addr, chunk, SocketError::NoError);
863
864            spi_offset = chunk_end;
865
866            // Read all available data with the specified receiver buffer size
867            loop {
868                let receive_slice = &mut app_receive_buffer[0..receive_buffer_size];
869                let read_result = client.receive(&mut socket_handle, receive_slice);
870
871                match read_result {
872                    Ok(bytes_read) => {
873                        if bytes_read == 0 {
874                            break; // No more data from this SPI chunk
875                        }
876
877                        // Copy received data to our accumulator
878                        received_data[total_bytes_received..total_bytes_received + bytes_read]
879                            .copy_from_slice(&receive_slice[0..bytes_read]);
880                        total_bytes_received += bytes_read;
881                    }
882                    Err(nb::Error::WouldBlock) => {
883                        break; // Need more SPI data
884                    }
885                    Err(e) => {
886                        panic!("Unexpected error: {:?}", e);
887                    }
888                }
889            }
890        }
891
892        // Verify all data was received correctly
893        assert_eq!(
894            total_bytes_received, total_size,
895            "Total bytes received {} != expected {} (SPI: {}, RX: {})",
896            total_bytes_received, total_size, spi_chunk_size, receive_buffer_size
897        );
898
899        let received_slice = &received_data[0..total_size];
900        let actual_checksum = crate::client::tests::compute_crc16(received_slice);
901        assert_eq!(
902            actual_checksum, expected_checksum,
903            "Checksum mismatch! (SPI: {}, RX: {})",
904            spi_chunk_size, receive_buffer_size
905        );
906
907        assert_eq!(
908            received_slice, source_slice,
909            "Data content mismatch! (SPI: {}, RX: {})",
910            spi_chunk_size, receive_buffer_size
911        );
912    }
913}