From de4059a9ca07399935fece522cb2786c7c84bb75 Mon Sep 17 00:00:00 2001 From: Nuno Luz Date: Sat, 21 Nov 2020 15:41:06 +0000 Subject: [PATCH 1/5] qt transport --- include/sentry.h | 25 +++++ src/CMakeLists.txt | 1 + src/transports/sentry_transport_qt.c | 139 +++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 src/transports/sentry_transport_qt.c diff --git a/include/sentry.h b/include/sentry.h index 93baaef63..c10f40dd6 100644 --- a/include/sentry.h +++ b/include/sentry.h @@ -595,6 +595,31 @@ SENTRY_API void sentry_transport_free(sentry_transport_t *transport); SENTRY_API sentry_transport_t *sentry_new_function_transport( void (*func)(const sentry_envelope_t *envelope, void *data), void *data); +/** + * Create a new function transport tailored for QT usage (it abstracts the + * interface from sentry data structures). Unlike the function transport, this + * handles the rate_limiter and retry_after implementation. + * + * It is a convenience function which works with a borrowed `data`, and will + * automatically free the envelope, so the user provided function does not need + * to do that. + * + * This function assumes requests are async. Upon receiving the response, the + * `sentry_qt_transport_process_response` must be called with the appropriate + * response data. + */ +SENTRY_API sentry_transport_t *sentry_new_qt_transport( + void (*func)( + const char *url, const char *body, const char *headers, void *data), + void *data); + +/** + * To be used to report responses to the QT transport. + * Pass the values of response headers: retry-after and x-sentry-rate-limits + **/ +void sentry_qt_transport_process_response( + sentry_transport_t *transport, char *rate_limits, char *retry_after); + /* -- Options APIs -- */ /** diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 70505656e..2b52ddedd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,6 +44,7 @@ sentry_target_sources_cwd(sentry transports/sentry_disk_transport.c transports/sentry_disk_transport.h transports/sentry_function_transport.c + transports/sentry_transport_qt.c unwinder/sentry_unwinder.c ) diff --git a/src/transports/sentry_transport_qt.c b/src/transports/sentry_transport_qt.c new file mode 100644 index 000000000..48110383a --- /dev/null +++ b/src/transports/sentry_transport_qt.c @@ -0,0 +1,139 @@ +#include "sentry_alloc.h" +#include "sentry_core.h" +#include "sentry_database.h" +#include "sentry_envelope.h" +#include "sentry_options.h" +#include "sentry_ratelimiter.h" +#include "sentry_string.h" +#include "sentry_sync.h" +#include "sentry_transport.h" +#include "sentry_utils.h" + +#include +#include + +typedef struct qt_transport_state_s { + sentry_dsn_t *dsn; + sentry_rate_limiter_t *ratelimiter; + void (*func)(const char *url, const char *body, const char *headers, void *data)); + void *data; + bool debug; +} qt_transport_state_t; + +static qt_transport_state_t * +sentry__qt_transport_state_new(void) +{ + qt_transport_state_t *state = SENTRY_MAKE(qt_transport_state_t); + if (!state) { + return NULL; + } + memset(state, 0, sizeof(qt_transport_state_t)); + + state->ratelimiter = sentry__rate_limiter_new(); + + return state; +} + +static void +sentry__qt_transport_state_free(void *_state) +{ + qt_transport_state_t *state = _state; + sentry__dsn_decref(state->dsn); + sentry__rate_limiter_free(state->ratelimiter); + sentry_free(state); +} + +static int +sentry__qt_transport_start( + const sentry_options_t *options, void *transport_state) +{ + qt_transport_state_t *state = sentry__qt_transport_state_new(); + + state->dsn = sentry__dsn_incref(options->dsn); + state->debug = options->debug; + + return 0; +} + +static int +sentry__qt_transport_shutdown(uint64_t timeout, void *transport_state) +{ +} + +static void +sentry__qt_transport_send_envelope(sentry_envelope_t *envelope, void *_state) +{ + qt_transport_state_t *state = (qt_transport_state_t *)_state; + + sentry_prepared_http_request_t *req = sentry__prepare_http_request( + envelope, state->dsn, state->ratelimiter); + if (!req) { + return; + } + + char buf[2048]; + buf[0] = '\0'; + for (size_t i = 0; i < req->headers_len; i++) { + if (i == 0) { + snprintf(buf, sizeof(buf), "%s:%s", req->headers[i].key, + req->headers[i].value); + } else { + snprintf(buf, sizeof(buf), "%s,%s:%s", buf, req->headers[i].key, + req->headers[i].value); + } + } + + state->func(req->url, req->body, buf, state->data); + + curl_slist_free_all(headers); + sentry_free(info.retry_after); + sentry_free(info.x_sentry_rate_limits); + sentry__prepared_http_request_free(req); +} + +void +sentry_qt_transport_process_response( + sentry_transport_t *transport, char *rate_limits, char *retry_after) +{ + if (!transport->running) { + return; + } + + qt_transport_state_t *state = (qt_transport_state_t *)transport->state; + + if (rate_limits) { + sentry__rate_limiter_update_from_header( + state->ratelimiter, rate_limits); + } else if (retry_after) { + sentry__rate_limiter_update_from_http_retry_after( + state->ratelimiter, retry_after); + } +} + +sentry_transport_t * +sentry_new_qt_transport(void (*func)(const char *url, const char *body, + const char *headers, void *data), + void *data) +{ + SENTRY_DEBUG("initializing qt transport"); + qt_transport_state_t *state = sentry__qt_transport_state_new(); + if (!state) { + return NULL; + } + state->func = func; + state->data = data; + + sentry_transport_t *transport + = sentry_transport_new(sentry__qt_transport_send_envelope); + if (!transport) { + sentry__qt_transport_state_free(state); + return NULL; + } + sentry_transport_set_state(transport, state); + sentry_transport_set_free_func(transport, sentry__qt_transport_state_free); + sentry_transport_set_startup_func(transport, sentry__qt_transport_start); + sentry_transport_set_shutdown_func( + transport, sentry__qt_transport_shutdown); + + return transport; +} From 7bb5c9ac14a5c64662b9fc68752c115fd2b12297 Mon Sep 17 00:00:00 2001 From: Nuno Luz Date: Sat, 21 Nov 2020 16:31:14 +0000 Subject: [PATCH 2/5] fix qt transport --- include/sentry.h | 6 +++--- src/transports/sentry_transport_qt.c | 26 ++++++++++++-------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/include/sentry.h b/include/sentry.h index c10f40dd6..65f871c39 100644 --- a/include/sentry.h +++ b/include/sentry.h @@ -609,8 +609,8 @@ SENTRY_API sentry_transport_t *sentry_new_function_transport( * response data. */ SENTRY_API sentry_transport_t *sentry_new_qt_transport( - void (*func)( - const char *url, const char *body, const char *headers, void *data), + void (*func)(const char *url, const char *body, const char *headers, + void *data, void *state), void *data); /** @@ -618,7 +618,7 @@ SENTRY_API sentry_transport_t *sentry_new_qt_transport( * Pass the values of response headers: retry-after and x-sentry-rate-limits **/ void sentry_qt_transport_process_response( - sentry_transport_t *transport, char *rate_limits, char *retry_after); + void *_state, char *rate_limits, char *retry_after); /* -- Options APIs -- */ diff --git a/src/transports/sentry_transport_qt.c b/src/transports/sentry_transport_qt.c index 48110383a..a15b16782 100644 --- a/src/transports/sentry_transport_qt.c +++ b/src/transports/sentry_transport_qt.c @@ -15,7 +15,8 @@ typedef struct qt_transport_state_s { sentry_dsn_t *dsn; sentry_rate_limiter_t *ratelimiter; - void (*func)(const char *url, const char *body, const char *headers, void *data)); + void (*func)(const char *url, const char *body, const char *headers, + void *data, void *state); void *data; bool debug; } qt_transport_state_t; @@ -47,7 +48,7 @@ static int sentry__qt_transport_start( const sentry_options_t *options, void *transport_state) { - qt_transport_state_t *state = sentry__qt_transport_state_new(); + qt_transport_state_t *state = (qt_transport_state_t *)transport_state; state->dsn = sentry__dsn_incref(options->dsn); state->debug = options->debug; @@ -56,8 +57,10 @@ sentry__qt_transport_start( } static int -sentry__qt_transport_shutdown(uint64_t timeout, void *transport_state) +sentry__qt_transport_shutdown( + uint64_t UNUSED(timeout), void *UNUSED(transport_state)) { + return 0; } static void @@ -68,6 +71,7 @@ sentry__qt_transport_send_envelope(sentry_envelope_t *envelope, void *_state) sentry_prepared_http_request_t *req = sentry__prepare_http_request( envelope, state->dsn, state->ratelimiter); if (!req) { + sentry_envelope_free(envelope); return; } @@ -83,23 +87,17 @@ sentry__qt_transport_send_envelope(sentry_envelope_t *envelope, void *_state) } } - state->func(req->url, req->body, buf, state->data); + state->func(req->url, req->body, buf, state->data, state); - curl_slist_free_all(headers); - sentry_free(info.retry_after); - sentry_free(info.x_sentry_rate_limits); sentry__prepared_http_request_free(req); + sentry_envelope_free(envelope); } void sentry_qt_transport_process_response( - sentry_transport_t *transport, char *rate_limits, char *retry_after) + void *_state, char *rate_limits, char *retry_after) { - if (!transport->running) { - return; - } - - qt_transport_state_t *state = (qt_transport_state_t *)transport->state; + qt_transport_state_t *state = (qt_transport_state_t *)_state; if (rate_limits) { sentry__rate_limiter_update_from_header( @@ -112,7 +110,7 @@ sentry_qt_transport_process_response( sentry_transport_t * sentry_new_qt_transport(void (*func)(const char *url, const char *body, - const char *headers, void *data), + const char *headers, void *data, void *state), void *data) { SENTRY_DEBUG("initializing qt transport"); From 50176a473068f84f931d180b04fbd06550121e52 Mon Sep 17 00:00:00 2001 From: Nuno Luz Date: Mon, 23 Nov 2020 09:11:29 +0000 Subject: [PATCH 3/5] separate headers by line break --- src/transports/sentry_transport_qt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transports/sentry_transport_qt.c b/src/transports/sentry_transport_qt.c index a15b16782..4019faa80 100644 --- a/src/transports/sentry_transport_qt.c +++ b/src/transports/sentry_transport_qt.c @@ -82,7 +82,7 @@ sentry__qt_transport_send_envelope(sentry_envelope_t *envelope, void *_state) snprintf(buf, sizeof(buf), "%s:%s", req->headers[i].key, req->headers[i].value); } else { - snprintf(buf, sizeof(buf), "%s,%s:%s", buf, req->headers[i].key, + snprintf(buf, sizeof(buf), "%s\n%s:%s", buf, req->headers[i].key, req->headers[i].value); } } From 899078a42227aaa067da638683020d7a1887c4ca Mon Sep 17 00:00:00 2001 From: Nuno Luz Date: Mon, 23 Nov 2020 15:58:06 +0000 Subject: [PATCH 4/5] pass body length --- src/transports/sentry_transport_qt.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/transports/sentry_transport_qt.c b/src/transports/sentry_transport_qt.c index 4019faa80..958c7e5b3 100644 --- a/src/transports/sentry_transport_qt.c +++ b/src/transports/sentry_transport_qt.c @@ -15,8 +15,8 @@ typedef struct qt_transport_state_s { sentry_dsn_t *dsn; sentry_rate_limiter_t *ratelimiter; - void (*func)(const char *url, const char *body, const char *headers, - void *data, void *state); + void (*func)(const char *url, const char *body, const long bodyLen, + const char *headers, void *data, void *state); void *data; bool debug; } qt_transport_state_t; @@ -87,7 +87,7 @@ sentry__qt_transport_send_envelope(sentry_envelope_t *envelope, void *_state) } } - state->func(req->url, req->body, buf, state->data, state); + state->func(req->url, req->body, req->body_len, buf, state->data, state); sentry__prepared_http_request_free(req); sentry_envelope_free(envelope); @@ -109,8 +109,9 @@ sentry_qt_transport_process_response( } sentry_transport_t * -sentry_new_qt_transport(void (*func)(const char *url, const char *body, - const char *headers, void *data, void *state), +sentry_new_qt_transport( + void (*func)(const char *url, const char *body, const long bodyLen, + const char *headers, void *data, void *state), void *data) { SENTRY_DEBUG("initializing qt transport"); From d84f6e881013833e6d39ec2a6595dc160d77a80a Mon Sep 17 00:00:00 2001 From: Nuno Luz Date: Mon, 23 Nov 2020 17:31:38 +0000 Subject: [PATCH 5/5] fix include file for qt transport --- include/sentry.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/sentry.h b/include/sentry.h index 65f871c39..d3c4da6d8 100644 --- a/include/sentry.h +++ b/include/sentry.h @@ -609,8 +609,8 @@ SENTRY_API sentry_transport_t *sentry_new_function_transport( * response data. */ SENTRY_API sentry_transport_t *sentry_new_qt_transport( - void (*func)(const char *url, const char *body, const char *headers, - void *data, void *state), + void (*func)(const char *url, const char *body, const long bodyLen, + const char *headers, void *data, void *state), void *data); /**