Skip to content

Commit

Permalink
Merge pull request #3 from mystaff/nluz-qttransport
Browse files Browse the repository at this point in the history
qt transport
  • Loading branch information
nunomluz authored Nov 24, 2020
2 parents 6f73d4c + d84f6e8 commit 65264dc
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 0 deletions.
25 changes: 25 additions & 0 deletions include/sentry.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 long bodyLen,
const char *headers, void *data, void *state),
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(
void *_state, char *rate_limits, char *retry_after);

/* -- Options APIs -- */

/**
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
)

Expand Down
138 changes: 138 additions & 0 deletions src/transports/sentry_transport_qt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#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 <stdlib.h>
#include <string.h>

typedef struct qt_transport_state_s {
sentry_dsn_t *dsn;
sentry_rate_limiter_t *ratelimiter;
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;

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 = (qt_transport_state_t *)transport_state;

state->dsn = sentry__dsn_incref(options->dsn);
state->debug = options->debug;

return 0;
}

static int
sentry__qt_transport_shutdown(
uint64_t UNUSED(timeout), void *UNUSED(transport_state))
{
return 0;
}

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) {
sentry_envelope_free(envelope);
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\n%s:%s", buf, req->headers[i].key,
req->headers[i].value);
}
}

state->func(req->url, req->body, req->body_len, buf, state->data, state);

sentry__prepared_http_request_free(req);
sentry_envelope_free(envelope);
}

void
sentry_qt_transport_process_response(
void *_state, char *rate_limits, char *retry_after)
{
qt_transport_state_t *state = (qt_transport_state_t *)_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 long bodyLen,
const char *headers, void *data, void *state),
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;
}

0 comments on commit 65264dc

Please sign in to comment.