[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[Libevent-users] evhttp close callback not invoked when client closes the browser in chunked mode
hello, everyone
i am trying to write a simple comet server with evhttp.
the attached is my code currently compiled and runnable.
but when i visit ip:8811/streaming, and close the browser, the server
side connection callback doesn't invoked.
where in this file it's named HTTPServer::onClose.
can any one tell me how to get the callback when the browser closed?
thanks.
#include <event.h>
#include <evhttp.h>
#include <unistd.h>
#include <iostream>
#include <cassert>
#include <map>
#define MAX 10000
using namespace std;
extern "C" {
class Push {
};
class HTTPServer {
private:
struct event_base *base;
struct evhttp *httpd;
struct evhttp_bound_socket *handle;
map<string, evhttp_request *> requests;
string address;
int port;
int token;
public:
HTTPServer(string address = "0.0.0.0", int port = 80) {
base = event_base_new();
assert(base);
httpd = evhttp_new(base);
assert(httpd);
this->address = address;
this->port = port;
int code = evhttp_bind_socket(httpd, address.c_str(), port);
cout << endl << code << endl;
this->initCb();
token = 10000;
}
virtual void initHeader(struct evhttp_request *req) {
evhttp_add_header(req->output_headers, "Server", "Comet Server");
evhttp_add_header(req->output_headers, "Cache-Control", "no-cache");
evhttp_add_header(req->output_headers, "Content-Type", "text/plain");
}
virtual void initCb() {
evhttp_set_cb(httpd, "/streaming", HTTPServer::onStreaming, (void *)this);
evhttp_set_cb(httpd, "/register", HTTPServer::onRegister, (void *)this);
evhttp_set_cb(httpd, "/notify", HTTPServer::onNotify, (void *)this);
}
int getToken();
int sendMessage(struct evhttp_request *req, string message, bool chunked = false);
static void onCommon(struct evhttp_request *req, void *arg);
static void onStreaming(struct evhttp_request *req, void *arg);
static void onRegister(struct evhttp_request *req, void *arg);
static void onNotify(struct evhttp_request *req, void *arg);
static void onClose(struct evhttp_connection *con, void *arg);
void run() {
cout << "Inside Run" << endl;
event_base_dispatch(base);
}
~HTTPServer() {
evhttp_free(httpd);
}
};
int HTTPServer::getToken() {
return token++;
}
int HTTPServer::sendMessage(struct evhttp_request *req, string message, bool chunked) {
struct evbuffer *buf;
buf = evbuffer_new();
evbuffer_add_printf(buf, "%s", message.c_str());
if (!chunked) {
evhttp_send_reply(req, HTTP_OK, "OK", buf);
} else {
evhttp_send_reply_chunk(req, buf);
}
}
void HTTPServer::onClose(struct evhttp_connection *con, void *arg) {
cout << " connection closed " << endl;
}
void HTTPServer::onRegister(struct evhttp_request *req, void *arg) {
HTTPServer *server = (HTTPServer *) arg;
int key = server->getToken();
cout << key << endl;
struct evbuffer *buf;
buf = evbuffer_new();
evbuffer_add_printf(buf, "%d", key);
evhttp_send_reply(req, HTTP_OK, "OK", buf);
}
void HTTPServer::onNotify(struct evhttp_request *req, void *arg) {
}
void HTTPServer::onStreaming(struct evhttp_request *req, void *arg) {
HTTPServer *server = (HTTPServer *)arg;
cout << "Inside onComet" << endl;
const char * uri = evhttp_request_uri(req);
cout << uri << endl;
cout << req->kind <<endl;
server->initHeader(req);
evhttp_send_reply_start(req, HTTP_OK, "OK");
evhttp_connection_set_closecb(req->evcon, HTTPServer::onClose, NULL);
//evhttp_send_reply(req, HTTP_OK, "OK");
//evhttp_send_reply_chunk(req, buf);
cout << "Inside onComet end" << endl;
string a = "hello world from streaming";
server->sendMessage(req, a, true);
}
void HTTPServer::onCommon(struct evhttp_request *req, void *arg) {
cout << "Inside onCommon" << endl;
struct evbuffer *buf;
buf = evbuffer_new();
cout << req->kind <<endl;
if (buf == NULL) {
cerr << "1, failed to create response buffer" << endl;
cout << "1, failed to create response buffer" << endl;
}
evbuffer_add_printf(buf, "{\"now\":%d}", (int)time(NULL));
evhttp_send_reply(req, HTTP_OK, "OK", buf);
cout << "Inside onCommon end" << endl;
}
}
int main() {
HTTPServer *server = new HTTPServer("0.0.0.0", 8811);
server->run();
}