summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server.c109
1 files changed, 81 insertions, 28 deletions
diff --git a/src/server.c b/src/server.c
index 2fae757..9154a3c 100644
--- a/src/server.c
+++ b/src/server.c
@@ -48,7 +48,8 @@ enum server_cmd {
};
struct server_conn {
- int fd;
+ int fdin;
+ int fdout;
struct sockaddr addr;
socklen_t addrlen;
@@ -71,7 +72,8 @@ struct server_conn {
#include <conts/vec.h>
struct server_ctx {
- int tcp_sock;
+ int sock;
+ bool oneshot;
struct server_conns conns;
struct conn_polls polls;
int timeout;
@@ -130,6 +132,8 @@ static bool streq(const char *s1, const char *s2)
static int new_connection(struct server_ctx *ctx, int new_conn_fd)
{
+ assert(!ctx->oneshot);
+
struct sockaddr addr;
socklen_t addrlen;
@@ -159,7 +163,8 @@ static int new_connection(struct server_ctx *ctx, int new_conn_fd)
}
struct server_conn conn = {
- .fd = fd,
+ .fdin = fd,
+ .fdout = fd,
.addr = addr,
.addrlen = addrlen,
.cmd = META_PARSE_CMD,
@@ -176,7 +181,10 @@ static int new_connection(struct server_ctx *ctx, int new_conn_fd)
* freed by now. Invalidates the conn pointer! */
static int kill_connection(struct server_ctx *ctx, struct server_conn *conn)
{
- close(conn->fd);
+ close(conn->fdin);
+ if (conn->fdout != conn->fdin)
+ close(conn->fdout);
+
strbuf_destroy(&conn->strbuf);
assert(server_conns_len(&ctx->conns) >= 1);
@@ -203,7 +211,7 @@ static ssize_t reread(struct server_conn *conn, size_t c)
size_t n = strbuf->n;
strbuf_reserve(strbuf, n + c);
- ssize_t r = readx(conn->fd, strbuf->buf + n, c);
+ ssize_t r = readx(conn->fdin, strbuf->buf + n, c);
if (r < 0)
return r;
@@ -609,7 +617,7 @@ static enum que_op sync_cmd(struct server_ctx *ctx, struct server_conn *conn)
syslog(LOG_DEBUG, "sending sync\n");
const char buf[] = "From: urmum@amazon.com";
- ssize_t ret = writex(conn->fd, buf, sizeof(buf));
+ ssize_t ret = writex(conn->fdout, buf, sizeof(buf));
assert(ret == sizeof(buf));
conn->cmd = META_PARSE_CMD;
destroy_sync(cmd);
@@ -621,22 +629,44 @@ static enum que_op sync_cmd(struct server_ctx *ctx, struct server_conn *conn)
return LARK_KILL;
}
-static int event_loop(int tcp_sock)
+static int event_loop(int sock, bool oneshot)
{
struct server_ctx ctx = {
- .tcp_sock = tcp_sock,
+ .sock = sock,
+ .oneshot = oneshot,
.conns = server_conns_create(0),
.polls = conn_polls_create(0),
.timeout = -1
};
+ /* set up a connection */
+ if (oneshot) {
+ struct server_conn conn = {
+ .fdin = sock,
+ .fdout = sock == STDIN_FILENO ? STDOUT_FILENO : sock,
+ .addr = {},
+ .addrlen = 0,
+ .cmd = META_PARSE_CMD,
+ .strbuf = strbuf_create(0),
+ .nextlen = 0
+ };
+
+ memset(&conn.u, 0, sizeof(conn.u));
+ server_conns_append(&ctx.conns, conn);
+ }
+
int ret = 0;
while (1) {
+ if (ctx.oneshot && server_conns_len(&ctx.conns) == 0)
+ break;
+
/* build up set of connections to poll */
conn_polls_reset(&ctx.polls);
+ /* no need to poll if we're in oneshot mode, but keep pollfd
+ * around to simplify index calculations */
struct pollfd tcp_poll = {
- .fd = ctx.tcp_sock,
+ .fd = ctx.oneshot ? -1 : ctx.sock,
.events = POLLIN,
.revents = 0
};
@@ -644,7 +674,7 @@ static int event_loop(int tcp_sock)
foreach(server_conns, c, &ctx.conns) {
struct pollfd conn_poll = {
- .fd = c->fd,
+ .fd = c->fdin,
.events = POLLIN,
.revents = 0
};
@@ -732,31 +762,54 @@ static int event_loop(int tcp_sock)
int main(int argc, char *argv[argc])
{
- int ret = 0;
+ int ret = 0, opt;
- openlog(NULL, LOG_PERROR, LOG_USER);
+ const char *single_conn = NULL;
+ while ((opt = getopt(argc, argv, "s:")) != -1) {
+ switch (opt) {
+ case 's':
+ single_conn = optarg;
+ break;
- int tcp_sock = socket(AF_INET, SOCK_STREAM, 0);
- if (tcp_sock == -1) {
- err(EXIT_FAILURE, "failed opening tcp socket");
+ default:
+ fprintf(stderr, "usage: %s [-s socket or - for stdin]\n",
+ argv[0]);
+ exit(EXIT_FAILURE);
+ }
}
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- /* should probably come up with a reasonable port at some point */
- addr.sin_port = htons(24242);
+ openlog(NULL, LOG_PERROR, LOG_USER);
- if (bind(tcp_sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
- err(EXIT_FAILURE, "failed binding tcp socket");
- }
+ int sock = -1;
+ if (single_conn) {
+ if (streq(single_conn, "-"))
+ sock = STDIN_FILENO;
+ else
+ sock = open(single_conn, O_RDONLY);
+
+ if (sock == -1)
+ err(EXIT_FAILURE, "failed opening single connection");
+
+ } else {
+ int sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock == -1)
+ err(EXIT_FAILURE, "failed opening tcp socket");
+
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ /* should probably come up with a reasonable port at some point */
+ addr.sin_port = htons(24242);
+
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1)
+ err(EXIT_FAILURE, "failed binding tcp socket");
- if (listen(tcp_sock, 64) == -1) {
- err(EXIT_FAILURE, "failed listening on tcp socket");
+ if (listen(sock, 64) == -1)
+ err(EXIT_FAILURE, "failed listening on tcp socket");
}
- ret = event_loop(tcp_sock);
- close(tcp_sock);
+ ret = event_loop(sock, single_conn != NULL);
+ close(sock);
return ret;
}