priv->err_cb (priv->fd, session, priv->ud, err);
REF_RELEASE (session);
g_error_free (err);
+
+ rspamd_milter_plan_io (session, priv, EV_WRITE);
+}
+
+static void
+rspamd_milter_on_protocol_ping (struct rspamd_milter_session *session,
+ struct rspamd_milter_private *priv)
+{
+ GError *err = NULL;
+ static const gchar reply[] = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Server: rspamd/2.7 (milter mode)\r\n"
+ "Content-Length: 6\r\n"
+ "Content-Type: text/plain\r\n"
+ "\r\n"
+ "pong\r\n";
+
+ if (write (priv->fd, reply, sizeof (reply)) == -1) {
+ gint serrno = errno;
+ msg_err_milter ("cannot write pong reply: %s", strerror (serrno));
+ g_set_error (&err, rspamd_milter_quark (), serrno, "ping command IO error: %s",
+ strerror (serrno));
+ priv->state = RSPAMD_MILTER_WANNA_DIE;
+ REF_RETAIN (session);
+ priv->err_cb (priv->fd, session, priv->ud, err);
+ REF_RELEASE (session);
+ g_error_free (err);
+ }
+ else {
+ priv->state = RSPAMD_MILTER_PONG_AND_DIE;
+ rspamd_milter_plan_io (session, priv, EV_WRITE);
+ }
+}
+
+static gint
+rspamd_milter_http_on_url (http_parser * parser, const gchar *at, size_t length)
+{
+ GString *url = (GString *)parser->data;
+
+ g_string_append_len (url, at, length);
+
+ return 0;
}
static void
/* Check if we have HTTP input instead of milter */
if (priv->parser.buf->len > sizeof ("GET") &&
memcmp (priv->parser.buf->str, "GET", 3) == 0) {
- err = g_error_new (rspamd_milter_quark (), EINVAL,
- "HTTP GET request is not supported in milter mode");
+ struct http_parser http_parser;
+ struct http_parser_settings http_callbacks;
+ GString *url = g_string_new (NULL);
+
+ /* Hack, hack, hack */
+ /*
+ * This code is assumed to read `/ping` command and
+ * handle it to monitor port's availability since
+ * milter protocol is stupid and does not allow to do that
+ * This code also assumes that HTTP request can be read
+ * as as single data chunk which is not true in some cases
+ * In general, don't use it for anything but ping checks
+ */
+ memset (&http_callbacks, 0, sizeof (http_callbacks));
+ http_parser_init (&http_parser, HTTP_REQUEST);
+ http_parser.data = url;
+ http_callbacks.on_url = rspamd_milter_http_on_url;
+ http_parser_execute (&http_parser, &http_callbacks,
+ priv->parser.buf->str, priv->parser.buf->len);
+
+ if (url->len == sizeof ("/ping") - 1 &&
+ rspamd_lc_cmp (url->str, "/ping", url->len) == 0) {
+ rspamd_milter_on_protocol_ping (session, priv);
+ g_string_free (url, TRUE);
+
+ return TRUE;
+ }
+ else {
+ err = g_error_new (rspamd_milter_quark (), EINVAL,
+ "HTTP GET request is not supported in milter mode, url: %s",
+ url->str);
+ }
+
+ g_string_free (url, TRUE);
}
else if (priv->parser.buf->len > sizeof ("POST") &&
memcmp (priv->parser.buf->str, "POST", 4) == 0) {
REF_RELEASE (session);
return FALSE;
break;
+ case RSPAMD_MILTER_PONG_AND_DIE:
+ err = g_error_new (rspamd_milter_quark (), 0,
+ "ping command");
+ REF_RETAIN (session);
+ priv->err_cb (priv->fd, session, priv->ud, err);
+ REF_RELEASE (session);
+ g_error_free (err);
+ REF_RELEASE (session);
+ return FALSE;
+ break;
}
return TRUE;