/* * SIPB service monitor: HTTP connection module * * Nickolai Zeldovich * May 2002 */ #include #include #include #include "sipbmon.h" static rxx urx ("^http://([\\w\\.-]+)(:\\d{1,6})?(/\\S*)", "i"); struct httpreq_t { int fd; struct tcpconn_t *tc; httpreq_t () : fd (-1), tc (NULL) {} }; static void http_read_cb (cbsb cb, strbuf rbuf, httpreq_t *req) { int cc = rbuf.tosuio ()->input (req->fd); if (cc < 0 && errno != EAGAIN) { fdcb (req->fd, selread, NULL); close (req->fd); (*cb) (str ("Error reading response: ") << strerror (errno), false); delete req; } if (cc == 0) { fdcb (req->fd, selread, NULL); close (req->fd); (*cb) (rbuf, true); delete req; } } static void http_write_cb (cbsb cb, httpreq_t *req, bool ok) { if (!ok) { close (req->fd); (*cb) (str ("Write failed: ") << strerror (errno), false); delete req; return; } strbuf rbuf; fdcb (req->fd, selread, wrap (&http_read_cb, cb, rbuf, req)); } static void http_connect_cb (str host, str file, cbsb cb, httpreq_t *req, int fd) { req->tc = NULL; if (fd < 0) { (*cb) (str (strerror (errno)), false); delete req; return; } req->fd = fd; strbuf rbuf; rbuf << "GET " << file << " HTTP/1.0\r\n" << "Host: " << host << "\r\n" << "Connection: close\r\n" << "\r\n"; net_write (fd, rbuf.tosuio (), wrap (&http_write_cb, cb, req)); } httpreq_t * http_get (str url, cbsb cb) { if (!urx.match (url)) { (*cb) ("Unable to match URL regexp", false); return NULL; } str host = urx[1]; str file = urx[3]; int port; if (urx[2]) convertint (urx[2].cstr () + 1, &port); // skip colon else port = 80; httpreq_t *req = New httpreq_t; req->tc = tcpconn (host, port, wrap (&http_connect_cb, host, file, cb, req)); return req; } void httpreq_abort (httpreq_t *req) { if (req->tc != NULL) { tcpconn_abort (req->tc); req->tc = NULL; } if (req->fd >= 0) { fdcb (req->fd, selread, NULL); fdcb (req->fd, selwrite, NULL); close (req->fd); } }