mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-05 02:38:31 +00:00
Support pings, binary messages
This commit is contained in:
parent
a3c060b2ff
commit
988bbd2475
1 changed files with 44 additions and 10 deletions
|
@ -412,7 +412,7 @@ struct ClearedPerMessage {
|
||||||
bool hascontenttype;
|
bool hascontenttype;
|
||||||
bool gotcachecontrol;
|
bool gotcachecontrol;
|
||||||
bool gotxcontenttypeoptions;
|
bool gotxcontenttypeoptions;
|
||||||
bool iswebsocket;
|
char websockettype;
|
||||||
int frags;
|
int frags;
|
||||||
int statuscode;
|
int statuscode;
|
||||||
int isyielding;
|
int isyielding;
|
||||||
|
@ -5100,7 +5100,7 @@ static int LuaUpgradeWS(lua_State *L) {
|
||||||
p = AppendHeader(p, "Sec-WebSocket-Accept", accept);
|
p = AppendHeader(p, "Sec-WebSocket-Accept", accept);
|
||||||
|
|
||||||
cpm.luaheaderp = p;
|
cpm.luaheaderp = p;
|
||||||
cpm.iswebsocket = true;
|
cpm.websockettype = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5109,6 +5109,7 @@ static int LuaReadWS(lua_State *L) {
|
||||||
size_t i, got, amt;
|
size_t i, got, amt;
|
||||||
unsigned char wshdr[10], wshdrlen, *extlen, *mask;
|
unsigned char wshdr[10], wshdrlen, *extlen, *mask;
|
||||||
uint64_t len;
|
uint64_t len;
|
||||||
|
struct iovec iov[2];
|
||||||
OnlyCallDuringRequest(L, "ReadWS");
|
OnlyCallDuringRequest(L, "ReadWS");
|
||||||
|
|
||||||
got = 0;
|
got = 0;
|
||||||
|
@ -5117,9 +5118,13 @@ static int LuaReadWS(lua_State *L) {
|
||||||
luaL_error(L, "Could not read WS header");
|
luaL_error(L, "Could not read WS header");
|
||||||
} while ((got += rc) < 2);
|
} while ((got += rc) < 2);
|
||||||
|
|
||||||
if (!(wshdr[1] | (1 << 7))) luaL_error(L, "Unmasked WS frame");
|
if (wshdr[0] & 0x70) goto close; // reserved bit set
|
||||||
|
if (!(wshdr[1] | (1 << 7))) goto close; // unmasked
|
||||||
|
if ((wshdr[0] & 0x7) >= 0x3) goto close; // reserved opcode
|
||||||
|
|
||||||
len = wshdr[1] & ~(1 << 7);
|
len = wshdr[1] & ~(1 << 7);
|
||||||
|
if (wshdr[0] & 0x8 && len >= 126) goto close; // long control frame
|
||||||
|
|
||||||
wshdrlen = 6;
|
wshdrlen = 6;
|
||||||
if (len == 126) {
|
if (len == 126) {
|
||||||
wshdrlen = 8;
|
wshdrlen = 8;
|
||||||
|
@ -5150,13 +5155,38 @@ static int LuaReadWS(lua_State *L) {
|
||||||
luaL_error(L, "Could not read WS data");
|
luaL_error(L, "Could not read WS data");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((wshdr[0] & 0xF) == 0x8)
|
|
||||||
luaL_error(L, "WS connection closed");
|
|
||||||
|
|
||||||
for (i = 0, amt = amtread; i < got; ++i, ++amt) inbuf.p[amt] ^= mask[i & 0x3];
|
for (i = 0, amt = amtread; i < got; ++i, ++amt) inbuf.p[amt] ^= mask[i & 0x3];
|
||||||
|
|
||||||
|
if ((wshdr[0] & 0xF) == 0x9) {
|
||||||
|
wshdr[0] = (wshdr[0] & ~0xF) | 0xA;
|
||||||
|
wshdr[1] = wshdr[1] & ~0x80;
|
||||||
|
iov[0].iov_base = wshdr;
|
||||||
|
iov[0].iov_len = wshdrlen - 4;
|
||||||
|
iov[1].iov_base = inbuf.p + amtread;
|
||||||
|
iov[1].iov_len = got;
|
||||||
|
Send(iov, 2);
|
||||||
|
}
|
||||||
|
|
||||||
lua_pushlstring(L, inbuf.p + amtread, got);
|
lua_pushlstring(L, inbuf.p + amtread, got);
|
||||||
return 1;
|
lua_pushnumber(L, wshdr[0]);
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
close:
|
||||||
|
lua_pushnil(L);
|
||||||
|
lua_pushnumber(L, 0x08);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int LuaSetWSFlags(lua_State *L) {
|
||||||
|
OnlyCallDuringRequest(L, "SetWSFlags");
|
||||||
|
char flags = lround(lua_tonumber(L, 1));
|
||||||
|
if (flags & 0x01) {
|
||||||
|
cpm.websockettype = 1;
|
||||||
|
} else if (flags & 0x02) {
|
||||||
|
cpm.websockettype = 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <SORTED>
|
// <SORTED>
|
||||||
|
@ -5376,6 +5406,7 @@ static const luaL_Reg kLuaFuncs[] = {
|
||||||
{"SetHeader", LuaSetHeader}, //
|
{"SetHeader", LuaSetHeader}, //
|
||||||
{"SetLogLevel", LuaSetLogLevel}, //
|
{"SetLogLevel", LuaSetLogLevel}, //
|
||||||
{"SetStatus", LuaSetStatus}, //
|
{"SetStatus", LuaSetStatus}, //
|
||||||
|
{"SetWSFlags", LuaSetWSFlags}, // undocumented
|
||||||
{"Sha1", LuaSha1}, //
|
{"Sha1", LuaSha1}, //
|
||||||
{"Sha224", LuaSha224}, //
|
{"Sha224", LuaSha224}, //
|
||||||
{"Sha256", LuaSha256}, //
|
{"Sha256", LuaSha256}, //
|
||||||
|
@ -6460,14 +6491,16 @@ static bool StreamWS(char *p) {
|
||||||
bzero(iov, sizeof(iov));
|
bzero(iov, sizeof(iov));
|
||||||
iov[0].iov_base = wshdr;
|
iov[0].iov_base = wshdr;
|
||||||
|
|
||||||
wshdr[0] = 0x1 | (1 << 7);
|
|
||||||
extlen = &wshdr[2];
|
extlen = &wshdr[2];
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!YL || lua_status(YL) != LUA_YIELD) break; // done yielding
|
if (!YL || lua_status(YL) != LUA_YIELD) break; // done yielding
|
||||||
cpm.contentlength = 0;
|
cpm.contentlength = 0;
|
||||||
status = lua_resume(YL, NULL, 0, &nresults);
|
status = lua_resume(YL, NULL, 0, &nresults);
|
||||||
if (status != LUA_OK && status != LUA_YIELD) {
|
if (status == LUA_OK) {
|
||||||
|
lua_pop(YL, nresults);
|
||||||
|
break;
|
||||||
|
} else if (status != LUA_YIELD) {
|
||||||
LogLuaError("resume", lua_tostring(YL, -1));
|
LogLuaError("resume", lua_tostring(YL, -1));
|
||||||
lua_pop(YL, 1);
|
lua_pop(YL, 1);
|
||||||
break;
|
break;
|
||||||
|
@ -6492,6 +6525,7 @@ static bool StreamWS(char *p) {
|
||||||
*(uint64_t *)extlen = htobe64(rc);
|
*(uint64_t *)extlen = htobe64(rc);
|
||||||
iov[0].iov_len = 10;
|
iov[0].iov_len = 10;
|
||||||
}
|
}
|
||||||
|
wshdr[0] = cpm.websockettype | (1 << 7);
|
||||||
if (Send(iov, 2) == -1) break;
|
if (Send(iov, 2) == -1) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6562,7 +6596,7 @@ static bool HandleMessageActual(void) {
|
||||||
}
|
}
|
||||||
if (!cpm.generator) {
|
if (!cpm.generator) {
|
||||||
return TransmitResponse(p);
|
return TransmitResponse(p);
|
||||||
} else if (cpm.iswebsocket) {
|
} else if (cpm.websockettype) {
|
||||||
return StreamWS(p);
|
return StreamWS(p);
|
||||||
} else {
|
} else {
|
||||||
return StreamResponse(p);
|
return StreamResponse(p);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue