Search code examples
cevent-handlinglibevent

Libevent: how to temporarily disable, then re-enable EV_READ? (In C)


I am using libevent for handling data receipt on a set of ports. The behavior i would like to accomplish is this:

-Say i have a set of ports, 1001-1004 -Read in data on port, say 1001. -As soon as the callback is hit, disable further reading on this port (1001). -Once all ports have received data, turn them all back on for reading.

Right now i have a struct of bufferevents:

static struct bufferevent *bev[4];

I set up the listeners like they show in the documentation:

/* Listener 1 */
sin.sin_port = htons(MIXPORT + 1);
listener1 = evconnlistener_new_bind(base, accept1, NULL,
    LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1,
    (struct sockaddr*)&sin, sizeof(sin));
if (!listener1) { perror("Couldn't create listener1"); return 1; }
evconnlistener_set_error_cb(listener1, accept_error_cb);

static void accept1(struct evconnlistener *listener,
evutil_socket_t fd, struct sockaddr *address, int socklen,
void *ctx) {
/* A new connection was received on this port */
struct event_base *base = evconnlistener_get_base(listener);
bev[0] = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);

/* Callback for when (*bufevent, data READ, data WRITTEN, event OCCURRED, *void) */
bufferevent_setcb(bev[0], read1, NULL, echo_event_cb, NULL);

/* Set bufferevent to be able to read */
bufferevent_enable(bev[0], EV_READ);
}

Then i gave it a READ callback:

static void read1(struct bufferevent *bev, void *ctx) {
if(LOG) { logoutput("Data received on port 1"); }

struct evbuffer *input = bufferevent_get_input(bev);
size_t len = evbuffer_get_length(input);
data[0] = malloc(len);

/* Copy evbuffer data into array */
evbuffer_copyout(input, data[0], len);
/* Remove data from evbuffer after copying it out */
evbuffer_drain(input, len);

handle(0);
}  

In my "handle" function, i told it to do this:

static void handle(int i)
{
/* Disable reading on port until re-enabled later */
bufferevent_disable(bev[i], EV_READ);  // I thought this should do it?!

// Do other stuff...
random_function();
}

And finally...

static void random_function(); {
/* Re-enable read on port */
    bufferevent_enable(bev[src], EV_READ);
}

Any ideas what i'm doing wrong? When i sent data to a random port, i am still able to send it more, and more, and more.
TIA!


Solution

  • It looks like you are just disabling reading the data on a socket, but this won't stop someone from sending you data on that socket (The OS will buffer a fair amount of data from them because it assumes that you'll want to read it when you have time).

    You can't stop them from sending data, but you can stop new connections to those ports (by not accepting connections on your blocked ports until you want to again), and you can close connections on your closed ports if they do send you data (that would mean that you still want to read on those ports, but if they send you anything, you close() them or something like that.)