Make improvements to redbean

The following Lua APIs have been added:

  - IsDaemon() → bool
  - ProgramPidPath(str)

The following Lua hooks have been added:

  - OnClientConnection(ip:int,port:int,serverip:int,serverport:int) → bool
  - OnProcessCreate(pid:int,ip:int,port:int,serverip:int,serverport:int)
  - OnProcessDestroy(pid:int)
  - OnServerStart()
  - OnServerStop()
  - OnWorkerStart()
  - OnWorkerStop()

redbean now does a better job at applying gzip on the fly from the local
filesystem, using a streaming chunked api with constant memory, which is
useful for doing things like serving a 4gb text file off NFS, and having
it start transmitting in milliseconds. redbean will also compute entropy
on the beginnings of files to determine if compression is profitable.

This change pays off technical debts relating to memory, such as relying
on exit() to free() allocations. That's now mostly fixed so it should be
easier now to spot memory leaks in malloc traces.

This change also fixes bugs and makes improvements to our SSL support.
Uniprocess mode failed handshakes are no longer an issue. Token Alpn is
offered so curl -v looks less weird. Hybrid SSL certificate loading is
now smarter about naming conflicts. Self-signed CA root anchors will no
longer be delivered to the client during the handshake.
This commit is contained in:
Justine Tunney 2021-07-10 15:02:03 -07:00
parent 98c674d915
commit 8c4cce043c
25 changed files with 22326 additions and 359 deletions

View file

@ -30,6 +30,7 @@
#include "libc/sysv/consts/exit.h" #include "libc/sysv/consts/exit.h"
#include "libc/sysv/consts/ipproto.h" #include "libc/sysv/consts/ipproto.h"
#include "libc/sysv/consts/shut.h" #include "libc/sysv/consts/shut.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/consts/so.h" #include "libc/sysv/consts/so.h"
#include "libc/sysv/consts/sock.h" #include "libc/sysv/consts/sock.h"
#include "libc/sysv/consts/sol.h" #include "libc/sysv/consts/sol.h"
@ -175,6 +176,7 @@ static int AppendFmt(struct Buffer *b, const char *fmt, ...) {
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if (!NoDebug()) showcrashreports(); if (!NoDebug()) showcrashreports();
xsigaction(SIGPIPE, SIG_IGN, 0, 0, 0);
/* /*
* Read flags. * Read flags.
@ -282,7 +284,6 @@ int main(int argc, char *argv[]) {
"Connection: close\r\n" "Connection: close\r\n"
"User-Agent: %s\r\n", "User-Agent: %s\r\n",
kHttpMethod[method], _gc(EncodeUrl(&url, 0)), host, port, agent); kHttpMethod[method], _gc(EncodeUrl(&url, 0)), host, port, agent);
fprintf(stderr, "%`'.*s\n", request.i, request.p);
for (int i = 0; i < headers.n; ++i) { for (int i = 0; i < headers.n; ++i) {
AppendFmt(&request, "%s\r\n", headers.p[i]); AppendFmt(&request, "%s\r\n", headers.p[i]);
} }
@ -459,6 +460,7 @@ Finished:
mbedtls_ssl_free(&ssl); mbedtls_ssl_free(&ssl);
mbedtls_ctr_drbg_free(&drbg); mbedtls_ctr_drbg_free(&drbg);
mbedtls_ssl_config_free(&conf); mbedtls_ssl_config_free(&conf);
mbedtls_ctr_drbg_free(&drbg);
} }
return 0; return 0;

View file

@ -112,7 +112,7 @@ struct AsanGlobal {
struct AsanMorgue { struct AsanMorgue {
unsigned i; unsigned i;
void *p[16]; void *p[32];
}; };
static struct AsanMorgue __asan_morgue; static struct AsanMorgue __asan_morgue;

View file

@ -78,7 +78,6 @@ int PrintBacktraceUsingSymbols(int fd, const struct StackFrame *bp,
} else { } else {
p = stpcpy(p, "UNKNOWN"); p = stpcpy(p, "UNKNOWN");
} }
*p++ = '\r';
*p++ = '\n'; *p++ = '\n';
if (write(fd, buf, p - buf) == -1) { if (write(fd, buf, p - buf) == -1) {
return -1; return -1;

View file

@ -58,7 +58,7 @@ static const char kGregNames[17][4] forcealign(1) = {
static const char kCpuFlags[12] forcealign(1) = "CVPRAKZSTIDO"; static const char kCpuFlags[12] forcealign(1) = "CVPRAKZSTIDO";
static const char kFpuExceptions[6] forcealign(1) = "IDZOUP"; static const char kFpuExceptions[6] forcealign(1) = "IDZOUP";
static const char kCrashSigNames[8][5] forcealign(1) = { static const char kCrashSigNames[8][5] forcealign(1) = {
"QUIT", "FPE", "ILL", "SEGV", "TRAP", "ABRT", "BUS"}; "QUIT", "FPE", "ILL", "SEGV", "TRAP", "ABRT", "BUS", "PIPE"};
hidden int kCrashSigs[8]; hidden int kCrashSigs[8];
hidden struct sigaction g_oldcrashacts[8]; hidden struct sigaction g_oldcrashacts[8];

View file

@ -27,6 +27,12 @@
static bool once; static bool once;
static void PutEnvDestroy(void) {
char **a;
for (a = environ; *a; ++a) free(*a);
free(environ);
}
static void PutEnvInit(void) { static void PutEnvInit(void) {
char **pin, **pout; char **pin, **pout;
pin = environ; pin = environ;
@ -34,6 +40,7 @@ static void PutEnvInit(void) {
environ = pout; environ = pout;
while (*pin) *pout++ = strdup(*pin++); while (*pin) *pout++ = strdup(*pin++);
*pout = NULL; *pout = NULL;
atexit(PutEnvDestroy);
} }
int PutEnvImpl(char *s, bool overwrite) { int PutEnvImpl(char *s, bool overwrite) {

View file

@ -1,7 +1,7 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the any purpose with or without fee is hereby granted, provided that the
@ -16,39 +16,37 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/fmt/itoa.h" #include "libc/math.h"
#include "libc/runtime/runtime.h" #include "libc/rand/rand.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "third_party/dlmalloc/dlmalloc.internal.h"
static uintptr_t lastfree_; /**
* Returns number between 0 and 8.
void *AddressBirthAction(void *addr) { *
char buf[64], *p; * This gives you an idea of the density of information. Cryptographic
p = buf; * random should be in the ballpark of 7.9 whereas plaintext will be
p = stpcpy(p, __FUNCTION__); * more like 4.5.
p = stpcpy(p, ": 0x"); *
p += uint64toarray_radix16((uintptr_t)addr, p); * @param p is treated as binary octets
*p++ = '\n'; * @param n should be at least 1000
__print(buf, p - buf); */
if (lastfree_ == (uintptr_t)addr) { double MeasureEntropy(const char *p, size_t n) {
lastfree_ = 0; size_t i;
double e, x;
long h[256];
e = 0;
if (n) {
memset(h, 0, sizeof(h));
for (i = 0; i < n; ++i) {
++h[p[i] & 255];
}
for (i = 0; i < 256; i++) {
if (h[i]) {
x = h[i];
x /= n;
e += x * log2(1 / x);
}
}
} }
return addr; return e;
}
void *AddressDeathAction(void *addr) {
char buf[64], *p;
p = buf;
p = stpcpy(p, __FUNCTION__);
p = stpcpy(p, ": 0x");
p += uint64toarray_radix16((uintptr_t)addr, p);
if (lastfree_ != (uintptr_t)addr) {
lastfree_ = (uintptr_t)addr;
} else {
p = stpcpy(p, " [OBVIOUS DOUBLE FREE]");
}
*p++ = '\n';
__print(buf, p - buf);
return addr;
} }

View file

@ -26,6 +26,7 @@ char *initstate(unsigned, char *, size_t);
char *setstate(char *); char *setstate(char *);
long random(void); long random(void);
void srandom(unsigned); void srandom(unsigned);
double MeasureEntropy(const char *, size_t);
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -55,8 +55,7 @@ static inline noasan uint64_t UncheckedAlignedRead64(unsigned char *p) {
void *memccpy(void *dst, const void *src, int c, size_t n) { void *memccpy(void *dst, const void *src, int c, size_t n) {
size_t i; size_t i;
uint64_t v, w; uint64_t v, w;
unsigned char *d; unsigned char *d, *q;
unsigned char *pd;
const unsigned char *s; const unsigned char *s;
i = 0; i = 0;
d = dst; d = dst;
@ -72,15 +71,15 @@ void *memccpy(void *dst, const void *src, int c, size_t n) {
if (~(w ^ v) & ((w ^ v) - 0x0101010101010101) & 0x8080808080808080) { if (~(w ^ v) & ((w ^ v) - 0x0101010101010101) & 0x8080808080808080) {
break; break;
} else { } else {
pd = d + i; q = d + i;
pd[0] = (w >> 000) & 255; q[0] = (w & 0x00000000000000ff) >> 000;
pd[1] = (w >> 010) & 255; q[1] = (w & 0x000000000000ff00) >> 010;
pd[2] = (w >> 020) & 255; q[2] = (w & 0x0000000000ff0000) >> 020;
pd[3] = (w >> 030) & 255; q[3] = (w & 0x00000000ff000000) >> 030;
pd[4] = (w >> 040) & 255; q[4] = (w & 0x000000ff00000000) >> 040;
pd[5] = (w >> 050) & 255; q[5] = (w & 0x0000ff0000000000) >> 050;
pd[6] = (w >> 060) & 255; q[6] = (w & 0x00ff000000000000) >> 060;
pd[7] = (w >> 070) & 255; q[7] = (w & 0xff00000000000000) >> 070;
} }
} }
for (; i < n; ++i) { for (; i < n; ++i) {

View file

@ -28,6 +28,35 @@
* data from modifying memory without authorization; the memccpy() * data from modifying memory without authorization; the memccpy()
* function can be used for that purpose. * function can be used for that purpose.
* *
* Here's an example of the only use case we know of for strncpy:
*
* static const struct People {
* char name[8];
* int age;
* } kPeople[] = {
* {"alice", 29}, //
* {"bob", 42}, //
* };
*
* int GetAge(const char *name) {
* char k[8];
* int m, l, r;
* l = 0;
* r = ARRAYLEN(kPeople) - 1;
* strncpy(k, name, 8);
* while (l <= r) {
* m = (l + r) >> 1;
* if (READ64BE(kPeople[m].name) < READ64BE(k)) {
* l = m + 1;
* } else if (READ64BE(kPeople[m].name) > READ64BE(k)) {
* r = m - 1;
* } else {
* return kPeople[m].age;
* }
* }
* return -1;
* }
*
* @return dest * @return dest
* @see stpncpy(), memccpy() * @see stpncpy(), memccpy()
* @asyncsignalsafe * @asyncsignalsafe

View file

@ -7,6 +7,10 @@ extern size_t kHyperionSize;
extern char kHyperion[]; extern char kHyperion[];
extern uint8_t kHyperionZip[]; extern uint8_t kHyperionZip[];
extern size_t kMobySize;
extern char kMoby[];
extern uint8_t kMobyZip[];
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_TESTLIB_HYPERION_H_ */ #endif /* COSMOPOLITAN_LIBC_TESTLIB_HYPERION_H_ */

32
libc/testlib/moby.S Normal file
View file

@ -0,0 +1,32 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or 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 "libc/macros.internal.h"
.rodata
// Nontrivial NUL-terminated string test vector.
.align 1
kMoby:
0: .incbin "libc/testlib/moby.txt"
1: .byte 0
.endobj kMoby,globl
.align 8
kMobySize:
.quad 1b-0b
.endobj kMobySize,globl

12
libc/testlib/moby.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef COSMOPOLITAN_LIBC_TESTLIB_MOBY_H_
#define COSMOPOLITAN_LIBC_TESTLIB_MOBY_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern size_t kMobySize;
extern char kMoby[];
extern uint8_t kMobyZip[];
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_TESTLIB_MOBY_H_ */

21257
libc/testlib/moby.txt Normal file

File diff suppressed because it is too large Load diff

View file

@ -13,22 +13,25 @@ LIBC_TESTLIB_A = o/$(MODE)/libc/testlib/testlib.a
LIBC_TESTLIB_A_CHECKS = $(LIBC_TESTLIB_A).pkg LIBC_TESTLIB_A_CHECKS = $(LIBC_TESTLIB_A).pkg
LIBC_TESTLIB_A_ASSETS = \ LIBC_TESTLIB_A_ASSETS = \
libc/testlib/blocktronics.txt \
libc/testlib/hyperion.txt \ libc/testlib/hyperion.txt \
libc/testlib/blocktronics.txt libc/testlib/moby.txt
LIBC_TESTLIB_A_HDRS = \ LIBC_TESTLIB_A_HDRS = \
libc/testlib/bench.h \ libc/testlib/bench.h \
libc/testlib/ezbench.h \
libc/testlib/blocktronics.h \ libc/testlib/blocktronics.h \
libc/testlib/ezbench.h \
libc/testlib/hyperion.h \ libc/testlib/hyperion.h \
libc/testlib/moby.h \
libc/testlib/testlib.h libc/testlib/testlib.h
LIBC_TESTLIB_A_SRCS_S = \ LIBC_TESTLIB_A_SRCS_S = \
libc/testlib/bench.S \ libc/testlib/bench.S \
libc/testlib/blocktronics.S \
libc/testlib/combo.S \ libc/testlib/combo.S \
libc/testlib/fixture.S \ libc/testlib/fixture.S \
libc/testlib/blocktronics.S \
libc/testlib/hyperion.S \ libc/testlib/hyperion.S \
libc/testlib/moby.S \
libc/testlib/testcase.S \ libc/testlib/testcase.S \
libc/testlib/thrashcodecache.S \ libc/testlib/thrashcodecache.S \
libc/testlib/thunks/assert_eq.S \ libc/testlib/thunks/assert_eq.S \
@ -44,32 +47,32 @@ LIBC_TESTLIB_A_SRCS_S = \
LIBC_TESTLIB_A_SRCS_C = \ LIBC_TESTLIB_A_SRCS_C = \
libc/testlib/almostequallongdouble.c \ libc/testlib/almostequallongdouble.c \
libc/testlib/hexequals.c \ libc/testlib/benchrunner.c \
libc/testlib/binequals.c \ libc/testlib/binequals.c \
libc/testlib/clearxmmregisters.c \ libc/testlib/clearxmmregisters.c \
libc/testlib/formatbool.c \ libc/testlib/comborunner.c \
libc/testlib/formatrange.c \ libc/testlib/contains.c \
libc/testlib/globals.c \ libc/testlib/endswith.c \
libc/testlib/incrementfailed.c \ libc/testlib/ezbenchcontrol.c \
libc/testlib/formatfloat.c \ libc/testlib/ezbenchreport.c \
libc/testlib/fixturerunner.c \
libc/testlib/formatbinaryasglyphs.c \ libc/testlib/formatbinaryasglyphs.c \
libc/testlib/formatbinaryashex.c \ libc/testlib/formatbinaryashex.c \
libc/testlib/formatbool.c \
libc/testlib/formatfloat.c \
libc/testlib/formatint.c \ libc/testlib/formatint.c \
libc/testlib/formatrange.c \
libc/testlib/formatstr.c \ libc/testlib/formatstr.c \
libc/testlib/globals.c \
libc/testlib/hexequals.c \
libc/testlib/incrementfailed.c \
libc/testlib/shoulddebugbreak.c \ libc/testlib/shoulddebugbreak.c \
libc/testlib/showerror.c \ libc/testlib/showerror.c \
libc/testlib/showerror_.c \ libc/testlib/showerror_.c \
libc/testlib/strequals.c \
libc/testlib/startswith.c \ libc/testlib/startswith.c \
libc/testlib/endswith.c \
libc/testlib/contains.c \
libc/testlib/strcaseequals.c \ libc/testlib/strcaseequals.c \
libc/testlib/benchrunner.c \ libc/testlib/strequals.c \
libc/testlib/testrunner.c \ libc/testlib/testrunner.c
libc/testlib/comborunner.c \
libc/testlib/fixturerunner.c \
libc/testlib/ezbenchreport.c \
libc/testlib/ezbenchcontrol.c
LIBC_TESTLIB_A_SRCS = \ LIBC_TESTLIB_A_SRCS = \
$(LIBC_TESTLIB_A_SRCS_S) \ $(LIBC_TESTLIB_A_SRCS_S) \

View file

@ -16,13 +16,17 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/bits.h"
#include "libc/log/check.h" #include "libc/log/check.h"
#include "libc/math.h" #include "libc/math.h"
#include "libc/nexgen32e/x86feature.h" #include "libc/nexgen32e/x86feature.h"
#include "libc/rand/lcg.internal.h" #include "libc/rand/lcg.internal.h"
#include "libc/rand/rand.h" #include "libc/rand/rand.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h" #include "libc/stdio/stdio.h"
#include "libc/sysv/consts/grnd.h" #include "libc/sysv/consts/grnd.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/hyperion.h"
#include "libc/testlib/testlib.h" #include "libc/testlib/testlib.h"
/* JustReturnZero */ /* JustReturnZero */
@ -134,6 +138,18 @@ uint64_t SixthEditionLowByte(void) {
return x; return x;
} }
uint64_t MobyDick(void) {
static int i;
if ((i += 8) > kMobySize) i = 8;
return READ64LE(kMoby + i);
}
uint64_t ExecutableImage(void) {
static int i;
if ((i += 8) > _end - _base) i = 8;
return READ64LE(_base + i);
}
uint32_t SeventhEditionRand(void) { uint32_t SeventhEditionRand(void) {
return ((randx = randx * 1103515245 + 12345) >> 16) & 077777; return ((randx = randx * 1103515245 + 12345) >> 16) & 077777;
} }
@ -197,6 +213,8 @@ static const struct RandomFunction {
} kRandomFunctions[] = { } kRandomFunctions[] = {
{"JustReturnZero", JustReturnZero, false}, // {"JustReturnZero", JustReturnZero, false}, //
{"JustIncrement", JustIncrement, false}, // {"JustIncrement", JustIncrement, false}, //
{"MobyDick", MobyDick, false}, //
{"ExecutableImage", ExecutableImage, false}, //
{"SixthEditionLowByte", SixthEditionLowByte, false}, // {"SixthEditionLowByte", SixthEditionLowByte, false}, //
{"SeventhEditionLowByte", SeventhEditionLowByte, false}, // {"SeventhEditionLowByte", SeventhEditionLowByte, false}, //
{"KnuthLcg", KnuthLcg, false}, // {"KnuthLcg", KnuthLcg, false}, //
@ -210,7 +228,7 @@ static const struct RandomFunction {
TEST(getrandom, sanityTest) { TEST(getrandom, sanityTest) {
uint64_t q; uint64_t q;
size_t i, j, k; size_t i, j, k;
double montepi, chip, scc, ent, mean, chisq; double montepi, chip, scc, mean, chisq, ent;
for (k = 0; k < 1; ++k) { for (k = 0; k < 1; ++k) {
for (j = 0; j < ARRAYLEN(kRandomFunctions); ++j) { for (j = 0; j < ARRAYLEN(kRandomFunctions); ++j) {
rt_init(0); rt_init(0);
@ -240,3 +258,126 @@ TEST(getrandom, sanityTest) {
} }
} }
} }
TEST(MeasureEntropy, test) {
MeasureEntropy(kMoby, 1000);
EXPECT_EQ(00, lroundl(10 * MeasureEntropy(" ", 12)));
EXPECT_EQ(16, lroundl(10 * MeasureEntropy("abcabcabcabc", 12)));
EXPECT_EQ(36, lroundl(10 * MeasureEntropy("abcdefghijkl", 12)));
EXPECT_EQ(49, lroundl(10 * MeasureEntropy(kMoby, 512)));
}
TEST(MeasureEntropy, testElfExecutable) {
EXPECT_EQ(19, lroundl(10 * MeasureEntropy("\
\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x03\x00\x3e\x00\x01\x00\x00\x00\x18\xd7\x00\x00\x00\x00\x00\x00\
\x40\x00\x00\x00\x00\x00\x00\x00\xc8\xd0\x0c\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x40\x00\x38\x00\x09\x00\x40\x00\x16\x00\x15\x00\
\x06\x00\x00\x00\x04\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\
\x40\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\
\xf8\x01\x00\x00\x00\x00\x00\x00\xf8\x01\x00\x00\x00\x00\x00\x00\
\x08\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\
\x38\x02\x00\x00\x00\x00\x00\x00\x38\x02\x00\x00\x00\x00\x00\x00\
\x38\x02\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\
\x19\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\
\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x90\xbc\x00\x00\x00\x00\x00\x00\x90\xbc\x00\x00\x00\x00\x00\x00\
\x00\x10\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\
\x00\xc0\x00\x00\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\
\x00\xc0\x00\x00\x00\x00\x00\x00\x62\xb2\x09\x00\x00\x00\x00\x00\
\x62\xb2\x09\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\
\x01\x00\x00\x00\x04\x00\x00\x00\x00\x80\x0a\x00\x00\x00\x00\x00\
\x00\x80\x0a\x00\x00\x00\x00\x00\x00\x80\x0a\x00\x00\x00\x00\x00\
\xe4\x09\x02\x00\x00\x00\x00\x00\xe4\x09\x02\x00\x00\x00\x00\x00\
\x00\x10\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\
\xc0\x95\x0c\x00\x00\x00\x00\x00\xc0\xa5\x0c\x00\x00\x00\x00\x00\
\xc0\xa5\x0c\x00\x00\x00\x00\x00\x64\x3a\x00\x00\x00\x00\x00\x00\
\xa8\x42\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\
\x02\x00\x00\x00\x06\x00\x00\x00\xa0\xc2\x0c\x00\x00\x00\x00\x00\
\xa0\xd2\x0c\x00\x00\x00\x00\x00\xa0\xd2\x0c\x00\x00\x00\x00\x00\
\x80\x01\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00\x00\x00\x00\
\x08\x00\x00\x00\x00\x00\x00\x00\x51\xe5\x74\x64\x06\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00",
512)));
}
TEST(MeasureEntropy, testApeExecutable) {
EXPECT_EQ(53, lroundl(10 * MeasureEntropy("\
\x7f\x45\x4c\x46\x02\x01\x01\x09\x00\x00\x00\x00\x00\x00\x00\x00\
\x02\x00\x3e\x00\x01\x00\x00\x00\x0a\x11\x40\x00\x00\x00\x00\x00\
\xe0\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x40\x00\x38\x00\x04\x00\x00\x00\x00\x00\x00\x00\
\xb2\x40\xeb\x00\xeb\x14\x90\x90\xeb\x06\x48\x83\xec\x08\x31\xd2\
\xbd\x00\x00\xeb\x05\xe9\xb0\x10\x00\x00\xfc\x0f\x1f\x87\x3e\xe0\
\xbf\x00\x70\x31\xc9\x8e\xc1\xfa\x8e\xd7\x89\xcc\xfb\x0e\x1f\xe8\
\x00\x00\x5e\x81\xee\x72\x00\xb8\x00\x02\x50\x50\x07\x31\xff\xb9\
\x00\x02\xf3\xa4\x0f\x1f\x87\xd2\xff\xea\x8e\x20\x00\x00\x8e\xd9\
\xb9\x00\x1b\xb8\x50\x00\x8e\xc0\x31\xc0\x31\xff\xf3\xaa\x80\xfa\
\x40\x74\x13\xe8\x15\x00\x07\xb0\x01\x31\xc9\x30\xf6\xbf\x40\x03\
\xe8\x48\x00\x4f\x75\xfa\xea\x20\x25\x00\x00\x53\x52\xb4\x08\xcd\
\x13\x72\x2c\x88\xcf\x80\xe7\x3f\x80\xe1\xc0\xd0\xc1\xd0\xc1\x86\
\xcd\x1e\x06\x1f\x31\xf6\x8e\xc6\xbe\x10\x15\x87\xf7\xa5\xa5\xa5\
\xa5\xa5\xa4\x1f\x93\xab\x91\xab\x92\xab\x58\xaa\x92\x5b\xc3\x5a\
\x80\xf2\x80\x31\xc0\xcd\x13\x72\xf7\xeb\xc1\x50\x51\x86\xcd\xd0\
\xc9\xd0\xc9\x08\xc1\x31\xdb\xb0\x01\xb4\x02\xcd\x13\x59\x58\x72\
\x1d\x8c\xc6\x83\xc6\x20\x8e\xc6\xfe\xc0\x3a\x06\x1c\x15\x76\x0d\
\xb0\x01\xfe\xc6\x3a\x36\x20\x15\x76\x03\x30\xf6\x41\xc3\x50\x31\
\xc0\xcd\x13\x58\xeb\xc5\x89\xfe\xac\x84\xc0\x74\x09\xbb\x07\x00\
\xb4\x0e\xcd\x10\xeb\xf2\xc3\x57\xbf\x78\x24\xe8\xe8\xff\x5f\xe8\
\xe4\xff\xbf\x80\x24\xe8\xde\xff\xf3\x90\xeb\xfc\xb9\x04\x00\xbe\
\x00\x04\xad\x85\xc0\x74\x0b\x51\x56\x97\xbe\x9e\x24\xe8\x05\x00\
\x5e\x59\xe2\xee\xc3\x89\xfa\x85\xd2\x74\x14\x52\x56\x31\xc9\xb1\
\x03\x01\xca\xac\x5e\x0c\x80\xee\x5a\xac\xee\x42\x49\x79\xfa\xc3\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x55\xaa",
512)));
}
TEST(MeasureEntropy, testDevUrandom) {
EXPECT_EQ(76, lroundl(10 * MeasureEntropy("\
\x67\xa6\x8f\x6f\x6f\x01\xa4\x60\xa5\x5a\x6a\xfa\x06\xfd\xbb\xbe\
\xe4\x73\x2f\xc4\x20\x25\xd9\xb2\x78\x7d\x9f\xaf\x5d\x03\x49\x01\
\x90\x94\x8a\xc0\x33\x78\xe0\x65\xd8\x9c\x19\x96\x25\x90\xc8\x6e\
\xf2\x65\xac\x72\xd9\x8e\x58\x05\x26\x22\xa3\x58\x41\x40\xee\x3c\
\x3a\xb0\x08\x7c\x70\x0e\x23\xdc\x52\x10\x21\x5c\xb7\x3d\x3a\xce\
\x7c\xd7\x2a\x8c\x35\x0c\x21\x2b\x03\x75\xbe\x0c\x49\x5b\xdb\x7a\
\x7e\xeb\x27\x03\x56\xca\x9f\xf8\x00\xb4\x4d\x5b\xd6\xde\x41\xd6\
\x86\x7b\x3c\x13\xd4\x2d\xd4\xe9\x79\x05\x48\xcc\xa5\x17\xf8\xb6\
\x74\xdf\x39\x70\x32\x64\x70\x10\xfb\x53\x06\x87\xef\xff\x9f\x4c\
\x07\xee\x09\x54\xb8\xda\x1a\x49\x9b\x12\x3a\xf9\xc3\x55\xbc\xa5\
\xad\x6c\x3d\x1f\x39\x84\xc6\xac\x45\x14\x4f\xa9\xfc\xd6\xfb\xce\
\x41\xf8\x78\x85\xe5\x72\x9c\x0c\xd3\x81\x9b\xa4\x72\xc9\xd5\xc8\
\xc2\x3c\xcc\x36\x58\xf6\x23\x2a\x2e\x9c\x38\xea\x73\x17\xf0\x72\
\x2d\x57\xf8\xc5\x62\x84\xb7\xce\x24\x7b\x46\x65\xc7\xf3\x78\x88\
\x77\x36\x93\x25\x5d\x78\xc9\xfb\x24\xbb\xec\x2f\x77\x4f\x82\xd8\
\x63\x23\xd1\x39\x54\x78\x14\x7d\x24\xc8\x1a\xed\x32\x2d\x7b\xdc\
\xf4\x92\xb1\xaf\x0d\x9b\xba\xb6\x72\xfb\xb2\x7f\x8f\xd5\x4c\x5e\
\x05\xa7\x05\x15\xc5\x51\xd0\x86\x0a\xce\x04\x84\x1e\xba\x44\xf3\
\xbc\x09\xa9\x4e\xc1\xc7\xbd\x7e\x45\x38\x04\xa3\x6c\xfa\x46\x57\
\x40\x93\xbf\xdd\x12\x05\x6c\xb0\xee\x08\x40\x74\xc9\xda\xe7\x30\
\xfa\x1f\x12\xc8\x31\x33\x53\xe4\x65\x2a\xe8\xbf\x2b\x3c\xd6\xcc\
\xec\x8f\x9a\x6f\xe1\xe0\xe6\x81\x0a\xf5\x46\x07\xeb\xcd\xba\xcb\
\xa1\xe5\x4a\x42\xd6\x20\xce\xb6\x16\xcf\x73\x30\x25\x17\xe3\x00\
\x2b\x58\x93\x86\x74\x57\x48\x8b\x2a\x35\x88\xc7\x84\x18\x53\x23\
\xba\xc3\x06\x0a\xd7\x09\xf2\xcb\xe1\xb1\x39\x07\xaf\x2d\xb2\xbc\
\x7d\x71\x91\x6f\x71\x53\x82\xed\x51\x96\xbf\x90\xb4\x4a\x9a\x20\
\x21\x8a\x72\xa3\xbc\xfc\xb9\xcd\x47\x5e\x38\x9c\xd2\xf9\xae\x7f\
\xb2\x1a\x2a\x81\x68\x31\x53\xb2\x11\xfa\x80\x71\x31\xdd\xde\x56\
\x9c\x5f\x3f\x50\xb5\x5f\x99\x5d\x36\x34\x23\x13\xa9\xf0\x04\x3d\
\xa0\xee\x1c\xe5\xe3\x8d\x60\x76\x62\x5a\xd2\xa3\xa2\x51\xea\x75\
\xab\x1f\x2f\xc4\x08\x35\x5d\xf3\x28\x5d\x59\x67\x88\xf0\x61\x6c\
\x8b\x5f\xaf\x90\xa9\x90\xfe\x36\x29\xcc\x02\xf7\x2f\xa7\x19\x0e",
512)));
}
BENCH(getrandom, bench) {
EZBENCH2("MeasureEntropy", donothing, MeasureEntropy(kMoby, 512));
}

View file

@ -37,9 +37,11 @@ TEST_LIBC_STDIO_DIRECTDEPS = \
LIBC_SYSV \ LIBC_SYSV \
LIBC_TESTLIB \ LIBC_TESTLIB \
LIBC_TIME \ LIBC_TIME \
LIBC_LOG \
LIBC_UNICODE \ LIBC_UNICODE \
LIBC_X \ LIBC_X \
LIBC_ZIPOS LIBC_ZIPOS \
THIRD_PARTY_ZLIB
TEST_LIBC_STDIO_DEPS := \ TEST_LIBC_STDIO_DEPS := \
$(call uniq,$(foreach x,$(TEST_LIBC_STDIO_DIRECTDEPS),$($(x)))) $(call uniq,$(foreach x,$(TEST_LIBC_STDIO_DIRECTDEPS),$($(x))))

View file

@ -24,7 +24,7 @@ size_t bulk_free(void *array[], size_t nelem) {
for (a = array; a != fence; ++a) { for (a = array; a != fence; ++a) {
void *mem = *a; void *mem = *a;
if (mem != 0) { if (mem != 0) {
mchunkptr p = mem2chunk(ADDRESS_DEATH_ACTION(mem)); mchunkptr p = mem2chunk(AddressDeathAction(mem));
size_t psize = chunksize(p); size_t psize = chunksize(p);
#if FOOTERS #if FOOTERS
if (get_mstate_for(p) != g_dlmalloc) { if (get_mstate_for(p) != g_dlmalloc) {

View file

@ -74,14 +74,14 @@ static void **ialloc(mstate m, size_t n_elements, size_t *sizes, int opts,
size_t array_chunk_size; size_t array_chunk_size;
array_chunk = chunk_plus_offset(p, contents_size); array_chunk = chunk_plus_offset(p, contents_size);
array_chunk_size = remainder_size - contents_size; array_chunk_size = remainder_size - contents_size;
marray = ADDRESS_BIRTH_ACTION((void **)(chunk2mem(array_chunk))); marray = AddressBirthAction((void **)(chunk2mem(array_chunk)));
set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size); set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
remainder_size = contents_size; remainder_size = contents_size;
} }
/* split out elements */ /* split out elements */
for (i = 0;; ++i) { for (i = 0;; ++i) {
marray[i] = ADDRESS_BIRTH_ACTION(chunk2mem(p)); marray[i] = AddressBirthAction(chunk2mem(p));
if (i != n_elements - 1) { if (i != n_elements - 1) {
if (element_size != 0) if (element_size != 0)
size = element_size; size = element_size;

View file

@ -578,7 +578,7 @@ static void *tmalloc_large(mstate m, size_t nb) {
return 0; return 0;
} }
void *dlmalloc(size_t bytes) { void *dlmalloc_impl(size_t bytes, bool takeaction) {
/* /*
Basic algorithm: Basic algorithm:
If a small request (< 256 bytes minus per-chunk overhead): If a small request (< 256 bytes minus per-chunk overhead):
@ -708,12 +708,16 @@ void *dlmalloc(size_t bytes) {
postaction: postaction:
POSTACTION(g_dlmalloc); POSTACTION(g_dlmalloc);
return ADDRESS_BIRTH_ACTION(mem); return takeaction ? AddressBirthAction(mem) : mem;
} }
return 0; return 0;
} }
void *dlmalloc(size_t bytes) {
return dlmalloc_impl(bytes, true);
}
void dlfree(void *mem) { void dlfree(void *mem) {
/* /*
Consolidate freed chunks with preceeding or succeeding bordering Consolidate freed chunks with preceeding or succeeding bordering
@ -721,7 +725,7 @@ void dlfree(void *mem) {
with special cases for top, dv, mmapped chunks, and usage errors. with special cases for top, dv, mmapped chunks, and usage errors.
*/ */
if (mem != 0) { if (mem != 0) {
mem = ADDRESS_DEATH_ACTION(mem); mem = AddressDeathAction(mem);
mchunkptr p = mem2chunk(mem); mchunkptr p = mem2chunk(mem);
#if FOOTERS #if FOOTERS
@ -887,7 +891,7 @@ void *dlmemalign$impl(mstate m, size_t alignment, size_t bytes) {
} else { } else {
size_t nb = request2size(bytes); size_t nb = request2size(bytes);
size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
mem = dlmalloc(req); mem = dlmalloc_impl(req, false);
if (mem != 0) { if (mem != 0) {
mchunkptr p = mem2chunk(mem); mchunkptr p = mem2chunk(mem);
if (PREACTION(m)) return 0; if (PREACTION(m)) return 0;
@ -936,7 +940,7 @@ void *dlmemalign$impl(mstate m, size_t alignment, size_t bytes) {
POSTACTION(m); POSTACTION(m);
} }
} }
return ADDRESS_BIRTH_ACTION(mem); return AddressBirthAction(mem);
} }
void *dlmemalign(size_t alignment, size_t bytes) { void *dlmemalign(size_t alignment, size_t bytes) {

View file

@ -3,9 +3,12 @@
#ifndef __STRICT_ANSI__ #ifndef __STRICT_ANSI__
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/bits/bits.h" #include "libc/bits/bits.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/log/backtrace.internal.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
#if 0 #if 0
@ -674,15 +677,64 @@ extern struct MallocState g_dlmalloc[1];
/* ─────────────────────────────── Hooks ──────────────────────────────── */ /* ─────────────────────────────── Hooks ──────────────────────────────── */
#ifdef MTRACE /* TODO(jart): Add --mtrace flag for this */ /*
void *AddressBirthAction(void *); d = {}
void *AddressDeathAction(void *); lines = open("log").read().split('\n')
#define ADDRESS_BIRTH_ACTION(A) AddressBirthAction(A) def bad(i):
#define ADDRESS_DEATH_ACTION(A) AddressDeathAction(A) while i < len(lines):
#else if lines[i].startswith(('BIRTH', 'DEATH')):
#define ADDRESS_BIRTH_ACTION(A) (A) break
#define ADDRESS_DEATH_ACTION(A) (A) print lines[i]
i += 1
for i, line in enumerate(lines):
i += 1
x = line.split()
if len(x) != 2: continue
if x[0] == 'DEATH':
b = int(x[1], 16)
if b in d:
if d[b] < 0:
print "OH NO", i, d[b]
else:
d[b] = -d[b]
else:
print "wut", i
elif x[0] == 'BIRTH':
b = int(x[1], 16)
if b in d:
if d[b] > 0:
print "bad malloc", i, d[b]
d[b] = i
else:
d[b] = i
for k,v in d.items():
if v > 0:
print "unfreed", v
bad(v)
*/
#define MALLOC_TRACE 0
static inline void *AddressBirthAction(void *p) {
#if MALLOC_TRACE
(dprintf)(2, "BIRTH %p\n", p);
if (weaken(PrintBacktraceUsingSymbols) && weaken(GetSymbolTable)) {
weaken(PrintBacktraceUsingSymbols)(2, __builtin_frame_address(0),
weaken(GetSymbolTable)());
}
#endif #endif
return p;
}
static inline void *AddressDeathAction(void *p) {
#if MALLOC_TRACE
(dprintf)(2, "DEATH %p\n", p);
if (weaken(PrintBacktraceUsingSymbols) && weaken(GetSymbolTable)) {
weaken(PrintBacktraceUsingSymbols)(2, __builtin_frame_address(0),
weaken(GetSymbolTable)());
}
#endif
return p;
}
/* /*
PREACTION should be defined to return 0 on success, and nonzero on PREACTION should be defined to return 0 on success, and nonzero on
@ -907,7 +959,7 @@ extern struct MallocParams g_mparams;
#else /* GNUC */ #else /* GNUC */
#define RTCHECK(e) (e) #define RTCHECK(e) (e)
#endif /* GNUC */ #endif /* GNUC */
#else /* !IsTrustworthy() */ #else /* !IsTrustworthy() */
#define RTCHECK(e) (1) #define RTCHECK(e) (1)
#endif /* !IsTrustworthy() */ #endif /* !IsTrustworthy() */

View file

@ -643,7 +643,7 @@
* *
* Uncomment this macro to respect client's ciphersuite order * Uncomment this macro to respect client's ciphersuite order
*/ */
/*#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE*/ #define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
/** /**
* \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
@ -661,7 +661,7 @@
* *
* Comment this macro to disable support for ALPN. * Comment this macro to disable support for ALPN.
*/ */
/*#define MBEDTLS_SSL_ALPN*/ #define MBEDTLS_SSL_ALPN
#ifdef MBEDTLS_SSL_PROTO_DTLS #ifdef MBEDTLS_SSL_PROTO_DTLS
/** /**

View file

@ -722,25 +722,17 @@ static const struct DisArg {
{"Yvqp", DisYvqp}, // {"Yvqp", DisYvqp}, //
}; };
static int CompareString8(const char a[8], const char b[8]) {
uint64_t x, y;
x = READ64BE(a);
y = READ64BE(b);
return x > y ? 1 : x < y ? -1 : 0;
}
char *DisArg(struct Dis *d, char *p, const char *s) { char *DisArg(struct Dis *d, char *p, const char *s) {
char key[8]; char k[8];
int c, m, l, r; int m, l, r;
l = 0; l = 0;
r = ARRAYLEN(kDisArgs) - 1; r = ARRAYLEN(kDisArgs) - 1;
strncpy(key, s, 8); strncpy(k, s, 8);
while (l <= r) { while (l <= r) {
m = (l + r) >> 1; m = (l + r) >> 1;
c = CompareString8(kDisArgs[m].s, key); if (READ64BE(kDisArgs[m].s) < READ64BE(k)) {
if (c < 0) {
l = m + 1; l = m + 1;
} else if (c > 0) { } else if (READ64BE(kDisArgs[m].s) > READ64BE(k)) {
r = m - 1; r = m - 1;
} else { } else {
return kDisArgs[m].f(d, d->xedd->op.rde, p); return kDisArgs[m].f(d, d->xedd->op.rde, p);

View file

@ -192,6 +192,45 @@ SECURITY
-addext 'keyUsage = critical,cRLSign,keyCertSign' -addext 'keyUsage = critical,cRLSign,keyCertSign'
sudo ./redbean.com -C ca.crt -K .ca.key -p 80 -p 443 sudo ./redbean.com -C ca.crt -K .ca.key -p 80 -p 443
Let's say you're migrating away from NGINX and you use Let's Encrypt.
In that case you'll likely want something like the following:
certbot certonly --nginx --key-type ecdsa \
--cert-name redbean-ecdsa -d redbean.dev -d www.redbean.dev
certbot certonly --nginx --key-type rsa \
--cert-name redbean-rsa -d redbean.dev -d www.redbean.dev
You can then program /var/www/html/.init.lua as such:
ProgramPrivateKey(Slurp('/etc/letsencrypt/live/redbean-ecdsa/privkey.pem'))
ProgramCertificate(Slurp('/etc/letsencrypt/live/redbean-ecdsa/fullchain.pem'))
ProgramPrivateKey(Slurp('/etc/letsencrypt/live/redbean-rsa/privkey.pem'))
ProgramCertificate(Slurp('/etc/letsencrypt/live/redbean-rsa/fullchain.pem'))
if IsDaemon() then
ProgramUid(33) # see `vipw` to get appropriate number
ProgramGid(33) # see `vigr` to get appropriate number
ProgramPort(80)
ProgramPort(443)
ProgramLogPath('/var/log/redbean.log')
ProgramPidPath('/var/run/redbean.pid')
end
function OnHttpRequest()
path = GetPath()
if path == '/favicon.ico' or
path == '/site.webmanifest' or
path == '/favicon-16x16.png' or
path == '/favicon-32x32.png' or
path == '/apple-touch-icon' then
SetLogLevel(kLogWarn)
end
Route()
SetHeader('Content-Language', 'en-US')
end
You'd then run redbean as follows:
redbean.com -dD /var/www/html
SSL verbosity is controlled as follows for troubleshooting: SSL verbosity is controlled as follows for troubleshooting:
-V log ssl errors -V log ssl errors
@ -295,13 +334,51 @@ GLOBALS
HOOKS HOOKS
OnHttpRequest OnHttpRequest()
If this function is defined in the global scope by your /.init.lua If this function is defined in the global scope by your /.init.lua
then redbean will call it at the ealiest possible moment to then redbean will call it at the ealiest possible moment to
handover control for all messages (with the exception of OPTIONS handover control for all messages (with the exception of OPTIONS
*). See functions like Route which asks redbean to do its default *). See functions like Route which asks redbean to do its default
thing from the handler. thing from the handler.
OnClientConnection(ip:int,port:int,serverip:int,serverport:int) → bool
If this function is defined it'll be called from the main process
each time redbean accepts a new client connection. If it returns
true then redbean will close the connection without calling fork.
OnProcessCreate(pid:int,ip:int,port:int,serverip:int,serverport:int)
If this function is defined it'll be called from the main process
each time redbean forks a connection handler worker process. The
ip/port of the remote client is provided, along with the ip/port
of the listening interface that accepted the connection. This may
be used to create a server activity dashboard, in which case the
data provider handler should set SetHeader('Connection','Close').
This won't be called in unprocess mode.
OnProcessDestroy(pid:int)
If this function is defined it'll be called from the main process
each time redbean reaps a child connection process using wait4().
This won't be called in unprocess mode.
OnServerStart()
If this function is defined it'll be called from the main process
right before the main event loop starts.
OnServerStop()
If this function is defined it'll be called from the main process
after all the connection processes have been reaped and exit() is
ready to be called.
OnWorkerStart()
If this function is defined it'll be called from the child worker
process after it's been forked and before messages are handled.
This won't be called in unprocess mode.
OnWorkerStop()
If this function is defined it'll be called from the child worker
process once _exit() is ready to be called. This won't be called
in unprocess mode.
FUNCTIONS FUNCTIONS
Write(data:str) Write(data:str)
@ -708,6 +785,9 @@ FUNCTIONS
ProgramPrivateKey(Slurp("/etc/letsencrypt/fullchain.pem")) for ProgramPrivateKey(Slurp("/etc/letsencrypt/fullchain.pem")) for
local file system only. local file system only.
IsDaemon() → bool
Returns true if -d flag was passed to redbean.
ProgramUid(int) ProgramUid(int)
Same as the -U flag if called from .init.lua for setuid() Same as the -U flag if called from .init.lua for setuid()
@ -736,6 +816,16 @@ FUNCTIONS
space then redbean will truncate the log file if has access to space then redbean will truncate the log file if has access to
change the log file after daemonizing. change the log file after daemonizing.
ProgramPidPath(str)
Same as the -P flag if called from .init.lua for setting the pid
file path on the local file system. It's useful for reloading
daemonized redbean using `kill -HUP $(cat /var/run/redbean.pid)`
or terminating redbean with `kill $(cat /var/run/redbean.pid)`
which will gracefully terminate all clients. Sending the TERM
signal twice will cause a forceful shutdown, which might make
someone with a slow internet connection who's downloading big
files unhappy.
Slurp(filename:str) → str Slurp(filename:str) → str
Reads file data from local file system. Reads file data from local file system.
@ -792,21 +882,39 @@ FUNCTIONS
Underlong(str) → str Underlong(str) → str
Canonicalizes overlong encodings. Canonicalizes overlong encodings.
bsf(x:int) → int Crc32(initial:int,data:str) → int
Computes 32-bit CRC-32 used by zip/zlib/gzip/etc.
Crc32c(initial:int,data:str) → int
Computes 32-bit Castagnoli Cyclic Redundancy Check.
Md5(str) → str
Computes MD5 checksum, returning 16 bytes of binary.
Sha1(str) → str
Computes SHA1 checksum, returning 20 bytes of binary.
Sha224(str) → str
Computes SHA224 checksum, returning 28 bytes of binary.
Sha256(str) → str
Computes SHA256 checksum, returning 32 bytes of binary.
Sha384(str) → str
Computes SHA384 checksum, returning 48 bytes of binary.
Sha512(str) → str
Computes SHA512 checksum, returning 64 bytes of binary.
Bsf(x:int) → int
Returns position of first bit set. Passing 0 will raise an error. Returns position of first bit set. Passing 0 will raise an error.
Same as the Intel x86 instruction BSF. Same as the Intel x86 instruction BSF.
bsr(x:int) → int Bsr(x:int) → int
Returns binary logarithm of 𝑥. Passing 0 will raise an error. Same Returns binary logarithm of 𝑥. Passing 0 will raise an error. Same
as the Intel x86 instruction BSR. as the Intel x86 instruction BSR.
crc32(initial:int,data:str) → int Popcnt(x:int) → int
Computes Phil Katz CRC-32 used by zip/zlib/gzip/etc.
crc32c(initial:int,data:str) → int
Computes 32-bit Castagnoli Cyclic Redundancy Check.
popcnt(x:int) → int
Returns number of bits set in integer. Returns number of bits set in integer.
LSQLITE3 MODULE LSQLITE3 MODULE

File diff suppressed because it is too large Load diff

93
tool/viz/dumphexc.c Normal file
View file

@ -0,0 +1,93 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or 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 "libc/fmt/fmt.h"
#include "libc/macros.internal.h"
#include "libc/stdio/stdio.h"
struct Append {
size_t i, n;
char *p;
};
int AppendFmt(struct Append *b, const char *fmt, ...) {
int n;
char *p;
va_list va, vb;
va_start(va, fmt);
va_copy(vb, va);
n = vsnprintf(b->p + b->i, b->n - b->i, fmt, va);
if (n >= b->n - b->i) {
do {
if (b->n) {
b->n += b->n >> 1; /* this is the important line */
} else {
b->n = 16;
}
} while (b->i + n + 1 > b->n);
b->p = realloc(b->p, b->n);
vsnprintf(b->p + b->i, b->n - b->i, fmt, vb);
}
va_end(vb);
va_end(va);
b->i += n;
return n;
}
char *DumpHexc(const char *data, size_t size, size_t *z) {
long o;
int b, i, n;
char A[128], *p;
struct Append buf;
if (size == -1) size = data ? strlen(data) : 0;
buf.i = 0;
buf.n = 256;
buf.p = calloc(1, 256);
AppendFmt(&buf, "\"\\\n");
for (b = o = 0; (n = MIN(16, size)); data += n, size -= n) {
p = A;
for (i = 0; i < n; ++i) {
*p++ = '\\';
*p++ = 'x';
*p++ = "0123456789abcdef"[(data[i] & 0xF0) >> 4];
*p++ = "0123456789abcdef"[(data[i] & 0x0F) >> 0];
}
if (o) AppendFmt(&buf, "\\\n");
AppendFmt(&buf, "%.*s", p - A, A);
o += n;
}
AppendFmt(&buf, "\"");
if (z) *z = buf.i;
return buf.p;
}
int main(int argc, char *argv[]) {
char *p;
size_t n, g;
char buf[512];
struct Append b = {0};
while ((g = fread(buf, 1, sizeof(buf), stdin))) {
AppendFmt(&b, "%.*s", g, buf);
}
if (!ferror(stdin)) {
p = DumpHexc(b.p, b.i, &n);
fwrite(p, 1, n, stdout);
}
printf("\n");
return ferror(stdin) || ferror(stdout) ? 1 : 0;
}