diff --git a/.pubnub.yml b/.pubnub.yml index eaa5b3b1..acd61929 100644 --- a/.pubnub.yml +++ b/.pubnub.yml @@ -1,8 +1,13 @@ name: c-core schema: 1 -version: "5.3.1" +version: "5.3.2" scm: github.com/pubnub/c-core changelog: + - date: 2025-09-23 + version: v5.3.2 + changes: + - type: bug + text: "Fix the issue because of which `poll` always returned immediately without waiting for the actual event (TLS handshake flow uses proper watcher now)." - date: 2025-09-17 version: v5.3.1 changes: @@ -1031,7 +1036,7 @@ sdks: distribution-type: source code distribution-repository: GitHub release package-name: C-Core - location: https://github.com/pubnub/c-core/releases/tag/v5.3.1 + location: https://github.com/pubnub/c-core/releases/tag/v5.3.2 requires: - name: "miniz" @@ -1097,7 +1102,7 @@ sdks: distribution-type: source code distribution-repository: GitHub release package-name: C-Core - location: https://github.com/pubnub/c-core/releases/tag/v5.3.1 + location: https://github.com/pubnub/c-core/releases/tag/v5.3.2 requires: - name: "miniz" @@ -1163,7 +1168,7 @@ sdks: distribution-type: source code distribution-repository: GitHub release package-name: C-Core - location: https://github.com/pubnub/c-core/releases/tag/v5.3.1 + location: https://github.com/pubnub/c-core/releases/tag/v5.3.2 requires: - name: "miniz" @@ -1225,7 +1230,7 @@ sdks: distribution-type: source code distribution-repository: GitHub release package-name: C-Core - location: https://github.com/pubnub/c-core/releases/tag/v5.3.1 + location: https://github.com/pubnub/c-core/releases/tag/v5.3.2 requires: - name: "miniz" @@ -1286,7 +1291,7 @@ sdks: distribution-type: source code distribution-repository: GitHub release package-name: C-Core - location: https://github.com/pubnub/c-core/releases/tag/v5.3.1 + location: https://github.com/pubnub/c-core/releases/tag/v5.3.2 requires: - name: "miniz" @@ -1342,7 +1347,7 @@ sdks: distribution-type: source code distribution-repository: GitHub release package-name: C-Core - location: https://github.com/pubnub/c-core/releases/tag/v5.3.1 + location: https://github.com/pubnub/c-core/releases/tag/v5.3.2 requires: - name: "miniz" @@ -1395,7 +1400,7 @@ sdks: distribution-type: source code distribution-repository: GitHub release package-name: C-Core - location: https://github.com/pubnub/c-core/releases/tag/v5.3.1 + location: https://github.com/pubnub/c-core/releases/tag/v5.3.2 requires: - name: "miniz" diff --git a/CHANGELOG.md b/CHANGELOG.md index 86828f01..f6421db1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v5.3.2 +September 23 2025 + +#### Fixed +- Fix the issue because of which `poll` always returned immediately without waiting for the actual event (TLS handshake flow uses proper watcher now). + ## v5.3.1 September 17 2025 diff --git a/core/pbpal.h b/core/pbpal.h index c4384282..8e2247fa 100644 --- a/core/pbpal.h +++ b/core/pbpal.h @@ -37,13 +37,15 @@ enum pbpal_resolv_n_connect_result { enum pbpal_tls_result { pbtlsEstablished, pbtlsStarted, + pbtlsStartedWaitRead, + pbtlsStartedWaitWrite, pbtlsInProgress, pbtlsResourceFailure, pbtlsFailed }; /* Handles socket condition on given platform */ -enum pubnub_res pbpal_handle_socket_condition(int result, pubnub_t* pb, char const* file, int line); +enum pubnub_res pbpal_handle_socket_condition(int result, pubnub_t* pb, char const* file, int line, bool *needRead, bool* needWrite); /** Handles start of a TCP (HTTP) connection. It first handles DNS resolving for the context @p pb. If DNS is already resolved, it diff --git a/core/pubnub_netcore.c b/core/pubnub_netcore.c index ba8ad429..098f9828 100644 --- a/core/pubnub_netcore.c +++ b/core/pubnub_netcore.c @@ -723,7 +723,11 @@ int pbnc_fsm(struct pubnub_* pb) case pbtlsEstablished: break; case pbtlsStarted: + case pbtlsStartedWaitRead: + case pbtlsStartedWaitWrite: pb->state = PBS_WAIT_TLS_CONNECT; + if (pbtlsStartedWaitWrite == res) pbntf_watch_out_events(pb); + if (pbtlsStartedWaitRead == res) pbntf_watch_in_events(pb); return 0; case pbtlsFailed: if (pb->options.fallbackSSL) { @@ -770,6 +774,8 @@ int pbnc_fsm(struct pubnub_* pb) pb->state = PBS_TX_GET; goto next_state; case pbtlsStarted: + case pbtlsStartedWaitRead: + case pbtlsStartedWaitWrite: break; case pbtlsFailed: if (pb->options.fallbackSSL) { diff --git a/core/pubnub_version_internal.h b/core/pubnub_version_internal.h index 70ba9e50..ee08a47c 100644 --- a/core/pubnub_version_internal.h +++ b/core/pubnub_version_internal.h @@ -3,7 +3,7 @@ #define INC_PUBNUB_VERSION_INTERNAL -#define PUBNUB_SDK_VERSION "5.3.1" +#define PUBNUB_SDK_VERSION "5.3.2" #endif /* !defined INC_PUBNUB_VERSION_INTERNAL */ diff --git a/core/samples/pubnub_sync_sample.c b/core/samples/pubnub_sync_sample.c index de1aa56d..0487edde 100644 --- a/core/samples/pubnub_sync_sample.c +++ b/core/samples/pubnub_sync_sample.c @@ -140,11 +140,6 @@ subscribe_thr(void *pn_sub_addr) int main() { -#if defined _WIN32 - uintptr_t sub_thread; -#else - pthread_t sub_thread; -#endif time_t t0; char const* msg; enum pubnub_res res; @@ -169,19 +164,6 @@ int main() pubnub_set_auth(pbp, "danaske"); -#if defined _WIN32 - sub_thread = _beginthread(subscribe_thr, 0, pbp); -#else - pthread_create(&sub_thread, NULL, subscribe_thr, pbp); -#endif - puts("Lets go sleeping..."); - sleep(4); - puts("Done sleeping. Cancelling subscribe long-poll..."); - pubnub_cancel(pbp); - sleep(2); - printf("What we have: %s\n", pubnub_res_2_string(pubnub_last_result(pbp))); - return 0; - puts("Publishing..."); time(&t0); res = pubnub_publish(pbp, chan, "\"Hello world from sync!\""); diff --git a/lib/sockets/pbpal_resolv_and_connect_sockets.c b/lib/sockets/pbpal_resolv_and_connect_sockets.c index 92801443..97a89f83 100644 --- a/lib/sockets/pbpal_resolv_and_connect_sockets.c +++ b/lib/sockets/pbpal_resolv_and_connect_sockets.c @@ -420,10 +420,12 @@ enum pbpal_resolv_n_connect_result pbpal_resolv_and_connect(pubnub_t* pb) #endif #ifdef PUBNUB_CALLBACK_API sockaddr_inX_t dest = { 0 }; +#if PUBNUB_PROXY_API #if PUBNUB_USE_IPV6 const bool has_ipv6_proxy = 0 != pb->proxy_ipv6_address.ipv6[0] || 0 != pb->proxy_ipv6_address.ipv6[1]; #endif /* PUBNUB_USE_IPV6 */ +#endif /* PUBNUB_PROXY_API */ prepare_port_and_hostname(pb, &port, &origin); #if PUBNUB_PROXY_API diff --git a/mbedtls/pbpal_connect_mbedtls.c b/mbedtls/pbpal_connect_mbedtls.c index c9df3429..d98714f9 100644 --- a/mbedtls/pbpal_connect_mbedtls.c +++ b/mbedtls/pbpal_connect_mbedtls.c @@ -174,11 +174,13 @@ enum pbpal_tls_result pbpal_check_tls(pubnub_t* pb) { PUBNUB_ASSERT_OPT(PBS_CONNECTED == pb->state); PUBNUB_LOG_TRACE("pbpal_check_tls(pb=%p)\n", pb); + bool needRead = false, needWrite = false; result = mbedtls_ssl_handshake(pb->pal.ssl); - if (PNR_OK != (result = pbpal_handle_socket_condition(result, pb, __FILE__, __LINE__))) { + if (PNR_OK != (result = pbpal_handle_socket_condition(result, pb, __FILE__, __LINE__, &needRead, &needWrite))) { PUBNUB_LOG_TRACE("pbpal_check_tls(pb=%p) result = %d\n", pb, result); - return (result == PNR_IN_PROGRESS) ? pbtlsStarted : pbtlsFailed; + if (result != PNR_IN_PROGRESS) return pbtlsFailed; + return needRead ? pbtlsStartedWaitRead : needWrite ? pbtlsStartedWaitWrite : pbtlsStarted; } PUBNUB_LOG_DEBUG("TLS connection established\n"); diff --git a/mbedtls/pbpal_mbedtls.c b/mbedtls/pbpal_mbedtls.c index f524ac3c..e62197ef 100644 --- a/mbedtls/pbpal_mbedtls.c +++ b/mbedtls/pbpal_mbedtls.c @@ -63,7 +63,7 @@ int pbpal_send_str(pubnub_t* pb, char const* s) } -enum pubnub_res pbpal_handle_socket_condition(int result, pubnub_t* pb, char const* file, int line) +enum pubnub_res pbpal_handle_socket_condition(int result, pubnub_t* pb, char const* file, int line, bool *needRead, bool* needWrite) { char reason[100] = {0}; @@ -83,6 +83,10 @@ enum pubnub_res pbpal_handle_socket_condition(int result, pubnub_t* pb, char con if (pbms_active(pb->pal.connection_timer) || (pbms_elapsed(pb->pal.connection_timer) < pb->transaction_timeout_ms)) { PUBNUB_LOG_TRACE("pb=%p TLS/SSL_I/O operation should retry\n", pb); + + if (needWrite && MBEDTLS_ERR_SSL_WANT_WRITE == result) *needWrite = true; + if (needRead && MBEDTLS_ERR_SSL_WANT_READ == result) *needRead = true; + return PNR_IN_PROGRESS; } @@ -132,7 +136,7 @@ int pbpal_send_status(pubnub_t* pb) PUBNUB_LOG_TRACE("will write..."); if (0 >= (result = mbedtls_ssl_write(pb->pal.ssl, pb->ptr, pb->len))) { - result = pbpal_handle_socket_condition(result, pb, __FILE__, __LINE__); + result = pbpal_handle_socket_condition(result, pb, __FILE__, __LINE__, NULL, NULL); } else { PUBNUB_ASSERT_OPT((unsigned)result <= pb->len); pb->ptr += result; @@ -189,7 +193,7 @@ enum pubnub_res pbpal_line_read_status(pubnub_t* pb) int result = mbedtls_ssl_read(pb->pal.ssl, pb->ptr, pb->left); if (result <= 0) { - return pbpal_handle_socket_condition(result, pb, __FILE__, __LINE__); + return pbpal_handle_socket_condition(result, pb, __FILE__, __LINE__, NULL, NULL); } PUBNUB_ASSERT_OPT(result <= pb->left); @@ -293,7 +297,7 @@ enum pubnub_res pbpal_read_status(pubnub_t* pb) have_read = mbedtls_ssl_read(pb->pal.ssl, pb->ptr, to_read); if (have_read <= 0) { - return pbpal_handle_socket_condition(have_read, pb, __FILE__, __LINE__); + return pbpal_handle_socket_condition(have_read, pb, __FILE__, __LINE__, NULL, NULL); } PUBNUB_ASSERT_OPT(pb->left >= have_read); diff --git a/openssl/pbpal_connect_openssl.c b/openssl/pbpal_connect_openssl.c index 8109bd78..508d2095 100644 --- a/openssl/pbpal_connect_openssl.c +++ b/openssl/pbpal_connect_openssl.c @@ -44,6 +44,8 @@ static int print_to_pubnub_log(const char* s, size_t len, void* p) /* Starfields Inc (Class 2) Root certificate. It was used to sign the server certificate of https://pubsub.pubnub.com. (at the time of writing this, 2015-06-04). + + Valid to: June 29, 2034 */ static char pubnub_cert_Starfield[] = "-----BEGIN CERTIFICATE-----\n" @@ -78,6 +80,7 @@ static char pubnub_cert_Starfield[] = 2 s:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA + Valid to: January 28, 2028 */ static char pubnub_cert_GlobalSign[] = "-----BEGIN CERTIFICATE-----\n" @@ -231,10 +234,12 @@ enum pbpal_tls_result pbpal_check_tls(pubnub_t* pb) ssl = pb->pal.ssl; PUBNUB_ASSERT(NULL != ssl); + bool needRead = false, needWrite = false; rslt = SSL_connect(ssl); - rslt = pbpal_handle_socket_condition(rslt, pb, __FILE__, __LINE__); + rslt = pbpal_handle_socket_condition(rslt, pb, __FILE__, __LINE__, &needRead, &needWrite); if (PNR_OK != rslt) { - return (rslt == PNR_IN_PROGRESS) ? pbtlsStarted : pbtlsFailed; + if (rslt != PNR_IN_PROGRESS) return pbtlsFailed; + return needRead ? pbtlsStartedWaitRead : needWrite ? pbtlsStartedWaitWrite : pbtlsStarted; } PUBNUB_LOG_TRACE("pb=%p: SSL connected\n", pb); socket_set_rcv_timeout(pb->pal.socket, pb->transaction_timeout_ms); diff --git a/openssl/pbpal_openssl.c b/openssl/pbpal_openssl.c index 24d2b556..fe448a9d 100644 --- a/openssl/pbpal_openssl.c +++ b/openssl/pbpal_openssl.c @@ -180,7 +180,7 @@ int pbpal_send_str(pubnub_t* pb, char const* s) } -enum pubnub_res pbpal_handle_socket_condition(int result, pubnub_t* pb, char const* file, int line) +enum pubnub_res pbpal_handle_socket_condition(int result, pubnub_t* pb, char const* file, int line, bool *needRead, bool* needWrite) { SSL* ssl = pb->pal.ssl; @@ -202,6 +202,9 @@ enum pubnub_res pbpal_handle_socket_condition(int result, pubnub_t* pb, char con || (pbms_elapsed(pb->pal.tryconn) < pb->transaction_timeout_ms)) { PUBNUB_LOG_TRACE("pb=%p: TLS/SSL_I/O operation should retry, error=%d\n", pb, error); + if (needWrite && SSL_ERROR_WANT_WRITE == error) *needWrite = true; + if (needRead && SSL_ERROR_WANT_READ == error) *needRead = true; + return PNR_IN_PROGRESS; } else { @@ -258,8 +261,7 @@ int pbpal_send_status(pubnub_t* pb) rslt = SSL_write(ssl, pb->ptr, pb->len); } if (rslt <= 0) { - rslt = (pbpal_handle_socket_condition(rslt, pb, __FILE__, __LINE__) == PNR_IN_PROGRESS) ? +1 - : -1; + rslt = (pbpal_handle_socket_condition(rslt, pb, __FILE__, __LINE__, NULL, NULL) == PNR_IN_PROGRESS) ? +1 : -1; } else { PUBNUB_ASSERT_OPT((unsigned)rslt <= pb->len); @@ -323,7 +325,7 @@ enum pubnub_res pbpal_line_read_status(pubnub_t* pb) recvres = SSL_read(ssl, (char*)pb->ptr, pb->left); } if (recvres <= 0) { - return pbpal_handle_socket_condition(recvres, pb, __FILE__, __LINE__); + return pbpal_handle_socket_condition(recvres, pb, __FILE__, __LINE__, NULL, NULL); } PUBNUB_ASSERT_OPT(recvres <= pb->left); @@ -424,7 +426,7 @@ enum pubnub_res pbpal_read_status(pubnub_t* pb) have_read = SSL_read(ssl, pb->ptr, to_recv); } if (have_read <= 0) { - return pbpal_handle_socket_condition(have_read, pb, __FILE__, __LINE__); + return pbpal_handle_socket_condition(have_read, pb, __FILE__, __LINE__, NULL, NULL); } PUBNUB_ASSERT_OPT(pb->left >= have_read); pb->left -= have_read;