static void ui_handler(evutil_socket_t fd, short what, void *arg) { struct uiclient *client = arg; if (evbuffer_read(client->inbuf, fd, -1) <= 0) { ui_dead(client); return; } for (;;) { size_t eol_len; struct evbuffer_ptr line = evbuffer_search_eol(client->inbuf, NULL, &eol_len, EVBUFFER_EOL_LF); if (line.pos == -1) break; char *p = (char *)malloc(line.pos + 1); if (p != NULL) { evbuffer_remove(client->inbuf, (void *)p, line.pos); p[line.pos] = '\0'; /* ensure termination */ evbuffer_drain(client->inbuf, eol_len); ui_handle_command(client->outbuf, p); free(p); } } ui_write_prompt(client); event_add(client->ev_read, NULL); }
static void echo_read_cb(struct bufferevent *bev, void *ctx) { /* This callback is invoked when there is data to read on bev. */ struct evbuffer *input = bufferevent_get_input(bev); struct evbuffer *output = bufferevent_get_output(bev); while (1) { size_t eol_len = 0; struct evbuffer_ptr eol = evbuffer_search_eol(input, NULL, &eol_len, EVBUFFER_EOL_LF); if (eol.pos < 0) { // not found '\n' size_t readable = evbuffer_get_length(input); if (readable > MAX_LINE_LENGTH) { printf("input is too long %zd\n", readable); bufferevent_free(bev); } break; } else if (eol.pos > MAX_LINE_LENGTH) { printf("line is too long %zd\n", eol.pos); bufferevent_free(bev); break; } else { assert(eol_len == 1); // int nr = evbuffer_remove_buffer(input, output, eol.pos+1); // copy input buffer to request char request[MAX_LINE_LENGTH+1]; assert(eol.pos+1 <= sizeof(request)); int req_len = evbuffer_remove(input, request, eol.pos+1); assert(req_len == eol.pos+1); // business logic char response[MAX_LINE_LENGTH+1]; int resp_len = req_len; memcpy(response, request, req_len); // copy response to output buffer int succeed = evbuffer_add(output, response, resp_len); assert(succeed == 0); // high water mark check if (evbuffer_get_length(output) > MAX_OUTPUT_BUFFER) { // or, stop reading bufferevent_free(bev); break; } } } }