Skip to content

Commit 31df8f3

Browse files
net: use recv/send directly instead of wolfSSL's optional wolfIO helpers
wolfIO_Recv and wolfIO_Send are declared under USE_WOLFSSL_IO || WOLFSSL_USER_IO || HAVE_HTTP_CLIENT, but defined only under USE_WOLFSSL_IO, which wolfSSL auto-defines only when none of WOLFSSL_USER_IO, MICRIUM, WOLFSSL_CONTIKI or WOLFSSL_NO_SOCK is set. The built-in transport therefore compiled but failed to link against such a wolfSSL, with undefined references to both symbols. It now calls recv and send directly and translates errno itself: EINTR retries, EAGAIN/EWOULDBLOCK map to the caller's WANT_READ or WANT_WRITE, ECONNRESET and EPIPE to CONN_CLOSED. That covers a superset of what TranslateIoReturnCode reported, and lets the file drop its wolfssl/wolfio.h and wolfssl/error-ssl.h includes.
1 parent 0f8185e commit 31df8f3

5 files changed

Lines changed: 100 additions & 46 deletions

File tree

docs/ARCHITECTURE.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,10 @@ The contract:
443443
something different from `connect`'s. wolfCert passes only two values.
444444
`0` asks the call never to block: return `WOLFCERT_ERR_WANT_READ` or
445445
`WOLFCERT_ERR_WANT_WRITE` rather than wait. `-1` asks it to block until
446-
bytes move.
446+
bytes move. If your stack has its own receive or send timeout, implement
447+
`-1` with a call that lets it apply, rather than an unbounded wait around a
448+
non-blocking transfer: the second shape silently discards whatever the
449+
application configured.
447450
- **`disconnect` runs exactly once per successful `connect`**, on every error
448451
path included. A failed `connect` is never paired with one.
449452
- **`ctx` is transport-wide** (the stack instance, say), distinct from the

src/http.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,8 @@ static int dial(WolfCertConn* c, const char* host, int port, int timeout_ms,
341341
#else
342342
if (t == NULL && connect_cb != NULL) {
343343
rc = wolfcert_legacy_connect(connect_cb, connect_ctx, host, port,
344-
timeout_ms, &c->handle);
344+
timeout_ms, c->io_timeout_ms == 0,
345+
&c->handle);
345346
if (rc != WOLFCERT_OK)
346347
return rc;
347348

src/internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ extern const WolfCertTransport wolfcert_legacy_transport;
318318
int wolfcert_transport_is_fd_backed(const WolfCertTransport* t);
319319
int wolfcert_legacy_connect(WolfCertConnectFn cb, void* cb_ctx,
320320
const char* host, int port, int timeout_ms,
321-
void** conn);
321+
int nonblocking, void** conn);
322322

323323
int wolfcert_pem_cert_to_der(const uint8_t* pem, size_t pem_len,
324324
WolfCertBuffer* out_der, void* heap);

src/net_posix.c

Lines changed: 91 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@
3131
#include <wolfcert/errors.h>
3232
#include "internal.h"
3333

34-
#include <wolfssl/wolfio.h>
35-
#include <wolfssl/error-ssl.h>
36-
3734
#include <errno.h>
3835
#include <limits.h>
3936
#include <fcntl.h>
@@ -183,26 +180,13 @@ static int posix_wait(int fd, short events, int timeout_ms, int want)
183180
return WOLFCERT_OK;
184181
}
185182

186-
/* wolfIO_* return CBIO codes, which carry no direction: WANT_READ and
187-
* WANT_WRITE are the same value, so the caller supplies `want`. */
188-
static int map_io(int n, int want)
189-
{
190-
if (n > 0)
191-
return n;
192-
/* wolfSSL passes a 0-length read straight through, so map it here. */
193-
if (n == 0)
194-
return WOLFCERT_ERR_CONN_CLOSED;
195-
196-
switch (n) {
197-
case WOLFSSL_CBIO_ERR_WANT_READ: /* == WANT_WRITE */
198-
return want;
199-
case WOLFSSL_CBIO_ERR_CONN_CLOSE:
200-
case WOLFSSL_CBIO_ERR_CONN_RST:
201-
return WOLFCERT_ERR_CONN_CLOSED;
202-
default:
203-
return WOLFCERT_ERR_IO;
204-
}
205-
}
183+
/* A failed transfer is an I/O error unless it merely would block, so this is
184+
* the one errno the byte path reads. */
185+
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
186+
#define WOLFCERT_WOULDBLOCK(e) ((e) == EAGAIN || (e) == EWOULDBLOCK)
187+
#else
188+
#define WOLFCERT_WOULDBLOCK(e) ((e) == EAGAIN)
189+
#endif
206190

207191
/* poll() only promises that one byte can move, so the transfer must never
208192
* block; the wait is poll's job. Sockets the transport owns stay O_NONBLOCK. */
@@ -242,8 +226,8 @@ static int posix_read(void* ctx, void* conn, uint8_t* buf, size_t len,
242226
int timeout_ms)
243227
{
244228
int fd = (int)(intptr_t)conn;
229+
ssize_t n;
245230
int rc;
246-
int n;
247231

248232
(void)ctx;
249233

@@ -257,24 +241,30 @@ static int posix_read(void* ctx, void* conn, uint8_t* buf, size_t len,
257241
if (rc != WOLFCERT_OK)
258242
return rc;
259243

260-
/* TranslateIoReturnCode reports EINTR rather than retrying. */
261244
do {
262-
n = wolfIO_Recv(fd, (char*)buf, (int)len, 0);
263-
} while (n == WOLFSSL_CBIO_ERR_ISR);
245+
n = recv(fd, buf, len, 0);
246+
} while (n < 0 && errno == EINTR);
264247

265-
if (n != WOLFSSL_CBIO_ERR_WANT_READ || timeout_ms >= 0)
266-
break;
267-
}
248+
if (n > 0)
249+
return (int)n;
250+
if (n == 0)
251+
return WOLFCERT_ERR_CONN_CLOSED;
268252

269-
return map_io(n, WOLFCERT_ERR_WANT_READ);
253+
/* poll() can report a readiness the transfer then declines. Only an
254+
* unbounded caller waits again; the others report it. */
255+
if (!WOLFCERT_WOULDBLOCK(errno))
256+
return WOLFCERT_ERR_IO;
257+
if (timeout_ms >= 0)
258+
return WOLFCERT_ERR_WANT_READ;
259+
}
270260
}
271261

272262
static int posix_write(void* ctx, void* conn, const uint8_t* buf, size_t len,
273263
int timeout_ms)
274264
{
275265
int fd = (int)(intptr_t)conn;
266+
ssize_t n;
276267
int rc;
277-
int n;
278268

279269
(void)ctx;
280270

@@ -289,14 +279,19 @@ static int posix_write(void* ctx, void* conn, const uint8_t* buf, size_t len,
289279
return rc;
290280

291281
do {
292-
n = wolfIO_Send(fd, (char*)(uintptr_t)buf, (int)len, 0);
293-
} while (n == WOLFSSL_CBIO_ERR_ISR);
282+
n = send(fd, buf, len, 0);
283+
} while (n < 0 && errno == EINTR);
294284

295-
if (n != WOLFSSL_CBIO_ERR_WANT_WRITE || timeout_ms >= 0)
296-
break;
297-
}
285+
if (n > 0)
286+
return (int)n;
287+
if (n == 0)
288+
return WOLFCERT_ERR_IO;
298289

299-
return map_io(n, WOLFCERT_ERR_WANT_WRITE);
290+
if (!WOLFCERT_WOULDBLOCK(errno))
291+
return WOLFCERT_ERR_IO;
292+
if (timeout_ms >= 0)
293+
return WOLFCERT_ERR_WANT_WRITE;
294+
}
300295
}
301296

302297
static int posix_disconnect(void* ctx, void* conn)
@@ -314,10 +309,11 @@ const WolfCertTransport wolfcert_posix_transport = {
314309
};
315310

316311
/* Dial through the deprecated connect_cb, keeping every fd detail in this file.
317-
* The descriptor becomes ours, so it gets the O_NONBLOCK posix_connect sets. */
312+
* The descriptor belongs to the application, so only a non-blocking session
313+
* changes its mode; a blocking one leaves it exactly as supplied. */
318314
int wolfcert_legacy_connect(WolfCertConnectFn cb, void* cb_ctx,
319315
const char* host, int port, int timeout_ms,
320-
void** conn)
316+
int nonblocking, void** conn)
321317
{
322318
int fd;
323319

@@ -328,7 +324,7 @@ int wolfcert_legacy_connect(WolfCertConnectFn cb, void* cb_ctx,
328324
if (fd < 0)
329325
return WOLFCERT_ERR_IO;
330326

331-
if (set_nonblock(fd) != WOLFCERT_OK) {
327+
if (nonblocking && set_nonblock(fd) != WOLFCERT_OK) {
332328
(void)close(fd);
333329
return WOLFCERT_ERR_IO;
334330
}
@@ -338,8 +334,61 @@ int wolfcert_legacy_connect(WolfCertConnectFn cb, void* cb_ctx,
338334
}
339335

340336
/* Byte path for a connection opened by wolfcert_legacy_connect. */
337+
static int legacy_read(void* ctx, void* conn, uint8_t* buf, size_t len,
338+
int timeout_ms)
339+
{
340+
int fd = (int)(intptr_t)conn;
341+
ssize_t n;
342+
343+
if (timeout_ms >= 0)
344+
return posix_read(ctx, conn, buf, len, timeout_ms);
345+
346+
if (buf == NULL || len == 0)
347+
return WOLFCERT_ERR_BAD_ARG;
348+
if (len > INT_MAX)
349+
len = INT_MAX;
350+
351+
do {
352+
n = recv(fd, buf, len, 0);
353+
} while (n < 0 && errno == EINTR);
354+
355+
if (n > 0)
356+
return (int)n;
357+
if (n == 0)
358+
return WOLFCERT_ERR_CONN_CLOSED;
359+
360+
/* A would-block here is the descriptor's own timeout expiring. */
361+
return WOLFCERT_ERR_IO;
362+
}
363+
364+
static int legacy_write(void* ctx, void* conn, const uint8_t* buf, size_t len,
365+
int timeout_ms)
366+
{
367+
int fd = (int)(intptr_t)conn;
368+
ssize_t n;
369+
370+
if (timeout_ms >= 0)
371+
return posix_write(ctx, conn, buf, len, timeout_ms);
372+
373+
if (buf == NULL || len == 0)
374+
return WOLFCERT_ERR_BAD_ARG;
375+
if (len > INT_MAX)
376+
len = INT_MAX;
377+
378+
do {
379+
n = send(fd, buf, len, 0);
380+
} while (n < 0 && errno == EINTR);
381+
382+
if (n > 0)
383+
return (int)n;
384+
if (n == 0)
385+
return WOLFCERT_ERR_IO;
386+
387+
return WOLFCERT_ERR_IO;
388+
}
389+
341390
const WolfCertTransport wolfcert_legacy_transport = {
342-
NULL, posix_read, posix_write, posix_disconnect, NULL
391+
NULL, legacy_read, legacy_write, posix_disconnect, NULL
343392
};
344393

345394
int wolfcert_transport_is_fd_backed(const WolfCertTransport* t)

wolfcert/types.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ typedef enum {
6464
} WolfCertEncoding;
6565

6666
/* Deprecated: use WolfCertTransport, never both on one config (BAD_ARG). An
67-
* fd cannot carry a non-socket handle, which is why this is going away. */
67+
* fd cannot carry a non-socket handle, which is why this is going away.
68+
* Return it blocking; its own SO_RCVTIMEO / SO_SNDTIMEO then bound the I/O. */
6869
typedef int (*WolfCertConnectFn)(const char* host, int port,
6970
int timeout_ms, void* ctx);
7071

0 commit comments

Comments
 (0)