Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ sentry_target_sources_cwd(sentry
transports/sentry_disk_transport.c
transports/sentry_disk_transport.h
transports/sentry_function_transport.c
transports/sentry_http_transport.c
transports/sentry_http_transport.h
unwinder/sentry_unwinder.c
)

Expand Down Expand Up @@ -119,11 +121,11 @@ endif()
# transport
if(SENTRY_TRANSPORT_CURL)
sentry_target_sources_cwd(sentry
transports/sentry_transport_curl.c
transports/sentry_http_transport_curl.c
)
elseif(SENTRY_TRANSPORT_WINHTTP)
sentry_target_sources_cwd(sentry
transports/sentry_transport_winhttp.c
transports/sentry_http_transport_winhttp.c
)
elseif(SENTRY_TRANSPORT_NONE)
sentry_target_sources_cwd(sentry
Expand Down
172 changes: 1 addition & 171 deletions src/sentry_transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,6 @@
#include "sentry_alloc.h"
#include "sentry_envelope.h"
#include "sentry_options.h"
#include "sentry_ratelimiter.h"
#include "sentry_string.h"

#ifdef SENTRY_TRANSPORT_COMPRESSION
# include "zlib.h"
#endif

#define ENVELOPE_MIME "application/x-sentry-envelope"
#ifdef SENTRY_TRANSPORT_COMPRESSION
// The headers we use are: `x-sentry-auth`, `content-type`, `content-encoding`,
// `content-length`
# define MAX_HTTP_HEADERS 4
#else
// The headers we use are: `x-sentry-auth`, `content-type`, `content-length`
# define MAX_HTTP_HEADERS 3
#endif

struct sentry_transport_s {
void (*send_envelope_func)(sentry_envelope_t *envelope, void *state);
Expand Down Expand Up @@ -158,162 +142,8 @@ sentry_transport_free(sentry_transport_t *transport)
sentry_free(transport);
}

#ifdef SENTRY_UNITTEST
void *
sentry__transport_get_bgworker(sentry_transport_t *transport)
sentry__transport_get_state(sentry_transport_t *transport)
{
// For HTTP transports (curl/winhttp), the transport state is the bgworker
return transport ? transport->state : NULL;
}
#endif

#ifdef SENTRY_TRANSPORT_COMPRESSION
static bool
gzipped_with_compression(const char *body, const size_t body_len,
char **compressed_body, size_t *compressed_body_len)
{
if (!body || body_len == 0) {
return false;
}

z_stream stream;
memset(&stream, 0, sizeof(stream));
stream.next_in = (unsigned char *)body;
stream.avail_in = (unsigned int)body_len;

int err = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
MAX_WBITS + 16, 9, Z_DEFAULT_STRATEGY);
if (err != Z_OK) {
SENTRY_WARNF("deflateInit2 failed: %d", err);
return false;
}

size_t len = compressBound((unsigned long)body_len);
char *buffer = sentry_malloc(len);
if (!buffer) {
deflateEnd(&stream);
return false;
}

while (err == Z_OK) {
stream.next_out = (unsigned char *)(buffer + stream.total_out);
stream.avail_out = (unsigned int)(len - stream.total_out);
err = deflate(&stream, Z_FINISH);
}

if (err != Z_STREAM_END) {
SENTRY_WARNF("deflate failed: %d", err);
sentry_free(buffer);
buffer = NULL;
deflateEnd(&stream);
return false;
}

*compressed_body_len = stream.total_out;
*compressed_body = buffer;

deflateEnd(&stream);
return true;
}
#endif

sentry_prepared_http_request_t *
sentry__prepare_http_request(sentry_envelope_t *envelope,
const sentry_dsn_t *dsn, const sentry_rate_limiter_t *rl,
const char *user_agent)
{
if (!dsn || !dsn->is_valid) {
return NULL;
}

size_t body_len = 0;
bool body_owned = true;
char *body = sentry_envelope_serialize_ratelimited(
envelope, rl, &body_len, &body_owned);
if (!body) {
return NULL;
}

#ifdef SENTRY_TRANSPORT_COMPRESSION
bool compressed = false;
char *compressed_body = NULL;
size_t compressed_body_len = 0;
compressed = gzipped_with_compression(
body, body_len, &compressed_body, &compressed_body_len);
if (compressed) {
if (body_owned) {
sentry_free(body);
body_owned = false;
}
body = compressed_body;
body_len = compressed_body_len;
body_owned = true;
}
#endif

sentry_prepared_http_request_t *req
= SENTRY_MAKE(sentry_prepared_http_request_t);
if (!req) {
if (body_owned) {
sentry_free(body);
}
return NULL;
}
req->headers = sentry_malloc(
sizeof(sentry_prepared_http_header_t) * MAX_HTTP_HEADERS);
if (!req->headers) {
sentry_free(req);
if (body_owned) {
sentry_free(body);
}
return NULL;
}
req->headers_len = 0;

req->method = "POST";
req->url = sentry__dsn_get_envelope_url(dsn);

sentry_prepared_http_header_t *h;
h = &req->headers[req->headers_len++];
h->key = "x-sentry-auth";
h->value = sentry__dsn_get_auth_header(dsn, user_agent);

h = &req->headers[req->headers_len++];
h->key = "content-type";
h->value = sentry__string_clone(ENVELOPE_MIME);

#ifdef SENTRY_TRANSPORT_COMPRESSION
if (compressed) {
h = &req->headers[req->headers_len++];
h->key = "content-encoding";
h->value = sentry__string_clone("gzip");
}
#endif

h = &req->headers[req->headers_len++];
h->key = "content-length";
h->value = sentry__int64_to_string((int64_t)body_len);

req->body = body;
req->body_len = body_len;
req->body_owned = body_owned;

return req;
}

void
sentry__prepared_http_request_free(sentry_prepared_http_request_t *req)
{
if (!req) {
return;
}
sentry_free(req->url);
for (size_t i = 0; i < req->headers_len; i++) {
sentry_free(req->headers[i].value);
}
sentry_free(req->headers);
if (req->body_owned) {
sentry_free(req->body);
}
sentry_free(req);
}
41 changes: 1 addition & 40 deletions src/sentry_transport.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#include "sentry_boot.h"
#include "sentry_database.h"
#include "sentry_ratelimiter.h"
#include "sentry_utils.h"

/**
Expand Down Expand Up @@ -56,44 +55,6 @@ sentry_transport_t *sentry__transport_new_default(void);
size_t sentry__transport_dump_queue(
sentry_transport_t *transport, sentry_run_t *run);

#ifdef SENTRY_UNITTEST
/**
* Test helper function to get the bgworker from a transport.
* Only available in unit tests and only works for HTTP transports.
*/
void *sentry__transport_get_bgworker(sentry_transport_t *transport);
#endif

typedef struct sentry_prepared_http_header_s {
const char *key;
char *value;
} sentry_prepared_http_header_t;

/**
* This represents a HTTP request, with method, url, headers and a body.
*/
typedef struct sentry_prepared_http_request_s {
const char *method;
char *url;
sentry_prepared_http_header_t *headers;
size_t headers_len;
char *body;
size_t body_len;
bool body_owned;
} sentry_prepared_http_request_t;

/**
* Consumes the given envelope and transforms it into into a prepared http
* request. This can return NULL when all the items in the envelope have been
* rate limited.
*/
sentry_prepared_http_request_t *sentry__prepare_http_request(
sentry_envelope_t *envelope, const sentry_dsn_t *dsn,
const sentry_rate_limiter_t *rl, const char *user_agent);

/**
* Free a previously allocated HTTP request.
*/
void sentry__prepared_http_request_free(sentry_prepared_http_request_t *req);
void *sentry__transport_get_state(sentry_transport_t *transport);

#endif
Loading
Loading