The new module configuration interface.

Configuration and building example:

  ./configure
  ./configure python
  ./configure php
  ./configure go
  make all

or

  ./configure
  make nginext
  ./configure python
  make python
  ./configure php
  make php
  ./configure go
  make go

Modules configuration options and building examples:

  ./configure python --module=python2 --config=python2.7-config
  make python2

  ./configure php --module=php7 --config=php7.0-config
                  --lib-path=/usr/local/php7.0
  make php7

  ./configure go --go=go1.6 --go-path=${HOME}/go1.6
  make go1.6
This commit is contained in:
Igor Sysoev
2017-08-17 21:47:19 +03:00
parent 5ef8e0ee89
commit 949548da29
29 changed files with 1376 additions and 474 deletions

View File

@@ -20,6 +20,11 @@ NXT_EXEC_LINK = $NXT_EXEC_LINK $NXT_LD_OPT
NXT_SHARED_LOCAL_LINK = $NXT_SHARED_LOCAL_LINK $NXT_LD_OPT NXT_SHARED_LOCAL_LINK = $NXT_SHARED_LOCAL_LINK $NXT_LD_OPT
NXT_MODULE_LINK = $NXT_MODULE_LINK $NXT_LD_OPT NXT_MODULE_LINK = $NXT_MODULE_LINK $NXT_LD_OPT
.PHONY: $NXT_BIN
$NXT_BIN: $NXT_BUILD_DIR/$NXT_BIN
all: $NXT_BIN
END END
@@ -169,24 +174,19 @@ $echo >> $NXT_MAKEFILE
# Object files list. # Object files list.
nxt_modules_obj=`$echo $NXT_MODULES_SRC | sed -e "s/\.c$/\.o/"`
$echo "NXT_OBJS = \\" >> $NXT_MAKEFILE $echo "NXT_OBJS = \\" >> $NXT_MAKEFILE
for nxt_src in $NXT_MAKE_SRCS $NXT_MODULES_SRCS for nxt_src in $NXT_MAKE_SRCS
do do
nxt_obj=`$echo $nxt_src | sed -e "s/\.c$/\.o/"` nxt_obj=`$echo $nxt_src | sed -e "s/\.c$/\.o/"`
$echo " $NXT_BUILD_DIR/$nxt_obj \\" >> $NXT_MAKEFILE $echo " $NXT_BUILD_DIR/$nxt_obj \\" >> $NXT_MAKEFILE
done done
$echo " $nxt_modules_obj" >> $NXT_MAKEFILE
$echo >> $NXT_MAKEFILE $echo >> $NXT_MAKEFILE
# nginext executable. # nginext executable.
NXT_BIN=nginext
cat << END >> $NXT_MAKEFILE cat << END >> $NXT_MAKEFILE
$NXT_BUILD_DIR/$NXT_BIN: $NXT_BUILD_DIR/$NXT_LIB_STATIC \\ $NXT_BUILD_DIR/$NXT_BIN: $NXT_BUILD_DIR/$NXT_LIB_STATIC \\
@@ -215,48 +215,17 @@ END
done done
# nxt_modules.c.
cat << END >> $NXT_MAKEFILE
$nxt_modules_obj: $NXT_MODULES_SRC \$(NXT_DEPS)
\$(CC) -c \$(CFLAGS) \$(NXT_INCS) \\
$NXT_LIB_AUX_CFLAGS \\
-o $nxt_modules_obj \\
$NXT_MODULES_SRC
END
if [ $NXT_PYTHON_MODULE != NO ]; then
. auto/modules/python/make
fi
if [ $NXT_PHP_MODULE != NO ]; then
. auto/modules/php/make
fi
if [ $NXT_GO_MODULE != NO ]; then
. auto/modules/go/make
fi
# Makefile. # Makefile.
# *.dSYM is MacOSX Clang debug information. # *.dSYM is MacOSX Clang debug information.
cat << END > Makefile cat << END > Makefile
.PHONY: $NXT_BIN lib_test
all: $NXT_BIN
include $NXT_MAKEFILE include $NXT_MAKEFILE
.PHONY: lib_test
lib_test: $NXT_BUILD_DIR/lib_unit_test $NXT_BUILD_DIR/utf8_file_name_test lib_test: $NXT_BUILD_DIR/lib_unit_test $NXT_BUILD_DIR/utf8_file_name_test
clean: clean:
rm -rf $NXT_BUILD_DIR *.dSYM Makefile rm -rf $NXT_BUILD_DIR *.dSYM Makefile
$NXT_BIN: $NXT_BUILD_DIR/$NXT_BIN
END END

37
auto/modules/conf Normal file
View File

@@ -0,0 +1,37 @@
# Copyright (C) Igor Sysoev
# Copyright (C) NGINX, Inc.
if [ ! -f $NXT_AUTOCONF_DATA ]; then
echo
echo Please run common $0 before configuring module \"$nxt_module\".
echo
exit 1
fi
. $NXT_AUTOCONF_DATA
case "$nxt_module" in
python)
. auto/modules/python
;;
php)
. auto/modules/php
;;
go)
. auto/modules/go
;;
*)
echo
echo $0: error: invalid module \"$nxt_module\".
echo
exit 1
;;
esac

109
auto/modules/go Normal file
View File

@@ -0,0 +1,109 @@
# Copyright (C) Max Romanov
# Copyright (C) NGINX, Inc.
shift
NXT_GO=go
for nxt_option; do
case "$nxt_option" in
-*=*) value=`$echo "$nxt_option" | sed -e 's/[-_a-zA-Z0-9]*=//'` ;;
*) value="" ;;
esac
case "$nxt_option" in
--go=*) NXT_GO="$value" ;;
--go-path=*) NXT_GO_PATH="$value" ;;
--help)
cat << END
--go=NAME set go executable
--go-path=PATH set GOPATH variable to install package
END
exit 0
;;
*)
$echo
$echo $0: error: invalid Go option \"$nxt_option\"
$echo
exit 1
;;
esac
done
$echo "configuring Go package"
$echo "configuring Go package ..." >> $NXT_AUTOCONF_ERR
$echo -n "checking for Go ..."
$echo "checking for Go ..." >> $NXT_AUTOCONF_ERR
nxt_go_test="GOPATH=`pwd` CGO_CPPFLAGS=-DNXT_CONFIGURE \
\"${NXT_GO}\" build -o build/nxt_go_gen.a --buildmode=c-archive nginext"
if /bin/sh -c "$nxt_go_test" >> $NXT_AUTOCONF_ERR 2>&1; then
$echo " found"
NXT_GO_VERSION="`${NXT_GO} version`"
$echo " + ${NXT_GO_VERSION}"
else
$echo "----------" >> $NXT_AUTOCONF_ERR
$echo $nxt_go_test >> $NXT_AUTOCONF_ERR
$echo "----------" >> $NXT_AUTOCONF_ERR
$echo
$echo
$echo $0: error: no Go found.
$echo
exit 1;
fi
NXT_GO_PATH=${NXT_GO_PATH=`go env GOPATH`}
NXT_GO_PATH=${NXT_GO_PATH:-`pwd`/${NXT_GO}}
$echo " + Go package path: \"${NXT_GO_PATH}\""
if grep ^$NXT_GO: $NXT_MAKEFILE 2>&1 > /dev/null; then
$echo
$echo $0: error: duplicate \"$NXT_GO\" package configured.
$echo
exit 1;
fi
cat << END >> $NXT_MAKEFILE
.PHONY: ${NXT_GO}
NXT_ROOT = `pwd`
GOPATH = $NXT_GO_PATH
GOOS = `go env GOOS`
GOARCH = `go env GOARCH`
${NXT_GO}:
install -d \$(GOPATH)/src/nginext
install -p ./src/nginext/*.c ./src/nginext/*.h \\
./src/nginext/*.go \$(GOPATH)/src/nginext/
CGO_CFLAGS="-I\$(NXT_ROOT)/build -I\$(NXT_ROOT)/src" \\
CGO_LDFLAGS="-L\$(NXT_ROOT)/build" \\
GOPATH=$NXT_GO_PATH \\
go install -v nginext
${NXT_GO}-uninstall:
rm -rf \$(GOPATH)/src/nginext
rm -f \$(GOPATH)/pkg/\$(GOOS)_\$(GOARCH)/nginext.a
END
sed -i.bak -e "s/\(all:.*\)/\1 ${NXT_GO}/" $NXT_MAKEFILE

152
auto/modules/php Normal file
View File

@@ -0,0 +1,152 @@
# Copyright (C) Max Romanov
# Copyright (C) Igor Sysoev
# Copyright (C) NGINX, Inc.
shift
for nxt_option; do
case "$nxt_option" in
-*=*) value=`$echo "$nxt_option" | sed -e 's/[-_a-zA-Z0-9]*=//'` ;;
*) value="" ;;
esac
case "$nxt_option" in
--config=*) NXT_PHP_CONFIG="$value" ;;
--module=*) NXT_PHP_MODULE="$value" ;;
--lib-path=*) NXT_PHP_LIB_PATH="$value" ;;
--help)
cat << END
--config=NAME set php-config name
--module=NAME set php module name
--lib-path=PATH set path to libphp.so library
END
exit 0
;;
*)
$echo
$echo $0: error: invalid PHP option \"$nxt_option\"
$echo
exit 1
;;
esac
done
NXT_PHP_CONFIG=${NXT_PHP_CONFIG=php-config}
NXT_PHP=${NXT_PHP_CONFIG%-config*}
NXT_PHP_MODULE=${NXT_PHP_MODULE=${NXT_PHP##*/}}
NXT_PHP_LIB_PATH=${NXT_PHP_LIB_PATH=}
$echo "configuring PHP module"
$echo "configuring PHP module ..." >> $NXT_AUTOCONF_ERR
$echo -n "checking for PHP ..."
$echo "checking for PHP ..." >> $NXT_AUTOCONF_ERR
NXT_PHP_LDFLAGS=
if /bin/sh -c "${NXT_PHP_CONFIG} --version" >> $NXT_AUTOCONF_ERR 2>&1; then
$echo " found"
NXT_PHP_VERSION="`${NXT_PHP_CONFIG} --version`"
$echo " + PHP version: ${NXT_PHP_VERSION}"
$echo " + PHP SAPI: [`${NXT_PHP_CONFIG} --php-sapis`]"
NXT_PHP_INCLUDE="`${NXT_PHP_CONFIG} --includes`"
NXT_PHP_LIB="-lphp${NXT_PHP_VERSION%%.*}"
if [ "$NXT_PHP_LIB_PATH" != "" ]; then
# "php-config --ldflags" does not contain path to libphp.
NXT_PHP_LDFLAGS="-L${NXT_PHP_LIB_PATH} -Wl,-rpath ${NXT_PHP_LIB_PATH}"
fi
nxt_feature="PHP embed SAPI"
nxt_feature_name=NXT_HAVE_PHP
nxt_feature_run=no
nxt_feature_incs="${NXT_PHP_INCLUDE}"
nxt_feature_libs="${NXT_PHP_LIB} ${NXT_PHP_LDFLAGS}"
nxt_feature_test="
#include <php.h>
#include <php_main.h>
int main() {
php_request_startup();
return 0;
}"
. auto/feature
if [ $nxt_found = no ]; then
$echo
$echo $0: error: no PHP embed SAPI found.
$echo
exit 1;
fi
else
$echo
$echo $0: error: no PHP found.
$echo
exit 1;
fi
if grep ^$NXT_PHP_MODULE: $NXT_MAKEFILE 2>&1 > /dev/null; then
$echo
$echo $0: error: duplicate \"$NXT_PHP_MODULE\" module configured.
$echo
exit 1;
fi
$echo " + PHP module: nginext.${NXT_PHP_MODULE}"
$echo >> $NXT_MAKEFILE
NXT_PHP_MODULE_SRCS=" \
src/nxt_php_sapi.c \
"
# The php module object files.
nxt_objs=
for nxt_src in $NXT_PHP_MODULE_SRCS; do
nxt_obj=`$echo $nxt_src | sed -e "s/\.c$/-$NXT_PHP_MODULE.o/"`
nxt_objs="$nxt_objs $NXT_BUILD_DIR/$nxt_obj"
cat << END >> $NXT_MAKEFILE
$NXT_BUILD_DIR/$nxt_obj: $nxt_src
\$(CC) -c \$(CFLAGS) \$(NXT_INCS) $NXT_PHP_INCLUDE \\
-o $NXT_BUILD_DIR/$nxt_obj $nxt_src
END
done
cat << END >> $NXT_MAKEFILE
.PHONY: ${NXT_PHP_MODULE}
${NXT_PHP_MODULE}: $NXT_BUILD_DIR/nginext.${NXT_PHP_MODULE}
$NXT_BUILD_DIR/nginext.${NXT_PHP_MODULE}: $nxt_objs
$NXT_MODULE_LINK -o $NXT_BUILD_DIR/nginext.${NXT_PHP_MODULE} \\
$nxt_objs ${NXT_PHP_LIB} ${NXT_PHP_LDFLAGS}
END
sed -i.bak -e "s/\(all:.*\)/\1 ${NXT_PHP_MODULE}/" $NXT_MAKEFILE

148
auto/modules/python Normal file
View File

@@ -0,0 +1,148 @@
# Copyright (C) Valentin V. Bartenev
# Copyright (C) Igor Sysoev
# Copyright (C) NGINX, Inc.
shift
for nxt_option; do
case "$nxt_option" in
-*=*) value=`$echo "$nxt_option" | sed -e 's/[-_a-zA-Z0-9]*=//'` ;;
*) value="" ;;
esac
case "$nxt_option" in
--config=*) NXT_PYTHON_CONFIG="$value" ;;
--module=*) NXT_PYTHON_MODULE="$value" ;;
--help)
cat << END
--config=NAME set python-config name
--module=NAME set python module name
END
exit 0
;;
*)
$echo
$echo $0: error: invalid Python option \"$nxt_option\"
$echo
exit 1
;;
esac
done
NXT_PYTHON_CONFIG=${NXT_PYTHON_CONFIG=python-config}
NXT_PYTHON=${NXT_PYTHON_CONFIG%-config*}
NXT_PYTHON_MODULE=${NXT_PYTHON_MODULE=${NXT_PYTHON##*/}}
$echo "configuring Python module"
$echo "configuring Python module ..." >> $NXT_AUTOCONF_ERR
nxt_found=no
if /bin/sh -c "$NXT_PYTHON_CONFIG --prefix" >> $NXT_AUTOCONF_ERR 2>&1; then
NXT_PYTHON_INCLUDE=`${NXT_PYTHON_CONFIG} --includes`
NXT_PYTHON_LIBS=`${NXT_PYTHON_CONFIG} --ldflags`
nxt_feature="Python"
nxt_feature_name=NXT_HAVE_PYTHON
nxt_feature_run=no
nxt_feature_incs="${NXT_PYTHON_INCLUDE}"
nxt_feature_libs="${NXT_PYTHON_LIBS}"
nxt_feature_test="
#include <Python.h>
int main() {
Py_Initialize();
return 0;
}"
. auto/feature
else
$echo "checking for Python ... not found"
fi
if [ $nxt_found = no ]; then
$echo
$echo $0: error: no Python found.
$echo
exit 1;
fi
nxt_feature="Python version"
nxt_feature_name=NXT_PYTHON_VERSION
nxt_feature_run=value
nxt_feature_incs="${NXT_PYTHON_INCLUDE}"
nxt_feature_libs="${NXT_PYTHON_LIBS}"
nxt_feature_test="
#include <Python.h>
#include <stdio.h>
int main() {
printf("PY_VERSION");
return 0;
}"
. auto/feature
if grep ^$NXT_PYTHON_MODULE: $NXT_MAKEFILE 2>&1 > /dev/null; then
$echo
$echo $0: error: duplicate \"$NXT_PYTHON_MODULE\" module configured.
$echo
exit 1;
fi
$echo " + Python module: nginext.${NXT_PYTHON_MODULE}"
$echo >> $NXT_MAKEFILE
NXT_PYTHON_MODULE_SRCS=" \
src/nxt_python_wsgi.c \
"
# The python module object files.
nxt_objs=
for nxt_src in $NXT_PYTHON_MODULE_SRCS; do
nxt_obj=`$echo $nxt_src | sed -e "s/\.c$/-$NXT_PYTHON_MODULE.o/"`
nxt_objs="$nxt_objs $NXT_BUILD_DIR/$nxt_obj"
cat << END >> $NXT_MAKEFILE
$NXT_BUILD_DIR/$nxt_obj: $nxt_src
\$(CC) -c \$(CFLAGS) \$(NXT_INCS) $NXT_PYTHON_INCLUDE \\
-o $NXT_BUILD_DIR/$nxt_obj $nxt_src
END
done
cat << END >> $NXT_MAKEFILE
.PHONY: ${NXT_PYTHON_MODULE}
${NXT_PYTHON_MODULE}: $NXT_BUILD_DIR/nginext.${NXT_PYTHON_MODULE}
$NXT_BUILD_DIR/nginext.${NXT_PYTHON_MODULE}: $nxt_objs
$NXT_MODULE_LINK -o $NXT_BUILD_DIR/nginext.${NXT_PYTHON_MODULE} \\
$nxt_objs $NXT_PYTHON_LIBS
END
sed -i.bak -e "s/\(all:.*\)/\1 ${NXT_PYTHON_MODULE}/" $NXT_MAKEFILE

View File

@@ -41,16 +41,6 @@ NXT_TEST_BUILD_HPUX_SENDFILE=NO
NXT_LIB_UNIT_TEST=NO NXT_LIB_UNIT_TEST=NO
NXT_PYTHON=python
NXT_PYTHON_MODULE=NO
NXT_PHP=php
NXT_PHP_LDFLAGS=
NXT_PHP_MODULE=NO
NXT_GO=go
NXT_GO_MODULE=NO
for nxt_option for nxt_option
do do
case "$nxt_option" in case "$nxt_option" in
@@ -96,16 +86,6 @@ do
--with-lib-unit-tests) NXT_LIB_UNIT_TEST=YES ;; --with-lib-unit-tests) NXT_LIB_UNIT_TEST=YES ;;
--with-python=*) NXT_PYTHON="$value" ;;
--with-python_module) NXT_PYTHON_MODULE=YES ;;
--with-php=*) NXT_PHP="$value" ;;
--with-php-ldflags=*) NXT_PHP_LDFLAGS="$value" ;;
--with-php_module) NXT_PHP_MODULE=YES ;;
--with-go=*) NXT_GO="$value" ;;
--with-go_module) NXT_GO_MODULE=YES ;;
*) *)
$echo $echo
$echo "$0: error: invalid option \"$nxt_option\"". $echo "$0: error: invalid option \"$nxt_option\"".

View File

@@ -26,7 +26,6 @@ case "$NXT_SYSTEM" in
NXT_SHARED_LOCAL_LINK="\$(CC) -shared \ NXT_SHARED_LOCAL_LINK="\$(CC) -shared \
-Wl,-soname,\\\$\$ORIGIN/libnxt.so" -Wl,-soname,\\\$\$ORIGIN/libnxt.so"
NXT_MODULE_LINK="\$(CC) -shared" NXT_MODULE_LINK="\$(CC) -shared"
NXT_MODULE_LINK="\$(CC) -shared"
# "-Wl,-E" exports symbols of executable file. # "-Wl,-E" exports symbols of executable file.
NXT_EXEC_LINK="\$(CC) -Wl,-E" NXT_EXEC_LINK="\$(CC) -Wl,-E"
@@ -104,8 +103,8 @@ case "$NXT_SYSTEM" in
# MacOSX 10.6 (Snow Leopard) has deprecated ucontext(3). # MacOSX 10.6 (Snow Leopard) has deprecated ucontext(3).
# MacOSX 10.7 (Lion) has deprecated system OpenSSL. # MacOSX 10.7 (Lion) has deprecated system OpenSSL.
# MAC_OS_X_VERSION_MIN_REQUIRED macro does not help. # MAC_OS_X_VERSION_MIN_REQUIRED macro does not help.
# The minimum version allowed for i386 is 10.4 (Tiger). # "-rpath" is supported since MacOSX 10.5 (Leopard).
NXT_CFLAGS="$NXT_CFLAGS -mmacosx-version-min=10.4" NXT_CFLAGS="$NXT_CFLAGS -mmacosx-version-min=10.5"
NXT_STATIC_LINK="ar -r -c" NXT_STATIC_LINK="ar -r -c"
NXT_SHARED_LINK="\$(CC) -dynamiclib" NXT_SHARED_LINK="\$(CC) -dynamiclib"
@@ -113,7 +112,8 @@ case "$NXT_SYSTEM" in
-install_name @executable_path/libnxt.dylib" -install_name @executable_path/libnxt.dylib"
# Prior to MacOSX 10.5 (Leopard) only bundles could be unloaded. # Prior to MacOSX 10.5 (Leopard) only bundles could be unloaded.
NXT_MODULE_LINK="\$(CC) -bundle -undefined dynamic_lookup" # NXT_MODULE_LINK="\$(CC) -bundle -undefined dynamic_lookup"
NXT_MODULE_LINK="\$(CC) -dynamiclib -undefined dynamic_lookup"
NXT_EXEC_LINK="\$(CC)" NXT_EXEC_LINK="\$(CC)"
NXT_SHARED_LOCAL_EXEC_LINK= NXT_SHARED_LOCAL_EXEC_LINK=

View File

@@ -41,7 +41,7 @@ case "$NXT_SYSTEM" in
echo=echo echo=echo
CC=${CC:-cc} CC=${CC:-cc}
NXT_TEST_CFLAGS="$NXT_TEST_CFLAGS -mmacosx-version-min=10.4" NXT_TEST_CFLAGS="$NXT_TEST_CFLAGS -mmacosx-version-min=10.5"
;; ;;
AIX) AIX)

24
auto/save Normal file
View File

@@ -0,0 +1,24 @@
# Copyright (C) Igor Sysoev
# Copyright (C) NGINX, Inc.
cat << END > $NXT_AUTOCONF_DATA
CC='$CC'
CFLAGS='$CFLAGS'
NXT_CFLAGS='$NXT_CFLAGS'
NXT_CC_OPT='$NXT_CC_OPT'
NXT_LD_OPT='$NXT_LD_OPT'
NXT_MODULE_LINK='$NXT_MODULE_LINK'
NXT_TEST_CFLAGS='$NXT_TEST_CFLAGS'
NXT_TEST_LIBS='$NXT_TEST_LIBS'
echo=$NXT_BUILD_DIR/echo
NXT_LIB_AUX_CFLAGS=
NXT_LIB_AUX_LIBS=
END

View File

@@ -147,6 +147,7 @@ NXT_LIB_SRCS=" \
src/nxt_controller.c \ src/nxt_controller.c \
src/nxt_router.c \ src/nxt_router.c \
src/nxt_application.c \ src/nxt_application.c \
src/nxt_go.c \
src/nxt_port_hash.c \ src/nxt_port_hash.c \
" "

View File

@@ -73,6 +73,8 @@ fi
# FreeBSD dlopen() is in libc. # FreeBSD dlopen() is in libc.
# MacOSX libdl.dylib is a symlink to libSystem.dylib. # MacOSX libdl.dylib is a symlink to libSystem.dylib.
# GCC5 AddressSanitizer intercepts dlopen() and dlclose() but not dlsym()
# so all dynamic linker functions should be tested.
NXT_LIBDL= NXT_LIBDL=
@@ -85,7 +87,9 @@ nxt_feature_test="#include <stdlib.h>
#include <dlfcn.h> #include <dlfcn.h>
int main() { int main() {
dlopen(NULL, 0); void *h = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL);
dlsym(h, \"\");
dlclose(h);
return 0; return 0;
}" }"
. auto/feature . auto/feature

33
configure vendored
View File

@@ -20,16 +20,37 @@ NXT_TEST_CFLAGS=${NXT_TEST_CFLAGS=}
NXT_TEST_LIBS=${NXT_TEST_LIBS=} NXT_TEST_LIBS=${NXT_TEST_LIBS=}
NXT_UNIT_TEST_TARGETS=${NXT_UNIT_TEST_TARGETS=} NXT_UNIT_TEST_TARGETS=${NXT_UNIT_TEST_TARGETS=}
# STUB
NXT_BUILD_DIR=build
NXT_AUTOTEST=$NXT_BUILD_DIR/autotest
NXT_AUTOCONF_ERR=$NXT_BUILD_DIR/autoconf.err
NXT_AUTOCONF_DATA=$NXT_BUILD_DIR/autoconf.data
NXT_AUTO_CONFIG_H=$NXT_BUILD_DIR/nxt_auto_config.h
NXT_MAKEFILE=$NXT_BUILD_DIR/Makefile
NXT_BIN=nginext
nxt_module=${1:-no}
case $nxt_module in
no|--*)
;;
unit)
shift
;;
*)
. auto/modules/conf
exit 0
;;
esac
. auto/os/test . auto/os/test
. auto/options . auto/options
test -d $NXT_BUILD_DIR || mkdir $NXT_BUILD_DIR test -d $NXT_BUILD_DIR || mkdir $NXT_BUILD_DIR
NXT_AUTOTEST=$NXT_BUILD_DIR/autotest
NXT_AUTOCONF_ERR=$NXT_BUILD_DIR/autoconf.err
NXT_AUTO_CONFIG_H=$NXT_BUILD_DIR/nxt_auto_config.h
NXT_MAKEFILE=$NXT_BUILD_DIR/Makefile
> $NXT_AUTOCONF_ERR > $NXT_AUTOCONF_ERR
> $NXT_AUTO_CONFIG_H > $NXT_AUTO_CONFIG_H
@@ -102,6 +123,7 @@ fi
. auto/test_build . auto/test_build
. auto/sources . auto/sources
. auto/save
# LOOK # LOOK
@@ -113,5 +135,4 @@ NXT_LIB_AUX_LIBS="$NXT_OPENSSL_LIBS $NXT_GNUTLS_LIBS \\
$NXT_CYASSL_LIBS $NXT_POLARSSL_LIBS \\ $NXT_CYASSL_LIBS $NXT_POLARSSL_LIBS \\
$NXT_PCRE_LIB" $NXT_PCRE_LIB"
. auto/modules/conf
. auto/make . auto/make

View File

@@ -11,8 +11,22 @@
#include <nxt_application.h> #include <nxt_application.h>
#include <nxt_master_process.h> #include <nxt_master_process.h>
#include <glob.h>
typedef struct {
nxt_str_t type;
nxt_str_t version;
nxt_str_t file;
} nxt_module_t;
static nxt_buf_t *nxt_discovery_modules(nxt_task_t *task, const char *path);
static nxt_int_t nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp,
nxt_array_t *modules, const char *name);
static nxt_app_module_t *nxt_app_module_load(nxt_task_t *task,
const char *name);
nxt_application_module_t *nxt_app_modules[NXT_APP_MAX];
static nxt_thread_mutex_t nxt_app_mutex; static nxt_thread_mutex_t nxt_app_mutex;
static nxt_thread_cond_t nxt_app_cond; static nxt_thread_cond_t nxt_app_cond;
@@ -22,14 +36,243 @@ static nxt_http_fields_hash_t *nxt_app_request_fields_hash;
static nxt_application_module_t *nxt_app; static nxt_application_module_t *nxt_app;
nxt_int_t
nxt_discovery_start(nxt_task_t *task, void *data)
{
nxt_buf_t *b;
nxt_port_t *main_port;
nxt_runtime_t *rt;
nxt_debug(task, "DISCOVERY");
b = nxt_discovery_modules(task, "build/nginext.*");
rt = task->thread->runtime;
main_port = rt->port_by_type[NXT_PROCESS_MASTER];
nxt_port_socket_write(task, main_port, NXT_PORT_MSG_MODULES, -1,
0, -1, b);
return NXT_OK;
}
static void
nxt_discovery_completion_handler(nxt_task_t *task, void *obj, void *data)
{
nxt_mp_t *mp;
nxt_buf_t *b;
b = obj;
mp = b->data;
nxt_mp_destroy(mp);
exit(0);
}
static nxt_buf_t *
nxt_discovery_modules(nxt_task_t *task, const char *path)
{
char *name;
u_char *p, *end;
size_t size;
glob_t glb;
nxt_mp_t *mp;
nxt_buf_t *b;
nxt_int_t ret;
nxt_uint_t i, n;
nxt_array_t *modules;
nxt_module_t *module;
b = NULL;
mp = nxt_mp_create(1024, 128, 256, 32);
if (mp == NULL) {
return b;
}
ret = glob(path, 0, NULL, &glb);
if (ret == 0) {
n = glb.gl_pathc;
modules = nxt_array_create(mp, n, sizeof(nxt_module_t));
if (modules == NULL) {
goto fail;
}
for (i = 0; i < n; i++) {
name = glb.gl_pathv[i];
ret = nxt_discovery_module(task, mp, modules, name);
if (ret != NXT_OK) {
goto fail;
}
}
size = sizeof("[]") - 1;
module = modules->elts;
n = modules->nelts;
for (i = 0; i < n; i++) {
nxt_debug(task, "module: %V %V %V",
&module[i].type, &module[i].version, &module[i].file);
size += sizeof("{\"type\": \"\",") - 1;
size += sizeof(" \"version\": \"\",") - 1;
size += sizeof(" \"file\": \"\"},") - 1;
size += module[i].type.length
+ module[i].version.length
+ module[i].file.length;
}
b = nxt_buf_mem_alloc(mp, size, 0);
if (b == NULL) {
goto fail;
}
b->completion_handler = nxt_discovery_completion_handler;
p = b->mem.free;
end = b->mem.end;
*p++ = '[';
for (i = 0; i < n; i++) {
p = nxt_sprintf(p, end,
"{\"type\": \"%V\", \"version\": \"%V\", \"file\": \"%V\"},",
&module[i].type, &module[i].version, &module[i].file);
}
*p++ = ']';
b->mem.free = p;
}
fail:
globfree(&glb);
return b;
}
static nxt_int_t
nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules,
const char *name)
{
void *dl;
nxt_str_t *s;
nxt_int_t ret;
nxt_uint_t i, n;
nxt_module_t *module;
nxt_application_module_t *app;
/*
* Only memory allocation failure should return NXT_ERROR.
* Any module processing errors are ignored.
*/
ret = NXT_ERROR;
dl = dlopen(name, RTLD_GLOBAL | RTLD_NOW);
if (dl == NULL) {
nxt_log(task, NXT_LOG_CRIT, "dlopen(\"%s\"), failed: \"%s\"",
name, dlerror());
return NXT_OK;
}
app = dlsym(dl, "nxt_app_module");
if (app != NULL) {
nxt_log(task, NXT_LOG_NOTICE, "module: %V \"%s\"",
&app->version, name);
module = modules->elts;
n = modules->nelts;
for (i = 0; i < n; i++) {
if (nxt_strstr_eq(&app->version, &module[i].version)) {
nxt_log(task, NXT_LOG_NOTICE,
"ignoring %s module with the same "
"application language version %V as in %s",
name, &module[i].version, &module[i].file);
goto done;
}
}
module = nxt_array_add(modules);
if (module == NULL) {
goto fail;
}
s = nxt_str_dup(mp, &module->type, &app->type);
if (s == NULL) {
goto fail;
}
s = nxt_str_dup(mp, &module->version, &app->version);
if (s == NULL) {
goto fail;
}
module->file.length = nxt_strlen(name);
module->file.start = nxt_mp_alloc(mp, module->file.length);
if (module->file.start == NULL) {
goto fail;
}
nxt_memcpy(module->file.start, name, module->file.length);
} else {
nxt_log(task, NXT_LOG_CRIT, "dlsym(\"%s\"), failed: \"%s\"",
name, dlerror());
}
done:
ret = NXT_OK;
fail:
if (dlclose(dl) != 0) {
nxt_log(task, NXT_LOG_CRIT, "dlclose(\"%s\"), failed: \"%s\"",
name, dlerror());
}
return ret;
}
nxt_int_t nxt_int_t
nxt_app_start(nxt_task_t *task, void *data) nxt_app_start(nxt_task_t *task, void *data)
{ {
nxt_int_t ret; nxt_int_t ret;
nxt_app_lang_module_t *lang;
nxt_common_app_conf_t *app_conf; nxt_common_app_conf_t *app_conf;
app_conf = data; app_conf = data;
lang = nxt_app_lang_module(task->thread->runtime, &app_conf->type);
if (nxt_slow_path(lang == NULL)) {
nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"",
&app_conf->type);
return NXT_ERROR;
}
nxt_app = lang->module;
if (nxt_app == NULL) {
nxt_debug(task, "application language module: %V \"%s\"",
&lang->version, lang->file);
nxt_app = nxt_app_module_load(task, lang->file);
}
if (nxt_slow_path(nxt_thread_mutex_create(&nxt_app_mutex) != NXT_OK)) { if (nxt_slow_path(nxt_thread_mutex_create(&nxt_app_mutex) != NXT_OK)) {
return NXT_ERROR; return NXT_ERROR;
} }
@@ -38,8 +281,6 @@ nxt_app_start(nxt_task_t *task, void *data)
return NXT_ERROR; return NXT_ERROR;
} }
nxt_app = nxt_app_modules[app_conf->type_id];
ret = nxt_app->init(task, data); ret = nxt_app->init(task, data);
if (nxt_slow_path(ret != NXT_OK)) { if (nxt_slow_path(ret != NXT_OK)) {
@@ -53,6 +294,24 @@ nxt_app_start(nxt_task_t *task, void *data)
} }
static nxt_app_module_t *
nxt_app_module_load(nxt_task_t *task, const char *name)
{
void *dl;
dl = dlopen(name, RTLD_GLOBAL | RTLD_LAZY);
if (dl != NULL) {
return dlsym(dl, "nxt_app_module");
}
nxt_log(task, NXT_LOG_CRIT, "dlopen(\"%s\"), failed: \"%s\"",
name, dlerror());
return NULL;
}
nxt_int_t nxt_int_t
nxt_app_http_init(nxt_task_t *task, nxt_runtime_t *rt) nxt_app_http_init(nxt_task_t *task, nxt_runtime_t *rt)
{ {
@@ -681,30 +940,56 @@ nxt_app_msg_write_raw(nxt_task_t *task, nxt_app_wmsg_t *msg, const u_char *c,
} }
nxt_app_lang_module_t *
nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name)
{
u_char *p, *end, *version;
size_t type_length, version_length;
nxt_uint_t i, n;
nxt_app_lang_module_t *lang;
end = name->start + name->length;
version = end;
for (p = name->start; p < end; p++) {
if (*p == ' ') {
version = p + 1;
break;
}
if (*p >= '0' && *p <= '9') {
version = p;
break;
}
}
type_length = p - name->start;
version_length = end - version;
lang = rt->languages->elts;
n = rt->languages->nelts;
for (i = 0; i < n; i++) {
if (nxt_str_eq(&lang[i].type, name->start, type_length)
&& nxt_str_start(&lang[i].version, version, version_length))
{
return &lang[i];
}
}
return NULL;
}
nxt_app_type_t nxt_app_type_t
nxt_app_parse_type(nxt_str_t *str) nxt_app_parse_type(nxt_str_t *str)
{ {
if (nxt_str_eq(str, "python", 6)) { if (nxt_str_eq(str, "python", 6)) {
return NXT_APP_PYTHON; return NXT_APP_PYTHON;
} else if (nxt_str_eq(str, "python2", 7)) {
return NXT_APP_PYTHON2;
} else if (nxt_str_eq(str, "python3", 7)) {
return NXT_APP_PYTHON3;
} else if (nxt_str_eq(str, "php", 3)) { } else if (nxt_str_eq(str, "php", 3)) {
return NXT_APP_PHP; return NXT_APP_PHP;
} else if (nxt_str_eq(str, "php5", 4)) {
return NXT_APP_PHP5;
} else if (nxt_str_eq(str, "php7", 4)) {
return NXT_APP_PHP7;
} else if (nxt_str_eq(str, "ruby", 4)) {
return NXT_APP_RUBY;
} else if (nxt_str_eq(str, "go", 2)) { } else if (nxt_str_eq(str, "go", 2)) {
return NXT_APP_GO; return NXT_APP_GO;

View File

@@ -10,20 +10,26 @@
typedef enum { typedef enum {
NXT_APP_UNKNOWN = 0,
NXT_APP_PYTHON, NXT_APP_PYTHON,
NXT_APP_PYTHON2,
NXT_APP_PYTHON3,
NXT_APP_PHP, NXT_APP_PHP,
NXT_APP_PHP5,
NXT_APP_PHP7,
NXT_APP_RUBY,
NXT_APP_GO, NXT_APP_GO,
NXT_APP_MAX, NXT_APP_UNKNOWN,
} nxt_app_type_t; } nxt_app_type_t;
typedef struct nxt_app_module_s nxt_application_module_t;
typedef struct nxt_app_module_s nxt_app_module_t;
typedef struct {
nxt_str_t type;
nxt_str_t version;
char *file;
nxt_application_module_t *module;
} nxt_app_lang_module_t;
typedef struct nxt_common_app_conf_s nxt_common_app_conf_t; typedef struct nxt_common_app_conf_s nxt_common_app_conf_t;
@@ -48,7 +54,6 @@ typedef struct {
struct nxt_common_app_conf_s { struct nxt_common_app_conf_s {
nxt_str_t name; nxt_str_t name;
nxt_str_t type; nxt_str_t type;
nxt_app_type_t type_id;
nxt_str_t user; nxt_str_t user;
nxt_str_t group; nxt_str_t group;
@@ -148,13 +153,13 @@ nxt_inline u_char *
nxt_app_msg_write_length(u_char *dst, size_t length); nxt_app_msg_write_length(u_char *dst, size_t length);
/* TODO asynchronous mmap buffer assignment */ /* TODO asynchronous mmap buffer assignment */
u_char *nxt_app_msg_write_get_buf(nxt_task_t *task, nxt_app_wmsg_t *msg, NXT_EXPORT u_char *nxt_app_msg_write_get_buf(nxt_task_t *task,
size_t size); nxt_app_wmsg_t *msg, size_t size);
nxt_int_t nxt_app_msg_write(nxt_task_t *task, nxt_app_wmsg_t *msg, NXT_EXPORT nxt_int_t nxt_app_msg_write(nxt_task_t *task, nxt_app_wmsg_t *msg,
u_char *c, size_t size); u_char *c, size_t size);
nxt_int_t nxt_app_msg_write_prefixed_upcase(nxt_task_t *task, NXT_EXPORT nxt_int_t nxt_app_msg_write_prefixed_upcase(nxt_task_t *task,
nxt_app_wmsg_t *msg, const nxt_str_t *prefix, const nxt_str_t *v); nxt_app_wmsg_t *msg, const nxt_str_t *prefix, const nxt_str_t *v);
nxt_inline nxt_int_t nxt_inline nxt_int_t
@@ -178,44 +183,37 @@ nxt_app_msg_write_nvp_(nxt_task_t *task, nxt_app_wmsg_t *msg,
nxt_inline nxt_int_t nxt_app_msg_write_size(nxt_task_t *task, nxt_inline nxt_int_t nxt_app_msg_write_size(nxt_task_t *task,
nxt_app_wmsg_t *msg, size_t size); nxt_app_wmsg_t *msg, size_t size);
nxt_int_t nxt_app_msg_flush(nxt_task_t *task, nxt_app_wmsg_t *msg, NXT_EXPORT nxt_int_t nxt_app_msg_flush(nxt_task_t *task, nxt_app_wmsg_t *msg,
nxt_bool_t last); nxt_bool_t last);
nxt_int_t nxt_app_msg_write_raw(nxt_task_t *task, nxt_app_wmsg_t *msg, NXT_EXPORT nxt_int_t nxt_app_msg_write_raw(nxt_task_t *task,
const u_char *c, size_t size); nxt_app_wmsg_t *msg, const u_char *c, size_t size);
nxt_int_t nxt_app_msg_read_str(nxt_task_t *task, nxt_app_rmsg_t *msg, NXT_EXPORT nxt_int_t nxt_app_msg_read_str(nxt_task_t *task, nxt_app_rmsg_t *msg,
nxt_str_t *str); nxt_str_t *str);
size_t nxt_app_msg_read_raw(nxt_task_t *task, nxt_app_rmsg_t *msg, void *buf, NXT_EXPORT size_t nxt_app_msg_read_raw(nxt_task_t *task,
size_t size); nxt_app_rmsg_t *msg, void *buf, size_t size);
nxt_int_t nxt_app_msg_read_nvp(nxt_task_t *task, nxt_app_rmsg_t *rmsg, NXT_EXPORT nxt_int_t nxt_app_msg_read_nvp(nxt_task_t *task,
nxt_str_t *n, nxt_str_t *v); nxt_app_rmsg_t *rmsg, nxt_str_t *n, nxt_str_t *v);
nxt_int_t nxt_app_msg_read_size(nxt_task_t *task, nxt_app_rmsg_t *rmsg, NXT_EXPORT nxt_int_t nxt_app_msg_read_size(nxt_task_t *task,
size_t *size); nxt_app_rmsg_t *rmsg, size_t *size);
typedef struct nxt_app_module_s nxt_application_module_t;
typedef struct nxt_app_module_s nxt_app_module_t;
struct nxt_app_module_s { struct nxt_app_module_s {
nxt_str_t type;
nxt_str_t version;
nxt_int_t (*init)(nxt_task_t *task, nxt_int_t (*init)(nxt_task_t *task,
nxt_common_app_conf_t *conf); nxt_common_app_conf_t *conf);
nxt_int_t (*prepare_msg)(nxt_task_t *task,
nxt_app_request_t *r,
nxt_app_wmsg_t *wmsg);
nxt_int_t (*run)(nxt_task_t *task, nxt_int_t (*run)(nxt_task_t *task,
nxt_app_rmsg_t *rmsg, nxt_app_rmsg_t *rmsg,
nxt_app_wmsg_t *wmsg); nxt_app_wmsg_t *wmsg);
}; };
extern nxt_application_module_t *nxt_app_modules[NXT_APP_MAX];
nxt_int_t nxt_app_http_read_body(nxt_app_request_t *r, u_char *data, nxt_int_t nxt_app_http_read_body(nxt_app_request_t *r, u_char *data,
size_t len); size_t len);
nxt_int_t nxt_app_write(nxt_app_request_t *r, const u_char *data, size_t len); nxt_int_t nxt_app_write(nxt_app_request_t *r, const u_char *data, size_t len);
@@ -290,6 +288,11 @@ nxt_app_msg_read_length(u_char *src, size_t *length)
} }
nxt_app_lang_module_t *nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name);
nxt_app_type_t nxt_app_parse_type(nxt_str_t *str); nxt_app_type_t nxt_app_parse_type(nxt_str_t *str);
extern nxt_application_module_t nxt_go_module;
#endif /* _NXT_APPLICATION_H_INCLIDED_ */ #endif /* _NXT_APPLICATION_H_INCLIDED_ */

View File

@@ -6,6 +6,7 @@
#include <nxt_main.h> #include <nxt_main.h>
#include <nxt_conf.h> #include <nxt_conf.h>
#include <nxt_application.h>
typedef struct { typedef struct {
@@ -214,10 +215,19 @@ nxt_conf_vldt_app(nxt_conf_value_t *conf, nxt_str_t *name,
nxt_conf_value_t *value) nxt_conf_value_t *value)
{ {
nxt_str_t type; nxt_str_t type;
nxt_uint_t n;
nxt_thread_t *thread;
nxt_conf_value_t *type_value; nxt_conf_value_t *type_value;
nxt_app_lang_module_t *lang;
static nxt_str_t type_str = nxt_string("type"); static nxt_str_t type_str = nxt_string("type");
static void *members[] = {
nxt_conf_vldt_python_members,
nxt_conf_vldt_php_members,
nxt_conf_vldt_go_members,
};
type_value = nxt_conf_get_object_member(value, &type_str, NULL); type_value = nxt_conf_get_object_member(value, &type_str, NULL);
if (nxt_slow_path(type_value == NULL)) { if (nxt_slow_path(type_value == NULL)) {
@@ -230,16 +240,16 @@ nxt_conf_vldt_app(nxt_conf_value_t *conf, nxt_str_t *name,
nxt_conf_get_string(type_value, &type); nxt_conf_get_string(type_value, &type);
if (nxt_str_eq(&type, "python", 6)) { thread = nxt_thread();
return nxt_conf_vldt_object(conf, value, nxt_conf_vldt_python_members);
lang = nxt_app_lang_module(thread->runtime, &type);
if (lang == NULL) {
return NXT_ERROR;
} }
if (nxt_str_eq(&type, "php", 3)) { n = nxt_app_parse_type(&lang->type);
return nxt_conf_vldt_object(conf, value, nxt_conf_vldt_php_members); if (n != NXT_APP_UNKNOWN) {
} return nxt_conf_vldt_object(conf, value, members[n]);
if (nxt_str_eq(&type, "go", 2)) {
return nxt_conf_vldt_object(conf, value, nxt_conf_vldt_go_members);
} }
return NXT_ERROR; return NXT_ERROR;

View File

@@ -10,30 +10,17 @@
static nxt_int_t nxt_go_init(nxt_task_t *task, nxt_common_app_conf_t *conf); static nxt_int_t nxt_go_init(nxt_task_t *task, nxt_common_app_conf_t *conf);
static nxt_int_t nxt_go_prepare_msg(nxt_task_t *task,
nxt_app_request_t *r, nxt_app_wmsg_t *msg);
static nxt_int_t nxt_go_run(nxt_task_t *task, static nxt_int_t nxt_go_run(nxt_task_t *task,
nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *msg); nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *msg);
nxt_application_module_t nxt_go_module = { nxt_application_module_t nxt_go_module = {
nxt_string("go"),
nxt_string("go"),
nxt_go_init, nxt_go_init,
nxt_go_prepare_msg, nxt_go_run,
nxt_go_run
}; };
nxt_int_t
nxt_go_module_init(nxt_thread_t *thr, nxt_runtime_t *rt);
nxt_int_t
nxt_go_module_init(nxt_thread_t *thr, nxt_runtime_t *rt)
{
nxt_app_modules[NXT_APP_GO] = &nxt_go_module;
return NXT_OK;
}
extern char **environ; extern char **environ;
nxt_inline int nxt_inline int
@@ -112,82 +99,6 @@ nxt_go_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
} }
static nxt_int_t
nxt_go_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, nxt_app_wmsg_t *wmsg)
{
nxt_int_t rc;
nxt_buf_t *b;
nxt_http_field_t *field;
nxt_app_request_header_t *h;
static const nxt_str_t eof = nxt_null_string;
h = &r->header;
#define RC(S) \
do { \
rc = (S); \
if (nxt_slow_path(rc != NXT_OK)) { \
goto fail; \
} \
} while(0)
#define NXT_WRITE(N) \
RC(nxt_app_msg_write_str(task, wmsg, N))
/* TODO error handle, async mmap buffer assignment */
NXT_WRITE(&h->method);
NXT_WRITE(&h->target);
if (h->path.start == h->target.start) {
NXT_WRITE(&eof);
} else {
NXT_WRITE(&h->path);
}
if (h->query.start != NULL) {
RC(nxt_app_msg_write_size(task, wmsg,
h->query.start - h->target.start + 1));
} else {
RC(nxt_app_msg_write_size(task, wmsg, 0));
}
NXT_WRITE(&h->version);
NXT_WRITE(&h->host);
NXT_WRITE(&h->cookie);
NXT_WRITE(&h->content_type);
NXT_WRITE(&h->content_length);
RC(nxt_app_msg_write_size(task, wmsg, h->parsed_content_length));
nxt_list_each(field, h->fields) {
NXT_WRITE(&field->name);
NXT_WRITE(&field->value);
} nxt_list_loop;
/* end-of-headers mark */
NXT_WRITE(&eof);
RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size));
for(b = r->body.buf; b != NULL; b = b->next) {
RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos,
nxt_buf_mem_used_size(&b->mem)));
}
#undef NXT_WRITE
#undef RC
return NXT_OK;
fail:
return NXT_ERROR;
}
static nxt_int_t static nxt_int_t
nxt_go_run(nxt_task_t *task, nxt_go_run(nxt_task_t *task,
nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *msg) nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *msg)

View File

@@ -27,6 +27,8 @@ static nxt_int_t nxt_master_start_controller_process(nxt_task_t *task,
nxt_runtime_t *rt); nxt_runtime_t *rt);
static nxt_int_t nxt_master_start_router_process(nxt_task_t *task, static nxt_int_t nxt_master_start_router_process(nxt_task_t *task,
nxt_runtime_t *rt); nxt_runtime_t *rt);
static nxt_int_t nxt_master_start_discovery_process(nxt_task_t *task,
nxt_runtime_t *rt);
static nxt_int_t nxt_master_start_worker_process(nxt_task_t *task, static nxt_int_t nxt_master_start_worker_process(nxt_task_t *task,
nxt_runtime_t *rt, nxt_common_app_conf_t *app_conf, uint32_t stream); nxt_runtime_t *rt, nxt_common_app_conf_t *app_conf, uint32_t stream);
static nxt_int_t nxt_master_create_worker_process(nxt_task_t *task, static nxt_int_t nxt_master_create_worker_process(nxt_task_t *task,
@@ -44,6 +46,9 @@ static void nxt_master_port_socket_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg); nxt_port_recv_msg_t *msg);
static nxt_int_t nxt_master_listening_socket(nxt_sockaddr_t *sa, static nxt_int_t nxt_master_listening_socket(nxt_sockaddr_t *sa,
nxt_listening_socket_t *ls); nxt_listening_socket_t *ls);
static void nxt_master_port_modules_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg);
static int nxt_cdecl nxt_app_lang_compare(const void *v1, const void *v2);
const nxt_sig_event_t nxt_master_process_signals[] = { const nxt_sig_event_t nxt_master_process_signals[] = {
@@ -63,8 +68,6 @@ nxt_int_t
nxt_master_process_start(nxt_thread_t *thr, nxt_task_t *task, nxt_master_process_start(nxt_thread_t *thr, nxt_task_t *task,
nxt_runtime_t *rt) nxt_runtime_t *rt)
{ {
nxt_int_t ret;
rt->types |= (1U << NXT_PROCESS_MASTER); rt->types |= (1U << NXT_PROCESS_MASTER);
if (nxt_master_process_port_create(task, rt) != NXT_OK) { if (nxt_master_process_port_create(task, rt) != NXT_OK) {
@@ -73,12 +76,12 @@ nxt_master_process_start(nxt_thread_t *thr, nxt_task_t *task,
nxt_master_process_title(task); nxt_master_process_title(task);
ret = nxt_master_start_controller_process(task, rt); /*
if (ret != NXT_OK) { * The dicsovery process will send a message processed by
return ret; * nxt_master_port_modules_handler() which starts the controller
} * and router processes.
*/
return nxt_master_start_router_process(task, rt); return nxt_master_start_discovery_process(task, rt);
} }
@@ -197,8 +200,6 @@ nxt_port_master_start_worker_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
return; return;
} }
app_conf.type_id = nxt_app_parse_type(&app_conf.type);
ret = nxt_master_start_worker_process(task, task->thread->runtime, ret = nxt_master_start_worker_process(task, task->thread->runtime,
&app_conf, msg->port_msg.stream); &app_conf, msg->port_msg.stream);
@@ -216,6 +217,7 @@ static nxt_port_handler_t nxt_master_process_port_handlers[] = {
nxt_port_ready_handler, nxt_port_ready_handler,
nxt_port_master_start_worker_handler, nxt_port_master_start_worker_handler,
nxt_master_port_socket_handler, nxt_master_port_socket_handler,
nxt_master_port_modules_handler,
nxt_port_rpc_handler, nxt_port_rpc_handler,
nxt_port_rpc_handler, nxt_port_rpc_handler,
}; };
@@ -289,7 +291,7 @@ nxt_master_start_controller_process(nxt_task_t *task, nxt_runtime_t *rt)
{ {
nxt_process_init_t *init; nxt_process_init_t *init;
init = nxt_mp_get(rt->mem_pool, sizeof(nxt_process_init_t)); init = nxt_malloc(sizeof(nxt_process_init_t));
if (nxt_slow_path(init == NULL)) { if (nxt_slow_path(init == NULL)) {
return NXT_ERROR; return NXT_ERROR;
} }
@@ -308,12 +310,36 @@ nxt_master_start_controller_process(nxt_task_t *task, nxt_runtime_t *rt)
} }
static nxt_int_t
nxt_master_start_discovery_process(nxt_task_t *task, nxt_runtime_t *rt)
{
nxt_process_init_t *init;
init = nxt_malloc(sizeof(nxt_process_init_t));
if (nxt_slow_path(init == NULL)) {
return NXT_ERROR;
}
init->start = nxt_discovery_start;
init->name = "discovery";
init->user_cred = &rt->user_cred;
init->port_handlers = nxt_discovery_process_port_handlers;
init->signals = nxt_worker_process_signals;
init->type = NXT_PROCESS_DISCOVERY;
init->data = rt;
init->stream = 0;
init->restart = 0;
return nxt_master_create_worker_process(task, rt, init);
}
static nxt_int_t static nxt_int_t
nxt_master_start_router_process(nxt_task_t *task, nxt_runtime_t *rt) nxt_master_start_router_process(nxt_task_t *task, nxt_runtime_t *rt)
{ {
nxt_process_init_t *init; nxt_process_init_t *init;
init = nxt_mp_get(rt->mem_pool, sizeof(nxt_process_init_t)); init = nxt_malloc(sizeof(nxt_process_init_t));
if (nxt_slow_path(init == NULL)) { if (nxt_slow_path(init == NULL)) {
return NXT_ERROR; return NXT_ERROR;
} }
@@ -885,3 +911,130 @@ fail:
return NXT_ERROR; return NXT_ERROR;
} }
static nxt_conf_map_t nxt_app_lang_module_map[] = {
{
nxt_string("type"),
NXT_CONF_MAP_STR_COPY,
offsetof(nxt_app_lang_module_t, type),
},
{
nxt_string("version"),
NXT_CONF_MAP_STR_COPY,
offsetof(nxt_app_lang_module_t, version),
},
{
nxt_string("file"),
NXT_CONF_MAP_CSTRZ,
offsetof(nxt_app_lang_module_t, file),
},
};
static void
nxt_master_port_modules_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
{
uint32_t index;
nxt_mp_t *mp;
nxt_int_t ret;
nxt_buf_t *b;
nxt_runtime_t *rt;
nxt_conf_value_t *conf, *root, *value;
nxt_app_lang_module_t *lang;
static nxt_str_t root_path = nxt_string("/");
rt = task->thread->runtime;
if (msg->port_msg.pid != rt->port_by_type[NXT_PROCESS_DISCOVERY]->pid) {
return;
}
b = msg->buf;
if (b == NULL) {
return;
}
nxt_debug(task, "application languages: \"%*s\"",
b->mem.free - b->mem.pos, b->mem.pos);
mp = nxt_mp_create(1024, 128, 256, 32);
if (mp == NULL) {
return;
}
conf = nxt_conf_json_parse(mp, b->mem.pos, b->mem.free, NULL);
if (conf == NULL) {
goto fail;
}
root = nxt_conf_get_path(conf, &root_path);
if (root == NULL) {
goto fail;
}
for (index = 0; /* void */ ; index++) {
value = nxt_conf_get_array_element(root, index);
if (value == NULL) {
break;
}
lang = nxt_array_add(rt->languages);
if (lang == NULL) {
goto fail;
}
lang->module = NULL;
ret = nxt_conf_map_object(rt->mem_pool, value, nxt_app_lang_module_map,
nxt_nitems(nxt_app_lang_module_map), lang);
if (ret != NXT_OK) {
goto fail;
}
nxt_debug(task, "lang %V %V \"%s\"",
&lang->type, &lang->version, lang->file);
}
qsort(rt->languages->elts, rt->languages->nelts,
sizeof(nxt_app_lang_module_t), nxt_app_lang_compare);
fail:
nxt_mp_destroy(mp);
ret = nxt_master_start_controller_process(task, rt);
if (ret == NXT_OK) {
(void) nxt_master_start_router_process(task, rt);
}
}
static int nxt_cdecl
nxt_app_lang_compare(const void *v1, const void *v2)
{
int n;
size_t length;
const nxt_app_lang_module_t *lang1, *lang2;
lang1 = v1;
lang2 = v2;
length = nxt_min(lang1->version.length, lang2->version.length);
n = nxt_strncmp(lang1->version.start, lang2->version.start, length);
if (n == 0) {
n = lang1->version.length - lang2->version.length;
}
/* Negate result to move higher versions to the beginning. */
return -n;
}

View File

@@ -25,10 +25,12 @@ void nxt_master_stop_worker_processes(nxt_task_t *task, nxt_runtime_t *runtime);
nxt_int_t nxt_controller_start(nxt_task_t *task, void *data); nxt_int_t nxt_controller_start(nxt_task_t *task, void *data);
nxt_int_t nxt_router_start(nxt_task_t *task, void *data); nxt_int_t nxt_router_start(nxt_task_t *task, void *data);
nxt_int_t nxt_discovery_start(nxt_task_t *task, void *data);
nxt_int_t nxt_app_start(nxt_task_t *task, void *data); nxt_int_t nxt_app_start(nxt_task_t *task, void *data);
extern nxt_port_handler_t nxt_controller_process_port_handlers[]; extern nxt_port_handler_t nxt_controller_process_port_handlers[];
extern nxt_port_handler_t nxt_worker_process_port_handlers[]; extern nxt_port_handler_t nxt_worker_process_port_handlers[];
extern nxt_port_handler_t nxt_discovery_process_port_handlers[];
extern nxt_port_handler_t nxt_app_process_port_handlers[]; extern nxt_port_handler_t nxt_app_process_port_handlers[];
extern nxt_port_handler_t nxt_router_process_port_handlers[]; extern nxt_port_handler_t nxt_router_process_port_handlers[];
extern const nxt_sig_event_t nxt_master_process_signals[]; extern const nxt_sig_event_t nxt_master_process_signals[];

View File

@@ -16,9 +16,6 @@
static nxt_int_t nxt_php_init(nxt_task_t *task, nxt_common_app_conf_t *conf); static nxt_int_t nxt_php_init(nxt_task_t *task, nxt_common_app_conf_t *conf);
static nxt_int_t nxt_php_prepare_msg(nxt_task_t *task,
nxt_app_request_t *r, nxt_app_wmsg_t *wmsg);
static nxt_int_t nxt_php_run(nxt_task_t *task, static nxt_int_t nxt_php_run(nxt_task_t *task,
nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *wmsg); nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *wmsg);
@@ -58,8 +55,6 @@ static int nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC);
static void nxt_php_flush(void *server_context); static void nxt_php_flush(void *server_context);
extern nxt_int_t nxt_php_sapi_init(nxt_thread_t *thr, nxt_runtime_t *rt);
static sapi_module_struct nxt_php_sapi_module = static sapi_module_struct nxt_php_sapi_module =
{ {
@@ -173,30 +168,14 @@ nxt_php_str_trim_lead(nxt_str_t *str, u_char t)
} }
nxt_application_module_t nxt_php_module = { NXT_EXPORT nxt_application_module_t nxt_app_module = {
nxt_string("php"),
nxt_string(PHP_VERSION),
nxt_php_init, nxt_php_init,
nxt_php_prepare_msg, nxt_php_run,
nxt_php_run
}; };
nxt_int_t
nxt_php_sapi_init(nxt_thread_t *thr, nxt_runtime_t *rt)
{
nxt_app_modules[NXT_APP_PHP] = &nxt_php_module;
#if PHP_MAJOR_VERSION == 5
nxt_app_modules[NXT_APP_PHP5] = &nxt_php_module;
#endif
#if PHP_MAJOR_VERSION == 7
nxt_app_modules[NXT_APP_PHP7] = &nxt_php_module;
#endif
return NXT_OK;
}
static nxt_int_t static nxt_int_t
nxt_php_init(nxt_task_t *task, nxt_common_app_conf_t *conf) nxt_php_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
{ {
@@ -356,92 +335,6 @@ fail:
} }
static nxt_int_t
nxt_php_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
nxt_app_wmsg_t *wmsg)
{
nxt_int_t rc;
nxt_buf_t *b;
nxt_http_field_t *field;
nxt_app_request_header_t *h;
static const nxt_str_t prefix = nxt_string("HTTP_");
static const nxt_str_t eof = nxt_null_string;
h = &r->header;
#define RC(S) \
do { \
rc = (S); \
if (nxt_slow_path(rc != NXT_OK)) { \
goto fail; \
} \
} while(0)
#define NXT_WRITE(N) \
RC(nxt_app_msg_write_str(task, wmsg, N))
/* TODO error handle, async mmap buffer assignment */
NXT_WRITE(&h->method);
NXT_WRITE(&h->target);
if (h->path.start == h->target.start) {
NXT_WRITE(&eof);
} else {
NXT_WRITE(&h->path);
}
if (h->query.start != NULL) {
RC(nxt_app_msg_write_size(task, wmsg,
h->query.start - h->target.start + 1));
} else {
RC(nxt_app_msg_write_size(task, wmsg, 0));
}
NXT_WRITE(&h->version);
// PHP_SELF
// SCRIPT_NAME
// SCRIPT_FILENAME
// DOCUMENT_ROOT
NXT_WRITE(&r->remote);
NXT_WRITE(&h->host);
NXT_WRITE(&h->cookie);
NXT_WRITE(&h->content_type);
NXT_WRITE(&h->content_length);
RC(nxt_app_msg_write_size(task, wmsg, h->parsed_content_length));
nxt_list_each(field, h->fields) {
RC(nxt_app_msg_write_prefixed_upcase(task, wmsg,
&prefix, &field->name));
NXT_WRITE(&field->value);
} nxt_list_loop;
/* end-of-headers mark */
NXT_WRITE(&eof);
RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size));
for(b = r->body.buf; b != NULL; b = b->next) {
RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos,
nxt_buf_mem_used_size(&b->mem)));
}
#undef NXT_WRITE
#undef RC
return NXT_OK;
fail:
return NXT_ERROR;
}
static nxt_int_t static nxt_int_t
nxt_php_run(nxt_task_t *task, nxt_php_run(nxt_task_t *task,
nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *wmsg) nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *wmsg)

View File

@@ -24,6 +24,7 @@ typedef enum {
_NXT_PORT_MSG_READY, _NXT_PORT_MSG_READY,
_NXT_PORT_MSG_START_WORKER, _NXT_PORT_MSG_START_WORKER,
_NXT_PORT_MSG_SOCKET, _NXT_PORT_MSG_SOCKET,
_NXT_PORT_MSG_MODULES,
_NXT_PORT_MSG_RPC_READY, _NXT_PORT_MSG_RPC_READY,
_NXT_PORT_MSG_RPC_ERROR, _NXT_PORT_MSG_RPC_ERROR,
@@ -41,6 +42,7 @@ typedef enum {
NXT_PORT_MSG_START_WORKER = _NXT_PORT_MSG_START_WORKER | NXT_PORT_MSG_START_WORKER = _NXT_PORT_MSG_START_WORKER |
NXT_PORT_MSG_LAST, NXT_PORT_MSG_LAST,
NXT_PORT_MSG_SOCKET = _NXT_PORT_MSG_SOCKET | NXT_PORT_MSG_LAST, NXT_PORT_MSG_SOCKET = _NXT_PORT_MSG_SOCKET | NXT_PORT_MSG_LAST,
NXT_PORT_MSG_MODULES = _NXT_PORT_MSG_MODULES | NXT_PORT_MSG_LAST,
NXT_PORT_MSG_RPC_READY = _NXT_PORT_MSG_RPC_READY, NXT_PORT_MSG_RPC_READY = _NXT_PORT_MSG_RPC_READY,
NXT_PORT_MSG_RPC_READY_LAST = _NXT_PORT_MSG_RPC_READY | NXT_PORT_MSG_LAST, NXT_PORT_MSG_RPC_READY_LAST = _NXT_PORT_MSG_RPC_READY | NXT_PORT_MSG_LAST,
NXT_PORT_MSG_RPC_ERROR = _NXT_PORT_MSG_RPC_ERROR | NXT_PORT_MSG_LAST, NXT_PORT_MSG_RPC_ERROR = _NXT_PORT_MSG_RPC_ERROR | NXT_PORT_MSG_LAST,

View File

@@ -14,6 +14,7 @@ typedef enum {
NXT_PROCESS_CONTROLLER, NXT_PROCESS_CONTROLLER,
NXT_PROCESS_ROUTER, NXT_PROCESS_ROUTER,
NXT_PROCESS_WORKER, NXT_PROCESS_WORKER,
NXT_PROCESS_DISCOVERY,
NXT_PROCESS_MAX, NXT_PROCESS_MAX,
} nxt_process_type_t; } nxt_process_type_t;

View File

@@ -61,9 +61,6 @@ typedef struct nxt_python_run_ctx_s nxt_python_run_ctx_t;
static nxt_int_t nxt_python_init(nxt_task_t *task, nxt_common_app_conf_t *conf); static nxt_int_t nxt_python_init(nxt_task_t *task, nxt_common_app_conf_t *conf);
static nxt_int_t nxt_python_prepare_msg(nxt_task_t *task,
nxt_app_request_t *r, nxt_app_wmsg_t *msg);
static nxt_int_t nxt_python_run(nxt_task_t *task, static nxt_int_t nxt_python_run(nxt_task_t *task,
nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *msg); nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *msg);
@@ -93,13 +90,12 @@ nxt_inline nxt_int_t nxt_python_write(nxt_python_run_ctx_t *ctx,
nxt_inline nxt_int_t nxt_python_write_py_str(nxt_python_run_ctx_t *ctx, nxt_inline nxt_int_t nxt_python_write_py_str(nxt_python_run_ctx_t *ctx,
PyObject *str, nxt_bool_t flush, nxt_bool_t last); PyObject *str, nxt_bool_t flush, nxt_bool_t last);
extern nxt_int_t nxt_python_wsgi_init(nxt_thread_t *thr, nxt_runtime_t *rt);
NXT_EXPORT nxt_application_module_t nxt_app_module = {
nxt_application_module_t nxt_python_module = { nxt_string("python"),
nxt_string(PY_VERSION),
nxt_python_init, nxt_python_init,
nxt_python_prepare_msg, nxt_python_run,
nxt_python_run
}; };
@@ -177,23 +173,6 @@ static PyObject *nxt_py_environ_ptyp;
static nxt_python_run_ctx_t *nxt_python_run_ctx; static nxt_python_run_ctx_t *nxt_python_run_ctx;
nxt_int_t
nxt_python_wsgi_init(nxt_thread_t *thr, nxt_runtime_t *rt)
{
nxt_app_modules[NXT_APP_PYTHON] = &nxt_python_module;
#if PY_MAJOR_VERSION == 2
nxt_app_modules[NXT_APP_PYTHON2] = &nxt_python_module;
#endif
#if PY_MAJOR_VERSION == 3
nxt_app_modules[NXT_APP_PYTHON3] = &nxt_python_module;
#endif
return NXT_OK;
}
static nxt_int_t static nxt_int_t
nxt_python_init(nxt_task_t *task, nxt_common_app_conf_t *conf) nxt_python_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
{ {
@@ -319,84 +298,6 @@ fail:
} }
static nxt_int_t
nxt_python_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
nxt_app_wmsg_t *wmsg)
{
nxt_int_t rc;
nxt_buf_t *b;
nxt_http_field_t *field;
nxt_app_request_header_t *h;
static const nxt_str_t prefix = nxt_string("HTTP_");
static const nxt_str_t eof = nxt_null_string;
h = &r->header;
#define RC(S) \
do { \
rc = (S); \
if (nxt_slow_path(rc != NXT_OK)) { \
goto fail; \
} \
} while(0)
#define NXT_WRITE(N) \
RC(nxt_app_msg_write_str(task, wmsg, N))
/* TODO error handle, async mmap buffer assignment */
NXT_WRITE(&h->method);
NXT_WRITE(&h->target);
if (h->path.start == h->target.start) {
NXT_WRITE(&eof);
} else {
NXT_WRITE(&h->path);
}
if (h->query.start != NULL) {
RC(nxt_app_msg_write_size(task, wmsg,
h->query.start - h->target.start + 1));
} else {
RC(nxt_app_msg_write_size(task, wmsg, 0));
}
NXT_WRITE(&h->version);
NXT_WRITE(&r->remote);
NXT_WRITE(&h->host);
NXT_WRITE(&h->content_type);
NXT_WRITE(&h->content_length);
nxt_list_each(field, h->fields) {
RC(nxt_app_msg_write_prefixed_upcase(task, wmsg,
&prefix, &field->name));
NXT_WRITE(&field->value);
} nxt_list_loop;
/* end-of-headers mark */
NXT_WRITE(&eof);
RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size));
for(b = r->body.buf; b != NULL; b = b->next) {
RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos,
nxt_buf_mem_used_size(&b->mem)));
}
#undef NXT_WRITE
#undef RC
return NXT_OK;
fail:
return NXT_ERROR;
}
static nxt_int_t static nxt_int_t
nxt_python_run(nxt_task_t *task, nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *wmsg) nxt_python_run(nxt_task_t *task, nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *wmsg)
{ {

View File

@@ -134,6 +134,12 @@ static void nxt_router_process_http_request(nxt_task_t *task,
nxt_conn_t *c, nxt_app_parse_ctx_t *ap); nxt_conn_t *c, nxt_app_parse_ctx_t *ap);
static void nxt_router_process_http_request_mp(nxt_task_t *task, static void nxt_router_process_http_request_mp(nxt_task_t *task,
nxt_req_app_link_t *ra, nxt_port_t *port); nxt_req_app_link_t *ra, nxt_port_t *port);
static nxt_int_t nxt_python_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
nxt_app_wmsg_t *wmsg);
static nxt_int_t nxt_php_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
nxt_app_wmsg_t *wmsg);
static nxt_int_t nxt_go_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
nxt_app_wmsg_t *wmsg);
static void nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data); static void nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data);
static void nxt_router_conn_close(nxt_task_t *task, void *obj, void *data); static void nxt_router_conn_close(nxt_task_t *task, void *obj, void *data);
static void nxt_router_conn_free(nxt_task_t *task, void *obj, void *data); static void nxt_router_conn_free(nxt_task_t *task, void *obj, void *data);
@@ -146,6 +152,14 @@ static void nxt_router_gen_error(nxt_task_t *task, nxt_conn_t *c, int code,
static nxt_router_t *nxt_router; static nxt_router_t *nxt_router;
static nxt_app_prepare_msg_t nxt_app_prepare_msg[] = {
nxt_python_prepare_msg,
nxt_php_prepare_msg,
nxt_go_prepare_msg,
};
nxt_int_t nxt_int_t
nxt_router_start(nxt_task_t *task, void *data) nxt_router_start(nxt_task_t *task, void *data)
{ {
@@ -654,6 +668,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_conf_value_t *applications, *application; nxt_conf_value_t *applications, *application;
nxt_conf_value_t *listeners, *listener; nxt_conf_value_t *listeners, *listener;
nxt_socket_conf_t *skcf; nxt_socket_conf_t *skcf;
nxt_app_lang_module_t *lang;
nxt_router_app_conf_t apcf; nxt_router_app_conf_t apcf;
nxt_router_listener_conf_t lscf; nxt_router_listener_conf_t lscf;
@@ -735,17 +750,27 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_debug(task, "application type: %V", &apcf.type); nxt_debug(task, "application type: %V", &apcf.type);
nxt_debug(task, "application workers: %D", apcf.workers); nxt_debug(task, "application workers: %D", apcf.workers);
type = nxt_app_parse_type(&apcf.type); lang = nxt_app_lang_module(task->thread->runtime, &apcf.type);
if (type == NXT_APP_UNKNOWN) { if (lang == NULL) {
nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"", nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"",
&apcf.type); &apcf.type);
goto app_fail; goto app_fail;
} }
if (nxt_app_modules[type] == NULL) { nxt_debug(task, "application language module: \"%s\"", lang->file);
type = nxt_app_parse_type(&lang->type);
if (type == NXT_APP_UNKNOWN) {
nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"",
&lang->type);
goto app_fail;
}
if (nxt_app_prepare_msg[type] == NULL) {
nxt_log(task, NXT_LOG_CRIT, "unsupported application type: \"%V\"", nxt_log(task, NXT_LOG_CRIT, "unsupported application type: \"%V\"",
&apcf.type); &lang->type);
goto app_fail; goto app_fail;
} }
@@ -763,7 +788,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
app->type = type; app->type = type;
app->max_workers = apcf.workers; app->max_workers = apcf.workers;
app->live = 1; app->live = 1;
app->module = nxt_app_modules[type]; app->prepare_msg = nxt_app_prepare_msg[type];
nxt_queue_insert_tail(&tmcf->apps, &app->link); nxt_queue_insert_tail(&tmcf->apps, &app->link);
} }
@@ -2687,7 +2712,7 @@ nxt_router_process_http_request_mp(nxt_task_t *task, nxt_req_app_link_t *ra,
wmsg.buf = &wmsg.write; wmsg.buf = &wmsg.write;
wmsg.stream = ra->req_id; wmsg.stream = ra->req_id;
res = port->app->module->prepare_msg(task, &ap->r, &wmsg); res = port->app->prepare_msg(task, &ap->r, &wmsg);
if (nxt_slow_path(res != NXT_OK)) { if (nxt_slow_path(res != NXT_OK)) {
nxt_router_gen_error(task, c, 500, nxt_router_gen_error(task, c, 500,
@@ -2710,6 +2735,246 @@ nxt_router_process_http_request_mp(nxt_task_t *task, nxt_req_app_link_t *ra,
} }
static nxt_int_t
nxt_python_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
nxt_app_wmsg_t *wmsg)
{
nxt_int_t rc;
nxt_buf_t *b;
nxt_http_field_t *field;
nxt_app_request_header_t *h;
static const nxt_str_t prefix = nxt_string("HTTP_");
static const nxt_str_t eof = nxt_null_string;
h = &r->header;
#define RC(S) \
do { \
rc = (S); \
if (nxt_slow_path(rc != NXT_OK)) { \
goto fail; \
} \
} while(0)
#define NXT_WRITE(N) \
RC(nxt_app_msg_write_str(task, wmsg, N))
/* TODO error handle, async mmap buffer assignment */
NXT_WRITE(&h->method);
NXT_WRITE(&h->target);
if (h->path.start == h->target.start) {
NXT_WRITE(&eof);
} else {
NXT_WRITE(&h->path);
}
if (h->query.start != NULL) {
RC(nxt_app_msg_write_size(task, wmsg,
h->query.start - h->target.start + 1));
} else {
RC(nxt_app_msg_write_size(task, wmsg, 0));
}
NXT_WRITE(&h->version);
NXT_WRITE(&r->remote);
NXT_WRITE(&h->host);
NXT_WRITE(&h->content_type);
NXT_WRITE(&h->content_length);
nxt_list_each(field, h->fields) {
RC(nxt_app_msg_write_prefixed_upcase(task, wmsg,
&prefix, &field->name));
NXT_WRITE(&field->value);
} nxt_list_loop;
/* end-of-headers mark */
NXT_WRITE(&eof);
RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size));
for(b = r->body.buf; b != NULL; b = b->next) {
RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos,
nxt_buf_mem_used_size(&b->mem)));
}
#undef NXT_WRITE
#undef RC
return NXT_OK;
fail:
return NXT_ERROR;
}
static nxt_int_t
nxt_php_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
nxt_app_wmsg_t *wmsg)
{
nxt_int_t rc;
nxt_buf_t *b;
nxt_http_field_t *field;
nxt_app_request_header_t *h;
static const nxt_str_t prefix = nxt_string("HTTP_");
static const nxt_str_t eof = nxt_null_string;
h = &r->header;
#define RC(S) \
do { \
rc = (S); \
if (nxt_slow_path(rc != NXT_OK)) { \
goto fail; \
} \
} while(0)
#define NXT_WRITE(N) \
RC(nxt_app_msg_write_str(task, wmsg, N))
/* TODO error handle, async mmap buffer assignment */
NXT_WRITE(&h->method);
NXT_WRITE(&h->target);
if (h->path.start == h->target.start) {
NXT_WRITE(&eof);
} else {
NXT_WRITE(&h->path);
}
if (h->query.start != NULL) {
RC(nxt_app_msg_write_size(task, wmsg,
h->query.start - h->target.start + 1));
} else {
RC(nxt_app_msg_write_size(task, wmsg, 0));
}
NXT_WRITE(&h->version);
// PHP_SELF
// SCRIPT_NAME
// SCRIPT_FILENAME
// DOCUMENT_ROOT
NXT_WRITE(&r->remote);
NXT_WRITE(&h->host);
NXT_WRITE(&h->cookie);
NXT_WRITE(&h->content_type);
NXT_WRITE(&h->content_length);
RC(nxt_app_msg_write_size(task, wmsg, h->parsed_content_length));
nxt_list_each(field, h->fields) {
RC(nxt_app_msg_write_prefixed_upcase(task, wmsg,
&prefix, &field->name));
NXT_WRITE(&field->value);
} nxt_list_loop;
/* end-of-headers mark */
NXT_WRITE(&eof);
RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size));
for(b = r->body.buf; b != NULL; b = b->next) {
RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos,
nxt_buf_mem_used_size(&b->mem)));
}
#undef NXT_WRITE
#undef RC
return NXT_OK;
fail:
return NXT_ERROR;
}
static nxt_int_t
nxt_go_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, nxt_app_wmsg_t *wmsg)
{
nxt_int_t rc;
nxt_buf_t *b;
nxt_http_field_t *field;
nxt_app_request_header_t *h;
static const nxt_str_t eof = nxt_null_string;
h = &r->header;
#define RC(S) \
do { \
rc = (S); \
if (nxt_slow_path(rc != NXT_OK)) { \
goto fail; \
} \
} while(0)
#define NXT_WRITE(N) \
RC(nxt_app_msg_write_str(task, wmsg, N))
/* TODO error handle, async mmap buffer assignment */
NXT_WRITE(&h->method);
NXT_WRITE(&h->target);
if (h->path.start == h->target.start) {
NXT_WRITE(&eof);
} else {
NXT_WRITE(&h->path);
}
if (h->query.start != NULL) {
RC(nxt_app_msg_write_size(task, wmsg,
h->query.start - h->target.start + 1));
} else {
RC(nxt_app_msg_write_size(task, wmsg, 0));
}
NXT_WRITE(&h->version);
NXT_WRITE(&h->host);
NXT_WRITE(&h->cookie);
NXT_WRITE(&h->content_type);
NXT_WRITE(&h->content_length);
RC(nxt_app_msg_write_size(task, wmsg, h->parsed_content_length));
nxt_list_each(field, h->fields) {
NXT_WRITE(&field->name);
NXT_WRITE(&field->value);
} nxt_list_loop;
/* end-of-headers mark */
NXT_WRITE(&eof);
RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size));
for(b = r->body.buf; b != NULL; b = b->next) {
RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos,
nxt_buf_mem_used_size(&b->mem)));
}
#undef NXT_WRITE
#undef RC
return NXT_OK;
fail:
return NXT_ERROR;
}
static const nxt_conn_state_t nxt_router_conn_close_state static const nxt_conn_state_t nxt_router_conn_close_state
nxt_aligned(64) = nxt_aligned(64) =
{ {

View File

@@ -66,6 +66,11 @@ typedef struct {
} nxt_joint_job_t; } nxt_joint_job_t;
typedef nxt_int_t (*nxt_app_prepare_msg_t)(nxt_task_t *task,
nxt_app_request_t *r, nxt_app_wmsg_t *wmsg);
struct nxt_app_s { struct nxt_app_s {
nxt_thread_mutex_t mutex; /* Protects ports queue. */ nxt_thread_mutex_t mutex; /* Protects ports queue. */
nxt_queue_t ports; /* of nxt_port_t.app_link */ nxt_queue_t ports; /* of nxt_port_t.app_link */
@@ -83,7 +88,7 @@ struct nxt_app_s {
nxt_queue_link_t link; nxt_queue_link_t link;
nxt_str_t conf; nxt_str_t conf;
nxt_app_module_t *module; nxt_app_prepare_msg_t prepare_msg;
}; };

View File

@@ -61,6 +61,7 @@ nxt_runtime_create(nxt_task_t *task)
nxt_int_t ret; nxt_int_t ret;
nxt_array_t *listen_sockets; nxt_array_t *listen_sockets;
nxt_runtime_t *rt; nxt_runtime_t *rt;
nxt_app_lang_module_t *lang;
mp = nxt_mp_create(1024, 128, 256, 32); mp = nxt_mp_create(1024, 128, 256, 32);
@@ -90,6 +91,18 @@ nxt_runtime_create(nxt_task_t *task)
goto fail; goto fail;
} }
rt->languages = nxt_array_create(mp, 1, sizeof(nxt_app_lang_module_t));
if (nxt_slow_path(rt->languages == NULL)) {
goto fail;
}
/* Should not fail. */
lang = nxt_array_add(rt->languages);
lang->type = (nxt_str_t) nxt_string("go");
lang->version = (nxt_str_t) nxt_null_string;
lang->file = NULL;
lang->module = &nxt_go_module;
listen_sockets = nxt_array_create(mp, 1, sizeof(nxt_listen_socket_t)); listen_sockets = nxt_array_create(mp, 1, sizeof(nxt_listen_socket_t));
if (nxt_slow_path(listen_sockets == NULL)) { if (nxt_slow_path(listen_sockets == NULL)) {
goto fail; goto fail;
@@ -324,7 +337,6 @@ nxt_runtime_thread_pools(nxt_thread_t *thr, nxt_runtime_t *rt)
static void static void
nxt_runtime_start(nxt_task_t *task, void *obj, void *data) nxt_runtime_start(nxt_task_t *task, void *obj, void *data)
{ {
nxt_uint_t i;
nxt_runtime_t *rt; nxt_runtime_t *rt;
rt = obj; rt = obj;
@@ -338,12 +350,6 @@ nxt_runtime_start(nxt_task_t *task, void *obj, void *data)
goto fail; goto fail;
} }
for (i = 0; i < nxt_init_modules_n; i++) {
if (nxt_init_modules[i](task->thread, rt) != NXT_OK) {
goto fail;
}
}
if (nxt_runtime_log_files_create(task, rt) != NXT_OK) { if (nxt_runtime_log_files_create(task, rt) != NXT_OK) {
goto fail; goto fail;
} }

View File

@@ -19,6 +19,7 @@ struct nxt_runtime_s {
nxt_array_t *listen_sockets; /* of nxt_listen_socket_t */ nxt_array_t *listen_sockets; /* of nxt_listen_socket_t */
nxt_array_t *services; /* of nxt_service_t */ nxt_array_t *services; /* of nxt_service_t */
nxt_array_t *languages; /* of nxt_app_lang_module_t */
void *data; void *data;
nxt_runtime_cont_t start; nxt_runtime_cont_t start;

View File

@@ -64,8 +64,7 @@ nxt_str_dup(nxt_mp_t *mp, nxt_str_t *dst, const nxt_str_t *src)
* nxt_str_cstrz() creates a C style zero-terminated copy of a source * nxt_str_cstrz() creates a C style zero-terminated copy of a source
* nxt_str_t. The function is intended to create strings suitable * nxt_str_t. The function is intended to create strings suitable
* for libc and kernel interfaces so result is pointer to char instead * for libc and kernel interfaces so result is pointer to char instead
* of u_char to minimize casts. The copy is aligned to 2 bytes thus * of u_char to minimize casts.
* the lowest bit may be used as marker.
*/ */
char * char *
@@ -73,7 +72,7 @@ nxt_str_cstrz(nxt_mp_t *mp, const nxt_str_t *src)
{ {
char *p, *dst; char *p, *dst;
dst = nxt_mp_align(mp, 2, src->length + 1); dst = nxt_mp_alloc(mp, src->length + 1);
if (nxt_fast_path(dst != NULL)) { if (nxt_fast_path(dst != NULL)) {
p = nxt_cpymem(dst, src->start, src->length); p = nxt_cpymem(dst, src->start, src->length);

View File

@@ -158,7 +158,7 @@ nxt_str_eq(s, p, _length) \
#define \ #define \
nxt_str_start(s, p, _length) \ nxt_str_start(s, p, _length) \
(((s)->length > _length) && (nxt_memcmp((s)->start, p, _length) == 0)) (((s)->length >= _length) && (nxt_memcmp((s)->start, p, _length) == 0))
#define \ #define \

View File

@@ -32,6 +32,7 @@ nxt_port_handler_t nxt_controller_process_port_handlers[] = {
NULL, /* NXT_PORT_MSG_READY */ NULL, /* NXT_PORT_MSG_READY */
NULL, /* NXT_PORT_MSG_START_WORKER */ NULL, /* NXT_PORT_MSG_START_WORKER */
NULL, /* NXT_PORT_MSG_SOCKET */ NULL, /* NXT_PORT_MSG_SOCKET */
NULL, /* NXT_PORT_MSG_MODULES */
nxt_port_rpc_handler, nxt_port_rpc_handler,
nxt_port_rpc_handler, nxt_port_rpc_handler,
}; };
@@ -47,6 +48,7 @@ nxt_port_handler_t nxt_worker_process_port_handlers[] = {
NULL, /* NXT_PORT_MSG_READY */ NULL, /* NXT_PORT_MSG_READY */
NULL, /* NXT_PORT_MSG_START_WORKER */ NULL, /* NXT_PORT_MSG_START_WORKER */
NULL, /* NXT_PORT_MSG_SOCKET */ NULL, /* NXT_PORT_MSG_SOCKET */
NULL, /* NXT_PORT_MSG_MODULES */
nxt_port_rpc_handler, nxt_port_rpc_handler,
nxt_port_rpc_handler, nxt_port_rpc_handler,
}; };
@@ -62,6 +64,7 @@ nxt_port_handler_t nxt_app_process_port_handlers[] = {
NULL, /* NXT_PORT_MSG_READY */ NULL, /* NXT_PORT_MSG_READY */
NULL, /* NXT_PORT_MSG_START_WORKER */ NULL, /* NXT_PORT_MSG_START_WORKER */
NULL, /* NXT_PORT_MSG_SOCKET */ NULL, /* NXT_PORT_MSG_SOCKET */
NULL, /* NXT_PORT_MSG_MODULES */
nxt_port_rpc_handler, nxt_port_rpc_handler,
nxt_port_rpc_handler, nxt_port_rpc_handler,
}; };
@@ -77,6 +80,23 @@ nxt_port_handler_t nxt_router_process_port_handlers[] = {
NULL, /* NXT_PORT_MSG_READY */ NULL, /* NXT_PORT_MSG_READY */
NULL, /* NXT_PORT_MSG_START_WORKER */ NULL, /* NXT_PORT_MSG_START_WORKER */
NULL, /* NXT_PORT_MSG_SOCKET */ NULL, /* NXT_PORT_MSG_SOCKET */
NULL, /* NXT_PORT_MSG_MODULES */
nxt_port_rpc_handler,
nxt_port_rpc_handler,
};
nxt_port_handler_t nxt_discovery_process_port_handlers[] = {
nxt_worker_process_quit_handler,
nxt_port_new_port_handler,
nxt_port_change_log_file_handler,
nxt_port_mmap_handler,
nxt_port_data_handler,
nxt_port_remove_pid_handler,
NULL, /* NXT_PORT_MSG_READY */
NULL, /* NXT_PORT_MSG_START_WORKER */
NULL, /* NXT_PORT_MSG_SOCKET */
NULL, /* NXT_PORT_MSG_MODULES */
nxt_port_rpc_handler, nxt_port_rpc_handler,
nxt_port_rpc_handler, nxt_port_rpc_handler,
}; };