[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [Libevent-users] Counting the number of transferred bytes



On 2019-07-17 09:29, Azat Khuzhin wrote:
> On Mon, Jul 15, 2019 at 11:59 PM Steffen Christgau <mail@xxxxxxx> 
> wrote:
>> I stumbled across filters but I'm not sure if that's the right way to
>> go. Something like a "null filter" that passes data just from source 
>> to
>> destination without modifications could be used for counting. However,
>> for my use-case such a filter must be applied after encryption by TLS.
> 
> Indeed you can use bufferevent filter, take a look at
> bufferevent_openssl_filter_new()
> 
> You can start with a simple POC, and share it here if you will need 
> help.

Based on what I have seen in the le-proxy example and the zlib
regression test, my impression was that it would be sufficient to
replace the bufferevent of the (openssl) socket with the one returned by
the filter and use the original bufferevent as underlying bev.

This is what I've done in the https-client example. I added a "null"
filter for both incoming and outgoing data and which passes data through
but does nothing else except printing a message that the filter was
invoked.  You can find an according patch attached to this mail.
However, it does not work as expected. With the patch, the client is
broken. The TCP connection to the HTTP(s) server is still established,
but no data is transferred and the filters aren't invoked. For accesses
to HTTPS, the TLS handshake is done, but again no filter is invoked and
no HTTP traffic is observed.

Any suggestions on how to proceed?

Regards, Steffen
--- https-client.c	2019-07-22 18:41:55.794053162 +0200
+++ https-client.c	2019-07-22 18:40:59.920604381 +0200
@@ -47,6 +47,23 @@
 
 static int ignore_cert = 0;
 
+static enum bufferevent_filter_result filter_in(struct evbuffer *src, struct evbuffer *dst, ev_ssize_t dst_limit, enum bufferevent_flush_mode mode, void *ctx)
+{
+	printf("%s:%s\n", __FILE__, __func__);
+	evbuffer_add_buffer(dst, src);
+
+	return BEV_OK;
+}
+
+static enum bufferevent_filter_result filter_out(struct evbuffer *src, struct evbuffer *dst, ev_ssize_t dst_limit, enum bufferevent_flush_mode mode, void *ctx)
+{
+	printf("%s:%s\n", __FILE__, __func__);
+	evbuffer_add_buffer(dst, src);
+
+	return BEV_OK;
+}
+
+
 static void
 http_request_done(struct evhttp_request *req, void *ctx)
 {
@@ -199,7 +216,7 @@
 
 	SSL_CTX *ssl_ctx = NULL;
 	SSL *ssl = NULL;
-	struct bufferevent *bev;
+	struct bufferevent *bev, *filter_bev;
 	struct evhttp_connection *evcon = NULL;
 	struct evhttp_request *req;
 	struct evkeyvalq *output_headers;
@@ -401,11 +418,26 @@
 
 	if (strcasecmp(scheme, "http") == 0) {
 		bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
+		filter_bev = bufferevent_filter_new(bev, filter_in, filter_out, 0, NULL, NULL);
+		if (!filter_bev) {
+			fprintf(stderr, "unable to create filter for bev\n");
+		} else {
+			fprintf(stderr, "created filter\n");
+			bev = filter_bev;
+		}
 	} else {
 		type = HTTPS;
 		bev = bufferevent_openssl_socket_new(base, -1, ssl,
 			BUFFEREVENT_SSL_CONNECTING,
 			BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
+
+		filter_bev = bufferevent_openssl_filter_new(base, bev, ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
+		if (!filter_bev) {
+			fprintf(stderr, "unable to create filter for bev\n");
+		} else {
+			fprintf(stderr, "created filter\n");
+			bev = filter_bev;
+		}
 	}
 
 	if (bev == NULL) {