#include "cryptobox.h"
#include "keypairs_cache.h"
#include "keypair_private.h"
+#include "ref.h"
/* This number is used as expire time in seconds for cache items (2 days) */
#define DEFAULT_EXPIRE 172800L
struct fuzzy_session {
struct rspamd_worker *worker;
+ rspamd_inet_addr_t *addr;
+ struct rspamd_fuzzy_storage_ctx *ctx;
union {
struct rspamd_fuzzy_encrypted_shingle_cmd enc_shingle;
struct rspamd_fuzzy_cmd normal;
struct rspamd_fuzzy_shingle_cmd shingle;
} cmd;
+
+ struct rspamd_fuzzy_encrypted_reply reply;
+
enum rspamd_fuzzy_epoch epoch;
enum fuzzy_cmd_type cmd_type;
gint fd;
guint64 time;
- rspamd_inet_addr_t *addr;
- struct rspamd_fuzzy_storage_ctx *ctx;
+ struct event io;
+ ref_entry_t ref;
guchar nm[rspamd_cryptobox_MAX_NMBYTES];
};
+static void rspamd_fuzzy_write_reply (struct fuzzy_session *session);
+
static gboolean
rspamd_fuzzy_check_client (struct fuzzy_session *session)
{
}
static void
-rspamd_fuzzy_write_reply (struct fuzzy_session *session,
- gconstpointer data, gsize len)
+rspamd_fuzzy_reply_io (gint fd, gshort what, gpointer d)
+{
+ struct fuzzy_session *session = d;
+
+ rspamd_fuzzy_write_reply (session);
+ REF_RELEASE (session);
+}
+
+static void
+rspamd_fuzzy_write_reply (struct fuzzy_session *session)
{
gssize r;
+ gsize len;
+ gconstpointer data;
+
+ if (session->cmd_type == CMD_ENCRYPTED_NORMAL ||
+ session->cmd_type == CMD_ENCRYPTED_SHINGLE) {
+ /* Encrypted reply */
+ data = &session->reply;
+ len = sizeof (session->reply);
+ }
+ else {
+ data = &session->reply.rep;
+ len = sizeof (session->reply.rep);
+ }
r = rspamd_inet_address_sendto (session->fd, data, len, 0,
session->addr);
if (r == -1) {
- if (errno == EINTR) {
- rspamd_fuzzy_write_reply (session, data, len);
+ if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
+ /* Grab reference to avoid early destruction */
+ REF_RETAIN (session);
+ event_set (&session->io, session->fd, EV_WRITE,
+ rspamd_fuzzy_reply_io, session);
+ event_base_set (session->ctx->ev_base, &session->io);
+ event_add (&session->io, NULL);
}
else {
msg_err ("error while writing reply: %s", strerror (errno));
{
gboolean res = FALSE, encrypted = FALSE;
struct rspamd_fuzzy_cmd *cmd;
- struct rspamd_fuzzy_encrypted_reply rep;
struct rspamd_fuzzy_reply result;
switch (session->cmd_type) {
}
result.tag = cmd->tag;
- memcpy (&rep.rep, &result, sizeof (result));
+ memcpy (&session->reply.rep, &result, sizeof (result));
if (encrypted) {
/* We need also to encrypt reply */
- ottery_rand_bytes (rep.hdr.nonce, sizeof (rep.hdr.nonce));
- rspamd_cryptobox_encrypt_nm_inplace ((guchar *)&rep.rep, sizeof (rep.rep),
- rep.hdr.nonce, session->nm, rep.hdr.mac);
- rspamd_fuzzy_write_reply (session, &rep, sizeof (rep));
- }
- else {
- rspamd_fuzzy_write_reply (session, &rep.rep, sizeof (rep.rep));
+ ottery_rand_bytes (session->reply.hdr.nonce,
+ sizeof (session->reply.hdr.nonce));
+ rspamd_cryptobox_encrypt_nm_inplace ((guchar *)&session->reply.rep,
+ sizeof (session->reply.rep),
+ session->reply.hdr.nonce,
+ session->nm,
+ session->reply.hdr.mac);
}
+
+ rspamd_fuzzy_write_reply (session);
}
return TRUE;
}
+static void
+fuzzy_session_destroy (gpointer d)
+{
+ struct fuzzy_session *session = d;
+
+ rspamd_inet_address_destroy (session->addr);
+ rspamd_explicit_memzero (session->nm, sizeof (session->nm));
+ session->worker->nconns--;
+ g_slice_free1 (sizeof (*session), session);
+}
+
/*
* Accept new connection and construct task
*/
accept_fuzzy_socket (gint fd, short what, void *arg)
{
struct rspamd_worker *worker = (struct rspamd_worker *)arg;
- struct fuzzy_session session;
+ struct fuzzy_session *session;
+ rspamd_inet_addr_t *addr;
gssize r;
guint8 buf[512];
- session.worker = worker;
- session.fd = fd;
- session.ctx = worker->ctx;
- session.time = (guint64)time (NULL);
-
/* Got some data */
if (what == EV_READ) {
buf,
sizeof (buf),
0,
- &session.addr);
+ &addr);
if (r == -1) {
if (errno == EINTR) {
continue;
}
- else if (errno == EAGAIN) {
+ else if (errno == EAGAIN || errno == EWOULDBLOCK) {
+
return;
}
return;
}
- if (rspamd_fuzzy_cmd_from_wire (buf, r, &session)) {
+ session = g_slice_alloc0 (sizeof (*session));
+ REF_INIT_RETAIN (session, fuzzy_session_destroy);
+ session->worker = worker;
+ session->fd = fd;
+ session->ctx = worker->ctx;
+ session->time = (guint64) time (NULL);
+ session->addr = addr;
+
+ if (rspamd_fuzzy_cmd_from_wire (buf, r, session)) {
/* Check shingles count sanity */
- rspamd_fuzzy_process_command (&session);
+ rspamd_fuzzy_process_command (session);
}
else {
/* Discard input */
msg_debug ("invalid fuzzy command of size %d received", r);
}
- rspamd_inet_address_destroy (session.addr);
- rspamd_explicit_memzero (session.nm, sizeof (session.nm));
- worker->nconns--;
+ REF_RELEASE (session);
}
}
}