diff --git a/.gitignore b/.gitignore index e6b87b0b9e..f2d1c81370 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ node_modules/ # ?? /inst cscope.* +build/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..53a902eeb1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,21 @@ +[submodule "subprojects/softfloat3"] + path = subprojects/softfloat3 + url = https://github.com/urbit/berkeley-softfloat-3.git +[submodule "subprojects/commonmark-legacy"] + path = subprojects/commonmark-legacy + url = https://github.com/urbit/commonmark-legacy.git +[submodule "subprojects/ed25519"] + path = subprojects/ed25519 + url = https://github.com/urbit/ed25519.git +[submodule "subprojects/libscrypt"] + path = subprojects/libscrypt + url = https://github.com/urbit/libscrypt.git +[submodule "subprojects/murmur3"] + path = subprojects/murmur3 + url = https://github.com/urbit/murmur3.git +[submodule "subprojects/libuv"] + path = subprojects/libuv + url = https://github.com/urbit/libuv.git +[submodule "subprojects/h2o"] + path = subprojects/libh2o + url = https://github.com/urbit/h2o.git diff --git a/.travis.yml b/.travis.yml index 8063ec07f9..3380299c7f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,30 +1,36 @@ language: c -script: make && make test # no ./configure +script: meson build && cd ./build && ninja # Uncomment me if this gets annoying # -# notifications: -# email: false +# notifications: +# email: false + +before_install: + - wget https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-linux.zip + - unzip ninja-linux.zip + - sudo mv ninja /usr/bin/ +install: + - pip3 install --user -I meson==0.44.1 addons: apt: packages: + - python3 + - python3-pip - libgmp3-dev - libsigsegv-dev - openssl - libssl-dev - libncurses5-dev - - make - - exuberant-ctags - automake - autoconf + - make - libtool - g++ - - ragel - - cmake - re2c - libcurl4-gnutls-dev - - python + - unzip # before_deploy: "make deb" # TODO deploy: skip_cleanup: true @@ -32,7 +38,7 @@ deploy: prerelease: true # turn this off for official releases api_key: secure: V4E7784ECSS3MO6ZIRtang9XwibDyvDYGb0MoSaP2CTlmzIAhdokr4KJFM0qM4KRaaajCdQuqi0lojgOjwdxs7e0GkAwScb33LFxQ7Chj/QkFOY7V1AnSRLR5OsXnazB0nur5aSwvcvnggQ2XW3OeF7zIvGfs9aR97SEz/xCrVE= - file: bin/urbit # TODO upload package from before_deploy + file: ./build/urbit # TODO upload package from before_deploy on: repo: urbit/urbit tags: true diff --git a/Makefile b/Makefile deleted file mode 100644 index 33b0853c9c..0000000000 --- a/Makefile +++ /dev/null @@ -1,552 +0,0 @@ -# A simple makefile. -# - -default: all --include .make.conf - -CORE=.MAKEFILE-VERSION - -# Pick one of: -# linux -# osx - -UNAME=$(shell uname) -ifeq ($(UNAME),Darwin) - OS=osx -else ifeq ($(UNAME),Linux) - OS=linux -else ifeq ($(UNAME),FreeBSD) - OS=bsd -else ifeq ($(UNAME),OpenBSD) - OS=bsd -else - $(error unknown unix) -endif - -# Pick one of: -# little -# big -# -ENDIAN=little - -# Binary directory - not in quotes. -# -BIN=bin - -# Only include/link with this if it exists. -# (Mac OS X El Capitan clean install does not have /opt) -ifneq (,$(wildcard /opt/local/.)) - OPTLOCALINC?=/opt/local/include - OPTLOCALLIB?=/opt/local/lib -endif - -# Only include/link with this if it exists. -# (`brew install openssl` on Mac OS X El Capitan puts openssl here) -ifneq (,$(wildcard /usr/local/opt/openssl/.)) - OPENSSLINC?=/usr/local/opt/openssl/include - OPENSSLLIB?=/usr/local/opt/openssl/lib -endif - -# can't have empty -I or -L options due to whitespace sensitivity -ifdef OPTLOCALINC - OPTLOCALIFLAGS=-I$(OPTLOCALINC) -endif -ifdef OPTLOCALLIB - OPTLOCALLFLAGS=-L$(OPTLOCALLIB) -endif -ifdef OPENSSLINC - OPENSSLIFLAGS=-I$(OPENSSLINC) -endif -ifdef OPENSSLLIB - OPENSSLLFLAGS=-L$(OPENSSLLIB) -endif - -CURLINC=$(shell curl-config --cflags) -CURLLIB=$(shell curl-config --libs) - -RM=rm -f -CC=cc -CXX=c++ -CXXFLAGS=$(CFLAGS) -CLD=c++ $(CFLAGS) -L/usr/local/lib $(OPTLOCALLFLAGS) $(OPENSSLLFLAGS) - -ifeq ($(OS),osx) - CLDOSFLAGS=-bind_at_load - OSLIBS=-framework CoreServices -framework CoreFoundation -endif -ifeq ($(OS),linux) - OSLIBS=-lpthread -lrt -lcurses - DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -endif -ifeq ($(OS),bsd) - OSLIBS=-lpthread -lncurses -lkvm -endif - -ifeq ($(STATIC),yes) -LIBS=-lssl -lcrypto -lncurses /usr/local/lib/libsigsegv.a /usr/local/lib/libgmp.a $(CURLLIB) $(OSLIBS) -else -LIBS=-lssl -lcrypto -lgmp -lncurses -lsigsegv $(CURLLIB) $(OSLIBS) -endif - -INCLUDE=include -MDEFINES=-DU3_OS_$(OS) -DU3_OS_ENDIAN_$(ENDIAN) - -DEBUG=no - -ifeq ($(DEBUG),yes) -CFLAGS=-g -else -CFLAGS?=-O3 -endif - -LIBUV_VER=libuv-v1.7.5 - -LIBUV_CONFIGURE_OPTIONS=CC=$(CC) - -# NOTFORCHECKIN - restore -O3 -# -DGHETTO \ -# -DHUSH -CFLAGS+= $(COSFLAGS) -ffast-math \ - -funsigned-char \ - -I/usr/local/include \ - $(OPTLOCALIFLAGS) \ - $(OPENSSLIFLAGS) \ - $(CURLINC) \ - -I$(INCLUDE) \ - -Ioutside/$(LIBUV_VER)/include \ - -Ioutside/anachronism/include \ - -Ioutside/ed25519/src \ - -Ioutside/commonmark/src \ - -Ioutside/commonmark/build/src \ - -Ioutside/scrypt \ - -Ioutside/softfloat-3/source/include \ - -Ioutside/murmur3 \ - $(DEFINES) \ - $(MDEFINES) - -# TODO remove -Wno-* -CWFLAGS=-Wall \ - -Wextra \ - -Wno-sign-compare \ - -Wno-unused-parameter \ - -Wno-missing-field-initializers \ - -Wno-strict-aliasing \ - -Wno-error -ifneq ($(OS),bsd) - CWFLAGS+=-Wno-error=unused-result -endif - -# glibc 2.24 deprecates readdir_r; iff glibc >=2.24, -# don't upgrade 'deprecated declarations' warnings to errors -# dependency: `getconf`, which comes w/glibc -GLIBC := $(lastword $(shell getconf GNU_LIBC_VERSION 2>/dev/null)) -# dependency: none, uses make's native functions -GLIBC_MAJ := $(word 1, $(subst ., ,$(GLIBC))) -GLIBC_MIN := $(word 2, $(subst ., ,$(GLIBC))) -# dependency: `expr` shell built-in -GLIBC_GE_2_24 := $(shell expr $(GLIBC_MAJ) ">" 2 "|" \ - $(GLIBC_MAJ) "=" 2 "&" $(GLIBC_MIN) ">=" 24 2>/dev/null) -ifeq (1,$(GLIBC_GE_2_24)) - CWFLAGS+=-Wno-error=deprecated-declarations -endif - -ifdef NO_SILENT_RULES -%.o: %.c $(CORE) - $(CC) -c $(CWFLAGS) $(CFLAGS) -o $@ $< - @$(CC) -MM -MP $(CWFLAGS) $(CFLAGS) -MT $@ $< -MF .d/$*.d -else -%.o: %.c $(CORE) - @echo " CC $@" - @$(CC) -c $(CWFLAGS) $(CFLAGS) -o $@ $< - @$(CC) -MM -MP $(CWFLAGS) $(CFLAGS) -MT $@ $< -MF .d/$*.d -endif - -N_OFILES=\ - noun/allocate.o \ - noun/events.o \ - noun/hashtable.o \ - noun/imprison.o \ - noun/jets.o \ - noun/manage.o \ - noun/nock.o \ - noun/retrieve.o \ - noun/trace.o \ - noun/xtract.o \ - noun/vortex.o \ - noun/zave.o - -J_A_OFILES=\ - jets/a/add.o \ - jets/a/dec.o \ - jets/a/div.o \ - jets/a/gte.o \ - jets/a/gth.o \ - jets/a/lte.o \ - jets/a/lth.o \ - jets/a/mod.o \ - jets/a/mul.o \ - jets/a/sub.o - -J_B_OFILES=\ - jets/b/bind.o \ - jets/b/clap.o \ - jets/b/drop.o \ - jets/b/flop.o \ - jets/b/lent.o \ - jets/b/levy.o \ - jets/b/lien.o \ - jets/b/murn.o \ - jets/b/need.o \ - jets/b/reap.o \ - jets/b/reel.o \ - jets/b/roll.o \ - jets/b/skid.o \ - jets/b/skim.o \ - jets/b/skip.o \ - jets/b/scag.o \ - jets/b/slag.o \ - jets/b/snag.o \ - jets/b/sort.o \ - jets/b/turn.o \ - jets/b/weld.o - -J_C_OFILES=\ - jets/c/bex.o \ - jets/c/xeb.o \ - jets/c/can.o \ - jets/c/cap.o \ - jets/c/cat.o \ - jets/c/con.o \ - jets/c/cut.o \ - jets/c/dor.o \ - jets/c/dvr.o \ - jets/c/dis.o \ - jets/c/end.o \ - jets/c/gor.o \ - jets/c/hor.o \ - jets/c/lsh.o \ - jets/c/mas.o \ - jets/c/met.o \ - jets/c/mix.o \ - jets/c/mug.o \ - jets/c/muk.o \ - jets/c/peg.o \ - jets/c/po.o \ - jets/c/pow.o \ - jets/c/rap.o \ - jets/c/rep.o \ - jets/c/rip.o \ - jets/c/rsh.o \ - jets/c/sqt.o \ - jets/c/vor.o - -J_D_OFILES=\ - jets/d/in_has.o \ - jets/d/in_int.o \ - jets/d/in_gas.o \ - jets/d/in_mer.o \ - jets/d/in_put.o \ - jets/d/in_tap.o \ - jets/d/in_uni.o \ - jets/d/in_wyt.o \ - jets/d/in_bif.o \ - jets/d/in_dif.o \ - jets/d/by_gas.o \ - jets/d/by_get.o \ - jets/d/by_has.o \ - jets/d/by_int.o \ - jets/d/by_put.o \ - jets/d/by_uni.o \ - jets/d/by_bif.o \ - jets/d/by_dif.o - -J_E_OFILES=\ - jets/e/aes_ecb.o \ - jets/e/aes_cbc.o \ - jets/e/aesc.o \ - jets/e/cue.o \ - jets/e/fl.o \ - jets/e/jam.o \ - jets/e/mat.o \ - jets/e/mink.o \ - jets/e/mule.o \ - jets/e/parse.o \ - jets/e/rd.o \ - jets/e/rq.o \ - jets/e/rs.o \ - jets/e/rh.o \ - jets/e/rub.o \ - jets/e/scr.o \ - jets/e/shax.o \ - jets/e/lore.o \ - jets/e/loss.o \ - jets/e/lune.o \ - jets/e/trip.o - -J_E_OFILES_ED=\ - jets/e/ed_puck.o \ - jets/e/ed_sign.o \ - jets/e/ed_veri.o \ - jets/e/ed_shar.o - -J_F_OFILES=\ - jets/f/ap.o \ - jets/f/cell.o \ - jets/f/comb.o \ - jets/f/cons.o \ - jets/f/core.o \ - jets/f/face.o \ - jets/f/fitz.o \ - jets/f/flan.o \ - jets/f/flip.o \ - jets/f/flor.o \ - jets/f/fork.o \ - jets/f/help.o \ - jets/f/hike.o \ - jets/f/look.o \ - jets/f/loot.o - -J_F_OFILES_UT=\ - jets/f/ut.o \ - jets/f/ut_burn.o \ - jets/f/ut_buss.o \ - jets/f/ut_conk.o \ - jets/f/ut_crop.o \ - jets/f/ut_find.o \ - jets/f/ut_fire.o \ - jets/f/ut_fish.o \ - jets/f/ut_fuse.o \ - jets/f/ut_gain.o \ - jets/f/ut_lose.o \ - jets/f/ut_mint.o \ - jets/f/ut_mull.o \ - jets/f/ut_nest.o \ - jets/f/ut_peek.o \ - jets/f/ut_peel.o \ - jets/f/ut_play.o \ - jets/f/ut_repo.o \ - jets/f/ut_rest.o \ - jets/f/ut_tack.o \ - jets/f/ut_toss.o \ - jets/f/ut_wrap.o - -J_G_OFILES=\ - jets/g/down.o - -J_OFILES=\ - $(J_A_OFILES) \ - $(J_B_OFILES) \ - $(J_C_OFILES) \ - $(J_D_OFILES) \ - $(J_E_OFILES) \ - $(J_E_OFILES_ED) \ - $(J_F_OFILES) \ - $(J_F_OFILES_UT) \ - $(J_G_OFILES) \ - jets/tree.o - -BASE_OFILES=$(N_OFILES) $(J_OFILES) - -OUT_OFILES=\ - outside/jhttp/http_parser.o \ - outside/murmur3/MurmurHash3.o - -V_OFILES=\ - vere/ames.o \ - vere/behn.o \ - vere/cttp.o \ - vere/http.o \ - vere/loop.o \ - vere/raft.o \ - vere/reck.o \ - vere/sist.o \ - vere/term.o \ - vere/time.o \ - vere/unix.o \ - vere/save.o \ - vere/walk.o - -MAIN_FILE =\ - vere/main.o - -VERE_OFILES=\ - $(OUT_OFILES) \ - $(BASE_OFILES) \ - $(MAIN_FILE) \ - $(V_OFILES) - -VERE_DFILES=$(VERE_OFILES:%.o=.d/%.d) - --include $(VERE_DFILES) - -TEST_HASH_MAIN_FILE =\ - tests/hashtable_tests.o - -TEST_HASH_OFILES=\ - $(OUT_OFILES) \ - $(BASE_OFILES) \ - $(TEST_HASH_MAIN_FILE) \ - $(V_OFILES) - -TEST_HASH_DFILES=$(TEST_HASH_OFILES:%.o=.d/%.d) - --include $(TEST_HASH_DFILES) - -# This is a silly hack necessitated by the fact that libuv uses configure -# -# * Making 'all' obviously requires outside/libuv, -# which requires the libuv Makefile to be created. -# * Making distclean on outside/libuv destroys the makefile. -# * ...so configuring outside/libuv is parodoxically required -# in order to distclean it! -# * But what if developer types 'make distclean all' ? -# * first target makes libuv Makefile, then destroys it...and -# second target knows that it was made. -# * ...so second target borks. -# * Solution: make libuv not only depend on its own Makefile, -# but on a side effect of creating its own makefile. -# -LIBUV_MAKEFILE=outside/$(LIBUV_VER)/Makefile -LIBUV_MAKEFILE2=outside/$(LIBUV_VER)/config.log - -LIBUV=outside/$(LIBUV_VER)/.libs/libuv.a - -LIBED25519=outside/ed25519/ed25519.a - -LIBANACHRONISM=outside/anachronism/build/libanachronism.a - -LIBCOMMONMARK=outside/commonmark/build/src/libcmark.a - -LIBSCRYPT=outside/scrypt/scrypt.a - -LIBSOFTFLOAT=outside/softfloat-3/build/Linux-x86_64-GCC/softfloat.a - -TAGS=\ - .tags \ - .etags \ - GPATH GTAGS GRTAGS \ - cscope.in.out cscope.po.out cscope.out - -all: urbit - -.MAKEFILE-VERSION: Makefile .make.conf - @echo "Makefile update." - @touch .MAKEFILE-VERSION - -.make.conf: - @echo "# Set custom configuration here, please!" > ".make.conf" - -urbit: $(BIN)/urbit - -$(LIBUV_MAKEFILE) $(LIBUV_MAKEFILE2): - cd outside/$(LIBUV_VER) ; sh autogen.sh ; ./configure $(LIBUV_CONFIGURE_OPTIONS) - -# [h]act II: the plot thickens -# -# * Specifying two targets that each configure libuv works -# when the rules are executed sequentially, -# * but when attempting a parallel build, it is likely Make -# will try to configure libuv simultaneously. -# * We can specify a dependency between the two targets so -# that execution of their rule(s) is serialized. -# * Further, libuv does not seem to be friendly towards -# parallel builds either. A true fix is out of scope here -# * ...so we must instruct Make to only use one job when it -# attempts to build libuv. -# -$(LIBUV_MAKEFILE2): $(LIBUV_MAKEFILE) - -$(LIBUV): $(LIBUV_MAKEFILE) $(LIBUV_MAKEFILE2) - $(MAKE) -C outside/$(LIBUV_VER) all-am -j1 - -$(LIBED25519): - $(MAKE) -C outside/ed25519 - -$(LIBANACHRONISM): - $(MAKE) -C outside/anachronism static - -$(LIBCOMMONMARK): - $(MAKE) -C outside/commonmark - -$(LIBSCRYPT): - $(MAKE) -C outside/scrypt MDEFINES="$(MDEFINES)" - -$(LIBSOFTFLOAT): - $(MAKE) -C outside/softfloat-3/build/Linux-x86_64-GCC - -$(V_OFILES): include/vere/vere.h - -ifdef NO_SILENT_RULES -$(BIN)/urbit: $(LIBCOMMONMARK) $(VERE_OFILES) $(LIBUV) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT) $(LIBSOFTFLOAT) - mkdir -p $(BIN) - $(CLD) $(CLDOSFLAGS) -o $(BIN)/urbit $(VERE_OFILES) $(LIBUV) $(LIBED25519) $(LIBANACHRONISM) $(LIBS) $(LIBCOMMONMARK) $(LIBSCRYPT) $(LIBSOFTFLOAT) -else -$(BIN)/urbit: $(LIBCOMMONMARK) $(VERE_OFILES) $(LIBUV) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT) $(LIBSOFTFLOAT) - @echo " CCLD $(BIN)/urbit" - @mkdir -p $(BIN) - @$(CLD) $(CLDOSFLAGS) -o $(BIN)/urbit $(VERE_OFILES) $(LIBUV) $(LIBED25519) $(LIBANACHRONISM) $(LIBS) $(LIBCOMMONMARK) $(LIBSCRYPT) $(LIBSOFTFLOAT) -endif - -# This should start a comet or something -test: - @echo "FIXME no tests defined" - -test_hash: $(BIN)/test_hash - -ifdef NO_SILENT_RULES -$(BIN)/test_hash: $(LIBCOMMONMARK) $(TEST_HASH_OFILES) $(LIBUV) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT) $(LIBSOFTFLOAT) - mkdir -p $(BIN) - $(CLD) $(CLDOSFLAGS) -o $(BIN)/test_hash $(TEST_HASH_OFILES) $(LIBUV) $(LIBED25519) $(LIBANACHRONISM) $(LIBS) $(LIBCOMMONMARK) $(LIBSCRYPT) $(LIBSOFTFLOAT) -else -$(BIN)/test_hash: $(LIBCOMMONMARK) $(TEST_HASH_OFILES) $(LIBUV) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT) $(LIBSOFTFLOAT) - @echo "VERE_DFILES=$(VERE_DFILES)" - @echo " CCLD $(BIN)/test_hash" - @mkdir -p $(BIN) - @$(CLD) $(CLDOSFLAGS) -o $(BIN)/test_hash $(TEST_HASH_OFILES) $(LIBUV) $(LIBED25519) $(LIBANACHRONISM) $(LIBS) $(LIBCOMMONMARK) $(LIBSCRYPT) $(LIBSOFTFLOAT) -endif - -tags: ctags etags gtags cscope - -ctags: - @ctags -R -f .tags --exclude=root || true - -etags: - @etags -f .etags $$(find . -name '*.c' -or -name '*.h') || true - -gtags: - @gtags || true - -cscope: - @cscope -b -q -R || true - -osxpackage: - $(RM) -r inst - $(MAKE) distclean - $(MAKE) $(BIN)/urbit LIB=/usr/local/lib/urb STATIC=yes - mkdir -p inst/usr/local/lib/urb inst/usr/local/bin - cp $(BIN)/urbit inst/usr/local/bin - cp urb/urbit.pill inst/usr/local/lib/urb - pkgbuild --root inst --identifier org.urbit.urbit --version 0.2 urbit.pkg - -debbuild: - $(MAKE) $(BIN)/urbit LIB=/usr/share/urb - -debinstall: - mkdir -p $(DESTDIR)/usr/bin $(DESTDIR)/usr/share/urb - install -m755 $(BIN)/urbit $(DESTDIR)/usr/bin - cp urb/urbit.pill $(DESTDIR)/usr/share/urb - -clean: - $(RM) $(VERE_OFILES) $(BIN)/urbit urbit.pkg $(VERE_DFILES) $(TAGS) - $(RM) -r debian/files debian/urbit* - -# 'make distclean all -jn' ∀ n>1 still does not work because it is possible -# Make will attempt to build urbit while it is also cleaning urbit.. -distclean: clean $(LIBUV_MAKEFILE) - $(MAKE) -C outside/$(LIBUV_VER) distclean - $(MAKE) -C outside/ed25519 clean - $(MAKE) -C outside/anachronism clean - $(MAKE) -C outside/scrypt clean - $(MAKE) -C outside/softfloat-3/build/Linux-x86_64-GCC clean - -.PHONY: clean debbuild debinstalldistclean etags osxpackage tags test diff --git a/README.md b/README.md index c1ed536da2..829db92c3b 100644 --- a/README.md +++ b/README.md @@ -16,15 +16,13 @@ If you're doing development on Urbit, keep reading. `vere`, the Urbit virtual machine, depends on the following: - C compiler ([gcc](https://gcc.gnu.org) or [clang](http://clang.llvm.org)) -- [GNU Make](https://www.gnu.org/software/make/) +- [Meson](http://mesonbuild.com/) - [GMP](https://gmplib.org) -- [CMake](https://cmake.org) -- automake, autoconf, and libtool - [OpenSSL](https://www.openssl.org) - [libsigsegv](https://www.gnu.org/software/libsigsegv/) - [libcurl](https://curl.haxx.se/libcurl/) +- [libuv](http://libuv.org) - curses implementation (ncurses on Linux distributions, OS curses otherwise) -- [Ragel](https://www.colm.net/open-source/ragel/) - [re2c](http://re2c.org) Most of these dependencies are unfortunate; we aim to drastically shrink the @@ -34,16 +32,44 @@ for future unbundling or removal wherever possible. ## Building -Our Makefile should handle the build smoothly on all supported platforms. It's -just a simple Makefile, written by hand for GNU Make, and the most complicated -parts of its internal machinery have to do with the varied build systems of the -bundled libraries. +Urbit uses Meson build system. -Useful targets are the default `all`, `clean`, and `distclean`. The last may not -produce an entirely clean distribution directory, and runs a bundled library's -configure script; `git clean` may be a better option. +Some libraries which are not found in major distributions: +- ed25519 +- http-parser legacy version 0.1.0 +- murmur3 +- softfloat3 +- urbit-scrypt +- commonmark legacy version 0.12.0 -The `vere` binary is produced in `bin/urbit`. +are included as git submodules. To build urbit from source, perform the following steps: + +## Configuration & compilation +(For instructions for legacy meson, also see below) + +1. Install all required dependencies. +2. Run `./scripts/bootstrap` +3. Run `./scripts/build` +4. The executable should appear in `./build` directory. + +### Using meson & ninja +To configure project, enter the build directory and enter +`meson configure`. Without any arguments this command will display available +options. For example, to compile debug build of urbit, use +`meson configure -Ddebug=true`. +To set the prefix for installation use +`meson configure -Dprefix=/usr`, and so on. + +## Configuration & compilation for legacy meson + +The syntax for legacy meson (Version `0.29`) is a bit different. +1. Manually create `build` directory and invoke meson as `meson . ./build` +2. If you want to set options, this is done in one step. + Use `meson -D [options] . ./build` to prepare customized build. + +Once the project is configured, use `ninja` to build it. +To install it into the default prefix, use `ninja install`. +If you want to specify custom `DESTDIR`, use `DESTDIR=... ninja install`. ## Building the Debian Package diff --git a/debian/control b/debian/control index ee8711ca0e..430ff65e3c 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: urbit Section: net Priority: extra Maintainer: Ted Blackman -Build-Depends: debhelper (>= 9), libgmp3-dev, libsigsegv-dev, openssl, libssl-dev, automake, autoconf, libtool, g++, ragel, cmake, re2c, libcurl4-gnutls-dev +Build-Depends: debhelper (>= 9), libgmp3-dev, libsigsegv-dev, openssl, libssl-dev,libtool, meson, re2c, libcurl4-gnutls-dev Standards-Version: 3.9.5 Homepage: http://urbit.org diff --git a/include/all.h b/include/all.h index ed86089673..4f77916b1e 100644 --- a/include/all.h +++ b/include/all.h @@ -2,7 +2,7 @@ ** ** This file is in the public domain. */ -# include "version.h" +# include "config.h" /** c3: C environment. **/ # include "c/portable.h" // C and OS portability @@ -12,7 +12,7 @@ /** u3: noun environment. **/ -# include "noun/aliases.h" // general u3 +# include "noun/aliases.h" // general u3 # include "noun/allocate.h" // u3a: allocation # include "noun/events.h" // u3e: persistence @@ -24,7 +24,7 @@ # include "noun/options.h" // u3o: config options # include "noun/retrieve.h" // u3r: noun access (error returns) # include "noun/trace.h" // u3t: profiling / tracing -# include "noun/xtract.h" // u3x: noun access (error crashes) +# include "noun/xtract.h" // u3x: noun access (error crashes) # include "noun/vortex.h" // u3v: arvo kernel # include "noun/zave.h" // u3z: memoization @@ -52,4 +52,3 @@ */ # define uH u3_term_io_hija() # define uL(x) u3_term_io_loja(x) - diff --git a/include/c/defs.h b/include/c/defs.h index 1d78e791c6..5332d42a1b 100644 --- a/include/c/defs.h +++ b/include/c/defs.h @@ -90,3 +90,10 @@ c3_assert(!"memory lost"); \ } \ rut;}) + +/* c3_calloc(): asserting calloc + */ +#define c3_calloc(s) ({ \ + void* rut = c3_malloc(s); \ + memset(rut, 0, s); \ + rut;}) diff --git a/include/c/motes.h b/include/c/motes.h index 56ab356be7..23670d86f2 100644 --- a/include/c/motes.h +++ b/include/c/motes.h @@ -232,6 +232,7 @@ # define c3__con c3_s3('c','o','n') # define c3__cone c3_s4('c','o','n','e') # define c3__cong c3_s4('c','o','n','g') +# define c3__conn c3_s4('c','o','n','n') # define c3__cons c3_s4('c','o','n','s') # define c3__cook c3_s4('c','o','o','k') # define c3__cool c3_s4('c','o','o','l') @@ -772,6 +773,7 @@ # define c3__oops c3_s4('o','o','p','s') # define c3__op c3_s2('o','p') # define c3__open c3_s4('o','p','e','n') +# define c3__opts c3_s4('o','p','t','s') # define c3__or c3_s2('o','r') # define c3__ord c3_s3('o','r','d') # define c3__orth c3_s4('o','r','t','h') diff --git a/include/c/portable.h b/include/c/portable.h index 7ed2db6647..650dff24dc 100644 --- a/include/c/portable.h +++ b/include/c/portable.h @@ -4,10 +4,15 @@ */ /** Must be compiled on gcc with C99 support. **/ + +#include "config.h" + # ifndef __GNUC__ # error "port me" # endif +# ifndef _GNU_SOURCE # define _GNU_SOURCE +# endif /** System include files. @@ -189,3 +194,10 @@ # else # define c3_rand u3_sist_rand # endif + +/* Static assertion + */ +#define ASSERT_CONCAT_(a, b) a##b +#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b) +#define STATIC_ASSERT(e,m) \ + ;enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(int)(!!(e)) } diff --git a/include/config.h.in b/include/config.h.in new file mode 100644 index 0000000000..66f7783096 --- /dev/null +++ b/include/config.h.in @@ -0,0 +1,13 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#mesondefine URBIT_VERSION + +#mesondefine U3_OS_linux +#mesondefine U3_OS_bsd +#mesondefine U3_OS_osx + +#mesondefine U3_OS_ENDIAN_little +#mesondefine U3_OS_ENDIAN_big + +#endif /*CONFIG_H*/ diff --git a/include/vere/vere.h b/include/vere/vere.h index 988b8b7abd..729f3b8f9e 100644 --- a/include/vere/vere.h +++ b/include/vere/vere.h @@ -2,6 +2,9 @@ ** ** This file is in the public domain. */ + +#include "h2o.h" + /** Quasi-tunable parameters. **/ /* First kernel this executable can boot. @@ -19,7 +22,9 @@ */ typedef struct _u3_hhed { struct _u3_hhed* nex_u; + c3_w nam_w; c3_c* nam_c; + c3_w val_w; c3_c* val_c; } u3_hhed; @@ -31,85 +36,38 @@ c3_y hun_y[0]; } u3_hbod; - /* u3_hrat: http parser state. - */ - typedef enum { - u3_hreq_non, - u3_hreq_nam, - u3_hreq_val - } u3_hrat; - - /* u3_csat: client connection state. - */ - typedef enum { - u3_csat_dead = 0, // connection dead - u3_csat_addr = 1, // connection addressed - u3_csat_clyr = 2, // connection open in cleartext - u3_csat_crop = 3, // connection open, ssl needs hs - u3_csat_sing = 4, // connection handshaking ssl - u3_csat_cryp = 5, // connection open, ssl open - } u3_csat; - - /* u3_hmet: http method. Matches jhttp encoding. - */ - typedef enum { - u3_hmet_delete, - u3_hmet_get, - u3_hmet_head, - u3_hmet_post, - u3_hmet_put, - u3_hmet_nop, // virtual method - u3_hmet_other // ie, unsupported - } u3_hmet; - /* u3_hreq: incoming http request. */ typedef struct _u3_hreq { - struct _u3_hcon* hon_u; // connection + h2o_req_t* rec_u; // h2o request c3_w seq_l; // sequence within connection - u3_hmet met_e; // method - u3_hrat rat_e; // parser state - c3_c* url_c; // url - c3_w ipf_w; // ipv4 - c3_o liv; // keepalive - c3_o end; // all responses added - u3_hhed* hed_u; // headers - u3_hbod* bod_u; // body parts (exit) - u3_hbod* dob_u; // body parts (entry) - struct _u3_hreq* nex_u; // next in request queue - u3_hbod* rub_u; // exit of write queue - u3_hbod* bur_u; // entry of write queue + struct _u3_hcon* hon_u; // connection backlink + struct _u3_hreq* nex_u; // next in connection's list } u3_hreq; - /* u3_hrep: outgoing http response. - */ - typedef struct _u3_hrep { - c3_w sev_l; // server number - c3_w coq_l; // connection number - c3_w seq_l; // request number - c3_w sas_w; // status - u3_hhed* hed_u; // headers - u3_hbod* bod_u; // body (one part) - } u3_hrep; - /* u3_hcon: incoming http connection. */ typedef struct _u3_hcon { - uv_tcp_t wax_u; // event handler state + uv_tcp_t wax_u; // client stream handler + h2o_conn_t* con_u; // h2o connection + h2o_socket_t* sok_u; // h2o connection socket + c3_w ipf_w; // client ipv4 c3_w coq_l; // connection number c3_w seq_l; // next request number - struct _u3_http* htp_u; // backlink to server + struct _u3_http* htp_u; // server backlink + struct _u3_hreq* req_u; // request list struct _u3_hcon* nex_u; // next in server's list - struct _u3_hreq* ruc_u; // request under construction - struct _u3_hreq* req_u; // exit of request queue - struct _u3_hreq* qer_u; // entry of request queue - void* par_u; // struct http_parser * } u3_hcon; /* u3_http: http server. */ typedef struct _u3_http { - uv_tcp_t wax_u; // event handler state + uv_tcp_t wax_u; // server stream handler + h2o_globalconf_t* fig_u; // h2o global config + h2o_context_t* ctx_u; // h2o ctx + h2o_accept_ctx_t* cep_u; // h2o accept ctx (wat for?) + h2o_hostconf_t* hos_u; // h2o host config + h2o_handler_t* han_u; // h2o request handler c3_w sev_l; // server number c3_w coq_l; // next connection number c3_w por_w; // running port @@ -119,13 +77,20 @@ struct _u3_http* nex_u; // next in list } u3_http; + /* u3_csat: client connection state. + */ + typedef enum { + u3_csat_init = 0, // initialized + u3_csat_addr = 1, // address resolution begun + u3_csat_quit = 2, // cancellation requested + u3_csat_ripe = 3 // passed to libh2o + } u3_csat; + /* u3_cres: response to http client. */ typedef struct _u3_cres { - u3_hrat rat_e; // parser state - void* par_u; // struct http_parser * c3_w sas_w; // status code - u3_hhed* hed_u; // headers + u3_noun hed; // headers u3_hbod* bod_u; // exit of body queue u3_hbod* dob_u; // entry of body queue } u3_cres; @@ -134,59 +99,42 @@ */ typedef struct _u3_creq { // client request c3_l num_l; // request number + h2o_http1client_t* cli_u; // h2o client + u3_csat sat_e; // connection state + c3_o sec; // yes == https + c3_w ipf_w; // IP + c3_c* ipf_c; // IP (string) c3_c* hot_c; // host c3_s por_s; // port + c3_c* por_c; // port (string) + c3_m met_m; // method c3_c* url_c; // url - c3_o sec; // yes == https - u3_hmet met_e; // method u3_hhed* hed_u; // headers u3_hbod* bod_u; // body - u3_cres* res_u; // nascent response - struct _u3_ccon* coc_u; // parent connection - struct _u3_creq* nex_u; // next in queue - } u3_creq; - - /* u3_sslx: per-connection ssl context. - */ - typedef struct _u3_sslx { - void* ssl_u; // struct SSL* - void* rio_u; // struct BIO* for read - void* wio_u; // struct BIO* for write - } u3_sslx; - - /* u3_ccon: outgoing http connection. - */ - typedef struct _u3_ccon { // client connection - uv_tcp_t wax_u; // i/o handler state - uv_connect_t cot_u; // connection handler state - uv_getaddrinfo_t adr_u; // resolver state - u3_sslx ssl; // ssl state - u3_csat sat_e; // connection state - c3_c* hot_c; // hostname - c3_s por_s; // port - c3_w ipf_w; // IP - c3_o sec; // yes == https u3_hbod* rub_u; // exit of send queue u3_hbod* bur_u; // entry of send queue - u3_creq* ceq_u; // exit of request queue - u3_creq* qec_u; // entry of request queue - struct _u3_ccon* pre_u; // previous in list - struct _u3_ccon* nex_u; // next in list - } u3_ccon; + h2o_iovec_t* vec_u; // send-buffer array + u3_cres* res_u; // nascent response + struct _u3_creq* nex_u; // next in list + struct _u3_creq* pre_u; // previous in list + } u3_creq; /* u3_chot: foreign host (not yet used). */ typedef struct _u3_chot { c3_w ipf_w; // ip address (or 0) c3_c* hot_c; // hostname (no port) (or 0) - struct _u3_ccon* ins_u; // insecure connection (or 0) - struct _u3_ccon* sec_u; // secure connection (or 0) + void* ins_u; // insecure connection (or 0) + void* sec_u; // secure connection (or 0) } u3_chot; /* u3_cttp: http client. */ typedef struct _u3_cttp { - struct _u3_ccon* coc_u; // connection list + u3_creq* ceq_u; // request list + h2o_http1client_ctx_t* // + ctx_u; // h2o client ctx + void* tls_u; // client SSL_CTX* } u3_cttp; /* u3_apac: ames packet, coming or going. @@ -581,12 +529,11 @@ u3_behn teh_u; // behn timer c3_o liv; // if u3_no, shut down c3_i xit_i; // exit code for shutdown - void* ssl_u; // struct SSL_CTX* + void* tls_u; // server SSL_CTX* } u3_host; // host == computer == process # define u3L u3_Host.lup_u // global event loop # define u3Z (&(u3_Raft)) -# define u3S u3_Host.ssl_u /** Global variables. **/ @@ -683,7 +630,7 @@ /* u3_walk_save(): save file or bail. */ void - u3_walk_save(c3_c* pas_c, u3_noun tim, u3_atom pad); + u3_walk_save(c3_c* pas_c, u3_noun tim, u3_atom pad, c3_c* bas_c, u3_noun pax); /* u3_sync_reck(): traverse filesystem for changes -> lamb */ diff --git a/include/version.h b/include/version.h deleted file mode 100644 index 8fcd4d24b9..0000000000 --- a/include/version.h +++ /dev/null @@ -1 +0,0 @@ -#define URBIT_VERSION "0.5.1" diff --git a/jets/c/muk.c b/jets/c/muk.c index 60e0a6b419..6d71aed1c6 100644 --- a/jets/c/muk.c +++ b/jets/c/muk.c @@ -2,7 +2,7 @@ ** */ #include "all.h" -#include +#include /* functions */ diff --git a/jets/e/rd.c b/jets/e/rd.c index 04281147bd..d4b44f7782 100644 --- a/jets/e/rd.c +++ b/jets/e/rd.c @@ -2,7 +2,7 @@ ** */ #include "all.h" -#include "softfloat.h" +#include #define DOUBNAN 0x7ff8000000000000 diff --git a/jets/e/rh.c b/jets/e/rh.c index 96c2f2f74c..472de374ac 100644 --- a/jets/e/rh.c +++ b/jets/e/rh.c @@ -2,7 +2,7 @@ ** */ #include "all.h" -#include "softfloat.h" +#include #define HALFNAN 0x7e00 @@ -151,8 +151,8 @@ /* div */ u3_noun - u3qes_div(u3_atom a, - u3_atom b, + u3qes_div(u3_atom a, + u3_atom b, u3_atom r) { union half c, d, e; @@ -183,7 +183,7 @@ /* sqt */ u3_noun - u3qes_sqt(u3_atom a, + u3qes_sqt(u3_atom a, u3_atom r) { union half c, d; diff --git a/jets/e/rq.c b/jets/e/rq.c index f4c506c9a2..19af6acc60 100644 --- a/jets/e/rq.c +++ b/jets/e/rq.c @@ -2,7 +2,7 @@ ** */ #include "all.h" -#include "softfloat.h" +#include #define QUADNAN 0x7fff800000000000 diff --git a/jets/e/rs.c b/jets/e/rs.c index d4ee29d7e3..b0f2a45748 100644 --- a/jets/e/rs.c +++ b/jets/e/rs.c @@ -2,7 +2,7 @@ ** */ #include "all.h" -#include "softfloat.h" +#include #define SINGNAN 0x7fc00000 @@ -151,8 +151,8 @@ /* div */ u3_noun - u3qet_div(u3_atom a, - u3_atom b, + u3qet_div(u3_atom a, + u3_atom b, u3_atom r) { union sing c, d, e; @@ -183,7 +183,7 @@ /* sqt */ u3_noun - u3qet_sqt(u3_atom a, + u3qet_sqt(u3_atom a, u3_atom r) { union sing c, d; diff --git a/jets/e/scr.c b/jets/e/scr.c index 9111f8a6cc..69d1cdecd0 100644 --- a/jets/e/scr.c +++ b/jets/e/scr.c @@ -5,7 +5,9 @@ #include #include -#include + +#include +#include static int _crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t, uint32_t, uint32_t, uint8_t *, size_t); @@ -17,8 +19,8 @@ static int _crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, u3qes_hsl(u3_atom p, u3_atom pl, u3_atom s, u3_atom sl, u3_atom n, - u3_atom r, - u3_atom z, + u3_atom r, + u3_atom z, u3_atom d) { // asserting that n is power of 2 in _crypto_scrypt @@ -30,7 +32,7 @@ static int _crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, (((c3_d)r * 128 * ((c3_d)n + z - 1)) <= (1 << 30)))) return u3m_bail(c3__exit); - c3_y* b_p = u3a_malloc(pl + 1); c3_y* b_s= u3a_malloc(sl + 1); + c3_y* b_p = u3a_malloc(pl + 1); c3_y* b_s= u3a_malloc(sl + 1); u3r_bytes(0, pl, b_p, p); u3r_bytes(0, sl, b_s, s); b_p[pl] = 0; b_s[sl]=0; c3_y* buf = u3a_malloc(d); @@ -73,7 +75,7 @@ static int _crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, return u3m_bail(c3__exit); c3_w pl = u3r_met(3, p); c3_w sl = u3r_met(3, s); - c3_y* b_p = u3a_malloc(pl + 1); c3_y* b_s= u3a_malloc(sl + 1); + c3_y* b_p = u3a_malloc(pl + 1); c3_y* b_s= u3a_malloc(sl + 1); u3r_bytes(0, pl, b_p, p); u3r_bytes(0, sl, b_s, s); b_p[pl] = 0; b_s[sl]=0; c3_y* buf = u3a_malloc(d); @@ -112,12 +114,12 @@ static int _crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, (c != 0))) return u3m_bail(c3__exit); - c3_y* b_p = u3a_malloc(pl + 1); c3_y* b_s= u3a_malloc(pl + 1); + c3_y* b_p = u3a_malloc(pl + 1); c3_y* b_s= u3a_malloc(pl + 1); u3r_bytes(0, pl, b_p, p); u3r_bytes(0, sl, b_s, s); b_p[pl] = 0; b_s[sl]=0; c3_y* buf = u3a_malloc(d); - PBKDF2_SHA256(b_p, pl, b_s, sl, c, buf, d); + libscrypt_PBKDF2_SHA256(b_p, pl, b_s, sl, c, buf, d); u3_noun res = u3i_bytes(d, buf); u3a_free(b_p); u3a_free(b_s); u3a_free(buf); @@ -147,12 +149,12 @@ static int _crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, return u3m_bail(c3__exit); c3_w pl = u3r_met(3, p); c3_w sl = u3r_met(3, s); - c3_y* b_p = u3a_malloc(pl + 1); c3_y* b_s= u3a_malloc(pl + 1); + c3_y* b_p = u3a_malloc(pl + 1); c3_y* b_s= u3a_malloc(pl + 1); u3r_bytes(0, pl, b_p, p); u3r_bytes(0, sl, b_s, s); b_p[pl] = 0; b_s[sl]=0; c3_y* buf = u3a_malloc(d); - PBKDF2_SHA256(b_p, pl, b_s, sl, c, buf, d); + libscrypt_PBKDF2_SHA256(b_p, pl, b_s, sl, c, buf, d); u3_noun res = u3i_bytes(d, buf); u3a_free(b_p); u3a_free(b_s); u3a_free(buf); @@ -170,35 +172,6 @@ static int _crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, return u3qes_pbk(p, s, c, d); } -/*- - * Copyright 2009 Colin Percival - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ - /** * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, @@ -213,77 +186,5 @@ _crypto_scrypt(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p, uint8_t * buf, size_t buflen) { - void * B0, * V0, * XY0; - uint8_t * B; - uint32_t * V; - uint32_t * XY; - uint32_t i; - - if (((N & (N-1)) != 0) || N == 0) - goto err0; - - /* Sanity-check parameters. */ -#if SIZE_MAX > UINT32_MAX - if (buflen > (((uint64_t)(1) << 32) - 1) * 32) { - errno = EFBIG; - goto err0; - } -#endif - if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) { - errno = EFBIG; - goto err0; - } - if (((N & (N - 1)) != 0) || (N == 0)) { - errno = EINVAL; - goto err0; - } - int test_size_max = (r > SIZE_MAX / 128 / p) || (N > SIZE_MAX / 128 / r); - -#if SIZE_MAX / 256 <= UINT32_MAX - test_size_max = (r > (SIZE_MAX - 64) / 256) || test_size_max; -#endif - if(test_size_max) { - errno = ENOMEM; - goto err0; - } - - /* Allocate memory. */ - if ((B0 = u3a_malloc(128 * r * p + 63)) == NULL) - goto err0; - B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63)); - if ((XY0 = u3a_malloc(256 * r + 64 + 63)) == NULL) - goto err1; - XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63)); - if ((V0 = u3a_malloc(128 * r * N + 63)) == NULL) - goto err2; - V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63)); - - /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ - PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r); - - /* 2: for i = 0 to p - 1 do */ - for (i = 0; i < p; i++) { - /* 3: B_i <-- MF(B_i, N) */ - smix(&B[i * 128 * r], r, N, V, XY); - } - - /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ - PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen); - - /* Free memory. */ - - u3a_free(V0); - u3a_free(XY0); - u3a_free(B0); - - /* Success! */ - return (0); - -err2: - u3a_free(XY0); -err1: - u3a_free(B0); -err0: - /* Failure! */ - return (-1); + return libscrypt_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen); } diff --git a/meson.build b/meson.build new file mode 100644 index 0000000000..eff66da1c2 --- /dev/null +++ b/meson.build @@ -0,0 +1,332 @@ +project('urbit', 'c', meson_version: '>=0.29.0') + +legacy_meson = false + +detect_meson_version = run_command('meson', '--version') +meson_ver = detect_meson_version.stdout() + +if(meson_ver == '0.29.0\n') + legacy_meson = true +elif(not meson.version().version_compare('>=0.40.0')) + error('Meson 0.29.0 is last legacy version supported. Otherwise please upgrade to 0.40.0 or higher.') +endif + +jets_a_src = [ +'jets/a/add.c', +'jets/a/dec.c', +'jets/a/div.c', +'jets/a/gte.c', +'jets/a/gth.c', +'jets/a/lte.c', +'jets/a/lth.c', +'jets/a/mod.c', +'jets/a/mul.c', +'jets/a/sub.c',] + +jets_b_src = [ +'jets/b/bind.c', +'jets/b/clap.c', +'jets/b/drop.c', +'jets/b/flop.c', +'jets/b/lent.c', +'jets/b/levy.c', +'jets/b/lien.c', +'jets/b/murn.c', +'jets/b/need.c', +'jets/b/reap.c', +'jets/b/reel.c', +'jets/b/roll.c', +'jets/b/skid.c', +'jets/b/skim.c', +'jets/b/skip.c', +'jets/b/scag.c', +'jets/b/slag.c', +'jets/b/snag.c', +'jets/b/sort.c', +'jets/b/turn.c', + 'jets/b/weld.c' ] + +jets_c_src = [ +'jets/c/bex.c', +'jets/c/xeb.c', +'jets/c/can.c', +'jets/c/cap.c', +'jets/c/cat.c', +'jets/c/con.c', +'jets/c/cut.c', +'jets/c/dor.c', +'jets/c/dvr.c', +'jets/c/dis.c', +'jets/c/end.c', +'jets/c/gor.c', +'jets/c/hor.c', +'jets/c/lsh.c', +'jets/c/mas.c', +'jets/c/met.c', +'jets/c/mix.c', +'jets/c/mug.c', +'jets/c/muk.c', +'jets/c/peg.c', +'jets/c/po.c', +'jets/c/pow.c', +'jets/c/rap.c', +'jets/c/rep.c', +'jets/c/rip.c', +'jets/c/rsh.c', +'jets/c/sqt.c', +'jets/c/vor.c', +] + +jets_d_src = [ +'jets/d/in_has.c', +'jets/d/in_int.c', +'jets/d/in_gas.c', +'jets/d/in_mer.c', +'jets/d/in_put.c', +'jets/d/in_tap.c', +'jets/d/in_uni.c', +'jets/d/in_wyt.c', +'jets/d/in_bif.c', +'jets/d/in_dif.c', +'jets/d/by_gas.c', +'jets/d/by_get.c', +'jets/d/by_has.c', +'jets/d/by_int.c', +'jets/d/by_put.c', +'jets/d/by_uni.c', +'jets/d/by_bif.c', +'jets/d/by_dif.c' +] + +jets_e_src = [ +'jets/e/aes_ecb.c', +'jets/e/aes_cbc.c', +'jets/e/aesc.c', +'jets/e/cue.c', +'jets/e/fl.c', +'jets/e/jam.c', +'jets/e/mat.c', +'jets/e/mink.c', +'jets/e/mule.c', +'jets/e/parse.c', +'jets/e/rd.c', +'jets/e/rq.c', +'jets/e/rs.c', +'jets/e/rh.c', +'jets/e/rub.c', +'jets/e/scr.c', +'jets/e/shax.c', +'jets/e/lore.c', +'jets/e/loss.c', +'jets/e/lune.c', +'jets/e/trip.c' +] + +jets_e_ed_src = [ +'jets/e/ed_puck.c', +'jets/e/ed_sign.c', +'jets/e/ed_veri.c', +'jets/e/ed_shar.c' + +] +jets_f_src = [ +'jets/f/ap.c', +'jets/f/cell.c', +'jets/f/comb.c', +'jets/f/cons.c', +'jets/f/core.c', +'jets/f/face.c', +'jets/f/fitz.c', +'jets/f/flan.c', +'jets/f/flip.c', +'jets/f/flor.c', +'jets/f/fork.c', +'jets/f/help.c', +'jets/f/hike.c', +'jets/f/look.c', +'jets/f/loot.c' +] + +jets_f_ut_src = [ +'jets/f/ut.c', +'jets/f/ut_burn.c', +'jets/f/ut_buss.c', +'jets/f/ut_conk.c', +'jets/f/ut_crop.c', +'jets/f/ut_find.c', +'jets/f/ut_fire.c', +'jets/f/ut_fish.c', +'jets/f/ut_fuse.c', +'jets/f/ut_gain.c', +'jets/f/ut_lose.c', +'jets/f/ut_mint.c', +'jets/f/ut_mull.c', +'jets/f/ut_nest.c', +'jets/f/ut_peek.c', +'jets/f/ut_peel.c', +'jets/f/ut_play.c', +'jets/f/ut_repo.c', +'jets/f/ut_rest.c', +'jets/f/ut_tack.c', +'jets/f/ut_toss.c', +'jets/f/ut_wrap.c' +] + +jets_g_src = [ +'jets/g/down.c' +] + +jets_src = [ +'jets/tree.c' +] +noun_src = ['noun/allocate.c', + 'noun/events.c', + 'noun/hashtable.c', + 'noun/imprison.c', + 'noun/jets.c', + 'noun/manage.c', + 'noun/nock.c', + 'noun/retrieve.c', + 'noun/trace.c', + 'noun/vortex.c', + 'noun/xtract.c', + 'noun/zave.c'] + +vere_src = ['vere/ames.c', + 'vere/behn.c', + 'vere/cttp.c', + 'vere/http.c', + 'vere/loop.c', + 'vere/main.c', + 'vere/raft.c', + 'vere/reck.c', + 'vere/save.c', + 'vere/sist.c', + 'vere/term.c', + 'vere/time.c', + 'vere/unix.c', + 'vere/walk.c'] + +src_list = [ +vere_src, noun_src, +jets_a_src, jets_b_src, +jets_c_src, jets_d_src, +jets_e_src, jets_e_ed_src, jets_f_src, jets_f_ut_src, +jets_g_src, jets_src] + +sources = [] +foreach s : src_list + sources += s +endforeach + +incdir = include_directories('include/') + +conf_data = configuration_data() +conf_data.set('URBIT_VERSION', '"0.5.1"') + +osdet = build_machine.system() +os_c_flags = ['-funsigned-char','-ffast-math'] +os_deps = [] +os_link_flags = [] + +if osdet == 'linux' + conf_data.set('U3_OS_linux', true) + + if(legacy_meson) + pthread_dep = find_library('pthread') + else + pthread_dep = meson.get_compiler('c').find_library('pthread') + endif + + ncurses_dep = dependency('ncurses') + os_deps = os_deps + [pthread_dep, ncurses_dep] + +elif osdet == 'darwin' + conf_data.set('U3_OS_osx', true) + + os_c_flags = os_c_flags + ['-bind_at_load'] + # os_link_flags = ['-framework CoreServices', '-framework CoreFoundation'] + if(legacy_meson) + ncurses_dep = find_library('ncurses') + else + ncurses_dep = meson.get_compiler('c').find_library('ncurses') + endif + + os_deps = os_deps + [ncurses_dep] + +elif osdet == 'bsd' + conf_data.set('U3_OS_bsd', true) + + pthread_dep = meson.get_compiler('c').find_library('pthread') + kvm_dep = meson.get_compiler('c').find_library('kvm') + ncurses_dep = dependency('ncurses') + os_deps = os_deps + [kvm_dep, pthread_dep, ncurses_dep] +else + error('Unsupported OS detected:' + osdet) +endif + +endian = build_machine.endian() + +if endian == 'little' + conf_data.set('U3_OS_ENDIAN_little', true) +else + error('Little endian encoding required') +endif + +configure_file(input : 'include/config.h.in', + output : 'config.h', + configuration : conf_data) + +# We expect these libs to supplied with the distribution +curl_dep = dependency('libcurl', version: '>=7.35.0') + +if osdet == 'darwin' + libcrypto = meson.get_compiler('c').find_library('crypto', dirs: [ '/usr/local/opt/openssl/lib/' ]) + libssl = meson.get_compiler('c').find_library('ssl', dirs: [ '/usr/local/opt/openssl/lib/' ]) + openssl_dep = declare_dependency(dependencies: [libcrypto, libssl], include_directories: include_directories('/usr/local/opt/openssl/include')) +else + openssl_dep = dependency('openssl', version: '>=1.0.0') +endif + +if(legacy_meson) + gmp_dep = find_library('gmp') + sigsegv_dep = find_library('sigsegv') +else + gmp_dep = meson.get_compiler('c').find_library('gmp') + sigsegv_dep = meson.get_compiler('c').find_library('sigsegv') +endif + +# For these libs we provide fallback bundle +cmark_dep = dependency('libcmark', version: '0.12.0', fallback: ['commonmark-legacy', 'cmark_dep']) +urbitscrypt_dep = dependency('libscrypt', version: '>=0.1.21', fallback: ['libscrypt', 'libscrypt_dep']) + +ed25519_dep = dependency('ed25519', version: '>=0.1.0', fallback: ['ed25519', 'ed25519_dep']) +murmur3_dep = dependency('murmur3', version: '>=0.1.0', fallback: ['murmur3', 'murmur3_dep']) +softfloat3_dep = dependency('softfloat3', version: '>=3.0.0', fallback: ['softfloat3', 'softfloat3_dep']) +libuv_dep = dependency('libuv', version: '>=1.8.0', fallback:['libuv', 'libuv_dep']) +libh2o_dep = dependency('libh2o', version: '>=0.13.3', fallback: ['libh2o', 'libh2o_dep']) + +opt_flags = [] +if get_option('debug') + opt_flags = ['-g'] +else + opt_flags = ['-O3'] +endif + +executable('urbit', +sources : sources, +include_directories : incdir, +c_args : opt_flags + os_c_flags, +link_args: os_link_flags, +dependencies: [openssl_dep, + curl_dep, + libuv_dep, + libh2o_dep, + cmark_dep, + gmp_dep, + sigsegv_dep, + urbitscrypt_dep, + ed25519_dep, + murmur3_dep, + softfloat3_dep] + os_deps, +install: true) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000000..378902f8d9 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1 @@ +option('debug', type:'boolean', value: false) diff --git a/outside/anachronism/.gitignore b/outside/anachronism/.gitignore deleted file mode 100644 index 567609b123..0000000000 --- a/outside/anachronism/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build/ diff --git a/outside/anachronism/LICENSE b/outside/anachronism/LICENSE deleted file mode 100644 index 72d4b706ee..0000000000 --- a/outside/anachronism/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2010 Jonathan Castello - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/outside/anachronism/Makefile b/outside/anachronism/Makefile deleted file mode 100644 index 123576f13c..0000000000 --- a/outside/anachronism/Makefile +++ /dev/null @@ -1,70 +0,0 @@ -SHELL = sh -UNAME = $(shell uname) - -ifneq ($(UNAME),FreeBSD) -CC = gcc -else -CC = cc -endif -FLAGS = -c -fPIC -Iinclude/ -CFLAGS = --pedantic -Wall -Wextra -march=native -std=gnu99 -INCLUDE = include/anachronism - -VERSION_MAJOR = 0 -VERSION = $(VERSION_MAJOR).3.1 - -SO = libanachronism.so -SOFILE = $(SO).$(VERSION) -SONAME = $(SO).$(VERSION_MAJOR) - - -all: static shared -shared: build/ build/$(SOFILE) -static: build/ build/libanachronism.a - -build/: - mkdir build - -build/$(SOFILE): build/nvt.o build/parser.o - $(CC) -shared -Wl,-soname,$(SONAME) -o build/$(SOFILE) build/nvt.o build/parser.o - -build/libanachronism.a: build/nvt.o build/parser.o - ar rcs build/libanachronism.a build/nvt.o build/parser.o - -build/nvt.o: src/nvt.c $(INCLUDE)/nvt.h $(INCLUDE)/common.h - $(CC) $(FLAGS) $(CFLAGS) src/nvt.c -o build/nvt.o - -build/parser.o: src/parser.c $(INCLUDE)/parser.h $(INCLUDE)/common.h - $(CC) $(FLAGS) $(CFLAGS) src/parser.c -o build/parser.o - -src/parser.c: src/parser.rl src/parser_common.rl - ragel -C -G2 src/parser.rl -o src/parser.c - - -graph: doc/parser.png - -doc/parser.png: src/parser.rl src/parser_common.rl - ragel -V -p src/parser.rl | dot -Tpng > doc/parser.png - -install: all - install -D -d /usr/local/include/anachronism/ /usr/local/lib - install -D include/anachronism/* /usr/local/include/anachronism/ - install -D build/$(SOFILE) /usr/local/lib/$(SOFILE) - install -D build/libanachronism.a /usr/local/lib/libanachronism.a - ln -s -f /usr/local/lib/$(SOFILE) /usr/local/lib/$(SONAME) - ln -s -f /usr/local/lib/$(SOFILE) /usr/local/lib/$(SO) - -uninstall: - -rm -rf /usr/local/include/anachronism - -rm /usr/local/lib/libanachronism.a - -rm /usr/local/lib/$(SOFILE) - -rm /usr/local/lib/$(SONAME) - -rm /usr/local/lib/$(SO) - -clean: - -rm -f build/nvt.o build/router.o build/parser.o - -distclean: clean - -rm -f build/libanachronism.a build/$(SOFILE) - -.PHONY: all static shared clean distclean install uninstall diff --git a/outside/anachronism/README.md b/outside/anachronism/README.md deleted file mode 100644 index 894825e045..0000000000 --- a/outside/anachronism/README.md +++ /dev/null @@ -1,158 +0,0 @@ -# Anachronism -Anachronism is a fully-compliant implementation of [the Telnet protocol][wiki-telnet]. Fallen -out of favor in this day and age, most people only know it as a command-line -tool for debugging HTTP. Today, Telnet is most commonly used in the realm of -[MUDs][wiki-muds], though there are still a few other niches filled by Telnet. - -Anachronism offers a simple API for translating between streams of data and -events, and is completely network-agnostic. Anachronism also offers **channels**, an -abstraction layer which treats Telnet as a data multiplexer. Channels make it -extremely easy to build reusable modules for Telnet sub-protocols such -as MCCP (MUD Client Compression Protocol), which can be written once and plugged -into any application that wants to include support. - -[wiki-telnet]: http://en.wikipedia.org/wiki/Telnet (Telnet at Wikipedia) -[wiki-muds]: http://en.wikipedia.org/wiki/MUD (MUDs at Wikipedia) - -## Installation -While Anachronism has no dependencies and is theoretically cross-platform, I've -only written a Makefile for Linux. Help would be appreciated for making this -work across more platforms. - - make - sudo make install - -This will install Anachronism's shared and static libraries to /usr/local/lib, -and its header files to /usr/local/include/anachronism/. You may also need to -run `ldconfig` to make Anachronism available to your project's compiler/linker. - -## Usage -The anachronism/nvt.h header can be consulted for more complete documentation. - -### Basic usage -The core type exposed by Anachronism is the telnet\_nvt, which represents the -Telnet RFC's "Network Virtual Terminal". An NVT is created using -telnet\_nvt\_new(). When creating an NVT, you must provide it with a set of -callbacks to send events to, and an optional void\* to store as the event -handler's context. You can use telnet\_recv() to process incoming data, and -the telnet\_send\_\*() set of functions to emit outgoing data. - - #include - #include - - void on_event(telnet_nvt* nvt, telnet_event* event) - { - switch (event->type) - { - // A data event (normal text received) - case TELNET_EV_DATA: - { - telnet_data_event* ev = (telnet_data_event*)event; - printf("[IN]: %.*s\n", ev->length, ev->data); - break; - } - - // Outgoing data emitted by the NVT - case TELNET_EV_SEND: - { - telnet_send_event* ev = (telnet_send_event*)event; - printf("[OUT]: %.*s\n", ev->length, ev->data); - break; - } - } - } - - int main() - { - // Create an NVT - telnet_nvt* nvt = telnet_nvt_new(NULL, &on_event, NULL, NULL); - - // Process some incoming data - const char* data = "foo bar baz"; - telnet_receive(nvt, (const telnet_byte*)data, strlen(data), NULL); - - // Free the NVT - telnet_nvt_free(nvt); - return 0; - } - -### Telopts -Anachronism provides an easy-to-use interface to Telnet's "telopt" functionality -via the telnet\_telopt\_*() set of functions. As telopts are negotiated and -utilized, events are sent to the telopt callback provided to telnet_nvt_new(). - - #include - #include - - void on_event(telnet_nvt* nvt, telnet_event* event) - { - switch (event->type) - { - // Outgoing data emitted by the NVT - case TELNET_EV_SEND: - { - telnet_send_event* ev = (telnet_send_event*)event; - printf("[OUT]: %.*s\n", ev->length, ev->data); - break; - } - } - } - - void on_telopt_event(telnet_nvt* nvt, telnet_byte telopt, telnet_telopt_event* event) - { - // telopt is the telopt this event was triggered for - - switch (event->type) - { - case TELNET_EV_TELOPT_TOGGLE: - telnet_telopt_toggle_event* ev = (telnet_telopt_toggle_event*)event; - // ev->where is TELNET_TELOPT_LOCAL or TELNET_TELOPT_REMOTE, - // corresponding to Telnet's WILL/WONT and DO/DONT commands. - // ev->status is TELNET_TELOPT_ON or TELNET_TELOPT_OFF. - break; - case TELNET_EV_TELOPT_FOCUS: - telnet_telopt_focus_event* ev = (telnet_telopt_focus_event*)event; - // ev->focus is 1 or 0 depending on if a subnegotiation packet has - // begun or ended. - break; - case TELNET_EV_TELOPT_DATA: - telnet_telopt_data_event* ev = (telnet_telopt_data_event*)event; - // ev->data is a pointer to the received data. - // ev->length is the length of the data buffer. - break; - } - } - - int main() - { - // Create an NVT - telnet_nvt* nvt = telnet_nvt_new(NULL, &on_event, &on_telopt_event, NULL); - - // Ask to enable a telopt locally (a WILL command) - telnet_request_enable(nvt, 230, TELNET_LOCAL); - - // Process some incoming data - const char* data = "\xFF\xFD\xE6" // IAC DO 230 (turn channel on) - "\xFF\xFA\xE6" // IAC SB 230 (switch to channel) - "foo bar baz" (send data) - "\xFF\xF0"; // IAC SE (switch to main) - telnet_receive(nvt, (const telnet_byte*)data, strlen(data), NULL); - - // Free the NVT - telnet_nvt_free(nvt); - return 0; - } - -### Interrupting - TODO: Explain how to interrupt the parser. - -## Alternatives -* [libtelnet][github-libtelnet], by Elanthis
- It incorporates a number of (rather MUD-specific) protocols by default, - though its API is quite different. - -[github-libtelnet]: https://github.com/elanthis/libtelnet (libtelnet on GitHub) - -## Credits -Someone from #startups on Freenode IRC suggested the name (I'm sure as a joke). -If you read this, remind me who you are so I can credit you properly! diff --git a/outside/anachronism/doc/channels.md b/outside/anachronism/doc/channels.md deleted file mode 100644 index bfcbf838cf..0000000000 --- a/outside/anachronism/doc/channels.md +++ /dev/null @@ -1,50 +0,0 @@ -# Telnet - -## Channels -Telnet supports data multiplexing by way of 256 built-in sub-channels, each -identified by a byte in the interval [\x00-\xFF]. By switching between -channels, you can send completely separate streams of data through the same -connection. - -All channels start out closed by default. To open a channel, one host must -request or offer a channel using IAC WILL <id> or IAC DO <id>. The remote host -then responds with IAC DO <id> or IAC WILL <id>, respectively. Alternatively, -the request may be denied using IAC DONT <id> or IAC WONT <id>, respectively. - -In order to switch to a specific channel, the IAC SB <id> sequence must -be used. All data sent afterwards will be routed through that specific channel. -To switch back to the main channel, IAC SE must be used. Note that subchannels -do not support any IAC sequences except IAC IAC (an escaped \xFF byte) and -IAC SE (return to the main channel). In particular, you cannot switch directly -from one subchannel to another: you must revert to the main channel first. - -Due to the unbiased nature of Telnet, neither side of the connection is -automatically recognized as the server or the client. However, a host may either -request a channel (as a client) or offer a channel (as a server). The WILL/WONT -commands are used in the role of server ("I will", "I wont"), while DO/DONT -are used in the role of client ("You do", "You do not"). As such, a channel -may be opened twice (even simultaneously). - -As an example, lets assume a terminal is connected to a server using Telnet. The -server offers MCCP (data compression), but wants to know what the terminal's -window size is. The following communication might occur: - - IAC DO NAWS - IAC WILL MCCP - IAC WILL NAWS - IAC SB NAWS \x50 \x00 \x50 \x00 IAC SE - IAC DO MCCP - IAC SB MCCP IAC SE - (compressed data) - -Notice that MCCP was negotiated such that the server offers the compression. -Only the server-to-client flow of data is compressed; the client would not -compress its data unless the channel was negotiated in the other direction as -well. - -In general, a specific subchannel is tied to a specific Telnet subprotocol. For -example, the EXOPL subprotocol is assigned to channel 255, so that channel -should be avoided for any other purpose. A full list of registered subprotocols -can be found on the [IANA website][1]. - -[1]: http://www.iana.org/assignments/telnet-options diff --git a/outside/anachronism/doc/parser.png b/outside/anachronism/doc/parser.png deleted file mode 100644 index b6a5e05a9e..0000000000 Binary files a/outside/anachronism/doc/parser.png and /dev/null differ diff --git a/outside/anachronism/include/anachronism/common.h b/outside/anachronism/include/anachronism/common.h deleted file mode 100644 index 9dcc157a87..0000000000 --- a/outside/anachronism/include/anachronism/common.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef ANACHRONISM_COMMON_H -#define ANACHRONISM_COMMON_H - -#include /* for size_t */ - -// Telnet bytes must be unsigned -typedef unsigned char telnet_byte; - -// Error codes returned from API functions -// Positive codes are success/notice codes. -// Nonpositive codes are errors. -// ALLOC is 0 for parity with the NULL result from malloc(). -typedef enum telnet_error -{ - TELNET_E_NOT_SUBNEGOTIABLE = -4, // The telopt is not open for subnegotiation. - TELNET_E_BAD_PARSER = -3, // The telnet_parser* passed is NULL - TELNET_E_BAD_NVT = -2, // The telnet_nvt* passed is NULL - TELNET_E_INVALID_COMMAND = -1, // The telnet_byte passed is not an allowed command in this API method - TELNET_E_ALLOC = 0, // Not enough memory to allocate essential library structures - TELNET_E_OK = 1, // Huge Success! - TELNET_E_INTERRUPT = 2, // Parser interrupted by user code. -} telnet_error; - -#endif // ANACHRONISM_COMMON_H diff --git a/outside/anachronism/include/anachronism/nvt.h b/outside/anachronism/include/anachronism/nvt.h deleted file mode 100644 index 3ab5d5a576..0000000000 --- a/outside/anachronism/include/anachronism/nvt.h +++ /dev/null @@ -1,214 +0,0 @@ -#ifndef ANACHRONISM_ANACHRONISM_H -#define ANACHRONISM_ANACHRONISM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -// predefined Telnet commands from 240-255 -enum -{ - IAC_SE = 240, - IAC_NOP, - IAC_DM, - IAC_BRK, - IAC_IP, - IAC_AO, - IAC_AYT, - IAC_EC, - IAC_EL, - IAC_GA, - IAC_SB, - IAC_WILL, - IAC_WONT, - IAC_DO, - IAC_DONT, - IAC_IAC, -}; - -typedef enum telnet_telopt_location -{ - TELNET_LOCAL, - TELNET_REMOTE, -} telnet_telopt_location; - - -/** - * NVT Events - */ - -typedef enum telnet_event_type -{ - TELNET_EV_DATA, /* A stretch of plain data was received. (data, length) */ - TELNET_EV_COMMAND, /* A simple IAC comamnd was recevied. (command) */ - TELNET_EV_WARNING, /* A non-fatal invalid sequence was received. (message, position) */ - TELNET_EV_SEND, /* Outgoing data to be sent. (data, length) */ -} telnet_event_type; - -typedef struct telnet_event -{ - telnet_event_type type; -} telnet_event; - -typedef struct telnet_data_event -{ - telnet_event SUPER_; - const telnet_byte* data; - size_t length; -} telnet_data_event; - -typedef struct telnet_command_event -{ - telnet_event SUPER_; - telnet_byte command; -} telnet_command_event; - -typedef struct telnet_warning_event -{ - telnet_event SUPER_; - const char* message; - size_t position; -} telnet_warning_event; - -typedef struct telnet_send_event -{ - telnet_event SUPER_; - const telnet_byte* data; - size_t length; -} telnet_send_event; - - -/** - * Telopt Events - */ - -typedef enum telnet_telopt_event_type -{ - TELNET_EV_TELOPT_TOGGLE, - TELNET_EV_TELOPT_FOCUS, - TELNET_EV_TELOPT_DATA, -} telnet_telopt_event_type; - -typedef struct telnet_telopt_event -{ - telnet_telopt_event_type type; -} telnet_telopt_event; - -typedef struct telnet_telopt_toggle_event -{ - telnet_telopt_event SUPER_; - telnet_telopt_location where; - unsigned char status; -} telnet_telopt_toggle_event; - -typedef struct telnet_telopt_focus_event -{ - telnet_telopt_event SUPER_; - unsigned char focus; -} telnet_telopt_focus_event; - -typedef struct telnet_telopt_data_event -{ - telnet_telopt_event SUPER_; - const telnet_byte* data; - size_t length; -} telnet_telopt_data_event; - - - -typedef struct telnet_nvt telnet_nvt; - - -typedef void (*telnet_nvt_event_callback)(telnet_nvt* nvt, telnet_event* event); -typedef void (*telnet_telopt_event_callback)(telnet_nvt* nvt, telnet_byte telopt, telnet_telopt_event* event); -typedef unsigned char (*telnet_negotiate_event_callback)(telnet_nvt* nvt, telnet_byte telopt, telnet_telopt_location where); - -/** - Creates a new Telnet NVT. - - Errors: - TELNET_E_ALLOC - Unable to allocate enough memory for the NVT. - */ -telnet_nvt* telnet_nvt_new(void* userdata, - telnet_nvt_event_callback nvt_callback, - telnet_telopt_event_callback telopt_callback, - telnet_negotiate_event_callback negotiate_callback); - -void telnet_nvt_free(telnet_nvt* nvt); - -/** - Every NVT can have some user-specific data attached, such as a user-defined struct. - This can be accessed (primarily by event callbacks) to differentiate between NVTs. - - Errors: - TELNET_E_BAD_NVT - Invalid telnet_nvt* parameter. - - Example: - // assuming a FILE was passed to telnet_nvt_new(): - FILE out = NULL; - telnet_get_userdata(nvt, (void**)&out); - */ -telnet_error telnet_get_userdata(telnet_nvt* nvt, void** udata); - -/** - Processes incoming data. - If `bytes_used` is non-NULL, it will be set to the length of the string that - was read. This is generally only useful if you use telnet_halt() in a callback. - - Errors: - TELNET_E_BAD_NVT - Invalid telnet_nvt* parameter. - TELNET_E_ALLOC - Unable to allocate destination buffer for incoming text. - TELNET_E_INTERRUPT - User code interrupted the parser. - */ -telnet_error telnet_receive(telnet_nvt* nvt, const telnet_byte* data, size_t length, size_t* bytes_used); - -/** - If currently parsing (i.e. telnet_recv() is running), interrupts the parser. - This is useful for things such as MCCP, where a Telnet sequence hails the start of - data that must be decompressed before being parsed. - - Errors: - TELNET_E_BAD_NVT - Invalid telnet_nvt* parameter. - */ -telnet_error telnet_interrupt(telnet_nvt* nvt); - - -/** - Sends a string as a stream of escaped Telnet data. - - Errors: - TELNET_E_BAD_NVT - Invalid telnet_nvt* parameter. - TELNET_E_ALLOC - Unable to allocate destination buffer for outgoing text. - */ -telnet_error telnet_send_data(telnet_nvt* nvt, const telnet_byte* data, const size_t length); - -/** - Sends a Telnet command. - - Errors: - TELNET_E_BAD_NVT - Invalid telnet_nvt* parameter. - TELNET_E_INVALID_COMMAND - The command cannot be WILL, WONT, DO, DONT, SB, or SE. - */ -telnet_error telnet_send_command(telnet_nvt* nvt, const telnet_byte command); - -/** - Sends a subnegotiation packet. - - Errors: - TELNET_E_BAD_NVT - Invalid telnet_nvt* parameter. - TELNET_E_ALLOC - Unable to allocate destination buffer for outgoing text. - */ -telnet_error telnet_send_subnegotiation(telnet_nvt* nvt, const telnet_byte option, const telnet_byte* data, const size_t length); - - -telnet_error telnet_telopt_enable(telnet_nvt* nvt, const telnet_byte telopt, telnet_telopt_location where); -telnet_error telnet_telopt_disable(telnet_nvt* nvt, const telnet_byte telopt, telnet_telopt_location where); -telnet_error telnet_telopt_status(telnet_nvt* nvt, const telnet_byte telopt, telnet_telopt_location where, unsigned char* status); - -#ifdef __cplusplus -} -#endif - -#endif // ANACHRONISM_ANACHRONISM_H diff --git a/outside/anachronism/include/anachronism/parser.h b/outside/anachronism/include/anachronism/parser.h deleted file mode 100644 index 8309ee5aec..0000000000 --- a/outside/anachronism/include/anachronism/parser.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef ANACHRONISM_PARSER_H -#define ANACHRONISM_PARSER_H - -#include - -typedef enum telnet_parser_event_type -{ - TELNET_EV_PARSER_DATA, - TELNET_EV_PARSER_COMMAND, - TELNET_EV_PARSER_OPTION, - TELNET_EV_PARSER_SUBNEGOTIATION, - TELNET_EV_PARSER_WARNING, -} telnet_parser_event_type; - -typedef struct telnet_parser_event -{ - telnet_parser_event_type type; -} telnet_parser_event; - -typedef struct telnet_parser_data_event -{ - telnet_parser_event SUPER_; - const telnet_byte* data; - size_t length; -} telnet_parser_data_event; - -typedef struct telnet_parser_command_event -{ - telnet_parser_event SUPER_; - telnet_byte command; -} telnet_parser_command_event; - -typedef struct telnet_parser_option_event -{ - telnet_parser_event SUPER_; - telnet_byte command; - telnet_byte option; -} telnet_parser_option_event; - -typedef struct telnet_parser_subnegotiation_event -{ - telnet_parser_event SUPER_; - int active; - telnet_byte option; -} telnet_parser_subnegotiation_event; - -typedef struct telnet_parser_warning_event -{ - telnet_parser_event SUPER_; - const char* message; - size_t position; -} telnet_parser_warning_event; - - - -typedef struct telnet_parser telnet_parser; - -typedef void (*telnet_parser_callback)(telnet_parser* parser, telnet_parser_event* event); - - -telnet_parser* telnet_parser_new(void* userdata, telnet_parser_callback callback); -void telnet_parser_free(telnet_parser* parser); - -telnet_error telnet_parser_get_userdata(telnet_parser* parser, void** userdata); - -telnet_error telnet_parser_parse(telnet_parser* parser, - const telnet_byte* data, - size_t length, - size_t* bytes_used); - -telnet_error telnet_parser_interrupt(telnet_parser* parser); - -#endif // ANACHRONISM_PARSER_H diff --git a/outside/anachronism/src/README.md b/outside/anachronism/src/README.md deleted file mode 100644 index 8ee6808236..0000000000 --- a/outside/anachronism/src/README.md +++ /dev/null @@ -1,6 +0,0 @@ -* parser_common.rl -
The language-agnostic Ragel grammar for the Telnet protocol. -* parser.rl -
The C implementation of the Ragel grammar. Compiled to parser.c by Ragel. -* nvt.c -
The core implementation of Anachronism's NVT and Channel constructs. diff --git a/outside/anachronism/src/nvt.c b/outside/anachronism/src/nvt.c deleted file mode 100644 index f33d93f752..0000000000 --- a/outside/anachronism/src/nvt.c +++ /dev/null @@ -1,631 +0,0 @@ -#include -#include -#include -#include - - -#define TELOPT_TOGGLE_CALLBACK(nvt, telopt, where_, status_) do { \ - if ((nvt)->telopt_callback) { \ - telnet_telopt_toggle_event ev; \ - ev.SUPER_.type = TELNET_EV_TELOPT_TOGGLE; \ - ev.where = (where_); \ - ev.status = (status_); \ - \ - (nvt)->telopt_callback((nvt), (telopt), (telnet_telopt_event*)&ev); \ - } \ -} while (0) - -#define TELOPT_FOCUS_CALLBACK(nvt, telopt, status_) do { \ - if ((nvt)->telopt_callback) { \ - telnet_telopt_focus_event ev; \ - ev.SUPER_.type = TELNET_EV_TELOPT_FOCUS; \ - ev.status = (status_); \ - \ - (nvt)->telopt_callback((nvt), (telopt), (telnet_telopt_event*)&ev); \ - } \ -} while (0) - -#define TELOPT_DATA_CALLBACK(nvt, telopt, data_, length_) do { \ - if ((nvt)->telopt_callback) { \ - telnet_telopt_data_event ev; \ - ev.SUPER_.type = TELNET_EV_TELOPT_DATA; \ - ev.data = (data_); \ - ev.length = (length_); \ - \ - (nvt)->telopt_callback((nvt), (telopt), (telnet_telopt_event*)&ev); \ - } \ -} while (0) - -#define SEND_CALLBACK(nvt, data_, length_) do { \ - if ((nvt)->callback) { \ - telnet_send_event ev; \ - ev.SUPER_.type = TELNET_EV_SEND; \ - ev.data = (data_); \ - ev.length = (length_); \ - \ - (nvt)->callback((nvt), (telnet_event*)&ev); \ - } \ -} while (0) - - -// Q Method of Implementing TELNET Option Negotiation -// ftp://ftp.rfc-editor.org/in-notes/rfc1143.txt -typedef enum qstate { - Q_NO = 0, Q_WANTYES, Q_WANTYESNO, - Q_YES, Q_WANTNO, Q_WANTNOYES, -} qstate; - -typedef struct telnet_qstate -{ - unsigned remote : 3; - unsigned local : 3; -} telnet_qstate; - -struct telnet_nvt -{ - telnet_parser* parser; - telnet_qstate options[256]; // track the state of each subnegotiation option - short current_remote; - - telnet_nvt_event_callback callback; - telnet_telopt_event_callback telopt_callback; - telnet_negotiate_event_callback negotiate_callback; - - void* userdata; -}; - -static unsigned char telopt_status(telnet_nvt* nvt, - telnet_byte telopt, - telnet_telopt_location where) -{ - unsigned int qval = (where == TELNET_LOCAL) ? - nvt->options[telopt].local : - nvt->options[telopt].remote; - - switch (qval) { - case Q_YES: case Q_WANTNO: case Q_WANTNOYES: - return 1; - default: - return 0; - } -} -#define telopt_subnegotiable(nvt, telopt) (telopt_status((nvt), (telopt), TELNET_REMOTE) || telopt_status((nvt), (telopt), TELNET_LOCAL)) - - -static void send_option(telnet_nvt* nvt, telnet_byte command, telnet_byte telopt) -{ - const telnet_byte buf[] = {IAC_IAC, command, telopt}; - SEND_CALLBACK(nvt, buf, 3); -} - -static void process_option_event(telnet_nvt* nvt, - telnet_byte command, - telnet_byte telopt) -{ - telnet_qstate* q = &nvt->options[telopt]; - // Every qstate begins zeroed-out, and Q_NO is 0. - - switch (command) - { - case IAC_WILL: - switch (q->remote) - { - case Q_NO: - if (nvt->negotiate_callback && nvt->negotiate_callback(nvt, telopt, TELNET_REMOTE)) { - send_option(nvt, IAC_DO, telopt); - q->remote = Q_YES; - TELOPT_TOGGLE_CALLBACK(nvt, telopt, TELNET_REMOTE, 1); - } else { - send_option(nvt, IAC_DONT, telopt); - } - break; - case Q_WANTNO: - // error - q->remote = Q_NO; - break; - case Q_WANTNOYES: - // error - q->remote = Q_YES; - TELOPT_TOGGLE_CALLBACK(nvt, telopt, TELNET_REMOTE, 1); - break; - case Q_WANTYES: - q->remote = Q_YES; - TELOPT_TOGGLE_CALLBACK(nvt, telopt, TELNET_REMOTE, 1); - break; - case Q_WANTYESNO: - send_option(nvt, IAC_DONT, telopt); - q->remote = Q_WANTNO; - TELOPT_TOGGLE_CALLBACK(nvt, telopt, TELNET_REMOTE, 1); - break; - } - break; - case IAC_WONT: - switch (q->remote) - { - case Q_YES: - send_option(nvt, IAC_DONT, telopt); - q->remote = Q_NO; - TELOPT_TOGGLE_CALLBACK(nvt, telopt, TELNET_REMOTE, 0); - break; - case Q_WANTNO: - q->remote = Q_NO; - break; - case Q_WANTNOYES: - send_option(nvt, IAC_DO, telopt); - q->remote = Q_WANTYES; - break; - case Q_WANTYES: - q->remote = Q_NO; - break; - case Q_WANTYESNO: - q->remote = Q_NO; - break; - } - break; - case IAC_DO: - switch (q->local) - { - case Q_NO: - if (nvt->negotiate_callback && nvt->negotiate_callback(nvt, telopt, TELNET_LOCAL)) { - send_option(nvt, IAC_WILL, telopt); - q->local = Q_YES; - TELOPT_TOGGLE_CALLBACK(nvt, telopt, TELNET_LOCAL, 1); - } else { - send_option(nvt, IAC_WONT, telopt); - } - break; - case Q_WANTNO: - // error - q->local = Q_NO; - break; - case Q_WANTNOYES: - // error - q->local = Q_YES; - TELOPT_TOGGLE_CALLBACK(nvt, telopt, TELNET_LOCAL, 1); - break; - case Q_WANTYES: - q->local = Q_YES; - TELOPT_TOGGLE_CALLBACK(nvt, telopt, TELNET_LOCAL, 1); - break; - case Q_WANTYESNO: - send_option(nvt, IAC_WONT, telopt); - q->local = Q_WANTNO; - TELOPT_TOGGLE_CALLBACK(nvt, telopt, TELNET_LOCAL, 1); - break; - } - break; - case IAC_DONT: - switch (q->local) - { - case Q_YES: - send_option(nvt, IAC_DONT, telopt); - q->local = Q_NO; - TELOPT_TOGGLE_CALLBACK(nvt, telopt, TELNET_LOCAL, 0); - break; - case Q_WANTNO: - q->local = Q_NO; - break; - case Q_WANTNOYES: - send_option(nvt, IAC_WILL, telopt); - q->local = Q_WANTYES; - break; - case Q_WANTYES: - q->local = Q_NO; - break; - case Q_WANTYESNO: - q->local = Q_NO; - break; - } - break; - } -} - -static void process_data_event(telnet_nvt* nvt, - const telnet_byte* data, - size_t length) -{ - if (nvt->current_remote == -1) { - // Main-line data - if (nvt->callback) { - telnet_data_event ev; - ev.SUPER_.type = TELNET_EV_DATA; - ev.data = data; - ev.length = length; - nvt->callback(nvt, (telnet_event*)&ev); - } - } else { - // Telopt data - telnet_byte telopt = (telnet_byte)nvt->current_remote; - - if (nvt->telopt_callback) { - // Make sure the telopt is enabled - if (telopt_subnegotiable(nvt, telopt)) { - telnet_telopt_data_event ev; - ev.SUPER_.type = TELNET_EV_TELOPT_DATA; - ev.data = data; - ev.length = length; - nvt->telopt_callback(nvt, telopt, (telnet_telopt_event*)&ev); - } - } - } -} - -static void process_subnegotiation_event(telnet_nvt* nvt, - int open, - telnet_byte telopt) -{ - if (open) { - nvt->current_remote = telopt; - } else { - nvt->current_remote = -1; - } - - if (nvt->telopt_callback) { - // Make sure the telopt is enabled - if (telopt_subnegotiable(nvt, telopt)) { - telnet_telopt_focus_event ev; - ev.SUPER_.type = TELNET_EV_TELOPT_FOCUS; - ev.focus = open; - nvt->telopt_callback(nvt, telopt, (telnet_telopt_event*)&ev); - } - } -} - -static void process_event(telnet_parser* parser, telnet_parser_event* event) -{ - telnet_nvt* nvt = NULL; - telnet_parser_get_userdata(parser, (void*)&nvt); - - switch (event->type) - { - case TELNET_EV_PARSER_DATA: - { - telnet_parser_data_event* ev = (telnet_parser_data_event*)event; - process_data_event(nvt, ev->data, ev->length); - break; - } - - case TELNET_EV_PARSER_OPTION: - { - telnet_parser_option_event* ev = (telnet_parser_option_event*)event; - process_option_event(nvt, ev->command, ev->option); - break; - } - - case TELNET_EV_PARSER_SUBNEGOTIATION: - { - telnet_parser_subnegotiation_event* ev = (telnet_parser_subnegotiation_event*)event; - process_subnegotiation_event(nvt, ev->active, ev->option); - break; - } - - case TELNET_EV_PARSER_COMMAND: - { - if (nvt->callback) { - telnet_parser_command_event* parser_ev = (telnet_parser_command_event*) event; - - telnet_command_event ev; - ev.SUPER_.type = TELNET_EV_COMMAND; - ev.command = parser_ev->command; - nvt->callback(nvt, (telnet_event*)&ev); - } - break; - } - - case TELNET_EV_PARSER_WARNING: - { - if (nvt->callback) { - telnet_parser_warning_event* parser_ev = (telnet_parser_warning_event*) event; - - telnet_warning_event ev; - ev.SUPER_.type = TELNET_EV_WARNING; - ev.message = parser_ev->message; - ev.position = parser_ev->position; - nvt->callback(nvt, (telnet_event*)&ev); - } - break; - } - - default: - break; - } -} - - -telnet_nvt* telnet_nvt_new(void* userdata, - telnet_nvt_event_callback nvt_callback, - telnet_telopt_event_callback telopt_callback, - telnet_negotiate_event_callback negotiate_callback) -{ - telnet_nvt* nvt = malloc(sizeof(telnet_nvt)); - if (nvt) - { - telnet_parser* parser = telnet_parser_new((void*)nvt, &process_event); - if (parser) - { - memset(nvt, 0, sizeof(*nvt)); - nvt->parser = parser; - nvt->callback = nvt_callback; - nvt->telopt_callback = telopt_callback; - nvt->negotiate_callback = negotiate_callback; - nvt->userdata = userdata; - nvt->current_remote = -1; - } - else - { - free(nvt); - nvt = NULL; - } - } - return nvt; -} - -void telnet_nvt_free(telnet_nvt* nvt) -{ - if (nvt) - { - telnet_parser_free(nvt->parser); - free(nvt); - } -} - -telnet_error telnet_get_userdata(telnet_nvt* nvt, void** userdata) -{ - if (!nvt) - return TELNET_E_BAD_NVT; - - *userdata = nvt->userdata; - return TELNET_E_OK; -} - -telnet_error telnet_receive(telnet_nvt* nvt, const telnet_byte* data, size_t length, size_t* bytes_used) -{ - if (!nvt) - return TELNET_E_BAD_NVT; - - return telnet_parser_parse(nvt->parser, data, length, bytes_used); -} - -telnet_error telnet_interrupt(telnet_nvt* nvt) -{ - if (!nvt) - return TELNET_E_BAD_NVT; - - return telnet_parser_interrupt(nvt->parser); -} - - -static int safe_concat(const telnet_byte* in, size_t inlen, telnet_byte* out, size_t outlen) -{ - // Copy as much as possible into the buffer. - memcpy(out, in, (outlen < inlen) ? outlen : inlen); - - // true if everything could be copied, false otherwise - return outlen >= inlen; -} - -// Escapes any special characters in data, writing the result data to out. -// Returns -1 if not everything could be copied (and out is full). -// Otherwise returns the length of the data in out. -// -// To avoid potential -1 return values, pass in an out buffer double the length of the data buffer. -static size_t telnet_escape(const telnet_byte* data, size_t length, telnet_byte* out, size_t outsize) -{ - if (data == NULL || out == NULL) - return 0; - - size_t outlen = 0; - size_t left = 0; - size_t right = 0; - const char* seq = NULL; - for (; right < length; ++right) - { - switch (data[right]) - { - case IAC_IAC: - seq = "\xFF\xFF"; - break; - case '\r': - // Only escape \r if it doesn't immediately precede \n. - if (right + 1 >= length || data[right+1] != '\n') - { - seq = "\r\0"; - break; - } - // !!FALLTHROUGH!! - default: - continue; // Move to the next character - } - - // Add any normal data that hasn't been added yet. - if (safe_concat(data+left, right-left, out+outlen, outsize-outlen) == 0) - return -1; - outlen += right - left; - left = right + 1; - - // Add the escape sequence. - if (safe_concat((const telnet_byte*)seq, 2, out+outlen, outsize-outlen) == 0) - return -1; - outlen += 2; - } - - // Add any leftover normal data. - if (left < right) - { - if (safe_concat(data+left, right-left, out+outlen, outsize-outlen) == 0) - return -1; - outlen += right - left; - } - - return outlen; -} - -telnet_error telnet_send_data(telnet_nvt* nvt, const telnet_byte* data, const size_t length) -{ - if (!nvt) - return TELNET_E_BAD_NVT; - else if (!nvt->callback) - return TELNET_E_OK; // immediate success since they apparently don't want the data to go anywhere - - // Due to the nature of the protocol, the most any one byte can be encoded as is two bytes. - // Hence, the smallest buffer guaranteed to contain any input is double the length of the source. - size_t bufsize = sizeof(telnet_byte) * length * 2; - telnet_byte* buf = malloc(bufsize); - if (!buf) - return TELNET_E_ALLOC; - - bufsize = telnet_escape(data, length, buf, bufsize); - - SEND_CALLBACK(nvt, buf, bufsize); - - free(buf); - buf = NULL; - - return TELNET_E_OK; -} - -telnet_error telnet_send_command(telnet_nvt* nvt, const telnet_byte command) -{ - if (!nvt) - return TELNET_E_BAD_NVT; - else if (command >= IAC_SB || command == IAC_SE) - return TELNET_E_INVALID_COMMAND; // Invalid command - - const telnet_byte buf[] = {IAC_IAC, command}; - SEND_CALLBACK(nvt, buf, 2); - - return TELNET_E_OK; -} - -telnet_error telnet_send_subnegotiation(telnet_nvt* nvt, const telnet_byte option, const telnet_byte* data, const size_t length) -{ - if (!nvt) - return TELNET_E_BAD_NVT; - else if (!telopt_subnegotiable(nvt, option)) - return TELNET_E_NOT_SUBNEGOTIABLE; - else if (!nvt->callback) - return TELNET_E_OK; - - // length*2 is the maximum buffer size needed for an escaped string. - // The extra five bytes are for the IAC, SB,