Skip to content

Commit

Permalink
[quark] Replace UID with Quark
Browse files Browse the repository at this point in the history
  Quark is a lightweight C-based webserver. This commit removes the old
  OCAML-based webserver, UID, and replaces it with Quark. We also
  add POST support to Quark to allow for the UI code to log debug
  messages to dom0

Signed-off-by: Chris Rogers <[email protected]>
  • Loading branch information
Chris Rogers committed Dec 24, 2020
1 parent 503bc07 commit 05c1353
Show file tree
Hide file tree
Showing 8 changed files with 395 additions and 135 deletions.
2 changes: 1 addition & 1 deletion recipes-core/packagegroups/packagegroup-xenclient-dom0.bb
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ RDEPENDS_${PN} = " \
vusb-daemon \
xenmgr-data \
updatemgr \
uid \
surfman \
linuxfb-surfman-plugin \
xenmgr \
Expand All @@ -113,6 +112,7 @@ RDEPENDS_${PN} = " \
pesign \
ipxe \
udev-extraconf-dom0 \
quark \
"

# OE upgrade - temporarly disabled:
Expand Down
319 changes: 319 additions & 0 deletions recipes-extended/quark/files/add-POST-and-argo-support.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,319 @@
################################################################################
SHORT DESCRIPTION:
################################################################################
Add POST and argo support to quark.

################################################################################
LONG DESCRIPTION:
################################################################################
POST support: very basic; added to support surf sending log messages via POST

argo support: added a few select() calls to prevent server lockup when serving
resources

################################################################################
CHANGELOG
################################################################################
x64 patch: Nicholas Tsirakis <[email protected]>

################################################################################
REMOVAL
################################################################################

################################################################################
UPSTREAM PLAN
################################################################################

################################################################################
INTERNAL DEPENDENCIES
################################################################################

################################################################################
PATCHES
################################################################################

commit 8ea834685a163c7dd20ac6c46e0efcae43f8d2e8
Author: Nicholas Tsirakis <[email protected]>
Date: Tue Feb 12 10:22:24 2019 -0500

x64 patch

diff --git a/config.mk b/config.mk
index 7056241..668b0ef 100644
--- a/config.mk
+++ b/config.mk
@@ -4,13 +4,13 @@ VERSION = 0
# Customize below to fit your system

# paths
-PREFIX = /usr/local
+PREFIX ?= /usr
MANPREFIX = $(PREFIX)/share/man

# flags
-CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700 -D_BSD_SOURCE
-CFLAGS = -std=c99 -pedantic -Wall -Wextra -Os
-LDFLAGS = -s
+CPPFLAGS ?= -DVERSION=\"$(VERSION)\" -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700 -D_BSD_SOURCE
+CFLAGS ?= -std=c99 -pedantic -Wall -Wextra -O
+LDFLAGS ?=

# compiler and linker
-CC = cc
+CC ?= gcc
diff --git a/http.c b/http.c
index c848e81..f53c25c 100644
--- a/http.c
+++ b/http.c
@@ -30,6 +30,7 @@ const char *req_field_str[] = {
const char *req_method_str[] = {
[M_GET] = "GET",
[M_HEAD] = "HEAD",
+ [M_POST] = "POST"
};

const char *status_str[] = {
@@ -121,14 +122,37 @@ http_get_request(int fd, struct request *r)
}
}

- /* remove terminating empty line */
- if (hlen < 2) {
+ /* split header and payload (if applicable)
+ *
+ * expected POST format: HEADER,
+ * two newlines,
+ * PAYLOAD,
+ * two newlines
+ *
+ * expected GET format: HEADER,
+ * two newlines
+ */
+
+ /* find first occurrence of double newlines */
+ p = strstr(h, "\r\n\r\n");
+ if (!p) {
return http_send_status(fd, S_BAD_REQUEST);
}
- hlen -= 2;

- /* null-terminate the header */
- h[hlen] = '\0';
+ /* keep the first newline */
+ p += 2;
+
+ /* find second occurrence - if exists, POST request, else GET */
+ q = strstr(p, "\r\n\r\n");
+ if (q) {
+ *q = '\0';
+ strncpy(r->payload, p, q-p+1);
+ } else {
+ r->payload[0] = '\0';
+ }
+
+ /* null terminate header; strip second newline */
+ *p = '\0';

/*
* parse request line
@@ -270,6 +294,8 @@ http_get_request(int fd, struct request *r)
memmove(r->field[REQ_HOST], p, q - p + 1);
}

+ /* wait until our fd is available for the next operation */
+ wait_fd_ready(fd, true, true);
return 0;
}

@@ -355,7 +381,7 @@ http_send_response(int fd, struct request *r)
struct tm tm;
size_t len, i;
off_t lower, upper;
- int hasport, ipv6host;
+ int hasport, ipv6host, ret;
static char realtarget[PATH_MAX], tmptarget[PATH_MAX], t[TIMESTAMP_LEN];
char *p, *q, *mime;
const char *vhostmatch, *targethost, *err;
@@ -604,5 +630,10 @@ http_send_response(int fd, struct request *r)
}
}

- return resp_file(fd, RELPATH(realtarget), r, &st, mime, lower, upper);
+ /* wait until our fd is available for the next operation */
+ wait_fd_ready(fd, true, true);
+ ret = resp_file(fd, RELPATH(realtarget), r, &st, mime, lower, upper);
+ wait_fd_ready(fd, true, false);
+
+ return ret;
}
diff --git a/http.h b/http.h
index cd1ba22..f0ea49e 100644
--- a/http.h
+++ b/http.h
@@ -5,6 +5,7 @@
#include <limits.h>

#define HEADER_MAX 4096
+#define PAYLOAD_MAX 8192
#define FIELD_MAX 200

enum req_field {
@@ -19,6 +20,7 @@ extern const char *req_field_str[];
enum req_method {
M_GET,
M_HEAD,
+ M_POST,
NUM_REQ_METHODS,
};

@@ -28,6 +30,7 @@ struct request {
enum req_method method;
char target[PATH_MAX];
char field[NUM_REQ_FIELDS][FIELD_MAX];
+ char payload[PAYLOAD_MAX];
};

enum status {
diff --git a/main.c b/main.c
index e9d0a06..a3eebf6 100644
--- a/main.c
+++ b/main.c
@@ -13,6 +13,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <syslog.h>
#include <time.h>
#include <unistd.h>

@@ -31,14 +32,17 @@ serve(int infd, struct sockaddr_storage *in_sa)
char inaddr[INET6_ADDRSTRLEN /* > INET_ADDRSTRLEN */];
char tstmp[21];

- /* set connection timeout */
- if (sock_set_timeout(infd, 30)) {
- goto cleanup;
- }
-
/* handle request */
- if (!(status = http_get_request(infd, &r))) {
- status = http_send_response(infd, &r);
+ status = http_get_request(infd, &r);
+
+ if (!status) {
+ if (r.method == M_POST) {
+ /* handle POST */
+ syslog(LOG_INFO, "[quark] %s", r.payload);
+ } else {
+ /* handle GET */
+ status = http_send_response(infd, &r);
+ }
}

/* write output to log */
@@ -228,18 +232,6 @@ main(int argc, char *argv[])
die("setrlimit RLIMIT_NPROC:");
}

- /* validate user and group */
- errno = 0;
- if (user && !(pwd = getpwnam(user))) {
- die("getpwnam '%s': %s", user, errno ? strerror(errno) :
- "Entry not found");
- }
- errno = 0;
- if (group && !(grp = getgrnam(group))) {
- die("getgrnam '%s': %s", group, errno ? strerror(errno) :
- "Entry not found");
- }
-
/* Open a new process group */
setpgid(0,0);

@@ -270,23 +262,6 @@ main(int argc, char *argv[])
die("chroot .:");
}

- /* drop root */
- if (grp && setgroups(1, &(grp->gr_gid)) < 0) {
- die("setgroups:");
- }
- if (grp && setgid(grp->gr_gid) < 0) {
- die("setgid:");
- }
- if (pwd && setuid(pwd->pw_uid) < 0) {
- die("setuid:");
- }
- if (getuid() == 0) {
- die("Won't run as root user", argv0);
- }
- if (getgid() == 0) {
- die("Won't run as root group", argv0);
- }
-
/* accept incoming connections */
while (1) {
in_sa_len = sizeof(in_sa);
diff --git a/resp.c b/resp.c
index 3075c28..ee12606 100644
--- a/resp.c
+++ b/resp.c
@@ -141,6 +141,7 @@ resp_file(int fd, char *name, struct request *r, struct stat *st, char *mime,
"Date: %s\r\n"
"Connection: close\r\n"
"Last-Modified: %s\r\n"
+ "Expires: Wed, 1 Jan 2030 00:00:00 GMT\r\n"
"Content-Type: %s\r\n"
"Content-Length: %zu\r\n",
s, status_str[s], timestamp(time(NULL), t1),
diff --git a/util.c b/util.c
index 0b05d91..5e16271 100644
--- a/util.c
+++ b/util.c
@@ -133,3 +133,27 @@ reallocarray(void *optr, size_t nmemb, size_t size)
}
return realloc(optr, size * nmemb);
}
+
+void
+wait_fd_ready(int fd, bool read, bool write)
+{
+ struct timeval tv;
+ fd_set readfds;
+ fd_set writefds;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 500000;
+
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+
+ if (read) {
+ FD_SET(fd, &readfds);
+ }
+
+ if (write) {
+ FD_SET(fd, &writefds);
+ }
+
+ select(fd + 1, &readfds, &writefds, NULL, &tv);
+}
diff --git a/util.h b/util.h
index 12b7bd8..d41dc40 100644
--- a/util.h
+++ b/util.h
@@ -3,6 +3,7 @@
#define UTIL_H

#include <regex.h>
+#include <stdbool.h>
#include <stddef.h>
#include <time.h>

@@ -54,4 +55,6 @@ int esnprintf(char *, size_t, const char *, ...);
void *reallocarray(void *, size_t, size_t);
long long strtonum(const char *, long long, long long, const char **);

+void wait_fd_ready(int, bool, bool);
+
#endif /* UTIL_H */
41 changes: 41 additions & 0 deletions recipes-extended/quark/files/quark.initscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#! /bin/sh

set -e

QUARK="/usr/bin/quark"
QUARK_OPTS="-h 1.0.0.0 -p 80 -d /usr/lib/xui"
PIDFILE="/var/run/quark.pid"

start_quark() {
LD_PRELOAD=/usr/lib/libv4v-1.0.so.0.0.0 INET_IS_V4V=1 start-stop-daemon --start --background --make-pidfile --pidfile="${PIDFILE}" --quiet --oknodo --exec $QUARK -- $QUARK_OPTS
}

stop_quark() {
start-stop-daemon --stop --quiet --oknodo --pidfile="${PIDFILE}"
rm -f "${PIDFILE}"
}

test -x $QUARK || exit 0

case "$1" in
start)
echo "Starting Quark server"
start_quark
;;
stop)
echo "Stopping Quark server"
stop_quark
;;

restart)
echo "Restarting Quark server"
stop_quark
start_quark
;;

*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac

exit 0
Loading

0 comments on commit 05c1353

Please sign in to comment.