hxcpp
created pr with
hxcpp/ssl-short-read.1
added hxcpp/ssl-short-read.2
1: d70d1ca < -: ------- SSL read/write needs to return wouldblock if partial read
-: ------- > 1: dd64130 SSL read/write needs to return wouldblock if partial read
2: af61d88 = 2: d3fe10a Throw exceptions for more error codes
3: 124b85a = 3: 6f33bf1 Retry handshake on would block
4: e8e22fe = 4: 5a504b4 Include whole erorr message in exception
cmds
checkout latest patchset:
ssh pr.pico.sh pull hxcpp:ssl-short-read | git am -3checkout specific patchset revision:
ssh pr.pico.sh pull hxcpp:ssl-short-read [rev] | git am -3add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh hxcpp:ssl-short-readadd comment to patch request:
ssh pr.pico.sh comment hxcpp:ssl-short-read "lgtm!"
Patchset
hxcpp/ssl-short-read.1
→ SSL read/write needs to return wouldblock if partial read
Stephen Paul Weber
Throw exceptions for more error codes
2026-10-27T21:17:55ZStephen Paul Weber
Retry handshake on would block
2026-10-27T21:18:19ZStephen Paul Weber
Include whole erorr message in exception
2026-10-27T21:18:51ZStephen Paul Weber
2026-10-27T21:19:11Z
SSL read/write needs to return wouldblock if partial read
Stephen Paul Weber
2026-10-27T21:17:55ZSemantic diff summary
0 added,
0 modified,
0 signature changed,
0 removed
across 0 analyzed files
(1 file skipped: unsupported file type)
+7
-50
Sources/c_borogove/src/hx/libs/ssl/SSL.cpp
#
| ... | ... | @@ -109,16 +109,21 @@ void _hx_ssl_close(Dynamic hssl) { | |
| 109 | 109 | ||
| 110 | 110 | static OSStatus socket_read(SSLConnectionRef conn, void *data, size_t *len) { | |
| 111 | 111 | int fd = (int)(intptr_t)conn; | |
| 112 | + | size_t requested = *len; | |
| 112 | 113 | ssize_t ret = recv(fd, data, *len, 0); | |
| 113 | - | if (ret > 0) { *len = ret; return noErr; } | |
| 114 | + | if (ret > 0) { *len = ret; return ret < requested ? errSSLWouldBlock : noErr; } | |
| 115 | + | *len = 0; | |
| 114 | 116 | if (ret == 0) return errSSLClosedGraceful; | |
| 115 | 117 | if (errno == EAGAIN || errno == EWOULDBLOCK) return errSSLWouldBlock; | |
| 116 | 118 | return errSecIO; | |
| 117 | 119 | } | |
| 120 | + | ||
| 118 | 121 | static OSStatus socket_write(SSLConnectionRef conn, const void *data, size_t *len) { | |
| 119 | 122 | int fd = (int)(intptr_t)conn; | |
| 123 | + | size_t requested = *len; | |
| 120 | 124 | ssize_t ret = send(fd, data, *len, 0); | |
| 121 | - | if (ret > 0) { *len = ret; return noErr; } | |
| 125 | + | if (ret >= 0) { *len = ret; return ret < requested ? errSSLWouldBlock : noErr; } | |
| 126 | + | *len = 0; | |
| 122 | 127 | if (errno == EAGAIN || errno == EWOULDBLOCK) return errSSLWouldBlock; | |
| 123 | 128 | return errSecIO; | |
| 124 | 129 | } |
| ... | ... | @@ -617,50 +622,6 @@ Array<unsigned char> _hx_ssl_read( Dynamic hssl ) { | |
| 617 | 622 | return result; | |
| 618 | 623 | } | |
| 619 | 624 | ||
| 620 | - | #ifdef NEKO_WINDOWS | |
| 621 | - | static int verify_callback(void* param, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { | |
| 622 | - | if (*flags == 0 || *flags & MBEDTLS_X509_BADCERT_CN_MISMATCH) { | |
| 623 | - | return 0; | |
| 624 | - | } | |
| 625 | - | ||
| 626 | - | HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL); | |
| 627 | - | if(store == NULL) { | |
| 628 | - | return MBEDTLS_ERR_X509_FATAL_ERROR; | |
| 629 | - | } | |
| 630 | - | PCCERT_CONTEXT primary_context = {0}; | |
| 631 | - | if(!CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, crt->raw.p, crt->raw.len, CERT_STORE_ADD_REPLACE_EXISTING, &primary_context)) { | |
| 632 | - | CertCloseStore(store, 0); | |
| 633 | - | return MBEDTLS_ERR_X509_FATAL_ERROR; | |
| 634 | - | } | |
| 635 | - | PCCERT_CHAIN_CONTEXT chain_context = {0}; | |
| 636 | - | CERT_CHAIN_PARA parameters = {0}; | |
| 637 | - | if(!CertGetCertificateChain(NULL, primary_context, NULL, store, ¶meters, 0, NULL, &chain_context)) { | |
| 638 | - | CertFreeCertificateContext(primary_context); | |
| 639 | - | CertCloseStore(store, 0); | |
| 640 | - | return MBEDTLS_ERR_X509_FATAL_ERROR; | |
| 641 | - | } | |
| 642 | - | CERT_CHAIN_POLICY_PARA policy_parameters = {0}; | |
| 643 | - | CERT_CHAIN_POLICY_STATUS policy_status = {0}; | |
| 644 | - | if(!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, chain_context, &policy_parameters, &policy_status)) { | |
| 645 | - | CertFreeCertificateChain(chain_context); | |
| 646 | - | CertFreeCertificateContext(primary_context); | |
| 647 | - | CertCloseStore(store, 0); | |
| 648 | - | return MBEDTLS_ERR_X509_FATAL_ERROR; | |
| 649 | - | } | |
| 650 | - | if(policy_status.dwError == 0) { | |
| 651 | - | *flags = 0; | |
| 652 | - | } else { | |
| 653 | - | // if we ever want to read the verification result, | |
| 654 | - | // we need to properly map dwError to flags | |
| 655 | - | *flags |= MBEDTLS_X509_BADCERT_OTHER; | |
| 656 | - | } | |
| 657 | - | CertFreeCertificateChain(chain_context); | |
| 658 | - | CertFreeCertificateContext(primary_context); | |
| 659 | - | CertCloseStore(store, 0); | |
| 660 | - | return 0; | |
| 661 | - | } | |
| 662 | - | #endif | |
| 663 | - | ||
| 664 | 625 | Dynamic _hx_ssl_conf_new( bool server ) { | |
| 665 | 626 | int ret; | |
| 666 | 627 | sslconf *conf = new sslconf(); |
| ... | ... | @@ -671,9 +632,6 @@ Dynamic _hx_ssl_conf_new( bool server ) { | |
| 671 | 632 | conf->destroy(); | |
| 672 | 633 | ssl_error( ret ); | |
| 673 | 634 | } | |
| 674 | - | #ifdef NEKO_WINDOWS | |
| 675 | - | mbedtls_ssl_conf_verify(conf->c, verify_callback, NULL); | |
| 676 | - | #endif | |
| 677 | 635 | mbedtls_ssl_conf_rng( conf->c, mbedtls_ctr_drbg_random, &ctr_drbg ); | |
| 678 | 636 | return conf; | |
| 679 | 637 | } |