Skip to content
Browse files

kill off JuliaWebRepl and nginx. add uv.a and julia.h to installed ou…

…tputs
  • Loading branch information...
1 parent 62c9a59 commit de88a2ebfa1ab3e824b9ca0bca879da6ad5a09c0 @vtjnash vtjnash committed Mar 15, 2013
Showing with 43 additions and 16,706 deletions.
  1. +0 −3 .gitmodules
  2. +5 −13 Makefile
  3. +34 −0 contrib/mac-gtk.sh
  4. +1 −4 contrib/windows/prepare-julia-env.bat
  5. +0 −1 deps/.gitignore
  6. +1 −57 deps/Makefile
  7. +1 −1 deps/libuv
  8. +0 −1 deps/nginx
  9. +0 −10 extras/Makefile
  10. +0 −241 extras/julia_web.jl
  11. +0 −219 extras/julia_web_base.jl
  12. +1 −0 src/julia.expmap
  13. +0 −5 ui/webserver/.gitignore
  14. +0 −59 ui/webserver/Makefile
  15. +0 −1,857 ui/webserver/json.h
  16. +0 −4,230 ui/webserver/jsoncpp.cpp
  17. +0 −12 ui/webserver/launch-julia-webserver
  18. +0 −39 ui/webserver/launch-julia-webserver.bat
  19. +0 −120 ui/webserver/message_types.h
  20. +0 −34 ui/webserver/nginx-win.conf
  21. +0 −35 ui/webserver/nginx.conf
  22. +0 −669 ui/webserver/server.cpp
  23. +0 −116 ui/webserver/server.h
  24. +0 −1,122 ui/webserver/webserver.cpp
  25. BIN ui/website/assets/favicon.psd
  26. BIN ui/website/assets/logo_dark.psd
  27. BIN ui/website/assets/logo_light.psd
  28. +0 −4,676 ui/website/d3.js
  29. BIN ui/website/favicon.ico
  30. BIN ui/website/images/banner.png
  31. BIN ui/website/images/bullet.png
  32. BIN ui/website/images/logo.png
  33. BIN ui/website/images/slogan.png
  34. +0 −100 ui/website/index.css
  35. +0 −36 ui/website/index.htm
  36. +0 −167 ui/website/index.js
  37. +0 −274 ui/website/jquery.autoresize.js
  38. +0 −4 ui/website/jquery.js
  39. +0 −23 ui/website/jquery.json.js
  40. +0 −26 ui/website/layout.js
  41. +0 −96 ui/website/localstorage.js
  42. +0 −1,265 ui/website/modernizr-2.5.3.js
  43. +0 −170 ui/website/repl.css
  44. +0 −52 ui/website/repl.htm
  45. +0 −920 ui/website/repl.js
  46. +0 −1 ui/website/repl.scgi
  47. +0 −48 ui/website/reset.css
View
3 .gitmodules
@@ -4,9 +4,6 @@
[submodule "deps/openlibm"]
path = deps/openlibm
url = git://github.com/JuliaLang/openlibm.git
-[submodule "deps/nginx"]
- path = deps/nginx
- url = git://github.com/git-mirror/nginx
[submodule "deps/Rmath"]
path = deps/Rmath
url = git://github.com/JuliaLang/Rmath.git
View
18 Makefile
@@ -25,7 +25,6 @@ julia-debug julia-release:
@$(MAKE) $(QUIET_MAKE) -C deps
@$(MAKE) $(QUIET_MAKE) -C src lib$@
@$(MAKE) $(QUIET_MAKE) -C base
- @$(MAKE) $(QUIET_MAKE) -C extras
@$(MAKE) $(QUIET_MAKE) -C ui $@
@ln -sf $(BUILD)/bin/$@-$(DEFAULT_REPL) julia
@@ -55,8 +54,8 @@ JL_PRIVATE_LIBS = amd arpack cholmod colamd fftw3 fftw3f fftw3_threads \
umfpack z openblas
PREFIX ?= julia-$(JULIA_COMMIT)
-install: release webrepl
- @for subdir in "sbin" "bin" "etc" "libexec" $(JL_LIBDIR) $(JL_PRIVATE_LIBDIR) "share/julia" ; do \
+install: release
+ @for subdir in "bin" "libexec" $(JL_LIBDIR) $(JL_PRIVATE_LIBDIR) "share/julia" "include/julia" ; do \
mkdir -p $(PREFIX)/$$subdir ; \
done
ifeq ($(OS), Darwin)
@@ -72,11 +71,12 @@ endif
-for suffix in $(JL_PRIVATE_LIBS) ; do \
cp -a $(BUILD)/lib/lib$${suffix}*.$(SHLIB_EXT)* $(PREFIX)/$(JL_PRIVATE_LIBDIR) ; \
done
+ cp -a $(BUILD)/lib/libuv.a $(PREFIX)/$(JL_PRIVATE_LIBDIR)
+ cp -a src/julia.h $(BUILD)/include/uv* $(PREFIX)/include/julia
# Copy system image
cp $(BUILD)/$(JL_PRIVATE_LIBDIR)/sys.ji $(PREFIX)/$(JL_PRIVATE_LIBDIR)
# Copy in all .jl sources as well
cp -R -L $(BUILD)/share/julia $(PREFIX)/share/
- -cp $(BUILD)/etc/nginx.conf $(PREFIX)/etc/
ifeq ($(OS), WINNT)
-cp $(JULIAHOME)/contrib/windows/* $(PREFIX)
endif
@@ -91,7 +91,6 @@ ifeq ($(OS), Darwin)
-./contrib/fixup-libgfortran.sh $(PREFIX)/$(JL_PRIVATE_LIBDIR)
endif
ifeq ($(OS), WINNT)
- cp -R $(BUILD)/sbin $(PREFIX)
-[ -e dist-extras/7za.exe ] && cp dist-extras/7za.exe $(PREFIX)/bin/7z.exe
-[ -e dist-extras/PortableGit-1.8.0-preview20121022.7z ] && \
mkdir $(PREFIX)/Git && \
@@ -113,7 +112,6 @@ endif
clean: | $(CLEAN_TARGETS)
@$(MAKE) -C base clean
- @$(MAKE) -C extras clean
@$(MAKE) -C src clean
@$(MAKE) -C ui clean
@for buildtype in "release" "debug" ; do \
@@ -131,7 +129,7 @@ cleanall: clean
# @$(MAKE) -C deps clean-uv
.PHONY: default debug release julia-debug julia-release \
- test testall test-* clean cleanall webrepl \
+ test testall test-* clean cleanall \
run-julia run-julia-debug run-julia-release
test: release
@@ -143,12 +141,6 @@ testall: release
test-%: release
@$(MAKE) $(QUIET_MAKE) -C test $*
-webrepl: all
-ifeq ($(USE_SYSTEM_NGINX), 0)
- @$(MAKE) $(QUIET_MAKE) -C deps install-nginx
-endif
- @$(MAKE) -C ui/webserver julia-release
-
# download target for some hardcoded windows dependencies
.PHONY: win-extras
win-extras:
View
34 contrib/mac-gtk.sh
@@ -0,0 +1,34 @@
+#/bin/sh
+
+# This script will attempt to download and build GTK+-3,
+# including dependencies, in ~/gtk (also puts stuff in
+# ~/.local, ~/Source, ~/.jhbuildrc*)
+# While this should work, it may be preferable to execute
+# each line separately in the terminal
+
+curl -O https://raw.github.com/jralls/gtk-osx-build/master/gtk-osx-build-setup.sh
+sh gtk-osx-build-setup.sh
+export PATH=$PATH:~/.local/bin/
+sed -i -e 's/^setup_sdk/#setup_sdk/g' ~/.jhbuildrc-custom
+cat << EOF >> .jhbuildrc-custom
+setup_sdk(target=_target, sdk_version=_target, architectures=[_default_arch])
+os.environ["DYLD_LIBRARY_PATH"] = ""
+build_policy = "updated-deps"
+modules = [ "meta-gtk-osx-bootstrap",
+ "freetype", "fontconfig",
+ "meta-gtk-osx-core",
+ "meta-gtk-osx-themes",
+ "gtk-quartz-engine" ]
+EOF
+
+jhbuild bootstrap --skip=libiconv --ignore-system
+jhbuild build
+
+cd ~/gtk/source
+curl -O http://ftp.gnome.org/pub/gnome/sources/gtk-mac-bundler/0.6/gtk-mac-bundler-0.6.1.tar.bz2
+tar jxvf gtk-mac-bundler-0.6.1.tar.bz2
+cd gtk-mac-bundler-0.6.1
+make install
+cd ~/gtk
+
+
View
5 contrib/windows/prepare-julia-env.bat
@@ -7,7 +7,7 @@
@rem
set SYS_PATH=%PATH%
-set PATH=%~dp0bin;%~dp0usr\bin;%~dp0..\usr\bin;%~dp0..\..\usr\bin
+set PATH=%~dp0bin;%~dp0usr\bin;%~dp0..\usr\bin;%~dp0..\..\usr\bin;%SYS_PATH%
set JULIA_EXE=julia-release-readline.exe
for %%A in (%JULIA_EXE%) do set JULIA_HOME=%%~dp$PATH:A
set JULIA=%JULIA_HOME%%JULIA_EXE%
@@ -16,7 +16,4 @@ set HOME=%APPDATA%\julia
set JL_PRIVATE_LIBDIR=lib\julia
set JULIA_EDITOR=start
-@rem for issue #2124:
-set OPENBLAS_NUM_THREADS=1
-
if not exist "%JULIA_HOME%..\lib\julia\sys.ji" (echo "Preparing Julia for first launch. This may take a while" && echo "You may see two git related errors. This is completely normal" && cd "%JULIA_HOME%..\share\julia\base" && "%JULIA%" -b sysimg.jl && popd && pushd "%cd%")
View
1 deps/.gitignore
@@ -14,7 +14,6 @@
/libunwind-*
/lighttpd-*
/llvm-*
-/nginx-*
/openblas-*
/patchelf-*
/pcre-*
View
58 deps/Makefile
@@ -385,7 +385,7 @@ $(UV_OBJ_TARGET): $(UV_OBJ_SOURCE)
cp -r libuv/include/* $(BUILD)/include
clean-uv:
- -$(MAKE) -C libuv clean uname_S=$(uname_S)
+ -$(MAKE) clean $(LIBUV_MAKE_FLAGS)
-rm -rf $(BUILD)/lib/libuv.a $(BUILD)/include/uv.h $(BUILD)/include/uv-private
distclean-uv: clean-uv
@@ -1095,62 +1095,6 @@ get-unwind: libunwind-$(UNWIND_VER).tar.gz
configure-unwind: libunwind-$(UNWIND_VER)/config.status
compile-unwind: $(LIBUNWIND_TARGET_SOURCE)
check-unwind: libunwind-$(UNWIND_VER)/checked
-install-unwind: $(LIBUNWIND_TARGET_OBJ)
-
-
-## NGINX ##
-
-ifneq ($(OS), WINNT)
-NGINX_OBJ_TARGET = $(BUILD)/sbin/nginx
-NGINX_SRC_TARGET = nginx/objs/nginx
-NGINX_FLAGS = --with-ld-opt="-L'$(BUILD)/lib' -lpcre -Wl,-rpath,'$(BUILD)/lib' $(RPATH)"
-
-nginx/.gitignore:
- rm -f $@
- for x in .gitignore Makefile config.status objs; do echo /$$x >> $@; done
-nginx/auto/configure: | compile-pcre
- (cd .. && git submodule update --init)
- touch -c $@
-nginx/config.status: nginx/auto/configure nginx/.gitignore
- cd nginx && \
- ./auto/configure --without-http_gzip_module --without-http_rewrite_module $(NGINX_FLAGS) --with-debug --prefix=".."
- echo 1 > $@
-$(NGINX_SRC_TARGET): nginx/config.status nginx/.gitignore
- $(MAKE) -C nginx
- touch -c $@
-$(NGINX_OBJ_TARGET): $(NGINX_SRC_TARGET) nginx/.gitignore
- $(MAKE) -C nginx install DESTDIR="$(abspath $(BUILD)/bin)/"
- touch -c $@
-
-clean-nginx:
- -$(MAKE) -C nginx clean
-distclean-nginx:
- -rm -rf nginx
-
-get-nginx: nginx/auto/configure
-configure-nginx: nginx/config.status
-compile-nginx: $(NGINX_SRC_TARGET)
-check-nginx: $(NGINX_SRC_TARGET)
-install-nginx: $(NGINX_OBJ_TARGET)
-else
-NGINX_VER=1.2.6
-NGINX_SRC_TARGET = nginx-$(NGINX_VER).zip
-NGINX_OBJ_TARGET = nginx-$(NGINX_VER)/nginx.exe
-$(NGINX_SRC_TARGET):
- $(WGET) http://nginx.org/download/$@
-$(NGINX_OBJ_TARGET): $(NGINX_SRC_TARGET)
- unzip $<
- touch -c $@
-$(BUILD)/sbin/nginx.exe: $(NGINX_OBJ_TARGET)
- mkdir -p $(BUILD)/sbin
- cp -a nginx-$(NGINX_VER)/* $(BUILD)/sbin
- touch -c $@
-get-nginx: $(NGINX_SRC_TARGET)
-configure-nginx: get-nginx
-compile-nginx: $(NGINX_OBJ_TARGET)
-check-nginx: compile-nginx
-install-nginx: $(BUILD)/sbin/nginx.exe
-endif
## GMP ##
2 deps/libuv
@@ -1 +1 @@
-Subproject commit 1c5b9d80a08aa8b418cc8e57e99dc25f785805d1
+Subproject commit d469f03eda6c95f064be3c25b7a9e9a7547c7617
1 deps/nginx
@@ -1 +0,0 @@
-Subproject commit e0235968fc75df45482929b0312dfd7a0b199520
View
10 extras/Makefile
@@ -1,10 +0,0 @@
-JULIAHOME = $(abspath ..)
-include $(JULIAHOME)/Make.inc
-
-all: webrepl_msgtypes_h.jl
-
-webrepl_msgtypes_h.jl: ../ui/webserver/message_types.h
- $(QUIET_PERL) $(CC) -E -Dnotdefined $^ > $@
-
-clean:
- rm -f webrepl_msgtypes_h.jl
View
241 extras/julia_web.jl
@@ -1,241 +0,0 @@
-###########################################
-# plotting functions
-###########################################
-
-# number of points to plot for functions
-const __PLOT_POINTS = 450
-
-# the aspect ratio of plots
-const __PLOT_ASPECT_RATIO = 1.95
-
-# how similar the domain and range needs to be for aspect ratio preservation
-const __PRESERVE_ASPECT_RATIO_THRESHOLD = 0.05
-
-# how much extra padding to add around the plot
-const __HORIZONTAL_PADDING = 0.05
-const __VERTICAL_PADDING = 0.05
-
-# helper functions
-function __safe_min(x::Array{Float64, 1})
- m = NaN
- for i=1:length(x)
- if x[i] != Inf && x[i] != -Inf && !isequal(x[i], NaN)
- if isequal(m, NaN) || x[i] < m
- m = x[i]
- end
- end
- end
- if isequal(m, NaN)
- return error("unable to determine window dimensions")
- end
- return m
-end
-
-function __safe_max(x::Array{Float64, 1})
- m = NaN
- for i=1:length(x)
- if x[i] != Inf && x[i] != -Inf && !isequal(x[i], NaN)
- if isequal(m, NaN) || x[i] > m
- m = x[i]
- end
- end
- end
- if isequal(m, NaN)
- return error("unable to determine window dimensions")
- end
- return m
-end
-
-# plot an array (window determined manually)
-
-plot(x::Array, y::Array, xmin::Number, xmax::Number, ymin::Number, ymax::Number) =
- plot(x, y, xmin, xmax, ymin, ymax, "line")
-
-function plot(x::Array, y::Array, xmin::Number, xmax::Number, ymin::Number, ymax::Number, plottype::String)
- # make sure we have arrays of numbers
- x_safe = try convert(Array{Float64, 1}, x[:]) catch error("x coordinates must be convertable to float64") end
- y_safe = try convert(Array{Float64, 1}, y[:]) catch error("y coordinates must be convertable to float64") end
-
- # make sure there are the same number of x and y coordinates
- if length(x_safe) != length(y_safe) return error("size of x and y arrays must be equal") end
-
- # make sure there are enough data to plot
- if length(x_safe) < 1 return error("at least two data points required for line plot") end
-
- # make sure the window is okay
- if xmin == Inf || xmin == -Inf || isequal(xmin, NaN) return error(string("invalid xmin: ", string(xmin))) end
- if xmax == Inf || xmax == -Inf || isequal(xmax, NaN) return error(string("invalid xmax: ", string(xmax))) end
- if ymin == Inf || ymin == -Inf || isequal(ymin, NaN) return error(string("invalid ymin: ", string(ymin))) end
- if ymax == Inf || ymax == -Inf || isequal(ymax, NaN) return error(string("invalid ymax: ", string(ymax))) end
- if xmin >= xmax return error("xmax must be greater than xmin") end
- if ymin >= ymax return error("ymax must be greater than ymin") end
-
- # remove points with infinite or NaN components
- pairs = {}
- for i=1:length(x_safe)
- if x_safe[i] != Inf && x_safe[i] != -Inf && !isequal(x_safe[i], NaN)
- if y_safe[i] != Inf && y_safe[i] != -Inf && !isequal(y_safe[i], NaN)
- pairs = [pairs, {(x_safe[i], y_safe[i])}]
- end
- end
- end
- x_safe = [pairs[i][1] for i=1:length(pairs)]
- y_safe = [pairs[i][2] for i=1:length(pairs)]
-
- # send the message to the browser
- __write_message(__Message(__MSG_OUTPUT_PLOT, {
- plottype,
- string("[", join([string(i) for i=x_safe], ","), "]"),
- string("[", join([string(i) for i=y_safe], ","), "]"),
- string(float64(xmin)),
- string(float64(xmax)),
- string(float64(ymin)),
- string(float64(ymax))
- }))
-end
-
-# plot an array (window determined automatically)
-
-plot(x::Array, y::Array) = plot(x, y, "line")
-
-function plot(x::Array, y::Array, plottype::String)
- # make sure we have arrays of numbers
- x_safe = try convert(Array{Float64, 1}, x[:]) catch error("x coordinates must be convertable to float64") end
- y_safe = try convert(Array{Float64, 1}, y[:]) catch error("y coordinates must be convertable to float64") end
-
- # make sure there are the same number of x and y coordinates
- if length(x_safe) != length(y_safe) return error("size of x and y arrays must be equal") end
-
- # make sure there are enough data to plot
- if length(x_safe) < 1 return error("at least two data points required for line plot") end
-
- # determine the window
- xmin = __safe_min(x_safe)
- xmax = __safe_max(x_safe)
- ymin = __safe_min(y_safe)
- ymax = __safe_max(y_safe)
- if xmin == xmax
- xmin -= 0.5
- xmax += 0.5
- end
- if ymin == ymax
- ymin -= 0.5
- ymax += 0.5
- end
-
- # determine if we want to preserve the aspect ratio
- if abs((ymax-ymin)/(xmax-xmin)-1) < __PRESERVE_ASPECT_RATIO_THRESHOLD
- # we do -- determine the center of the plot
- cx = (xmax+xmin)/2.0
- cy = (ymax+ymin)/2.0
-
- # determine how big the window is
- w = max(xmax-xmin, ymax-ymin)/2.0
- wx = w+2.0*w*__HORIZONTAL_PADDING
- wy = w+2.0*w*__VERTICAL_PADDING
-
- # add some horizontal padding to preserve the aspect ratio
- plot(x_safe, y_safe, cx-wx*__PLOT_ASPECT_RATIO, cx+wx*__PLOT_ASPECT_RATIO, cy-wy, cy+wy, plottype)
- else
- # nope -- just add some padding
- plot(x_safe, y_safe,
- xmin-(xmax-xmin)*__HORIZONTAL_PADDING,
- xmax+(xmax-xmin)*__HORIZONTAL_PADDING,
- ymin-(ymax-ymin)*__VERTICAL_PADDING,
- ymax+(ymax-ymin)*__VERTICAL_PADDING,
- plottype)
- end
-end
-
-# plot an array (window determined automatically)
-
-plot(y::Array) = plot(y, "line")
-
-function plot(y::Array, plottype)
- # make sure we have an array of numbers
- y_safe = try convert(Array{Float64, 1}, y[:]) catch error("y coordinates must be convertable to float64") end
-
- # make sure there are enough data to plot
- if length(y_safe) < 1 return error("at least two data points required for line plot") end
-
- # don't use +/-Inf or NaN when determining window
- for i=1:length(y_safe)
- if y_safe[i] == Inf || y_safe[i] == -Inf || isequal(y_safe[i], NaN)
- y_safe[i] = 0.0
- end
- end
-
- # determine the window
- x_safe = [i-1 for i=1:length(y_safe)]
- xmin = 0
- xmax = length(y)-1
- ymin = __safe_min(y_safe)
- ymax = __safe_max(y_safe)
- if ymin == ymax
- ymin -= 0.5
- ymax += 0.5
- end
-
- # determine if we want to preserve the aspect ratio
- if abs((ymax-ymin)/(xmax-xmin)-1) < __PRESERVE_ASPECT_RATIO_THRESHOLD
- # we do -- determine the center of the plot
- cx = (xmax+xmin)/2.0
- cy = (ymax+ymin)/2.0
-
- # determine how big the window is
- w = max(xmax-xmin, ymax-ymin)/2.0
- wx = w+2.0*w*__HORIZONTAL_PADDING
- wy = w+2.0*w*__VERTICAL_PADDING
-
- # add some horizontal padding to preserve the aspect ratio
- plot(x_safe, y_safe, cx-wx*__PLOT_ASPECT_RATIO, cx+wx*__PLOT_ASPECT_RATIO, cy-wy, cy+wy, plottype)
- else
- # nope -- just add some padding
- plot(x_safe, y_safe,
- xmin-(xmax-xmin)*__HORIZONTAL_PADDING,
- xmax+(xmax-xmin)*__HORIZONTAL_PADDING,
- ymin-(ymax-ymin)*__VERTICAL_PADDING,
- ymax+(ymax-ymin)*__VERTICAL_PADDING,
- plottype)
- end
-end
-
-# plot a function (vertical window determined automatically)
-
-plot(f::Function, xmin::Number, xmax::Number) = plot(f, xmin, xmax, "line")
-
-function plot(f::Function, xmin::Number, xmax::Number, plottype::String)
- # make sure the window is okay
- if xmin == Inf || xmin == -Inf || isequal(xmin, NaN) return error(string("invalid xmin: ", string(xmin))) end
- if xmax == Inf || xmax == -Inf || isequal(xmax, NaN) return error(string("invalid xmax: ", string(xmax))) end
- if xmin >= xmax return error("xmax must be greater than xmin") end
-
- # make the range
- x = [xmin+float64(i-1)*(xmax-xmin)/(__PLOT_POINTS-1) for i=1:__PLOT_POINTS]
- y = [try float64(f(i)) catch 0 end for i=x]
-
- # make the plot
- plot(x, y, plottype)
-end
-
-# plot a function (window determined manually)
-
-plot(f::Function, xmin::Number, xmax::Number, ymin::Number, ymax::Number) =
- plot(f, xmin, xmax, ymin, ymax, "line")
-
-function plot(f::Function, xmin::Number, xmax::Number, ymin::Number, ymax::Number, plottype::String)
- # make sure the window is okay
- if xmin == Inf || xmin == -Inf || isequal(xmin, NaN) return error(string("invalid xmin: ", string(xmin))) end
- if xmax == Inf || xmax == -Inf || isequal(xmax, NaN) return error(string("invalid xmax: ", string(xmax))) end
- if ymin == Inf || ymin == -Inf || isequal(ymin, NaN) return error(string("invalid ymin: ", string(ymin))) end
- if ymax == Inf || ymax == -Inf || isequal(ymax, NaN) return error(string("invalid ymax: ", string(ymax))) end
- if xmin >= xmax return error("xmax must be greater than xmin") end
- if ymin >= ymax return error("ymax must be greater than ymin") end
-
- # make the range
- x = [xmin+float64(i-1)*(xmax-xmin)/(__PLOT_POINTS-1) for i=1:__PLOT_POINTS]
- y = [try float64(f(i)) catch 0 end for i=x]
-
- # make the plot
- plot(x, y, xmin, xmax, ymin, ymax, plottype)
-end
View
219 extras/julia_web_base.jl
@@ -1,219 +0,0 @@
-## Julia Webrepl ##
-const DEBUG = false
-import Base.show
-
-###########################################
-# protocol
-###########################################
-
-###### the julia<-->server protocol #######
-
-# the message type is sent as a byte
-# the next byte indicates how many arguments there are
-# each argument is four bytes indicating the size of the argument, then the data for that argument
-
-###### the server<-->browser protocol #####
-
-# messages are sent as arrays of arrays (json)
-# the outer array is an "array of messages"
-# each message is itself an array:
-# [message_type::number, arg0::string, arg1::string, ...]
-
-# import the message types
-include("webrepl_msgtypes_h.jl")
-
-###########################################
-# set up the socket connection
-###########################################
-
-# open a socket on any port
-(port,sock) = Base.open_any_tcp_port(4444)
-
-# print the socket number so the server knows what it is
-println(STDOUT,int16(port))
-
-# wait for the server to connect to the socket
-__io = Base.wait_accept(sock)
-Base.start_reading(__io)
-
-###########################################
-# protocol implementation
-###########################################
-
-# a message
-type __Message
- msg_type::Uint8
- args::Array{Any, 1}
-end
-show(m::__Message) = __print_message(m)
-
-# read a message
-function __read_message()
- msg_type = read(__io, Uint8)
- args = {}
- num_args = read(__io, Uint8)
- for i=1:num_args
- arg_length = read(__io, Uint32)
- arg = ASCIIString(read(__io, Uint8, arg_length))
- push!(args, arg)
- end
- return __Message(msg_type, args)
-end
-
-# send a message
-const __io_out_buf = PipeString()
-function __write_message(msg)
- if DEBUG show(msg); println() end
- write(__io, uint8(msg.msg_type))
- write(__io, uint8(length(msg.args)))
- for arg=msg.args
- write(__io_out_buf, arg)
- data = takebuf_array(__io_out_buf)
- write(__io, uint32(length(data)))
- write(__io, data)
- end
- #flush(__io)
-end
-
-# print a message (useful for debugging)
-function __print_message(msg)
- print(msg.msg_type)
- print(": [ ")
- for arg=msg.args
- print("\"")
- print(arg)
- print("\" ")
- end
- println("]")
-end
-
-###########################################
-# standard web library
-###########################################
-
-# load the special functions available to the web repl
-include("julia_web.jl")
-
-###########################################
-# input event handler
-###########################################
-
-# store the result of the previous input
-ans = nothing
-
-# callback for that event handler
-function __socket_callback(fd)
- # read the message
- __msg = __read_message()
- if DEBUG show(__msg); println() end
-
- # MSG_INPUT_EVAL
- if __msg.msg_type == __MSG_INPUT_EVAL && length(__msg.args) == 3
- # parse the arguments
- __user_name = __msg.args[1]
- __user_id = __msg.args[2]
- __input = __msg.args[3]
-
- # split the input into lines
- __lines = split(__input, '\n')
-
- # try to parse each line incrementally
- __parsed_exprs = {}
- __input_so_far = ""
- __all_nothing = true
-
- for i=1:length(__lines)
- # add the next line of input
- __input_so_far = string(__input_so_far, __lines[i], "\n")
-
- # try to parse it
- __expr = Base.parse_input_line(__input_so_far)
-
- # if there was nothing to parse, just keep going
- if __expr == nothing
- continue
- end
- __all_nothing = false
- __expr_multitoken = isa(__expr, Expr)
-
- # stop now if there was a parsing error
- if __expr_multitoken && __expr.head == :error
- # send everyone the input
- __write_message(__Message(__MSG_OUTPUT_EVAL_INPUT, {__user_id, __user_name, __input}))
- return __write_message(__Message(__MSG_OUTPUT_EVAL_ERROR, {__user_id, __expr.args[1]}))
- end
-
- # if the expression was incomplete, just keep going
- if __expr_multitoken && __expr.head == :continue
- continue
- end
-
- # add the parsed expression to the list
- __input_so_far = ""
- __parsed_exprs = [__parsed_exprs, {(__user_id, __expr)}]
- end
-
- # if the input was empty, stop early
- if __all_nothing
- # send everyone the input
- __write_message(__Message(__MSG_OUTPUT_EVAL_INPUT, {__user_id, __user_name, __input}))
- return __write_message(__Message(__MSG_OUTPUT_EVAL_RESULT, {__user_id, ""}))
- end
-
- # tell the browser if we didn't get a complete expression
- if length(__parsed_exprs) == 0
- return __write_message(__Message(__MSG_OUTPUT_EVAL_INCOMPLETE, {__user_id}))
- end
-
- # send everyone the input
- __write_message(__Message(__MSG_OUTPUT_EVAL_INPUT, {__user_id, __user_name, __input}))
-
- put(__eval_channel, __parsed_exprs)
- end
-end
-
-# event handler for socket input
-enq_work(@task while true __socket_callback(__io) end)
-
-web_show(user_id, ans) =
- __Message(__MSG_OUTPUT_EVAL_RESULT, {user_id, sprint(repl_show, ans)})
-
-function __eval_exprs(__parsed_exprs)
- global ans
- user_id = ""
-
- # try to evaluate the expressions
- for i=1:length(__parsed_exprs)
- # evaluate the expression and stop if any exceptions happen
- user_id = __parsed_exprs[i][1]
- try
- ans = eval(__parsed_exprs[i][2])
- catch __error
- return __write_message(__Message(__MSG_OUTPUT_EVAL_ERROR, {user_id, sprint(show, __error)}))
- end
- end
-
- # send the result of the last expression
- if isa(ans,Nothing)
- return __write_message(__Message(__MSG_OUTPUT_EVAL_RESULT, {user_id, ""}))
- else
- return __write_message(web_show(user_id, ans))
- end
-end
-
-# print version info
-println("Julia ", Base.version_string)
-println(Base.commit_string, "\n")
-
-# work around bug displaying "\n "
-#print(" ",replace(Base.banner_plain, "\n", "\n "))
-
-###########################################
-# wait forever while asynchronous processing happens
-###########################################
-
-__eval_channel = RemoteRef()
-
-while true
- __eval_exprs(take(__eval_channel))
-end
View
1 src/julia.expmap
@@ -170,6 +170,7 @@
jl_load_file_string;
jl_loaderror_type;
jl_load_file_string;
+ jl_locate_sysimg;
jl_lstat;
jl_macroexpand;
jl_main_module;
View
5 ui/webserver/.gitignore
@@ -1,5 +0,0 @@
-/*.o
-/webserver
-/julia-release-webserver
-/julia-debug-webserver
-/julia-debug-webserver.dSYM
View
59 ui/webserver/Makefile
@@ -1,59 +0,0 @@
-JULIAHOME = $(abspath ../..)
-include $(JULIAHOME)/Make.inc
-
-override CFLAGS += $(JCFLAGS)
-override CXXFLAGS += $(JCXXFLAGS)
-
-LIBS = $(BUILD)/$(JL_LIBDIR)/libuv.a
-ifeq ($(OS), Linux)
-LIBS += -lpthread -lrt
-endif
-
-ifeq ($(OS),WINNT)
-LIBS += -lws2_32 -liphlpapi -lpsapi
-endif
-
-ifeq ($(OS),Darwin)
-LIBS += -framework ApplicationServices
-endif
-
-WEBSERVER_SRCS = webserver.o server.o jsoncpp.o
-WEBSERVER_DSRCS = webserver.do server.do jsoncpp.do
-
-%.o: %.cpp *.h
- $(QUIET_CC)$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(SHIPFLAGS) -c $< -o $@
-%.do: %.cpp *.h
- $(QUIET_CC)$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEBUGFLAGS) -c $< -o $@
-
-
-ifeq ($(OS),WINNT)
-LAUNCH_SCRIPT = launch-julia-webserver.bat
-else
-LAUNCH_SCRIPT = launch-julia-webserver
-endif
-$(BUILD)/bin/$(LAUNCH_SCRIPT): $(LAUNCH_SCRIPT)
- cp $< $@
-
-$(BUILD)/etc/nginx.conf: nginx.conf nginx-win.conf
-ifeq ($(OS),WINNT)
- cp nginx-win.conf $@
-else
- cp nginx.conf $@
-endif
-
-julia-release julia-debug: %: $(BUILD)/bin/%-webserver$(EXE) $(BUILD)/bin/$(LAUNCH_SCRIPT) $(BUILD)/etc/nginx.conf
-
-release debug:
- $(MAKE) julia-$@
-
-$(BUILD)/bin/julia-release-webserver$(EXE): $(WEBSERVER_SRCS)
- $(QUIET_LINK) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $(SHIPFLAGS) $(LDFLAGS) $(WEBSERVER_SRCS) $(LIBS)
-
-$(BUILD)/bin/julia-debug-webserver$(EXE): $(WEBSERVER_DSRCS)
- $(QUIET_LINK) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $(DEBUGFLAGS) $(LDFLAGS) $(WEBSERVER_DSRCS) $(LIBS)
-
-
-clean:
- rm -f *.o *.do
- rm -f $(BUILD)/bin/julia-*-webserver
- rm -f $(BUILD)/bin/*.bat
View
1,857 ui/webserver/json.h
0 additions, 1,857 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
4,230 ui/webserver/jsoncpp.cpp
0 additions, 4,230 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
12 ui/webserver/launch-julia-webserver
@@ -1,12 +0,0 @@
-#!/bin/sh
-cd $(dirname $0)
-test -x ../sbin/nginx || { echo "Install nginx with \"make webrepl\" " && exit 0; }
-
-echo "Connect to http://localhost:2000/ for the web REPL."
-../sbin/nginx -c etc/nginx.conf &
-
-[ x$(uname) = xDarwin ] && (sleep 1 && open http://localhost:2000/) &
-./julia-release-webserver -p 2001
-#gdb --args ./julia-debug-webserver -p 2001
-kill `cat ../logs/nginx.pid`
-
View
39 ui/webserver/launch-julia-webserver.bat
@@ -1,39 +0,0 @@
-@echo off
-
-pushd %cd%
-setlocal enableextensions enabledelayedexpansion
-call %~dp0prepare-julia-env.bat %*
-
-if exist %JULIA_HOME%..\sbin\nginx.exe goto nginx
-if exist %JULIA_HOME%..\sbin\lighttpd.exe goto lighttpd
-
-:error
-echo Please install either lighttpd or nginx into usr/sbin
-goto end
-
-:nginx
-pushd %cd%
-cd %JULIA_HOME%..\sbin
-start /b nginx -c %JULIA_HOME%..\etc\nginx.conf
-popd
-goto julia
-
-:lighttpd
-start /b %JULIA_HOME%..\sbin\lighttpd -D -f %JULIA_HOME%..\etc\lighttpd.conf -m %JULIA_HOME%..\lib
-goto julia
-
-:julia
-echo Connect to http://localhost:2000/ for the web REPL.
-echo Press Ctrl-C to quit, then answer N to prompt
-start /b http://localhost:2000/
-cd %JULIA_HOME%..\bin
-call julia-release-webserver.exe -p 2001
-
-:end
-echo Killing nginx... (this can take a few seconds)
-for /F "delims=" %%a in (%JULIA_HOME%../sbin/logs/nginx.pid) do taskkill /f /t /pid %%a
-sleep 1
-echo Exiting...
-endlocal
-popd
-pause
View
120 ui/webserver/message_types.h
@@ -1,120 +0,0 @@
-#ifndef notdefined
-#define This_file_is_used_by_the_SCGI_server_and_the_Julia_back_end
-#define NOTE_These_message_types_must_match_those_in_index_dot_js_and_repl_dot_js
-#endif
-
-#ifndef notdefined
-#define MSG_INPUT_NULL 0
-#else
-__MSG_INPUT_NULL = uint8(0) # {}, null message (should be ignored)
-#endif
-
-#ifndef notdefined
-#define MSG_INPUT_START 1
-#else
-__MSG_INPUT_START = uint8(1) # {user_name, session_name}, create/join a new session
-#endif
-
-#ifndef notdefined
-#define MSG_INPUT_POLL 2
-#else
-__MSG_INPUT_POLL = uint8(2) # {}, poll the server
-#endif
-
-#ifndef notdefined
-#define MSG_INPUT_EVAL 3
-#else
-__MSG_INPUT_EVAL = uint8(3) # {user_name, user_id, input}, evaluate an expression (this message is forwarded to julia)
-#endif
-
-#ifndef notdefined
-#define MSG_INPUT_REPLAY_HISTORY 4
-#else
-__MSG_INPUT_REPLAY_HISTORY = uint8(4) # {}, ask the server to resend all messages
-#endif
-
-#ifndef notdefined
-#define MSG_INPUT_GET_USER 5
-#else
-__MSG_INPUT_GET_USER = uint8(5) # {}, ask the server to send back the user
-#endif
-
-
-
-#ifndef notdefined
-#define MSG_OUTPUT_NULL 0
-#else
-__MSG_OUTPUT_NULL = uint8(0) # {}, null message (should be ignored)
-#endif
-
-#ifndef notdefined
-#define MSG_OUTPUT_WELCOME 1
-#else
-__MSG_OUTPUT_WELCOME = uint8(1) # {}, successfully created/joined the session
-#endif
-
-#ifndef notdefined
-#define MSG_OUTPUT_READY 2
-#else
-__MSG_OUTPUT_READY = uint8(2) # {}, ready for input, sent only when session starts (stored in replay history)
-#endif
-
-#ifndef notdefined
-#define MSG_OUTPUT_MESSAGE 3
-#else
-__MSG_OUTPUT_MESSAGE = uint8(3) # {message}, send a message to the user (stored in replay history)
-#endif
-
-#ifndef notdefined
-#define MSG_OUTPUT_OTHER 4
-#else
-__MSG_OUTPUT_OTHER = uint8(4) # {text}, standard output pipe (stored in replay history)
-#endif
-
-#ifndef notdefined
-#define MSG_OUTPUT_EVAL_INPUT 5
-#else
-__MSG_OUTPUT_EVAL_INPUT = uint8(5) # {user_id, user_name, input}, input from a user (this message comes from julia, stored in replay history)
-#endif
-
-#ifndef notdefined
-#define MSG_OUTPUT_FATAL_ERROR 6
-#else
-__MSG_OUTPUT_FATAL_ERROR = uint8(6) # {message}, fatal error message (terminates session, stored in replay history)
-#endif
-
-#ifndef notdefined
-#define MSG_OUTPUT_EVAL_INCOMPLETE 7
-#else
-__MSG_OUTPUT_EVAL_INCOMPLETE = uint8(7) # {user_id}, incomplete expression (this message comes from julia)
-#endif
-
-#ifndef notdefined
-#define MSG_OUTPUT_EVAL_RESULT 8
-#else
-__MSG_OUTPUT_EVAL_RESULT = uint8(8) # {user_id, result}, expression result (this message comes from julia, stored in replay history)
-#endif
-
-#ifndef notdefined
-#define MSG_OUTPUT_EVAL_ERROR 9
-#else
-__MSG_OUTPUT_EVAL_ERROR = uint8(9) # {user_id, message}, error evaluating expression (this message comes from julia, stored in replay history)
-#endif
-
-#ifndef notdefined
-#define MSG_OUTPUT_PLOT 10
-#else
-__MSG_OUTPUT_PLOT = uint8(10) # {type, ...} create a plot, the format of the data depends on the type of plot (this message comes from julia, stored in replay history)
-#endif
-
-#ifndef notdefined
-#define MSG_OUTPUT_GET_USER 11
-#else
-__MSG_OUTPUT_GET_USER = uint8(11) # {user_name, user_id} response to MSG_GET_USER
-#endif
-
-#ifndef notdefined
-#define MSG_OUTPUT_HTML 12
-#else
-__MSG_OUTPUT_HTML = uint8(12) # {html} raw html
-#endif
View
34 ui/webserver/nginx-win.conf
@@ -1,34 +0,0 @@
-# Julia Windows nginx.conf script
-
-error_log logs/nginx.log info;
-events {
- worker_connections 256;
-}
-http {
- access_log logs/access.log combined;
- types {
- text/html html htm;
- text/plain txt;
- image/jpeg jpg;
- image/png png;
- text/css css;
- application/javascript js;
- }
-
- index index.html index.htm default.htm;
-
- server {
- listen 2000;
- location /repl.scgi {
- scgi_pass localhost:2001;
- scgi_param SCGI 1;
- scgi_param REQUEST_METHOD $request_method;
- scgi_param CONTENT_TYPE $content_type;
- scgi_pass_request_headers on;
- }
-
- location / {
- root ../share/julia/ui/website;
- }
- }
-}
View
35 ui/webserver/nginx.conf
@@ -1,35 +0,0 @@
-# Julia Linux / Mac nginx.conf script
-
-error_log logs/nginx.log info;
-pid logs/nginx.pid;
-events {
- worker_connections 256;
-}
-http {
- access_log logs/access.log combined;
- types {
- text/html html htm;
- text/plain txt;
- image/jpeg jpg;
- image/png png;
- text/css css;
- application/javascript js;
- }
-
- index index.html index.htm default.htm;
-
- server {
- listen 2000;
- location /repl.scgi {
- scgi_pass localhost:2001;
- scgi_param SCGI 1;
- scgi_param REQUEST_METHOD $request_method;
- scgi_param CONTENT_TYPE $content_type;
- scgi_pass_request_headers on;
- }
-
- location / {
- root share/julia/ui/website;
- }
- }
-}
View
669 ui/webserver/server.cpp
@@ -1,669 +0,0 @@
-#include <iostream>
-#include "server.h"
-#include "../../deps/libuv/include/uv.h"
-
-using namespace std;
-
-namespace scgi
-{
-// convert a value to a string
-template <class T> string to_string(const T& t)
-{
- // convert a value to a string
- stringstream ss;
- ss<<t;
- return ss.str();
-}
-
-// parse a value from a string
-template <class T> T from_string(const string& t)
-{
- // parse a value from a string
- T ret;
- stringstream(t)>>ret;
- return ret;
-}
-
-// strip a string of leading and trailing whitespace
-string strip(string str)
-{
- // remove leading whitespace
- while (!str.empty())
- {
- if (str[0] == ' ' || str[0] == '\t' || str[0] == '\n' || str[0] == '\r')
- str = str.substr(1, str.size()-1);
- else
- break;
- }
- // remove trailing whitespace
- while (!str.empty())
- {
- if (str[str.size()-1] == ' ' || str[str.size()-1] == '\t' || str[str.size()-1] == '\n' || str[str.size()-1] == '\r')
- str = str.substr(0, str.size()-1);
- else
- break;
- }
- // return the result
- return str;
-}
-
-// convert a string to lowercase
-string to_lower(string str)
-{
- // convert a string to lowercase
- for (size_t j = 0; j < str.size(); j++)
- str[j] = tolower(str[j]);
- return str;
-}
-
-// convert a string to uppercase
-string to_upper(string str)
-{
- // convert a string to uppercase
- for (size_t j = 0; j < str.size(); j++)
- str[j] = toupper(str[j]);
- return str;
-}
-
-// split strings by a character
-vector<string> split(string str, char separator)
-{
- // split a string
- vector<string> result;
- string current_str;
- for (size_t i = 0; i < str.size(); i++)
- {
- if (str[i] == separator)
- {
- result.push_back(current_str);
- current_str = "";
- }
- else
- current_str += str.substr(i, 1);
- }
- result.push_back(current_str);
- return result;
-}
-
-// decode data of type application/x-www-form-urlencoded
-string url_decode(string str)
-{
- // replace + characters with spaces
- for (size_t i = 0; i < str.size(); i++)
- {
- if (str[i] == '+')
- str[i] = ' ';
- }
- // escape characters
- for (size_t i = 0; i < str.size(); i++)
- {
- if (str[i] == '%')
- {
- // get the next two characters
- string code = str.substr(i+1, 2);
-
- // read the value
- unsigned int x;
- stringstream stream;
- stream<<std::hex<<code;
- stream>>x;
- char c = (char)x;
-
- // replace the character
- str = str.substr(0, i)+c+str.substr(i+3, str.size()-(i+3));
- }
- }
- // return the result
- return str;
-}
-}
-
-int scgi::request::get_cookie_num()
-{
- // return the number of cookies
- return (int)cookie_list.size();
-}
-
-string scgi::request::get_cookie_name(int id)
-{
- // get the name of a particular cookie
- return cookie_list[id].name;
-}
-
-string scgi::request::get_cookie_value(string name)
-{
- // search for the cookie by name
- for (size_t i = 0; i < cookie_list.size(); i++)
- {
- // compare the lowercase names
- if (to_lower(name) == to_lower(cookie_list[i].name))
- return cookie_list[i].value;
- }
- return "";
-}
-
-bool scgi::request::get_cookie_exists(string name)
-{
- // search for the cookie by name
- for (size_t i = 0; i < cookie_list.size(); i++)
- {
- // compare the lowercase names
- if (to_lower(name) == to_lower(cookie_list[i].name))
- return true;
- }
- return false;
-}
-
-using namespace scgi;
-
-int scgi::request::get_field_num()
-{
- // return the number of fields
- return (int)field_list.size();
-}
-
-string scgi::request::get_field_name(int id)
-{
- // get the name of a particular field
- return field_list[id].name;
-}
-
-string scgi::request::get_field_value(string name)
-{
- // search for the field by name
- for (size_t i = 0; i < field_list.size(); i++)
- {
- // compare the lowercase names
- if (to_lower(name) == to_lower(field_list[i].name))
- return field_list[i].value;
- }
- return "";
-}
-
-string scgi::request::get_field_filename(string name)
-{
- // search for the field by name
- for (size_t i = 0; i < field_list.size(); i++)
- {
- // compare the lowercase names
- if (to_lower(name) == to_lower(field_list[i].name))
- return field_list[i].filename;
- }
- return "";
-}
-
-bool scgi::request::get_field_exists(string name)
-{
- // search for the field by name
- for (size_t i = 0; i < field_list.size(); i++)
- {
- // compare the lowercase names
- if (to_lower(name) == to_lower(field_list[i].name))
- return true;
- }
- return false;
-}
-
-namespace scgi
-{
-
-#define PASS_ON(f) stream->read_cb = &f; \
- uv_buf_t buf2; \
- buf2.base=const_cast<char*>(pos); \
- buf2.len=buf.len-nread-(pos-buf.base); \
- f(stream,nread-(pos-buf.base),buf2);
-
-void request_aborted(uv_handle_t *stream)
-{
- std::cout<<"Request Aborted";
- delete (reading_in_progress*)stream->data;
- delete (uv_tcp_t*)stream;
-}
-
-void abort_request(uv_stream_t *stream)
-{
- uv_close((uv_handle_t*)stream,request_aborted);
-}
-
-void read_body(uv_stream_t* stream, ssize_t nread, uv_buf_t buf)
-{
- if(nread<0) {
- abort_request(stream);
- return;
- }
-
- reading_in_progress *p = (reading_in_progress*)(stream->data);
- if(p->isComma) {
- buf.base=buf.base+2;
- nread-=2;
- }
- if(p->bufBase==0) p->bufBase=buf.base;
- if(p->body_length>p->pos+nread) {
- p->body.append(buf.base,nread);
- p->pos+=nread;
- } else {
- p->body.append(buf.base,p->body_length-p->pos);
- //do the actual processing
- // get the type of request
- bool get = true;
-
- bool request_method_exists = false;
- string request_method;
- for (size_t i = 0; i < p->header_list.size(); i++)
- {
- if (to_upper(p->header_list[i].name) == "REQUEST_METHOD")
- {
- request_method_exists = true;
- request_method = p->header_list[i].value;
- break;
- }
- }
-
- if (request_method_exists)
- {
- if (to_upper(request_method) == "POST")
- get = false;
- }
- if (get)
- {
- // the encoding for GET is application/x-www-form-urlencoded
- bool query_string_exists = false;
- string query_string;
- for (size_t i = 0; i < p->header_list.size(); i++)
- {
- if (to_upper(p->header_list[i].name) == "QUERY_STRING")
- {
- query_string_exists = true;
- query_string = p->header_list[i].value;
- break;
- }
- }
-
- if (query_string_exists)
- {
- // get the key=value strings
- vector<string> pairs = split(query_string, '&');
-
- // construct the values
- for (size_t i = 0; i < pairs.size(); i++)
- {
- vector<string> pair = split(pairs[i], '=');
- if (pair.size() == 2)
- {
- field field_obj;
- field_obj.name = url_decode(strip(pair[0]));
- field_obj.value = url_decode(strip(pair[1]));
- p->request_obj.field_list.push_back(field_obj);
- }
- }
- }
- }
- else
- {
- // the encoding for POST can be application/x-www-form-urlencoded or multipart/form-data
- bool content_type_exists = false;
- string content_type;
- for (size_t i = 0; i < p->header_list.size(); i++)
- {
- if (to_upper(p->header_list[i].name) == "CONTENT_TYPE")
- {
- content_type_exists = true;
- content_type = p->header_list[i].value;
- break;
- }
- }
-
- if (content_type_exists)
- {
- // get the subparts of the CONTENT_TYPE header
- vector<string> content_type_fields = split(content_type, ';');
- for (size_t i = 0; i < content_type_fields.size(); i++)
- content_type_fields[i] = strip(content_type_fields[i]);
-
- // application/x-www-form-urlencoded
- if (to_lower(content_type_fields[0]) == "application/x-www-form-urlencoded")
- {
- // get the key=value strings
- vector<string> pairs = split(p->body, '&');
-
- // construct the values
- for (size_t i = 0; i < pairs.size(); i++)
- {
- vector<string> pair = split(pairs[i], '=');
- if (pair.size() == 2)
- {
- field field_obj;
- field_obj.name = url_decode(strip(pair[0]));
- field_obj.value = url_decode(strip(pair[1]));
- p->request_obj.field_list.push_back(field_obj);
- }
- }
- }
-
- // multipart/form-data
- if (to_lower(content_type_fields[0]) == "multipart/form-data")
- {
- // get the boundary fields
- vector<string> boundary_fields = split(content_type_fields[1], '=');
- for (size_t i = 0; i < boundary_fields.size(); i++)
- boundary_fields[i] = strip(boundary_fields[i]);
- if (boundary_fields.size() == 2)
- {
- // extract the boundary
- string boundary = boundary_fields[1];
-
- // get the field data from the body
- string field_data = p->body;
-
- // loop through the fields
- while (true)
- {
- // make a new field
- field field_obj;
-
- // skip whitespace
- while (!field_data.empty())
- {
- if (field_data[0] != ' ' && field_data[0] != '\t' && field_data[0] != '\r' && field_data[0] != '\n')
- break;
- field_data = field_data.substr(1, field_data.size()-1);
- }
-
- // skip the boundary
- if (field_data.size() < boundary.size()+2)
- break;
- if (field_data.substr(0, boundary.size()+2) != "--"+boundary)
- break;
- field_data = field_data.substr(boundary.size()+2, field_data.size()-(boundary.size()+2));
-
- // skip whitespace
- while (!field_data.empty())
- {
- if (field_data[0] != ' ' && field_data[0] != '\t' && field_data[0] != '\r' && field_data[0] != '\n')
- break;
- field_data = field_data.substr(1, field_data.size()-1);
- }
-
- // check if we have reached the end
- if (field_data.size() < 2)
- break;
- if (field_data.substr(0, 2) == "--")
- break;
-
- // start parsing lines
- while (true)
- {
- // get the line
- size_t newline_pos = field_data.size();
- for (size_t i = 0; i < field_data.size(); i++)
- {
- if (field_data[i] == '\n')
- {
- newline_pos = i;
- break;
- }
- }
- string line = strip(field_data.substr(0, newline_pos));
- field_data = field_data.substr(newline_pos+1, field_data.size()-(newline_pos+1));
-
- // check if we're done parsing the headers
- if (line.empty())
- break;
-
- // check if this is a "Content-Disposition" header
- string disposition_header = "Content-Disposition:";
- if (line.size() >= disposition_header.size())
- {
- if (to_lower(line.substr(0, disposition_header.size())) == to_lower(disposition_header))
- {
- // take out the "Content-Disposition:" tag
- line = line.substr(disposition_header.size(), line.size()-disposition_header.size());
-
- // get the disposition fields
- vector<string> disposition_fields = split(line, ';');
- for (size_t i = 0; i < disposition_fields.size(); i++)
- disposition_fields[i] = strip(disposition_fields[i]);
-
- // parse the fields
- for (size_t i = 0; i < disposition_fields.size(); i++)
- {
- // get the key=value pair
- vector<string> pair = split(disposition_fields[i], '=');
- if (pair.size() == 2)
- {
- // name
- if (to_upper(strip(pair[0])) == "NAME")
- {
- // get the name
- field_obj.name = strip(pair[1]);
-
- // strip the quotes
- if (field_obj.name.size() >= 2)
- {
- if (field_obj.name[0] == '\"' && field_obj.name[field_obj.name.size()-1] == '\"')
- field_obj.name = field_obj.name.substr(1, field_obj.name.size()-2);
- }
-
- // move on
- continue;
- }
-
- // filename
- if (to_upper(strip(pair[0])) == "FILENAME")
- {
- // get the filename
- field_obj.filename = strip(pair[1]);
-
- // strip the quotes
- if (field_obj.filename.size() >= 2)
- {
- if (field_obj.filename[0] == '\"' && field_obj.filename[field_obj.filename.size()-1] == '\"')
- field_obj.filename = field_obj.filename.substr(1, field_obj.filename.size()-2);
- }
-
- // move on
- continue;
- }
- }
- }
- }
- }
- }
-
- // find out how much data to extract
- size_t field_size = 0;
- for (size_t i = 0; i < field_data.size()-(boundary.size()+2); i++)
- {
- if (field_data.substr(i, boundary.size()+3) == "\n--"+boundary || field_data.substr(i, boundary.size()+4) == "\r\n--"+boundary)
- {
- field_size = i;
- break;
- }
- }
-
- // extract the data
- field_obj.value = field_data.substr(0, field_size);
- field_data = field_data.substr(field_size, field_data.size()-field_size);
-
- // add the field to the list
- p->request_obj.field_list.push_back(field_obj);
- }
- }
- }
- }
- }
-
- // get the response
- p->cb(&(p->request_obj),stream);
- }
- delete[] p->bufBase;
- p->bufBase=0;
-}
-
-
-void read_header(uv_stream_t* stream, ssize_t nread, uv_buf_t buf)
-{
- if(nread<0) {
- abort_request(stream);
- return;
- }
-
- const char *pos = buf.base;
- reading_in_progress *p = (reading_in_progress*)(stream->data);
- if(p->bufBase==0)p->bufBase=buf.base;
- int i;
- if(p->isComma) {
- (++(p->pos),++pos);
- p->isComma=false;
- }
- for(i=0; i<buf.len&&p->pos<p->header_length; ++i, ++pos, ++p->pos)
- {
- if(p->inName) {
- if(*pos==0)
- p->inName=false;
- else
- p->current_header.name+=*pos;
- } else {
- if(*pos!=0)
- p->current_header.value+=*pos;
- else {
- //header complete
-
- // check if this is the "CONTENT_LENGTH" header
- if (p->header_list.empty())
- p->body_length = from_string<int>(p->current_header.value);
-
- // add the header to the list
- p->header_list.push_back(p->current_header); //this creates a copy
- p->current_header.name="";
- p->current_header.value="";
- p->inName=true;
- }
- }
- }
- if(p->current_header.name!="")
- p->header_list.push_back(p->current_header);
- if(p->pos>=p->header_length) {
- //process cookies
- for (size_t j = 0; j < p->header_list.size(); j++)
- {
- if (to_upper(p->header_list[j].name) == "HTTP_COOKIE")
- {
- vector<string> crumb_list = split(p->header_list[j].value, ';');
- for (size_t k = 0; k < crumb_list.size(); k++)
- {
- // get the crumb
- vector<string> crumb = split(crumb_list[k], '=');
- if (crumb.size() == 2)
- {
- // create the cookie
- cookie cookie_obj;
- cookie_obj.name = strip(crumb[0]);
- cookie_obj.value = strip(crumb[1]);
-
- // add the cookie the list
- p->request_obj.cookie_list.push_back(cookie_obj);
- }
- }
- }
- }
- p->pos=0;
- p->isComma=true;
- PASS_ON(read_body)
- } else {
- delete[] p->bufBase;
- p->bufBase=0;
- }
-}
-
-//read the length of the header;
-void read_header_length(uv_stream_t* stream, ssize_t nread, uv_buf_t buf)
-{
-#ifdef DEBUG_TRACE
- cout << "Header Length!\n";
-#endif
- if(nread<0) {
- abort_request(stream);
- return;
- }
-
- const char *pos = buf.base;
- reading_in_progress *p = (reading_in_progress*)(stream->data);
- if(p->bufBase==0) p->bufBase=buf.base;
- int i;
- for(i = 0; i<buf.len; ++i, ++pos)
- {
- if(*pos!=':') {
- p->header_length_str+=*pos;
- } else
- break;
- }
- if(buf.len>0&&*pos==':') {
- //we're done
- p->header_length = from_string<int>(p->header_length_str);
- PASS_ON(read_header)
- } else {
- delete[] p->bufBase;
- p->bufBase=0;
- }
-}
-
-uv_buf_t allocBuffer(uv_handle_t* handle, size_t suggested_size)
-{
- uv_buf_t buf;
- buf.base = new char[suggested_size];
- buf.len = suggested_size;
- return buf;
-}
-
-// handle a single request
-void handle_request_and_release_socket(uv_stream_t* server, int status)
-{
- uv_tcp_t *client = new uv_tcp_t;
- uv_tcp_init(uv_default_loop(),client);
- uv_accept((uv_stream_t*)server,(uv_stream_t*)client);
-
-#ifdef DEBUG_TRACE
- std::cout<<"Accepted connection!\n";
-#endif
-
- // create the request object
-
- reading_in_progress *p= new reading_in_progress;
- p->body_length=0;
- p->inName=true;
- p->header_length=0;
- p->pos=0;
- p->isComma=true;
- p->cstr=0;
- p->cb=(callback)server->data;
- p->bufBase=0;
- client->data=p;
-
- uv_read_start((uv_stream_t*)client,&allocBuffer,&read_header_length);
-}
-
-void run_server(int port, callback cb)
-{
- struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", port);
- uv_tcp_t server;
- int err;
-
- server.data=(void*)cb;
-
- err = uv_tcp_init(uv_default_loop(), &server);
- //assert(err == 0);
- err = uv_tcp_bind(&server, addr);
- //assert(err == 0);
-
-#ifdef __WIN32__
- uv_tcp_simultaneous_accepts(&server,0);
-#endif
-
- err = uv_listen((uv_stream_t*)&server, 128, &handle_request_and_release_socket);
- //assert(r == 0)
-
- uv_run(uv_default_loop(),UV_RUN_DEFAULT);
-}
-
-}
View
116 ui/webserver/server.h
@@ -1,116 +0,0 @@
-#ifndef INCLUDE_SERVER
-#define INCLUDE_SERVER
-
-#include "../../deps/libuv/include/uv.h"
-#include <string>
-#include <vector>
-#include <sstream>
-//#define JULIA_DEBUG_TRACE
-//#define CPP_DEBUG_TRACE
-
-namespace scgi
-{
-
-
- // represents a GET/POST field
- class field
- {
- public:
- std::string name;
- std::string value;
- std::string filename;
- };
-
- // represents a cookie
- class cookie
- {
- public:
- std::string name;
- std::string value;
- };
-
- // represents an HTTP request
- class request
- {
- public:
- /////////////////////////////////////////////
- // form fields
- /////////////////////////////////////////////
-
- // get the number of fields
- int get_field_num();
-
- // get a field name
- std::string get_field_name(int id);
-
- // get a field value (not case sensitive)
- std::string get_field_value(std::string name);
-
- // get a field filename (for file uploads; not case sensitive)
- std::string get_field_filename(std::string name);
-
- // get whether a field exists (not case sensitive)
- bool get_field_exists(std::string name);
-
- // the form fields
- std::vector<field> field_list;
-
- /////////////////////////////////////////////
- // cookies
- /////////////////////////////////////////////
-
- // get the number of cookies
- int get_cookie_num();
-
- // get a cookie name
- std::string get_cookie_name(int id);
-
- // get a cookie value (not case sensitive)
- std::string get_cookie_value(std::string name);
-
- // get a cookie filename (for file uploads; not case sensitive)
- std::string get_cookie_filename(std::string name);
-
- // get whether a cookie exists (not case sensitive)
- bool get_cookie_exists(std::string name);
-
- // the form cookies
- std::vector<cookie> cookie_list;
- };
-
- // represents an SCGI header
- class header
- {
- public:
- std::string name;
- std::string value;
- };
-
- // the callback function for requests: string response = callback(request req);
- // if the "multithreaded" parameter of run_server is true, this callback must be
- // thread safe!
- typedef void (*callback)(request*,uv_stream_t *client);
-
- struct reading_in_progress {
- std::string header_length_str;
- int header_length;
- int body_length;
- int pos;
- std::vector<header> header_list;
- header current_header;
- bool inName;
- bool isComma;
- request request_obj;
- char *cstr;
- std::string body;
- callback cb;
- const char *bufBase;
- };
-
- // run the server - this blocks forever
- void run_server(int port, callback cb);
-}
-
-struct julia_session;
-
-#endif
View
1,122 ui/webserver/webserver.cpp
@@ -1,1122 +0,0 @@
-#include <iostream>
-#include <fstream>
-#include <map>
-#include <ctime>
-#include <stdlib.h>
-#include <cstring>
-#include <unistd.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include "server.h"
-#include "json.h"
-#include "message_types.h"
-#ifndef __WIN32__
-#include <sys/wait.h>
-#endif
-
-extern char **environ; //only unistd.h post- POSIX 2008
-
-using namespace std;
-using namespace scgi;
-
-/////////////////////////////////////////////////////////////////////////////
-// string helper functions
-/////////////////////////////////////////////////////////////////////////////
-
-// convert a value to a string
-template <class T> std::string to_string(const T& t)
-{
- // convert a value to a string
- stringstream ss;
- ss<<t;
- return ss.str();
-}
-
-// parse a string from a value
-template <class T> T from_string(const std::string& t)
-{
- // parse a value from a string
- T ret;
- stringstream(t)>>ret;
- return ret;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// messages
-/////////////////////////////////////////////////////////////////////////////
-
-// a message
-class message
-{
-public:
- // see ui/webserver/julia_web_base.j for documentation
- uint8_t type;
- vector<string> args;
-};
-
-/////////////////////////////////////////////////////////////////////////////
-// julia_sessions
-/////////////////////////////////////////////////////////////////////////////
-
-// if a julia_session hasn't been queried in this time, it dies
-const int WEB_SESSION_TIMEOUT = 20; // in seconds
-
-// a web julia_session
-struct web_session {
- // time since watchdog was last "pet"
- time_t update_time;
-
- // to be sent to the client
- vector<message> outbox;
-
- // the user name
- string user_name;
-};
-
-enum julia_session_status
-{
- SESSION_WAITING_FOR_PORT_NUM,
- SESSION_NORMAL,
- SESSION_TERMINATING,
- SESSION_KILLED,
-};
-
-// a julia_session
-struct julia_session
-{
- // a map from julia_session tokens to web julia_sessions that use this julia julia_session
- map<string, web_session> web_session_map;
-
- // the session name
- string session_name;
-
- // to be sent to julia
- string inbox_std;
-
- // to be sent to julia
- vector<message> inbox;
-
- // to be sent to the client as MSG_OTHER_OUTPUT
- string outbox_std;
-
- // to be converted into messages
- string outbox_raw;
-
- //temporary buffer for reading the portnumber
- string portbuf;
-
- // keep track of messages sent to all the clients (not messages sent to particular users)
- vector<message> outbox_history;
-
- //pipes
- uv_process_t *proc;
- uv_pipe_t *julia_in;
- uv_pipe_t *julia_out;
- uv_pipe_t *julia_err;
-
- // the socket for communicating to julia
- uv_tcp_t *sock;
-
- // whether the julia_session should terminate
- bool should_terminate;
-
- // the status of the julia_session
- julia_session_status status;
-
- //notifier
- uv_async_t *data_notifier;
-};
-
-// a list of all julia_sessions
-vector<julia_session*> julia_session_list;
-
-void close_process(julia_session *julia_session_ptr);
-
-/////////////////////////////////////////////////////////////////////////////
-// THREAD: inbox_thread (from browser to julia)
-/////////////////////////////////////////////////////////////////////////////
-
-// add to the inbox regularly according to this interval
-const int INBOX_INTERVAL = 10000; // in nanoseconds
-
-void free_socket_write_buffer(uv_write_t* req, int status)
-{
- delete[] ((char*)req->data);
- delete req;
-}
-
-void free_write_buffer(uv_write_t* req, int status)
-{
- delete[] (char*)req->data;
- delete req;
-}
-
-static uv_buf_t alloc_buf(uv_handle_t* handle, size_t suggested_size) {
- uv_buf_t buf;
- buf.len = suggested_size;
- buf.base = new char[suggested_size];
- return buf;
-}
-
-
-//when data arrives from client (currently async, will be websocket)
-void read_client(uv_async_t* handle, int status)
-{
- julia_session *julia_session_ptr=(julia_session*)handle->data;
-
- if(julia_session_ptr->status != SESSION_NORMAL) {
- return;
- }
-
- // get the inbox data
- string inbox = julia_session_ptr->inbox_std;
-
- // if there is no inbox data and no messages to send, or if julia isn't ready, wait and try again
- if ((inbox == "" && julia_session_ptr->inbox.empty()) || julia_session_ptr->status != SESSION_NORMAL)
- {
- return;
- }
-
- if(inbox.size()>0) {
- char *cstr = new char [inbox.size()];
- memcpy (cstr, inbox.data(), inbox.size());
-
- uv_buf_t buffer;
- buffer.base = cstr;
- buffer.len = inbox.size();
-
- uv_write_t *req = new uv_write_s;
- req->data=(void*)cstr;
- uv_write(req,(uv_stream_t*)julia_session_ptr->julia_in,&buffer,1,&free_write_buffer);
- }
-
- // write messages to julia
- for (size_t i = 0; i < julia_session_ptr->inbox.size(); i++)
- {
- // get the message
- message msg = julia_session_ptr->inbox[i];
-
- uv_write_t *req2 = new uv_write_s;
-
- size_t total_size=2+4*msg.args.size();
- for (size_t j = 0; j < msg.args.size(); j++) {
- total_size+=msg.args[j].size();
- }
- char *msg_buf = new char[total_size];
- uv_buf_t buf;
- buf.base=msg_buf;
- buf.len=total_size;
- req2->data = msg_buf;
-
- *(msg_buf++)=msg.type;
- *(msg_buf++)=msg.args.size();
-
- if(msg.args.size()>0) {
-
- // iterate through the arguments
- for (size_t j = 0; j < msg.args.size(); j++) {
- // write the size of the argument
- *((uint32_t*)(msg_buf)) = (uint32_t)msg.args[j].size();
- memcpy((msg_buf+sizeof(uint32_t)),msg.args[j].data(),msg.args[j].size());
- msg_buf+=sizeof(uint32_t)+msg.args[j].size();
- }
- }
-
-
- uv_buf_t buf2;
- uv_write(req2,(uv_stream_t*)julia_session_ptr->sock,&buf,1,&free_socket_write_buffer);
- }
- julia_session_ptr->inbox.clear();
-
- // remove the written data from the inbox
- julia_session_ptr->inbox_std.clear();
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// THREAD: outbox_thread (from julia to browser)
-/////////////////////////////////////////////////////////////////////////////
-
-// add to the outbox regularly according to this interval
-const int OUTBOX_INTERVAL = 10000; // in nanoseconds
-
-// check for the port number from julia according to this interval
-const int PORT_NUM_INTERVAL = 10000; // in nanoseconds
-
-void socketClosed(uv_handle_t *stream)
-{
- delete (uv_tcp_t *)stream;
-}
-
-//read from julia on metadata socket (typically starts at 4444)
-void readSocketData(uv_stream_t *sock,ssize_t nread, uv_buf_t buf)
-{
- julia_session *julia_session_ptr=(julia_session*)sock->data;
- if(nread == -1)
- return close_process(julia_session_ptr);
- else if(julia_session_ptr->status != SESSION_NORMAL)
- return;
-
- julia_session_ptr->outbox_raw.append(buf.base,nread);
-
- // try to convert the raw outbox data into messages
- string outbox_raw = julia_session_ptr->outbox_raw;
- while (outbox_raw.size() >= 2)
- {
- // construct the message
- message msg;
-
- // get the message type
- msg.type = (*((uint8_t*)(&outbox_raw[0])));
-
- // get the number of arguments
- uint8_t arg_num = *((uint8_t*)(&outbox_raw[1]));
-
- // try to read the arguments
- int pos = 2;
- for (uint8_t i = 0; i < arg_num; i++)
- {
- // make sure there is enough data left to read
- if (outbox_raw.size() < pos+4)
- goto done;
-
- // get the size of this argument
- uint32_t arg_size = *((uint32_t*)(&outbox_raw[pos]));
- pos += 4;
-
- // make sure there is enough data left to read
- if (outbox_raw.size() < pos+arg_size)
- goto done;
-
- // get the argument
- msg.args.push_back(outbox_raw.substr(pos, arg_size));
- pos += arg_size;
- }
-
- // check if we have a whole message
- if (msg.args.size() == arg_num)
- {
- // we have a whole message - eat it from outbox_raw
- outbox_raw = julia_session_ptr->outbox_raw = outbox_raw.substr(pos, outbox_raw.size()-pos);
-
-
- // add the message to the outbox queue of all the users of this julia session if necessary
- if (msg.type == MSG_OUTPUT_EVAL_INPUT ||
- msg.type == MSG_OUTPUT_EVAL_RESULT ||
- msg.type == MSG_OUTPUT_EVAL_ERROR ||
- msg.type == MSG_OUTPUT_PLOT ||
- msg.type == MSG_OUTPUT_HTML) {
- julia_session_ptr->outbox_history.push_back(msg);
- for (map<string, web_session>::iterator iter = julia_session_ptr->web_session_map.begin(); iter != julia_session_ptr->web_session_map.end(); iter++)
- iter->second.outbox.push_back(msg);
- }
- if (msg.type == MSG_OUTPUT_EVAL_INCOMPLETE) {
- for (map<string, web_session>::iterator iter = julia_session_ptr->web_session_map.begin(); iter != julia_session_ptr->web_session_map.end(); iter++) {
- if (iter->first == msg.args[0])
- iter->second.outbox.push_back(msg);
- }
- }
- }
- }
-
- done:
- return;
-}
-
-void cleanup_web_sessions(julia_session *session, time_t t);
-void cleanup_session(julia_session *session);
-
-void connected(uv_connect_t* req, int status)
-{
- julia_session *julia_session_ptr=(julia_session*)req->handle->data;
- if(status == -1) {
- std::cerr << "An error occured during the connection: " << uv_last_error(uv_default_loop()).code;
- cleanup_web_sessions(julia_session_ptr,0); //close all web sessions
- cleanup_session(julia_session_ptr);
- } else {
- // switch to normal operation
- julia_session_ptr->status = SESSION_NORMAL;
-
- // send a ready message
- message ready_message;
- ready_message.type = MSG_OUTPUT_READY;
- julia_session_ptr->outbox_history.push_back(ready_message);
- for (map<string, web_session>::iterator iter = julia_session_ptr->web_session_map.begin(); iter != julia_session_ptr->web_session_map.end(); iter++)
- iter->second.outbox.push_back(ready_message);
-#ifdef JULIA_DEBUG_TRACE
- cout<<"Julia Process Connected\n";
-#endif
- uv_read_start((uv_stream_t*)julia_session_ptr->sock,&alloc_buf,readSocketData);
- }
- delete req;
-}
-
-
-#define JL_TCP_LOOP uv_default_loop()
-
-//read from julia (on stdin)
-void julia_incoming(uv_stream_t* stream, ssize_t nread, uv_buf_t buf)
-{
-#ifdef JULIA_DEBUG_TRACE
- cout<<"Recevied Data from Julia on STDOUT:\n";
- cout<<std::string(buf.base,buf.len)<<"\n";
-#endif
-
- julia_session *julia_session_ptr=(julia_session*)stream->data;
-
- if(nread==-1)
- return close_process(julia_session_ptr);
-
- // prepare for reading from julia
- uv_pipe_t *pipe = julia_session_ptr->julia_out;
-
-
- // send the outbox data to the client
- if (julia_session_ptr->status == SESSION_NORMAL)
- {
- // just dump the output into the julia_session
- julia_session_ptr->outbox_std.append(buf.base,nread);
- }
-
- // get the port number
- if (julia_session_ptr->status == SESSION_WAITING_FOR_PORT_NUM)
- {
- if(stream!=(uv_stream_t*)julia_session_ptr->julia_out) //allow debugging tools to print to stderr before startup
- return;
- julia_session_ptr->portbuf.append(buf.base,nread);
- // wait for a newline
- size_t newline_pos = julia_session_ptr->portbuf.find("\n");
- if (newline_pos == string::npos)
- {
- return;
- }
-
- // read the port number
- string num_string = julia_session_ptr->portbuf.substr(0, newline_pos);
- julia_session_ptr->portbuf = julia_session_ptr->portbuf.substr(newline_pos+1, julia_session_ptr->portbuf.size()-(newline_pos+1));
- int port_num = from_string<int>(num_string);
-
- // start
- julia_session_ptr->sock = new uv_tcp_t;
- uv_tcp_init(JL_TCP_LOOP,julia_session_ptr->sock);
- uv_connect_t *c=new uv_connect_t;
- sockaddr_in address=uv_ip4_addr("127.0.0.1", port_num);
- julia_session_ptr->sock->data=julia_session_ptr;
- uv_tcp_connect(c, julia_session_ptr->sock,address,&connected);
-
- cout << "Port number received. Connecting ...\n";
- }
-
-
- delete[] buf.base;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// THREAD: watchdog_thread
-/////////////////////////////////////////////////////////////////////////////
-
-// the watchdog runs regularly according to this interval
-const int WATCHDOG_INTERVAL = 10000; // every second
-
-// this is defined below but we need it here too
-std::string create_julia_session(bool idle);
-
-
-void pipes_done(uv_handle_t *pipe)
-{
- julia_session *julia_session_ptr = ((julia_session*)pipe->data);
- if((uv_pipe_t*)pipe==julia_session_ptr->julia_in) julia_session_ptr->julia_in=0;
- else if((uv_pipe_t*)pipe==julia_session_ptr->julia_out) julia_session_ptr->julia_out=0;
- else if((uv_pipe_t*)pipe==julia_session_ptr->julia_err) julia_session_ptr->julia_err=0;
- delete (uv_pipe_t*)pipe;
-}
-
-void process_exited(uv_handle_t*p)
-{
- julia_session *julia_session_ptr = (julia_session*)p->data;
- delete (uv_process_t*)p;
- julia_session_ptr->proc = 0;
- if(julia_session_ptr->status != SESSION_KILLED) {
- julia_session_ptr->status = SESSION_TERMINATING;
- close_process(julia_session_ptr);
- }
- cout<<"Process Exited\n";
-}
-
-void process_exited2(uv_process_t*p, int exit_status, int term_signal)
-{
- process_exited((uv_handle_t*)p);
-}
-
-void close_process(julia_session *julia_session_ptr)
-{
- if(julia_session_ptr->status==SESSION_KILLED)
- return;
-
- julia_session_ptr->status = SESSION_KILLED;
-
- // close the pipes
- if(julia_session_ptr->julia_in != 0)
- uv_close((uv_handle_t*)julia_session_ptr->julia_in,&pipes_done);
- if(julia_session_ptr->julia_out != 0)
- uv_close((uv_handle_t*)julia_session_ptr->julia_out,&pipes_done);
- if(julia_session_ptr->julia_err != 0)
- uv_close((uv_handle_t*)julia_session_ptr->julia_err,&pipes_done);
- if(julia_session_ptr->sock != 0)
- uv_close((uv_handle_t*)julia_session_ptr->sock,&socketClosed);
-
- if(julia_session_ptr->proc != 0) {
- // kill the julia process
- uv_process_kill(julia_session_ptr->proc, 9);
- uv_close((uv_handle_t*)julia_session_ptr->proc,&process_exited);
- }
-}
-
-void cleanup_web_sessions(julia_session *session, time_t t)
-{
- vector<string> web_session_zombies;
- for (map<string, web_session>::iterator iter = session->web_session_map.begin(); iter != session->web_session_map.end(); iter++)
- {
- if ((t == 0) || (t-(iter->second).update_time >= WEB_SESSION_TIMEOUT))
- web_session_zombies.push_back(iter->first);
- }
- for (size_t j = 0; j < web_session_zombies.size(); j++)
- {
- cout<<"User \""<<session->web_session_map[web_session_zombies[j]].user_name<<"\" has left session \""<<session->session_name<<"\".\n";
- session->web_session_map.erase(web_session_zombies[j]);
- }
-}
-
-void cleanup_session(julia_session *session)
-{
- if(session->status==SESSION_NORMAL)
- session->status = SESSION_TERMINATING;
- close_process(session);
-}
-
-void watchdog(uv_timer_t* handle, int status)
-{
- // get the current time