• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kaidokert / winc-rs / 13918127466

18 Mar 2025 07:58AM UTC coverage: 76.091% (+1.1%) from 74.993%
13918127466

push

github

web-flow
Refactor async ops with a shared state machine (#45)

168 of 321 new or added lines in 4 files covered. (52.34%)

3 existing lines in 3 files now uncovered.

2651 of 3484 relevant lines covered (76.09%)

1997.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

59.86
/winc-rs/src/stack/socket_callbacks.rs
1
use core::net::Ipv4Addr;
2

3
use crate::manager::{EventListener, SocketError, WifiConnError, WifiConnState};
4
use crate::ConnectionInfo;
5

6
use crate::{debug, error, info};
7

8
use crate::socket::Socket;
9

10
use crate::Ipv4AddrFormatWrapper;
11

12
use super::SockHolder;
13
use crate::manager::{PingError, ScanResult, SOCKET_BUFFER_MAX_LENGTH};
14

15
use crate::stack::sock_holder::SocketStore;
16

17
/// Opaque handle to a socket. Returned by socket APIs
18
#[derive(Clone, Copy, PartialEq, Debug)]
19
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
20
pub struct Handle(pub u8);
21

22
#[derive(Debug, PartialEq, Clone)]
23
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
24
pub(crate) enum WifiModuleState {
25
    Reset,
26
    Starting,
27
    Started,
28
    ConnectingToAp,
29
    ConnectedToAp,
30
    ConnectionFailed,
31
}
32

33
/// Ping operation results
34
#[derive(Debug)]
35
pub struct PingResult {
36
    pub ip: Ipv4Addr,
37
    pub rtt: u32,
38
    pub num_successful: u16,
39
    pub num_failed: u16,
40
    pub error: PingError,
41
}
42

43
#[cfg(feature = "defmt")]
44
impl defmt::Format for PingResult {
45
    fn format(&self, f: defmt::Formatter) {
46
        defmt::write!(
47
            f,
48
            "ip: {}, rtt: {}, num_successful: {}, num_failed: {}, error: {}",
49
            Ipv4AddrFormatWrapper::new(&self.ip),
50
            self.rtt,
51
            self.num_successful,
52
            self.num_failed,
53
            self.error
54
        );
55
    }
56
}
57

58
// TODO: This should be exposed to user
59
#[allow(dead_code)]
60
pub struct SystemTime {
61
    year: u16,
62
    month: u8,
63
    day: u8,
64
    hour: u8,
65
    minute: u8,
66
    second: u8,
67
}
68

69
pub(crate) struct ConnectionState {
70
    conn_state: WifiConnState,
71
    pub conn_error: Option<WifiConnError>,
72
    pub ip_conf: Option<crate::manager::IPConf>,
73
    system_time: Option<SystemTime>,
74
    ip_conflict: Option<Ipv4Addr>,
75
    pub scan_number_aps: Option<Option<u8>>,
76
    pub scan_results: Option<Option<ScanResult>>,
77
    pub conn_info: Option<Option<ConnectionInfo>>,
78
    pub rssi_level: Option<Option<i8>>,
79
    pub ping_result: Option<Option<PingResult>>,
80
}
81

82
impl ConnectionState {
83
    fn new() -> Self {
30✔
84
        Self {
30✔
85
            conn_state: WifiConnState::Disconnected,
30✔
86
            conn_error: None,
30✔
87
            ip_conf: None,
30✔
88
            system_time: None,
30✔
89
            rssi_level: None,
30✔
90
            ip_conflict: None,
30✔
91
            conn_info: None,
30✔
92
            scan_number_aps: None,
30✔
93
            scan_results: None,
30✔
94
            ping_result: None,
30✔
95
        }
30✔
96
    }
30✔
97
}
98

99
pub(crate) const UDP_SOCK_OFFSET: usize = 7;
100
pub(crate) const MAX_UDP_SOCKETS: usize = 4;
101

102
pub(crate) struct SocketCallbacks {
103
    // #define TCP_SOCK_MAX                                                                                (7)
104
    // indexes 0-6
105
    pub tcp_sockets: SockHolder<UDP_SOCK_OFFSET, 0>,
106
    // #define UDP_SOCK_MAX                                                                                4
107
    pub udp_sockets: SockHolder<MAX_UDP_SOCKETS, UDP_SOCK_OFFSET>,
108
    // Needed to keep track of connect() and recvfrom address
109
    pub udp_socket_connect_addr: [Option<core::net::SocketAddrV4>; MAX_UDP_SOCKETS],
110
    pub recv_buffer: [u8; SOCKET_BUFFER_MAX_LENGTH],
111

112
    // This is global
113
    pub dns_resolved_addr: Option<Option<core::net::Ipv4Addr>>,
114
    pub connection_state: ConnectionState,
115
    pub state: WifiModuleState,
116
}
117

118
#[derive(Debug, Clone, Copy, PartialEq)]
119
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
120
pub(crate) struct ConnectResult {
121
    pub error: SocketError,
122
}
123

124
#[derive(Debug, Clone, Copy, PartialEq)]
125
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
126
pub(crate) struct SendRequest {
127
    pub offset: usize,
128
    pub grand_total_sent: i16,
129
    pub total_sent: i16,
130
    pub remaining: i16,
131
}
132

133
#[derive(Debug, Clone, Copy, PartialEq)]
134
pub(crate) struct RecvResult {
135
    pub recv_len: usize,
136
    pub from_addr: core::net::SocketAddrV4,
137
    pub error: SocketError,
138
}
139
#[cfg(feature = "defmt")]
140
impl defmt::Format for RecvResult {
141
    fn format(&self, f: defmt::Formatter) {
142
        defmt::write!(
143
            f,
144
            "recv_len: {}, from_addr: {:?}, error: {}",
145
            self.recv_len,
146
            Ipv4AddrFormatWrapper::new(self.from_addr.ip()),
147
            self.error
148
        );
149
    }
150
}
151

152
#[derive(Debug, Clone, Copy, PartialEq)]
153
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
154
pub(crate) struct BindListenResult {
155
    pub error: SocketError,
156
}
157

158
#[derive(Debug, Clone, Copy, PartialEq)]
159
pub(crate) struct AcceptResult {
160
    pub accept_addr: core::net::SocketAddrV4,
161
    pub accepted_socket: Socket,
162
}
163
#[cfg(feature = "defmt")]
164
impl defmt::Format for AcceptResult {
165
    fn format(&self, f: defmt::Formatter) {
166
        defmt::write!(
167
            f,
168
            "accept_addr: {:?}, port: {}, accepted_socket: {:?}",
169
            Ipv4AddrFormatWrapper::new(self.accept_addr.ip()),
170
            self.accept_addr.port(),
171
            self.accepted_socket
172
        );
173
    }
174
}
175

176
#[derive(PartialEq, Clone, Copy, Debug)]
177
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
178
pub enum AsyncState {
179
    Pending(Option<u32>),
180
    Done,
181
}
182

183
#[derive(PartialEq, Clone, Copy, Debug)]
184
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
185
pub enum AsyncOp {
186
    Connect(Option<ConnectResult>),
187
    Send(SendRequest, Option<i16>),
188
    SendTo(SendRequest, Option<i16>),
189
    Recv(Option<RecvResult>),
190
    RecvFrom(Option<RecvResult>),
191
    Accept(Option<AcceptResult>),
192
}
193

194
#[derive(PartialEq, Clone, Copy, Debug)]
195
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
196
pub enum ClientSocketOp {
197
    None,
198
    New,
199
    Bind(Option<BindListenResult>),
200
    Listen(Option<BindListenResult>),
201
    AsyncOp(AsyncOp, AsyncState),
202
}
203

204
impl SocketCallbacks {
205
    pub fn new() -> Self {
30✔
206
        Self {
30✔
207
            tcp_sockets: SockHolder::new(),
30✔
208
            udp_sockets: SockHolder::new(),
30✔
209
            udp_socket_connect_addr: [None; MAX_UDP_SOCKETS],
30✔
210
            recv_buffer: [0; SOCKET_BUFFER_MAX_LENGTH],
30✔
211
            dns_resolved_addr: None,
30✔
212
            connection_state: ConnectionState::new(),
30✔
213
            state: WifiModuleState::Reset,
30✔
214
        }
30✔
215
    }
30✔
216
    pub fn resolve(&mut self, socket: Socket) -> Option<&mut (Socket, ClientSocketOp)> {
12✔
217
        if socket.v < UDP_SOCK_OFFSET as u8 {
12✔
218
            debug!("resolving tcp: {:?}", socket.v);
12✔
219
            self.tcp_sockets.get(Handle(socket.v))
12✔
220
        } else {
221
            debug!("resolving udp: {:?}", socket.v);
×
222
            self.udp_sockets
×
223
                .get(Handle(socket.v - UDP_SOCK_OFFSET as u8))
×
224
        }
225
    }
12✔
226
}
227

228
impl EventListener for SocketCallbacks {
229
    fn on_rssi(&mut self, level: i8) {
1✔
230
        info!("client: Got RSSI:{}", level);
1✔
231
        self.connection_state.rssi_level = Some(Some(level));
1✔
232
    }
1✔
233

234
    fn on_resolve(&mut self, ip: core::net::Ipv4Addr, host: &str) {
6✔
235
        debug!(
6✔
236
            "on_resolve: ip:{:?} host:{:?}",
×
237
            Ipv4AddrFormatWrapper::new(&ip),
×
238
            host
239
        );
240
        self.dns_resolved_addr = Some(Some(ip));
6✔
241
    }
6✔
242

243
    fn on_default_connect(&mut self, connected: bool) {
×
244
        debug!("client: got connected {}", connected)
×
245
    }
×
246
    fn on_dhcp(&mut self, conf: crate::manager::IPConf) {
×
247
        debug!("client: on_dhcp: IP config: {}", conf);
×
248
        self.connection_state.ip_conf = Some(conf);
×
249
    }
×
250
    fn on_connstate_changed(&mut self, state: WifiConnState, err: WifiConnError) {
3✔
251
        debug!("client: Connection state changed: {:?} {:?}", state, err);
3✔
252
        self.connection_state.conn_state = state;
3✔
253
        self.connection_state.conn_error = Some(err);
3✔
254
        match self.state {
3✔
255
            WifiModuleState::ConnectingToAp => match self.connection_state.conn_state {
3✔
256
                WifiConnState::Connected => {
2✔
257
                    self.state = WifiModuleState::ConnectedToAp;
2✔
258
                }
2✔
259
                _ => {
260
                    self.state = WifiModuleState::ConnectionFailed;
1✔
261
                    debug!(
1✔
262
                        "on_connstate_changed FAILED: {:?} {:?}",
×
263
                        self.connection_state.conn_state, self.connection_state.conn_error
264
                    );
265
                }
266
            },
267
            _ => {
268
                error!(
×
269
                    "UNKNOWN STATE on_connstate_changed: {:?} {:?}",
×
270
                    self.connection_state.conn_state, self.connection_state.conn_error
271
                );
272
            }
273
        }
274
    }
3✔
275

276
    fn on_connection_info(&mut self, info: ConnectionInfo) {
1✔
277
        debug!("client: conninfo, state:{}", info);
1✔
278
        self.connection_state.conn_info = Some(Some(info));
1✔
279
    }
1✔
280
    fn on_system_time(&mut self, year: u16, month: u8, day: u8, hour: u8, minute: u8, second: u8) {
×
281
        debug!(
×
282
            "client: on_system_time: {}-{:02}-{:02} {:02}:{:02}:{:02}",
×
283
            year, month, day, hour, minute, second
284
        );
285
        self.connection_state.system_time = Some(SystemTime {
×
286
            year,
×
287
            month,
×
288
            day,
×
289
            hour,
×
290
            minute,
×
291
            second,
×
292
        });
×
293
    }
×
294
    fn on_ip_conflict(&mut self, ip: Ipv4Addr) {
×
295
        info!(
×
296
            "client: on_ip_conflict: {:?}",
×
297
            Ipv4AddrFormatWrapper::new(&ip)
×
298
        );
299
        self.connection_state.ip_conflict = Some(ip);
×
300
    }
×
301

302
    fn on_scan_result(&mut self, result: ScanResult) {
1✔
303
        debug!("Scanresult {}", result);
1✔
304
        self.connection_state.scan_results = Some(Some(result));
1✔
305
    }
1✔
306
    fn on_scan_done(&mut self, num_aps: u8, err: WifiConnError) {
1✔
307
        debug!("Scan done, aps:{} error:{}", num_aps, err);
1✔
308
        if err != WifiConnError::Unhandled {
1✔
309
            self.connection_state.conn_error = Some(err);
×
310
        }
1✔
311
        self.connection_state.scan_number_aps = Some(Some(num_aps));
1✔
312
    }
1✔
313
    fn on_ping(
1✔
314
        &mut self,
1✔
315
        ip: Ipv4Addr,
1✔
316
        token: u32,
1✔
317
        rtt: u32,
1✔
318
        num_successful: u16,
1✔
319
        num_failed: u16,
1✔
320
        error: PingError,
1✔
321
    ) {
1✔
322
        let ping_result = PingResult {
1✔
323
            ip,
1✔
324
            rtt,
1✔
325
            num_successful,
1✔
326
            num_failed,
1✔
327
            error,
1✔
328
        };
1✔
329
        debug!("client: on_ping: {:?} token:# {}", ping_result, token);
1✔
330
        self.connection_state.ping_result = Some(Some(ping_result));
1✔
331
    }
1✔
332

333
    // todo: Consolidate the error cases to match statements below
334
    fn on_connect(&mut self, socket: Socket, err: SocketError) {
4✔
335
        debug!("on_connect: socket {:?}", socket);
4✔
336
        match self.resolve(socket) {
4✔
337
            Some((
338
                _,
339
                ClientSocketOp::AsyncOp(
340
                    AsyncOp::Connect(option),
2✔
341
                    asyncstate @ AsyncState::Pending(_),
2✔
342
                ),
2✔
343
            )) => {
2✔
344
                option.replace(ConnectResult { error: err });
2✔
345
                *asyncstate = AsyncState::Done;
2✔
346
            }
2✔
347
            Some((s, op)) => error!(
2✔
348
                "UNKNOWN STATE on_connect (x): socket:{:?} error:{:?} state:{:?}",
2✔
349
                s, err, op
350
            ),
351
            None => error!(
×
352
                "on_connect (x): COULD NOT FIND SOCKET socket:{:?} error:{:?}",
×
353
                socket, err
354
            ),
355
        }
356
    }
4✔
357
    fn on_send_to(&mut self, socket: Socket, len: i16) {
×
358
        debug!("on_send_to: socket:{:?} length:{:?}", socket, len);
×
359
        match self.resolve(socket) {
×
360
            Some((
NEW
361
                s,
×
NEW
362
                ClientSocketOp::AsyncOp(
×
NEW
363
                    AsyncOp::SendTo(req, option),
×
NEW
364
                    asyncstate @ AsyncState::Pending(_),
×
NEW
365
                ),
×
NEW
366
            )) => {
×
367
                req.total_sent += len;
×
368
                req.remaining -= len;
×
369
                if req.remaining <= 0 {
×
NEW
370
                    debug!("FIN: on_send_to: socket:{:?} length:{:?}", s, len);
×
371
                    option.replace(len);
×
NEW
372
                    *asyncstate = AsyncState::Done;
×
373
                } else {
NEW
374
                    debug!("CONT: on_send_to: socket:{:?} length:{:?}", s, len);
×
375
                }
376
            }
377
            Some((s, op)) => error!(
×
NEW
378
                "UNKNOWN STATE on_send_to (x): socket:{:?} len:{:?} state:{:?}",
×
379
                s, len, *op
380
            ),
381
            None => error!(
×
382
                "on_send (x): COULD NOT FIND SOCKET socket:{:?} len:{:?}",
×
383
                socket, len
384
            ),
385
        }
386
    }
×
387
    fn on_send(&mut self, socket: Socket, len: i16) {
2✔
388
        debug!("on_send: socket {:?} len:{}", socket, len);
2✔
389
        match self.resolve(socket) {
2✔
390
            Some((
391
                s,
1✔
392
                ClientSocketOp::AsyncOp(
1✔
393
                    AsyncOp::Send(req, option),
1✔
394
                    asyncstate @ AsyncState::Pending(_),
1✔
395
                ),
1✔
396
            )) => {
1✔
397
                req.total_sent += len;
1✔
398
                req.remaining -= len;
1✔
399
                if req.remaining <= 0 {
1✔
400
                    debug!("FIN: on_send: socket:{:?} length:{:?}", s, len);
1✔
401
                    option.replace(len);
1✔
402
                    *asyncstate = AsyncState::Done;
1✔
403
                } else {
404
                    debug!("CONT: on_send: socket:{:?} length:{:?}", s, len);
×
405
                }
406
            }
407
            Some((s, op)) => error!(
1✔
408
                "UNKNOWN STATE on_send (x): socket:{:?} len:{:?} state:{:?}",
1✔
409
                s, len, *op
410
            ),
411
            None => error!(
×
412
                "on_send (x): COULD NOT FIND SOCKET socket:{:?} len:{:?}",
×
413
                socket, len
414
            ),
415
        }
416
    }
2✔
417
    fn on_recv(
2✔
418
        &mut self,
2✔
419
        socket: Socket,
2✔
420
        address: core::net::SocketAddrV4,
2✔
421
        data: &[u8],
2✔
422
        err: crate::manager::SocketError,
2✔
423
    ) {
2✔
424
        debug!("on_recv: socket {:?}", socket);
2✔
425
        match self.resolve(socket) {
2✔
426
            Some((s, ClientSocketOp::AsyncOp(
1✔
427
                    AsyncOp::Recv(option),
1✔
428
                    asyncstate @ AsyncState::Pending(_),))) => {
1✔
429
                debug!(
1✔
430
                    "on_recv: socket:{:?} address:{:?} data:{:?} len:{:?} error:{:?}",
×
431
                    s,
×
432
                    Ipv4AddrFormatWrapper::new(address.ip()),
×
433
                    data,
×
434
                    data.len(),
×
435
                    err
436
                );
437
                option.replace(RecvResult {
1✔
438
                    recv_len: data.len(),
1✔
439
                    from_addr: address,
1✔
440
                    error: err,
1✔
441
                });
1✔
442
                *asyncstate = AsyncState::Done;
1✔
443
                self.recv_buffer[..data.len()].copy_from_slice(data);
1✔
444
            }
445
            Some((_, op)) => error!(
1✔
446
                "Socket NOT in recv: socket:{:?} address:{:?} data:{:?} error:{:?} actual state:{:?}",
1✔
447
                socket,
1✔
448
                Ipv4AddrFormatWrapper::new(address.ip()),
1✔
449
                data,
450
                err, op
451
            ),
452
            None => error!(
×
453
                "UNKNOWN on_recv: socket:{:?} address:{:?} data:{:?} error:{:?}",
×
454
                socket,
×
455
                Ipv4AddrFormatWrapper::new(address.ip()),
×
456
                data,
457
                err
458
            ),
459
        }
460
    }
2✔
461
    fn on_recvfrom(
×
462
        &mut self,
×
463
        socket: Socket,
×
464
        address: core::net::SocketAddrV4,
×
465
        data: &[u8],
×
466
        err: crate::manager::SocketError,
×
467
    ) {
×
468
        debug!("on_recvfrom: socket {:?}", socket);
×
469
        match self.resolve(socket) {
×
NEW
470
            Some((s, ClientSocketOp::AsyncOp(
×
NEW
471
                    AsyncOp::RecvFrom(option),
×
NEW
472
                    asyncstate @ AsyncState::Pending(_),))) => {
×
473
                debug!(
×
474
                    "on_recvfrom: raw:{:?} socket:{:?} address:{:?} data:{:?} error:{:?}",
×
475
                    socket,
×
476
                    s,
×
477
                    Ipv4AddrFormatWrapper::new(address.ip()),
×
478
                    data,
479
                    err
480
                );
481
                option.replace(RecvResult {
×
482
                    recv_len: data.len(),
×
483
                    from_addr: address,
×
484
                    error: err,
×
485
                });
×
NEW
486
                *asyncstate = AsyncState::Done;
×
UNCOV
487
                self.recv_buffer[..data.len()].copy_from_slice(data);
×
488
            }
489
            Some((_, op)) => error!(
×
490
                "Socket NOT in recvfrom: socket:{:?} address:{:?} data:{:?} error:{:?} actual state:{:?}",
×
491
                socket,
×
492
                Ipv4AddrFormatWrapper::new(address.ip()),
×
493
                data,
494
                err,
495
                op
496
            ),
497
            None => error!(
×
498
                "UNKNOWN on_recvfrom: socket:{:?} address:{:?} data:{:?} error:{:?}",
×
499
                socket,
×
500
                Ipv4AddrFormatWrapper::new(address.ip()),
×
501
                data,
502
                err
503
            ),
504
        }
505
    }
×
506
    fn on_bind(&mut self, sock: Socket, err: SocketError) {
1✔
507
        debug!("on_bind: socket {:?}", sock);
1✔
508
        match self.resolve(sock) {
1✔
509
            Some((_, ClientSocketOp::Bind(option))) => {
1✔
510
                option.replace(BindListenResult { error: err });
1✔
511
            }
1✔
512
            Some((s, op)) => error!(
×
513
                "UNKNOWN on_bind: socket:{:?} error:{:?} state:{:?}",
×
514
                s, err, op
515
            ),
516
            None => error!("UNKNOWN socket on_bind: socket:{:?} error:{:?}", sock, err),
×
517
        }
518
    }
1✔
519
    fn on_listen(&mut self, sock: Socket, err: SocketError) {
1✔
520
        debug!("on_listen: socket {:?}", sock);
1✔
521
        match self.resolve(sock) {
1✔
522
            Some((_, ClientSocketOp::Listen(option))) => {
1✔
523
                option.replace(BindListenResult { error: err });
1✔
524
            }
1✔
525
            Some((s, op)) => error!(
×
526
                "UNKNOWN on_listen: socket:{:?} error:{:?} state:{:?}",
×
527
                s, err, op
528
            ),
529
            None => error!(
×
530
                "UNKNOWN socket on_listen: socket:{:?} error:{:?}",
×
531
                sock, err
532
            ),
533
        }
534
    }
1✔
535

536
    fn on_accept(
2✔
537
        &mut self,
2✔
538
        address: core::net::SocketAddrV4,
2✔
539
        listen_socket: Socket,
2✔
540
        accepted_socket: Socket,
2✔
541
        _data_offset: u16,
2✔
542
    ) {
2✔
543
        debug!(
2✔
544
            "on_accept: address:{:?} port:{:?} listen_socket:{:?} accepted_socket:{:?}",
×
545
            Ipv4AddrFormatWrapper::new(address.ip()),
×
546
            address.port(),
×
547
            listen_socket,
548
            accepted_socket
549
        );
550

551
        match self.resolve(listen_socket) {
2✔
552
            Some((s, ClientSocketOp::AsyncOp(
1✔
553
                    AsyncOp::Accept(option),
1✔
554
                    asyncstate @ AsyncState::Pending(_),))) => {
1✔
555
                debug!("on_accept: socket:{:?} port:{:?} address:{:?} accepted_socket:{:?}", s,
1✔
NEW
556
                    Ipv4AddrFormatWrapper::new(address.ip()),
×
NEW
557
                    address.port(),
×
558
                    accepted_socket);
559
                option.replace(AcceptResult {
1✔
560
                    accept_addr: address,
1✔
561
                    accepted_socket,
1✔
562
                });
1✔
563
                *asyncstate = AsyncState::Done;
1✔
564
            }
565
            // Todo here: If it was in None state, move it to accept backlog
566
            Some((_, op)) => error!(
1✔
567
                "Socket was NOT in accept: address:{:?} port:{:?} listen_socket:{:?} accepted_socket:{:?} actual state:{:?}",
1✔
568
                Ipv4AddrFormatWrapper::new(address.ip()),
1✔
569
                address.port(),
1✔
570
                listen_socket,
571
                accepted_socket,
572
                op
573
            ),
574
            None => error!(
×
575
                "UNKNOWN socket on_accept: address:{:?} port:{:?} listen_socket:{:?} accepted_socket:{:?}",
×
576
                Ipv4AddrFormatWrapper::new(address.ip()),
×
577
                address.port(),
×
578
                listen_socket,
579
                accepted_socket
580
            ),
581
        }
582
    }
2✔
583
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc