]> source.dussan.org Git - rspamd.git/commitdiff
Force restful replies for restful sessions (not tested with all commands).
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Sun, 16 Sep 2012 16:11:19 +0000 (20:11 +0400)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Sun, 16 Sep 2012 16:11:19 +0000 (20:11 +0400)
src/buffer.c
src/buffer.h
src/controller.c

index 0dd28daa0b7151a315405f31d4db8f00a516693e..c81c6a686575c2638de99911c92887904cd9e70d 100644 (file)
@@ -688,14 +688,14 @@ rspamd_set_dispatcher_policy (rspamd_io_dispatcher_t * d, enum io_policy policy,
 }
 
 gboolean
-rspamd_dispatcher_write (rspamd_io_dispatcher_t * d, void *data, size_t len, gboolean delayed, gboolean allocated)
+rspamd_dispatcher_write (rspamd_io_dispatcher_t * d, const void *data, size_t len, gboolean delayed, gboolean allocated)
 {
        rspamd_buffer_t                *newbuf;
 
        newbuf = memory_pool_alloc_tmp (d->pool, sizeof (rspamd_buffer_t));
        if (len == 0) {
                /* Assume NULL terminated */
-               len = strlen ((gchar *)data);
+               len = strlen ((const gchar *)data);
        }
 
        if (!allocated) {
@@ -709,7 +709,7 @@ rspamd_dispatcher_write (rspamd_io_dispatcher_t * d, void *data, size_t len, gbo
        }
        else {
                newbuf->data = memory_pool_alloc_tmp (d->pool, sizeof (f_str_t));
-               newbuf->data->begin = data;
+               newbuf->data->begin = (gchar *)data;
                newbuf->data->size = len;
        }
 
index 235497aa2ed00e83933878bbeb4025f7b7816efa..11b03bca4b1d3ad854a16866c43c234b225b56a8 100644 (file)
@@ -96,7 +96,7 @@ void rspamd_set_dispatcher_policy (rspamd_io_dispatcher_t *d,
  * @param len length of data
  */
 gboolean rspamd_dispatcher_write (rspamd_io_dispatcher_t *d,
-                                                                                                 void *data,
+                                                                                                 const void *data,
                                                                                                  size_t len, gboolean delayed, gboolean allocated) G_GNUC_WARN_UNUSED_RESULT;
 
 /**
index 7bd90e7dba37a49eb942188ec9fc03b4d55861c2..a8945f8d396fa3588d67d8bbb91d95abd79b8c3d 100644 (file)
@@ -204,6 +204,35 @@ free_session (void *ud)
        g_slice_free1 (sizeof (struct controller_session), session);
 }
 
+static gboolean
+restful_write_reply (gint error_code, const gchar *err_message, const gchar *buf, gsize buflen, rspamd_io_dispatcher_t *d)
+{
+       static gchar                                     hbuf[256];
+       gint                                                     r;
+
+       r = rspamd_snprintf (hbuf, sizeof (hbuf),
+                       "HTTP/1.0 %d %s" CRLF "Version: " RVERSION CRLF,
+                       error_code, err_message ? err_message : "OK");
+       if (buflen > 0) {
+               r += rspamd_snprintf (hbuf + r, sizeof (hbuf) - r, "Content-Length: %z" CRLF, buflen);
+       }
+       r += rspamd_snprintf (hbuf + r, sizeof (hbuf) - r, CRLF);
+
+       if (buf != NULL) {
+               if (!rspamd_dispatcher_write (d, hbuf, r, TRUE, FALSE)) {
+                       return FALSE;
+               }
+               return rspamd_dispatcher_write (d, buf, buflen, FALSE, FALSE);
+       }
+       else {
+               if (!rspamd_dispatcher_write (d, hbuf, r, TRUE, TRUE)) {
+                       return FALSE;
+               }
+       }
+
+       return TRUE;
+}
+
 static gint
 check_auth (struct controller_command *cmd, struct controller_session *session)
 {
@@ -211,9 +240,14 @@ check_auth (struct controller_command *cmd, struct controller_session *session)
        gint                            r;
 
        if (cmd->privilleged && !session->authorized) {
-               r = rspamd_snprintf (out_buf, sizeof (out_buf), "not authorized" CRLF);
-               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
-                       return 0;
+               if (!session->restful) {
+                       r = rspamd_snprintf (out_buf, sizeof (out_buf), "not authorized" CRLF);
+                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                               return 0;
+                       }
+               }
+               else {
+                       (void)restful_write_reply (403, "Not authorized", NULL, 0, session->dispatcher);
                }
                return 0;
        }
@@ -461,7 +495,12 @@ process_stat_command (struct controller_session *session)
                cur_cl = g_list_next (cur_cl);
        }
 
-       return rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+       if (!session->restful) {
+               return rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+       }
+       else {
+               return restful_write_reply (200, NULL, out_buf, r, session->dispatcher);
+       }
 }
 
 static gboolean
@@ -519,8 +558,15 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
        case COMMAND_RELOAD:
                if (check_auth (cmd, session)) {
                        r = rspamd_snprintf (out_buf, sizeof (out_buf), "reload request sent" CRLF);
-                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
-                               return FALSE;
+                       if (!session->restful) {
+                               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                       return FALSE;
+                               }
+                       }
+                       else {
+                               if (! restful_write_reply (200, out_buf, NULL, 0, session->dispatcher)) {
+                                       return FALSE;
+                               }
                        }
                        kill (getppid (), SIGHUP);
                }
@@ -533,8 +579,15 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
        case COMMAND_SHUTDOWN:
                if (check_auth (cmd, session)) {
                        r = rspamd_snprintf (out_buf, sizeof (out_buf), "shutdown request sent" CRLF);
-                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
-                               return FALSE;
+                       if (!session->restful) {
+                               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                       return FALSE;
+                               }
+                       }
+                       else {
+                               if (! restful_write_reply (200, out_buf, NULL, 0, session->dispatcher)) {
+                                       return FALSE;
+                               }
                        }
                        kill (getppid (), SIGTERM);
                }
@@ -560,8 +613,15 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
                                uptime -= hours * 3600 + minutes * 60;
                                r = rspamd_snprintf (out_buf, sizeof (out_buf), "%d hour%s %d minute%s %d second%s" CRLF, hours, hours > 1 ? "s" : " ", minutes, minutes > 1 ? "s" : " ", (gint)uptime, uptime > 1 ? "s" : " ");
                        }
-                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
-                               return FALSE;
+                       if (!session->restful) {
+                               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                       return FALSE;
+                               }
+                       }
+                       else {
+                               if (! restful_write_reply (200, NULL, out_buf, r, session->dispatcher)) {
+                                       return FALSE;
+                               }
                        }
                }
                break;
@@ -601,7 +661,7 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
                                if ((arg = g_hash_table_lookup (session->kwargs, "classifier")) == NULL) {
                                        msg_debug ("no classifier specified in learn command");
                                        r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF);
-                                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                       if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) {
                                                return FALSE;
                                        }
                                        return TRUE;
@@ -612,14 +672,16 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
                                if ((arg = g_hash_table_lookup (session->kwargs, "content-length")) == NULL) {
                                        msg_debug ("no size specified in learn command");
                                        r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF);
-                                       return rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+                                       if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) {
+                                               return FALSE;
+                                       }
                                }
                                else {
                                        size = strtoul (arg, &err_str, 10);
                                        if (err_str && *err_str != '\0') {
                                                msg_debug ("message size is invalid: %s", arg);
                                                r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn size is invalid" CRLF);
-                                               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                               if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) {
                                                        return FALSE;
                                                }
                                                return TRUE;
@@ -671,7 +733,7 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
                                if ((arg = g_hash_table_lookup (session->kwargs, "classifier")) == NULL) {
                                        msg_debug ("no classifier specified in learn command");
                                        r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF);
-                                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                       if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) {
                                                return FALSE;
                                        }
                                        return TRUE;
@@ -682,14 +744,16 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
                                if ((arg = g_hash_table_lookup (session->kwargs, "content-length")) == NULL) {
                                        msg_debug ("no size specified in learn command");
                                        r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF);
-                                       return rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+                                       if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) {
+                                               return FALSE;
+                                       }
                                }
                                else {
                                        size = strtoul (arg, &err_str, 10);
                                        if (err_str && *err_str != '\0') {
                                                msg_debug ("message size is invalid: %s", arg);
                                                r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn size is invalid" CRLF);
-                                               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                               if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) {
                                                        return FALSE;
                                                }
                                                return TRUE;
@@ -865,8 +929,15 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
                        "    counters - show rspamd counters" CRLF 
                        "    uptime - rspamd uptime" CRLF
                        "    weights <statfile> <size> - weight of message in all statfiles" CRLF);
-               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
-                       return FALSE;
+               if (!session->restful) {
+                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                               return FALSE;
+                       }
+               }
+               else {
+                       if (! restful_write_reply (200, NULL, out_buf, r, session->dispatcher)) {
+                               return FALSE;
+                       }
                }
                break;
        case COMMAND_COUNTERS:
@@ -1164,8 +1235,15 @@ controller_read_socket (f_str_t * in, void *arg)
                        msg_warn ("processing of message failed");
                        session->state = STATE_REPLY;
                        r = rspamd_snprintf (out_buf, sizeof (out_buf), "cannot process message" CRLF);
-                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
-                               return FALSE;
+                       if (!session->restful) {
+                               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                       return FALSE;
+                               }
+                       }
+                       else {
+                               if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) {
+                                       return FALSE;
+                               }
                        }
                        return FALSE;
                }
@@ -1176,8 +1254,15 @@ controller_read_socket (f_str_t * in, void *arg)
                        session->state = STATE_REPLY;
                        r = rspamd_snprintf (out_buf, sizeof (out_buf), "cannot process message" CRLF);
                        destroy_session (task->s);
-                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
-                               return FALSE;
+                       if (!session->restful) {
+                               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                       return FALSE;
+                               }
+                       }
+                       else {
+                               if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) {
+                                       return FALSE;
+                               }
                        }
                }
                else {
@@ -1202,8 +1287,15 @@ controller_read_socket (f_str_t * in, void *arg)
                        free_task (task, FALSE);
                        session->state = STATE_REPLY;
                        r = rspamd_snprintf (out_buf, sizeof (out_buf), "cannot process message" CRLF END);
-                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
-                               return FALSE;
+                       if (!session->restful) {
+                               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                       return FALSE;
+                               }
+                       }
+                       else {
+                               if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) {
+                                       return FALSE;
+                               }
                        }
                        return FALSE;
                }
@@ -1222,8 +1314,15 @@ controller_read_socket (f_str_t * in, void *arg)
                                        session->session_pool, &c, &tokens, FALSE, part->is_utf, part->urls_offset)) {
                                i = rspamd_snprintf (out_buf, sizeof (out_buf), "weights failed, tokenizer error" CRLF END);
                                free_task (task, FALSE);
-                               if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) {
-                                       return FALSE;
+                               if (!session->restful) {
+                                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                               return FALSE;
+                                       }
+                               }
+                               else {
+                                       if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) {
+                                               return FALSE;
+                                       }
                                }
                                session->state = STATE_REPLY;
                                return TRUE;
@@ -1328,8 +1427,15 @@ controller_write_socket (void *arg)
                session->learn_task->dispatcher = NULL;
                destroy_session (session->learn_task->s);
                session->state = STATE_REPLY;
-               if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) {
-                       return FALSE;
+               if (!session->restful) {
+                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) {
+                               return FALSE;
+                       }
+               }
+               else {
+                       if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) {
+                               return FALSE;
+                       }
                }
                return TRUE;
        }
@@ -1415,9 +1521,12 @@ accept_socket (gint fd, short what, void *arg)
                memcpy (&new_session->dispatcher->peer_addr, &su.s4.sin_addr,
                                sizeof (guint32));
        }
+#if 0
+       /* As we support now restful HTTP like connections, this should not be printed anymore */
        if (! rspamd_dispatcher_write (new_session->dispatcher, greetingbuf, strlen (greetingbuf), FALSE, FALSE)) {
                msg_warn ("cannot write greeting");
        }
+#endif
 }
 
 gpointer