}
static void
-lua_tcp_push_error (struct lua_tcp_cbdata *cbd, const char *err, ...)
+lua_tcp_push_error (struct lua_tcp_cbdata *cbd, gboolean is_fatal,
+ const char *err, ...)
{
- va_list ap;
+ va_list ap, ap_copy;
struct lua_tcp_cbdata **pcbd;
struct lua_tcp_handler *hdl;
gint cbref;
- hdl = g_queue_peek_head (cbd->handlers);
+ va_start (ap, err);
- g_assert (hdl != NULL);
+ for (;;) {
+ if (is_fatal) {
+ hdl = g_queue_pop_head (cbd->handlers);
+ }
+ else {
+ hdl = g_queue_peek_head (cbd->handlers);
+ }
- if (hdl->type == LUA_WANT_READ) {
- cbref = hdl->h.r.cbref;
- }
- else {
- cbref = hdl->h.w.cbref;
- }
+ if (hdl == NULL) {
+ va_end (ap_copy);
+ break;
+ }
- if (cbref != -1) {
- lua_rawgeti (cbd->L, LUA_REGISTRYINDEX, cbref);
+ if (hdl->type == LUA_WANT_READ) {
+ cbref = hdl->h.r.cbref;
+ }
+ else {
+ cbref = hdl->h.w.cbref;
+ }
- /* Error message */
- va_start (ap, err);
- lua_pushvfstring (cbd->L, err, ap);
- va_end (ap);
+ if (cbref != -1) {
+ lua_rawgeti (cbd->L, LUA_REGISTRYINDEX, cbref);
- /* Body */
- lua_pushnil (cbd->L);
- /* Connection */
- pcbd = lua_newuserdata (cbd->L, sizeof (*pcbd));
- *pcbd = cbd;
- rspamd_lua_setclass (cbd->L, "rspamd{tcp}", -1);
- REF_RETAIN (cbd);
+ /* Error message */
+ va_copy (ap_copy, ap);
+ lua_pushvfstring (cbd->L, err, ap_copy);
+ va_end (ap_copy);
- if (lua_pcall (cbd->L, 3, 0, 0) != 0) {
- msg_info ("callback call failed: %s", lua_tostring (cbd->L, -1));
- lua_pop (cbd->L, 1);
+ /* Body */
+ lua_pushnil (cbd->L);
+ /* Connection */
+ pcbd = lua_newuserdata (cbd->L, sizeof (*pcbd));
+ *pcbd = cbd;
+ rspamd_lua_setclass (cbd->L, "rspamd{tcp}", -1);
+ REF_RETAIN (cbd);
+
+ if (lua_pcall (cbd->L, 3, 0, 0) != 0) {
+ msg_info ("callback call failed: %s", lua_tostring (cbd->L, -1));
+ lua_pop (cbd->L, 1);
+ }
+
+ REF_RELEASE (cbd);
}
- REF_RELEASE (cbd);
+ if (!is_fatal) {
+ /* Stop on the first callback found */
+ break;
+ }
}
+
+ va_end (ap);
}
static void
r = sendmsg (cbd->fd, &msg, flags);
if (r == -1) {
- lua_tcp_push_error (cbd, "IO write error while trying to write %d "
+ lua_tcp_push_error (cbd, FALSE, "IO write error while trying to write %d "
"bytes: %s", (gint)remain, strerror (errno));
lua_tcp_shift_handler (cbd);
lua_tcp_plan_handler_event (cbd, TRUE, FALSE);
lua_tcp_process_read_handler (cbd, rh);
}
else {
- lua_tcp_push_error (cbd, "IO read error: connection terminated");
+ lua_tcp_push_error (cbd, FALSE, "IO read error: connection terminated");
}
lua_tcp_plan_handler_event (cbd, FALSE, TRUE);
}
/* Fatal error */
- lua_tcp_push_error (cbd, "IO read error while trying to read data: %s",
+ lua_tcp_push_error (cbd, TRUE, "IO read error while trying to read data: %s",
strerror (errno));
REF_RELEASE (cbd);
else if (what == EV_WRITE) {
if (!(cbd->flags & LUA_TCP_FLAG_CONNECTED)) {
if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error, &so_len) == -1) {
- lua_tcp_push_error (cbd, "Cannot get socket error: %s",
+ lua_tcp_push_error (cbd, TRUE, "Cannot get socket error: %s",
strerror (errno));
REF_RELEASE (cbd);
goto out;
}
else if (so_error != 0) {
- lua_tcp_push_error (cbd, "Socket error detected: %s",
+ lua_tcp_push_error (cbd, TRUE, "Socket error detected: %s",
strerror (so_error));
REF_RELEASE (cbd);
goto out;
}
#ifdef EV_CLOSED
else if (what == EV_CLOSED) {
- lua_tcp_push_error (cbd, "Remote peer has closed the connection");
+ lua_tcp_push_error (cbd, TRUE, "Remote peer has closed the connection");
REF_RELEASE (cbd);
}
#endif
else {
- lua_tcp_push_error (cbd, "IO timeout");
+ lua_tcp_push_error (cbd, TRUE, "IO timeout");
REF_RELEASE (cbd);
}
}
else {
/* Cannot read more */
- lua_tcp_push_error (cbd, "EOF, cannot read more data");
+ lua_tcp_push_error (cbd, FALSE, "EOF, cannot read more data");
lua_tcp_shift_handler (cbd);
lua_tcp_plan_handler_event (cbd, can_read, can_write);
}
}
else {
/* Cannot write more */
- lua_tcp_push_error (cbd, "EOF, cannot write more data");
+ lua_tcp_push_error (cbd, FALSE, "EOF, cannot write more data");
lua_tcp_shift_handler (cbd);
lua_tcp_plan_handler_event (cbd, can_read, can_write);
}
if (reply->code != RDNS_RC_NOERROR) {
rn = rdns_request_get_name (reply->request, NULL);
- lua_tcp_push_error (cbd, "unable to resolve host: %s",
+ lua_tcp_push_error (cbd, TRUE, "unable to resolve host: %s",
rn->name);
- REF_RETAIN (cbd);
+ REF_RELEASE (cbd);
}
else {
if (reply->entries->type == RDNS_REQUEST_A) {
rspamd_inet_address_set_port (cbd->addr, cbd->port);
if (!lua_tcp_make_connection (cbd)) {
- lua_tcp_push_error (cbd, "unable to make connection to the host %s",
+ lua_tcp_push_error (cbd, TRUE, "unable to make connection to the host %s",
rspamd_inet_address_to_string (cbd->addr));
- REF_RETAIN (cbd);
+ REF_RELEASE (cbd);
}
}
}
if (task == NULL) {
if (!make_dns_request (resolver, session, NULL, lua_tcp_dns_handler, cbd,
RDNS_REQUEST_A, host)) {
- lua_tcp_push_error (cbd, "cannot resolve host: %s", host);
- REF_RETAIN (cbd);
+ lua_tcp_push_error (cbd, TRUE, "cannot resolve host: %s", host);
+ REF_RELEASE (cbd);
}
}
else {
if (!make_dns_request_task (task, lua_tcp_dns_handler, cbd,
RDNS_REQUEST_A, host)) {
- lua_tcp_push_error (cbd, "cannot resolve host: %s", host);
+ lua_tcp_push_error (cbd, TRUE, "cannot resolve host: %s", host);
REF_RELEASE (cbd);
}
}