]> source.dussan.org Git - rspamd.git/commitdiff
Remove legacy client and rework build system.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sun, 19 Jan 2014 16:11:34 +0000 (16:11 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sun, 19 Jan 2014 16:11:34 +0000 (16:11 +0000)
--HG--
rename : lib/CMakeLists.txt => src/CMakeLists.txt

CMakeLists.txt
lib/CMakeLists.txt [deleted file]
lib/client/librspamdclient.c [deleted file]
lib/client/librspamdclient.h [deleted file]
lib/kvstorage/libkvstorageclient.c [deleted file]
lib/kvstorage/libkvstorageclient.h [deleted file]
src/CMakeLists.txt [new file with mode: 0644]
src/client/CMakeLists.txt
src/client/rspamdclient.c [new file with mode: 0644]
src/client/rspamdclient.h [new file with mode: 0644]

index f5a69f0407a04455a3bf4fc5dcddbecbb3e06384..7b9413f3e0d88739377aaa323893e131217ad9ae 100644 (file)
@@ -920,8 +920,7 @@ ADD_SUBDIRECTORY(src/json)
 ADD_SUBDIRECTORY(src/cdb)
 ADD_SUBDIRECTORY(src/ucl)
 ADD_SUBDIRECTORY(contrib/http-parser)
-ADD_SUBDIRECTORY(lib)
-
+ADD_SUBDIRECTORY(src)
 ADD_SUBDIRECTORY(src/client)
 
 ADD_SUBDIRECTORY(utils)
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
deleted file mode 100644 (file)
index 0f3cba7..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-# Librspamdclient
-SET(LIBRSPAMDCLIENTSRC                   client/librspamdclient.c)
-
-# Librspamd-util
-SET(LIBRSPAMDUTILSRC                   ../src/aio_event.c
-                                                               ../src/bloom.c
-                                                               ../src/diff.c
-                                                               ../src/fstring.c
-                                                               ../src/fuzzy.c
-                                                               ../src/hash.c
-                                                               ../src/http.c
-                                                               ../src/logger.c
-                                                               ../src/map.c
-                                                               ../src/memcached.c
-                                                               ../src/mem_pool.c
-                                                               ../src/printf.c
-                                                               ../src/radix.c
-                                                               ../src/rrd.c
-                                                               ../src/trie.c
-                                                               ../src/upstream.c
-                                                               ../src/util.c)
-
-# kvstorageclient
-
-SET(LIBRKVSTORAGESRC                     kvstorage/libkvstorageclient.c)
-
-# Librspamdserver
-SET(LIBRSPAMDSERVERSRC
-                               ../src/binlog.c
-                               ../src/buffer.c
-                               ../src/cfg_utils.c
-                               ../src/cfg_rcl.c
-                               ../src/cfg_xml.c
-                               ../src/dkim.c
-                               ../src/dns.c
-                               ../src/dynamic_cfg.c
-                               ../src/events.c
-                               ../src/html.c
-                               ../src/proxy.c
-                               ../src/roll_history.c
-                               ../src/settings.c
-                               ../src/spf.c
-                               ../src/statfile.c
-                               ../src/statfile_sync.c
-                               ../src/symbols_cache.c
-                               ../src/url.c
-                               ../src/view.c)
-                               
-# Librspamd mime
-SET(LIBRSPAMDMIMESRC
-                               ../src/expressions.c
-                               ../src/filter.c
-                               ../src/images.c
-                               ../src/message.c
-                               ../src/protocol.c
-                               ../src/smtp_utils.c
-                               ../src/smtp_proto.c
-                               ../src/worker_util.c)
-                               
-SET(TOKENIZERSSRC  ../src/tokenizers/tokenizers.c
-                               ../src/tokenizers/osb.c)
-
-SET(CLASSIFIERSSRC ../src/classifiers/classifiers.c
-                ../src/classifiers/bayes.c
-                               ../src/classifiers/winnow.c)
-# Add targets
-
-# Rspamdutil
-ADD_LIBRARY(rspamd-util ${LINK_TYPE} ${LIBRSPAMDUTILSRC})
-IF(CMAKE_COMPILER_IS_GNUCC)
-SET_TARGET_PROPERTIES(rspamd-util PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing")
-ENDIF(CMAKE_COMPILER_IS_GNUCC)
-
-TARGET_LINK_LIBRARIES(rspamd-util ${RSPAMD_REQUIRED_LIBRARIES})
-TARGET_LINK_LIBRARIES(rspamd-util pcre)
-TARGET_LINK_LIBRARIES(rspamd-util rspamd-ucl)
-TARGET_LINK_LIBRARIES(rspamd-util rspamd-http-parser)
-TARGET_LINK_LIBRARIES(rspamd-util event)
-
-IF(NOT DEBIAN_BUILD)
-SET_TARGET_PROPERTIES(rspamd-util PROPERTIES VERSION ${RSPAMD_VERSION})
-ENDIF(NOT DEBIAN_BUILD)
-
-IF(GLIB_COMPAT)
-       INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/contrib/lgpl")
-       TARGET_LINK_LIBRARIES(rspamd-util glibadditions)
-ENDIF(GLIB_COMPAT)
-
-IF(NO_SHARED MATCHES "OFF")
-       INSTALL(TARGETS rspamd-util 
-       LIBRARY DESTINATION ${LIBDIR} 
-       PUBLIC_HEADER DESTINATION include)
-ENDIF(NO_SHARED MATCHES "OFF")
-
-# Rspamd client
-IF(NOT DEBIAN_BUILD)
-       ADD_LIBRARY(rspamdclient SHARED ${LIBRSPAMDCLIENTSRC})
-       ADD_LIBRARY(rspamdclient_static STATIC ${LIBRSPAMDCLIENTSRC})
-       SET_TARGET_PROPERTIES(rspamdclient PROPERTIES PUBLIC_HEADER "client/librspamdclient.h")
-       IF(CMAKE_COMPILER_IS_GNUCC)
-               SET_TARGET_PROPERTIES(rspamdclient PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing")
-               SET_TARGET_PROPERTIES(rspamdclient_static PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing")
-       ENDIF(CMAKE_COMPILER_IS_GNUCC)
-       TARGET_LINK_LIBRARIES(rspamdclient rspamd-util)
-       TARGET_LINK_LIBRARIES(rspamdclient ${RSPAMD_REQUIRED_LIBRARIES})
-       TARGET_LINK_LIBRARIES(rspamdclient_static rspamd-util)
-       TARGET_LINK_LIBRARIES(rspamdclient_static ${RSPAMD_REQUIRED_LIBRARIES})
-ELSE(NOT DEBIAN_BUILD)
-       ADD_LIBRARY(rspamdclient STATIC ${LIBRSPAMDCLIENTSRC})
-       IF(CMAKE_COMPILER_IS_GNUCC)
-               SET_TARGET_PROPERTIES(rspamdclient PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing")
-       ENDIF(CMAKE_COMPILER_IS_GNUCC)
-       TARGET_LINK_LIBRARIES(rspamdclient rspamd-util)
-       TARGET_LINK_LIBRARIES(rspamdclient ${RSPAMD_REQUIRED_LIBRARIES})
-ENDIF(NOT DEBIAN_BUILD)
-
-IF(NOT DEBIAN_BUILD)
-       SET_TARGET_PROPERTIES(rspamdclient PROPERTIES VERSION ${RSPAMD_VERSION})
-       SET_TARGET_PROPERTIES(rspamdclient_static PROPERTIES VERSION ${RSPAMD_VERSION})
-ENDIF(NOT DEBIAN_BUILD)
-
-IF(GLIB_COMPAT)
-       INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/contrib/lgpl")
-       TARGET_LINK_LIBRARIES(rspamdclient glibadditions)
-ENDIF(GLIB_COMPAT)
-
-IF(NOT DEBIAN_BUILD)
-       INSTALL(TARGETS rspamdclient rspamdclient_static LIBRARY PUBLIC_HEADER 
-               LIBRARY DESTINATION ${LIBDIR} 
-       PUBLIC_HEADER DESTINATION ${INCLUDEDIR}
-               ARCHIVE DESTINATION ${LIBDIR})
-ENDIF(NOT DEBIAN_BUILD)    
-
-    
-# Librspamd-server
-
-#IF(WITH_DB)
-#      LIST(APPEND LIBRSPAMDSERVERSRC ../src/kvstorage_bdb.c)
-#ENDIF(WITH_DB)
-#IF(WITH_SQLITE)
-#      LIST(APPEND LIBRSPAMDSERVERSRC ../src/kvstorage_sqlite.c)
-#ENDIF(WITH_SQLITE)
-                               
-ADD_LIBRARY(rspamd-server ${LINK_TYPE} ${LIBRSPAMDSERVERSRC} ${TOKENIZERSSRC} ${CLASSIFIERSSRC})
-IF(NOT DEBIAN_BUILD)
-SET_TARGET_PROPERTIES(rspamd-server PROPERTIES VERSION ${RSPAMD_VERSION})
-ENDIF(NOT DEBIAN_BUILD)
-SET_TARGET_PROPERTIES(rspamd-server PROPERTIES LINKER_LANGUAGE C COMPILE_FLAGS "-DRSPAMD_LIB")
-TARGET_LINK_LIBRARIES(rspamd-server rspamd-lua)
-TARGET_LINK_LIBRARIES(rspamd-server rspamd-json)
-TARGET_LINK_LIBRARIES(rspamd-server rspamd-cdb)
-TARGET_LINK_LIBRARIES(rspamd-server rspamd-util)   
-IF(LIBJUDY_LIBRARY)
-       TARGET_LINK_LIBRARIES(rspamd-server Judy)
-ENDIF(LIBJUDY_LIBRARY)   
-IF(CMAKE_COMPILER_IS_GNUCC)
-SET_TARGET_PROPERTIES(rspamd-server PROPERTIES COMPILE_FLAGS "-DRSPAMD_LIB -fno-strict-aliasing")
-ENDIF(CMAKE_COMPILER_IS_GNUCC)
-
-IF(WITH_DB)
-       TARGET_LINK_LIBRARIES(rspamd-server db)
-ENDIF(WITH_DB)
-
-IF(OPENSSL_FOUND)
-       TARGET_LINK_LIBRARIES(rspamd-server ${OPENSSL_LIBRARIES})
-ENDIF(OPENSSL_FOUND)
-
-IF(NO_SHARED MATCHES "OFF")
-       INSTALL(TARGETS rspamd-server 
-       LIBRARY DESTINATION ${LIBDIR} 
-       PUBLIC_HEADER DESTINATION ${INCLUDEDIR})
-ENDIF(NO_SHARED MATCHES "OFF")
-    
-# Librspamdmime
-ADD_LIBRARY(rspamd-mime ${LINK_TYPE} ${LIBRSPAMDMIMESRC})
-IF(NOT DEBIAN_BUILD)
-SET_TARGET_PROPERTIES(rspamd-mime PROPERTIES VERSION ${RSPAMD_VERSION})
-ENDIF(NOT DEBIAN_BUILD)
-SET_TARGET_PROPERTIES(rspamd-mime PROPERTIES LINKER_LANGUAGE C)
-SET_TARGET_PROPERTIES(rspamd-mime PROPERTIES COMPILE_FLAGS "-DRSPAMD_LIB")
-TARGET_LINK_LIBRARIES(rspamd-mime rspamd-server)
-TARGET_LINK_LIBRARIES(rspamd-mime rspamd-util)      
-IF(CMAKE_COMPILER_IS_GNUCC)
-SET_TARGET_PROPERTIES(rspamd-mime PROPERTIES COMPILE_FLAGS "-DRSPAMD_LIB -fno-strict-aliasing")
-ENDIF(CMAKE_COMPILER_IS_GNUCC)
-
-IF(NO_SHARED MATCHES "OFF")
-       INSTALL(TARGETS rspamd-mime 
-               LIBRARY DESTINATION ${LIBDIR}  
-       PUBLIC_HEADER DESTINATION ${INCLUDEDIR})
-ENDIF(NO_SHARED MATCHES "OFF")
-
-INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/src")
\ No newline at end of file
diff --git a/lib/client/librspamdclient.c b/lib/client/librspamdclient.c
deleted file mode 100644 (file)
index 52620e1..0000000
+++ /dev/null
@@ -1,1561 +0,0 @@
-/*
- * Copyright (c) 2011, Vsevolod Stakhov
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "librspamdclient.h"
-#include "config.h"
-#include "upstream.h"
-#include "util.h"
-#include "cfg_file.h"
-#include "logger.h"
-
-#define MAX_RSPAMD_SERVERS 255
-#define DEFAULT_CONNECT_TIMEOUT 500
-#define DEFAULT_READ_TIMEOUT 5000
-/* Default connect timeout for sync sockets */
-#define CONNECT_TIMEOUT 3
-#define G_RSPAMD_ERROR rspamd_error_quark ()
-
-#ifndef CRLF
-# define CRLF "\r\n"
-#endif
-
-struct rspamd_server {
-       struct upstream up;
-       guint16 client_port;
-       guint16 controller_port;
-       gchar *name;
-       gchar *controller_name;
-       gchar *host;
-};
-
-struct rspamd_client {
-       struct rspamd_server servers[MAX_RSPAMD_SERVERS];
-       guint servers_num;
-       guint connect_timeout;
-       guint read_timeout;
-       struct in_addr *bind_addr;
-};
-
-struct rspamd_connection {
-       struct rspamd_server *server;
-       struct rspamd_client *client;
-       time_t connection_time;
-       gint socket;
-       union {
-               struct {
-                       struct rspamd_result *result;
-                       struct rspamd_metric *cur_metric;
-               } normal;
-               struct {
-                       struct rspamd_controller_result *result;
-                       enum {
-                               CONTROLLER_READ_REPLY,
-                               CONTROLLER_READ_HEADER,
-                               CONTROLLER_READ_DATA
-                       } state;
-               } controller;
-       } res;
-       gboolean is_controller;
-       GString *in_buf;
-       gint version;
-};
-
-/** Private functions **/
-static inline                   GQuark
-rspamd_error_quark (void)
-{
-       return g_quark_from_static_string ("g-rspamd-error-quark");
-}
-
-static void
-metric_free_func (gpointer arg)
-{
-       struct rspamd_metric            *m = arg;
-
-       g_hash_table_destroy (m->symbols);
-       g_free (m);
-}
-
-static void
-symbol_free_func (gpointer arg)
-{
-       struct rspamd_symbol            *s = arg;
-       GList                           *cur = s->options;
-
-       while (cur) {
-               g_free (cur->data);
-               cur = g_list_next (cur);
-       }
-       g_list_free (s->options);
-       g_free (s);
-}
-
-static struct rspamd_connection *
-rspamd_connect_specific_server (struct rspamd_client *client, gboolean is_control, GError **err, struct rspamd_server *serv)
-{
-       struct rspamd_connection        *new;
-
-       /* Allocate connection */
-       new = g_malloc0 (sizeof (struct rspamd_connection));
-       new->server = serv;
-       new->connection_time = time (NULL);
-       new->client = client;
-       /* Create socket */
-       new->socket = make_universal_socket (serv->host, is_control ? serv->controller_port : serv->client_port,
-                       SOCK_STREAM, TRUE, FALSE, TRUE);
-       if (new->socket == -1) {
-               goto err;
-       }
-       /* Poll waiting for writing */
-       if (poll_sync_socket (new->socket, client->connect_timeout , POLLOUT) <= 0) {
-               errno = ETIMEDOUT;
-               goto err;
-       }
-
-       new->in_buf = g_string_sized_new (BUFSIZ);
-       return new;
-
-       err:
-       if (*err == NULL) {
-               *err = g_error_new (G_RSPAMD_ERROR, errno, "Could not connect to server %s: %s",
-                               serv->name, strerror (errno));
-       }
-       upstream_fail (&serv->up, time (NULL));
-       g_free (new);
-       return NULL;
-}
-
-static struct rspamd_connection *
-rspamd_connect_random_server (struct rspamd_client *client, gboolean is_control, GError **err)
-{
-       struct rspamd_server            *selected = NULL;
-
-       if (client->servers_num == 0) {
-               errno = EINVAL;
-               if (*err == NULL) {
-                       *err = g_error_new (G_RSPAMD_ERROR, 1, "No servers can be reached");
-               }
-               return NULL;
-       }
-       /* Select random server */
-       selected = (struct rspamd_server *)get_random_upstream (client->servers,
-                       client->servers_num, sizeof (struct rspamd_server),
-                       time (NULL), DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS);
-       if (selected == NULL) {
-               errno = EINVAL;
-               if (*err == NULL) {
-                       *err = g_error_new (G_RSPAMD_ERROR, 1, "No servers can be reached");
-               }
-               return NULL;
-       }
-
-       return rspamd_connect_specific_server (client, is_control, err, selected);
-}
-
-static struct rspamd_metric *
-rspamd_create_metric (const gchar *begin, guint len)
-{
-       struct rspamd_metric            *new;
-
-       new = g_malloc0 (sizeof (struct rspamd_metric));
-       new->symbols = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, symbol_free_func);
-       new->name = g_malloc (len + 1);
-       memcpy (new->name, begin, len);
-       new->name[len] = '\0';
-
-       return new;
-}
-
-static struct rspamd_result *
-rspamd_create_result (struct rspamd_connection *c)
-{
-       struct rspamd_result           *new;
-
-       new = g_malloc (sizeof (struct rspamd_result));
-       new->conn = c;
-       new->headers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-       new->metrics = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, metric_free_func);
-       new->is_ok = FALSE;
-
-       return new;
-}
-
-static struct rspamd_controller_result *
-rspamd_create_controller_result (struct rspamd_connection *c)
-{
-       struct rspamd_controller_result  *new;
-
-       new = g_malloc (sizeof (struct rspamd_controller_result));
-       new->conn = c;
-       new->headers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-       new->data = NULL;
-       new->result = g_string_new (NULL);
-       new->code = 0;
-
-       return new;
-}
-
-/*
- * Parse line like RSPAMD/{version} {code} {message}
- */
-static gboolean
-parse_rspamd_first_line (struct rspamd_connection *conn, guint len, GError **err)
-{
-       gchar                           *b = conn->in_buf->str + sizeof("RSPAMD/") - 1, *p, *c;
-       guint                            remain = len - sizeof("RSPAMD/") + 1, state = 0, next_state = 0;
-       gdouble                          dver;
-
-       p = b;
-       c = p;
-       while (p - b <= (gint)remain) {
-               switch (state) {
-               case 0:
-                       /* Read version */
-                       if (g_ascii_isspace (*p)) {
-                               state = 99;
-                               next_state = 1;
-                               dver = strtod (c, NULL);
-                               conn->version = floor (dver * 10 + 0.5);
-                       }
-                       else if (!g_ascii_isdigit (*p) && *p != '.') {
-                               goto err;
-                       }
-                       p ++;
-                       break;
-               case 1:
-                       /* Read code */
-                       if (g_ascii_isspace (*p)) {
-                               state = 99;
-                               next_state = 2;
-                               if (*c == '0') {
-                                       conn->res.normal.result->is_ok = TRUE;
-                               }
-                       }
-                       else if (!g_ascii_isdigit (*p)) {
-                               goto err;
-                       }
-                       p ++;
-                       break;
-               case 2:
-                       /* Read message */
-                       if (g_ascii_isspace (*p) || p - b == (gint)remain) {
-                               state = 99;
-                               next_state = 3;
-                       }
-                       p ++;
-                       break;
-               case 3:
-                       goto err;
-               case 99:
-                       /* Skip spaces */
-                       if (!g_ascii_isspace (*p)) {
-                               state = next_state;
-                               c = p;
-                       }
-                       else {
-                               p ++;
-                       }
-                       break;
-               }
-       }
-
-       if (state != 99) {
-               goto err;
-       }
-
-       return TRUE;
-err:
-       if (*err == NULL) {
-               *err = g_error_new (G_RSPAMD_ERROR, errno, "Invalid protocol line: %*s at pos: %d",
-                               remain, b, (int)(p - b));
-       }
-       upstream_fail (&conn->server->up, conn->connection_time);
-       return FALSE;
-}
-
-/*
- * Parse line like Metric: <name>; <True|False|Skip>; <score> / <required_score>[ / <reject_score>]
- */
-static gboolean
-parse_rspamd_metric_line (struct rspamd_connection *conn, guint len, GError **err)
-{
-       gchar                           *b = conn->in_buf->str + sizeof("Metric:") - 1, *p, *c, *err_str;
-       guint                            remain = len - sizeof("Metric:") + 1, state = 0, next_state = 0;
-       struct rspamd_metric            *new = NULL;
-
-       p = b;
-
-       while (g_ascii_isspace (*p)) {
-               p ++;
-       }
-       c = p;
-
-       while (p - b <= (gint)remain) {
-               switch (state) {
-               case 0:
-                       /* Read metric's name */
-                       if (*p == ';') {
-                               if (p - c <= 1) {
-                                       /* Empty metric name */
-                                       goto err;
-                               }
-                               else {
-                                       /* Create new metric */
-                                       new = rspamd_create_metric (c, p - c);
-                                       if (g_hash_table_lookup (conn->res.normal.result->metrics, new->name) != NULL) {
-                                               /* Duplicate metric */
-                                               metric_free_func (new);
-                                               goto err;
-                                       }
-                                       g_hash_table_insert (conn->res.normal.result->metrics, new->name, new);
-                                       conn->res.normal.cur_metric = new;
-                                       state = 99;
-                                       next_state = 1;
-                               }
-                       }
-                       p ++;
-                       break;
-               case 1:
-                       /* Read boolean result */
-                       if (*p == ';') {
-                               if (p - c >= (gint)sizeof("Skip")) {
-                                       if (memcmp (c, "Skip", p - c - 1) == 0) {
-                                               new->is_skipped = TRUE;
-                                       }
-                               }
-                               state = 99;
-                               next_state = 2;
-                       }
-                       p ++;
-                       break;
-               case 2:
-                       /* Read score */
-                       if (g_ascii_isspace (*p)) {
-                               new->score = strtod (c, &err_str);
-                               if (*err_str != *p) {
-                                       /* Invalid score */
-                                       goto err;
-                               }
-                               state = 99;
-                               next_state = 3;
-                       }
-                       p ++;
-                       break;
-               case 3:
-                       /* Read / */
-                       if (g_ascii_isspace (*p)) {
-                               state = 99;
-                               next_state = 4;
-                       }
-                       else if (*p != '/') {
-                               goto err;
-                       }
-                       p ++;
-                       break;
-               case 4:
-                       /* Read required score */
-                       if (g_ascii_isspace (*p) || p - b == (gint)remain) {
-                               new->required_score = strtod (c, &err_str);
-                               if (*err_str != *p && *err_str != *(p + 1)) {
-                                       /* Invalid score */
-                                       goto err;
-                               }
-                               state = 99;
-                               next_state = 5;
-                       }
-                       p ++;
-                       break;
-               case 5:
-                       /* Read / if it exists */
-                       if (g_ascii_isspace (*p)) {
-                               state = 99;
-                               next_state = 6;
-                       }
-                       else if (*p != '/') {
-                               goto err;
-                       }
-                       p ++;
-                       break;
-               case 6:
-                       /* Read reject score */
-                       if (g_ascii_isspace (*p) || p - b == (gint)remain) {
-                               new->reject_score = strtod (c, &err_str);
-                               if (*err_str != *p && *err_str != *(p + 1)) {
-                                       /* Invalid score */
-                                       goto err;
-                               }
-                               state = 99;
-                       }
-                       p ++;
-                       break;
-               case 99:
-                       /* Skip spaces */
-                       if (!g_ascii_isspace (*p)) {
-                               state = next_state;
-                               c = p;
-                       }
-                       else {
-                               p ++;
-                       }
-                       break;
-               }
-       }
-
-       if (state != 99) {
-               goto err;
-       }
-       return TRUE;
-
-err:
-       if (*err == NULL) {
-               *err = g_error_new (G_RSPAMD_ERROR, errno, "Invalid metric line: %*s at pos: %d, state: %d",
-                       remain, b, (int)(p - b), state);
-       }
-       upstream_fail (&conn->server->up, conn->connection_time);
-       return FALSE;
-}
-
-/*
- * Parse line like Symbol: <name>[(score)]; [option1, [option2 ...]]
- */
-static gboolean
-parse_rspamd_symbol_line (struct rspamd_connection *conn, guint len, GError **err)
-{
-       gchar                           *b = conn->in_buf->str + sizeof("Symbol:") - 1, *p, *c, *err_str, *sym;
-       guint                            remain = len - sizeof("Symbol:") + 1, state = 0, next_state = 0, l;
-       struct rspamd_symbol            *new = NULL;
-
-       p = b;
-       while (g_ascii_isspace (*p)) {
-               p ++;
-       }
-       c = p;
-       while (p - b < (gint)remain) {
-               switch (state) {
-               case 0:
-                       /* Read symbol's name */
-                       if (p - b == (gint)remain - 1 || *p == ';' || *p == '(') {
-                               if (p - c <= 1) {
-                                       /* Empty symbol name */
-                                       goto err;
-                               }
-                               else {
-                                       if (p - b == (gint)remain) {
-                                               l = p - c + 1;
-                                       }
-                                       else {
-                                               if (*p == '(') {
-                                                       next_state = 1;
-                                               }
-                                               else if (*p == ';' ) {
-                                                       next_state = 2;
-                                               }
-                                               l = p - c;
-                                       }
-                                       /* Create new symbol */
-                                       sym = g_malloc (l + 1);
-                                       sym[l] = '\0';
-                                       memcpy (sym, c, l);
-
-                                       if (g_hash_table_lookup (conn->res.normal.cur_metric->symbols, sym) != NULL) {
-                                               /* Duplicate symbol */
-                                               g_free (sym);
-                                               goto err;
-                                       }
-                                       new = g_malloc0 (sizeof (struct rspamd_symbol));
-                                       new->name = sym;
-                                       g_hash_table_insert (conn->res.normal.cur_metric->symbols, sym, new);
-                                       state = 99;
-                               }
-                       }
-                       p ++;
-                       break;
-               case 1:
-                       /* Read symbol's weight */
-                       if (*p == ')') {
-                               new->weight = strtod (c, &err_str);
-                               if (*err_str != *p) {
-                                       /* Invalid weight */
-                                       goto err;
-                               }
-                               if (*(p + 1) == ';') {
-                                       p ++;
-                               }
-                               state = 99;
-                               if (conn->version >= 13) {
-                                       next_state = 2;
-                               }
-                               else {
-                                       next_state = 3;
-                               }
-                       }
-                       p ++;
-                       break;
-               case 2:
-                       /* Read description */
-                       if (*p == ';' || p - b == (gint)remain - 1) {
-                               if (*p == ';') {
-                                       l = p - c;
-                               }
-                               else {
-                                       l = p - c + 1;
-                               }
-
-                               if (l > 0) {
-                                       sym = g_malloc (l + 1);
-                                       sym[l] = '\0';
-                                       memcpy (sym, c, l);
-                                       new->description = sym;
-                               }
-                               state = 99;
-                               next_state = 3;
-                       }
-                       p ++;
-                       break;
-               case 3:
-                       /* Read option */
-                       if (*p == ',' || p - b == (gint)remain - 1) {
-                               /* Insert option into linked list */
-                               l = p - c;
-                               if (p - b == (gint)remain - 1) {
-                                       l ++;
-                               }
-                               sym = g_malloc (l + 1);
-                               sym[l] = '\0';
-                               memcpy (sym, c, l);
-                               new->options = g_list_prepend (new->options, sym);
-                               state = 99;
-                               next_state = 2;
-                       }
-                       p ++;
-                       break;
-               case 99:
-                       /* Skip spaces */
-                       if (!g_ascii_isspace (*p)) {
-                               state = next_state;
-                               c = p;
-                       }
-                       else {
-                               p ++;
-                       }
-                       break;
-               }
-       }
-
-       if (state != 99) {
-               goto err;
-       }
-       return TRUE;
-
-       err:
-       if (*err == NULL) {
-               *err = g_error_new (G_RSPAMD_ERROR, errno, "Invalid symbol line: %*s at pos: %d, at state: %d",
-                               remain, b, (int)(p - b), state);
-       }
-       upstream_fail (&conn->server->up, conn->connection_time);
-       return FALSE;
-}
-
-/*
- * Parse line like Action: <action>
- */
-static gboolean
-parse_rspamd_action_line (struct rspamd_connection *conn, guint len, GError **err)
-{
-       gchar                           *b = conn->in_buf->str + sizeof("Action:") - 1, *p, *c, *sym;
-       guint                            remain = len - sizeof("Action:") + 1, state = 0, next_state = 0;
-
-       p = b;
-       c = b;
-       while (p - b <= (gint)remain) {
-               switch (state) {
-               case 0:
-                       /* Read action */
-                       if (g_ascii_isspace (*p)) {
-                               state = 99;
-                               next_state = 1;
-                       }
-                       else {
-                               state = 1;
-                       }
-                       break;
-               case 1:
-                       if (p - b == (gint)remain) {
-                               if (p - c <= 1) {
-                                       /* Empty action name */
-                                       goto err;
-                               }
-                               else {
-                                       /* Create new action */
-                                       sym = g_malloc (p - c + 2);
-                                       sym[p - c + 1] = '\0';
-                                       memcpy (sym, c, p - c + 1);
-                                       conn->res.normal.cur_metric->action = sym;
-                                       state = 99;
-                               }
-                       }
-                       p ++;
-                       break;
-               case 99:
-                       /* Skip spaces */
-                       if (!g_ascii_isspace (*p)) {
-                               state = next_state;
-                               c = p;
-                       }
-                       else {
-                               p ++;
-                       }
-                       break;
-               }
-       }
-
-       if (state != 99) {
-               goto err;
-       }
-       return TRUE;
-
-       err:
-       if (*err == NULL) {
-               *err = g_error_new (G_RSPAMD_ERROR, errno, "Invalid action line: %*s at pos: %d",
-                               remain, b, (int)(p - b));
-       }
-       upstream_fail (&conn->server->up, conn->connection_time);
-       return FALSE;
-}
-
-/*
- * Parse line like Header: <value>
- */
-static gboolean
-parse_rspamd_header_line (struct rspamd_connection *conn, guint len, GError **err)
-{
-       gchar                           *b = conn->in_buf->str, *p, *c, *hname = NULL, *hvalue = NULL;
-       guint                            remain = len, state = 0, next_state = 0, clen;
-
-       p = b;
-       c = b;
-       while (p - b <= (gint)remain) {
-               switch (state) {
-               case 0:
-                       /* Read header name */
-                       if (*p == ':') {
-                               if (p - c <= 1) {
-                                       /* Empty header name */
-                                       goto err;
-                               }
-                               else {
-                                       /* Create header name */
-                                       hname = g_malloc (p - c + 1);
-                                       hname[p - c] = '\0';
-                                       memcpy (hname, c, p - c);
-                                       next_state = 1;
-                                       state = 99;
-                               }
-                       }
-                       p ++;
-                       break;
-               case 1:
-                       if (p - b == (gint)remain) {
-                               if (p - c <= 1) {
-                                       /* Empty action name */
-                                       goto err;
-                               }
-                               else {
-                                       /* Create header value */
-                                       hvalue = g_malloc (p - c + 2);
-                                       hvalue[p - c + 1] = '\0';
-                                       memcpy (hvalue, c, p - c + 1);
-                                       if (conn->is_controller) {
-                                               if (g_ascii_strcasecmp (hname, "Content-Length") == 0) {
-                                                       /* Preallocate data buffer */
-                                                       errno = 0;
-                                                       clen = strtoul (hvalue, NULL, 10);
-                                                       if (errno == 0 && clen > 0) {
-                                                               conn->res.controller.result->data = g_string_sized_new (clen);
-                                                       }
-                                               }
-                                               g_hash_table_replace (conn->res.controller.result->headers, hname, hvalue);
-                                       }
-                                       else {
-                                               g_hash_table_replace (conn->res.normal.result->headers, hname, hvalue);
-                                       }
-                                       state = 99;
-                               }
-                       }
-                       p ++;
-                       break;
-               case 99:
-                       /* Skip spaces */
-                       if (!g_ascii_isspace (*p)) {
-                               state = next_state;
-                               c = p;
-                       }
-                       else {
-                               p ++;
-                       }
-                       break;
-               }
-       }
-
-       if (state != 99) {
-               goto err;
-       }
-       return TRUE;
-
-err:
-       if (*err == NULL) {
-               *err = g_error_new (G_RSPAMD_ERROR, errno, "Invalid header line: %*s at pos: %d",
-                               remain, b, (int)(p - b));
-       }
-       if (hname) {
-               g_free (hname);
-       }
-       if (hvalue) {
-               g_free (hvalue);
-       }
-       upstream_fail (&conn->server->up, conn->connection_time);
-       return FALSE;
-}
-
-static gboolean
-parse_rspamd_controller_reply (struct rspamd_connection *conn, guint len, GError **err)
-{
-       gchar                           *b = conn->in_buf->str, *p, *c;
-       const gchar                                              http_rep[] = "HTTP/1.0 ";
-       guint                            remain = len, state = 0, next_state = 0;
-
-       /* First of all skip "HTTP/1.0 " line */
-       if (len < sizeof (http_rep) || memcmp (b, http_rep, sizeof (http_rep) - 1) != 0) {
-               g_set_error (err, G_RSPAMD_ERROR, -1, "Invalid reply line");
-               return FALSE;
-       }
-       b += sizeof (http_rep) - 1;
-       p = b;
-       c = b;
-       remain -= sizeof (http_rep) - 1;
-
-       while (p - b <= (gint)remain) {
-               switch (state) {
-               case 0:
-                       /* Try to get code */
-                       if (g_ascii_isdigit (*p)) {
-                               p ++;
-                       }
-                       else if (g_ascii_isspace (*p)) {
-                               conn->res.controller.result->code = atoi (c);
-                               next_state = 1;
-                               state = 99;
-                       }
-                       else {
-                               goto err;
-                       }
-                       break;
-               case 1:
-                       /* Get reply string */
-                       if (p - b == (gint)remain) {
-                               if (p - c <= 0) {
-                                       /* Empty action name */
-                                       goto err;
-                               }
-                               else {
-                                       /* Create header value */
-                                       conn->res.controller.result->result = g_string_sized_new (p - c + 1);
-                                       g_string_append_len (conn->res.controller.result->result, c, p - c);
-                                       state = 99;
-                               }
-                       }
-                       p ++;
-                       break;
-               case 99:
-                       /* Skip spaces */
-                       if (!g_ascii_isspace (*p)) {
-                               state = next_state;
-                               c = p;
-                       }
-                       else {
-                               p ++;
-                       }
-                       break;
-               }
-       }
-
-       if (state != 99) {
-               goto err;
-       }
-
-       conn->res.controller.state = CONTROLLER_READ_HEADER;
-
-       return TRUE;
-
-err:
-       if (*err == NULL) {
-               *err = g_error_new (G_RSPAMD_ERROR, errno, "Invalid reply line: %*s at pos: %d",
-                               remain, b, (int)(p - b));
-       }
-       return FALSE;
-}
-
-static gboolean
-parse_rspamd_reply_line (struct rspamd_connection *c, guint len, GError **err)
-{
-       gchar                           *p = c->in_buf->str;
-
-       if (c->is_controller) {
-               switch (c->res.controller.state) {
-               case CONTROLLER_READ_REPLY:
-                       return parse_rspamd_controller_reply (c, len, err);
-                       break;
-               case CONTROLLER_READ_HEADER:
-                       if (len == 0) {
-                               /* End of headers */
-                               c->res.controller.state = CONTROLLER_READ_DATA;
-                               if (c->res.controller.result->data == NULL) {
-                                       /* Cannot detect size as controller didn't send Content-Length header, so guess it */
-                                       c->res.controller.result->data = g_string_new (NULL);
-                               }
-                               return TRUE;
-                       }
-                       else {
-                               return parse_rspamd_header_line (c, len, err);
-                       }
-                       break;
-               case CONTROLLER_READ_DATA:
-                       g_string_append_len (c->res.controller.result->data, p, len);
-                       g_string_append_len (c->res.controller.result->data, CRLF, 2);
-                       return TRUE;
-                       break;
-               }
-       }
-       else {
-               /*
-                * In fact we have 3 states of parsing:
-                * 1) we have current metric and parse symbols
-                * 2) we have no current metric and skip everything to headers hash
-                * 3) we have current metric but got not symbol but header -> put it into headers hash
-                * Line is parsed using specific state machine
-                */
-               if (len > 0) {
-                       if (c->res.normal.cur_metric == NULL) {
-                               if (len > sizeof ("RSPAMD/") && memcmp (p, "RSPAMD/", sizeof ("RSPAMD/") - 1) == 0) {
-                                       return parse_rspamd_first_line (c, len, err);
-                               }
-                               else if (len > sizeof ("Metric:") && memcmp (p, "Metric:", sizeof("Metric:") - 1) == 0) {
-                                       return parse_rspamd_metric_line (c, len, err);
-                               }
-                               else {
-                                       return parse_rspamd_header_line (c, len, err);
-                               }
-                       }
-                       else {
-                               if (len > sizeof ("Metric:") && memcmp (p, "Metric:", sizeof("Metric:") - 1) == 0) {
-                                       return parse_rspamd_metric_line (c, len, err);
-                               }
-                               else if (len > sizeof ("Symbol:") && memcmp (p, "Symbol:", sizeof("Symbol:") - 1) == 0) {
-                                       return parse_rspamd_symbol_line (c, len, err);
-                               }
-                               else if (len > sizeof ("Action:") && memcmp (p, "Action:", sizeof("Action:") - 1) == 0) {
-                                       return parse_rspamd_action_line (c, len, err);
-                               }
-                               else {
-                                       return parse_rspamd_header_line (c, len, err);
-                               }
-                       }
-               }
-               else {
-                       /* TODO: here we should parse commands that contains data, like PROCESS */
-                       return TRUE;
-               }
-       }
-
-       /* Not reached */
-       return FALSE;
-}
-
-static gboolean
-read_rspamd_reply_line (struct rspamd_connection *c, GError **err)
-{
-       gint                             len, r;
-       char                             p;
-
-       /* Try to obtain string from the input buffer */
-       if (c->in_buf->len > 0) {
-               len = 0;
-               while (len < (gint)c->in_buf->len) {
-                       p = c->in_buf->str[len];
-                       if (p == '\n') {
-                               if (parse_rspamd_reply_line (c, len - 1, err)) {
-                                       /* Move remaining buffer to the begin of string */
-                                       c->in_buf = g_string_erase (c->in_buf, 0, len + 1);
-                                       len = 0;
-                               }
-                               else {
-                                       return FALSE;
-                               }
-                       }
-                       len ++;
-               }
-       }
-       /* Poll socket */
-       if ((r = poll_sync_socket (c->socket, c->client->read_timeout, POLL_IN)) <= 0) {
-               if (*err == NULL) {
-                       if (r == 0) {
-                               errno = ETIMEDOUT;
-                       }
-                       *err = g_error_new (G_RSPAMD_ERROR, errno, "Cannot read reply from rspamd server %s: %s",
-                                       c->server->name, strerror (errno));
-               }
-               upstream_fail (&c->server->up, c->connection_time);
-               return FALSE;
-       }
-       if (c->in_buf->allocated_len - c->in_buf->len < BUFSIZ / 2) {
-               /* Grow buffer */
-               c->in_buf = g_string_set_size (c->in_buf, c->in_buf->allocated_len * 2);
-       }
-       /* Read new data to a string */
-       if ((r = read (c->socket,
-                       c->in_buf->str + c->in_buf->len,
-                       c->in_buf->allocated_len - c->in_buf->len)) > 0) {
-               /* Try to parse remaining data */
-               c->in_buf->len += r;
-               return read_rspamd_reply_line (c, err);
-       }
-
-       return FALSE;
-}
-
-/*
- * More or less portable version of sendfile
- */
-static gboolean
-rspamd_sendfile (gint sock, gint fd, GError **err)
-{
-
-       /* Make socket blocking for further operations */
-       make_socket_blocking (sock);
-#ifdef HAVE_SENDFILE
-# if defined(FREEBSD) || defined(DARWIN)
-       off_t                           off = 0;
-#  if defined(FREEBSD)
-       /* FreeBSD version */
-       if (sendfile (fd, sock, 0, 0, NULL, &off, 0) != 0) {
-#  elif defined(DARWIN)
-       /* Darwin version */
-       if (sendfile (fd, sock, 0, &off, NULL, 0) != 0) {
-#  endif
-               goto err;
-       }
-# else
-       ssize_t                         r;
-       off_t                           off = 0;
-       struct stat                     st;
-
-       fstat (fd, &st);
-       /* Linux version */
-       r = sendfile (sock, fd, &off, st.st_size);
-       if (r == -1) {
-               goto err;
-       }
-# endif
-#else
-       /* Emulating version */
-       ssize_t                         r;
-       gchar                           buf[BUFSIZ];
-
-       while ((r = read (fd, buf, sizeof (buf))) > 0) {
-               if ((r = write (sock, buf, r)) != r) {
-                       goto err;
-               }
-       }
-#endif
-       make_socket_nonblocking (sock);
-
-       return TRUE;
-
-err:
-       if (*err == NULL) {
-               *err = g_error_new (G_RSPAMD_ERROR, errno, "Sendfile error: %s",
-                       strerror (errno));
-       }
-       return FALSE;
-}
-
-struct hash_iter_cb {
-       gchar *buf;
-       gsize size;
-       gsize pos;
-};
-
-static void
-rspamd_hash_iter_cb (gpointer key, gpointer value, gpointer ud)
-{
-       struct hash_iter_cb            *cd = ud;
-
-       cd->pos += snprintf (cd->buf + cd->pos, cd->size - cd->pos,
-                       "%s: %s\r\n", (const gchar *)key, (const gchar *)value);
-}
-
-static gboolean
-rspamd_send_normal_command (struct rspamd_connection *c, const gchar *command,
-               gsize clen, GHashTable *headers, GError **err)
-{
-       gchar                           outbuf[16384];
-       gint                            r;
-       struct hash_iter_cb             cbdata;
-
-       /* Write command */
-       r = snprintf (outbuf, sizeof (outbuf), "%s RSPAMC/1.3\r\n", command);
-       r += snprintf (outbuf + r, sizeof (outbuf) - r, "Content-Length: %lu\r\n", (unsigned long)clen);
-       /* Iterate through headers */
-       if (headers != NULL) {
-               cbdata.size = sizeof (outbuf);
-               cbdata.pos = r;
-               cbdata.buf = outbuf;
-               g_hash_table_foreach (headers, rspamd_hash_iter_cb, &cbdata);
-               r = cbdata.pos;
-       }
-       r += snprintf (outbuf + r, sizeof (outbuf) - r, "\r\n");
-
-       if ((r = write (c->socket, outbuf, r)) == -1) {
-               if (*err == NULL) {
-                       *err = g_error_new (G_RSPAMD_ERROR, errno, "Write error: %s",
-                               strerror (errno));
-               }
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
-static void
-rspamd_free_connection (struct rspamd_connection *c)
-{
-       make_socket_blocking (c->socket);
-       (void)close (c->socket);
-       g_string_free (c->in_buf, TRUE);
-
-       g_free (c);
-}
-
-
-
-static gboolean
-rspamd_send_controller_command (struct rspamd_connection *c, const gchar *command, const gchar *password, GHashTable *in_headers, gint fd, GByteArray *data, GError **err)
-{
-       struct iovec                                             iov[2];
-       gchar                                                            outbuf[BUFSIZ];
-       gint                                                             r;
-       struct stat                                                      st;
-       struct hash_iter_cb                      cbdata;
-
-       /* Form a request */
-       r = rspamd_snprintf (outbuf, sizeof (outbuf), "GET / HTTP/1.0" CRLF "Command: %s" CRLF, command);
-       /* Content length */
-       if (fd != -1) {
-               if (fstat (fd, &st) == -1) {
-                       g_set_error (err, G_RSPAMD_ERROR, errno, "Stat error: %s", strerror (errno));
-                       goto err;
-               }
-               r += rspamd_snprintf (outbuf + r, sizeof (outbuf) - r, "Content-Length: %z" CRLF, st.st_size);
-       }
-       else if (data && data->len > 0) {
-               r += rspamd_snprintf (outbuf + r, sizeof (outbuf) - r, "Content-Length: %z" CRLF, data->len);
-       }
-       /* Password */
-       if (password != NULL) {
-               r += rspamd_snprintf (outbuf + r, sizeof (outbuf) - r, "Password: %s" CRLF, password);
-       }
-       /* Other headers */
-       if (in_headers != NULL) {
-               cbdata.size = sizeof (outbuf);
-               cbdata.pos = r;
-               cbdata.buf = outbuf;
-               g_hash_table_foreach (in_headers, rspamd_hash_iter_cb, &cbdata);
-               r = cbdata.pos;
-       }
-       r += rspamd_snprintf (outbuf + r, sizeof (outbuf) - r, CRLF);
-
-
-       /* Assume that a socket is in blocking mode */
-       if (fd != -1) {
-#ifdef LINUX
-               if (send (c->socket, outbuf, r, MSG_MORE) == -1) {
-                       g_set_error (err, G_RSPAMD_ERROR, errno, "Send error: %s", strerror (errno));
-                       goto err;
-               }
-#else
-               if (send (c->socket, outbuf, r, 0) == -1) {
-                       g_set_error (err, G_RSPAMD_ERROR, errno, "Send error: %s", strerror (errno));
-                       goto err;
-               }
-#endif
-               if (!rspamd_sendfile (c->socket, fd, err)) {
-                       goto err;
-               }
-       }
-       else if (data && data->len > 0) {
-               /* Use iovec */
-               iov[0].iov_base = outbuf;
-               iov[0].iov_len = r;
-               iov[1].iov_base = data->data;
-               iov[1].iov_len = data->len;
-
-               if (writev (c->socket, iov, G_N_ELEMENTS (iov)) == -1) {
-                       g_set_error (err, G_RSPAMD_ERROR, errno, "Writev error: %s", strerror (errno));
-                       goto err;
-               }
-       }
-       else {
-               /* Just write request */
-               if (send (c->socket, outbuf, r, 0) == -1) {
-                       g_set_error (err, G_RSPAMD_ERROR, errno, "Send error: %s", strerror (errno));
-                       goto err;
-               }
-       }
-
-       return TRUE;
-err:
-       return FALSE;
-}
-
-/** Public API **/
-
-/*
- * Init rspamd client library
- */
-struct rspamd_client*
-rspamd_client_init_binded (const struct in_addr *addr)
-{
-       struct rspamd_client           *client;
-
-       client = g_malloc0 (sizeof (struct rspamd_client));
-       client->read_timeout = DEFAULT_READ_TIMEOUT;
-       client->connect_timeout = DEFAULT_CONNECT_TIMEOUT;
-
-       if (addr != NULL) {
-               client->bind_addr = g_malloc (sizeof (struct in_addr));
-               memcpy (client->bind_addr, addr, sizeof (struct in_addr));
-       }
-
-       return client;
-}
-
-struct rspamd_client*
-rspamd_client_init (void)
-{
-       return rspamd_client_init_binded (NULL);
-}
-
-/*
- * Add rspamd server
- */
-gboolean
-rspamd_add_server (struct rspamd_client *client, const gchar *host, guint16 port,
-               guint16 controller_port, GError **err)
-{
-       struct rspamd_server           *new;
-       gint                                                    nlen, i;
-
-       g_assert (client != NULL);
-
-       /* Avoid duplicates */
-       for (i = 0; i < (gint)client->servers_num; i ++) {
-               new = &client->servers[i];
-               if (new->client_port == port && new->controller_port == controller_port && strcmp (host, new->host) == 0) {
-                       /* Duplicate */
-                       return TRUE;
-               }
-       }
-
-       if (client->servers_num >= MAX_RSPAMD_SERVERS) {
-               if (*err == NULL) {
-                       *err = g_error_new (G_RSPAMD_ERROR, 1, "Maximum number of servers reached: %d", MAX_RSPAMD_SERVERS);
-               }
-               return FALSE;
-       }
-       new = &client->servers[client->servers_num];
-
-       new->client_port = port;
-       new->controller_port = controller_port;
-       new->host = g_strdup (host);
-       nlen = strlen (host) + sizeof ("65535") + 1;
-       new->name = g_malloc (nlen);
-       new->controller_name = g_malloc (nlen);
-       if (*host != '/') {
-               rspamd_snprintf (new->name, nlen, "%s:%d", host, (gint)port);
-               rspamd_snprintf (new->controller_name, nlen, "%s:%d", host, (gint)controller_port);
-       }
-       else {
-               rspamd_snprintf (new->name, nlen, "unix:%s", host);
-               rspamd_snprintf (new->controller_name, nlen, "unix:%s", host);
-       }
-
-       client->servers_num ++;
-       return TRUE;
-}
-
-/*
- * Set timeouts (values in milliseconds)
- */
-void
-rspamd_set_timeout (struct rspamd_client *client, guint connect_timeout, guint read_timeout)
-{
-       g_assert (client != NULL);
-
-       if (connect_timeout > 0) {
-               client->connect_timeout = connect_timeout;
-       }
-       if (read_timeout > 0) {
-               client->read_timeout = read_timeout;
-       }
-}
-
-/*
- * Scan message from memory
- */
-struct rspamd_result *
-rspamd_scan_memory (struct rspamd_client *client, const guchar *message, gsize length, GHashTable *headers, GError **err)
-{
-       struct rspamd_connection             *c;
-       struct rspamd_result                 *res = NULL;
-
-       g_assert (client != NULL);
-       g_assert (length > 0);
-
-       /* Connect to server */
-       c = rspamd_connect_random_server (client, FALSE, err);
-
-       if (c == NULL) {
-               return NULL;
-       }
-
-       /* Set socket blocking for writing */
-       make_socket_blocking (c->socket);
-       /* Send command */
-       if (!rspamd_send_normal_command (c, "SYMBOLS", length, headers, err)) {
-               return NULL;
-       }
-
-       /* Send message */
-       if (write (c->socket, message, length) == -1) {
-               if (*err == NULL) {
-                       *err = g_error_new (G_RSPAMD_ERROR, errno, "Write error: %s",
-                                       strerror (errno));
-               }
-               return NULL;
-       }
-
-       /* Create result structure */
-       res = rspamd_create_result (c);
-       c->res.normal.result = res;
-       c->is_controller = FALSE;
-       /* Restore non-blocking mode for reading operations */
-       make_socket_nonblocking (c->socket);
-
-       /* Read result cycle */
-       while (read_rspamd_reply_line (c, err));
-
-       upstream_ok (&c->server->up, c->connection_time);
-       return res;
-}
-
-/*
- * Scan message from file
- */
-struct rspamd_result *
-rspamd_scan_file (struct rspamd_client *client, const guchar *filename, GHashTable *headers, GError **err)
-{
-       gint                                 fd;
-       g_assert (client != NULL);
-
-       /* Open file */
-       if ((fd = open (filename, O_RDONLY)) == -1) {
-               if (*err == NULL) {
-                       *err = g_error_new (G_RSPAMD_ERROR, errno, "Open error for file %s: %s",
-                                       filename, strerror (errno));
-               }
-               return NULL;
-       }
-
-       return rspamd_scan_fd (client, fd, headers, err);
-}
-
-/*
- * Scan message from fd
- */
-struct rspamd_result *
-rspamd_scan_fd (struct rspamd_client *client, int fd, GHashTable *headers, GError **err)
-{
-       struct rspamd_connection             *c;
-       struct rspamd_result                 *res = NULL;
-       struct stat                           st;
-
-       g_assert (client != NULL);
-
-       /* Connect to server */
-       c = rspamd_connect_random_server (client, FALSE, err);
-
-       if (c == NULL) {
-               return NULL;
-       }
-
-       /* Get length */
-       if (fstat (fd, &st) == -1) {
-               if (*err == NULL) {
-                       *err = g_error_new (G_RSPAMD_ERROR, errno, "Stat error: %s",
-                                       strerror (errno));
-               }
-               return NULL;
-       }
-       if (st.st_size == 0) {
-               if (*err == NULL) {
-                       *err = g_error_new (G_RSPAMD_ERROR, -1, "File has zero length");
-               }
-               return NULL;
-       }
-       /* Set socket blocking for writing */
-       make_socket_blocking (c->socket);
-       /* Send command */
-       if (!rspamd_send_normal_command (c, "SYMBOLS", (gsize)st.st_size, headers, err)) {
-               return NULL;
-       }
-
-       /* Send message */
-       if (!rspamd_sendfile (c->socket, fd, err)) {
-               return NULL;
-       }
-
-       /* Create result structure */
-       res = rspamd_create_result (c);
-       c->is_controller = FALSE;
-       c->res.normal.result = res;
-       /* Restore non-blocking mode for reading operations */
-       make_socket_nonblocking (c->socket);
-
-       /* Read result cycle */
-       while (read_rspamd_reply_line (c, err));
-
-       upstream_ok (&c->server->up, c->connection_time);
-       return res;
-}
-
-/*
- * Send a common controller command to all servers
- */
-static void
-rspamd_controller_command_single (struct rspamd_client* client, const gchar *command, const gchar *password,
-               GHashTable *in_headers, GByteArray *mem, gint fd, GError **err,
-               struct rspamd_controller_result *res, struct rspamd_server *serv)
-{
-       struct rspamd_connection             *c;
-
-       /* Connect to server */
-       c = rspamd_connect_specific_server (client, FALSE, err, serv);
-
-       if (c == NULL) {
-               return;
-       }
-
-       res->conn = c;
-       /* Set socket blocking for writing */
-       make_socket_blocking (c->socket);
-
-       /* Send command */
-       if (!rspamd_send_controller_command (c, command, password, in_headers, fd, mem, err)) {
-               res->result = g_string_new (*err != NULL ? (*err)->message : "unknown error");
-               res->code = 500;
-               return;
-       }
-       c->is_controller = TRUE;
-       c->res.controller.result = res;
-
-       /* Restore non-blocking mode for reading operations */
-       make_socket_nonblocking (c->socket);
-
-       /* Read result cycle */
-       while (read_rspamd_reply_line (c, err));
-
-       upstream_ok (&c->server->up, c->connection_time);
-}
-
-/*
- * Send a common controller command to all servers
- */
-static GList*
-rspamd_controller_command_common (struct rspamd_client* client, const gchar *command, const gchar *password,
-               GHashTable *in_headers, GByteArray *mem, gint fd, GError **err)
-{
-       struct rspamd_server                            *serv;
-       struct rspamd_controller_result         *res;
-       GList                                                           *res_list = NULL;
-       guint                                                            i;
-
-       g_assert (client != NULL);
-
-       for (i = 0; i < client->servers_num; i ++) {
-               serv = &client->servers[i];
-               res = rspamd_create_controller_result (NULL);
-               res->server_name = serv->controller_name;
-               res_list = g_list_prepend (res_list, res);
-               /* Fill result */
-               rspamd_controller_command_single (client, command, password, in_headers, mem, fd, err, res, serv);
-       }
-
-       return res_list;
-}
-
-/**
- * Perform a simple controller command on all rspamd servers
- * @param client  rspamd client
- * @param command command to send
- * @param password password (NULL if no password required)
- * @param in_headers custom in headers, specific for this command (or NULL)
- * @param err error object (should be pointer to NULL object)
- * @return list of rspamd_controller_result structures for each server
- */
-GList*
-rspamd_controller_command_simple (struct rspamd_client* client, const gchar *command, const gchar *password,
-               GHashTable *in_headers, GError **err)
-{
-       return rspamd_controller_command_common (client, command, password, in_headers, NULL, -1, err);
-}
-
-/**
- * Perform a controller command on all rspamd servers with in memory argument
- * @param client  rspamd client
- * @param command command to send
- * @param password password (NULL if no password required)
- * @param in_headers custom in headers, specific for this command (or NULL)
- * @param message data to pass to the controller
- * @param length its length
- * @param err error object (should be pointer to NULL object)
- * @return list of rspamd_controller_result structures for each server
- */
-GList*
-rspamd_controller_command_memory (struct rspamd_client* client, const gchar *command, const gchar *password,
-               GHashTable *in_headers, const guchar *message, gsize length, GError **err)
-{
-       GByteArray                                                              ba;
-       ba.data = (guint8 *)message;
-       ba.len = length;
-       return rspamd_controller_command_common (client, command, password, in_headers, &ba, -1, err);
-}
-
-/**
- * Perform a controller command on all rspamd servers with descriptor argument
- * @param client  rspamd client
- * @param command command to send
- * @param password password (NULL if no password required)
- * @param in_headers custom in headers, specific for this command (or NULL)
- * @param fd file descriptor of data
- * @param err error object (should be pointer to NULL object)
- * @return list of rspamd_controller_result structures for each server
- */
-GList*
-rspamd_controller_command_fd (struct rspamd_client* client, const gchar *command, const gchar *password,
-               GHashTable *in_headers, gint fd, GError **err)
-{
-       return rspamd_controller_command_common (client, command, password, in_headers, NULL, fd, err);
-}
-
-/**
- * Perform a controller command on all rspamd servers with descriptor argument
- * @param client  rspamd client
- * @param command command to send
- * @param password password (NULL if no password required)
- * @param in_headers custom in headers, specific for this command (or NULL)
- * @param filename filename of data
- * @param err error object (should be pointer to NULL object)
- * @return list of rspamd_controller_result structures for each server
- */
-GList*
-rspamd_controller_command_file (struct rspamd_client* client, const gchar *command, const gchar *password,
-               GHashTable *in_headers, const gchar *filename, GError **err)
-{
-       gint                                                                    fd;
-
-       /* Open file */
-       if ((fd = open (filename, O_RDONLY)) == -1) {
-               if (*err == NULL) {
-                       *err = g_error_new (G_RSPAMD_ERROR, errno, "Open error for file %s: %s",
-                                       filename, strerror (errno));
-               }
-               return NULL;
-       }
-       return rspamd_controller_command_common (client, command, password, in_headers, NULL, fd, err);
-}
-
-
-/*
- * Free results
- */
-void
-rspamd_free_result (struct rspamd_result *result)
-{
-       g_assert (result != NULL);
-
-       g_hash_table_destroy (result->headers);
-       g_hash_table_destroy (result->metrics);
-       if (result->conn) {
-               rspamd_free_connection (result->conn);
-       }
-}
-
-void
-rspamd_free_controller_result (struct rspamd_controller_result *result)
-{
-       g_assert (result != NULL);
-
-       g_hash_table_destroy (result->headers);
-       g_string_free (result->result, TRUE);
-       if (result->data) {
-               g_string_free (result->data, TRUE);
-       }
-       if (result->conn) {
-               rspamd_free_connection (result->conn);
-       }
-}
-
-/*
- * Close library and free associated resources
- */
-void
-rspamd_client_close (struct rspamd_client *client)
-{
-       struct rspamd_server                    *serv;
-       guint                                                    i;
-
-       if (client->bind_addr) {
-               g_free (client->bind_addr);
-       }
-
-       /* Cleanup servers */
-       for (i = 0; i < client->servers_num; i ++) {
-               serv = &client->servers[i];
-               g_free (serv->host);
-               g_free (serv->name);
-               g_free (serv->controller_name);
-       }
-
-       g_free (client);
-}
diff --git a/lib/client/librspamdclient.h b/lib/client/librspamdclient.h
deleted file mode 100644 (file)
index 828bcd4..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-#ifndef LIBRSPAMD_CLIENT_H
-#define LIBRSPAMD_CLIENT_H
-
-#include <glib.h>
-
-/**
- * Struct for representing symbols
- */
-struct rspamd_symbol {
-       gchar *name;                /**< name */
-       gchar *description;             /**< description */
-       double weight;                  /**< weight */
-       GList *options;                 /**< List of options (as const gchar *) */
-};
-
-/**
- * Struct for representing metrics
- */
-struct rspamd_metric {
-       gchar *name;
-       gchar *action;
-       double score;
-       double required_score;
-       double reject_score;
-       gboolean is_skipped;
-       GHashTable *symbols;
-};
-
-struct rspamd_connection;
-struct rspamd_client;
-struct in_addr;
-
-/**
- * Result of scan
- */
-struct rspamd_result {
-       struct rspamd_connection *conn;
-       gboolean is_ok;
-       GHashTable *metrics;
-       GHashTable *headers;
-};
-
-/**
- * Result of controller command
- */
-struct rspamd_controller_result {
-       struct rspamd_connection *conn;
-       const gchar *server_name;
-       gint code;
-       GString *result;
-       GHashTable *headers;
-       GString *data;
-};
-
-/**
- * Init rspamd client library
- */
-struct rspamd_client* rspamd_client_init (void);
-
-/**
- * Init rspamd client library and bind it
- */
-struct rspamd_client* rspamd_client_init_binded (const struct in_addr *local_addr);
-
-/**
- * Add rspamd server
- */
-gboolean rspamd_add_server (struct rspamd_client* client, const gchar *host,
-               guint16 port, guint16 controller_port, GError **err);
-
-/**
- * Set timeouts (values in milliseconds)
- */
-void rspamd_set_timeout (struct rspamd_client* client, guint connect_timeout, guint read_timeout);
-
-/**
- * Scan message from memory
- */
-struct rspamd_result * rspamd_scan_memory (struct rspamd_client* client, const guchar *message, gsize length, GHashTable *headers, GError **err);
-
-/**
- * Scan message from file
- */
-struct rspamd_result * rspamd_scan_file (struct rspamd_client* client, const guchar *filename, GHashTable *headers, GError **err);
-
-/**
- * Scan message from fd
- */
-struct rspamd_result * rspamd_scan_fd (struct rspamd_client* client, int fd, GHashTable *headers, GError **err);
-
-/**
- * Perform a simple controller command on all rspamd servers
- * @param client  rspamd client
- * @param command command to send
- * @param password password (NULL if no password required)
- * @param in_headers custom in headers, specific for this command (or NULL)
- * @param err error object (should be pointer to NULL object)
- * @return list of rspamd_controller_result structures for each server
- */
-GList* rspamd_controller_command_simple (struct rspamd_client* client, const gchar *command, const gchar *password,
-               GHashTable *in_headers, GError **err);
-
-/**
- * Perform a controller command on all rspamd servers with in memory argument
- * @param client  rspamd client
- * @param command command to send
- * @param password password (NULL if no password required)
- * @param in_headers custom in headers, specific for this command (or NULL)
- * @param message data to pass to the controller
- * @param length its length
- * @param err error object (should be pointer to NULL object)
- * @return list of rspamd_controller_result structures for each server
- */
-GList* rspamd_controller_command_memory (struct rspamd_client* client, const gchar *command, const gchar *password,
-               GHashTable *in_headers, const guchar *message, gsize length, GError **err);
-
-/**
- * Perform a controller command on all rspamd servers with descriptor argument
- * @param client  rspamd client
- * @param command command to send
- * @param password password (NULL if no password required)
- * @param in_headers custom in headers, specific for this command (or NULL)
- * @param fd file descriptor of data
- * @param err error object (should be pointer to NULL object)
- * @return list of rspamd_controller_result structures for each server
- */
-GList* rspamd_controller_command_fd (struct rspamd_client* client, const gchar *command, const gchar *password,
-               GHashTable *in_headers, gint fd, GError **err);
-
-/**
- * Perform a controller command on all rspamd servers with descriptor argument
- * @param client  rspamd client
- * @param command command to send
- * @param password password (NULL if no password required)
- * @param in_headers custom in headers, specific for this command (or NULL)
- * @param filename filename of data
- * @param err error object (should be pointer to NULL object)
- * @return list of rspamd_controller_result structures for each server
- */
-GList* rspamd_controller_command_file (struct rspamd_client* client, const gchar *command, const gchar *password,
-               GHashTable *in_headers, const gchar *filename, GError **err);
-
-/*
- * Free results
- */
-void rspamd_free_result (struct rspamd_result *result);
-
-/*
- * Free controller results
- */
-void rspamd_free_controller_result (struct rspamd_controller_result *result);
-
-/*
- * Close library and free associated resources
- */
-void rspamd_client_close (struct rspamd_client *client);
-
-#endif
diff --git a/lib/kvstorage/libkvstorageclient.c b/lib/kvstorage/libkvstorageclient.c
deleted file mode 100644 (file)
index e0971f2..0000000
+++ /dev/null
@@ -1,1179 +0,0 @@
-/* Copyright (c) 2010, Vsevolod Stakhov
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *       * Redistributions of source code must retain the above copyright
- *         notice, this list of conditions and the following disclaimer.
- *       * Redistributions in binary form must reproduce the above copyright
- *         notice, this list of conditions and the following disclaimer in the
- *         documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "config.h"
-#include "mem_pool.h"
-#include "util.h"
-#include "libkvstorageclient.h"
-
-#define MAX_KV_LINE 1024
-
-#ifdef CRLF
-#undef CRLF
-#undef CR
-#undef LF
-#endif
-
-#define CRLF "\r\n"
-#define CR '\r'
-#define LF '\n'
-
-struct kvstorage_buf {
-       guint pos;
-       guint len;
-       guint8 data[1];
-};
-
-struct rspamd_kvstorage_connection {
-       gboolean asynced;
-       gint sock;
-       struct timeval tv;
-       enum {
-               KV_STATE_NONE = 0,
-               KV_STATE_CONNECTED,
-               KV_STATE_SET,
-               KV_STATE_GET,
-               KV_STATE_WRITE_DATA,
-               KV_STATE_READ_DATA,
-               KV_STATE_READ_ELT,
-               KV_STATE_READ_REPLY
-       } state;
-       struct event ev;
-       kvstorage_connect_cb conn_cb;
-       kvstorage_read_cb read_cb;
-       kvstorage_write_cb write_cb;
-       memory_pool_t *pool;
-};
-
-struct rspamd_kvstorage_async_data {
-       struct rspamd_kvstorage_connection *c;
-       struct kvstorage_buf *buf;
-       gchar *key;
-       guint keylen;
-       gpointer data;
-       guint datalen;
-       guint expire;
-       gpointer ud;
-};
-
-/*
- * Buffer functions
- */
-
-/*
- * Create new kvstorage_buf
- */
-static struct kvstorage_buf *
-rspamd_kvstorage_buf_create (guint size, memory_pool_t *pool)
-{
-       struct kvstorage_buf                                    *new;
-
-       new = memory_pool_alloc (pool, sizeof (struct kvstorage_buf) + size);
-       new->len = size;
-       new->pos = 0;
-
-       return new;
-}
-
-/*
- * Read a single line synced or asynced
- */
-static gint
-rspamd_kvstorage_buf_readline (struct kvstorage_buf *buf, struct rspamd_kvstorage_connection *conn)
-{
-       gint                                                                    r;
-       guint8                                                             *p;
-
-       r = read (conn->sock, buf->data, buf->len);
-       if (r == -1) {
-               return errno;
-       }
-       /* Try to parse what we have */
-       p = buf->data;
-       while (p - buf->data < r) {
-               if (*p == '\r' || *p == '\n') {
-
-                       buf->pos = p - buf->data;
-                       return 0;
-               }
-               p ++;
-       }
-
-       if (r == (gint)buf->len) {
-               /* Buffer is overflowed */
-               return EOVERFLOW;
-       }
-       /* Line end not found */
-       return EAGAIN;
-}
-
-/*
- * Read the whole buffer, return remaining characters or -1
- */
-static gint
-rspamd_kvstorage_buf_readall (struct kvstorage_buf *buf, struct rspamd_kvstorage_connection *conn)
-{
-       gint                                                                    r;
-
-       if (buf->len - buf->pos == 0) {
-               return 0;
-       }
-       r = read (conn->sock, buf->data + buf->pos, buf->len - buf->pos);
-       if (r == -1) {
-               return -1;
-       }
-
-       buf->pos += r;
-
-       /* Line end not found */
-       return buf->len - buf->pos;
-}
-
-/*
- * Write the whole buffer, return remaining characters or -1
- */
-static gint
-rspamd_kvstorage_buf_writeall (struct kvstorage_buf *buf, struct rspamd_kvstorage_connection *conn)
-{
-       gint                                                                    r;
-
-       if (buf->len - buf->pos == 0) {
-               return 0;
-       }
-       r = write (conn->sock, buf->data + buf->pos, buf->len - buf->pos);
-       if (r == -1) {
-               return -1;
-       }
-
-       buf->pos += r;
-
-       /* Line end not found */
-       return buf->len - buf->pos;
-}
-
-/*
- * Drain line from the begin of buffer, moving it from the beginning of buf
- */
-static void
-rspamd_kvstorage_buf_drainline (struct kvstorage_buf *buf)
-{
-       guint8                                                             *p;
-
-       p = buf->data + buf->pos;
-       /* Skip \r and \n characters */
-       while (p - buf->data < (gint)buf->len && (*p == '\r' || *p == '\n')) {
-               p ++;
-       }
-       if (p - buf->data == (gint)buf->len) {
-               /* Do not move anything */
-               buf->pos = 0;
-               return;
-       }
-       memcpy (buf->data, p, buf->len - (p - buf->data));
-       buf->pos = buf->len - (p - buf->data);
-}
-
-/* Common utility functions */
-
-/*
- * Parse reply line that contains an error
- */
-static enum rspamd_kvstorage_error
-rspamd_kvstorage_parse_reply_error (struct kvstorage_buf *buf)
-{
-       guint8                                                             *p;
-       guint                                   l = 0;
-
-       /* Get one word */
-       p = buf->data;
-       while (p - buf->data < (gint)buf->pos) {
-               if (g_ascii_isspace (*p)) {
-                       while (p - buf->data < (gint)buf->pos && g_ascii_isspace (*p)) {
-                               p ++;
-                       }
-                       break;
-               }
-               p ++;
-               l ++;
-       }
-
-       /* Get common errors */
-       if (g_ascii_strncasecmp (buf->data, "ERROR", MIN (l, sizeof("ERORR") - 1)) == 0) {
-               return KVSTORAGE_ERROR_INTERNAL_ERROR;
-       }
-       else if (g_ascii_strncasecmp (buf->data, "SERVER_ERROR", MIN (l, sizeof("SERVER_ERORR") - 1)) == 0) {
-               return KVSTORAGE_ERROR_SERVER_ERROR;
-       }
-       else if (g_ascii_strncasecmp (buf->data, "CLIENT_ERROR", MIN (l, sizeof("CLIENT_ERORR") - 1)) == 0) {
-               return KVSTORAGE_ERROR_CLIENT_ERROR;
-       }
-       else if (g_ascii_strncasecmp (buf->data, "NOT_STORED", MIN (l, sizeof("NOT_STORED") - 1)) == 0) {
-               return KVSTORAGE_ERROR_NOT_STORED;
-       }
-       else if (g_ascii_strncasecmp (buf->data, "NOT_FOUND", MIN (l, sizeof("NOT_FOUND") - 1)) == 0) {
-               return KVSTORAGE_ERROR_NOT_FOUND;
-       }
-       else if (g_ascii_strncasecmp (buf->data, "EXISTS", MIN (l, sizeof("EXISTS") - 1)) == 0) {
-               return KVSTORAGE_ERROR_EXISTS;
-       }
-       else if (g_ascii_strncasecmp (buf->data, "STORED", MIN (l, sizeof("STORED") - 1)) == 0) {
-               return KVSTORAGE_ERROR_OK;
-       }
-       else if (g_ascii_strncasecmp (buf->data, "DELETED", MIN (l, sizeof("DELETED") - 1)) == 0) {
-               return KVSTORAGE_ERROR_OK;
-       }
-
-       return KVSTORAGE_ERROR_INTERNAL_ERROR;
-}
-
-/*
- * Parse reply line, store element length
- */
-static enum rspamd_kvstorage_error
-rspamd_kvstorage_parse_get_line (struct kvstorage_buf *buf, guint *len, guint *flags)
-{
-       guint8                                                             *p, *c, *end;
-       gboolean                                error = TRUE;
-       gchar                                  *err_str;
-
-       p = buf->data;
-       end = buf->data + buf->pos;
-       while (p < end) {
-               if (g_ascii_isspace (*p)) {
-                       error = FALSE;
-                       while (p - buf->data < (gint)buf->pos && g_ascii_isspace (*p)) {
-                               p ++;
-                       }
-                       break;
-               }
-               p ++;
-       }
-       /* Here we got a word or error flag */
-       if (error) {
-               /* Something wrong here */
-               return KVSTORAGE_ERROR_SERVER_ERROR;
-       }
-       if (g_ascii_strncasecmp (buf->data, "VALUE", sizeof ("VALUE") - 1) != 0) {
-               return rspamd_kvstorage_parse_reply_error (buf);
-       }
-       /* Here we got key, flags and size items */
-       /* Skip key */
-       error = TRUE;
-       while (p < end) {
-               if (g_ascii_isspace (*p)) {
-                       error = FALSE;
-                       /* Skip spaces after key */
-                       while (p < end && g_ascii_isspace (*p)) {
-                               p ++;
-                       }
-                       break;
-               }
-               p ++;
-       }
-       if (error) {
-               /* Something wrong here */
-               return KVSTORAGE_ERROR_SERVER_ERROR;
-       }
-       /* Read flags */
-       c = p;
-       error = TRUE;
-       while (p < end) {
-               if (g_ascii_isspace (*p)) {
-                       error = FALSE;
-                       /* Skip spaces after flags */
-                       while (p - buf->data < (gint)buf->pos && g_ascii_isspace (*p)) {
-                               p ++;
-                       }
-                       break;
-               }
-               else if (!g_ascii_isdigit (*p)) {
-                       break;
-               }
-               p ++;
-       }
-       if (error) {
-               /* Something wrong here */
-               return KVSTORAGE_ERROR_SERVER_ERROR;
-       }
-       *flags = strtoul (c, &err_str, 10);
-       if (!g_ascii_isspace (*err_str)) {
-               return KVSTORAGE_ERROR_SERVER_ERROR;
-       }
-       /* Read len */
-       c = p;
-       while (p < end) {
-               if (!g_ascii_isdigit (*p)) {
-                       break;
-               }
-               p ++;
-       }
-       if (error) {
-               /* Something wrong here */
-               return KVSTORAGE_ERROR_SERVER_ERROR;
-       }
-       *len = strtoul (c, &err_str, 10);
-       if (!g_ascii_isspace (*err_str)) {
-               return KVSTORAGE_ERROR_SERVER_ERROR;
-       }
-
-       return KVSTORAGE_ERROR_OK;
-}
-
-/* Callbacks for async API */
-static void
-rspamd_kvstorage_connect_cb (int fd, short what, gpointer ud)
-{
-       struct rspamd_kvstorage_async_data              *d = ud;
-       kvstorage_connect_cb                     cb;
-
-       cb = (kvstorage_connect_cb)d->c->conn_cb;
-
-       if (what == EV_TIMEOUT) {
-               cb (KVSTORAGE_ERROR_TIMEOUT, d->c, d->ud);
-       }
-       else {
-               d->c->state = KV_STATE_CONNECTED;
-               cb (KVSTORAGE_ERROR_OK, d->c, d->ud);
-       }
-}
-
-static void
-rspamd_kvstorage_read_cb (int fd, short what, gpointer ud)
-{
-       struct rspamd_kvstorage_async_data              *d = ud;
-       kvstorage_read_cb                        cb;
-       guint                                                                    buflen, flags;
-       gint                                                                     r;
-       struct kvstorage_buf                                    *databuf;
-
-       cb = (kvstorage_read_cb)d->c->read_cb;
-
-       if (what == EV_TIMEOUT) {
-               cb (KVSTORAGE_ERROR_TIMEOUT, d->key, d->keylen, NULL, 0, d->c, d->ud);
-               return;
-       }
-       if (d->c->state == KV_STATE_GET) {
-               /* Create, fill and write buffer */
-               buflen = d->keylen + sizeof ("get " CRLF);
-               d->buf = rspamd_kvstorage_buf_create (buflen, d->c->pool);
-
-               r = rspamd_snprintf (d->buf->data, d->buf->len, "get %*s" CRLF,
-                               d->keylen, d->key);
-               d->buf->len = r;
-               r = rspamd_kvstorage_buf_writeall (d->buf, d->c);
-               if (r > 0) {
-                       /* Write more data at next call of this function */
-                       d->c->state = KV_STATE_WRITE_DATA;
-                       /* Event magic */
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_WRITE, rspamd_kvstorage_read_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else if (r == 0) {
-                       /* We have written everything */
-                       d->buf = rspamd_kvstorage_buf_create (MAX_KV_LINE, d->c->pool);
-                       d->c->state = KV_STATE_READ_ELT;
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_READ, rspamd_kvstorage_read_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else {
-                       /* Error occured during writing */
-                       cb (KVSTORAGE_ERROR_INTERNAL_ERROR, d->key, d->keylen, NULL, 0, d->c, d->ud);
-               }
-       }
-       else if (d->c->state == KV_STATE_WRITE_DATA) {
-               r = rspamd_kvstorage_buf_writeall (d->buf, d->c);
-               if (r > 0) {
-                       /* Write more data at next call of this function */
-                       d->c->state = KV_STATE_WRITE_DATA;
-                       /* Event magic */
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_WRITE, rspamd_kvstorage_read_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else if (r == 0) {
-                       /* We have written everything */
-                       d->c->state = KV_STATE_READ_ELT;
-                       d->buf = rspamd_kvstorage_buf_create (MAX_KV_LINE, d->c->pool);
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_READ, rspamd_kvstorage_read_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else {
-                       /* Error occured during writing */
-                       cb (KVSTORAGE_ERROR_INTERNAL_ERROR, d->key, d->keylen, NULL, 0, d->c, d->ud);
-               }
-       }
-       else if (d->c->state == KV_STATE_READ_ELT) {
-               /* Read element info */
-               r = rspamd_kvstorage_buf_readline (d->buf, d->c);
-               if (r == EAGAIN) {
-                       /* Read more data */
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_READ, rspamd_kvstorage_read_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else if (r == 0) {
-                       /* Got all data about elt */
-                       if ((r = rspamd_kvstorage_parse_get_line (d->buf, &d->datalen, &flags)) != KVSTORAGE_ERROR_OK) {
-                               cb (KVSTORAGE_ERROR_INTERNAL_ERROR, d->key, d->keylen, NULL, 0, d->c, d->ud);
-                               return;
-                       }
-                       rspamd_kvstorage_buf_drainline (d->buf);
-
-                       /* Now allocate and read the data */
-                       databuf = rspamd_kvstorage_buf_create (d->datalen, d->c->pool);
-                       memcpy (databuf->data, d->buf->data, d->buf->pos);
-                       d->buf = databuf;
-                       d->c->state = KV_STATE_READ_DATA;
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_READ, rspamd_kvstorage_read_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else {
-                       /* Error occured during reading reply line */
-                       cb (KVSTORAGE_ERROR_INTERNAL_ERROR, d->key, d->keylen, NULL, 0, d->c, d->ud);
-               }
-       }
-       else if (d->c->state == KV_STATE_READ_DATA) {
-               /* Read data to the buffer */
-               r = rspamd_kvstorage_buf_readall (d->buf, d->c);
-               if (r == 0) {
-                       /* All data read, read the last line */
-                       d->c->state = KV_STATE_READ_REPLY;
-                       /* Save databuf */
-                       d->data = d->buf->data;
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_READ, rspamd_kvstorage_read_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else if (r > 0) {
-                       /* Read more data into buffer */
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_READ, rspamd_kvstorage_read_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else {
-                       /* Error occured */
-                       cb (KVSTORAGE_ERROR_INTERNAL_ERROR, d->key, d->keylen, NULL, 0, d->c, d->ud);
-               }
-       }
-       else if (d->c->state == KV_STATE_READ_REPLY) {
-               /* Got something from server, try to read line */
-               r = rspamd_kvstorage_buf_readline (d->buf, d->c);
-               if (r == EAGAIN) {
-                       /* Read more data */
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_READ, rspamd_kvstorage_read_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else if (r == 0) {
-                       d->c->state = KV_STATE_CONNECTED;
-                       cb (rspamd_kvstorage_parse_reply_error (d->buf), d->key, d->keylen, d->data, d->datalen, d->c, d->ud);
-               }
-               else {
-                       /* Error occured during reading reply line */
-                       cb (KVSTORAGE_ERROR_INTERNAL_ERROR, d->key, d->keylen, NULL, 0, d->c, d->ud);
-               }
-       }
-}
-
-static void
-rspamd_kvstorage_write_cb (int fd, short what, gpointer ud)
-{
-       struct rspamd_kvstorage_async_data              *d = ud;
-       kvstorage_write_cb                       cb;
-       guint                                                                    buflen;
-       gint                                                                     r;
-
-       cb = (kvstorage_write_cb)d->c->write_cb;
-
-       if (what == EV_TIMEOUT) {
-               cb (KVSTORAGE_ERROR_TIMEOUT, d->key, d->keylen, d->c, d->ud);
-               return;
-       }
-       if (d->c->state == KV_STATE_SET) {
-               /* Create, fill and write buffer */
-               buflen = d->datalen + d->keylen + sizeof ("set  4294967296 4294967296 4294967296" CRLF);
-               d->buf = rspamd_kvstorage_buf_create (buflen, d->c->pool);
-
-               r = rspamd_snprintf (d->buf->data, d->buf->len, "set %*s %ud %ud %ud" CRLF "%*s",
-                               d->keylen, d->key, 0, d->expire, d->datalen, d->datalen, d->data);
-               d->buf->len = r;
-               r = rspamd_kvstorage_buf_writeall (d->buf, d->c);
-               if (r > 0) {
-                       /* Write more data at next call of this function */
-                       d->c->state = KV_STATE_WRITE_DATA;
-                       /* Event magic */
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_WRITE, rspamd_kvstorage_write_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else if (r == 0) {
-                       /* We have written everything */
-                       d->buf = rspamd_kvstorage_buf_create (MAX_KV_LINE, d->c->pool);
-                       d->c->state = KV_STATE_READ_REPLY;
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_READ, rspamd_kvstorage_write_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else {
-                       /* Error occured during writing */
-                       cb (KVSTORAGE_ERROR_INTERNAL_ERROR, d->key, d->keylen, d->c, d->ud);
-               }
-       }
-       else if (d->c->state == KV_STATE_WRITE_DATA) {
-               r = rspamd_kvstorage_buf_writeall (d->buf, d->c);
-               if (r > 0) {
-                       /* Write more data at next call of this function */
-                       d->c->state = KV_STATE_WRITE_DATA;
-                       /* Event magic */
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_WRITE, rspamd_kvstorage_write_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else if (r == 0) {
-                       /* We have written everything */
-                       d->c->state = KV_STATE_READ_REPLY;
-                       d->buf = rspamd_kvstorage_buf_create (MAX_KV_LINE, d->c->pool);
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_READ, rspamd_kvstorage_write_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else {
-                       /* Error occured during writing */
-                       cb (KVSTORAGE_ERROR_INTERNAL_ERROR, d->key, d->keylen, d->c, d->ud);
-               }
-       }
-       else if (d->c->state == KV_STATE_READ_REPLY) {
-               /* Got something from server, try to read line */
-               r = rspamd_kvstorage_buf_readline (d->buf, d->c);
-               if (r == EAGAIN) {
-                       /* Read more data */
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_READ, rspamd_kvstorage_write_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else if (r == 0) {
-                       d->c->state = KV_STATE_CONNECTED;
-                       cb (rspamd_kvstorage_parse_reply_error (d->buf), d->key, d->keylen, d->c, d->ud);
-               }
-               else {
-                       /* Error occured during reading reply line */
-                       cb (KVSTORAGE_ERROR_INTERNAL_ERROR, d->key, d->keylen, d->c, d->ud);
-               }
-       }
-}
-
-static void
-rspamd_kvstorage_delete_cb (int fd, short what, gpointer ud)
-{
-       struct rspamd_kvstorage_async_data              *d = ud;
-       kvstorage_write_cb                       cb;
-       guint                                                                    buflen;
-       gint                                                                     r;
-
-       cb = (kvstorage_write_cb)d->c->write_cb;
-
-       if (what == EV_TIMEOUT) {
-               cb (KVSTORAGE_ERROR_TIMEOUT, d->key, d->keylen, d->c, d->ud);
-               return;
-       }
-       if (d->c->state == KV_STATE_SET) {
-               /* Create, fill and write buffer */
-               buflen = MAX (MAX_KV_LINE, d->keylen + sizeof ("delete " CRLF));
-               d->buf = rspamd_kvstorage_buf_create (buflen, d->c->pool);
-
-               r = rspamd_snprintf (d->buf->data, d->buf->len, "delete %*s" CRLF,
-                               d->keylen, d->key);
-               d->buf->len = r;
-               r = rspamd_kvstorage_buf_writeall (d->buf, d->c);
-               if (r > 0) {
-                       /* Write more data at next call of this function */
-                       d->c->state = KV_STATE_WRITE_DATA;
-                       /* Event magic */
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_WRITE, rspamd_kvstorage_delete_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else if (r == 0) {
-                       /* We have written everything */
-                       d->buf = rspamd_kvstorage_buf_create (MAX_KV_LINE, d->c->pool);
-                       d->c->state = KV_STATE_READ_REPLY;
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_READ, rspamd_kvstorage_delete_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else {
-                       /* Error occured during writing */
-                       cb (KVSTORAGE_ERROR_INTERNAL_ERROR, d->key, d->keylen, d->c, d->ud);
-               }
-       }
-       else if (d->c->state == KV_STATE_WRITE_DATA) {
-               r = rspamd_kvstorage_buf_writeall (d->buf, d->c);
-               if (r > 0) {
-                       /* Write more data at next call of this function */
-                       d->c->state = KV_STATE_WRITE_DATA;
-                       /* Event magic */
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_WRITE, rspamd_kvstorage_delete_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else if (r == 0) {
-                       /* We have written everything */
-                       d->c->state = KV_STATE_READ_REPLY;
-                       d->buf = rspamd_kvstorage_buf_create (MAX_KV_LINE, d->c->pool);
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_READ, rspamd_kvstorage_delete_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else {
-                       /* Error occured during writing */
-                       cb (KVSTORAGE_ERROR_INTERNAL_ERROR, d->key, d->keylen, d->c, d->ud);
-               }
-       }
-       else if (d->c->state == KV_STATE_READ_REPLY) {
-               /* Got something from server, try to read line */
-               r = rspamd_kvstorage_buf_readline (d->buf, d->c);
-               if (r == EAGAIN) {
-                       /* Read more data */
-                       event_del (&d->c->ev);
-                       event_set (&d->c->ev, d->c->sock, EV_READ, rspamd_kvstorage_delete_cb, d);
-                       if (d->c->tv.tv_sec != 0 || d->c->tv.tv_usec != 0) {
-                               event_add (&d->c->ev, &d->c->tv);
-                       }
-                       else {
-                               event_add (&d->c->ev, NULL);
-                       }
-               }
-               else if (r == 0) {
-                       d->c->state = KV_STATE_CONNECTED;
-                       cb (rspamd_kvstorage_parse_reply_error (d->buf), d->key, d->keylen, d->c, d->ud);
-               }
-               else {
-                       /* Error occured during reading reply line */
-                       cb (KVSTORAGE_ERROR_INTERNAL_ERROR, d->key, d->keylen, d->c, d->ud);
-               }
-       }
-}
-
-/**
- *  Create async connection with rspamd
- *  @param host hostname, ip or unix socket for a server
- *  @param port port number in host byte order
- *  @param tv timeout for operations
- *  @param cb callback
- *  @param ud user data for callback
- *  @param conn target connection
- */
-enum rspamd_kvstorage_error
-rspamd_kvstorage_connect_async (const gchar *host,
-               guint16 port, struct timeval *tv, kvstorage_connect_cb cb, gpointer ud,
-               struct rspamd_kvstorage_connection **conn)
-{
-       struct rspamd_kvstorage_connection              *new;
-       struct rspamd_kvstorage_async_data      *data;
-       gint                                                                     sock;
-
-       /* Here we do NOT try to resolve hostname */
-       if ((sock = make_universal_socket (host, port, SOCK_STREAM, TRUE, FALSE, TRUE)) == -1) {
-               return KVSTORAGE_ERROR_SERVER_ERROR;
-       }
-
-       /* Allocate new connection structure */
-       new = g_malloc (sizeof (struct rspamd_kvstorage_connection));
-
-       /* Set fields */
-       new->sock = sock;
-       new->state = KV_STATE_NONE;
-       new->asynced = TRUE;
-       if (tv != NULL) {
-               memcpy (&new->tv, tv, sizeof (struct timeval));
-       }
-       else {
-               memset (&new->tv, 0, sizeof (struct timeval));
-       }
-
-       new->conn_cb = cb;
-       new->pool = memory_pool_new (memory_pool_get_size ());
-       data = memory_pool_alloc (new->pool, sizeof (struct rspamd_kvstorage_async_data));
-       data->ud = ud;
-       data->c = new;
-
-       /* Set event */
-       event_set (&new->ev, new->sock, EV_WRITE, rspamd_kvstorage_connect_cb, data);
-       if (tv != NULL) {
-               event_add (&new->ev, &new->tv);
-       }
-       else {
-               event_add (&new->ev, NULL);
-       }
-
-       *conn = new;
-       return KVSTORAGE_ERROR_OK;
-}
-
-/**
- * Read key asynced
- * @param conn connection structure
- * @param key key to read
- * @param cb callback
- * @param ud user data for callback
- */
-enum rspamd_kvstorage_error
-rspamd_kvstorage_get_async (struct rspamd_kvstorage_connection *conn,
-               const gpointer key, guint keylen, kvstorage_read_cb cb, gpointer ud)
-{
-       struct rspamd_kvstorage_async_data              *d;
-
-       if (conn == NULL || conn->state != KV_STATE_CONNECTED) {
-               return KVSTORAGE_ERROR_INTERNAL_ERROR;
-       }
-       else {
-               conn->read_cb = cb;
-               d = memory_pool_alloc (conn->pool, sizeof (struct rspamd_kvstorage_async_data));
-               d->ud = ud;
-               d->c = conn;
-               d->ud = ud;
-               d->key = memory_pool_strdup (conn->pool, key);
-               d->keylen = keylen;
-               conn->state = KV_STATE_GET;
-
-               /* Set event */
-               event_set (&conn->ev, conn->sock, EV_WRITE, rspamd_kvstorage_read_cb, d);
-               if (conn->tv.tv_sec != 0) {
-                       event_add (&conn->ev, &conn->tv);
-               }
-               else {
-                       event_add (&conn->ev, NULL);
-               }
-       }
-       return KVSTORAGE_ERROR_OK;
-}
-
-/**
- * Write key asynced
- * @param conn connection structure
- * @param key key to set
- * @param value data to write
- * @param cb callback
- * @param ud user data for callback
- */
-enum rspamd_kvstorage_error
-rspamd_kvstorage_set_async (struct rspamd_kvstorage_connection *conn,
-               const gpointer key, guint keylen, const gpointer value, gsize len, guint expire, kvstorage_write_cb cb,
-               gpointer ud)
-{
-       struct rspamd_kvstorage_async_data              *d;
-
-       if (conn == NULL || conn->state != KV_STATE_CONNECTED) {
-               return KVSTORAGE_ERROR_INTERNAL_ERROR;
-       }
-       else {
-               conn->write_cb = cb;
-               d = memory_pool_alloc (conn->pool, sizeof (struct rspamd_kvstorage_async_data));
-               d->ud = ud;
-               d->c = conn;
-               d->ud = ud;
-               d->key = memory_pool_strdup (conn->pool, key);
-               d->keylen = keylen;
-               d->data = value;
-               d->datalen = len;
-               conn->state = KV_STATE_SET;
-
-               /* Set event */
-               event_set (&conn->ev, conn->sock, EV_WRITE, rspamd_kvstorage_write_cb, d);
-               if (conn->tv.tv_sec != 0) {
-                       event_add (&conn->ev, &conn->tv);
-               }
-               else {
-                       event_add (&conn->ev, NULL);
-               }
-       }
-       return KVSTORAGE_ERROR_OK;
-}
-
-/**
- * Delete key asynced
- * @param conn connection structure
- * @param key key to delete
- * @param cb callback
- * @param ud user data for callback
- */
-enum rspamd_kvstorage_error
-rspamd_kvstorage_delete_async (struct rspamd_kvstorage_connection *conn,
-               const gpointer key, guint keylen, kvstorage_write_cb cb, gpointer ud)
-{
-       struct rspamd_kvstorage_async_data              *d;
-
-       if (conn == NULL || conn->state != KV_STATE_CONNECTED) {
-               return KVSTORAGE_ERROR_INTERNAL_ERROR;
-       }
-       else {
-               conn->write_cb = cb;
-               d = memory_pool_alloc (conn->pool, sizeof (struct rspamd_kvstorage_async_data));
-               d->ud = ud;
-               d->c = conn;
-               d->ud = ud;
-               d->key = memory_pool_strdup (conn->pool, key);
-               d->keylen = keylen;
-               conn->state = KV_STATE_SET;
-
-               /* Set event */
-               event_set (&conn->ev, conn->sock, EV_WRITE, rspamd_kvstorage_delete_cb, d);
-               if (conn->tv.tv_sec != 0) {
-                       event_add (&conn->ev, &conn->tv);
-               }
-               else {
-                       event_add (&conn->ev, NULL);
-               }
-       }
-       return KVSTORAGE_ERROR_OK;
-}
-
-/**
- * Close connection
- * @param conn connection structure
- */
-enum rspamd_kvstorage_error
-rspamd_kvstorage_close_async (struct rspamd_kvstorage_connection *conn)
-{
-       close (conn->sock);
-       memory_pool_delete (conn->pool);
-       event_del (&conn->ev);
-       g_free (conn);
-
-       return KVSTORAGE_ERROR_OK;
-}
-
-/* Synced API */
-/**
- *  Create sync connection with rspamd
- *  @param host hostname, ip or unix socket for a server
- *  @param port port number in host byte order
- *  @param tv timeout for operations
- *  @param conn target connection
- */
-enum rspamd_kvstorage_error
-rspamd_kvstorage_connect_sync (const gchar *host,
-               guint16 port, struct timeval *tv,
-               struct rspamd_kvstorage_connection **conn)
-{
-       struct rspamd_kvstorage_connection              *new;
-       gint                                                                     sock;
-
-       if ((sock = make_universal_socket (host, port, SOCK_STREAM, FALSE, FALSE, TRUE)) == -1) {
-               return KVSTORAGE_ERROR_INTERNAL_ERROR;
-       }
-
-       /* Allocate new connection structure */
-       new = g_malloc (sizeof (struct rspamd_kvstorage_connection));
-
-       /* Set fields */
-       new->sock = sock;
-       new->state = KV_STATE_CONNECTED;
-       new->asynced = FALSE;
-       if (tv != NULL) {
-               memcpy (&new->tv, tv, sizeof (struct timeval));
-       }
-       else {
-               memset (&new->tv, 0, sizeof (struct timeval));
-       }
-       new->pool = memory_pool_new (memory_pool_get_size ());
-
-       *conn = new;
-       return KVSTORAGE_ERROR_OK;
-}
-
-/**
- * Read key synced
- * @param conn connection structure
- * @param key key to read
- * @param value value readed
- */
-enum rspamd_kvstorage_error
-rspamd_kvstorage_get_sync (struct rspamd_kvstorage_connection *conn,
-               const gpointer key, guint keylen, gpointer **value, guint *len)
-{
-       struct kvstorage_buf                               *buf, *databuf;
-       gint                                    r;
-       guint                                                                   flags;
-
-       if (conn == NULL || conn->state != KV_STATE_CONNECTED) {
-               return KVSTORAGE_ERROR_INTERNAL_ERROR;
-       }
-
-       buf = rspamd_kvstorage_buf_create (MAX_KV_LINE, conn->pool);
-
-       r = rspamd_snprintf (buf->data, buf->len, "get %*s" CRLF, keylen, key);
-       buf->len = r;
-       while ((r = rspamd_kvstorage_buf_writeall (buf, conn)) > 0) {
-               poll_sync_socket (conn->sock, tv_to_msec (&conn->tv), POLL_OUT);
-       }
-
-       if (r == -1) {
-               return KVSTORAGE_ERROR_INTERNAL_ERROR;
-       }
-       /* Now read reply and try to parse line */
-       buf->len = MAX_KV_LINE;
-       buf->pos = 0;
-       while ((r = rspamd_kvstorage_buf_readline (buf, conn)) == EAGAIN) {
-               poll_sync_socket (conn->sock, tv_to_msec (&conn->tv), POLL_IN);
-       }
-       /* A line was read */
-       if (r == 0) {
-               if ((r = rspamd_kvstorage_parse_get_line (buf, len, &flags)) != KVSTORAGE_ERROR_OK) {
-                       return r;
-               }
-               rspamd_kvstorage_buf_drainline (buf);
-               /* Now allocate and read the data */
-               databuf = rspamd_kvstorage_buf_create (*len, conn->pool);
-               memcpy (databuf->data, buf->data, buf->pos);
-               while ((r = rspamd_kvstorage_buf_readall (databuf, conn)) > 0) {
-                       poll_sync_socket (conn->sock, tv_to_msec (&conn->tv), POLL_IN);
-               }
-               if (r == -1) {
-                       return KVSTORAGE_ERROR_INTERNAL_ERROR;
-               }
-               /* Now we have data inside buffer, read the last line */
-               buf->pos = 0;
-               while ((r = rspamd_kvstorage_buf_readline (buf, conn)) == EAGAIN) {
-                       poll_sync_socket (conn->sock, tv_to_msec (&conn->tv), POLL_IN);
-               }
-               *value = (gpointer)buf->data;
-       }
-
-
-       return KVSTORAGE_ERROR_OK;
-}
-
-/**
- * Write key synced
- * @param conn connection structure
- * @param key key to set
- * @param value data to write
- */
-enum rspamd_kvstorage_error
-rspamd_kvstorage_set_sync (struct rspamd_kvstorage_connection *conn,
-               const gpointer key, guint keylen, const gpointer value, gsize len, guint expire)
-{
-       struct kvstorage_buf                               *buf;
-       gint                                    r, buflen;
-
-       if (conn == NULL || conn->state != KV_STATE_CONNECTED) {
-               return KVSTORAGE_ERROR_INTERNAL_ERROR;
-       }
-
-       /* Create buf */
-       buflen = len + keylen + sizeof ("set  4294967296 4294967296 4294967296" CRLF);
-       buf = rspamd_kvstorage_buf_create (buflen, conn->pool);
-
-       r = rspamd_snprintf (buf->data, buf->len, "set %*s %ud %ud %ud" CRLF "%*s",
-                       keylen, key, 0, expire, len, len, value);
-       buf->len = r;
-       while ((r = rspamd_kvstorage_buf_writeall (buf, conn)) > 0) {
-               poll_sync_socket (conn->sock, tv_to_msec (&conn->tv), POLL_OUT);
-       }
-       if (r == -1) {
-               return KVSTORAGE_ERROR_INTERNAL_ERROR;
-       }
-       /* Now we can read reply */
-       buf->pos = 0;
-       buf->len = buflen;
-       while ((r = rspamd_kvstorage_buf_readline (buf, conn)) == EAGAIN) {
-               poll_sync_socket (conn->sock, tv_to_msec (&conn->tv), POLL_IN);
-       }
-
-       return rspamd_kvstorage_parse_reply_error (buf);
-}
-
-/**
- * Delete key synced
- * @param conn connection structure
- * @param key key to delete
- */
-enum rspamd_kvstorage_error
-rspamd_kvstorage_delete_sync (struct rspamd_kvstorage_connection *conn,
-               const gpointer key, guint keylen)
-{
-       struct kvstorage_buf                               *buf;
-       gint                                    r, buflen;
-
-       if (conn == NULL || conn->state != KV_STATE_CONNECTED) {
-               return KVSTORAGE_ERROR_INTERNAL_ERROR;
-       }
-
-       /* Create buf */
-       buflen = MAX (keylen + sizeof ("delete " CRLF), MAX_KV_LINE);
-       buf = rspamd_kvstorage_buf_create (buflen, conn->pool);
-
-       r = rspamd_snprintf (buf->data, buf->len, "delete %*s" CRLF,
-                       keylen, key);
-       buf->len = r;
-       while ((r = rspamd_kvstorage_buf_writeall (buf, conn)) > 0) {
-               poll_sync_socket (conn->sock, tv_to_msec (&conn->tv), POLL_OUT);
-       }
-       if (r == -1) {
-               return KVSTORAGE_ERROR_INTERNAL_ERROR;
-       }
-       /* Now we can read reply */
-       buf->len = buflen;
-       buf->pos = 0;
-       while ((r = rspamd_kvstorage_buf_readline (buf, conn)) == EAGAIN) {
-               poll_sync_socket (conn->sock, tv_to_msec (&conn->tv), POLL_IN);
-       }
-
-       return rspamd_kvstorage_parse_reply_error (buf);
-}
-
-/**
- * Close connection
- * @param conn connection structure
- */
-enum rspamd_kvstorage_error
-rspamd_kvstorage_close_sync (struct rspamd_kvstorage_connection *conn)
-{
-       close (conn->sock);
-       memory_pool_delete (conn->pool);
-       g_free (conn);
-
-       return KVSTORAGE_ERROR_OK;
-}
-
-const gchar*
-rspamd_kvstorage_strerror (enum rspamd_kvstorage_error err)
-{
-       switch (err) {
-       case KVSTORAGE_ERROR_OK:
-               return "operation completed";
-       case KVSTORAGE_ERROR_TIMEOUT:
-               return "operation timeout";
-       case KVSTORAGE_ERROR_NOT_FOUND:
-               return "key not found";
-       case KVSTORAGE_ERROR_NOT_STORED:
-               return "key not stored";
-       case KVSTORAGE_ERROR_EXISTS:
-               return "key exists";
-       case KVSTORAGE_ERROR_SERVER_ERROR:
-               return "server error";
-       case KVSTORAGE_ERROR_CLIENT_ERROR:
-               return "client error";
-       case KVSTORAGE_ERROR_INTERNAL_ERROR:
-               return "library error";
-       }
-
-       /* Not reached */
-       return "unknown error";
-}
diff --git a/lib/kvstorage/libkvstorageclient.h b/lib/kvstorage/libkvstorageclient.h
deleted file mode 100644 (file)
index 11145fd..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/* Copyright (c) 2010, Vsevolod Stakhov
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *       * Redistributions of source code must retain the above copyright
- *         notice, this list of conditions and the following disclaimer.
- *       * Redistributions in binary form must reproduce the above copyright
- *         notice, this list of conditions and the following disclaimer in the
- *         documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Rambler BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef LIBKVSTORAGECLIENT_H_
-#define LIBKVSTORAGECLIENT_H_
-
-#include <glib.h>
-#include <sys/time.h>
-
-/* Errors */
-enum rspamd_kvstorage_error {
-       KVSTORAGE_ERROR_OK = 0,
-       KVSTORAGE_ERROR_TIMEOUT,
-       KVSTORAGE_ERROR_NOT_FOUND,
-       KVSTORAGE_ERROR_NOT_STORED,
-       KVSTORAGE_ERROR_EXISTS,
-       KVSTORAGE_ERROR_SERVER_ERROR,
-       KVSTORAGE_ERROR_CLIENT_ERROR,
-       KVSTORAGE_ERROR_INTERNAL_ERROR
-};
-
-/* Forwarded definition */
-struct rspamd_kvstorage_connection;
-
-/* Callbacks for async API */
-typedef void (*kvstorage_connect_cb) (enum rspamd_kvstorage_error code,
-                                                                       struct rspamd_kvstorage_connection *conn, gpointer user_data);
-typedef void (*kvstorage_read_cb) (enum rspamd_kvstorage_error code, const gpointer key, guint keylen,
-                                                                       const gpointer value, gsize datalen, struct rspamd_kvstorage_connection *conn,
-                                                                       gpointer user_data);
-typedef void (*kvstorage_write_cb) (enum rspamd_kvstorage_error code, const gpointer key, guint keylen,
-                                                                       struct rspamd_kvstorage_connection *conn,
-                                                                       gpointer user_data);
-
-/* Asynced API */
-
-/**
- *  Create async connection with rspamd
- *  @param host hostname, ip or unix socket for a server
- *  @param port port number in host byte order
- *  @param tv timeout for operations
- *  @param cb callback
- *  @param ud user data for callback
- *  @param conn target connection
- */
-enum rspamd_kvstorage_error rspamd_kvstorage_connect_async (const gchar *host,
-               guint16 port, struct timeval *tv, kvstorage_connect_cb cb, gpointer ud,
-               struct rspamd_kvstorage_connection **conn);
-
-/**
- * Read key asynced
- * @param conn connection structure
- * @param key key to read
- * @param cb callback
- * @param ud user data for callback
- */
-enum rspamd_kvstorage_error rspamd_kvstorage_get_async (struct rspamd_kvstorage_connection *conn,
-               const gpointer key, guint keylen, kvstorage_read_cb cb, gpointer ud);
-
-/**
- * Write key asynced
- * @param conn connection structure
- * @param key key to set
- * @param value data to write
- * @param cb callback
- * @param ud user data for callback
- */
-enum rspamd_kvstorage_error rspamd_kvstorage_set_async (struct rspamd_kvstorage_connection *conn,
-               const gpointer key, guint keylen, const gpointer value, gsize len, guint expire, kvstorage_write_cb cb, gpointer ud);
-
-/**
- * Delete key asynced
- * @param conn connection structure
- * @param key key to delete
- * @param cb callback
- * @param ud user data for callback
- */
-enum rspamd_kvstorage_error rspamd_kvstorage_delete_async (struct rspamd_kvstorage_connection *conn,
-               const gpointer key, guint keylen, kvstorage_write_cb cb, gpointer ud);
-
-/**
- * Close connection
- * @param conn connection structure
- */
-enum rspamd_kvstorage_error rspamd_kvstorage_close_async (struct rspamd_kvstorage_connection *conn);
-
-/* Synced API */
-/**
- *  Create sync connection with rspamd
- *  @param host hostname, ip or unix socket for a server
- *  @param port port number in host byte order
- *  @param tv timeout for operations
- *  @param conn target connection
- */
-enum rspamd_kvstorage_error rspamd_kvstorage_connect_sync (const gchar *host,
-               guint16 port, struct timeval *tv,
-               struct rspamd_kvstorage_connection **conn);
-
-/**
- * Read key synced
- * @param conn connection structure
- * @param key key to read
- * @param value value readed
- */
-enum rspamd_kvstorage_error rspamd_kvstorage_get_sync (struct rspamd_kvstorage_connection *conn,
-               const gpointer key, guint keylen, gpointer **value, guint *len);
-
-/**
- * Write key synced
- * @param conn connection structure
- * @param key key to set
- * @param value data to write
- */
-enum rspamd_kvstorage_error rspamd_kvstorage_set_sync (struct rspamd_kvstorage_connection *conn,
-               const gpointer key, guint keylen, const gpointer value, gsize len, guint expire);
-
-/**
- * Delete key synced
- * @param conn connection structure
- * @param key key to delete
- */
-enum rspamd_kvstorage_error rspamd_kvstorage_delete_sync (struct rspamd_kvstorage_connection *conn,
-               const gpointer key, guint keylen);
-
-/**
- * Close connection
- * @param conn connection structure
- */
-enum rspamd_kvstorage_error rspamd_kvstorage_close_sync (struct rspamd_kvstorage_connection *conn);
-
-/**
- * Convert error code to string
- * @param err error code to be converted
- */
-const gchar* rspamd_kvstorage_strerror (enum rspamd_kvstorage_error err);
-
-#endif /* LIBKVSTORAGECLIENT_H_ */
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..4e24448
--- /dev/null
@@ -0,0 +1,146 @@
+# Librspamd-util
+SET(LIBRSPAMDUTILSRC                   aio_event.c
+                                                               bloom.c
+                                                               diff.c
+                                                               fstring.c
+                                                               fuzzy.c
+                                                               hash.c
+                                                               http.c
+                                                               logger.c
+                                                               map.c
+                                                               memcached.c
+                                                               mem_pool.c
+                                                               printf.c
+                                                               radix.c
+                                                               rrd.c
+                                                               trie.c
+                                                               upstream.c
+                                                               util.c)
+
+# Librspamdserver
+SET(LIBRSPAMDSERVERSRC
+                               binlog.c
+                               buffer.c
+                               cfg_utils.c
+                               cfg_rcl.c
+                               cfg_xml.c
+                               dkim.c
+                               dns.c
+                               dynamic_cfg.c
+                               events.c
+                               html.c
+                               proxy.c
+                               roll_history.c
+                               settings.c
+                               spf.c
+                               statfile.c
+                               statfile_sync.c
+                               symbols_cache.c
+                               url.c
+                               view.c)
+                               
+# Librspamd mime
+SET(LIBRSPAMDMIMESRC
+                               expressions.c
+                               filter.c
+                               images.c
+                               message.c
+                               protocol.c
+                               smtp_utils.c
+                               smtp_proto.c
+                               worker_util.c)
+                               
+SET(TOKENIZERSSRC  tokenizers/tokenizers.c
+                               tokenizers/osb.c)
+
+SET(CLASSIFIERSSRC classifiers/classifiers.c
+                classifiers/bayes.c
+                               classifiers/winnow.c)
+# Add targets
+
+# Rspamdutil
+ADD_LIBRARY(rspamd-util ${LINK_TYPE} ${LIBRSPAMDUTILSRC})
+IF(CMAKE_COMPILER_IS_GNUCC)
+SET_TARGET_PROPERTIES(rspamd-util PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing")
+ENDIF(CMAKE_COMPILER_IS_GNUCC)
+
+TARGET_LINK_LIBRARIES(rspamd-util ${RSPAMD_REQUIRED_LIBRARIES})
+TARGET_LINK_LIBRARIES(rspamd-util pcre)
+TARGET_LINK_LIBRARIES(rspamd-util rspamd-ucl)
+TARGET_LINK_LIBRARIES(rspamd-util rspamd-http-parser)
+TARGET_LINK_LIBRARIES(rspamd-util event)
+
+IF(NOT DEBIAN_BUILD)
+SET_TARGET_PROPERTIES(rspamd-util PROPERTIES VERSION ${RSPAMD_VERSION})
+ENDIF(NOT DEBIAN_BUILD)
+
+IF(GLIB_COMPAT)
+       INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/contrib/lgpl")
+       TARGET_LINK_LIBRARIES(rspamd-util glibadditions)
+ENDIF(GLIB_COMPAT)
+
+IF(NO_SHARED MATCHES "OFF")
+       INSTALL(TARGETS rspamd-util 
+       LIBRARY DESTINATION ${LIBDIR} 
+       PUBLIC_HEADER DESTINATION include)
+ENDIF(NO_SHARED MATCHES "OFF")
+    
+# Librspamd-server
+
+#IF(WITH_DB)
+#      LIST(APPEND LIBRSPAMDSERVERSRC kvstorage_bdb.c)
+#ENDIF(WITH_DB)
+#IF(WITH_SQLITE)
+#      LIST(APPEND LIBRSPAMDSERVERSRC kvstorage_sqlite.c)
+#ENDIF(WITH_SQLITE)
+                               
+ADD_LIBRARY(rspamd-server ${LINK_TYPE} ${LIBRSPAMDSERVERSRC} ${TOKENIZERSSRC} ${CLASSIFIERSSRC})
+IF(NOT DEBIAN_BUILD)
+SET_TARGET_PROPERTIES(rspamd-server PROPERTIES VERSION ${RSPAMD_VERSION})
+ENDIF(NOT DEBIAN_BUILD)
+SET_TARGET_PROPERTIES(rspamd-server PROPERTIES LINKER_LANGUAGE C COMPILE_FLAGS "-DRSPAMD_LIB")
+TARGET_LINK_LIBRARIES(rspamd-server rspamd-lua)
+TARGET_LINK_LIBRARIES(rspamd-server rspamd-json)
+TARGET_LINK_LIBRARIES(rspamd-server rspamd-cdb)
+TARGET_LINK_LIBRARIES(rspamd-server rspamd-util)   
+IF(LIBJUDY_LIBRARY)
+       TARGET_LINK_LIBRARIES(rspamd-server Judy)
+ENDIF(LIBJUDY_LIBRARY)   
+IF(CMAKE_COMPILER_IS_GNUCC)
+SET_TARGET_PROPERTIES(rspamd-server PROPERTIES COMPILE_FLAGS "-DRSPAMD_LIB -fno-strict-aliasing")
+ENDIF(CMAKE_COMPILER_IS_GNUCC)
+
+IF(WITH_DB)
+       TARGET_LINK_LIBRARIES(rspamd-server db)
+ENDIF(WITH_DB)
+
+IF(OPENSSL_FOUND)
+       TARGET_LINK_LIBRARIES(rspamd-server ${OPENSSL_LIBRARIES})
+ENDIF(OPENSSL_FOUND)
+
+IF(NO_SHARED MATCHES "OFF")
+       INSTALL(TARGETS rspamd-server 
+       LIBRARY DESTINATION ${LIBDIR} 
+       PUBLIC_HEADER DESTINATION ${INCLUDEDIR})
+ENDIF(NO_SHARED MATCHES "OFF")
+    
+# Librspamdmime
+ADD_LIBRARY(rspamd-mime ${LINK_TYPE} ${LIBRSPAMDMIMESRC})
+IF(NOT DEBIAN_BUILD)
+SET_TARGET_PROPERTIES(rspamd-mime PROPERTIES VERSION ${RSPAMD_VERSION})
+ENDIF(NOT DEBIAN_BUILD)
+SET_TARGET_PROPERTIES(rspamd-mime PROPERTIES LINKER_LANGUAGE C)
+SET_TARGET_PROPERTIES(rspamd-mime PROPERTIES COMPILE_FLAGS "-DRSPAMD_LIB")
+TARGET_LINK_LIBRARIES(rspamd-mime rspamd-server)
+TARGET_LINK_LIBRARIES(rspamd-mime rspamd-util)      
+IF(CMAKE_COMPILER_IS_GNUCC)
+SET_TARGET_PROPERTIES(rspamd-mime PROPERTIES COMPILE_FLAGS "-DRSPAMD_LIB -fno-strict-aliasing")
+ENDIF(CMAKE_COMPILER_IS_GNUCC)
+
+IF(NO_SHARED MATCHES "OFF")
+       INSTALL(TARGETS rspamd-mime 
+               LIBRARY DESTINATION ${LIBDIR}  
+       PUBLIC_HEADER DESTINATION ${INCLUDEDIR})
+ENDIF(NO_SHARED MATCHES "OFF")
+
+INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/src")
\ No newline at end of file
index 1d48a202fb7ef374f57dcb59bc6bbc99ffd41bfc..90936f037d65d4669610c8bcbc02bbc6f29265f8 100644 (file)
@@ -1,3 +1,26 @@
+# Librspamdclient
+SET(LIBRSPAMDCLIENTSRC                 rspamdclient.c)
+
+ADD_LIBRARY(rspamdclient SHARED ${LIBRSPAMDCLIENTSRC})
+IF(CMAKE_COMPILER_IS_GNUCC)
+       SET_TARGET_PROPERTIES(rspamdclient PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing")
+ENDIF(CMAKE_COMPILER_IS_GNUCC)
+
+TARGET_LINK_LIBRARIES(rspamdclient rspamd-util)
+TARGET_LINK_LIBRARIES(rspamdclient ${RSPAMD_REQUIRED_LIBRARIES})
+
+IF(GLIB_COMPAT)
+       INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/contrib/lgpl")
+       TARGET_LINK_LIBRARIES(rspamdclient glibadditions)
+ENDIF(GLIB_COMPAT)
+
+IF(NO_SHARED MATCHES "OFF")
+       INSTALL(TARGETS rspamdclient LIBRARY PUBLIC_HEADER 
+               LIBRARY DESTINATION ${LIBDIR} 
+       PUBLIC_HEADER DESTINATION ${INCLUDEDIR}
+               ARCHIVE DESTINATION ${LIBDIR})
+ENDIF(NO_SHARED MATCHES "OFF")
+
 # rspamc
 SET(RSPAMCSRC                    rspamc.c)
 
diff --git a/src/client/rspamdclient.c b/src/client/rspamdclient.c
new file mode 100644 (file)
index 0000000..126ddcd
--- /dev/null
@@ -0,0 +1,23 @@
+/* Copyright (c) 2014, Vsevolod Stakhov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *       * Redistributions of source code must retain the above copyright
+ *         notice, this list of conditions and the following disclaimer.
+ *       * Redistributions in binary form must reproduce the above copyright
+ *         notice, this list of conditions and the following disclaimer in the
+ *         documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
diff --git a/src/client/rspamdclient.h b/src/client/rspamdclient.h
new file mode 100644 (file)
index 0000000..90a4c1c
--- /dev/null
@@ -0,0 +1,32 @@
+/* Copyright (c) 2014, Vsevolod Stakhov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *       * Redistributions of source code must retain the above copyright
+ *         notice, this list of conditions and the following disclaimer.
+ *       * Redistributions in binary form must reproduce the above copyright
+ *         notice, this list of conditions and the following disclaimer in the
+ *         documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RSPAMDCLIENT_H_
+#define RSPAMDCLIENT_H_
+
+#include "config.h"
+#include "ucl.h"
+
+
+
+#endif /* RSPAMDCLIENT_H_ */