diff --git a/scripts/recook.sh b/scripts/recook.sh
new file mode 100755
index 0000000..e7f9827
--- /dev/null
+++ b/scripts/recook.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+set -e
+
+if [ -z "$1" ] ; then
+ echo "Usage $0 username"
+ exit 1
+fi
+
+if [ "`whoami`" != "root" ] ; then
+ echo "Run as root"
+ exit 1
+fi
+
+USERNAME="$1"
+# Robust way to get the user's home directory on both Linux and macOS
+export BD="$(sudo -H -u "$USERNAME" sh -c 'cd && pwd')"
+
+# change to $1 user
+sudo -u "$USERNAME" sh -c "
+set -e
+
+echo sanity=2 basedir=${BD}
+
+mkdir -p \"${BD}/libwebsockets/build\" && \
+cd \"${BD}/libwebsockets/build\" && \
+git fetch https://libwebsockets.org/repo/libwebsockets +_temp:m && \
+git reset --hard m && \
+make -j12
+"
+
+# return back to root
+cd "${BD}/libwebsockets/build"
+make -j12 install
+
+# change back to $1 user
+sudo -u "$USERNAME" sh -c "
+set -e
+
+cd \"${BD}/sai/build\" && \
+git fetch https://warmcat.com/repo/sai +_temp:m && \
+git reset --hard m && \
+make -j12
+"
+
+# return back to root
+cd "${BD}/sai/build"
+make -j12 install
+
+OS=$(uname -s)
+if [ "$OS" = "Linux" ]; then
+ systemctl restart sai-builder
+elif [ "$OS" = "Darwin" ]; then
+ launchctl unload /Library/LaunchDaemons/com.warmcat.sai-builder.plist
+ launchctl load /Library/LaunchDaemons/com.warmcat.sai-builder.plist
+else
+ echo "Unknown OS: $OS. Cannot restart sai-builder."
+fi
+
+exit 0
diff --git a/src/builder/b-power.c b/src/builder/b-power.c
index d77bc1c..086f87e 100644
--- a/src/builder/b-power.c
+++ b/src/builder/b-power.c
@@ -256,8 +256,19 @@ saib_power_stay_rx(void *userobj, const uint8_t *buf, size_t len, int flags)
return 0;
}
+static lws_ss_state_return_t
+saib_power_stay_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf,
+ size_t *len, int *flags)
+{
+ *len = 0;
+ *flags = LWSSS_FLAG_SOM | LWSSS_FLAG_EOM;
+
+ return LWSSSSRET_OK;
+}
+
LWS_SS_INFO("sai_power", saib_power_stay_t)
.rx = saib_power_stay_rx,
+ .tx = saib_power_stay_tx,
};
@@ -274,6 +285,9 @@ sul_stay_cb(lws_sorted_usec_list_t *sul)
if (r)
lwsl_ss_err(builder.ss_stay, "Unable to start stay connection (%d)", (int)r);
+ if (lws_ss_request_tx(builder.ss_stay))
+ lwsl_ss_warn(builder.ss_stay, "Unable to request tx");
+
lws_sul_schedule(builder.context, 0, &builder.sul_stay,
sul_stay_cb, SAI_STAY_POLL_US);
}
diff --git a/src/builder/b-refproxy.c b/src/builder/b-refproxy.c
index b4b6024..11bb82d 100644
--- a/src/builder/b-refproxy.c
+++ b/src/builder/b-refproxy.c
@@ -74,17 +74,17 @@ resproxy_find_by_cookie(struct sai_plat_server *spm, const char *c, size_t clen)
static int
saib_queue_yield_message(struct sai_plat_server *spm, const char *c, size_t len)
{
- char msg[256];
+ char msg[LWS_PRE + 256];
size_t jl;
/*
* We just send the cookie to relinquish the leased resources
*/
- jl = (size_t)lws_snprintf(msg, sizeof(msg),
+ jl = (size_t)lws_snprintf(msg + LWS_PRE, sizeof(msg) - LWS_PRE,
"{\"schema\":\"com-warmcat-sai-resource\","
"\"cookie\":\"%.*s\"}", (int)len, c);
- return saib_srv_queue_tx(spm->ss, msg, jl, LWSSS_FLAG_SOM | LWSSS_FLAG_EOM);
+ return saib_srv_queue_tx(spm->ss, msg + LWS_PRE, jl, LWSSS_FLAG_SOM | LWSSS_FLAG_EOM);
}
int
@@ -205,7 +205,16 @@ callback_resproxy(struct lws *wsi, enum lws_callback_reasons reason,
lws_strnncpy(pss->cookie, p, al, sizeof(pss->cookie));
lws_dll2_add_tail(&pss->list, &spm->resource_pss_list);
- return saib_srv_queue_tx(spm->ss, in, len, LWSSS_FLAG_SOM | LWSSS_FLAG_EOM);
+ {
+ int n;
+ char *buf = malloc(LWS_PRE + len);
+ if (!buf)
+ return -1;
+ memcpy(buf + LWS_PRE, in, len);
+ n = saib_srv_queue_tx(spm->ss, buf + LWS_PRE, len, LWSSS_FLAG_SOM | LWSSS_FLAG_EOM);
+ free(buf);
+ return n;
+ }
case LWS_CALLBACK_RAW_WRITEABLE:
if (pss->response) {
diff --git a/src/builder/b-ws-server.c b/src/builder/b-ws-server.c
index 0735e92..210ca28 100644
--- a/src/builder/b-ws-server.c
+++ b/src/builder/b-ws-server.c
@@ -121,7 +121,7 @@ saib_srv_queue_json_fragments_helper(struct lws_ss_handle *h,
return -1;
}
- if (saib_srv_queue_tx(h, buf + LWS_PRE, w, ssf))
+ if (saib_srv_queue_tx(h, buf + LWS_PRE, w, ssf) < 0)
return -1;
ssf &= ~((unsigned int)LWSSS_FLAG_SOM);
@@ -316,48 +316,50 @@ saib_m_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len,
int *flags)
{
struct sai_plat_server *spm = (struct sai_plat_server *)userobj;
- int *pi = (int *)lws_buflist_get_frag_start_or_NULL(&spm->bl_to_srv), depi;
+ unsigned int *pi = (unsigned int *)lws_buflist_get_frag_start_or_NULL(&spm->bl_to_srv);
char som, som1, eom, final = 1;
size_t fsl, used;
if (!spm->bl_to_srv)
return LWSSSSRET_TX_DONT_SEND;
- depi = *pi;
- *pi = (*pi) & (~(LWSSS_FLAG_SOM)); /* no SOM twice even on partial */
-
- /*
- * We can only issue *len at a time.
- *
- * Notice we are getting the stored flags from the START of the fragment each time.
- * that means we can still see the right flags stored with the fragment, even if we
- * have partially used the buflist frag and are partway through it.
- *
- * Ergo, only something to skip if we are at som=1. And also notice that although
- * *pi will be right, after the lws_buflist..._use() api, what it points to has been
- * destroyed. So we also dereference *pi into depi for use below.
- */
-
fsl = lws_buflist_next_segment_len(&spm->bl_to_srv, NULL);
lws_buflist_fragment_use(&spm->bl_to_srv, NULL, 0, &som, &eom);
if (som) {
+ spm->tx_flags = *pi;
fsl -= sizeof(int);
lws_buflist_fragment_use(&spm->bl_to_srv, buf, sizeof(int), &som1, &eom);
}
- if (!(depi & LWSSS_FLAG_SOM))
+ if (!(spm->tx_flags & LWSSS_FLAG_SOM))
som = 0;
- used = (size_t)lws_buflist_fragment_use(&spm->bl_to_srv, (uint8_t *)buf, *len, &som1, &eom);
- if (!used)
- return LWSSSSRET_TX_DONT_SEND;
+ if (fsl == 0)
+ used = 0;
+ else
+ used = (size_t)lws_buflist_fragment_use(&spm->bl_to_srv, (uint8_t *)buf, *len, &som1, &eom);
- if (used < fsl || !(depi & LWSSS_FLAG_EOM))
+ if (used < fsl || !(spm->tx_flags & LWSSS_FLAG_EOM))
final = 0;
+ if (!used && !som && !final && fsl > 0)
+ return LWSSSSRET_TX_DONT_SEND;
+
*len = used;
*flags = (som ? LWSSS_FLAG_SOM : 0) | (final ? LWSSS_FLAG_EOM : 0);
+ if (*flags & LWSSS_FLAG_SOM) {
+ if (spm->inside_msg) {
+ lwsl_err("%s: ILLEGAL SOM! Interrupted previous message starting with: %s\n",
+ __func__, spm->last_msg_start);
+ lwsl_hexdump_err(buf, *len);
+ }
+ lws_strnncpy(spm->last_msg_start, (const char *)buf, *len, sizeof(spm->last_msg_start));
+ spm->inside_msg = 1;
+ }
+ if (*flags & LWSSS_FLAG_EOM)
+ spm->inside_msg = 0;
+
// lwsl_ss_notice(spm->ss, "Sending %d builder->srv: ssflags %d", (int)*len, (int)*flags);
// lwsl_hexdump_notice(buf, *len);
diff --git a/src/common/include/private.h b/src/common/include/private.h
index 094d194..2bd1d07 100644
--- a/src/common/include/private.h
+++ b/src/common/include/private.h
@@ -493,6 +493,10 @@ typedef struct sai_plat_server {
int index; /* used to create unique build dir path */
uint16_t retries;
+ unsigned int tx_flags;
+
+ char last_msg_start[128];
+ uint8_t inside_msg;
} sai_plat_server_t;
struct sai_env {