2015-06-22 21:13:32 +02:00
|
|
|
/*
|
2018-01-20 22:51:06 +01:00
|
|
|
* Copyright (c) 2018 Joris Vink <joris@coders.se>
|
2015-06-22 21:13:32 +02:00
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
|
|
|
#include "kore.h"
|
|
|
|
#include "http.h"
|
|
|
|
|
|
|
|
struct msg_type {
|
|
|
|
u_int8_t id;
|
2015-06-23 18:17:14 +02:00
|
|
|
void (*cb)(struct kore_msg *, const void *);
|
2015-06-22 21:13:32 +02:00
|
|
|
TAILQ_ENTRY(msg_type) list;
|
|
|
|
};
|
|
|
|
|
|
|
|
TAILQ_HEAD(, msg_type) msg_types;
|
|
|
|
|
|
|
|
static struct msg_type *msg_type_lookup(u_int8_t);
|
2015-06-23 18:17:14 +02:00
|
|
|
static int msg_recv_packet(struct netbuf *);
|
|
|
|
static int msg_recv_data(struct netbuf *);
|
2015-06-22 21:13:32 +02:00
|
|
|
static void msg_disconnected_parent(struct connection *);
|
2015-07-06 21:08:36 +02:00
|
|
|
static void msg_disconnected_worker(struct connection *);
|
2018-08-13 09:53:49 +02:00
|
|
|
static void msg_type_shutdown(struct kore_msg *, const void *);
|
2015-11-27 16:22:50 +01:00
|
|
|
|
|
|
|
#if !defined(KORE_NO_HTTP)
|
2015-06-23 18:17:14 +02:00
|
|
|
static void msg_type_accesslog(struct kore_msg *, const void *);
|
|
|
|
static void msg_type_websocket(struct kore_msg *, const void *);
|
2015-11-27 16:22:50 +01:00
|
|
|
#endif
|
2015-06-22 21:13:32 +02:00
|
|
|
|
|
|
|
void
|
|
|
|
kore_msg_init(void)
|
|
|
|
{
|
|
|
|
TAILQ_INIT(&msg_types);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
kore_msg_parent_init(void)
|
|
|
|
{
|
|
|
|
u_int8_t i;
|
|
|
|
struct kore_worker *kw;
|
|
|
|
|
|
|
|
for (i = 0; i < worker_count; i++) {
|
|
|
|
kw = kore_worker_data(i);
|
|
|
|
kore_msg_parent_add(kw);
|
|
|
|
}
|
2015-06-23 18:17:14 +02:00
|
|
|
|
2018-08-13 09:53:49 +02:00
|
|
|
kore_msg_register(KORE_MSG_SHUTDOWN, msg_type_shutdown);
|
|
|
|
|
2015-11-27 16:22:50 +01:00
|
|
|
#if !defined(KORE_NO_HTTP)
|
2015-06-23 18:17:14 +02:00
|
|
|
kore_msg_register(KORE_MSG_ACCESSLOG, msg_type_accesslog);
|
2015-11-27 16:22:50 +01:00
|
|
|
#endif
|
2015-06-22 21:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
kore_msg_parent_add(struct kore_worker *kw)
|
|
|
|
{
|
|
|
|
kw->msg[0] = kore_connection_new(NULL);
|
|
|
|
kw->msg[0]->fd = kw->pipe[0];
|
|
|
|
kw->msg[0]->read = net_read;
|
|
|
|
kw->msg[0]->write = net_write;
|
|
|
|
kw->msg[0]->proto = CONN_PROTO_MSG;
|
|
|
|
kw->msg[0]->state = CONN_STATE_ESTABLISHED;
|
2015-07-07 16:11:40 +02:00
|
|
|
kw->msg[0]->hdlr_extra = &kw->id;
|
2015-07-06 21:08:36 +02:00
|
|
|
kw->msg[0]->disconnect = msg_disconnected_worker;
|
2015-12-10 09:26:24 +01:00
|
|
|
kw->msg[0]->handle = kore_connection_handle;
|
2015-06-22 21:13:32 +02:00
|
|
|
|
|
|
|
TAILQ_INSERT_TAIL(&connections, kw->msg[0], list);
|
|
|
|
kore_platform_event_all(kw->msg[0]->fd, kw->msg[0]);
|
|
|
|
|
2015-06-23 18:17:14 +02:00
|
|
|
net_recv_queue(kw->msg[0], sizeof(struct kore_msg), 0, msg_recv_packet);
|
2015-06-22 21:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
kore_msg_parent_remove(struct kore_worker *kw)
|
|
|
|
{
|
|
|
|
kore_connection_disconnect(kw->msg[0]);
|
|
|
|
kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
|
|
|
|
(void)close(kw->pipe[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
kore_msg_worker_init(void)
|
|
|
|
{
|
2015-11-27 16:22:50 +01:00
|
|
|
#if !defined(KORE_NO_HTTP)
|
2015-06-23 18:17:14 +02:00
|
|
|
kore_msg_register(KORE_MSG_WEBSOCKET, msg_type_websocket);
|
2015-11-27 16:22:50 +01:00
|
|
|
#endif
|
2015-06-23 18:17:14 +02:00
|
|
|
|
2015-06-22 21:13:32 +02:00
|
|
|
worker->msg[1] = kore_connection_new(NULL);
|
|
|
|
worker->msg[1]->fd = worker->pipe[1];
|
|
|
|
worker->msg[1]->read = net_read;
|
|
|
|
worker->msg[1]->write = net_write;
|
|
|
|
worker->msg[1]->proto = CONN_PROTO_MSG;
|
|
|
|
worker->msg[1]->state = CONN_STATE_ESTABLISHED;
|
|
|
|
worker->msg[1]->disconnect = msg_disconnected_parent;
|
2015-12-10 09:26:24 +01:00
|
|
|
worker->msg[1]->handle = kore_connection_handle;
|
2018-10-09 19:34:40 +02:00
|
|
|
worker->msg[1]->evt.flags = KORE_EVENT_WRITE;
|
2015-06-22 21:13:32 +02:00
|
|
|
|
|
|
|
TAILQ_INSERT_TAIL(&connections, worker->msg[1], list);
|
|
|
|
kore_platform_event_all(worker->msg[1]->fd, worker->msg[1]);
|
|
|
|
|
|
|
|
net_recv_queue(worker->msg[1],
|
2015-06-23 18:17:14 +02:00
|
|
|
sizeof(struct kore_msg), 0, msg_recv_packet);
|
2015-06-22 21:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2015-06-23 18:17:14 +02:00
|
|
|
kore_msg_register(u_int8_t id, void (*cb)(struct kore_msg *, const void *))
|
2015-06-22 21:13:32 +02:00
|
|
|
{
|
|
|
|
struct msg_type *type;
|
|
|
|
|
|
|
|
if ((type = msg_type_lookup(id)) != NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
type = kore_malloc(sizeof(*type));
|
|
|
|
type->id = id;
|
|
|
|
type->cb = cb;
|
|
|
|
TAILQ_INSERT_TAIL(&msg_types, type, list);
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-07-11 09:44:29 +02:00
|
|
|
kore_msg_send(u_int16_t dst, u_int8_t id, const void *data, size_t len)
|
2015-06-22 21:13:32 +02:00
|
|
|
{
|
|
|
|
struct kore_msg m;
|
|
|
|
|
|
|
|
m.id = id;
|
2015-07-06 21:08:36 +02:00
|
|
|
m.dst = dst;
|
2015-06-22 21:13:32 +02:00
|
|
|
m.length = len;
|
2015-07-06 21:08:36 +02:00
|
|
|
m.src = worker->id;
|
2015-06-22 21:13:32 +02:00
|
|
|
|
2015-11-27 16:22:50 +01:00
|
|
|
net_send_queue(worker->msg[1], &m, sizeof(m));
|
2017-02-28 06:27:50 +01:00
|
|
|
if (data != NULL && len > 0)
|
|
|
|
net_send_queue(worker->msg[1], data, len);
|
|
|
|
|
2015-06-22 21:13:32 +02:00
|
|
|
net_send_flush(worker->msg[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2015-06-23 18:17:14 +02:00
|
|
|
msg_recv_packet(struct netbuf *nb)
|
2015-06-22 21:13:32 +02:00
|
|
|
{
|
|
|
|
struct kore_msg *msg = (struct kore_msg *)nb->buf;
|
|
|
|
|
2017-02-28 06:27:50 +01:00
|
|
|
if (msg->length > 0) {
|
|
|
|
net_recv_expand(nb->owner, msg->length, msg_recv_data);
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (msg_recv_data(nb));
|
2015-06-22 21:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2015-06-23 18:17:14 +02:00
|
|
|
msg_recv_data(struct netbuf *nb)
|
2015-06-22 21:13:32 +02:00
|
|
|
{
|
2015-06-23 18:17:14 +02:00
|
|
|
struct connection *c;
|
2015-06-22 21:13:32 +02:00
|
|
|
struct msg_type *type;
|
2015-07-06 21:16:22 +02:00
|
|
|
u_int16_t destination;
|
2015-06-22 21:13:32 +02:00
|
|
|
struct kore_msg *msg = (struct kore_msg *)nb->buf;
|
|
|
|
|
2015-07-06 21:08:36 +02:00
|
|
|
if ((type = msg_type_lookup(msg->id)) != NULL) {
|
|
|
|
if (worker == NULL && msg->dst != KORE_MSG_PARENT)
|
|
|
|
fatal("received parent msg for non parent dst");
|
2015-07-06 21:16:22 +02:00
|
|
|
if (worker != NULL && msg->dst != worker->id)
|
|
|
|
fatal("received message for incorrect worker");
|
|
|
|
|
2017-02-28 06:27:50 +01:00
|
|
|
if (msg->length > 0)
|
|
|
|
type->cb(msg, nb->buf + sizeof(*msg));
|
|
|
|
else
|
|
|
|
type->cb(msg, NULL);
|
2015-07-06 21:08:36 +02:00
|
|
|
}
|
2015-06-23 18:17:14 +02:00
|
|
|
|
|
|
|
if (worker == NULL && type == NULL) {
|
2015-07-06 21:16:22 +02:00
|
|
|
destination = msg->dst;
|
2015-06-23 18:17:14 +02:00
|
|
|
TAILQ_FOREACH(c, &connections, list) {
|
2015-07-06 21:08:36 +02:00
|
|
|
if (c->proto != CONN_PROTO_MSG || c->hdlr_extra == NULL)
|
|
|
|
continue;
|
|
|
|
|
2015-07-06 21:16:22 +02:00
|
|
|
if (destination != KORE_MSG_WORKER_ALL &&
|
|
|
|
*(u_int8_t *)c->hdlr_extra != destination)
|
2015-07-06 21:08:36 +02:00
|
|
|
continue;
|
|
|
|
|
2015-07-06 21:16:22 +02:00
|
|
|
/* This allows the worker to receive the correct id. */
|
|
|
|
msg->dst = *(u_int8_t *)c->hdlr_extra;
|
|
|
|
|
2015-11-27 16:22:50 +01:00
|
|
|
net_send_queue(c, nb->buf, nb->s_off);
|
2015-06-23 18:17:14 +02:00
|
|
|
net_send_flush(c);
|
|
|
|
}
|
2015-06-22 21:13:32 +02:00
|
|
|
}
|
|
|
|
|
2015-06-23 18:17:14 +02:00
|
|
|
net_recv_reset(nb->owner, sizeof(struct kore_msg), msg_recv_packet);
|
2015-06-22 21:13:32 +02:00
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
msg_disconnected_parent(struct connection *c)
|
|
|
|
{
|
|
|
|
kore_log(LOG_ERR, "parent gone, shutting down");
|
|
|
|
if (kill(worker->pid, SIGQUIT) == -1)
|
|
|
|
kore_log(LOG_ERR, "failed to send SIGQUIT: %s", errno_s);
|
|
|
|
}
|
|
|
|
|
2015-07-06 21:08:36 +02:00
|
|
|
static void
|
|
|
|
msg_disconnected_worker(struct connection *c)
|
|
|
|
{
|
|
|
|
c->hdlr_extra = NULL;
|
|
|
|
}
|
|
|
|
|
2018-08-13 09:53:49 +02:00
|
|
|
static void
|
|
|
|
msg_type_shutdown(struct kore_msg *msg, const void *data)
|
|
|
|
{
|
|
|
|
kore_log(LOG_NOTICE,
|
|
|
|
"shutdown requested by worker %u, going down", msg->src);
|
|
|
|
|
|
|
|
(void)raise(SIGQUIT);
|
|
|
|
}
|
|
|
|
|
2015-11-27 16:22:50 +01:00
|
|
|
#if !defined(KORE_NO_HTTP)
|
2015-06-23 18:17:14 +02:00
|
|
|
static void
|
|
|
|
msg_type_accesslog(struct kore_msg *msg, const void *data)
|
|
|
|
{
|
|
|
|
if (kore_accesslog_write(data, msg->length) == -1)
|
|
|
|
kore_log(LOG_WARNING, "failed to write to accesslog");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
msg_type_websocket(struct kore_msg *msg, const void *data)
|
|
|
|
{
|
|
|
|
struct connection *c;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(c, &connections, list) {
|
|
|
|
if (c->proto == CONN_PROTO_WEBSOCKET) {
|
2015-11-27 16:22:50 +01:00
|
|
|
net_send_queue(c, data, msg->length);
|
2015-06-23 18:17:14 +02:00
|
|
|
net_send_flush(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-11-27 16:22:50 +01:00
|
|
|
#endif
|
2015-06-23 18:17:14 +02:00
|
|
|
|
2015-06-22 21:13:32 +02:00
|
|
|
static struct msg_type *
|
|
|
|
msg_type_lookup(u_int8_t id)
|
|
|
|
{
|
|
|
|
struct msg_type *type;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(type, &msg_types, list) {
|
|
|
|
if (type->id == id)
|
|
|
|
return (type);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (NULL);
|
|
|
|
}
|