/* * SIPB service monitor * * Nickolai Zeldovich * May 2002 */ #include #include #include "sipbmon.h" static rxx http_resp ("^HTTP/1\\.\\d 200 .*", "s"); static rxx pksd_resp1 (".*BEGIN PGP PUBLIC KEY BLOCK.*", "s"); static rxx pksd_resp2 (".*Type bits/keyID.*", "s"); static rxx news_resp1 ("^200 .* \\(posting ok\\).[\\r\\n]*", "s"); static rxx news_resp2 ("^211 .*", "s"); void http_checker::response (str s, bool ok) { httpreq = NULL; if (!ok) { down (s); return; } if (!http_resp.match (s)) { down ("Invalid HTTP response"); return; } up (); } void http_checker::start () { assert (!httpreq); httpreq = http_get (url, wrap (this, &http_checker::response)); } void http_checker::stop () { if (httpreq != NULL) { httpreq_abort (httpreq); httpreq = NULL; } } void tcp_checker::connected (int fd) { conn = NULL; if (fd < 0) { down (strerror (errno)); return; } close (fd); up (); } void tcp_checker::start () { conn = tcpconn (host, port, wrap (this, &tcp_checker::connected)); } void tcp_checker::stop () { if (conn) { tcpconn_abort (conn); conn = NULL; } } void pksd_checker::response2 (str s, bool ok) { httpreq = NULL; if (!ok) { down (s); return; } if (!http_resp.match (s)) { down ("invalid HTTP response on search"); return; } if (!pksd_resp2.match (s)) { down ("cannot search keys"); return; } up (); } void pksd_checker::response1 (str s, bool ok) { httpreq = NULL; if (!ok) { down (s); return; } if (!http_resp.match (s)) { down ("invalid HTTP response on fetch"); return; } if (!pksd_resp1.match (s)) { down ("cannot fetch key"); warn << "cannot fetch key: " << s << "\n"; return; } httpreq = http_get ("http://" << host << ":" << port << "/pks/lookup?search=0x" << key << "&op=index", wrap (this, &pksd_checker::response2)); } void pksd_checker::start () { assert (!httpreq); httpreq = http_get ("http://" << host << ":" << port << "/pks/lookup?op=get&search=0x" << key, wrap (this, &pksd_checker::response1)); } void pksd_checker::stop () { if (httpreq) { httpreq_abort (httpreq); httpreq = NULL; } } void news_checker::read2 (strbuf s) { int cc = s.tosuio ()->input (fd); if (cc < 0 && errno != EAGAIN) { fdcb (fd, selread, NULL); close (fd); fd = -1; down (strerror (errno)); return; } if (cc == 0) { fdcb (fd, selread, NULL); close (fd); fd = -1; down ("unexpected EOF after GROUP"); return; } if (news_resp2.match (s)) { fdcb (fd, selread, NULL); close (fd); fd = -1; up (); } } void news_checker::write_cb (bool ok) { if (!ok) { close (fd); fd = -1; down (strerror (errno)); return; } strbuf s; fdcb (fd, selread, wrap (this, &news_checker::read2, s)); } void news_checker::read1 (strbuf s) { int cc = s.tosuio ()->input (fd); if (cc < 0 && errno != EAGAIN) { fdcb (fd, selread, NULL); close (fd); fd = -1; down (strerror (errno)); return; } if (cc == 0) { fdcb (fd, selread, NULL); close (fd); fd = -1; down ("unexpected EOF after connect"); return; } if (news_resp1.match (s)) { fdcb (fd, selread, NULL); strbuf m; m << "GROUP " << group << "\r\n"; net_write (fd, m.tosuio (), wrap (this, &news_checker::write_cb)); } } void news_checker::connected (int afd) { conn = NULL; if (afd < 0) { down (strerror (errno)); return; } fd = afd; strbuf s; fdcb (fd, selread, wrap (this, &news_checker::read1, s)); } void news_checker::start () { assert (!conn); conn = tcpconn (host, port, wrap (this, &news_checker::connected)); } void news_checker::stop () { if (conn) { tcpconn_abort (conn); conn = NULL; } if (fd >= 0) { fdcb (fd, selread, NULL); fdcb (fd, selwrite, NULL); close (fd); } }