Added Lua modules: Copas, binaryheap, and timerwheel.
This commit is contained in:
parent
4ea35bed7d
commit
b1bc8aa063
140 changed files with 16071 additions and 50 deletions
|
@ -38,6 +38,9 @@ New Features
|
||||||
- LuaSocket
|
- LuaSocket
|
||||||
- LuaSec
|
- LuaSec
|
||||||
- LuaRS232
|
- LuaRS232
|
||||||
|
- timerwheel
|
||||||
|
- binaryheap
|
||||||
|
- Copas
|
||||||
|
|
||||||
- New command line option: -p (or --program). This is similar to the
|
- New command line option: -p (or --program). This is similar to the
|
||||||
existing -t (or --trace) option. Where "trace" displays and logs script
|
existing -t (or --trace) option. Where "trace" displays and logs script
|
||||||
|
@ -68,6 +71,8 @@ Fixes
|
||||||
|
|
||||||
- PNG files no longer generate warnings on the console.
|
- PNG files no longer generate warnings on the console.
|
||||||
|
|
||||||
|
- Non-VLDP videos now honor command line volume settings.
|
||||||
|
|
||||||
- Menu system now performs "natural sorting" of game titles instead of brain
|
- Menu system now performs "natural sorting" of game titles instead of brain
|
||||||
dead "computer sorting". It should make a lot more sense paging through
|
dead "computer sorting". It should make a lot more sense paging through
|
||||||
games now.
|
games now.
|
||||||
|
|
3
LICENSES
3
LICENSES
|
@ -4,7 +4,9 @@ these tools, Singe would not exist.
|
||||||
|
|
||||||
|
|
||||||
arg_parser BSD-2-Clause http://savannah.nongnu.org/projects/arg-parser
|
arg_parser BSD-2-Clause http://savannah.nongnu.org/projects/arg-parser
|
||||||
|
binaryheap.lua MIT http://tieske.github.io/binaryheap.lua
|
||||||
bzip2 bzip2-1.0.6 https://sourceware.org/bzip2
|
bzip2 bzip2-1.0.6 https://sourceware.org/bzip2
|
||||||
|
copas MIT https://lunarmodules.github.io/copas
|
||||||
ffmpeg LGPL-2.1 https://ffmpeg.org
|
ffmpeg LGPL-2.1 https://ffmpeg.org
|
||||||
ffms2 GPL-3.0-only https://github.com/FFMS/ffms2
|
ffms2 GPL-3.0-only https://github.com/FFMS/ffms2
|
||||||
jbigkit GPL-2.0 https://www.cl.cam.ac.uk/~mgk25/jbigkit
|
jbigkit GPL-2.0 https://www.cl.cam.ac.uk/~mgk25/jbigkit
|
||||||
|
@ -21,6 +23,7 @@ SDL2_gfx LGPL-2.1 https://github.com/ferzkopp/SDL_gfx
|
||||||
SDL2_image Zlib https://www.libsdl.org
|
SDL2_image Zlib https://www.libsdl.org
|
||||||
SDL2_mixer Zlib https://www.libsdl.org
|
SDL2_mixer Zlib https://www.libsdl.org
|
||||||
SDL2_ttf Zlib https://www.libsdl.org
|
SDL2_ttf Zlib https://www.libsdl.org
|
||||||
|
timerwheel MIT https://tieske.github.io/timerwheel.lua
|
||||||
uthash BSD-1-Clause https://troydhanson.github.io/uthash
|
uthash BSD-1-Clause https://troydhanson.github.io/uthash
|
||||||
vlc GPL-2.0 https://www.videolan.org/vlc
|
vlc GPL-2.0 https://www.videolan.org/vlc
|
||||||
xz Public-Domain https://github.com/tukaani-project/xz
|
xz Public-Domain https://github.com/tukaani-project/xz
|
||||||
|
|
|
@ -48,9 +48,12 @@ function loadGameAssets()
|
||||||
SPRITE_CABINET = spriteLoad(GAME_LIST[GAME_SELECTED].CABINET)
|
SPRITE_CABINET = spriteLoad(GAME_LIST[GAME_SELECTED].CABINET)
|
||||||
SPRITE_MARQUEE = spriteLoad(GAME_LIST[GAME_SELECTED].MARQUEE)
|
SPRITE_MARQUEE = spriteLoad(GAME_LIST[GAME_SELECTED].MARQUEE)
|
||||||
VIDEO_ATTRACT = videoLoad(GAME_LIST[GAME_SELECTED].ATTRACT)
|
VIDEO_ATTRACT = videoLoad(GAME_LIST[GAME_SELECTED].ATTRACT)
|
||||||
|
if GAME_LIST[GAME_SELECTED].AUDIO_TRACK then
|
||||||
|
videoSetAudioTrack(VIDEO_ATTRACT, GAME_LIST[GAME_SELECTED].AUDIO_TRACK)
|
||||||
|
end
|
||||||
videoPlay(VIDEO_ATTRACT)
|
videoPlay(VIDEO_ATTRACT)
|
||||||
videoSeek(VIDEO_ATTRACT, GAME_LIST[GAME_SELECTED].ATTRACT_START)
|
videoSeek(VIDEO_ATTRACT, GAME_LIST[GAME_SELECTED].ATTRACT_START)
|
||||||
videoSetVolume(VIDEO_ATTRACT, 0, 0)
|
-- videoSetVolume(VIDEO_ATTRACT, 0, 0)
|
||||||
|
|
||||||
-- Build text sprites
|
-- Build text sprites
|
||||||
local textBox = GAME_LIST[GAME_SELECTED].DESCRIPTION .. WRAP_BREAK .. WRAP_BREAK ..
|
local textBox = GAME_LIST[GAME_SELECTED].DESCRIPTION .. WRAP_BREAK .. WRAP_BREAK ..
|
||||||
|
|
51
build-all.sh
51
build-all.sh
|
@ -304,15 +304,6 @@ if [[ 0 == 1 ]]; then
|
||||||
# === "Indexing" Text ===
|
# === "Indexing" Text ===
|
||||||
createEmbeddedImage indexing
|
createEmbeddedImage indexing
|
||||||
|
|
||||||
# === Singe Framework ===
|
|
||||||
createEmbeddedBinary assets/Framework.singe ${G_GENERATED}/Framework_singe.h FRAMEWORK_SINGE_H
|
|
||||||
|
|
||||||
# === Default Config ===
|
|
||||||
createEmbeddedBinary assets/controls.cfg ${G_GENERATED}/controls_cfg.h CONTROLS_CFG_H
|
|
||||||
|
|
||||||
# === Singe Menu App ===
|
|
||||||
createEmbeddedBinary assets/Menu.singe ${G_GENERATED}/Menu_singe.h MENU_SINGE_H
|
|
||||||
|
|
||||||
# === Singe Menu Font ===
|
# === Singe Menu Font ===
|
||||||
createEmbeddedBinary assets/FreeSansBold.ttf ${G_GENERATED}/FreeSansBold_ttf.h FREESANSBOLD_TTF_H
|
createEmbeddedBinary assets/FreeSansBold.ttf ${G_GENERATED}/FreeSansBold_ttf.h FREESANSBOLD_TTF_H
|
||||||
|
|
||||||
|
@ -342,6 +333,32 @@ if [[ 0 == 1 ]]; then
|
||||||
# === LuaRS232 ===
|
# === LuaRS232 ===
|
||||||
createEmbeddedBinary thirdparty/librs232/bindings/lua/rs232.lua ${G_GENERATED}/rs232_lua.h RS232_LUA_H
|
createEmbeddedBinary thirdparty/librs232/bindings/lua/rs232.lua ${G_GENERATED}/rs232_lua.h RS232_LUA_H
|
||||||
|
|
||||||
|
# === Copas ===
|
||||||
|
createEmbeddedBinary thirdparty/copas/src/copas.lua ${G_GENERATED}/copas_lua.h COPAS_LUA_H
|
||||||
|
createEmbeddedBinary thirdparty/copas/src/copas/ftp.lua ${G_GENERATED}/copas_ftp_lua.h COPAS_FTP_LUA_H copas
|
||||||
|
createEmbeddedBinary thirdparty/copas/src/copas/http.lua ${G_GENERATED}/copas_http_lua.h COPAS_HTTP_LUA_H copas
|
||||||
|
createEmbeddedBinary thirdparty/copas/src/copas/smtp.lua ${G_GENERATED}/copas_smtp_lua.h COPAS_SMTP_LUA_H copas
|
||||||
|
createEmbeddedBinary thirdparty/copas/src/copas/lock.lua ${G_GENERATED}/copas_lock_lua.h COPAS_LOCK_LUA_H copas
|
||||||
|
createEmbeddedBinary thirdparty/copas/src/copas/queue.lua ${G_GENERATED}/copas_queue_lua.h COPAS_QUEUE_LUA_H copas
|
||||||
|
createEmbeddedBinary thirdparty/copas/src/copas/semaphore.lua ${G_GENERATED}/copas_semaphore_lua.h COPAS_SEMAPHORE_LUA_H copas
|
||||||
|
createEmbeddedBinary thirdparty/copas/src/copas/timer.lua ${G_GENERATED}/copas_timer_lua.h COPAS_TIMER_LUA_H copas
|
||||||
|
|
||||||
|
# === binaryheap.lua ===
|
||||||
|
createEmbeddedBinary thirdparty/binaryheap.lua/src/binaryheap.lua ${G_GENERATED}/binaryheap_lua.h BINARYHEAP_LUA_H
|
||||||
|
|
||||||
|
# === binaryheap.lua ===
|
||||||
|
createEmbeddedBinary thirdparty/timerwheel.lua/src/timerwheel/timerwheel.lua ${G_GENERATED}/timerwheel_lua.h TIMERWHEEL_LUA_H
|
||||||
|
fi
|
||||||
|
|
||||||
|
# === Singe Framework ===
|
||||||
|
createEmbeddedBinary assets/Framework.singe ${G_GENERATED}/Framework_singe.h FRAMEWORK_SINGE_H
|
||||||
|
|
||||||
|
# === Default Config ===
|
||||||
|
createEmbeddedBinary assets/controls.cfg ${G_GENERATED}/controls_cfg.h CONTROLS_CFG_H
|
||||||
|
|
||||||
|
# === Singe Menu App ===
|
||||||
|
createEmbeddedBinary assets/Menu.singe ${G_GENERATED}/Menu_singe.h MENU_SINGE_H
|
||||||
|
|
||||||
:<<UNUSED
|
:<<UNUSED
|
||||||
# === Singe Manual ===
|
# === Singe Manual ===
|
||||||
#libreoffice --headless "-env:UserInstallation=file:///tmp/LibreOffice_Conversion_${USER}" --convert-to pdf:writer_pdf_Export Manual.odt
|
#libreoffice --headless "-env:UserInstallation=file:///tmp/LibreOffice_Conversion_${USER}" --convert-to pdf:writer_pdf_Export Manual.odt
|
||||||
|
@ -350,7 +367,6 @@ if [[ 0 == 1 ]]; then
|
||||||
createEmbeddedBinary ${G_TARGET}/Manual.pdf ${G_GENERATED}/Manual_pdf.h MANUAL_H
|
createEmbeddedBinary ${G_TARGET}/Manual.pdf ${G_GENERATED}/Manual_pdf.h MANUAL_H
|
||||||
rm ${G_TARGET}/Manual.pdf
|
rm ${G_TARGET}/Manual.pdf
|
||||||
UNUSED
|
UNUSED
|
||||||
fi
|
|
||||||
|
|
||||||
pushd ${G_TARGET}
|
pushd ${G_TARGET}
|
||||||
clearAndEnterBuild
|
clearAndEnterBuild
|
||||||
|
@ -373,6 +389,7 @@ function createEmbeddedBinary() {
|
||||||
local BINFILE=$1
|
local BINFILE=$1
|
||||||
local SOURCEFILE=$2 # This is assumed to be an absolute path
|
local SOURCEFILE=$2 # This is assumed to be an absolute path
|
||||||
local BLOCKER=$3
|
local BLOCKER=$3
|
||||||
|
local PREFIX=$4
|
||||||
local FILENAME=$(basename ${BINFILE})
|
local FILENAME=$(basename ${BINFILE})
|
||||||
local DIRNAME=$(dirname ${BINFILE})
|
local DIRNAME=$(dirname ${BINFILE})
|
||||||
|
|
||||||
|
@ -382,9 +399,14 @@ function createEmbeddedBinary() {
|
||||||
pushd ${DIRNAME}
|
pushd ${DIRNAME}
|
||||||
xxd -i ${FILENAME} >> ${SOURCEFILE}
|
xxd -i ${FILENAME} >> ${SOURCEFILE}
|
||||||
popd
|
popd
|
||||||
|
if [[ ! -z ${PREFIX} ]]; then
|
||||||
|
PREFIX=${PREFIX}_
|
||||||
|
sed -i "s/unsigned char /unsigned char ${PREFIX}/" ${SOURCEFILE}
|
||||||
|
sed -i "s/unsigned int /unsigned int ${PREFIX}/" ${SOURCEFILE}
|
||||||
|
fi
|
||||||
printf "\n#else // EMBED_HERE\n\n" >> ${SOURCEFILE}
|
printf "\n#else // EMBED_HERE\n\n" >> ${SOURCEFILE}
|
||||||
printf "extern unsigned char ${FILENAME/\./_}[];\n" >> ${SOURCEFILE}
|
printf "extern unsigned char ${PREFIX}${FILENAME/\./_}[];\n" >> ${SOURCEFILE}
|
||||||
printf "extern unsigned int ${FILENAME/\./_}_len;\n" >> ${SOURCEFILE}
|
printf "extern unsigned int ${PREFIX}${FILENAME/\./_}_len;\n" >> ${SOURCEFILE}
|
||||||
printf "\n#endif // EMBED_HERE\n\n" >> ${SOURCEFILE}
|
printf "\n#endif // EMBED_HERE\n\n" >> ${SOURCEFILE}
|
||||||
outputFooter ${BLOCKER} >> ${SOURCEFILE}
|
outputFooter ${BLOCKER} >> ${SOURCEFILE}
|
||||||
}
|
}
|
||||||
|
@ -469,7 +491,7 @@ function outputLicense() {
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation; either version 2
|
* as published by the Free Software Foundation; either version 3
|
||||||
* of the License, or (at your option) any later version.
|
* of the License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
@ -479,7 +501,8 @@ function outputLicense() {
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
LICENSE
|
LICENSE
|
||||||
|
|
|
@ -58,5 +58,21 @@
|
||||||
// LuaRS232
|
// LuaRS232
|
||||||
#include "generated/rs232_lua.h"
|
#include "generated/rs232_lua.h"
|
||||||
|
|
||||||
|
// binaryheap
|
||||||
|
#include "generated/binaryheap_lua.h"
|
||||||
|
|
||||||
|
// timerwheel
|
||||||
|
#include "generated/timerwheel_lua.h"
|
||||||
|
|
||||||
|
// Copas
|
||||||
|
#include "generated/copas_lua.h"
|
||||||
|
#include "generated/copas_ftp_lua.h"
|
||||||
|
#include "generated/copas_http_lua.h"
|
||||||
|
#include "generated/copas_lock_lua.h"
|
||||||
|
#include "generated/copas_queue_lua.h"
|
||||||
|
#include "generated/copas_semaphore_lua.h"
|
||||||
|
#include "generated/copas_smtp_lua.h"
|
||||||
|
#include "generated/copas_timer_lua.h"
|
||||||
|
|
||||||
|
|
||||||
#endif // EMBEDDED_H
|
#endif // EMBEDDED_H
|
||||||
|
|
|
@ -1012,7 +1012,7 @@ void unpackGames(void) {
|
||||||
|
|
||||||
// Unpack it!
|
// Unpack it!
|
||||||
if (ok) {
|
if (ok) {
|
||||||
utilSay(">>> Unpacking %s: %s", types[packageType], de->d_name);
|
utilSay(">>> Installing %s: %s", types[packageType], de->d_name);
|
||||||
// https://github.com/libarchive/libarchive/wiki/Examples#user-content-A_Complete_Extractor
|
// https://github.com/libarchive/libarchive/wiki/Examples#user-content-A_Complete_Extractor
|
||||||
flags = ARCHIVE_EXTRACT_TIME;
|
flags = ARCHIVE_EXTRACT_TIME;
|
||||||
flags |= ARCHIVE_EXTRACT_PERM;
|
flags |= ARCHIVE_EXTRACT_PERM;
|
||||||
|
|
60
src/singe.c
60
src/singe.c
|
@ -279,34 +279,47 @@ GlobalT _global;
|
||||||
// Lua Modules
|
// Lua Modules
|
||||||
static const luaModuleT luaModules[] = {
|
static const luaModuleT luaModules[] = {
|
||||||
// LuaFileSystem
|
// LuaFileSystem
|
||||||
MODC("lfs", luaopen_lfs),
|
MODC("lfs", luaopen_lfs),
|
||||||
// LuaSocket
|
// LuaSocket
|
||||||
MODC("mime.core", luaopen_mime_core),
|
MODC("mime.core", luaopen_mime_core),
|
||||||
MODC("socket.core", luaopen_socket_core),
|
MODC("socket.core", luaopen_socket_core),
|
||||||
MODL("ltn12", ltn12_lua),
|
MODL("ltn12", ltn12_lua),
|
||||||
MODL("mbox", mbox_lua),
|
MODL("mbox", mbox_lua),
|
||||||
MODL("mime", mime_lua),
|
MODL("mime", mime_lua),
|
||||||
MODL("socket", socket_lua),
|
MODL("socket", socket_lua),
|
||||||
MODL("socket.ftp", ftp_lua),
|
MODL("socket.ftp", ftp_lua),
|
||||||
MODL("socket.headers", headers_lua),
|
MODL("socket.headers", headers_lua),
|
||||||
MODL("socket.http", http_lua),
|
MODL("socket.http", http_lua),
|
||||||
MODL("socket.smtp", smtp_lua),
|
MODL("socket.smtp", smtp_lua),
|
||||||
MODL("socket.tp", tp_lua),
|
MODL("socket.tp", tp_lua),
|
||||||
MODL("socket.url", url_lua),
|
MODL("socket.url", url_lua),
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
MODC("socket.unix", luaopen_socket_unix),
|
MODC("socket.unix", luaopen_socket_unix),
|
||||||
MODC("socket.serial", luaopen_socket_serial),
|
MODC("socket.serial", luaopen_socket_serial),
|
||||||
#endif
|
#endif
|
||||||
// LuaSec
|
// LuaSec
|
||||||
MODC("ssl.core", luaopen_ssl_core),
|
MODC("ssl.core", luaopen_ssl_core),
|
||||||
MODC("ssl.context", luaopen_ssl_context),
|
MODC("ssl.context", luaopen_ssl_context),
|
||||||
MODC("ssl.x509", luaopen_ssl_x509),
|
MODC("ssl.x509", luaopen_ssl_x509),
|
||||||
MODC("ssl.config", luaopen_ssl_config),
|
MODC("ssl.config", luaopen_ssl_config),
|
||||||
MODL("ssl.https", https_lua),
|
MODL("ssl.https", https_lua),
|
||||||
MODL("ssl", ssl_lua),
|
MODL("ssl", ssl_lua),
|
||||||
// LuaRS232
|
// LuaRS232
|
||||||
MODC("rs232.core", luaopen_luars232),
|
MODC("rs232.core", luaopen_luars232),
|
||||||
MODL("rs232", rs232_lua),
|
MODL("rs232", rs232_lua),
|
||||||
|
// binaryheap
|
||||||
|
MODL("binaryheap", binaryheap_lua),
|
||||||
|
// timerwheel
|
||||||
|
MODL("timerwheel", timerwheel_lua),
|
||||||
|
// Copas
|
||||||
|
MODL("copas", copas_lua),
|
||||||
|
MODL("copas.ftp", copas_ftp_lua),
|
||||||
|
MODL("copas.http", copas_http_lua),
|
||||||
|
MODL("copas.lock", copas_lock_lua),
|
||||||
|
MODL("copas.queue", copas_queue_lua),
|
||||||
|
MODL("copas.semaphore", copas_semaphore_lua),
|
||||||
|
MODL("copas.smtp", copas_smtp_lua),
|
||||||
|
MODL("copas.timer", copas_timer_lua),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2808,7 +2821,6 @@ int32_t apiVideoGetLanguageDescription(lua_State *L) {
|
||||||
if (lua_isstring(L, 1)) {
|
if (lua_isstring(L, 1)) {
|
||||||
c = (char *)lua_tostring(L, 1);
|
c = (char *)lua_tostring(L, 1);
|
||||||
r = videoGetLanguageDescription(c);
|
r = videoGetLanguageDescription(c);
|
||||||
// utilSay("[%s] [%s]", c, r);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -292,7 +292,6 @@ int32_t _loadVideoAndAudio(char *vFilename, char *aFilename, char *indexPath, bo
|
||||||
while ((tag = (AVDictionaryEntry *)av_dict_iterate(fmt_ctx->streams[x]->metadata, tag))) {
|
while ((tag = (AVDictionaryEntry *)av_dict_iterate(fmt_ctx->streams[x]->metadata, tag))) {
|
||||||
if (utilStricmp("language", tag->key) == 0) {
|
if (utilStricmp("language", tag->key) == 0) {
|
||||||
v->audio[count++].language = strdup(tag->value);
|
v->audio[count++].language = strdup(tag->value);
|
||||||
utilSay("Track %d is %s", x, tag->value);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -502,15 +501,6 @@ char *videoGetLanguageDescription(char *languageCode) {
|
||||||
int32_t i = 0;
|
int32_t i = 0;
|
||||||
|
|
||||||
while (p_languages[i].psz_eng_name != NULL) {
|
while (p_languages[i].psz_eng_name != NULL) {
|
||||||
/*
|
|
||||||
utilSay("[%s] [%s] [%s] [%s] [%s]",
|
|
||||||
languageCode,
|
|
||||||
p_languages[i].psz_eng_name,
|
|
||||||
p_languages[i].psz_iso639_1,
|
|
||||||
p_languages[i].psz_iso639_2T,
|
|
||||||
p_languages[i].psz_iso639_2B
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
if ((utilStricmp(languageCode, (char *)p_languages[i].psz_iso639_1) == 0) ||
|
if ((utilStricmp(languageCode, (char *)p_languages[i].psz_iso639_1) == 0) ||
|
||||||
(utilStricmp(languageCode, (char *)p_languages[i].psz_iso639_2T) == 0) ||
|
(utilStricmp(languageCode, (char *)p_languages[i].psz_iso639_2T) == 0) ||
|
||||||
(utilStricmp(languageCode, (char *)p_languages[i].psz_iso639_2B) == 0)) {
|
(utilStricmp(languageCode, (char *)p_languages[i].psz_iso639_2B) == 0)) {
|
||||||
|
|
7
thirdparty/binaryheap.lua/.busted
vendored
Normal file
7
thirdparty/binaryheap.lua/.busted
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
return {
|
||||||
|
default = {
|
||||||
|
verbose = true,
|
||||||
|
coverage = true,
|
||||||
|
output = "gtest",
|
||||||
|
},
|
||||||
|
}
|
13
thirdparty/binaryheap.lua/.editorconfig
vendored
Normal file
13
thirdparty/binaryheap.lua/.editorconfig
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
charset = utf-8
|
||||||
|
|
||||||
|
[*.lua]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
2
thirdparty/binaryheap.lua/.gitignore
vendored
Normal file
2
thirdparty/binaryheap.lua/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.DS_Store
|
||||||
|
luacov.*
|
31
thirdparty/binaryheap.lua/.luacheckrc
vendored
Normal file
31
thirdparty/binaryheap.lua/.luacheckrc
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
std = "ngx_lua+busted"
|
||||||
|
unused_args = false
|
||||||
|
redefined = false
|
||||||
|
max_line_length = false
|
||||||
|
|
||||||
|
|
||||||
|
globals = {
|
||||||
|
--"_KONG",
|
||||||
|
--"kong",
|
||||||
|
--"ngx.IS_CLI",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
not_globals = {
|
||||||
|
"string.len",
|
||||||
|
"table.getn",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ignore = {
|
||||||
|
--"6.", -- ignore whitespace warnings
|
||||||
|
"211/_ENV", -- unused variable
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
exclude_files = {
|
||||||
|
"here/**"
|
||||||
|
--"spec/fixtures/invalid-module.lua",
|
||||||
|
--"spec-old-api/fixtures/invalid-module.lua",
|
||||||
|
}
|
||||||
|
|
6
thirdparty/binaryheap.lua/.luacov
vendored
Normal file
6
thirdparty/binaryheap.lua/.luacov
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
modules = {
|
||||||
|
["binaryheap"] = "src/binaryheap.lua",
|
||||||
|
["binaryheap.*"] = "src"
|
||||||
|
}
|
||||||
|
runreport = true
|
||||||
|
deletestats = false -- file still needed to push to coveralls
|
29
thirdparty/binaryheap.lua/.travis.yml
vendored
Normal file
29
thirdparty/binaryheap.lua/.travis.yml
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
language: python
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
env:
|
||||||
|
- LUA="lua 5.1"
|
||||||
|
- LUA="lua 5.2"
|
||||||
|
- LUA="lua 5.3"
|
||||||
|
- LUA="luajit 2.0"
|
||||||
|
- LUA="luajit 2.0 --compat 5.2"
|
||||||
|
- LUA="luajit 2.1"
|
||||||
|
- LUA="luajit 2.1 --compat 5.2"
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- pip install hererocks
|
||||||
|
- hererocks here -r^ --$LUA
|
||||||
|
- source here/bin/activate
|
||||||
|
- luarocks install luacheck
|
||||||
|
- luarocks install busted
|
||||||
|
- luarocks install luacov-coveralls
|
||||||
|
|
||||||
|
install:
|
||||||
|
- luarocks make
|
||||||
|
|
||||||
|
script:
|
||||||
|
- luacheck .
|
||||||
|
- busted
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- luacov-coveralls
|
21
thirdparty/binaryheap.lua/LICENSE
vendored
Normal file
21
thirdparty/binaryheap.lua/LICENSE
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
Copyright © 2015-2019 Thijs Schreijer.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use, copy,
|
||||||
|
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
53
thirdparty/binaryheap.lua/README.md
vendored
Normal file
53
thirdparty/binaryheap.lua/README.md
vendored
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
[](https://travis-ci.com/Tieske/binaryheap.lua)
|
||||||
|
[](https://coveralls.io/github/Tieske/binaryheap.lua?branch=master)
|
||||||
|
|
||||||
|
binaryheap.lua
|
||||||
|
==============
|
||||||
|
|
||||||
|
[Binary heap](http://en.wikipedia.org/wiki/Binary_heap) implementation
|
||||||
|
|
||||||
|
Both the [source code](https://github.com/Tieske/binaryheap.lua) as well as the
|
||||||
|
[documentation](http://tieske.github.io/binaryheap.lua) are on github
|
||||||
|
|
||||||
|
Based on [original code](http://lua-users.org/lists/lua-l/2015-04/msg00137.html)
|
||||||
|
by Oliver Kroth, with
|
||||||
|
[extras](http://lua-users.org/lists/lua-l/2015-04/msg00133.html)
|
||||||
|
as proposed by Sean Conner.
|
||||||
|
|
||||||
|
Contributions
|
||||||
|
=============
|
||||||
|
This library was create by contributions from Oliver Kroth,
|
||||||
|
Thijs Schreijer, Boris Nagaev
|
||||||
|
|
||||||
|
History
|
||||||
|
=======
|
||||||
|
|
||||||
|
Version 0.4, 7-Nov-2018
|
||||||
|
|
||||||
|
- [breaking] added additional tests, mostly on returning errors, minor behaviour changes
|
||||||
|
- added `size` method
|
||||||
|
- fixed a lot of linter issues
|
||||||
|
|
||||||
|
Version 0.3, 15-Jul-2018
|
||||||
|
|
||||||
|
- bugfix `unique:pop` returning wrong order results (by Daurnimator)
|
||||||
|
- change `unique:peek` returning same order as `pop`
|
||||||
|
- added `unique:peekValue` returning just the value
|
||||||
|
|
||||||
|
Version 0.2, 21-Apr-2015
|
||||||
|
|
||||||
|
- bugfix `remove` function (by Boris Nagaev)
|
||||||
|
- configurable comparison function for the tree
|
||||||
|
|
||||||
|
Version 0.1, 20-Apr-2015
|
||||||
|
|
||||||
|
- Initial release
|
||||||
|
|
||||||
|
|
||||||
|
Copyright
|
||||||
|
=========
|
||||||
|
Copyright 2015-2019 Thijs Schreijer
|
||||||
|
|
||||||
|
License
|
||||||
|
=======
|
||||||
|
MIT/X11
|
26
thirdparty/binaryheap.lua/binaryheap-0.4-1.rockspec
vendored
Normal file
26
thirdparty/binaryheap.lua/binaryheap-0.4-1.rockspec
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package = "binaryheap"
|
||||||
|
version = "0.4-1"
|
||||||
|
|
||||||
|
source = {
|
||||||
|
url = "https://github.com/Tieske/binaryheap.lua/archive/version_0v4.tar.gz",
|
||||||
|
dir = "binaryheap.lua-version_0v4"
|
||||||
|
}
|
||||||
|
|
||||||
|
description = {
|
||||||
|
summary = "Binary heap implementation in pure Lua",
|
||||||
|
detailed = [[
|
||||||
|
Binary heaps are an efficient sorting algorithm. This module
|
||||||
|
implements a plain binary heap (without reverse lookup) and a
|
||||||
|
'unique' binary heap (with unique payloads and reverse lookup).
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "https://github.com/Tieske/binaryheap.lua"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1",
|
||||||
|
}
|
||||||
|
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = { binaryheap = "src/binaryheap.lua" }
|
||||||
|
}
|
11
thirdparty/binaryheap.lua/config.ld
vendored
Normal file
11
thirdparty/binaryheap.lua/config.ld
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
project='binaryheap.lua'
|
||||||
|
title='binaryheap'
|
||||||
|
description='Module to create binary heaps'
|
||||||
|
format='markdown'
|
||||||
|
file='./src/'
|
||||||
|
dir='docs'
|
||||||
|
readme='readme.md'
|
||||||
|
sort=true
|
||||||
|
sort_modules=true
|
||||||
|
all=false
|
||||||
|
style='./docs/'
|
703
thirdparty/binaryheap.lua/docs/index.html
vendored
Normal file
703
thirdparty/binaryheap.lua/docs/index.html
vendored
Normal file
|
@ -0,0 +1,703 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<head>
|
||||||
|
<title>binaryheap</title>
|
||||||
|
<link rel="stylesheet" href="ldoc.css" type="text/css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="container">
|
||||||
|
|
||||||
|
<div id="product">
|
||||||
|
<div id="product_logo"></div>
|
||||||
|
<div id="product_name"><big><b></b></big></div>
|
||||||
|
<div id="product_description"></div>
|
||||||
|
</div> <!-- id="product" -->
|
||||||
|
|
||||||
|
|
||||||
|
<div id="main">
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Menu -->
|
||||||
|
|
||||||
|
<div id="navigation">
|
||||||
|
<br/>
|
||||||
|
<h1>binaryheap.lua</h1>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#Basic_heap">Basic heap </a></li>
|
||||||
|
<li><a href="#Plain_heap">Plain heap </a></li>
|
||||||
|
<li><a href="#Unique_heap">Unique heap </a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Modules</h2>
|
||||||
|
<ul class="nowrap">
|
||||||
|
<li><strong>binaryheap</strong></li>
|
||||||
|
</ul>
|
||||||
|
<h2>Topics</h2>
|
||||||
|
<ul class="">
|
||||||
|
<li><a href="topics/readme.md.html">readme</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="content">
|
||||||
|
|
||||||
|
<h1>Module <code>binaryheap</code></h1>
|
||||||
|
<p>Binary heap implementation</p>
|
||||||
|
|
||||||
|
<p> A binary heap (or binary tree) is a <a href="http://en.wikipedia.org/wiki/Binary_heap">sorting algorithm</a>.</p>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
|
||||||
|
<p> The 'plain binary heap' is managed by positions. Which are hard to get once
|
||||||
|
an element is inserted. It can be anywhere in the list because it is re-sorted
|
||||||
|
upon insertion/deletion of items. The array with values is stored in field
|
||||||
|
<code>values</code>:</p>
|
||||||
|
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<span class="backtick"><code>peek = heap.values[1]</code></span>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p> A 'unique binary heap' is where the payload is unique and the payload itself
|
||||||
|
also stored (as key) in the heap with the position as value, as in;</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<span class="backtick"><code>heap.reverse[payload] = [pos]</code></span>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p> Due to this setup the reverse search, based on payload, is now a
|
||||||
|
much faster operation because instead of traversing the list/heap,
|
||||||
|
you can do;</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<span class="backtick"><code>pos = heap.reverse[payload]</code></span>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p> This means that deleting elements from a 'unique binary heap' is
|
||||||
|
faster than from a plain heap.</p>
|
||||||
|
|
||||||
|
<p> All management functions in the 'unique binary heap' take <code>payload</code>
|
||||||
|
instead of <code>pos</code> as argument.
|
||||||
|
Note that the value of the payload must be unique!</p>
|
||||||
|
|
||||||
|
<p> Fields of heap object:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>values - array of values</li>
|
||||||
|
<li>payloads - array of payloads (unique binary heap only)</li>
|
||||||
|
<li>reverse - map from payloads to indices (unique binary heap only)</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a href="#Basic_heap">Basic heap </a></h2>
|
||||||
|
<table class="function_list">
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#binaryHeap">binaryHeap (swap, erase, lt)</a></td>
|
||||||
|
<td class="summary">Creates a new binary heap.</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<h2><a href="#Plain_heap">Plain heap </a></h2>
|
||||||
|
<table class="function_list">
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#heap:insert">heap:insert (value)</a></td>
|
||||||
|
<td class="summary">Inserts an element in the heap.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#heap:peek">heap:peek ()</a></td>
|
||||||
|
<td class="summary">Returns the element at the top of the heap, without removing it.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#heap:pop">heap:pop ()</a></td>
|
||||||
|
<td class="summary">Removes the top of the heap and returns it.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#heap:remove">heap:remove (pos)</a></td>
|
||||||
|
<td class="summary">Removes an element from the heap.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#heap:size">heap:size ()</a></td>
|
||||||
|
<td class="summary">Returns the number of elements in the heap.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#heap:update">heap:update (pos, newValue)</a></td>
|
||||||
|
<td class="summary">Updates the value of an element in the heap.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#maxHeap">maxHeap (gt)</a></td>
|
||||||
|
<td class="summary">Creates a new max-heap, where the largest value is at the top.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#minHeap">minHeap (lt)</a></td>
|
||||||
|
<td class="summary">Creates a new min-heap, where the smallest value is at the top.</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<h2><a href="#Unique_heap">Unique heap </a></h2>
|
||||||
|
<table class="function_list">
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#heap:size">heap:size ()</a></td>
|
||||||
|
<td class="summary">Returns the number of elements in the heap.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#maxUnique">maxUnique (gt)</a></td>
|
||||||
|
<td class="summary">Creates a new max-heap with unique payloads.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#minUnique">minUnique (lt)</a></td>
|
||||||
|
<td class="summary">Creates a new min-heap with unique payloads.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#unique:insert">unique:insert (value, payload)</a></td>
|
||||||
|
<td class="summary">Inserts an element in the heap.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#unique:peek">unique:peek ()</a></td>
|
||||||
|
<td class="summary">Returns the element at the top of the heap, without removing it.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#unique:peekValue">unique:peekValue ()</a></td>
|
||||||
|
<td class="summary">Returns the element at the top of the heap, without removing it.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#unique:pop">unique:pop ()</a></td>
|
||||||
|
<td class="summary">Removes the top of the heap and returns it.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#unique:remove">unique:remove (payload)</a></td>
|
||||||
|
<td class="summary">Removes an element from the heap.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#unique:update">unique:update (payload, newValue)</a></td>
|
||||||
|
<td class="summary">Updates the value of an element in the heap.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#unique:valueByPayload">unique:valueByPayload (payload)</a></td>
|
||||||
|
<td class="summary">Returns the value associated with the payload</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
<h2 class="section-header has-description"><a name="Basic_heap"></a>Basic heap </h2>
|
||||||
|
|
||||||
|
<div class="section-description">
|
||||||
|
This is the base implementation of the heap. Under regular circumstances
|
||||||
|
this should not be used, instead use a <em>Plain heap</em> or <em>Unique heap</em>.
|
||||||
|
</div>
|
||||||
|
<dl class="function">
|
||||||
|
<dt>
|
||||||
|
<a name = "binaryHeap"></a>
|
||||||
|
<strong>binaryHeap (swap, erase, lt)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Creates a new binary heap.
|
||||||
|
This is the core of all heaps, the others
|
||||||
|
are built upon these sorting functions.
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">swap</span>
|
||||||
|
(function) <code>swap(heap, idx1, idx2)</code> swaps values at
|
||||||
|
<code>idx1</code> and <code>idx2</code> in the heaps <code>heap.values</code> and <code>heap.payloads</code> lists (see
|
||||||
|
return value below).
|
||||||
|
</li>
|
||||||
|
<li><span class="parameter">erase</span>
|
||||||
|
(function) <code>swap(heap, position)</code> raw removal
|
||||||
|
</li>
|
||||||
|
<li><span class="parameter">lt</span>
|
||||||
|
(function) in <code>lt(a, b)</code> returns <code>true</code> when <code>a < b</code> (for a min-heap)
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
table with two methods; <code>heap:bubbleUp(pos)</code> and <code>heap:sinkDown(pos)</code>
|
||||||
|
that implement the sorting algorithm and two fields; <code>heap.values</code> and
|
||||||
|
<code>heap.payloads</code> being lists, holding the values and payloads respectively.
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<h2 class="section-header has-description"><a name="Plain_heap"></a>Plain heap </h2>
|
||||||
|
|
||||||
|
<div class="section-description">
|
||||||
|
A plain heap carries a single piece of information per entry. This can be
|
||||||
|
any type (except <code>nil</code>), as long as the comparison function used to create
|
||||||
|
the heap can handle it.
|
||||||
|
</div>
|
||||||
|
<dl class="function">
|
||||||
|
<dt>
|
||||||
|
<a name = "heap:insert"></a>
|
||||||
|
<strong>heap:insert (value)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Inserts an element in the heap.
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">value</span>
|
||||||
|
the value used for sorting this element
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
nothing, or throws an error on bad input
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "heap:peek"></a>
|
||||||
|
<strong>heap:peek ()</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Returns the element at the top of the heap, without removing it.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
value at the top, or <code>nil</code> if there is none
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "heap:pop"></a>
|
||||||
|
<strong>heap:pop ()</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Removes the top of the heap and returns it.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
value at the top, or <code>nil</code> if there is none
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "heap:remove"></a>
|
||||||
|
<strong>heap:remove (pos)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Removes an element from the heap.
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">pos</span>
|
||||||
|
the position to remove
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
value, or nil if a bad <code>pos</code> value was provided
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "heap:size"></a>
|
||||||
|
<strong>heap:size ()</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Returns the number of elements in the heap.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
number of elements
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "heap:update"></a>
|
||||||
|
<strong>heap:update (pos, newValue)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Updates the value of an element in the heap.
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">pos</span>
|
||||||
|
the position which value to update
|
||||||
|
</li>
|
||||||
|
<li><span class="parameter">newValue</span>
|
||||||
|
the new value to use for this payload
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "maxHeap"></a>
|
||||||
|
<strong>maxHeap (gt)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Creates a new max-heap, where the largest value is at the top.
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">gt</span>
|
||||||
|
(optional) comparison function (greater-than), see <a href="index.html#binaryHeap">binaryHeap</a>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
the new heap
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "minHeap"></a>
|
||||||
|
<strong>minHeap (lt)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Creates a new min-heap, where the smallest value is at the top.
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">lt</span>
|
||||||
|
(optional) comparison function (less-than), see <a href="index.html#binaryHeap">binaryHeap</a>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
the new heap
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<h2 class="section-header has-description"><a name="Unique_heap"></a>Unique heap </h2>
|
||||||
|
|
||||||
|
<div class="section-description">
|
||||||
|
A unique heap carries 2 pieces of information per entry.</p>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>The <code>value</code>, this is used for ordering the heap. It can be any type (except
|
||||||
|
<code>nil</code>), as long as the comparison function used to create the heap can
|
||||||
|
handle it.</li>
|
||||||
|
<li>The <code>payload</code>, this can be any type (except <code>nil</code>), but it MUST be unique.</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p> With the 'unique heap' it is easier to remove elements from the heap.
|
||||||
|
</div>
|
||||||
|
<dl class="function">
|
||||||
|
<dt>
|
||||||
|
<a name = "heap:size"></a>
|
||||||
|
<strong>heap:size ()</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Returns the number of elements in the heap.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
number of elements
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "maxUnique"></a>
|
||||||
|
<strong>maxUnique (gt)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Creates a new max-heap with unique payloads.
|
||||||
|
A max-heap is where the largest value is at the top.</p>
|
||||||
|
|
||||||
|
<p> <em>NOTE</em>: All management functions in the 'unique binary heap'
|
||||||
|
take <code>payload</code> instead of <code>pos</code> as argument.
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">gt</span>
|
||||||
|
(optional) comparison function (greater-than), see <a href="index.html#binaryHeap">binaryHeap</a>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
the new heap
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "minUnique"></a>
|
||||||
|
<strong>minUnique (lt)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Creates a new min-heap with unique payloads.
|
||||||
|
A min-heap is where the smallest value is at the top.</p>
|
||||||
|
|
||||||
|
<p> <em>NOTE</em>: All management functions in the 'unique binary heap'
|
||||||
|
take <code>payload</code> instead of <code>pos</code> as argument.
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">lt</span>
|
||||||
|
(optional) comparison function (less-than), see <a href="index.html#binaryHeap">binaryHeap</a>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
the new heap
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "unique:insert"></a>
|
||||||
|
<strong>unique:insert (value, payload)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Inserts an element in the heap.
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">value</span>
|
||||||
|
the value used for sorting this element
|
||||||
|
</li>
|
||||||
|
<li><span class="parameter">payload</span>
|
||||||
|
the payload attached to this element
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
nothing, or throws an error on bad input
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "unique:peek"></a>
|
||||||
|
<strong>unique:peek ()</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Returns the element at the top of the heap, without removing it.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
payload, value, or <code>nil</code> if there is none
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "unique:peekValue"></a>
|
||||||
|
<strong>unique:peekValue ()</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Returns the element at the top of the heap, without removing it.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
value at the top, or <code>nil</code> if there is none
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Usage:</h3>
|
||||||
|
<ul>
|
||||||
|
<pre class="example"><span class="comment">-- simple timer based heap example
|
||||||
|
</span><span class="keyword">while</span> <span class="keyword">true</span> <span class="keyword">do</span>
|
||||||
|
sleep(heap:peekValue() - gettime()) <span class="comment">-- assume LuaSocket gettime function
|
||||||
|
</span> <span class="global">coroutine</span>.resume((heap:pop())) <span class="comment">-- assumes payload to be a coroutine,
|
||||||
|
</span> <span class="comment">-- double parens to drop extra return value
|
||||||
|
</span><span class="keyword">end</span></pre>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "unique:pop"></a>
|
||||||
|
<strong>unique:pop ()</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Removes the top of the heap and returns it.
|
||||||
|
When used with timers, <a href="index.html#unique:pop">pop</a> will return the payload that is due.</p>
|
||||||
|
|
||||||
|
<p> Note: this function returns <code>payload</code> as the first result to prevent
|
||||||
|
extra locals when retrieving the <code>payload</code>.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
payload, value, or <code>nil</code> if there is none
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "unique:remove"></a>
|
||||||
|
<strong>unique:remove (payload)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Removes an element from the heap.
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">payload</span>
|
||||||
|
the payload to remove
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
value, payload or nil if not found
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "unique:update"></a>
|
||||||
|
<strong>unique:update (payload, newValue)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Updates the value of an element in the heap.
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">payload</span>
|
||||||
|
the payoad whose value to update
|
||||||
|
</li>
|
||||||
|
<li><span class="parameter">newValue</span>
|
||||||
|
the new value to use for this payload
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
nothing, or throws an error on bad input
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "unique:valueByPayload"></a>
|
||||||
|
<strong>unique:valueByPayload (payload)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Returns the value associated with the payload
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">payload</span>
|
||||||
|
the payload to lookup
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
value or nil if no such payload exists
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
</div> <!-- id="content" -->
|
||||||
|
</div> <!-- id="main" -->
|
||||||
|
<div id="about">
|
||||||
|
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
|
||||||
|
<i style="float:right;">Last updated 2018-11-07 17:56:33 </i>
|
||||||
|
</div> <!-- id="about" -->
|
||||||
|
</div> <!-- id="container" -->
|
||||||
|
</body>
|
||||||
|
</html>
|
291
thirdparty/binaryheap.lua/docs/ldoc.css
vendored
Normal file
291
thirdparty/binaryheap.lua/docs/ldoc.css
vendored
Normal file
|
@ -0,0 +1,291 @@
|
||||||
|
body {
|
||||||
|
color: #47555c;
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: "Open Sans", sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
background: #eff4ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:link { color: #008fee; }
|
||||||
|
a:visited { color: #008fee; }
|
||||||
|
a:hover { color: #22a7ff; }
|
||||||
|
|
||||||
|
h1 { font-size:26px; font-weight: normal; }
|
||||||
|
h2 { font-size:22px; font-weight: normal; }
|
||||||
|
h3 { font-size:18px; font-weight: normal; }
|
||||||
|
h4 { font-size:16px; font-weight: bold; }
|
||||||
|
|
||||||
|
hr {
|
||||||
|
height: 1px;
|
||||||
|
background: #c1cce4;
|
||||||
|
border: 0px;
|
||||||
|
margin: 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
code, tt {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
span.parameter {
|
||||||
|
font-family: monospace;
|
||||||
|
font-weight: bold;
|
||||||
|
color: rgb(99, 115, 131);
|
||||||
|
}
|
||||||
|
span.parameter:after {
|
||||||
|
content:":";
|
||||||
|
}
|
||||||
|
span.types:before {
|
||||||
|
content:"(";
|
||||||
|
}
|
||||||
|
span.types:after {
|
||||||
|
content:")";
|
||||||
|
}
|
||||||
|
.type {
|
||||||
|
font-weight: bold; font-style:italic
|
||||||
|
}
|
||||||
|
|
||||||
|
p.name {
|
||||||
|
font-family: "Andale Mono", monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation {
|
||||||
|
float: left;
|
||||||
|
background-color: white;
|
||||||
|
border-right: 1px solid #d3dbec;
|
||||||
|
border-bottom: 1px solid #d3dbec;
|
||||||
|
|
||||||
|
width: 14em;
|
||||||
|
vertical-align: top;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation br {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation h1 {
|
||||||
|
background-color: white;
|
||||||
|
border-bottom: 1px solid #d3dbec;
|
||||||
|
padding: 15px;
|
||||||
|
margin-top: 0px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation h2 {
|
||||||
|
font-size: 18px;
|
||||||
|
background-color: white;
|
||||||
|
border-bottom: 1px solid #d3dbec;
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
margin-top: 30px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content h1 {
|
||||||
|
background-color: #2c3e67;
|
||||||
|
color: white;
|
||||||
|
padding: 15px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content h2 {
|
||||||
|
background-color: #6c7ea7;
|
||||||
|
color: white;
|
||||||
|
padding: 15px;
|
||||||
|
padding-top: 15px;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content h2 a {
|
||||||
|
background-color: #6c7ea7;
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content h2 a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content h3 {
|
||||||
|
font-style: italic;
|
||||||
|
padding-top: 15px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
margin-right: 15px;
|
||||||
|
margin-left: 15px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
border-bottom: solid 1px #bcd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content h4 {
|
||||||
|
margin-right: 15px;
|
||||||
|
margin-left: 15px;
|
||||||
|
border-bottom: solid 1px #bcd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content pre {
|
||||||
|
margin: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background-color: rgb(50, 55, 68);
|
||||||
|
color: white;
|
||||||
|
border-radius: 3px;
|
||||||
|
/* border: 1px solid #C0C0C0; /* silver */
|
||||||
|
padding: 15px;
|
||||||
|
overflow: auto;
|
||||||
|
font-family: "Andale Mono", monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content ul pre.example {
|
||||||
|
margin-left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.index {
|
||||||
|
/* border: 1px #00007f; */
|
||||||
|
}
|
||||||
|
table.index td { text-align: left; vertical-align: top; }
|
||||||
|
|
||||||
|
#navigation ul
|
||||||
|
{
|
||||||
|
font-size:1em;
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 1px 1px 10px 1px;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation li {
|
||||||
|
text-indent: -1em;
|
||||||
|
display: block;
|
||||||
|
margin: 3px 0px 0px 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation li li a {
|
||||||
|
margin: 0px 3px 0px -1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
margin-left: 14em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content p {
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content table {
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content p, #content table, #content ol, #content ul, #content dl {
|
||||||
|
max-width: 900px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#about {
|
||||||
|
padding: 15px;
|
||||||
|
padding-left: 16em;
|
||||||
|
background-color: white;
|
||||||
|
border-top: 1px solid #d3dbec;
|
||||||
|
border-bottom: 1px solid #d3dbec;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.module_list, table.function_list {
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: #cccccc;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 15px;
|
||||||
|
}
|
||||||
|
table.module_list td, table.function_list td {
|
||||||
|
border-width: 1px;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
border: solid 1px rgb(193, 204, 228);
|
||||||
|
}
|
||||||
|
table.module_list td.name, table.function_list td.name {
|
||||||
|
background-color: white; min-width: 200px; border-right-width: 0px;
|
||||||
|
}
|
||||||
|
table.module_list td.summary, table.function_list td.summary {
|
||||||
|
background-color: white; width: 100%; border-left-width: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.function {
|
||||||
|
margin-right: 15px;
|
||||||
|
margin-left: 15px;
|
||||||
|
border-bottom: solid 1px rgb(193, 204, 228);
|
||||||
|
border-left: solid 1px rgb(193, 204, 228);
|
||||||
|
border-right: solid 1px rgb(193, 204, 228);
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.function dt {
|
||||||
|
color: rgb(99, 123, 188);
|
||||||
|
font-family: monospace;
|
||||||
|
border-top: solid 1px rgb(193, 204, 228);
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.function dd {
|
||||||
|
margin-left: 15px;
|
||||||
|
margin-right: 15px;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content dl.function dd h3 {
|
||||||
|
margin-top: 0px;
|
||||||
|
margin-left: 0px;
|
||||||
|
padding-left: 0px;
|
||||||
|
font-size: 16px;
|
||||||
|
color: rgb(128, 128, 128);
|
||||||
|
border-bottom: solid 1px #def;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content dl.function dd ul, #content dl.function dd ol {
|
||||||
|
padding: 0px;
|
||||||
|
padding-left: 15px;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.nowrap {
|
||||||
|
overflow:auto;
|
||||||
|
white-space:nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-description {
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* stop sublists from having initial vertical space */
|
||||||
|
ul ul { margin-top: 0px; }
|
||||||
|
ol ul { margin-top: 0px; }
|
||||||
|
ol ol { margin-top: 0px; }
|
||||||
|
ul ol { margin-top: 0px; }
|
||||||
|
|
||||||
|
/* make the target distinct; helps when we're navigating to a function */
|
||||||
|
a:target + * {
|
||||||
|
background-color: #FF9;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* styles for prettification of source */
|
||||||
|
pre .comment { color: #bbccaa; }
|
||||||
|
pre .constant { color: #a8660d; }
|
||||||
|
pre .escape { color: #844631; }
|
||||||
|
pre .keyword { color: #ffc090; font-weight: bold; }
|
||||||
|
pre .library { color: #0e7c6b; }
|
||||||
|
pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; }
|
||||||
|
pre .string { color: #8080ff; }
|
||||||
|
pre .number { color: #f8660d; }
|
||||||
|
pre .operator { color: #2239a8; font-weight: bold; }
|
||||||
|
pre .preprocessor, pre .prepro { color: #a33243; }
|
||||||
|
pre .global { color: #c040c0; }
|
||||||
|
pre .user-keyword { color: #800080; }
|
||||||
|
pre .prompt { color: #558817; }
|
||||||
|
pre .url { color: #272fc2; text-decoration: underline; }
|
109
thirdparty/binaryheap.lua/docs/topics/readme.md.html
vendored
Normal file
109
thirdparty/binaryheap.lua/docs/topics/readme.md.html
vendored
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<head>
|
||||||
|
<title>binaryheap</title>
|
||||||
|
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="container">
|
||||||
|
|
||||||
|
<div id="product">
|
||||||
|
<div id="product_logo"></div>
|
||||||
|
<div id="product_name"><big><b></b></big></div>
|
||||||
|
<div id="product_description"></div>
|
||||||
|
</div> <!-- id="product" -->
|
||||||
|
|
||||||
|
|
||||||
|
<div id="main">
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Menu -->
|
||||||
|
|
||||||
|
<div id="navigation">
|
||||||
|
<br/>
|
||||||
|
<h1>binaryheap.lua</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Topics</h2>
|
||||||
|
<ul class="">
|
||||||
|
<li><strong>readme</strong></li>
|
||||||
|
</ul>
|
||||||
|
<h2>Modules</h2>
|
||||||
|
<ul class="nowrap">
|
||||||
|
<li><a href="../index.html">binaryheap</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="content">
|
||||||
|
|
||||||
|
|
||||||
|
<h1>binaryheap.lua</h1>
|
||||||
|
|
||||||
|
<p><a href="http://en.wikipedia.org/wiki/Binary_heap">Binary heap</a> implementation</p>
|
||||||
|
|
||||||
|
<p>Both the <a href="https://github.com/Tieske/binaryheap.lua">source code</a> as well as the
|
||||||
|
<a href="http://tieske.github.io/binaryheap.lua">documentation</a> are on github</p>
|
||||||
|
|
||||||
|
<p>Based on <a href="http://lua-users.org/lists/lua-l/2015-04/msg00137.html">original code</a>
|
||||||
|
by Oliver Kroth, with
|
||||||
|
<a href="http://lua-users.org/lists/lua-l/2015-04/msg00133.html">extras</a>
|
||||||
|
as proposed by Sean Conner.</p>
|
||||||
|
|
||||||
|
<h1>Contributions</h1>
|
||||||
|
<p>This library was create by contributions from Oliver Kroth,
|
||||||
|
Thijs Schreijer, Boris Nagaev</p>
|
||||||
|
|
||||||
|
<h1>History</h1>
|
||||||
|
|
||||||
|
<p>Version 0.4, 7-Nov-2018</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>[breaking] added additional tests, mostly on returning errors, minor behaviour changes</li>
|
||||||
|
<li>added <a href="../index.html#heap:size">size</a> method</li>
|
||||||
|
<li>fixed a lot of linter issues</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>Version 0.3, 15-Jul-2018</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>bugfix <a href="../index.html#unique:pop">unique:pop</a> returning wrong order results (by Daurnimator)</li>
|
||||||
|
<li>change <a href="../index.html#unique:peek">unique:peek</a> returning same order as <a href="../index.html#unique:pop">pop</a></li>
|
||||||
|
<li>added <a href="../index.html#unique:peekValue">unique:peekValue</a> returning just the value</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>Version 0.2, 21-Apr-2015</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>bugfix <a href="../index.html#heap:remove">remove</a> function (by Boris Nagaev)</li>
|
||||||
|
<li>configurable comparison function for the tree</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>Version 0.1, 20-Apr-2015</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Initial release</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<h1>Copyright</h1>
|
||||||
|
<p>Copyright 2015-2018 Thijs Schreijer</p>
|
||||||
|
|
||||||
|
<h1>License</h1>
|
||||||
|
<p>MIT/X11</p>
|
||||||
|
|
||||||
|
|
||||||
|
</div> <!-- id="content" -->
|
||||||
|
</div> <!-- id="main" -->
|
||||||
|
<div id="about">
|
||||||
|
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
|
||||||
|
<i style="float:right;">Last updated 2018-11-07 17:56:33 </i>
|
||||||
|
</div> <!-- id="about" -->
|
||||||
|
</div> <!-- id="container" -->
|
||||||
|
</body>
|
||||||
|
</html>
|
85
thirdparty/binaryheap.lua/examples/knight_dijkstra.lua
vendored
Normal file
85
thirdparty/binaryheap.lua/examples/knight_dijkstra.lua
vendored
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
-- Calculates shortest path of Knight from (1, 1) to (x, y).
|
||||||
|
-- Prints matrix of shortest paths for all cells.
|
||||||
|
-- Knight can't leave the rectangle from (1, 1) to (x, y).
|
||||||
|
|
||||||
|
-- See https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
|
||||||
|
-- See http://stackoverflow.com/questions/2339101
|
||||||
|
|
||||||
|
-- Usage:
|
||||||
|
-- $ lua knight_dijkstra.lua X Y
|
||||||
|
|
||||||
|
local binaryheap = require 'binaryheap'
|
||||||
|
|
||||||
|
local ROWS = tonumber(arg[2]) or 8
|
||||||
|
local COLS = tonumber(arg[1]) or 8
|
||||||
|
|
||||||
|
local unvisited = binaryheap.minUnique()
|
||||||
|
|
||||||
|
local function Cell(x, y)
|
||||||
|
return x .. '_' .. y
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Coordinates(cell)
|
||||||
|
local x, y = cell:match('(%d+)_(%d+)')
|
||||||
|
return x, y
|
||||||
|
end
|
||||||
|
|
||||||
|
local function neighbours(cell)
|
||||||
|
local x, y = Coordinates(cell)
|
||||||
|
local gen = coroutine.wrap(function()
|
||||||
|
coroutine.yield(x - 1, y - 2)
|
||||||
|
coroutine.yield(x - 1, y + 2)
|
||||||
|
coroutine.yield(x + 1, y - 2)
|
||||||
|
coroutine.yield(x + 1, y + 2)
|
||||||
|
coroutine.yield(x - 2, y - 1)
|
||||||
|
coroutine.yield(x - 2, y + 1)
|
||||||
|
coroutine.yield(x + 2, y - 1)
|
||||||
|
coroutine.yield(x + 2, y + 1)
|
||||||
|
end)
|
||||||
|
return coroutine.wrap(function()
|
||||||
|
for xx, yy in gen do
|
||||||
|
if 1 <= xx and xx <= COLS and
|
||||||
|
1 <= yy and yy <= ROWS then
|
||||||
|
coroutine.yield(Cell(xx, yy))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
for y = 1, ROWS do
|
||||||
|
for x = 1, COLS do
|
||||||
|
local cell = Cell(x, y)
|
||||||
|
unvisited:insert(math.huge, cell)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
unvisited:update('1_1', 0)
|
||||||
|
|
||||||
|
local final_distance = {}
|
||||||
|
|
||||||
|
while unvisited:peek() do
|
||||||
|
local current_distance, current = unvisited:peek()
|
||||||
|
assert(not final_distance[current])
|
||||||
|
final_distance[current] = current_distance
|
||||||
|
unvisited:remove(current)
|
||||||
|
-- update neighbours
|
||||||
|
local new_distance = current_distance + 1
|
||||||
|
for neighbour in neighbours(current) do
|
||||||
|
if unvisited.reverse[neighbour] then
|
||||||
|
local pos = unvisited.reverse[neighbour]
|
||||||
|
local distance = unvisited.value[pos]
|
||||||
|
if distance > new_distance then
|
||||||
|
unvisited:update(neighbour, new_distance)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for y = 1, ROWS do
|
||||||
|
local row = {}
|
||||||
|
for x = 1, COLS do
|
||||||
|
local cell = Cell(x, y)
|
||||||
|
local distance = final_distance[cell]
|
||||||
|
table.insert(row, distance)
|
||||||
|
end
|
||||||
|
print(table.concat(row, ' '))
|
||||||
|
end
|
835
thirdparty/binaryheap.lua/spec/binaryheap_spec.lua
vendored
Normal file
835
thirdparty/binaryheap.lua/spec/binaryheap_spec.lua
vendored
Normal file
|
@ -0,0 +1,835 @@
|
||||||
|
|
||||||
|
local bh = require('binaryheap')
|
||||||
|
|
||||||
|
local data = {
|
||||||
|
{ value = 98, payload = "pos08" }, -- 1
|
||||||
|
{ value = 28, payload = "pos05" }, -- 2
|
||||||
|
{ value = 36, payload = "pos06" }, -- 3
|
||||||
|
{ value = 48, payload = "pos09" }, -- 4
|
||||||
|
{ value = 68, payload = "pos10" }, -- 5
|
||||||
|
{ value = 58, payload = "pos13" }, -- 6
|
||||||
|
{ value = 80, payload = "pos15" }, -- 7
|
||||||
|
{ value = 46, payload = "pos04" }, -- 8
|
||||||
|
{ value = 19, payload = "pos03" }, -- 9
|
||||||
|
{ value = 66, payload = "pos11" }, -- 10
|
||||||
|
{ value = 22, payload = "pos02" }, -- 11
|
||||||
|
{ value = 60, payload = "pos12" }, -- 12
|
||||||
|
{ value = 15, payload = "pos01" }, -- 13
|
||||||
|
{ value = 83, payload = "pos14" }, -- 14
|
||||||
|
{ value = 59, payload = "pos07" }, -- 15
|
||||||
|
}
|
||||||
|
|
||||||
|
local sort = function(t)
|
||||||
|
table.sort(t, function(a,b) return (a.value < b.value) end)
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
|
local function check(heap)
|
||||||
|
for pos = 2, #heap.values do
|
||||||
|
local parent = math.floor(pos / 2)
|
||||||
|
assert(not heap.lt(heap.values[pos], heap.values[parent]))
|
||||||
|
end
|
||||||
|
if heap.payloads then
|
||||||
|
for pos in ipairs(heap.values) do
|
||||||
|
local payload = heap.payloads[pos]
|
||||||
|
assert(heap.reverse[payload] == pos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function newheap()
|
||||||
|
-- create a heap with data
|
||||||
|
local heap = bh.minUnique()
|
||||||
|
for _, node in ipairs(data) do
|
||||||
|
heap:insert(node.value,node.payload)
|
||||||
|
check(heap)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- create a sorted list with data, sorted by 'value'
|
||||||
|
local sorted = {}
|
||||||
|
for k,v in pairs(data) do sorted[k] = v end
|
||||||
|
sort(sorted)
|
||||||
|
-- create a reverse list of the sorted table; returns sorted-index, based on 'value'
|
||||||
|
local sreverse = {}
|
||||||
|
for i,v in ipairs(sorted) do
|
||||||
|
sreverse[v.value] = i
|
||||||
|
end
|
||||||
|
return heap, sorted, sreverse
|
||||||
|
end
|
||||||
|
|
||||||
|
local function testheap(heap, sorted)
|
||||||
|
while sorted[1] do
|
||||||
|
local value1, payload1
|
||||||
|
if heap.reverse then
|
||||||
|
-- it is a unique heap
|
||||||
|
payload1, value1 = heap:pop()
|
||||||
|
else
|
||||||
|
-- it is a plain heap
|
||||||
|
value1, payload1 = heap:pop()
|
||||||
|
end
|
||||||
|
local value2, payload2 = sorted[1].value, sorted[1].payload
|
||||||
|
table.remove(sorted, 1)
|
||||||
|
assert.are.equal(payload1, payload2)
|
||||||
|
assert.are.equal(value1, value2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe("[minUnique]", function()
|
||||||
|
|
||||||
|
it("validates order of insertion", function()
|
||||||
|
local h = newheap()
|
||||||
|
assert.are.equal(h.payloads[1], data[13].payload)
|
||||||
|
assert.are.equal(h.payloads[2], data[11].payload)
|
||||||
|
assert.are.equal(h.payloads[3], data[9].payload)
|
||||||
|
assert.are.equal(h.payloads[4], data[8].payload)
|
||||||
|
assert.are.equal(h.payloads[5], data[2].payload)
|
||||||
|
assert.are.equal(h.payloads[6], data[3].payload)
|
||||||
|
assert.are.equal(h.payloads[7], data[15].payload)
|
||||||
|
assert.are.equal(h.payloads[8], data[1].payload)
|
||||||
|
assert.are.equal(h.payloads[9], data[4].payload)
|
||||||
|
assert.are.equal(h.payloads[10], data[5].payload)
|
||||||
|
assert.are.equal(h.payloads[11], data[10].payload)
|
||||||
|
assert.are.equal(h.payloads[12], data[12].payload)
|
||||||
|
assert.are.equal(h.payloads[13], data[6].payload)
|
||||||
|
assert.are.equal(h.payloads[14], data[14].payload)
|
||||||
|
assert.are.equal(h.payloads[15], data[7].payload)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("validates order of popping", function()
|
||||||
|
testheap(newheap())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("peek()", function()
|
||||||
|
local heap, sorted = newheap()
|
||||||
|
local payload, value = heap:peek()
|
||||||
|
-- correct values?
|
||||||
|
assert.are.equal(value, sorted[1].value)
|
||||||
|
assert.are.equal(payload, sorted[1].payload)
|
||||||
|
-- are they still on the heap?
|
||||||
|
assert.are.equal(value, heap.values[1])
|
||||||
|
assert.are.equal(payload, heap.payloads[1])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("peekValue()", function()
|
||||||
|
local h = bh.minUnique()
|
||||||
|
h:insert(1, 11)
|
||||||
|
assert.equal(1, h:peekValue(11))
|
||||||
|
-- try again empty
|
||||||
|
h:pop()
|
||||||
|
assert.is_nil(h:peekValue(11))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("pop()", function()
|
||||||
|
local h = bh.minUnique()
|
||||||
|
h:insert(3, 13)
|
||||||
|
h:insert(2, 12)
|
||||||
|
h:insert(1, 11)
|
||||||
|
-- try again empty
|
||||||
|
local pl, v
|
||||||
|
pl, v = h:pop()
|
||||||
|
assert.equal(v, 1)
|
||||||
|
assert.equal(pl, 11)
|
||||||
|
pl, v = h:pop()
|
||||||
|
assert.equal(v, 2)
|
||||||
|
assert.equal(pl, 12)
|
||||||
|
pl, v = h:pop()
|
||||||
|
assert.equal(v, 3)
|
||||||
|
assert.equal(pl, 13)
|
||||||
|
pl, v = h:pop()
|
||||||
|
assert.is_nil(v)
|
||||||
|
assert.is_nil(pl)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("remove()", function()
|
||||||
|
it("a middle item", function()
|
||||||
|
local heap, sorted = newheap()
|
||||||
|
local idx = 4
|
||||||
|
local value = sorted[idx].value
|
||||||
|
local payload = sorted[idx].payload
|
||||||
|
local v, pl = heap:remove(payload)
|
||||||
|
check(heap)
|
||||||
|
-- did we get the right ones?
|
||||||
|
assert.are.equal(value, v)
|
||||||
|
assert.are.equal(payload, pl)
|
||||||
|
assert.is.Nil(heap[payload])
|
||||||
|
-- remove from test data and compare
|
||||||
|
table.remove(sorted, idx)
|
||||||
|
testheap(heap, sorted)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("the last item (of the array)", function()
|
||||||
|
local heap, sorted = newheap()
|
||||||
|
local idx = #heap.values
|
||||||
|
local value = sorted[idx].value
|
||||||
|
local payload = sorted[idx].payload
|
||||||
|
local v, pl = heap:remove(payload)
|
||||||
|
check(heap)
|
||||||
|
-- did we get the right ones?
|
||||||
|
assert.are.equal(value, v)
|
||||||
|
assert.are.equal(payload, pl)
|
||||||
|
assert.is.Nil(heap.reverse[payload])
|
||||||
|
-- remove from test data and compare
|
||||||
|
table.remove(sorted, idx)
|
||||||
|
testheap(heap, sorted)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("non existing payload returns nil", function()
|
||||||
|
local heap = newheap()
|
||||||
|
local v, pl = heap:remove({})
|
||||||
|
assert.is_nil(v)
|
||||||
|
assert.is_nil(pl)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("nil payload returns nil", function()
|
||||||
|
local heap = newheap()
|
||||||
|
local v, pl = heap:remove(nil)
|
||||||
|
assert.is_nil(v)
|
||||||
|
assert.is_nil(pl)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("with repeated values", function()
|
||||||
|
local h = bh.minUnique()
|
||||||
|
h:insert(1, 11)
|
||||||
|
check(h)
|
||||||
|
h:insert(1, 12)
|
||||||
|
check(h)
|
||||||
|
local value, payload
|
||||||
|
value, payload = h:remove(11)
|
||||||
|
check(h)
|
||||||
|
assert.equal(1, value)
|
||||||
|
assert.equal(11, payload)
|
||||||
|
payload, value = h:peek()
|
||||||
|
assert.equal(1, value)
|
||||||
|
assert.equal(12, payload)
|
||||||
|
assert.same({1}, h.values)
|
||||||
|
assert.same({12}, h.payloads)
|
||||||
|
assert.same({[12]=1}, h.reverse)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("insert()", function()
|
||||||
|
it("a top item", function()
|
||||||
|
local heap, sorted = newheap()
|
||||||
|
local nvalue = sorted[1].value - 10
|
||||||
|
local npayload = {}
|
||||||
|
table.insert(sorted, 1, {})
|
||||||
|
sorted[1].value = nvalue
|
||||||
|
sorted[1].payload = npayload
|
||||||
|
heap:insert(nvalue, npayload)
|
||||||
|
check(heap)
|
||||||
|
testheap(heap, sorted)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("a middle item", function()
|
||||||
|
local heap, sorted = newheap()
|
||||||
|
local nvalue = 57
|
||||||
|
local npayload = {}
|
||||||
|
table.insert(sorted, { value = nvalue, payload = npayload })
|
||||||
|
sort(sorted)
|
||||||
|
heap:insert(nvalue, npayload)
|
||||||
|
check(heap)
|
||||||
|
testheap(heap, sorted)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("a last item", function()
|
||||||
|
local heap, sorted = newheap()
|
||||||
|
local nvalue = sorted[#sorted].value + 10
|
||||||
|
local npayload = {}
|
||||||
|
table.insert(sorted, {})
|
||||||
|
sorted[#sorted].value = nvalue
|
||||||
|
sorted[#sorted].payload = npayload
|
||||||
|
heap:insert(nvalue, npayload)
|
||||||
|
check(heap)
|
||||||
|
testheap(heap, sorted)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("a nil value throws an error", function()
|
||||||
|
local heap = newheap()
|
||||||
|
assert.has.error(function()
|
||||||
|
heap:insert(nil, "something")
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("a nil payload throws an error", function()
|
||||||
|
local heap = newheap()
|
||||||
|
assert.has.error(function()
|
||||||
|
heap:insert(15, nil)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("a duplicate payload throws an error", function()
|
||||||
|
local heap = newheap()
|
||||||
|
local value = {}
|
||||||
|
heap:insert(1, value)
|
||||||
|
assert.has.error(function()
|
||||||
|
heap:insert(2, value)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("update()", function()
|
||||||
|
it("a top item", function()
|
||||||
|
local heap, sorted = newheap()
|
||||||
|
local idx = 1
|
||||||
|
local payload = sorted[idx].payload
|
||||||
|
local nvalue = sorted[#sorted].value + 1 -- move to end with new value
|
||||||
|
sorted[idx].value = nvalue
|
||||||
|
sort(sorted)
|
||||||
|
heap:update(payload, nvalue)
|
||||||
|
check(heap)
|
||||||
|
testheap(heap, sorted)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("a middle item", function()
|
||||||
|
local heap, sorted = newheap()
|
||||||
|
local idx = 4
|
||||||
|
local payload = sorted[idx].payload
|
||||||
|
local nvalue = sorted[idx].value * 2
|
||||||
|
sorted[idx].value = nvalue
|
||||||
|
sort(sorted)
|
||||||
|
heap:update(payload, nvalue)
|
||||||
|
check(heap)
|
||||||
|
testheap(heap, sorted)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("a last item", function()
|
||||||
|
local heap, sorted = newheap()
|
||||||
|
local idx = #sorted
|
||||||
|
local payload = sorted[idx].payload
|
||||||
|
local nvalue = sorted[1].value - 1 -- move to top with new value
|
||||||
|
sorted[idx].value = nvalue
|
||||||
|
sort(sorted)
|
||||||
|
heap:update(payload, nvalue)
|
||||||
|
check(heap)
|
||||||
|
testheap(heap, sorted)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("a nil value throws an error", function()
|
||||||
|
local heap, sorted = newheap()
|
||||||
|
local idx = #sorted
|
||||||
|
local payload = sorted[idx].payload
|
||||||
|
assert.has.error(function()
|
||||||
|
heap:update(payload, nil)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("an unknown payload throws an error", function()
|
||||||
|
local heap = newheap()
|
||||||
|
assert.has.error(function()
|
||||||
|
heap:update({}, 10)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("size()", function()
|
||||||
|
it("returns number of elements", function()
|
||||||
|
local h = bh.minUnique()
|
||||||
|
assert.equal(0, h:size())
|
||||||
|
h:insert(1, -1)
|
||||||
|
assert.equal(1, h:size())
|
||||||
|
h:insert(2, -2)
|
||||||
|
assert.equal(2, h:size())
|
||||||
|
h:insert(3, -3)
|
||||||
|
assert.equal(3, h:size())
|
||||||
|
h:insert(4, -4)
|
||||||
|
assert.equal(4, h:size())
|
||||||
|
h:insert(5, -5)
|
||||||
|
assert.equal(5, h:size())
|
||||||
|
h:pop()
|
||||||
|
assert.equal(4, h:size())
|
||||||
|
h:pop()
|
||||||
|
assert.equal(3, h:size())
|
||||||
|
h:pop()
|
||||||
|
assert.equal(2, h:size())
|
||||||
|
h:pop()
|
||||||
|
assert.equal(1, h:size())
|
||||||
|
h:pop()
|
||||||
|
assert.equal(0, h:size())
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("valueByPayload()", function()
|
||||||
|
it("gets value by payload", function()
|
||||||
|
local h = bh.minUnique()
|
||||||
|
h:insert(1, -1)
|
||||||
|
h:insert(2, -2)
|
||||||
|
h:insert(3, -3)
|
||||||
|
h:insert(4, -4)
|
||||||
|
h:insert(5, -5)
|
||||||
|
assert.equal(1, h:valueByPayload((-1)))
|
||||||
|
assert.equal(2, h:valueByPayload((-2)))
|
||||||
|
assert.equal(3, h:valueByPayload((-3)))
|
||||||
|
assert.equal(4, h:valueByPayload((-4)))
|
||||||
|
assert.equal(5, h:valueByPayload((-5)))
|
||||||
|
h:remove(-1)
|
||||||
|
assert.falsy(h:valueByPayload((-1)))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("non existing payload returns nil", function()
|
||||||
|
local h = bh.minUnique()
|
||||||
|
h:insert(1, -1)
|
||||||
|
h:insert(2, -2)
|
||||||
|
h:insert(3, -3)
|
||||||
|
h:insert(4, -4)
|
||||||
|
h:insert(5, -5)
|
||||||
|
assert.is_nil(h:valueByPayload({}))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("nil payload returns nil", function()
|
||||||
|
local h = bh.minUnique()
|
||||||
|
h:insert(1, -1)
|
||||||
|
h:insert(2, -2)
|
||||||
|
h:insert(3, -3)
|
||||||
|
h:insert(4, -4)
|
||||||
|
h:insert(5, -5)
|
||||||
|
assert.is_nil(h:valueByPayload(nil))
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("creates minUnique with custom less-than function", function()
|
||||||
|
local h = bh.minUnique(function (a, b)
|
||||||
|
return math.abs(a) < math.abs(b)
|
||||||
|
end)
|
||||||
|
h:insert(1, -1)
|
||||||
|
check(h)
|
||||||
|
h:insert(-2, 2)
|
||||||
|
check(h)
|
||||||
|
h:insert(3, -3)
|
||||||
|
check(h)
|
||||||
|
h:insert(-4, 4)
|
||||||
|
check(h)
|
||||||
|
h:insert(5, -5)
|
||||||
|
check(h)
|
||||||
|
local value, payload
|
||||||
|
payload, value = h:peek()
|
||||||
|
assert.equal(1, value)
|
||||||
|
assert.equal(-1, payload)
|
||||||
|
h:pop()
|
||||||
|
check(h)
|
||||||
|
payload, value = h:peek()
|
||||||
|
assert.equal(-2, value)
|
||||||
|
assert.equal(2, payload)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("[maxUnique]", function()
|
||||||
|
it("creates maxUnique with custom less-than function", function()
|
||||||
|
local h = bh.maxUnique(function (a, b)
|
||||||
|
return math.abs(a) > math.abs(b)
|
||||||
|
end)
|
||||||
|
h:insert(1, -1)
|
||||||
|
check(h)
|
||||||
|
h:insert(-2, 2)
|
||||||
|
check(h)
|
||||||
|
h:insert(3, -3)
|
||||||
|
check(h)
|
||||||
|
h:insert(-4, 4)
|
||||||
|
check(h)
|
||||||
|
h:insert(5, -5)
|
||||||
|
check(h)
|
||||||
|
local value, payload
|
||||||
|
payload, value = h:peek()
|
||||||
|
assert.equal(5, value)
|
||||||
|
assert.equal(-5, payload)
|
||||||
|
h:pop()
|
||||||
|
check(h)
|
||||||
|
payload, value = h:peek()
|
||||||
|
assert.equal(-4, value)
|
||||||
|
assert.equal(4, payload)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("[minHeap]", function()
|
||||||
|
it("creates minHeap", function()
|
||||||
|
local h = bh.minHeap()
|
||||||
|
check(h)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("insert()", function()
|
||||||
|
it("a number into minHeap", function()
|
||||||
|
local h = bh.minHeap()
|
||||||
|
h:insert(42)
|
||||||
|
check(h)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("nil throws an error", function()
|
||||||
|
local h = bh.minHeap()
|
||||||
|
assert.has.error(function()
|
||||||
|
h:insert(nil)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("remove()", function()
|
||||||
|
it("a position", function()
|
||||||
|
local h = bh.minHeap()
|
||||||
|
h:insert(42)
|
||||||
|
h:insert(43)
|
||||||
|
assert.equal(43, h:remove(2))
|
||||||
|
check(h)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("a bad position returns nil", function()
|
||||||
|
local h = bh.minHeap()
|
||||||
|
h:insert(42)
|
||||||
|
h:insert(43)
|
||||||
|
assert.is_nil(h:remove(0))
|
||||||
|
assert.is_nil(h:remove(3))
|
||||||
|
check(h)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("size()", function()
|
||||||
|
it("returns number of elements", function()
|
||||||
|
local h = bh.minHeap()
|
||||||
|
assert.equal(0, h:size())
|
||||||
|
h:insert(1)
|
||||||
|
assert.equal(1, h:size())
|
||||||
|
h:insert(2)
|
||||||
|
assert.equal(2, h:size())
|
||||||
|
h:insert(3)
|
||||||
|
assert.equal(3, h:size())
|
||||||
|
h:insert(4)
|
||||||
|
assert.equal(4, h:size())
|
||||||
|
h:insert(5)
|
||||||
|
assert.equal(5, h:size())
|
||||||
|
h:pop()
|
||||||
|
assert.equal(4, h:size())
|
||||||
|
h:pop()
|
||||||
|
assert.equal(3, h:size())
|
||||||
|
h:pop()
|
||||||
|
assert.equal(2, h:size())
|
||||||
|
h:pop()
|
||||||
|
assert.equal(1, h:size())
|
||||||
|
h:pop()
|
||||||
|
assert.equal(0, h:size())
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("peek()", function()
|
||||||
|
it("return nil in empty minHeap", function()
|
||||||
|
local h = bh.minHeap()
|
||||||
|
assert.is_nil(h:peek())
|
||||||
|
check(h)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("minHeap of one element", function()
|
||||||
|
local h = bh.minHeap()
|
||||||
|
h:insert(42)
|
||||||
|
check(h)
|
||||||
|
local value, payload = h:peek()
|
||||||
|
assert.equal(42, value)
|
||||||
|
assert.falsy(payload)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("minHeap of two elements", function()
|
||||||
|
local h = bh.minHeap()
|
||||||
|
h:insert(42)
|
||||||
|
check(h)
|
||||||
|
h:insert(1)
|
||||||
|
check(h)
|
||||||
|
local value, payload = h:peek()
|
||||||
|
assert.equal(1, value)
|
||||||
|
assert.falsy(payload)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("minHeap of 10 elements", function()
|
||||||
|
local h = bh.minHeap()
|
||||||
|
h:insert(10)
|
||||||
|
h:insert(7)
|
||||||
|
h:insert(1)
|
||||||
|
h:insert(5)
|
||||||
|
h:insert(6)
|
||||||
|
h:insert(9)
|
||||||
|
h:insert(8)
|
||||||
|
h:insert(4)
|
||||||
|
h:insert(2)
|
||||||
|
h:insert(3)
|
||||||
|
check(h)
|
||||||
|
local value, payload = h:peek()
|
||||||
|
assert.equal(1, value)
|
||||||
|
assert.falsy(payload)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("removes peek in minHeap of 5 elements", function()
|
||||||
|
local h = bh.minHeap()
|
||||||
|
h:insert(1)
|
||||||
|
h:insert(2)
|
||||||
|
h:insert(3)
|
||||||
|
h:insert(4)
|
||||||
|
h:insert(5)
|
||||||
|
local value
|
||||||
|
value = h:pop()
|
||||||
|
check(h)
|
||||||
|
assert.equal(1, value)
|
||||||
|
value = h:peek()
|
||||||
|
assert.equal(2, value)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("update()", function()
|
||||||
|
it("in minHeap of 5 elements (pos 2 -> pos 1)", function()
|
||||||
|
local h = bh.minHeap()
|
||||||
|
h:insert(1)
|
||||||
|
h:insert(2)
|
||||||
|
h:insert(3)
|
||||||
|
h:insert(4)
|
||||||
|
h:insert(5)
|
||||||
|
check(h)
|
||||||
|
h:update(2, -100)
|
||||||
|
check(h)
|
||||||
|
local value = h:peek()
|
||||||
|
assert.equal(-100, value)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("in minHeap of 5 elements (pos 1 -> pos 2)", function()
|
||||||
|
local h = bh.minHeap()
|
||||||
|
h:insert(1)
|
||||||
|
h:insert(2)
|
||||||
|
h:insert(3)
|
||||||
|
h:insert(4)
|
||||||
|
h:insert(5)
|
||||||
|
check(h)
|
||||||
|
h:update(1, 100)
|
||||||
|
check(h)
|
||||||
|
local value = h:peek()
|
||||||
|
assert.equal(2, value)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("nil throws an error", function()
|
||||||
|
local h = bh.minHeap()
|
||||||
|
h:insert(10)
|
||||||
|
assert.has.error(function()
|
||||||
|
h:update(nil)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("bad position throws an error", function()
|
||||||
|
local h = bh.minHeap()
|
||||||
|
h:insert(10)
|
||||||
|
assert.has.error(function()
|
||||||
|
h:update(0)
|
||||||
|
end)
|
||||||
|
assert.has.error(function()
|
||||||
|
h:update(2)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("creates minHeap with custom less-than function", function()
|
||||||
|
local h = bh.minHeap(function (a, b)
|
||||||
|
return math.abs(a) < math.abs(b)
|
||||||
|
end)
|
||||||
|
h:insert(1)
|
||||||
|
check(h)
|
||||||
|
h:insert(-2)
|
||||||
|
check(h)
|
||||||
|
h:insert(3)
|
||||||
|
check(h)
|
||||||
|
h:insert(-4)
|
||||||
|
check(h)
|
||||||
|
h:insert(5)
|
||||||
|
check(h)
|
||||||
|
assert.equal(1, h:peek())
|
||||||
|
h:pop()
|
||||||
|
check(h)
|
||||||
|
assert.equal(-2, h:peek())
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
describe("[maxHeap]", function()
|
||||||
|
it("creates maxHeap", function()
|
||||||
|
local h = bh.maxHeap()
|
||||||
|
check(h)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("insert()", function()
|
||||||
|
it("inserts a number into maxHeap", function()
|
||||||
|
local h = bh.maxHeap()
|
||||||
|
h:insert(42)
|
||||||
|
check(h)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("nil throws an error", function()
|
||||||
|
local h = bh.maxHeap()
|
||||||
|
assert.has.error(function()
|
||||||
|
h:insert(nil)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("remove()", function()
|
||||||
|
it("a position", function()
|
||||||
|
local h = bh.maxHeap()
|
||||||
|
h:insert(42)
|
||||||
|
h:insert(43)
|
||||||
|
assert.equal(42, h:remove(2))
|
||||||
|
check(h)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("a bad position returns nil", function()
|
||||||
|
local h = bh.maxHeap()
|
||||||
|
h:insert(42)
|
||||||
|
h:insert(43)
|
||||||
|
assert.is_nil(h:remove(0))
|
||||||
|
assert.is_nil(h:remove(3))
|
||||||
|
check(h)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("size()", function()
|
||||||
|
it("returns number of elements", function()
|
||||||
|
local h = bh.minHeap()
|
||||||
|
assert.equal(0, h:size())
|
||||||
|
h:insert(1)
|
||||||
|
assert.equal(1, h:size())
|
||||||
|
h:insert(2)
|
||||||
|
assert.equal(2, h:size())
|
||||||
|
h:insert(3)
|
||||||
|
assert.equal(3, h:size())
|
||||||
|
h:insert(4)
|
||||||
|
assert.equal(4, h:size())
|
||||||
|
h:insert(5)
|
||||||
|
assert.equal(5, h:size())
|
||||||
|
h:pop()
|
||||||
|
assert.equal(4, h:size())
|
||||||
|
h:pop()
|
||||||
|
assert.equal(3, h:size())
|
||||||
|
h:pop()
|
||||||
|
assert.equal(2, h:size())
|
||||||
|
h:pop()
|
||||||
|
assert.equal(1, h:size())
|
||||||
|
h:pop()
|
||||||
|
assert.equal(0, h:size())
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("peek()", function()
|
||||||
|
it("return nil in empty maxHeap", function()
|
||||||
|
local h = bh.maxHeap()
|
||||||
|
assert.is_nil(h:peek())
|
||||||
|
check(h)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("maxHeap of one element", function()
|
||||||
|
local h = bh.maxHeap()
|
||||||
|
h:insert(42)
|
||||||
|
check(h)
|
||||||
|
local value = h:peek()
|
||||||
|
assert.equal(42, value)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("maxHeap of two elements", function()
|
||||||
|
local h = bh.maxHeap()
|
||||||
|
h:insert(42)
|
||||||
|
check(h)
|
||||||
|
h:insert(1)
|
||||||
|
check(h)
|
||||||
|
local value = h:peek()
|
||||||
|
assert.equal(42, value)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("maxHeap of 10 elements", function()
|
||||||
|
local h = bh.maxHeap()
|
||||||
|
h:insert(10)
|
||||||
|
h:insert(7)
|
||||||
|
h:insert(1)
|
||||||
|
h:insert(5)
|
||||||
|
h:insert(6)
|
||||||
|
h:insert(9)
|
||||||
|
h:insert(8)
|
||||||
|
h:insert(4)
|
||||||
|
h:insert(2)
|
||||||
|
h:insert(3)
|
||||||
|
check(h)
|
||||||
|
local value = h:peek()
|
||||||
|
assert.equal(10, value)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("removes peek in maxHeap of 5 elements", function()
|
||||||
|
local h = bh.maxHeap()
|
||||||
|
h:insert(1)
|
||||||
|
h:insert(2)
|
||||||
|
h:insert(3)
|
||||||
|
h:insert(4)
|
||||||
|
h:insert(5)
|
||||||
|
check(h)
|
||||||
|
local value
|
||||||
|
value = h:pop()
|
||||||
|
check(h)
|
||||||
|
assert.equal(5, value)
|
||||||
|
value = h:peek()
|
||||||
|
assert.equal(4, value)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("update()", function()
|
||||||
|
it("in maxHeap of 5 elements (pos 2 -> pos 1)", function()
|
||||||
|
local h = bh.maxHeap()
|
||||||
|
h:insert(1)
|
||||||
|
h:insert(2)
|
||||||
|
h:insert(3)
|
||||||
|
h:insert(4)
|
||||||
|
h:insert(5)
|
||||||
|
check(h)
|
||||||
|
h:update(2, 100)
|
||||||
|
check(h)
|
||||||
|
local value = h:peek()
|
||||||
|
assert.equal(100, value)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("in maxHeap of 5 elements (pos 1 -> pos 2)", function()
|
||||||
|
local h = bh.maxHeap()
|
||||||
|
h:insert(1)
|
||||||
|
h:insert(2)
|
||||||
|
h:insert(3)
|
||||||
|
h:insert(4)
|
||||||
|
h:insert(5)
|
||||||
|
check(h)
|
||||||
|
h:update(1, -100)
|
||||||
|
check(h)
|
||||||
|
local value = h:peek()
|
||||||
|
assert.equal(4, value)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("nil throws an error", function()
|
||||||
|
local h = bh.maxHeap()
|
||||||
|
h:insert(10)
|
||||||
|
assert.has.error(function()
|
||||||
|
h:update(nil)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("bad position throws an error", function()
|
||||||
|
local h = bh.maxHeap()
|
||||||
|
h:insert(10)
|
||||||
|
assert.has.error(function()
|
||||||
|
h:update(0)
|
||||||
|
end)
|
||||||
|
assert.has.error(function()
|
||||||
|
h:update(2)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("creates maxHeap with custom greater-than function", function()
|
||||||
|
local h = bh.maxHeap(function (a, b)
|
||||||
|
return math.abs(a) > math.abs(b)
|
||||||
|
end)
|
||||||
|
h:insert(1)
|
||||||
|
check(h)
|
||||||
|
h:insert(-2)
|
||||||
|
check(h)
|
||||||
|
h:insert(3)
|
||||||
|
check(h)
|
||||||
|
h:insert(-4)
|
||||||
|
check(h)
|
||||||
|
h:insert(5)
|
||||||
|
check(h)
|
||||||
|
assert.equal(5, (h:peek()))
|
||||||
|
h:pop()
|
||||||
|
check(h)
|
||||||
|
assert.equal(-4, (h:peek()))
|
||||||
|
end)
|
||||||
|
end)
|
95
thirdparty/binaryheap.lua/spec/dijkstras_algorithm_spec.lua
vendored
Normal file
95
thirdparty/binaryheap.lua/spec/dijkstras_algorithm_spec.lua
vendored
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
describe("dijkstras algorithm with binaryheap", function()
|
||||||
|
-- See https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
|
||||||
|
|
||||||
|
it("calculates knight's shortest path", function()
|
||||||
|
-- See http://stackoverflow.com/questions/2339101
|
||||||
|
|
||||||
|
local binaryheap = require 'binaryheap'
|
||||||
|
|
||||||
|
local ROWS = 8
|
||||||
|
local COLS = 8
|
||||||
|
|
||||||
|
local unvisited = binaryheap.minUnique()
|
||||||
|
|
||||||
|
local function Cell(x, y)
|
||||||
|
return x .. '_' .. y
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Coordinates(cell)
|
||||||
|
local x, y = cell:match('(%d+)_(%d+)')
|
||||||
|
return x, y
|
||||||
|
end
|
||||||
|
|
||||||
|
local function neighbours(cell)
|
||||||
|
local x, y = Coordinates(cell)
|
||||||
|
local gen = coroutine.wrap(function()
|
||||||
|
coroutine.yield(x - 1, y - 2)
|
||||||
|
coroutine.yield(x - 1, y + 2)
|
||||||
|
coroutine.yield(x + 1, y - 2)
|
||||||
|
coroutine.yield(x + 1, y + 2)
|
||||||
|
coroutine.yield(x - 2, y - 1)
|
||||||
|
coroutine.yield(x - 2, y + 1)
|
||||||
|
coroutine.yield(x + 2, y - 1)
|
||||||
|
coroutine.yield(x + 2, y + 1)
|
||||||
|
end)
|
||||||
|
return coroutine.wrap(function()
|
||||||
|
for xx, yy in gen do
|
||||||
|
if 1 <= xx and xx <= COLS and
|
||||||
|
1 <= yy and yy <= ROWS then
|
||||||
|
coroutine.yield(Cell(xx, yy))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
for y = 1, ROWS do
|
||||||
|
for x = 1, COLS do
|
||||||
|
local cell = Cell(x, y)
|
||||||
|
unvisited:insert(math.huge, cell)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
unvisited:update('1_1', 0)
|
||||||
|
|
||||||
|
local final_distance = {}
|
||||||
|
|
||||||
|
while unvisited:peekValue() do
|
||||||
|
local current, current_distance = unvisited:peek()
|
||||||
|
assert(not final_distance[current])
|
||||||
|
final_distance[current] = current_distance
|
||||||
|
unvisited:remove(current)
|
||||||
|
-- update neighbours
|
||||||
|
local new_distance = current_distance + 1
|
||||||
|
for neighbour in neighbours(current) do
|
||||||
|
if unvisited.reverse[neighbour] then
|
||||||
|
local pos = unvisited.reverse[neighbour]
|
||||||
|
local distance = unvisited.values[pos]
|
||||||
|
if distance > new_distance then
|
||||||
|
unvisited:update(neighbour, new_distance)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local rows = {}
|
||||||
|
for y = 1, ROWS do
|
||||||
|
local row = {}
|
||||||
|
for x = 1, COLS do
|
||||||
|
local cell = Cell(x, y)
|
||||||
|
local distance = final_distance[cell]
|
||||||
|
table.insert(row, distance)
|
||||||
|
end
|
||||||
|
table.insert(rows, table.concat(row, ' '))
|
||||||
|
end
|
||||||
|
|
||||||
|
assert.equal([[
|
||||||
|
0 3 2 3 2 3 4 5
|
||||||
|
3 4 1 2 3 4 3 4
|
||||||
|
2 1 4 3 2 3 4 5
|
||||||
|
3 2 3 2 3 4 3 4
|
||||||
|
2 3 2 3 4 3 4 5
|
||||||
|
3 4 3 4 3 4 5 4
|
||||||
|
4 3 4 3 4 5 4 5
|
||||||
|
5 4 5 4 5 4 5 6]],
|
||||||
|
table.concat(rows, '\n'))
|
||||||
|
end)
|
||||||
|
end)
|
406
thirdparty/binaryheap.lua/src/binaryheap.lua
vendored
Normal file
406
thirdparty/binaryheap.lua/src/binaryheap.lua
vendored
Normal file
|
@ -0,0 +1,406 @@
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
-- Binary heap implementation
|
||||||
|
--
|
||||||
|
-- A binary heap (or binary tree) is a [sorting algorithm](http://en.wikipedia.org/wiki/Binary_heap).
|
||||||
|
--
|
||||||
|
-- The 'plain binary heap' is managed by positions. Which are hard to get once
|
||||||
|
-- an element is inserted. It can be anywhere in the list because it is re-sorted
|
||||||
|
-- upon insertion/deletion of items. The array with values is stored in field
|
||||||
|
-- `values`:
|
||||||
|
--
|
||||||
|
-- `peek = heap.values[1]`
|
||||||
|
--
|
||||||
|
-- A 'unique binary heap' is where the payload is unique and the payload itself
|
||||||
|
-- also stored (as key) in the heap with the position as value, as in;
|
||||||
|
-- `heap.reverse[payload] = [pos]`
|
||||||
|
--
|
||||||
|
-- Due to this setup the reverse search, based on payload, is now a
|
||||||
|
-- much faster operation because instead of traversing the list/heap,
|
||||||
|
-- you can do;
|
||||||
|
-- `pos = heap.reverse[payload]`
|
||||||
|
--
|
||||||
|
-- This means that deleting elements from a 'unique binary heap' is
|
||||||
|
-- faster than from a plain heap.
|
||||||
|
--
|
||||||
|
-- All management functions in the 'unique binary heap' take `payload`
|
||||||
|
-- instead of `pos` as argument.
|
||||||
|
-- Note that the value of the payload must be unique!
|
||||||
|
--
|
||||||
|
-- Fields of heap object:
|
||||||
|
--
|
||||||
|
-- * values - array of values
|
||||||
|
-- * payloads - array of payloads (unique binary heap only)
|
||||||
|
-- * reverse - map from payloads to indices (unique binary heap only)
|
||||||
|
|
||||||
|
local assert = assert
|
||||||
|
local floor = math.floor
|
||||||
|
local _ENV = nil
|
||||||
|
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
--================================================================
|
||||||
|
-- basic heap sorting algorithm
|
||||||
|
--================================================================
|
||||||
|
|
||||||
|
--- Basic heap.
|
||||||
|
-- This is the base implementation of the heap. Under regular circumstances
|
||||||
|
-- this should not be used, instead use a _Plain heap_ or _Unique heap_.
|
||||||
|
-- @section baseheap
|
||||||
|
|
||||||
|
--- Creates a new binary heap.
|
||||||
|
-- This is the core of all heaps, the others
|
||||||
|
-- are built upon these sorting functions.
|
||||||
|
-- @param swap (function) `swap(heap, idx1, idx2)` swaps values at
|
||||||
|
-- `idx1` and `idx2` in the heaps `heap.values` and `heap.payloads` lists (see
|
||||||
|
-- return value below).
|
||||||
|
-- @param erase (function) `swap(heap, position)` raw removal
|
||||||
|
-- @param lt (function) in `lt(a, b)` returns `true` when `a < b` (for a min-heap)
|
||||||
|
-- @return table with two methods; `heap:bubbleUp(pos)` and `heap:sinkDown(pos)`
|
||||||
|
-- that implement the sorting algorithm and two fields; `heap.values` and
|
||||||
|
-- `heap.payloads` being lists, holding the values and payloads respectively.
|
||||||
|
M.binaryHeap = function(swap, erase, lt)
|
||||||
|
|
||||||
|
local heap = {
|
||||||
|
values = {}, -- list containing values
|
||||||
|
erase = erase,
|
||||||
|
swap = swap,
|
||||||
|
lt = lt,
|
||||||
|
}
|
||||||
|
|
||||||
|
function heap:bubbleUp(pos)
|
||||||
|
local values = self.values
|
||||||
|
while pos>1 do
|
||||||
|
local parent = floor(pos/2)
|
||||||
|
if not lt(values[pos], values[parent]) then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
swap(self, parent, pos)
|
||||||
|
pos = parent
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function heap:sinkDown(pos)
|
||||||
|
local values = self.values
|
||||||
|
local last = #values
|
||||||
|
while true do
|
||||||
|
local min = pos
|
||||||
|
local child = 2 * pos
|
||||||
|
|
||||||
|
for c = child, child + 1 do
|
||||||
|
if c <= last and lt(values[c], values[min]) then min = c end
|
||||||
|
end
|
||||||
|
|
||||||
|
if min == pos then break end
|
||||||
|
|
||||||
|
swap(self, pos, min)
|
||||||
|
pos = min
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return heap
|
||||||
|
end
|
||||||
|
|
||||||
|
--================================================================
|
||||||
|
-- plain heap management functions
|
||||||
|
--================================================================
|
||||||
|
|
||||||
|
--- Plain heap.
|
||||||
|
-- A plain heap carries a single piece of information per entry. This can be
|
||||||
|
-- any type (except `nil`), as long as the comparison function used to create
|
||||||
|
-- the heap can handle it.
|
||||||
|
-- @section plainheap
|
||||||
|
do end -- luacheck: ignore
|
||||||
|
-- the above is to trick ldoc (otherwise `update` below disappears)
|
||||||
|
|
||||||
|
local update
|
||||||
|
--- Updates the value of an element in the heap.
|
||||||
|
-- @function heap:update
|
||||||
|
-- @param pos the position which value to update
|
||||||
|
-- @param newValue the new value to use for this payload
|
||||||
|
update = function(self, pos, newValue)
|
||||||
|
assert(newValue ~= nil, "cannot add 'nil' as value")
|
||||||
|
assert(pos >= 1 and pos <= #self.values, "illegal position")
|
||||||
|
self.values[pos] = newValue
|
||||||
|
if pos > 1 then self:bubbleUp(pos) end
|
||||||
|
if pos < #self.values then self:sinkDown(pos) end
|
||||||
|
end
|
||||||
|
|
||||||
|
local remove
|
||||||
|
--- Removes an element from the heap.
|
||||||
|
-- @function heap:remove
|
||||||
|
-- @param pos the position to remove
|
||||||
|
-- @return value, or nil if a bad `pos` value was provided
|
||||||
|
remove = function(self, pos)
|
||||||
|
local last = #self.values
|
||||||
|
if pos < 1 then
|
||||||
|
return -- bad pos
|
||||||
|
|
||||||
|
elseif pos < last then
|
||||||
|
local v = self.values[pos]
|
||||||
|
self:swap(pos, last)
|
||||||
|
self:erase(last)
|
||||||
|
self:bubbleUp(pos)
|
||||||
|
self:sinkDown(pos)
|
||||||
|
return v
|
||||||
|
|
||||||
|
elseif pos == last then
|
||||||
|
local v = self.values[pos]
|
||||||
|
self:erase(last)
|
||||||
|
return v
|
||||||
|
|
||||||
|
else
|
||||||
|
return -- bad pos: pos > last
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local insert
|
||||||
|
--- Inserts an element in the heap.
|
||||||
|
-- @function heap:insert
|
||||||
|
-- @param value the value used for sorting this element
|
||||||
|
-- @return nothing, or throws an error on bad input
|
||||||
|
insert = function(self, value)
|
||||||
|
assert(value ~= nil, "cannot add 'nil' as value")
|
||||||
|
local pos = #self.values + 1
|
||||||
|
self.values[pos] = value
|
||||||
|
self:bubbleUp(pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
local pop
|
||||||
|
--- Removes the top of the heap and returns it.
|
||||||
|
-- @function heap:pop
|
||||||
|
-- @return value at the top, or `nil` if there is none
|
||||||
|
pop = function(self)
|
||||||
|
if self.values[1] ~= nil then
|
||||||
|
return remove(self, 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local peek
|
||||||
|
--- Returns the element at the top of the heap, without removing it.
|
||||||
|
-- @function heap:peek
|
||||||
|
-- @return value at the top, or `nil` if there is none
|
||||||
|
peek = function(self)
|
||||||
|
return self.values[1]
|
||||||
|
end
|
||||||
|
|
||||||
|
local size
|
||||||
|
--- Returns the number of elements in the heap.
|
||||||
|
-- @function heap:size
|
||||||
|
-- @return number of elements
|
||||||
|
size = function(self)
|
||||||
|
return #self.values
|
||||||
|
end
|
||||||
|
|
||||||
|
local function swap(heap, a, b)
|
||||||
|
heap.values[a], heap.values[b] = heap.values[b], heap.values[a]
|
||||||
|
end
|
||||||
|
|
||||||
|
local function erase(heap, pos)
|
||||||
|
heap.values[pos] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--================================================================
|
||||||
|
-- plain heap creation
|
||||||
|
--================================================================
|
||||||
|
|
||||||
|
local function plainHeap(lt)
|
||||||
|
local h = M.binaryHeap(swap, erase, lt)
|
||||||
|
h.peek = peek
|
||||||
|
h.pop = pop
|
||||||
|
h.size = size
|
||||||
|
h.remove = remove
|
||||||
|
h.insert = insert
|
||||||
|
h.update = update
|
||||||
|
return h
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Creates a new min-heap, where the smallest value is at the top.
|
||||||
|
-- @param lt (optional) comparison function (less-than), see `binaryHeap`.
|
||||||
|
-- @return the new heap
|
||||||
|
M.minHeap = function(lt)
|
||||||
|
if not lt then
|
||||||
|
lt = function(a,b) return (a < b) end
|
||||||
|
end
|
||||||
|
return plainHeap(lt)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Creates a new max-heap, where the largest value is at the top.
|
||||||
|
-- @param gt (optional) comparison function (greater-than), see `binaryHeap`.
|
||||||
|
-- @return the new heap
|
||||||
|
M.maxHeap = function(gt)
|
||||||
|
if not gt then
|
||||||
|
gt = function(a,b) return (a > b) end
|
||||||
|
end
|
||||||
|
return plainHeap(gt)
|
||||||
|
end
|
||||||
|
|
||||||
|
--================================================================
|
||||||
|
-- unique heap management functions
|
||||||
|
--================================================================
|
||||||
|
|
||||||
|
--- Unique heap.
|
||||||
|
-- A unique heap carries 2 pieces of information per entry.
|
||||||
|
--
|
||||||
|
-- 1. The `value`, this is used for ordering the heap. It can be any type (except
|
||||||
|
-- `nil`), as long as the comparison function used to create the heap can
|
||||||
|
-- handle it.
|
||||||
|
-- 2. The `payload`, this can be any type (except `nil`), but it MUST be unique.
|
||||||
|
--
|
||||||
|
-- With the 'unique heap' it is easier to remove elements from the heap.
|
||||||
|
-- @section uniqueheap
|
||||||
|
do end -- luacheck: ignore
|
||||||
|
-- the above is to trick ldoc (otherwise `update` below disappears)
|
||||||
|
|
||||||
|
local updateU
|
||||||
|
--- Updates the value of an element in the heap.
|
||||||
|
-- @function unique:update
|
||||||
|
-- @param payload the payoad whose value to update
|
||||||
|
-- @param newValue the new value to use for this payload
|
||||||
|
-- @return nothing, or throws an error on bad input
|
||||||
|
function updateU(self, payload, newValue)
|
||||||
|
return update(self, self.reverse[payload], newValue)
|
||||||
|
end
|
||||||
|
|
||||||
|
local insertU
|
||||||
|
--- Inserts an element in the heap.
|
||||||
|
-- @function unique:insert
|
||||||
|
-- @param value the value used for sorting this element
|
||||||
|
-- @param payload the payload attached to this element
|
||||||
|
-- @return nothing, or throws an error on bad input
|
||||||
|
function insertU(self, value, payload)
|
||||||
|
assert(self.reverse[payload] == nil, "duplicate payload")
|
||||||
|
local pos = #self.values + 1
|
||||||
|
self.reverse[payload] = pos
|
||||||
|
self.payloads[pos] = payload
|
||||||
|
return insert(self, value)
|
||||||
|
end
|
||||||
|
|
||||||
|
local removeU
|
||||||
|
--- Removes an element from the heap.
|
||||||
|
-- @function unique:remove
|
||||||
|
-- @param payload the payload to remove
|
||||||
|
-- @return value, payload or nil if not found
|
||||||
|
function removeU(self, payload)
|
||||||
|
local pos = self.reverse[payload]
|
||||||
|
if pos ~= nil then
|
||||||
|
return remove(self, pos), payload
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local popU
|
||||||
|
--- Removes the top of the heap and returns it.
|
||||||
|
-- When used with timers, `pop` will return the payload that is due.
|
||||||
|
--
|
||||||
|
-- Note: this function returns `payload` as the first result to prevent
|
||||||
|
-- extra locals when retrieving the `payload`.
|
||||||
|
-- @function unique:pop
|
||||||
|
-- @return payload, value, or `nil` if there is none
|
||||||
|
function popU(self)
|
||||||
|
if self.values[1] then
|
||||||
|
local payload = self.payloads[1]
|
||||||
|
local value = remove(self, 1)
|
||||||
|
return payload, value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local peekU
|
||||||
|
--- Returns the element at the top of the heap, without removing it.
|
||||||
|
-- @function unique:peek
|
||||||
|
-- @return payload, value, or `nil` if there is none
|
||||||
|
peekU = function(self)
|
||||||
|
return self.payloads[1], self.values[1]
|
||||||
|
end
|
||||||
|
|
||||||
|
local peekValueU
|
||||||
|
--- Returns the element at the top of the heap, without removing it.
|
||||||
|
-- @function unique:peekValue
|
||||||
|
-- @return value at the top, or `nil` if there is none
|
||||||
|
-- @usage -- simple timer based heap example
|
||||||
|
-- while true do
|
||||||
|
-- sleep(heap:peekValue() - gettime()) -- assume LuaSocket gettime function
|
||||||
|
-- coroutine.resume((heap:pop())) -- assumes payload to be a coroutine,
|
||||||
|
-- -- double parens to drop extra return value
|
||||||
|
-- end
|
||||||
|
peekValueU = function(self)
|
||||||
|
return self.values[1]
|
||||||
|
end
|
||||||
|
|
||||||
|
local valueByPayload
|
||||||
|
--- Returns the value associated with the payload
|
||||||
|
-- @function unique:valueByPayload
|
||||||
|
-- @param payload the payload to lookup
|
||||||
|
-- @return value or nil if no such payload exists
|
||||||
|
valueByPayload = function(self, payload)
|
||||||
|
return self.values[self.reverse[payload]]
|
||||||
|
end
|
||||||
|
|
||||||
|
local sizeU
|
||||||
|
--- Returns the number of elements in the heap.
|
||||||
|
-- @function heap:size
|
||||||
|
-- @return number of elements
|
||||||
|
sizeU = function(self)
|
||||||
|
return #self.values
|
||||||
|
end
|
||||||
|
|
||||||
|
local function swapU(heap, a, b)
|
||||||
|
local pla, plb = heap.payloads[a], heap.payloads[b]
|
||||||
|
heap.reverse[pla], heap.reverse[plb] = b, a
|
||||||
|
heap.payloads[a], heap.payloads[b] = plb, pla
|
||||||
|
swap(heap, a, b)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function eraseU(heap, pos)
|
||||||
|
local payload = heap.payloads[pos]
|
||||||
|
heap.reverse[payload] = nil
|
||||||
|
heap.payloads[pos] = nil
|
||||||
|
erase(heap, pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
--================================================================
|
||||||
|
-- unique heap creation
|
||||||
|
--================================================================
|
||||||
|
|
||||||
|
local function uniqueHeap(lt)
|
||||||
|
local h = M.binaryHeap(swapU, eraseU, lt)
|
||||||
|
h.payloads = {} -- list contains payloads
|
||||||
|
h.reverse = {} -- reverse of the payloads list
|
||||||
|
h.peek = peekU
|
||||||
|
h.peekValue = peekValueU
|
||||||
|
h.valueByPayload = valueByPayload
|
||||||
|
h.pop = popU
|
||||||
|
h.size = sizeU
|
||||||
|
h.remove = removeU
|
||||||
|
h.insert = insertU
|
||||||
|
h.update = updateU
|
||||||
|
return h
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Creates a new min-heap with unique payloads.
|
||||||
|
-- A min-heap is where the smallest value is at the top.
|
||||||
|
--
|
||||||
|
-- *NOTE*: All management functions in the 'unique binary heap'
|
||||||
|
-- take `payload` instead of `pos` as argument.
|
||||||
|
-- @param lt (optional) comparison function (less-than), see `binaryHeap`.
|
||||||
|
-- @return the new heap
|
||||||
|
M.minUnique = function(lt)
|
||||||
|
if not lt then
|
||||||
|
lt = function(a,b) return (a < b) end
|
||||||
|
end
|
||||||
|
return uniqueHeap(lt)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Creates a new max-heap with unique payloads.
|
||||||
|
-- A max-heap is where the largest value is at the top.
|
||||||
|
--
|
||||||
|
-- *NOTE*: All management functions in the 'unique binary heap'
|
||||||
|
-- take `payload` instead of `pos` as argument.
|
||||||
|
-- @param gt (optional) comparison function (greater-than), see `binaryHeap`.
|
||||||
|
-- @return the new heap
|
||||||
|
M.maxUnique = function(gt)
|
||||||
|
if not gt then
|
||||||
|
gt = function(a,b) return (a > b) end
|
||||||
|
end
|
||||||
|
return uniqueHeap(gt)
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
14
thirdparty/copas/.editorconfig
vendored
Normal file
14
thirdparty/copas/.editorconfig
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
charset = utf-8
|
||||||
|
|
||||||
|
[*.lua]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
6
thirdparty/copas/.gitignore
vendored
Normal file
6
thirdparty/copas/.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
.DS_Store
|
||||||
|
**/*.srl
|
||||||
|
**/*.pem
|
||||||
|
*.rock
|
||||||
|
luacov.report.out
|
||||||
|
luacov.stats.out
|
31
thirdparty/copas/.luacheckrc
vendored
Normal file
31
thirdparty/copas/.luacheckrc
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
--std = "ngx_lua+busted"
|
||||||
|
unused_args = false
|
||||||
|
redefined = false
|
||||||
|
max_line_length = false
|
||||||
|
|
||||||
|
|
||||||
|
globals = {
|
||||||
|
--"_KONG",
|
||||||
|
--"kong",
|
||||||
|
--"ngx.IS_CLI",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
not_globals = {
|
||||||
|
"string.len",
|
||||||
|
"table.getn",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ignore = {
|
||||||
|
--"6.", -- ignore whitespace warnings
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
exclude_files = {
|
||||||
|
".install/**",
|
||||||
|
".luarocks/**",
|
||||||
|
--"spec/fixtures/invalid-module.lua",
|
||||||
|
--"spec-old-api/fixtures/invalid-module.lua",
|
||||||
|
}
|
||||||
|
|
4
thirdparty/copas/.luacov
vendored
Normal file
4
thirdparty/copas/.luacov
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.*"] = "src"
|
||||||
|
}
|
21
thirdparty/copas/LICENSE
vendored
Normal file
21
thirdparty/copas/LICENSE
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
Copyright © 2005-2013 Kepler Project, 2015-2023 Thijs Schreijer.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use, copy,
|
||||||
|
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
75
thirdparty/copas/Makefile
vendored
Normal file
75
thirdparty/copas/Makefile
vendored
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
# $Id: Makefile,v 1.3 2007/10/29 22:50:16 carregal Exp $
|
||||||
|
|
||||||
|
DESTDIR ?=
|
||||||
|
|
||||||
|
# Default prefix
|
||||||
|
PREFIX ?= /usr/local
|
||||||
|
|
||||||
|
# System's lua directory (where Lua libraries are installed)
|
||||||
|
LUA_DIR ?= $(PREFIX)/share/lua/5.1
|
||||||
|
|
||||||
|
DELIM=-e "print(([[=]]):rep(70))"
|
||||||
|
PKGPATH=-e "package.path='src/?.lua;'..package.path"
|
||||||
|
|
||||||
|
# Lua interpreter
|
||||||
|
LUA=lua
|
||||||
|
|
||||||
|
.PHONY: certs
|
||||||
|
|
||||||
|
install:
|
||||||
|
mkdir -p $(DESTDIR)$(LUA_DIR)/copas
|
||||||
|
cp src/copas.lua $(DESTDIR)$(LUA_DIR)/copas.lua
|
||||||
|
cp src/copas/ftp.lua $(DESTDIR)$(LUA_DIR)/copas/ftp.lua
|
||||||
|
cp src/copas/smtp.lua $(DESTDIR)$(LUA_DIR)/copas/smtp.lua
|
||||||
|
cp src/copas/http.lua $(DESTDIR)$(LUA_DIR)/copas/http.lua
|
||||||
|
cp src/copas/timer.lua $(DESTDIR)$(LUA_DIR)/copas/timer.lua
|
||||||
|
cp src/copas/lock.lua $(DESTDIR)$(LUA_DIR)/copas/lock.lua
|
||||||
|
cp src/copas/semaphore.lua $(DESTDIR)$(LUA_DIR)/copas/semaphore.lua
|
||||||
|
cp src/copas/queue.lua $(DESTDIR)$(LUA_DIR)/copas/queue.lua
|
||||||
|
|
||||||
|
tests/certs/clientA.pem:
|
||||||
|
cd ./tests/certs && \
|
||||||
|
./rootA.sh && \
|
||||||
|
./rootB.sh && \
|
||||||
|
./serverA.sh && \
|
||||||
|
./serverB.sh && \
|
||||||
|
./clientA.sh && \
|
||||||
|
./clientB.sh && \
|
||||||
|
cd ../..
|
||||||
|
|
||||||
|
certs: tests/certs/clientA.pem
|
||||||
|
|
||||||
|
test: certs
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/close.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/connecttwice.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/errhandlers.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/exit.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/exittest.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/http-timeout.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/httpredirect.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/largetransfer.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/lock.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/loop_starter.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/pause.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/queue.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/removeserver.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/removethread.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/request.lua 'http://www.google.com'
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/request.lua 'https://www.google.nl' true
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/semaphore.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/starve.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/tcptimeout.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/timer.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/timeout_errors.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/tls-sni.lua
|
||||||
|
$(LUA) $(DELIM) $(PKGPATH) tests/udptimeout.lua
|
||||||
|
$(LUA) $(DELIM)
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
$(RM) luacov.stats.out
|
||||||
|
$(MAKE) test LUA="$(LUA) -lluacov"
|
||||||
|
luacov
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) luacov.stats.out luacov.report.out
|
||||||
|
$(RM) tests/certs/*.pem tests/certs/*.srl
|
16
thirdparty/copas/Makefile.win
vendored
Normal file
16
thirdparty/copas/Makefile.win
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# $Id: Makefile.win,v 1.5 2008/01/16 18:07:17 mascarenhas Exp $
|
||||||
|
|
||||||
|
LUA_DIR= c:\lua5.1\lua
|
||||||
|
|
||||||
|
build clean:
|
||||||
|
|
||||||
|
install:
|
||||||
|
mkdir "$(LUA_DIR)\copas"
|
||||||
|
copy src\copas.lua "$(LUA_DIR)\copas.lua"
|
||||||
|
copy src\copas\ftp.lua "$(LUA_DIR)\copas\ftp.lua"
|
||||||
|
copy src\copas\http.lua "$(LUA_DIR)\copas\http.lua"
|
||||||
|
copy src\copas\lock.lua "$(LUA_DIR)\copas\lock.lua"
|
||||||
|
copy src\copas\queue.lua "$(LUA_DIR)\copas\queue.lua"
|
||||||
|
copy src\copas\semaphore.lua "$(LUA_DIR)\copas\semaphore.lua"
|
||||||
|
copy src\copas\smtp.lua "$(LUA_DIR)\copas\smtp.lua"
|
||||||
|
copy src\copas\timer.lua "$(LUA_DIR)\copas\timer.lua"
|
36
thirdparty/copas/README.md
vendored
Normal file
36
thirdparty/copas/README.md
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
# Copas 4.7
|
||||||
|
|
||||||
|
[](https://github.com/lunarmodules/copas/actions)
|
||||||
|
[](https://coveralls.io/github/lunarmodules/copas)
|
||||||
|
[](https://github.com/lunarmodules/copas/actions)
|
||||||
|
[](CHANGELOG.md)
|
||||||
|
[](LICENSE)
|
||||||
|
|
||||||
|
Copas is a dispatcher based on coroutines that can be used for asynchronous networking. For example TCP or UDP based servers. But it also features timers and client support for http(s), ftp and smtp requests.
|
||||||
|
|
||||||
|
It uses [LuaSocket](https://github.com/diegonehab/luasocket) as the interface with the TCP/IP stack and [LuaSec](https://github.com/brunoos/luasec) for ssl support.
|
||||||
|
|
||||||
|
A server or thread registered with Copas should provide a handler for requests and use Copas socket functions to send the response. Copas loops through requests and invokes the corresponding handlers. For a full implementation of a Copas HTTP server you can refer to [Xavante](http://keplerproject.github.io/xavante/) as an example.
|
||||||
|
|
||||||
|
Copas is free software and uses the same license as Lua (MIT), and can be downloaded from [its GitHub page](https://github.com/lunarmodules/copas).
|
||||||
|
|
||||||
|
The easiest way to install Copas is through [LuaRocks](https://luarocks.org/):
|
||||||
|
|
||||||
|
```
|
||||||
|
luarocks install copas
|
||||||
|
```
|
||||||
|
|
||||||
|
For more details see [the documentation](http://lunarmodules.github.io/copas/).
|
||||||
|
|
||||||
|
### Releasing a new version
|
||||||
|
|
||||||
|
- update changelog in docs (`index.html`, update `history` and `status` sections)
|
||||||
|
- update version in `copas.lua`
|
||||||
|
- update version at the top of this README,
|
||||||
|
- update copyright years if needed
|
||||||
|
- update rockspec
|
||||||
|
- commit as `release X.Y.Z`
|
||||||
|
- tag as `vX_Y_Z` and as `X.Y.Z`
|
||||||
|
- push commit and tag
|
||||||
|
- upload to luarocks
|
||||||
|
- test luarocks installation
|
85
thirdparty/copas/bin/copas.lua
vendored
Executable file
85
thirdparty/copas/bin/copas.lua
vendored
Executable file
|
@ -0,0 +1,85 @@
|
||||||
|
#!/usr/bin/env lua
|
||||||
|
|
||||||
|
-- luacheck: globals copas
|
||||||
|
copas = require("copas")
|
||||||
|
|
||||||
|
|
||||||
|
-- Error handler that forces an application exit
|
||||||
|
local function errorhandler(err, co, skt)
|
||||||
|
io.stderr:write(copas.gettraceback(err, co, skt).."\n")
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function version_info()
|
||||||
|
print(copas._VERSION, copas._COPYRIGHT)
|
||||||
|
print(copas._DESCRIPTION)
|
||||||
|
print("Lua VM:", _G._VERSION)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function load_lib(lib_name)
|
||||||
|
require(lib_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function run_code(code)
|
||||||
|
if loadstring then -- deprecated in Lua 5.2
|
||||||
|
assert(loadstring(code, "command line"))()
|
||||||
|
else
|
||||||
|
assert(load(code, "command line"))()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function run_stdin()
|
||||||
|
assert(loadfile())()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function run_file(filename, i)
|
||||||
|
-- shift arguments, such that the Lua file being executed is at index 0. The
|
||||||
|
-- first argument following the name is at index 1.
|
||||||
|
local last = #arg
|
||||||
|
local first = #arg
|
||||||
|
for idx, v in pairs(arg) do
|
||||||
|
if idx < first then first = idx end
|
||||||
|
end
|
||||||
|
for n = first - i, last do
|
||||||
|
arg[n] = arg[n+i] -- luacheck: ignore
|
||||||
|
end
|
||||||
|
assert(loadfile(filename))()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function show_usage()
|
||||||
|
print([[
|
||||||
|
usage: copas [options]... [script [args]...].
|
||||||
|
Available options are:
|
||||||
|
-e chunk Execute string 'chunk'.
|
||||||
|
-l name Require library 'name'.
|
||||||
|
-v Show version information.
|
||||||
|
-- Stop handling options.
|
||||||
|
- Execute stdin and stop handling options.]])
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
copas(function()
|
||||||
|
copas.seterrorhandler(errorhandler)
|
||||||
|
local i = 0
|
||||||
|
while i < math.max(#arg, 1) do -- if no args, use 1 being 'nil'
|
||||||
|
i = i + 1
|
||||||
|
local handled = false
|
||||||
|
local opt = arg[i] or "-" -- set default action if no args
|
||||||
|
-- options to continue handling
|
||||||
|
if opt == "-v" then version_info() handled = true end
|
||||||
|
if opt == "-l" then i = i + 1 load_lib(arg[i]) handled = true end
|
||||||
|
if opt == "-e" then i = i + 1 run_code(arg[i]) handled = true end
|
||||||
|
-- options that terminate handling
|
||||||
|
if opt == "--" then return end
|
||||||
|
if opt == "-" then return run_stdin() end
|
||||||
|
if opt:sub(1,1) == "-" and not handled then return show_usage() end
|
||||||
|
if not handled then return run_file(opt, i) end
|
||||||
|
end
|
||||||
|
end)
|
56
thirdparty/copas/copas-cvs-6.rockspec
vendored
Normal file
56
thirdparty/copas/copas-cvs-6.rockspec
vendored
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
local package_name = "copas"
|
||||||
|
local package_version = "cvs"
|
||||||
|
local rockspec_revision = "6"
|
||||||
|
local github_account_name = "lunarmodules"
|
||||||
|
local github_repo_name = package_name
|
||||||
|
|
||||||
|
|
||||||
|
package = package_name
|
||||||
|
version = package_version.."-"..rockspec_revision
|
||||||
|
source = {
|
||||||
|
url = "git+https://github.com/"..github_account_name.."/"..github_repo_name..".git",
|
||||||
|
branch = (package_version == "cvs") and "master" or nil,
|
||||||
|
tag = (package_version ~= "cvs") and package_version or nil,
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "https://github.com/"..github_account_name.."/"..github_repo_name,
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.5",
|
||||||
|
"luasocket >= 2.1, <= 3.0rc1-2",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
"binaryheap >= 0.4",
|
||||||
|
"timerwheel ~> 1",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
install = {
|
||||||
|
bin = {
|
||||||
|
copas = "bin/copas.lua",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.timer"] = "src/copas/timer.lua",
|
||||||
|
["copas.lock"] = "src/copas/lock.lua",
|
||||||
|
["copas.semaphore"] = "src/copas/semaphore.lua",
|
||||||
|
["copas.queue"] = "src/copas/queue.lua",
|
||||||
|
},
|
||||||
|
copy_directories = {
|
||||||
|
"docs",
|
||||||
|
},
|
||||||
|
}
|
BIN
thirdparty/copas/docs/copas.png
(Stored with Git LFS)
vendored
Normal file
BIN
thirdparty/copas/docs/copas.png
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
209
thirdparty/copas/docs/doc.css
vendored
Normal file
209
thirdparty/copas/docs/doc.css
vendored
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
body {
|
||||||
|
color: #47555c;
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: "Open Sans", sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: #eff4ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:link { color: #008fee; }
|
||||||
|
a:visited { color: #008fee; }
|
||||||
|
a:hover { color: #22a7ff; }
|
||||||
|
|
||||||
|
h1 { font-size:26px; }
|
||||||
|
h2 { font-size:24px; }
|
||||||
|
h3 { font-size:18px; }
|
||||||
|
h4 { font-size:16px; }
|
||||||
|
|
||||||
|
hr {
|
||||||
|
height: 1px;
|
||||||
|
background: #c1cce4;
|
||||||
|
border: 0px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: "Open Sans Mono", "Andale Mono", monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
tt {
|
||||||
|
font-family: "Open Sans Mono", "Andale Mono", monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
body, td, th {
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea, pre, tt {
|
||||||
|
font-family: "Open Sans Mono", "Andale Mono", monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
border-width: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example {
|
||||||
|
background-color: #323744;
|
||||||
|
color: white;
|
||||||
|
font-size: 16px;
|
||||||
|
padding: 16px 24px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.header, div.footer {
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
}
|
||||||
|
|
||||||
|
#product {
|
||||||
|
background-color: white;
|
||||||
|
padding: 10px;
|
||||||
|
height: 130px;
|
||||||
|
border-bottom: solid #d3dbec 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#product big {
|
||||||
|
font-size: 42px;
|
||||||
|
}
|
||||||
|
#product strong {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
#product_logo {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#product_name {
|
||||||
|
padding-top: 15px;
|
||||||
|
padding-left: 30px;
|
||||||
|
font-size: 42px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
#product_description {
|
||||||
|
padding-left: 30px;
|
||||||
|
color: #757779;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
background: #eff4ff;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation {
|
||||||
|
width: 100%;
|
||||||
|
background-color: rgb(44,62,103);
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation h1 {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation ul li a {
|
||||||
|
color: rgb(136, 208, 255);
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation ul li li a {
|
||||||
|
color: rgb(136, 208, 255);
|
||||||
|
font-weight: normal;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation ul {
|
||||||
|
display: inline;
|
||||||
|
color: white;
|
||||||
|
padding: 0px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation li {
|
||||||
|
display: inline;
|
||||||
|
list-style-type: none;
|
||||||
|
padding-left: 5px;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation li {
|
||||||
|
padding: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation li li {
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation li:hover a {
|
||||||
|
color: rgb(166, 238, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
padding: 20px;
|
||||||
|
width: 800px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#about {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.reference {
|
||||||
|
background-color: white;
|
||||||
|
padding: 20px;
|
||||||
|
border: solid #d3dbec 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.reference dt {
|
||||||
|
padding: 5px;
|
||||||
|
padding-top: 25px;
|
||||||
|
color: #637bbc;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.reference dl dt {
|
||||||
|
padding-top: 5px;
|
||||||
|
color: #637383;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.reference dd {
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
body {
|
||||||
|
font: 10pt "Times New Roman", "TimeNR", Times, serif;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
font-weight:bold; color: #004080; text-decoration: underline;
|
||||||
|
}
|
||||||
|
#main {
|
||||||
|
background-color: #ffffff; border-left: 0px;
|
||||||
|
}
|
||||||
|
#container {
|
||||||
|
margin-left: 2%; margin-right: 2%; background-color: #ffffff;
|
||||||
|
}
|
||||||
|
#content {
|
||||||
|
margin-left: 0px; padding: 1em; border-left: 0px; border-right: 0px; background-color: #ffffff;
|
||||||
|
}
|
||||||
|
#navigation {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#product_logo {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#about img {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.example {
|
||||||
|
font-family: "Andale Mono", monospace;
|
||||||
|
font-size: 8pt;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
}
|
395
thirdparty/copas/docs/index.html
vendored
Normal file
395
thirdparty/copas/docs/index.html
vendored
Normal file
|
@ -0,0 +1,395 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Copas - Coroutine Oriented Portable Asynchronous Services for Lua</title>
|
||||||
|
<link rel="stylesheet" href="doc.css" type="text/css"/>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="container">
|
||||||
|
|
||||||
|
<div id="product">
|
||||||
|
<div id="product_logo"><a href="http://www.keplerproject.org">
|
||||||
|
<img alt="Copas logo" src="copas.png"/>
|
||||||
|
</a></div>
|
||||||
|
<div id="product_name"><big><strong>Copas</strong></big></div>
|
||||||
|
<div id="product_description">Coroutine Oriented Portable Asynchronous Services for Lua</div>
|
||||||
|
</div> <!-- id="product" -->
|
||||||
|
|
||||||
|
|
||||||
|
<div id="main">
|
||||||
|
|
||||||
|
<div id="navigation">
|
||||||
|
<h1>Copas</h1>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Home</strong>
|
||||||
|
<ul>
|
||||||
|
<li><a href="index.html#status">Status</a></li>
|
||||||
|
<li><a href="index.html#download">Download</a></li>
|
||||||
|
<li><a href="index.html#dependencies">Dependencies</a></li>
|
||||||
|
<li><a href="index.html#history">History</a></li>
|
||||||
|
<li><a href="index.html#credits">Credits</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="manual.html">Manual</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html">Reference</a></li>
|
||||||
|
<li><a href="http://github.com/lunarmodules/copas/">Project</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="http://github.com/lunarmodules/copas/issues">Bug Tracker</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="license.html">License</a></li>
|
||||||
|
</ul>
|
||||||
|
</div> <!-- id="navigation" -->
|
||||||
|
|
||||||
|
<div id="content">
|
||||||
|
|
||||||
|
<h2><a name="over"></a>Overview</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Copas is a dispatcher based on coroutines that can be used for asynchroneous
|
||||||
|
networking. For example TCP or UDP based servers. But it also features timers
|
||||||
|
and client support for http(s), ftp and smtp requests.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
It uses <a href="http://www.cs.princeton.edu/~diego/professional/luasocket/">LuaSocket</a>
|
||||||
|
as the interface with the TCP/IP stack and <a href="https://github.com/brunoos/luasec">LuaSec</a> for ssl
|
||||||
|
support.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A server or thread registered with Copas should provide a handler for requests and use
|
||||||
|
Copas socket functions to send the response.
|
||||||
|
Copas loops through requests and invokes the corresponding handlers.
|
||||||
|
For a full implementation of a Copas HTTP server you can refer to
|
||||||
|
<a href="http://keplerproject.github.io/xavante">Xavante</a> as an example.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Copas is free software and uses the same <a href="license.html">license</a>
|
||||||
|
as Lua 5.1 to 5.4</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="status"></a>Status</h2>
|
||||||
|
|
||||||
|
<p>Current version is 4.7.0 and was developed for Lua 5.1 to 5.4.</p>
|
||||||
|
|
||||||
|
<h2><a name="download"></a>Download</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Copas can be downloaded from its
|
||||||
|
<a href="http://github.com/lunarmodules/copas">Github</a> page, in
|
||||||
|
the "Downloads" tab.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>You can also install Copas using <a href="http://www.luarocks.org">LuaRocks</a>:</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
luarocks install copas
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="dependencies"></a>Dependencies</h2>
|
||||||
|
|
||||||
|
<p>Copas depends on
|
||||||
|
LuaSocket, <a href="http://keplerproject.github.io/coxpcall/">Coxpcall</a> (only when using Lua 5.1), and (optionally) LuaSec.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2><a name="history"></a>History</h2>
|
||||||
|
|
||||||
|
<dl class="history">
|
||||||
|
<dt><strong>Copas 4.7.x</strong> [unreleased]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Fix: <code>copas.removethread</code> would not remove a sleeping thread immediately (it would not execute, but
|
||||||
|
would prevent the Copas loop from exiting until the timer expired).</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 4.7.0</strong> [15/Jan/2023]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Fix: windows makefile didn't include all submodules.</li>
|
||||||
|
<li>Fix: creating a new timer with a bad delay setting would throw a bad error message.</li>
|
||||||
|
<li>Refactor: submodules are now part of copas (lazily loaded) and do not need to be required anymore</li>
|
||||||
|
<li>Feat: runtime script added to directly run copas based code</li>
|
||||||
|
<li>Fix: improved socket wrapper for lacking LuaSec methods (<code>setoption, getoption, getpeername, getsockname</code>)</li>
|
||||||
|
<li>Feat: added LuaSec methods to wrapper (<code>getalpn, getsniname</code>)</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 4.6.0</strong> [30/Dec/2022]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Added: for timeouts in copas, lock, semaphore, and queue, allow <code>math.huge</code>
|
||||||
|
to specify no timeout/wait forever. Using <code>math.huge</code> over long timeouts will
|
||||||
|
reduce pressure on the timer-wheel.</li>
|
||||||
|
<li>Refactor: increase ringsize (timer-wheel) from 1 minute to 1 day to reduce timer-wheel pressure.</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 4.5.0</strong> [18/Dec/2022]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Added: <code>copas.status</code> got an extra parameter to track more detailed stats.</li>
|
||||||
|
<li>Fix: queue workers would not properly handle falsy items in the queue. The worker would
|
||||||
|
exit instead of handle the item.</li>
|
||||||
|
<li>Fix: a non-reentrant lock should block instead of returning an error when entered again.</li>
|
||||||
|
<li>Fix: finishing a queue would not honour the timeout.</li>
|
||||||
|
<li>Refactor: more manual cleanup instead of relying on weak-tables.</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 4.4.0</strong> [23/Oct/2022]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Fix: an error in the timer callback would kill the timer.</li>
|
||||||
|
<li>Added: <code>copas.geterrorhandler</code> to retrieve the active errorhandler.</li>
|
||||||
|
<li>Added: option <code>errorhandler</code> for timer objects.</li>
|
||||||
|
<li>Added: <code>copas.pause</code> and <code>copas.pauseforever</code> to replace <code>copas.sleep</code>. The latter
|
||||||
|
method can accidentally sleep-forever if time arithmetic returns a negative result.</li>
|
||||||
|
<li>Added: <code>copas.status</code> which returns an object with number of tasks/timers/sockets.</li>
|
||||||
|
<li>Change: renamed <code>copas.setErrorHandler</code> to <code>copas.seterrorhandler</code>.</li>
|
||||||
|
<li>Change: renamed <code>copas.useSocketTimeoutErrors</code> to <code>copas.usesockettimeouterrors</code>.</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 4.3.2</strong> [03/Oct/2022]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Fix: error handler for timeouts. Underlying <a href="https://github.com/keplerproject/coxpcall/issues/18">
|
||||||
|
bug is in coxpcall</a>, and hence this only applies to PuC Lua 5.1.</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 4.3.1</strong> [21/Sep/2022]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Fix: with Lua 5.1 the timeouts would resume the wrapped (by coxpcall)
|
||||||
|
coroutines, instead of the original ones. Causing errors to bubble up one
|
||||||
|
level too many.
|
||||||
|
</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 4.3.0</strong> [19/Sep/2022]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Fix: when the loop is idle, do an occasional GC to clean out any lingering
|
||||||
|
non-closed sockets. This could prevent the loop from exiting.</li>
|
||||||
|
<li>Fix: in debug mode very large data is now truncated when displayed.</li>
|
||||||
|
<li>Fix: the receive methods could starve other threads on high-throughput.</li>
|
||||||
|
<li>Change: order of <code>copas.addnamedthread</code> args.</li>
|
||||||
|
<li>Fix: <code>copas.receivepartial</code> could return early with no data received
|
||||||
|
if the `prefix` parameter was specified.</li>
|
||||||
|
<li>Change: renamed <code>copas.receivePartial</code> to <code>copas.receivepartial</code>.</li>
|
||||||
|
<li>Added: <code>sock:receivepartial</code> to better process streaming TCP data.</li>
|
||||||
|
<li>fix: <code>copas.receivepartial</code> is now documented.</li>
|
||||||
|
<li>fix: <code>copas.http</code> was missing some error handling.</li>
|
||||||
|
<li>fix: Copas timeouts when receiving/sending would not return partial results,
|
||||||
|
or last bytes sent.</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 4.2.0</strong> [06/Sep/2022]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Change: pick up datagram size from newer LuaSocket versions.</li>
|
||||||
|
<li>Fix: non-recurring timer can now be armed again from its own handler.</li>
|
||||||
|
<li>Added: calling on the module table now invokes the <code>copas.loop</code> method.</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 4.1.0</strong> [25/Aug/2022]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Fix: handle errors thrown by the error handlers themselves.</li>
|
||||||
|
<li>Deps: Bump timerwheel to 1.0 (no changes, just a small fix)</li>
|
||||||
|
<li>Added: <code>copas.gettraceback</code>, previously internal to the default error handler,
|
||||||
|
now exposed to make it easier to write proper error handlers</li>
|
||||||
|
<li>Added: http-request now takes a timeout setting, previously it would always use the default value
|
||||||
|
of 30 seconds.</li>
|
||||||
|
<li>Added: the previously internal function for generating a TCP socket in the http-request module,
|
||||||
|
is now exported as <code>http.getcreatefunc()</code>. This allows to capture the socket used by the
|
||||||
|
request. When using streaming responses, for example with server-sent events, this can be used to modify
|
||||||
|
the timeouts, or for closing the stream.</li>
|
||||||
|
<li>Fix: empty queues were not destroyed properly and could prevent Copas from exiting</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 4.0.0</strong> [29/Jul/2022]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>[breaking] Change: removed the "limitset". Its functionality can easily be recreated with
|
||||||
|
the new "queue" class, which is a better abstraction.</li>
|
||||||
|
<li>[breaking] Change: threads added through <code>copas.addthread</code> or
|
||||||
|
<code>copas.addnamedthread</code> will now be "scheduled", instead of immediately started.</li>
|
||||||
|
<li>Fixed: yielding to the Copas scheduler from user-code now throws a proper error and
|
||||||
|
no longer breaks the loop. Breaking the loop could also happen if a thread returned with
|
||||||
|
at least 2 return values.</li>
|
||||||
|
<li>Fixed: wrongly auto-closing sockets. Upon exiting a coroutine, sockets would be automatically
|
||||||
|
closed. This should only be the case for accepted TCP connections on a TCP server socket. This caused issues
|
||||||
|
for sockets shared between threads.<br />
|
||||||
|
[breaking]: this changes behavior, auto-close is now determined when accepting the connection, and no longer when
|
||||||
|
terminating the handler thread. This will only affect users that dynamically change <code>copas.autoclose</code>
|
||||||
|
at runtime.</li>
|
||||||
|
<li>Fixed: http requests would not set SNI defaults. Setting fields <code>protocol</code>,
|
||||||
|
<code>options</code>, and <code>verify</code> directly on the http options table is now deprecated. Instead
|
||||||
|
specify <code>sslparams</code>, similar to other SSL/TLS functions.</li>
|
||||||
|
<li>Added: added <code>sempahore:destroy()</code></li>
|
||||||
|
<li>Added: <code>copas.settimeouts</code>, to set separate timeouts for connect, send, receive</li>
|
||||||
|
<li>Added: queue class, see module "copas.queue"</li>
|
||||||
|
<li>Added: names for sockets and coroutines:
|
||||||
|
<ul>
|
||||||
|
<li><code>copas.addserver()</code> has a 4th argument; name, to name the server socket</li>
|
||||||
|
<li><code>copas.addnamedthread()</code> is new and identical to <code>copas.addthread()</code>,
|
||||||
|
but also accepts a name</li>
|
||||||
|
<li><code>copas.setsocketname()</code>, <code>copas.getsocketname()</code>,
|
||||||
|
<code>copas.setthreadname()</code>, <code>copas.getthreadname()</code> added to manage names</li>
|
||||||
|
<li><code>copas.debug.start()</code> and <code>copas.debug.end()</code> to enable debug
|
||||||
|
logging for the scheduler itself.</li>
|
||||||
|
<li><code>copas.debug.socket()</code> to enable debug logging for socket methods (experimental).</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 3.0.0</strong> [12/Nov/2021]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>[breaking] Change: <code>copas.addserver()</code> now uses the timeout value as a copas timeout,
|
||||||
|
instead of a luasocket timeout. The client sockets for incoming connections will
|
||||||
|
inherit the timeout from the server socket.</li>
|
||||||
|
<li>Added: support for SNI on TLS connections #81 (@amyspark)</li>
|
||||||
|
<li>Added: <code>copas.settimeout()</code> so Copas can manage its own timeouts instead of spinning forever (Patrick Barrett )</li>
|
||||||
|
<li>Added: timer class, see module "copas.timer"</li>
|
||||||
|
<li>Added: lock class, see module "copas.lock"</li>
|
||||||
|
<li>Added: semaphore class, see module "copas.semaphore"</li>
|
||||||
|
<li>Added: timeout interface <code>copas.timeout()</code></li>
|
||||||
|
<li>Added: option to override the default errorhandler, and fixes to the handler</li>
|
||||||
|
<li>Added: <code>copas.removethread()</code> added to be able to forcefully remove a previously added thread</li>
|
||||||
|
<li>Added: <code>copas.loop()</code> now takes an optional initialization function</li>
|
||||||
|
<li>Fixed: closing sockets from another thread would make the read/write ops hang #104</li>
|
||||||
|
<li>Fixed: coxpcall dependency in limit.lua #63 (Francois Perrad)</li>
|
||||||
|
<li>Fixed: CI now generates the certificates for testing, on unix make can be used, on Windows generate them manually</li>
|
||||||
|
<li>Fixed: type in wrapped <code>udp:setpeername</code> was actually calling <code>udp:getpeername</code></li>
|
||||||
|
<li>Fixed: default error handler didn't print the stacktrace</li>
|
||||||
|
<li>Fixed: small memory leak when sleeping until woken</li>
|
||||||
|
<li>Fixed: do not wrap <code>udp:sendto()</code> method, since udp send doesn't block</li>
|
||||||
|
<li>Change: performance improvement in big limit-sets (Francisco Castro)</li>
|
||||||
|
<li>Change: update deprecated tls default to tls 1.2 in (copas.http)</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 2.0.2</strong> [2017]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Added: <code>copas.running</code> flag</li>
|
||||||
|
<li>Fixed: fix for http request #53 (Peter Melnichenko)</li>
|
||||||
|
<li>Added: extra parameter <code>keep_open</code> for the <code>removeserver()</code> method (Hisham Muhammad)</li>
|
||||||
|
<li>Change: tweaked makefile with a <code>DESTDIR</code> variable (Richard Leitner)</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 2.0.1</strong> [2016]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Added: support for Lua 5.3 (no code changes, just rockspec update)</li>
|
||||||
|
<li>Fixed: yield across c boundary error (by Peter Melnichenko)</li>
|
||||||
|
<li>Fixed: bug in wrappers for <code>setoption()</code> and <code>shutdown()</code> (reported by Rob Probin)</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 2.0.0</strong> [2015]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Added: <code>removeserver()</code> function to remove servers from the scheduler (by Paul Kulchenko)</li>
|
||||||
|
<li>Added: client requests for http(s), ftp, and smtp (like LuaSocket/LuaSec, but async)</li>
|
||||||
|
<li>Added: transparent async support (handshake, and send/receive) for ssl using LuaSec</li>
|
||||||
|
<li>Added: <code>handler()</code> as a convenience for full copas and ssl wrapping</li>
|
||||||
|
<li>[breaking] Change: the loop now exits when there is nothing more to do</li>
|
||||||
|
<li>[breaking] Change: dummy first argument to new tasks removed</li>
|
||||||
|
<li>Fixed: completed the socket wrappers, missing functions were added</li>
|
||||||
|
<li>Fixed: connect issue, <code>step()</code> errorring out instead of returning <code>nil + error</code></li>
|
||||||
|
<li>Fixed: UDP sockets being auto closed</li>
|
||||||
|
<li>Fixed: the <code>receivePartial</code> function for http request support (by Paul Kulchenko)</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 1.2.1</strong> [2013]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Fixed bad version constant</li>
|
||||||
|
<li>Fixed timer issue</li>
|
||||||
|
<li>updated documentation</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 1.2.0</strong> [2013]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Support for Lua 5.2</li>
|
||||||
|
<li>UDP support</li>
|
||||||
|
<li>suspending threads</li>
|
||||||
|
<li>other minor updates</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 1.1.6</strong> [18/Mar/2010]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Now checks to see if socket.http was required before copas
|
||||||
|
</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 1.1.5</strong> [07/Apr/2009]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Fixed bug reported by Sam Roberts on the
|
||||||
|
Kepler list
|
||||||
|
(found due to Xavante locking up on some POST requests)
|
||||||
|
</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 1.1.4</strong> [10/Dec/2008]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Fixed bug [#5372]
|
||||||
|
- copas.connect is semi-broken (found by Gary NG)</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 1.1.3</strong> [19/May/2008]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Using <code>copcall</code> instead of <code>pcall</code> in <code>socket.protect</code>
|
||||||
|
(feature request [#5274] by Gary NG)</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 1.1.2</strong> [15/May/2008]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>Fixed Bug [#4249]
|
||||||
|
- bugs in copas.receive (found by Gary NG)</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 1.1.1</strong> [13/Aug/2007]</dt>
|
||||||
|
<dd>
|
||||||
|
<ul>
|
||||||
|
<li>Compatible with Lua 5.1</li>
|
||||||
|
<li>Refactored by Thomas Harning Jr. (for more details check
|
||||||
|
Bug 766)</li>
|
||||||
|
<li>Patch by Gary NG concerning the handling of stopped sockets</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 1.1</strong> [20/Sep/2006]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li><a href="reference.html">copas.addthread()</a> added</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong><a href="http://www.keplerproject.org/copas/1.0">Copas 1.0</a></strong> [17/May/2005]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li><a href="reference.html">copas.step()</a> added</li>
|
||||||
|
</ul></dd>
|
||||||
|
|
||||||
|
<dt><strong>Copas 1.0 Beta</strong>[17/Feb/2005]</dt>
|
||||||
|
<dd><ul>
|
||||||
|
<li>First public version</li>
|
||||||
|
</ul></dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<h2><a name="credits"></a>Credits</h2>
|
||||||
|
|
||||||
|
<p>Copas was designed and implemented by André Carregal and
|
||||||
|
Javier Guerra as part of the
|
||||||
|
<a href="http://www.keplerproject.org">Kepler Project</a> which
|
||||||
|
holds its copyright. Copas development had significative contributions from Diego Nehab,
|
||||||
|
Mike Pall, David Burgess, Leonardo Godinho, Thomas Harning Jr. and Gary NG.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="contact"></a>Contact us</h2>
|
||||||
|
|
||||||
|
<p>For more information please
|
||||||
|
<a href="mailto:info-NO-SPAM-THANKS@keplerproject.org">contact us</a>.
|
||||||
|
Comments are welcome!</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
You can also reach other Kepler developers and users on the Kepler Project
|
||||||
|
<a href="https://groups.google.com/forum/#!forum/kepler-project">mailing list</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div> <!-- id="content" -->
|
||||||
|
|
||||||
|
</div> <!-- id="main" -->
|
||||||
|
|
||||||
|
<div id="about">
|
||||||
|
<p><a href="http://validator.w3.org/check?uri=referer">Valid XHTML 1.0!</a></p>
|
||||||
|
</div> <!-- id="about" -->
|
||||||
|
|
||||||
|
</div> <!-- id="container" -->
|
||||||
|
</body>
|
||||||
|
</html>
|
100
thirdparty/copas/docs/license.html
vendored
Normal file
100
thirdparty/copas/docs/license.html
vendored
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Copas License</title>
|
||||||
|
<link rel="stylesheet" href="doc.css" type="text/css"/>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="container">
|
||||||
|
|
||||||
|
<div id="product">
|
||||||
|
<div id="product_logo"><a href="http://www.keplerproject.org">
|
||||||
|
<img alt="Copas logo" src="copas.png"/>
|
||||||
|
</a></div>
|
||||||
|
<div id="product_name"><big><strong>Copas</strong></big></div>
|
||||||
|
<div id="product_description">Coroutine Oriented Portable Asynchronous Services for Lua</div>
|
||||||
|
</div> <!-- id="product" -->
|
||||||
|
|
||||||
|
|
||||||
|
<div id="main">
|
||||||
|
|
||||||
|
<div id="navigation">
|
||||||
|
<h1>Copas</h1>
|
||||||
|
<ul>
|
||||||
|
<li><a href="index.html">Home</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="index.html#status">Status</a></li>
|
||||||
|
<li><a href="index.html#download">Download</a></li>
|
||||||
|
<li><a href="index.html#dependencies">Dependencies</a></li>
|
||||||
|
<li><a href="index.html#history">History</a></li>
|
||||||
|
<li><a href="index.html#credits">Credits</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="manual.html">Manual</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html">Reference</a></li>
|
||||||
|
<li><a href="http://github.com/lunarmodules/copas/">Project</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="http://github.com/lunarmodules/copas/issues">Bug Tracker</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><strong>License</strong></li>
|
||||||
|
</ul>
|
||||||
|
</div> <!-- id="navigation" -->
|
||||||
|
|
||||||
|
<div id="content">
|
||||||
|
<h1>License</h1>
|
||||||
|
<p>
|
||||||
|
Copas is free software: it can be used for both academic and
|
||||||
|
commercial purposes at absolutely no cost.</p>
|
||||||
|
<p>
|
||||||
|
The spirit of the license is that you are free to use Copas for
|
||||||
|
any purpose at no cost without having to ask us. The only
|
||||||
|
requirement is that if you do use Copas, then you should give us
|
||||||
|
credit by including the appropriate copyright notice somewhere in
|
||||||
|
your product or its documentation.</p>
|
||||||
|
<p>
|
||||||
|
Copas was designed and implemented by André Carregal and
|
||||||
|
Javier Guerra. The implementation is not derived from
|
||||||
|
licensed software.</p>
|
||||||
|
<p>
|
||||||
|
<!-- ===================================================================== -->
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
<p>Copyright © 2005-2013 Kepler Project, 2015-2023 Thijs Schreijer.</p>
|
||||||
|
<p>
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use, copy,
|
||||||
|
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:</p>
|
||||||
|
<p>
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.</p>
|
||||||
|
<p>
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.</p>
|
||||||
|
</div> <!-- id="content" -->
|
||||||
|
|
||||||
|
</div> <!-- id="main" -->
|
||||||
|
|
||||||
|
<div id="about">
|
||||||
|
<p><a href="http://validator.w3.org/check?uri=referer">Valid XHTML 1.0!</a></p>
|
||||||
|
<p><small>$Id: license.html,v 1.17 2009/03/24 22:04:26 carregal Exp $</small></p>
|
||||||
|
</div> <!-- id="about" -->
|
||||||
|
|
||||||
|
</div> <!-- id="container" -->
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
527
thirdparty/copas/docs/manual.html
vendored
Normal file
527
thirdparty/copas/docs/manual.html
vendored
Normal file
|
@ -0,0 +1,527 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Copas - Coroutine Oriented Portable Asynchronous Services for Lua</title>
|
||||||
|
<link rel="stylesheet" href="doc.css" type="text/css"/>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="container">
|
||||||
|
|
||||||
|
<div id="product">
|
||||||
|
<div id="product_logo"><a href="http://www.keplerproject.org">
|
||||||
|
<img alt="Copas logo" src="copas.png"/>
|
||||||
|
</a></div>
|
||||||
|
<div id="product_name"><big><strong>Copas</strong></big></div>
|
||||||
|
<div id="product_description">Coroutine Oriented Portable Asynchronous Services for Lua</div>
|
||||||
|
</div> <!-- id="product" -->
|
||||||
|
|
||||||
|
|
||||||
|
<div id="main">
|
||||||
|
|
||||||
|
<div id="navigation">
|
||||||
|
<h1>Copas</h1>
|
||||||
|
<ul>
|
||||||
|
<li><a href="index.html">Home</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="index.html#status">Status</a></li>
|
||||||
|
<li><a href="index.html#download">Download</a></li>
|
||||||
|
<li><a href="index.html#dependencies">Dependencies</a></li>
|
||||||
|
<li><a href="index.html#history">History</a></li>
|
||||||
|
<li><a href="index.html#credits">Credits</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><strong>Manual</strong></li>
|
||||||
|
<li><a href="reference.html">Reference</a></li>
|
||||||
|
<li><a href="http://github.com/lunarmodules/copas/">Project</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="http://github.com/lunarmodules/copas/issues">Bug Tracker</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="license.html">License</a></li>
|
||||||
|
</ul>
|
||||||
|
</div> <!-- id="navigation" -->
|
||||||
|
|
||||||
|
<div id="content">
|
||||||
|
|
||||||
|
<h2><a name="install"></a>Installing</h2>
|
||||||
|
|
||||||
|
<p>You can install Copas using <a href="http://www.luarocks.org">LuaRocks</a>:</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
luarocks install copas
|
||||||
|
</pre>
|
||||||
|
<p>Note: LuaSec is not automatically installed as a dependency. If you want to use ssl with Copas,
|
||||||
|
you need to manually install LuaSec as well.</p>
|
||||||
|
|
||||||
|
<h2><a name="cli"></a>Runtime</h2>
|
||||||
|
|
||||||
|
Copas can either be used as a regular Lua library, or as a runtime. A command line script that
|
||||||
|
acts as a runtime engine is included.
|
||||||
|
|
||||||
|
When using the runtime, the library is available as a global (<code>copas</code>), and the
|
||||||
|
scheduler will automatically be started. For example:
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
#!/usr/bin/env copas
|
||||||
|
|
||||||
|
local count = 0
|
||||||
|
copas.timer.new {
|
||||||
|
delay = 1,
|
||||||
|
recurring = true,
|
||||||
|
callback = function(self)
|
||||||
|
count = count + 1
|
||||||
|
print('hello world ' .. count)
|
||||||
|
if count >= 5 then
|
||||||
|
self:cancel()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2><a name="introduction"></a>Introduction to Copas</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Copas is a dispatcher that can help a lot in the creation of servers based on
|
||||||
|
<a href="http://www.cs.princeton.edu/~diego/professional/luasocket/">LuaSocket</a>.
|
||||||
|
Here we present a quick introduction to Copas and how to implement a server with it.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Assuming you know how to implement the desired server protocol, the first thing you have
|
||||||
|
to do in order to create a Copas based server is create a server socket to receive the
|
||||||
|
client connections. To do this you have to bind a host and a port using LuaSocket:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
server = socket.bind(host, port)
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>Then you have to create a handler function that implements the server protocol.
|
||||||
|
The handler function will be called with a socket for each client connection
|
||||||
|
and you can use <code>copas.send()</code> and <code>copas.receive()</code> on that socket to
|
||||||
|
exchange data with the client.</p>
|
||||||
|
|
||||||
|
<p>For example, a simple echo handler would be:</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
function echoHandler(skt)
|
||||||
|
while true do
|
||||||
|
local data = copas.receive(skt)
|
||||||
|
if data == "quit" then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
copas.send(skt, data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>You may alternatively use <code>copas.wrap()</code> to let your code more close to a standard
|
||||||
|
LuaSocket use:</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
function echoHandler(skt)
|
||||||
|
skt = copas.wrap(skt)
|
||||||
|
while true do
|
||||||
|
local data = skt:receive()
|
||||||
|
if data == "quit" then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
skt:send(data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
To register the server socket with Copas and associate it with the corresponding
|
||||||
|
handler we do:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
copas.addserver(server, echoHandler)
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>Finally, to start Copas and all the registered servers we just call:</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
copas()
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>As long as every handler uses Copas's <code>send</code> and <code>receive</code>,
|
||||||
|
simultaneous connections will be handled transparently by Copas for every registered
|
||||||
|
server.</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Since Copas is coroutine based, using it within a Lua <code>pcall</code> or
|
||||||
|
<code>xpcall</code> context does not work with Lua 5.1 yielding. If you need to use
|
||||||
|
any of those functions in your handler we strongly suggest using
|
||||||
|
<a href="http://keplerproject.github.com/coxpcall/">coxpcall</a>, a coroutine safe
|
||||||
|
version of the Lua 5.1 protected calls. For an example of this usage please check Xavante.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2><a name="why"></a>Why use Copas?</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
For those who already have a server implemented, here is an explanation of why and
|
||||||
|
how to migrate to Copas. In a typical LuaSocket server usually there is a dispatcher
|
||||||
|
loop like the one below:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
server = socket.bind(host, port)
|
||||||
|
while true do
|
||||||
|
skt = server:accept()
|
||||||
|
handle(skt)
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>Here <code>handle</code> is a function that implements the server protocol using LuaSocket's
|
||||||
|
socket functions:</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
function handle(skt)
|
||||||
|
...
|
||||||
|
-- gets some data from the client - "the request"
|
||||||
|
reqdata = skt:receive(pattern)
|
||||||
|
...
|
||||||
|
-- sends some data to the client - "the response"
|
||||||
|
skt:send(respdata)
|
||||||
|
...
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The problem with that approach is that the dispatcher loop is doing a busy wait
|
||||||
|
and can handle just one connection at a time. To solve the busy waiting we can
|
||||||
|
use LuaSocket's <code>socket.select()</code>, like in:</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
server = socket.bind(host, port)
|
||||||
|
reading = {server}
|
||||||
|
while true do
|
||||||
|
input = socket.select(reading)
|
||||||
|
skt = input:accept()
|
||||||
|
handle(skt)
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
While this helps our CPU usage, the server is still accepting only one client
|
||||||
|
connection at a time. To handle more than one client the server must be able to
|
||||||
|
multitask, and the solution usually involves some kind of threads.</p>
|
||||||
|
<p>The dispatcher loop then becomes something like:</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
server = socket.bind(host, port)
|
||||||
|
reading = {server}
|
||||||
|
while true do
|
||||||
|
input = socket.select(reading)
|
||||||
|
skt = input:accept()
|
||||||
|
newthread(handle(skt))
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
where <code>newthread</code> is able to create a new thread that executes
|
||||||
|
independently the handler function.</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The use of threads in the new loop solves the multitasking problem but may
|
||||||
|
create another. Some platforms does not offer multithreading or maybe you
|
||||||
|
don't want to use threads at all.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If that is the case, using Lua's coroutines may help a lot, and that's
|
||||||
|
exactly what Copas does. Copas implements the dispatcher loop using coroutines
|
||||||
|
so the handlers can multitask without the use of threads.</p>
|
||||||
|
|
||||||
|
<h2><a name="using"></a>Using Copas with an existing server</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If you already have a running server using some dispatcher like the previous
|
||||||
|
example, migrating to Copas is quite simple, usually consisting of just three
|
||||||
|
steps.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
First each server socket and its corresponding handler function have to be registered
|
||||||
|
with Copas:</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
server = socket.bind(host, port)
|
||||||
|
copas.addserver(server, handle)
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>Secondly the server handler has to be adapted to use Copas. One solution
|
||||||
|
is to use Copas <code>send</code> and <code>receive</code> functions to receive
|
||||||
|
and send data to the client:</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
function handle(skt)
|
||||||
|
...
|
||||||
|
-- gets some data from the client - "the request"
|
||||||
|
reqdata = copas.receive(skt, pattern)
|
||||||
|
...
|
||||||
|
-- sends some data to the client - "the response"
|
||||||
|
copas.send(skt, respdata)
|
||||||
|
...
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>The other alternative is to wrap the socket in a Copas socket. This
|
||||||
|
allows your handler code to remain basically the same:</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
function handle(skt)
|
||||||
|
-- this line may suffice for your handler to work with Copas
|
||||||
|
skt = copas.wrap(skt) -- or... skip this line and wrap `handle` using copas.handler()
|
||||||
|
-- now skt behaves like a LuaSocket socket but uses Copas'
|
||||||
|
...
|
||||||
|
-- gets some data from the client - "the request"
|
||||||
|
reqdata = skt:receive(pattern)
|
||||||
|
...
|
||||||
|
-- sends some data to the client - "the response"
|
||||||
|
skt:send(respdata)
|
||||||
|
...
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>Note that by default Copas might return different timeout errors than the
|
||||||
|
traditional Lua libraries. Checkout <code>copas.useSocketTimeoutErrors()</code>
|
||||||
|
for more information.</p>
|
||||||
|
|
||||||
|
<p>Finally, to run the dispatcher loop you just call:</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
copas()
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>During the loop Copas' dispatcher accepts connections from clients and
|
||||||
|
automatically calls the corresponding handler functions.</p>
|
||||||
|
|
||||||
|
<h2><a name="udp"></a>Using UDP servers</h2>
|
||||||
|
<p>Copas may also be used for UDP servers. Here is an example;</p>
|
||||||
|
<pre class="example">
|
||||||
|
local port = 51034
|
||||||
|
local server = socket.udp()
|
||||||
|
server:setsockname("*",port)
|
||||||
|
|
||||||
|
function handler(skt)
|
||||||
|
skt = copas.wrap(skt)
|
||||||
|
print("UDP connection handler")
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local s, err
|
||||||
|
print("receiving...")
|
||||||
|
s, err = skt:receive(2048)
|
||||||
|
if not s then
|
||||||
|
print("Receive error: ", err)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
print("Received data, bytes:" , #s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
copas.addserver(server, handler, 1)
|
||||||
|
copas()
|
||||||
|
</pre>
|
||||||
|
<p>For UDP sockets the <code>receivefrom()</code> and <code>sendto()</code>
|
||||||
|
methods are available, both for copas and when the socket is wrapped. These
|
||||||
|
methods cannot be used on TCP sockets.</p>
|
||||||
|
<p><strong>IMPORTANT:</strong> UDP sockets do not have the notion of master and client sockets, so where a handler function can close the client socket for a TCP connection, a handler should never close a UDP socket, because the socket is the same as the server socket, hence closing it destroys the server.</p>
|
||||||
|
<p><strong>NOTE:</strong> When using the <code>copas.receive([size])</code> method
|
||||||
|
on a UDP socket, the <code>size</code> parameter is NOT optional as with regular
|
||||||
|
luasocket UDP sockets. This limitation is removed when the socket is wrapped
|
||||||
|
(it then defaults to 8192, the max UDP datagram size luasocket supports).</p>
|
||||||
|
|
||||||
|
<h2><a name="tasks"></a>Adding tasks</h2>
|
||||||
|
<p>Additional threads may be added to the scheduler, as long as they use the Copas <code>send</code>, <code>receive</code> or <code>sleep</code> methods. Below an example of a thread being added to create an outgoing TCP connection using Copas;</p>
|
||||||
|
<pre class="example">
|
||||||
|
local socket = require("socket")
|
||||||
|
local copas = require("copas")
|
||||||
|
|
||||||
|
local host = "127.0.0.1"
|
||||||
|
local port = 10000
|
||||||
|
|
||||||
|
local skt = socket.connect(host, port)
|
||||||
|
skt:settimeout(0) -- important: make it non-blocking
|
||||||
|
|
||||||
|
copas.addthread(function()
|
||||||
|
while true do
|
||||||
|
print("receiving...")
|
||||||
|
local resp = copas.receive(skt, 6)
|
||||||
|
print("received:", resp or "nil")
|
||||||
|
if resp and resp:sub(1,4) == "quit" then
|
||||||
|
skt:close()
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
copas()
|
||||||
|
</pre>
|
||||||
|
<p>The example connects, echoes whatever it receives and exits upon receiving 'quit'. For an
|
||||||
|
example passing arguments to a task, see the async http example below.</p>
|
||||||
|
|
||||||
|
<h2><a name="timers"></a>Creating timers</h2>
|
||||||
|
<p>Timers can be created using the <code>copas.timer</code> module.
|
||||||
|
Below an example of a timer;</p>
|
||||||
|
<pre class="example">
|
||||||
|
local copas = require("copas")
|
||||||
|
|
||||||
|
copas(function()
|
||||||
|
copas.timer.new({
|
||||||
|
delay = 1, -- delay in seconds
|
||||||
|
recurring = true, -- make the timer repeat
|
||||||
|
params = "hello world",
|
||||||
|
callback = function(timer_obj, params)
|
||||||
|
print(params) -- prints "hello world"
|
||||||
|
timer_obj:cancel() -- cancel the timer after 1 occurence
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
</pre>
|
||||||
|
<p>The example simply prints a message once every second, but gets cancelled right after the first one.</p>
|
||||||
|
|
||||||
|
<h2><a name="synchronization"></a>Synchronization primitives</h2>
|
||||||
|
<p>Since Copas allows to asynchroneously schedule tasks, synchronization might be required
|
||||||
|
to protect resources from concurrent access. In this case the <code>copas.lock</code> and
|
||||||
|
<code>copas.semaphore</code> classes
|
||||||
|
can be used. The lock/semaphore will ensure that the coroutine running will be yielded until
|
||||||
|
the protected resource becomes available, without blocking other threads.
|
||||||
|
</p>
|
||||||
|
<pre class="example">
|
||||||
|
local copas = require("copas")
|
||||||
|
|
||||||
|
local lock = copas.lock.new()
|
||||||
|
|
||||||
|
local function some_func()
|
||||||
|
local ok, err, wait = lock:get()
|
||||||
|
if not ok then
|
||||||
|
return nil, "we got error '" .. err .. "' after " .. wait .. " seconds"
|
||||||
|
end
|
||||||
|
|
||||||
|
print("doing something on my own")
|
||||||
|
copas.pause() -- allow to yield, while inside the lock
|
||||||
|
print("after " .. ok .. " seconds waiting")
|
||||||
|
|
||||||
|
lock:release()
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
<p>The <code>some_func</code> function may now be called and the 2 lines will
|
||||||
|
be printed together because of the lock.</p>
|
||||||
|
|
||||||
|
<h2><a name="ssl"></a>Ssl support</h2>
|
||||||
|
<p>LuaSec is transparently integrated in the Copas scheduler (though must be installed separately when using LuaRocks).</p>
|
||||||
|
<p>
|
||||||
|
Here's an example for an incoming connection in a server scenario;
|
||||||
|
</p>
|
||||||
|
<pre class="example">
|
||||||
|
function handler(skt)
|
||||||
|
skt = copas.wrap(skt):dohandshake(sslparams)
|
||||||
|
-- skt = copas.wrap(skt, sslparams):dohandshake() -- would be identical
|
||||||
|
|
||||||
|
while true do
|
||||||
|
-- perform the regular reading/writing ops on skt
|
||||||
|
end
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
A simpler handler would wrap the handler function to do the wrapping and
|
||||||
|
handshake before the handler gets called;
|
||||||
|
</p>
|
||||||
|
<pre class="example">
|
||||||
|
function handle(skt)
|
||||||
|
-- by now `skt` is copas wrapped, and has its handshake already completed
|
||||||
|
|
||||||
|
while true do
|
||||||
|
-- perform the regular reading/writing ops on skt
|
||||||
|
end
|
||||||
|
end
|
||||||
|
handle = copas.handler(handle, sslparams) -- wraps the handler to auto wrap and handshake
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Here's an example for an outgoing request;
|
||||||
|
</p>
|
||||||
|
<pre class="example">
|
||||||
|
copas.addthread(function()
|
||||||
|
local skt = copas.wrap(socket.tcp(), sslparams)
|
||||||
|
skt:connect(host, port) -- connecting will also perform the handshake on a wrapped socket
|
||||||
|
|
||||||
|
while true do
|
||||||
|
|
||||||
|
-- perform the regular reading/writing ops on skt
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2><a name="highlevel"></a>High level requests</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
For creating high level requests; http(s), ftp or smtp versions of the
|
||||||
|
methods are available that handle them async. As opposed to the original
|
||||||
|
LuaSocket and LuaSec implementations.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Below an example that schedules a number of http requests, then starts the Copas
|
||||||
|
loop to execute them. The loop exits when it's done.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
local copas = require("copas")
|
||||||
|
local asynchttp = require("copas.http").request
|
||||||
|
|
||||||
|
local list = {
|
||||||
|
"http://www.google.com",
|
||||||
|
"http://www.microsoft.com",
|
||||||
|
"http://www.apple.com",
|
||||||
|
"http://www.facebook.com",
|
||||||
|
"http://www.yahoo.com",
|
||||||
|
}
|
||||||
|
|
||||||
|
local handler = function(host)
|
||||||
|
res, err = asynchttp(host)
|
||||||
|
print("Host done: "..host)
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, host in ipairs(list) do copas.addthread(handler, host) end
|
||||||
|
copas()
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2><a name="control"></a>Controlling Copas</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If you do not want copas to simply enter an infinite loop (maybe you have to
|
||||||
|
respond to events from other sources, such as an user interface), you should
|
||||||
|
have your own loop and just call <code>copas.step()</code> at each iteration of
|
||||||
|
the loop:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre class="example">
|
||||||
|
while condition do
|
||||||
|
copas.step()
|
||||||
|
-- processing for other events from your system here
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
When using your own main loop, you should consider manually setting the
|
||||||
|
<code>copas.running</code> flag.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div> <!-- id="content" -->
|
||||||
|
|
||||||
|
</div> <!-- id="main" -->
|
||||||
|
|
||||||
|
<div id="about">
|
||||||
|
<p><a href="http://validator.w3.org/check?uri=referer">Valid XHTML 1.0!</a></p>
|
||||||
|
<p><small>$Id: manual.html,v 1.19 2009/03/24 22:04:26 carregal Exp $</small></p>
|
||||||
|
</div> <!-- id="about" -->
|
||||||
|
|
||||||
|
</div> <!-- id="container" -->
|
||||||
|
</body>
|
||||||
|
</html>
|
1003
thirdparty/copas/docs/reference.html
vendored
Normal file
1003
thirdparty/copas/docs/reference.html
vendored
Normal file
File diff suppressed because it is too large
Load diff
44
thirdparty/copas/misc/cosocket.lua
vendored
Normal file
44
thirdparty/copas/misc/cosocket.lua
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Copas - Coroutine Oriented Portable Asynchronous Services
|
||||||
|
--
|
||||||
|
-- Copas Wrapper for socket.http module
|
||||||
|
--
|
||||||
|
-- Written by Leonardo Godinho da Cunha
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
local copas = require("copas")
|
||||||
|
local socket = require("socket")
|
||||||
|
|
||||||
|
local cosocket = {}
|
||||||
|
|
||||||
|
-- Meta information is public even begining with an "_"
|
||||||
|
cosocket._COPYRIGHT = "Copyright (C) 2004-2006 Kepler Project"
|
||||||
|
cosocket._DESCRIPTION = "Coroutine Oriented Portable Asynchronous Services Wrapper for socket module"
|
||||||
|
cosocket._NAME = "Copas.cosocket"
|
||||||
|
cosocket._VERSION = "0.1"
|
||||||
|
|
||||||
|
function cosocket.tcp ()
|
||||||
|
local skt = socket.tcp()
|
||||||
|
local w_skt_mt = { __index = skt }
|
||||||
|
local ret_skt = setmetatable ({ socket = skt }, w_skt_mt)
|
||||||
|
ret_skt.settimeout = function (self,val)
|
||||||
|
return self.socket:settimeout (val)
|
||||||
|
end
|
||||||
|
ret_skt.connect = function (self,host, port)
|
||||||
|
local ret,err = copas.connect (self.socket,host, port)
|
||||||
|
local d = copas.wrap(self.socket)
|
||||||
|
|
||||||
|
self.send= function(client, data)
|
||||||
|
local ret,val=d.send(client, data)
|
||||||
|
return ret,val
|
||||||
|
end
|
||||||
|
self.receive=d.receive
|
||||||
|
self.close = function (w_socket)
|
||||||
|
ret=w_socket.socket:close()
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
return ret,err
|
||||||
|
end
|
||||||
|
return ret_skt
|
||||||
|
end
|
||||||
|
|
||||||
|
return cosocket
|
24
thirdparty/copas/misc/echoserver.lua
vendored
Normal file
24
thirdparty/copas/misc/echoserver.lua
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
-- Tests Copas with a simple Echo server
|
||||||
|
--
|
||||||
|
-- Run the test file and the connect to the server using telnet on the used port.
|
||||||
|
-- The server should be able to echo any input, to stop the test just send the command "quit"
|
||||||
|
|
||||||
|
local copas = require("copas")
|
||||||
|
local socket = require("socket")
|
||||||
|
|
||||||
|
local function echoHandler(skt)
|
||||||
|
skt = copas.wrap(skt)
|
||||||
|
while true do
|
||||||
|
local data = skt:receive()
|
||||||
|
if not data or data == "quit" then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
skt:send(data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local server = socket.bind("localhost", 20000)
|
||||||
|
|
||||||
|
copas.addserver(server, echoHandler)
|
||||||
|
|
||||||
|
copas.loop()
|
58
thirdparty/copas/misc/testasyncspeed.lua
vendored
Normal file
58
thirdparty/copas/misc/testasyncspeed.lua
vendored
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
local copas = require("copas")
|
||||||
|
local synchttp = require("socket.http").request
|
||||||
|
local asynchttp = copas.http.request
|
||||||
|
local gettime = require("socket").gettime
|
||||||
|
|
||||||
|
local targets = {
|
||||||
|
"http://www.google.com",
|
||||||
|
"http://www.microsoft.com",
|
||||||
|
"http://www.apple.com",
|
||||||
|
"http://www.facebook.com",
|
||||||
|
"http://www.yahoo.com",
|
||||||
|
}
|
||||||
|
|
||||||
|
local function sync(list)
|
||||||
|
for _, host in ipairs(list) do
|
||||||
|
local res = synchttp(host)
|
||||||
|
if not res then
|
||||||
|
print("Error sync: "..host.." failed, rerun test!")
|
||||||
|
else
|
||||||
|
print("Sync host done: "..host)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local handler = function(host)
|
||||||
|
local res = asynchttp(host)
|
||||||
|
if not res then
|
||||||
|
print("Error async: "..host.." failed, rerun test!")
|
||||||
|
else
|
||||||
|
print("Async host done: "..host)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function async(list)
|
||||||
|
for _, host in ipairs(list) do copas.addthread(handler, host) end
|
||||||
|
copas.loop()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- three times to remove caching differences
|
||||||
|
async(targets)
|
||||||
|
async(targets)
|
||||||
|
async(targets)
|
||||||
|
print("\nNow starting the real test...\n")
|
||||||
|
|
||||||
|
local t1 = gettime()
|
||||||
|
print("Sync:")
|
||||||
|
sync(targets)
|
||||||
|
local t2 = gettime()
|
||||||
|
print("Async:")
|
||||||
|
async(targets)
|
||||||
|
local t3 = gettime()
|
||||||
|
|
||||||
|
print("\nResults:")
|
||||||
|
print("========")
|
||||||
|
print(" Sync : ", t2-t1)
|
||||||
|
print(" Async: ", t3-t2)
|
||||||
|
|
||||||
|
|
30
thirdparty/copas/rockspec/copas-1.1.2-1.rockspec
vendored
Normal file
30
thirdparty/copas/rockspec/copas-1.1.2-1.rockspec
vendored
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package = "Copas"
|
||||||
|
version = "1.1.2-1"
|
||||||
|
source = {
|
||||||
|
url = "http://luaforge.net/frs/download.php/3367/copas-1.1.2.tar.gz",
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "http://www.keplerproject.org/copas/"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1",
|
||||||
|
"luasocket >= 2.0"
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "make",
|
||||||
|
build_pass = false,
|
||||||
|
install_variables = {
|
||||||
|
LUA_DIR = "$(LUADIR)"
|
||||||
|
}
|
||||||
|
}
|
31
thirdparty/copas/rockspec/copas-1.1.3-1.rockspec
vendored
Normal file
31
thirdparty/copas/rockspec/copas-1.1.3-1.rockspec
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package = "Copas"
|
||||||
|
version = "1.1.3-1"
|
||||||
|
source = {
|
||||||
|
url = "http://luaforge.net/frs/download.php/3409/copas-1.1.3.tar.gz",
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "http://www.keplerproject.org/copas/"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1",
|
||||||
|
"luasocket >= 2.0",
|
||||||
|
"coxpcall >= 1.13",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "make",
|
||||||
|
build_pass = false,
|
||||||
|
install_variables = {
|
||||||
|
LUA_DIR = "$(LUADIR)"
|
||||||
|
}
|
||||||
|
}
|
28
thirdparty/copas/rockspec/copas-1.1.4-1.rockspec
vendored
Normal file
28
thirdparty/copas/rockspec/copas-1.1.4-1.rockspec
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package = "Copas"
|
||||||
|
version = "1.1.4-1"
|
||||||
|
source = {
|
||||||
|
url = "http://luaforge.net/frs/download.php/3896/copas-1.1.4.tar.gz",
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "http://www.keplerproject.org/copas/"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1",
|
||||||
|
"luasocket >= 2.0",
|
||||||
|
"coxpcall >= 1.13",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "module",
|
||||||
|
modules = { copas = "src/copas/copas.lua" }
|
||||||
|
}
|
28
thirdparty/copas/rockspec/copas-1.1.5-1.rockspec
vendored
Normal file
28
thirdparty/copas/rockspec/copas-1.1.5-1.rockspec
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package = "Copas"
|
||||||
|
version = "1.1.5-1"
|
||||||
|
source = {
|
||||||
|
url = "http://luaforge.net/frs/download.php/4027/copas-1.1.5.tar.gz",
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "http://www.keplerproject.org/copas/"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1",
|
||||||
|
"luasocket >= 2.0",
|
||||||
|
"coxpcall >= 1.13",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "module",
|
||||||
|
modules = { copas = "src/copas/copas.lua" }
|
||||||
|
}
|
28
thirdparty/copas/rockspec/copas-1.1.6-1.rockspec
vendored
Normal file
28
thirdparty/copas/rockspec/copas-1.1.6-1.rockspec
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package = "Copas"
|
||||||
|
version = "1.1.6-1"
|
||||||
|
source = {
|
||||||
|
url = "http://github.com/downloads/keplerproject/copas/copas-1.1.6.tar.gz",
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "http://www.keplerproject.org/copas/"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1",
|
||||||
|
"luasocket >= 2.0",
|
||||||
|
"coxpcall >= 1.13",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = { copas = "src/copas/copas.lua" }
|
||||||
|
}
|
29
thirdparty/copas/rockspec/copas-1.2.0-1.rockspec
vendored
Normal file
29
thirdparty/copas/rockspec/copas-1.2.0-1.rockspec
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
package = "Copas"
|
||||||
|
version = "1.2.0-1"
|
||||||
|
source = {
|
||||||
|
url = "https://github.com/keplerproject/copas/archive/v1_2_0.tar.gz",
|
||||||
|
dir = "copas-1_2_0",
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "http://www.keplerproject.org/copas/"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.3",
|
||||||
|
"luasocket >= 2.1",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = { copas = "src/copas/copas.lua" }
|
||||||
|
}
|
29
thirdparty/copas/rockspec/copas-1.2.1-1.rockspec
vendored
Normal file
29
thirdparty/copas/rockspec/copas-1.2.1-1.rockspec
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
package = "Copas"
|
||||||
|
version = "1.2.1-1"
|
||||||
|
source = {
|
||||||
|
url = "https://github.com/keplerproject/copas/archive/v1_2_1.tar.gz",
|
||||||
|
dir = "copas-1_2_1",
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "http://www.keplerproject.org/copas/"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.3",
|
||||||
|
"luasocket >= 2.1",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = { copas = "src/copas/copas.lua" }
|
||||||
|
}
|
35
thirdparty/copas/rockspec/copas-2.0.0-1.rockspec
vendored
Normal file
35
thirdparty/copas/rockspec/copas-2.0.0-1.rockspec
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
package = "Copas"
|
||||||
|
version = "2.0.0-1"
|
||||||
|
source = {
|
||||||
|
url = "https://github.com/keplerproject/copas/archive/v2_0_0.tar.gz",
|
||||||
|
dir = "copas-2_0_0",
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "http://www.keplerproject.org/copas/"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.3",
|
||||||
|
"luasocket >= 2.1",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.limit"] = "src/copas/limit.lua",
|
||||||
|
}
|
||||||
|
}
|
35
thirdparty/copas/rockspec/copas-2.0.0-2.rockspec
vendored
Normal file
35
thirdparty/copas/rockspec/copas-2.0.0-2.rockspec
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
package = "Copas"
|
||||||
|
version = "2.0.0-2"
|
||||||
|
source = {
|
||||||
|
url = "https://github.com/keplerproject/copas/archive/v2_0_0.tar.gz",
|
||||||
|
dir = "copas-2_0_0",
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "http://www.keplerproject.org/copas/"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.4",
|
||||||
|
"luasocket >= 2.1",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.limit"] = "src/copas/limit.lua",
|
||||||
|
}
|
||||||
|
}
|
35
thirdparty/copas/rockspec/copas-2.0.1-1.rockspec
vendored
Normal file
35
thirdparty/copas/rockspec/copas-2.0.1-1.rockspec
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
package = "Copas"
|
||||||
|
version = "2.0.1-1"
|
||||||
|
source = {
|
||||||
|
url = "https://github.com/keplerproject/copas/archive/v2_0_1.tar.gz",
|
||||||
|
dir = "copas-2_0_1",
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "http://www.keplerproject.org/copas/"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.4",
|
||||||
|
"luasocket >= 2.1",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.limit"] = "src/copas/limit.lua",
|
||||||
|
}
|
||||||
|
}
|
35
thirdparty/copas/rockspec/copas-2.0.2-1.rockspec
vendored
Normal file
35
thirdparty/copas/rockspec/copas-2.0.2-1.rockspec
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
package = "Copas"
|
||||||
|
version = "2.0.2-1"
|
||||||
|
source = {
|
||||||
|
url = "https://github.com/keplerproject/copas/archive/v2_0_2.tar.gz",
|
||||||
|
dir = "copas-2_0_2",
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "http://www.keplerproject.org/copas/"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.4",
|
||||||
|
"luasocket >= 2.1",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.limit"] = "src/copas/limit.lua",
|
||||||
|
}
|
||||||
|
}
|
51
thirdparty/copas/rockspec/copas-3.0.0-1.rockspec
vendored
Normal file
51
thirdparty/copas/rockspec/copas-3.0.0-1.rockspec
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
local package_name = "copas"
|
||||||
|
local package_version = "3.0.0"
|
||||||
|
local rockspec_revision = "1"
|
||||||
|
local github_account_name = "keplerproject"
|
||||||
|
local github_repo_name = package_name
|
||||||
|
|
||||||
|
|
||||||
|
package = package_name
|
||||||
|
version = package_version.."-"..rockspec_revision
|
||||||
|
source = {
|
||||||
|
url = "git://github.com/"..github_account_name.."/"..github_repo_name..".git",
|
||||||
|
branch = (package_version == "cvs") and "master" or nil,
|
||||||
|
tag = (package_version ~= "cvs") and package_version or nil,
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "https://github.com/"..github_account_name.."/"..github_repo_name,
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.4",
|
||||||
|
"luasocket >= 2.1",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
"binaryheap >= 0.4",
|
||||||
|
"timerwheel >= 0.2",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.limit"] = "src/copas/limit.lua",
|
||||||
|
["copas.timer"] = "src/copas/timer.lua",
|
||||||
|
["copas.lock"] = "src/copas/lock.lua",
|
||||||
|
["copas.semaphore"] = "src/copas/semaphore.lua",
|
||||||
|
},
|
||||||
|
copy_directories = {
|
||||||
|
"docs",
|
||||||
|
},
|
||||||
|
}
|
51
thirdparty/copas/rockspec/copas-3.0.0-2.rockspec
vendored
Normal file
51
thirdparty/copas/rockspec/copas-3.0.0-2.rockspec
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
local package_name = "copas"
|
||||||
|
local package_version = "3.0.0"
|
||||||
|
local rockspec_revision = "2"
|
||||||
|
local github_account_name = "lunarmodules"
|
||||||
|
local github_repo_name = package_name
|
||||||
|
|
||||||
|
|
||||||
|
package = package_name
|
||||||
|
version = package_version.."-"..rockspec_revision
|
||||||
|
source = {
|
||||||
|
url = "git+https://github.com/"..github_account_name.."/"..github_repo_name..".git",
|
||||||
|
branch = (package_version == "cvs") and "master" or nil,
|
||||||
|
tag = (package_version ~= "cvs") and package_version or nil,
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "https://github.com/"..github_account_name.."/"..github_repo_name,
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.5",
|
||||||
|
"luasocket >= 2.1",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
"binaryheap >= 0.4",
|
||||||
|
"timerwheel >= 0.2",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.limit"] = "src/copas/limit.lua",
|
||||||
|
["copas.timer"] = "src/copas/timer.lua",
|
||||||
|
["copas.lock"] = "src/copas/lock.lua",
|
||||||
|
["copas.semaphore"] = "src/copas/semaphore.lua",
|
||||||
|
},
|
||||||
|
copy_directories = {
|
||||||
|
"docs",
|
||||||
|
},
|
||||||
|
}
|
51
thirdparty/copas/rockspec/copas-3.0.0-3.rockspec
vendored
Normal file
51
thirdparty/copas/rockspec/copas-3.0.0-3.rockspec
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
local package_name = "copas"
|
||||||
|
local package_version = "3.0.0"
|
||||||
|
local rockspec_revision = "3"
|
||||||
|
local github_account_name = "lunarmodules"
|
||||||
|
local github_repo_name = package_name
|
||||||
|
|
||||||
|
|
||||||
|
package = package_name
|
||||||
|
version = package_version.."-"..rockspec_revision
|
||||||
|
source = {
|
||||||
|
url = "git+https://github.com/"..github_account_name.."/"..github_repo_name..".git",
|
||||||
|
branch = (package_version == "cvs") and "master" or nil,
|
||||||
|
tag = (package_version ~= "cvs") and package_version or nil,
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "https://github.com/"..github_account_name.."/"..github_repo_name,
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.5",
|
||||||
|
"luasocket >= 2.1, <= 3.0rc1-2",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
"binaryheap >= 0.4",
|
||||||
|
"timerwheel >= 0.2",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.limit"] = "src/copas/limit.lua",
|
||||||
|
["copas.timer"] = "src/copas/timer.lua",
|
||||||
|
["copas.lock"] = "src/copas/lock.lua",
|
||||||
|
["copas.semaphore"] = "src/copas/semaphore.lua",
|
||||||
|
},
|
||||||
|
copy_directories = {
|
||||||
|
"docs",
|
||||||
|
},
|
||||||
|
}
|
51
thirdparty/copas/rockspec/copas-4.0.0-1.rockspec
vendored
Normal file
51
thirdparty/copas/rockspec/copas-4.0.0-1.rockspec
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
local package_name = "copas"
|
||||||
|
local package_version = "4.0.0"
|
||||||
|
local rockspec_revision = "1"
|
||||||
|
local github_account_name = "lunarmodules"
|
||||||
|
local github_repo_name = package_name
|
||||||
|
|
||||||
|
|
||||||
|
package = package_name
|
||||||
|
version = package_version.."-"..rockspec_revision
|
||||||
|
source = {
|
||||||
|
url = "git+https://github.com/"..github_account_name.."/"..github_repo_name..".git",
|
||||||
|
branch = (package_version == "cvs") and "master" or nil,
|
||||||
|
tag = (package_version ~= "cvs") and package_version or nil,
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "https://github.com/"..github_account_name.."/"..github_repo_name,
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.5",
|
||||||
|
"luasocket >= 2.1, <= 3.0rc1-2",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
"binaryheap >= 0.4",
|
||||||
|
"timerwheel >= 0.2",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.timer"] = "src/copas/timer.lua",
|
||||||
|
["copas.lock"] = "src/copas/lock.lua",
|
||||||
|
["copas.semaphore"] = "src/copas/semaphore.lua",
|
||||||
|
["copas.queue"] = "src/copas/queue.lua",
|
||||||
|
},
|
||||||
|
copy_directories = {
|
||||||
|
"docs",
|
||||||
|
},
|
||||||
|
}
|
51
thirdparty/copas/rockspec/copas-4.1.0-1.rockspec
vendored
Normal file
51
thirdparty/copas/rockspec/copas-4.1.0-1.rockspec
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
local package_name = "copas"
|
||||||
|
local package_version = "4.1.0"
|
||||||
|
local rockspec_revision = "1"
|
||||||
|
local github_account_name = "lunarmodules"
|
||||||
|
local github_repo_name = package_name
|
||||||
|
|
||||||
|
|
||||||
|
package = package_name
|
||||||
|
version = package_version.."-"..rockspec_revision
|
||||||
|
source = {
|
||||||
|
url = "git+https://github.com/"..github_account_name.."/"..github_repo_name..".git",
|
||||||
|
branch = (package_version == "cvs") and "master" or nil,
|
||||||
|
tag = (package_version ~= "cvs") and package_version or nil,
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "https://github.com/"..github_account_name.."/"..github_repo_name,
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.5",
|
||||||
|
"luasocket >= 2.1, <= 3.0rc1-2",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
"binaryheap >= 0.4",
|
||||||
|
"timerwheel ~> 1",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.timer"] = "src/copas/timer.lua",
|
||||||
|
["copas.lock"] = "src/copas/lock.lua",
|
||||||
|
["copas.semaphore"] = "src/copas/semaphore.lua",
|
||||||
|
["copas.queue"] = "src/copas/queue.lua",
|
||||||
|
},
|
||||||
|
copy_directories = {
|
||||||
|
"docs",
|
||||||
|
},
|
||||||
|
}
|
51
thirdparty/copas/rockspec/copas-4.2.0-1.rockspec
vendored
Normal file
51
thirdparty/copas/rockspec/copas-4.2.0-1.rockspec
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
local package_name = "copas"
|
||||||
|
local package_version = "4.2.0"
|
||||||
|
local rockspec_revision = "1"
|
||||||
|
local github_account_name = "lunarmodules"
|
||||||
|
local github_repo_name = package_name
|
||||||
|
|
||||||
|
|
||||||
|
package = package_name
|
||||||
|
version = package_version.."-"..rockspec_revision
|
||||||
|
source = {
|
||||||
|
url = "git+https://github.com/"..github_account_name.."/"..github_repo_name..".git",
|
||||||
|
branch = (package_version == "cvs") and "master" or nil,
|
||||||
|
tag = (package_version ~= "cvs") and package_version or nil,
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "https://github.com/"..github_account_name.."/"..github_repo_name,
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.5",
|
||||||
|
"luasocket >= 2.1, <= 3.0rc1-2",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
"binaryheap >= 0.4",
|
||||||
|
"timerwheel ~> 1",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.timer"] = "src/copas/timer.lua",
|
||||||
|
["copas.lock"] = "src/copas/lock.lua",
|
||||||
|
["copas.semaphore"] = "src/copas/semaphore.lua",
|
||||||
|
["copas.queue"] = "src/copas/queue.lua",
|
||||||
|
},
|
||||||
|
copy_directories = {
|
||||||
|
"docs",
|
||||||
|
},
|
||||||
|
}
|
51
thirdparty/copas/rockspec/copas-4.3.0-1.rockspec
vendored
Normal file
51
thirdparty/copas/rockspec/copas-4.3.0-1.rockspec
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
local package_name = "copas"
|
||||||
|
local package_version = "4.3.0"
|
||||||
|
local rockspec_revision = "1"
|
||||||
|
local github_account_name = "lunarmodules"
|
||||||
|
local github_repo_name = package_name
|
||||||
|
|
||||||
|
|
||||||
|
package = package_name
|
||||||
|
version = package_version.."-"..rockspec_revision
|
||||||
|
source = {
|
||||||
|
url = "git+https://github.com/"..github_account_name.."/"..github_repo_name..".git",
|
||||||
|
branch = (package_version == "cvs") and "master" or nil,
|
||||||
|
tag = (package_version ~= "cvs") and package_version or nil,
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "https://github.com/"..github_account_name.."/"..github_repo_name,
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.5",
|
||||||
|
"luasocket >= 2.1, <= 3.0rc1-2",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
"binaryheap >= 0.4",
|
||||||
|
"timerwheel ~> 1",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.timer"] = "src/copas/timer.lua",
|
||||||
|
["copas.lock"] = "src/copas/lock.lua",
|
||||||
|
["copas.semaphore"] = "src/copas/semaphore.lua",
|
||||||
|
["copas.queue"] = "src/copas/queue.lua",
|
||||||
|
},
|
||||||
|
copy_directories = {
|
||||||
|
"docs",
|
||||||
|
},
|
||||||
|
}
|
51
thirdparty/copas/rockspec/copas-4.3.1-1.rockspec
vendored
Normal file
51
thirdparty/copas/rockspec/copas-4.3.1-1.rockspec
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
local package_name = "copas"
|
||||||
|
local package_version = "4.3.1"
|
||||||
|
local rockspec_revision = "1"
|
||||||
|
local github_account_name = "lunarmodules"
|
||||||
|
local github_repo_name = package_name
|
||||||
|
|
||||||
|
|
||||||
|
package = package_name
|
||||||
|
version = package_version.."-"..rockspec_revision
|
||||||
|
source = {
|
||||||
|
url = "git+https://github.com/"..github_account_name.."/"..github_repo_name..".git",
|
||||||
|
branch = (package_version == "cvs") and "master" or nil,
|
||||||
|
tag = (package_version ~= "cvs") and package_version or nil,
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "https://github.com/"..github_account_name.."/"..github_repo_name,
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.5",
|
||||||
|
"luasocket >= 2.1, <= 3.0rc1-2",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
"binaryheap >= 0.4",
|
||||||
|
"timerwheel ~> 1",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.timer"] = "src/copas/timer.lua",
|
||||||
|
["copas.lock"] = "src/copas/lock.lua",
|
||||||
|
["copas.semaphore"] = "src/copas/semaphore.lua",
|
||||||
|
["copas.queue"] = "src/copas/queue.lua",
|
||||||
|
},
|
||||||
|
copy_directories = {
|
||||||
|
"docs",
|
||||||
|
},
|
||||||
|
}
|
51
thirdparty/copas/rockspec/copas-4.3.2-1.rockspec
vendored
Normal file
51
thirdparty/copas/rockspec/copas-4.3.2-1.rockspec
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
local package_name = "copas"
|
||||||
|
local package_version = "4.3.2"
|
||||||
|
local rockspec_revision = "1"
|
||||||
|
local github_account_name = "lunarmodules"
|
||||||
|
local github_repo_name = package_name
|
||||||
|
|
||||||
|
|
||||||
|
package = package_name
|
||||||
|
version = package_version.."-"..rockspec_revision
|
||||||
|
source = {
|
||||||
|
url = "git+https://github.com/"..github_account_name.."/"..github_repo_name..".git",
|
||||||
|
branch = (package_version == "cvs") and "master" or nil,
|
||||||
|
tag = (package_version ~= "cvs") and package_version or nil,
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "https://github.com/"..github_account_name.."/"..github_repo_name,
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.5",
|
||||||
|
"luasocket >= 2.1, <= 3.0rc1-2",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
"binaryheap >= 0.4",
|
||||||
|
"timerwheel ~> 1",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.timer"] = "src/copas/timer.lua",
|
||||||
|
["copas.lock"] = "src/copas/lock.lua",
|
||||||
|
["copas.semaphore"] = "src/copas/semaphore.lua",
|
||||||
|
["copas.queue"] = "src/copas/queue.lua",
|
||||||
|
},
|
||||||
|
copy_directories = {
|
||||||
|
"docs",
|
||||||
|
},
|
||||||
|
}
|
51
thirdparty/copas/rockspec/copas-4.4.0-1.rockspec
vendored
Normal file
51
thirdparty/copas/rockspec/copas-4.4.0-1.rockspec
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
local package_name = "copas"
|
||||||
|
local package_version = "4.4.0"
|
||||||
|
local rockspec_revision = "1"
|
||||||
|
local github_account_name = "lunarmodules"
|
||||||
|
local github_repo_name = package_name
|
||||||
|
|
||||||
|
|
||||||
|
package = package_name
|
||||||
|
version = package_version.."-"..rockspec_revision
|
||||||
|
source = {
|
||||||
|
url = "git+https://github.com/"..github_account_name.."/"..github_repo_name..".git",
|
||||||
|
branch = (package_version == "cvs") and "master" or nil,
|
||||||
|
tag = (package_version ~= "cvs") and package_version or nil,
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "https://github.com/"..github_account_name.."/"..github_repo_name,
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.5",
|
||||||
|
"luasocket >= 2.1, <= 3.0rc1-2",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
"binaryheap >= 0.4",
|
||||||
|
"timerwheel ~> 1",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.timer"] = "src/copas/timer.lua",
|
||||||
|
["copas.lock"] = "src/copas/lock.lua",
|
||||||
|
["copas.semaphore"] = "src/copas/semaphore.lua",
|
||||||
|
["copas.queue"] = "src/copas/queue.lua",
|
||||||
|
},
|
||||||
|
copy_directories = {
|
||||||
|
"docs",
|
||||||
|
},
|
||||||
|
}
|
51
thirdparty/copas/rockspec/copas-4.5.0-1.rockspec
vendored
Normal file
51
thirdparty/copas/rockspec/copas-4.5.0-1.rockspec
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
local package_name = "copas"
|
||||||
|
local package_version = "4.5.0"
|
||||||
|
local rockspec_revision = "1"
|
||||||
|
local github_account_name = "lunarmodules"
|
||||||
|
local github_repo_name = package_name
|
||||||
|
|
||||||
|
|
||||||
|
package = package_name
|
||||||
|
version = package_version.."-"..rockspec_revision
|
||||||
|
source = {
|
||||||
|
url = "git+https://github.com/"..github_account_name.."/"..github_repo_name..".git",
|
||||||
|
branch = (package_version == "cvs") and "master" or nil,
|
||||||
|
tag = (package_version ~= "cvs") and package_version or nil,
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "https://github.com/"..github_account_name.."/"..github_repo_name,
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.5",
|
||||||
|
"luasocket >= 2.1, <= 3.0rc1-2",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
"binaryheap >= 0.4",
|
||||||
|
"timerwheel ~> 1",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.timer"] = "src/copas/timer.lua",
|
||||||
|
["copas.lock"] = "src/copas/lock.lua",
|
||||||
|
["copas.semaphore"] = "src/copas/semaphore.lua",
|
||||||
|
["copas.queue"] = "src/copas/queue.lua",
|
||||||
|
},
|
||||||
|
copy_directories = {
|
||||||
|
"docs",
|
||||||
|
},
|
||||||
|
}
|
51
thirdparty/copas/rockspec/copas-4.6.0-1.rockspec
vendored
Normal file
51
thirdparty/copas/rockspec/copas-4.6.0-1.rockspec
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
local package_name = "copas"
|
||||||
|
local package_version = "4.6.0"
|
||||||
|
local rockspec_revision = "1"
|
||||||
|
local github_account_name = "lunarmodules"
|
||||||
|
local github_repo_name = package_name
|
||||||
|
|
||||||
|
|
||||||
|
package = package_name
|
||||||
|
version = package_version.."-"..rockspec_revision
|
||||||
|
source = {
|
||||||
|
url = "git+https://github.com/"..github_account_name.."/"..github_repo_name..".git",
|
||||||
|
branch = (package_version == "cvs") and "master" or nil,
|
||||||
|
tag = (package_version ~= "cvs") and package_version or nil,
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "https://github.com/"..github_account_name.."/"..github_repo_name,
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.5",
|
||||||
|
"luasocket >= 2.1, <= 3.0rc1-2",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
"binaryheap >= 0.4",
|
||||||
|
"timerwheel ~> 1",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.timer"] = "src/copas/timer.lua",
|
||||||
|
["copas.lock"] = "src/copas/lock.lua",
|
||||||
|
["copas.semaphore"] = "src/copas/semaphore.lua",
|
||||||
|
["copas.queue"] = "src/copas/queue.lua",
|
||||||
|
},
|
||||||
|
copy_directories = {
|
||||||
|
"docs",
|
||||||
|
},
|
||||||
|
}
|
56
thirdparty/copas/rockspec/copas-4.7.0-1.rockspec
vendored
Normal file
56
thirdparty/copas/rockspec/copas-4.7.0-1.rockspec
vendored
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
local package_name = "copas"
|
||||||
|
local package_version = "4.7.0"
|
||||||
|
local rockspec_revision = "1"
|
||||||
|
local github_account_name = "lunarmodules"
|
||||||
|
local github_repo_name = package_name
|
||||||
|
|
||||||
|
|
||||||
|
package = package_name
|
||||||
|
version = package_version.."-"..rockspec_revision
|
||||||
|
source = {
|
||||||
|
url = "git+https://github.com/"..github_account_name.."/"..github_repo_name..".git",
|
||||||
|
branch = (package_version == "cvs") and "master" or nil,
|
||||||
|
tag = (package_version ~= "cvs") and package_version or nil,
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Coroutine Oriented Portable Asynchronous Services",
|
||||||
|
detailed = [[
|
||||||
|
Copas is a dispatcher based on coroutines that can be used by
|
||||||
|
TCP/IP servers. It uses LuaSocket as the interface with the
|
||||||
|
TCP/IP stack. A server registered with Copas should provide a
|
||||||
|
handler for requests and use Copas socket functions to send
|
||||||
|
the response. Copas loops through requests and invokes the
|
||||||
|
corresponding handlers. For a full implementation of a Copas
|
||||||
|
HTTP server you can refer to Xavante as an example.
|
||||||
|
]],
|
||||||
|
license = "MIT/X11",
|
||||||
|
homepage = "https://github.com/"..github_account_name.."/"..github_repo_name,
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1, < 5.5",
|
||||||
|
"luasocket >= 2.1, <= 3.0rc1-2",
|
||||||
|
"coxpcall >= 1.14",
|
||||||
|
"binaryheap >= 0.4",
|
||||||
|
"timerwheel ~> 1",
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
install = {
|
||||||
|
bin = {
|
||||||
|
copas = "bin/copas.lua",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modules = {
|
||||||
|
["copas"] = "src/copas.lua",
|
||||||
|
["copas.http"] = "src/copas/http.lua",
|
||||||
|
["copas.ftp"] = "src/copas/ftp.lua",
|
||||||
|
["copas.smtp"] = "src/copas/smtp.lua",
|
||||||
|
["copas.timer"] = "src/copas/timer.lua",
|
||||||
|
["copas.lock"] = "src/copas/lock.lua",
|
||||||
|
["copas.semaphore"] = "src/copas/semaphore.lua",
|
||||||
|
["copas.queue"] = "src/copas/queue.lua",
|
||||||
|
},
|
||||||
|
copy_directories = {
|
||||||
|
"docs",
|
||||||
|
},
|
||||||
|
}
|
2008
thirdparty/copas/src/copas.lua
vendored
Normal file
2008
thirdparty/copas/src/copas.lua
vendored
Normal file
File diff suppressed because it is too large
Load diff
95
thirdparty/copas/src/copas/ftp.lua
vendored
Normal file
95
thirdparty/copas/src/copas/ftp.lua
vendored
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
-- identical to the socket.ftp module except that it uses
|
||||||
|
-- async wrapped Copas sockets
|
||||||
|
|
||||||
|
local copas = require("copas")
|
||||||
|
local socket = require("socket")
|
||||||
|
local ftp = require("socket.ftp")
|
||||||
|
local ltn12 = require("ltn12")
|
||||||
|
local url = require("socket.url")
|
||||||
|
|
||||||
|
|
||||||
|
local create = function() return copas.wrap(socket.tcp()) end
|
||||||
|
local forwards = { -- setting these will be forwarded to the original smtp module
|
||||||
|
PORT = true,
|
||||||
|
TIMEOUT = true,
|
||||||
|
PASSWORD = true,
|
||||||
|
USER = true
|
||||||
|
}
|
||||||
|
|
||||||
|
copas.ftp = setmetatable({}, {
|
||||||
|
-- use original module as metatable, to lookup constants like socket.TIMEOUT, etc.
|
||||||
|
__index = ftp,
|
||||||
|
-- Setting constants is forwarded to the luasocket.ftp module.
|
||||||
|
__newindex = function(self, key, value)
|
||||||
|
if forwards[key] then ftp[key] = value return end
|
||||||
|
return rawset(self, key, value)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
local _M = copas.ftp
|
||||||
|
|
||||||
|
---[[ copy of Luasocket stuff here untile PR #133 is accepted
|
||||||
|
-- a copy of the version in LuaSockets' ftp.lua
|
||||||
|
-- no 'create' can be passed in the string form, hence a local copy here
|
||||||
|
local default = {
|
||||||
|
path = "/",
|
||||||
|
scheme = "ftp"
|
||||||
|
}
|
||||||
|
|
||||||
|
-- a copy of the version in LuaSockets' ftp.lua
|
||||||
|
-- no 'create' can be passed in the string form, hence a local copy here
|
||||||
|
local function parse(u)
|
||||||
|
local t = socket.try(url.parse(u, default))
|
||||||
|
socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'")
|
||||||
|
socket.try(t.host, "missing hostname")
|
||||||
|
local pat = "^type=(.)$"
|
||||||
|
if t.params then
|
||||||
|
t.type = socket.skip(2, string.find(t.params, pat))
|
||||||
|
socket.try(t.type == "a" or t.type == "i",
|
||||||
|
"invalid type '" .. t.type .. "'")
|
||||||
|
end
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
|
-- parses a simple form into the advanced form
|
||||||
|
-- if `body` is provided, a PUT, otherwise a GET.
|
||||||
|
-- If GET, then a field `target` is added to store the results
|
||||||
|
_M.parseRequest = function(u, body)
|
||||||
|
local t = parse(u)
|
||||||
|
if body then
|
||||||
|
t.source = ltn12.source.string(body)
|
||||||
|
else
|
||||||
|
t.target = {}
|
||||||
|
t.sink = ltn12.sink.table(t.target)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--]]
|
||||||
|
|
||||||
|
_M.put = socket.protect(function(putt, body)
|
||||||
|
if type(putt) == "string" then
|
||||||
|
putt = _M.parseRequest(putt, body)
|
||||||
|
_M.put(putt)
|
||||||
|
return table.concat(putt.target)
|
||||||
|
else
|
||||||
|
putt.create = putt.create or create
|
||||||
|
return ftp.put(putt)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
_M.get = socket.protect(function(gett)
|
||||||
|
if type(gett) == "string" then
|
||||||
|
gett = _M.parseRequest(gett)
|
||||||
|
_M.get(gett)
|
||||||
|
return table.concat(gett.target)
|
||||||
|
else
|
||||||
|
gett.create = gett.create or create
|
||||||
|
return ftp.get(gett)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
_M.command = function(cmdt)
|
||||||
|
cmdt.create = cmdt.create or create
|
||||||
|
return ftp.command(cmdt)
|
||||||
|
end
|
||||||
|
|
||||||
|
return _M
|
459
thirdparty/copas/src/copas/http.lua
vendored
Normal file
459
thirdparty/copas/src/copas/http.lua
vendored
Normal file
|
@ -0,0 +1,459 @@
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Full copy of the LuaSocket code, modified to include
|
||||||
|
-- https and http/https redirects, and Copas async enabled.
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- HTTP/1.1 client support for the Lua language.
|
||||||
|
-- LuaSocket toolkit.
|
||||||
|
-- Author: Diego Nehab
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Declare module and import dependencies
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
local socket = require("socket")
|
||||||
|
local url = require("socket.url")
|
||||||
|
local ltn12 = require("ltn12")
|
||||||
|
local mime = require("mime")
|
||||||
|
local string = require("string")
|
||||||
|
local headers = require("socket.headers")
|
||||||
|
local base = _G
|
||||||
|
local table = require("table")
|
||||||
|
local copas = require("copas")
|
||||||
|
copas.http = {}
|
||||||
|
local _M = copas.http
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Program constants
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- connection timeout in seconds
|
||||||
|
_M.TIMEOUT = 60
|
||||||
|
-- default port for document retrieval
|
||||||
|
_M.PORT = 80
|
||||||
|
-- user agent field sent in request
|
||||||
|
_M.USERAGENT = socket._VERSION
|
||||||
|
|
||||||
|
-- Default settings for SSL
|
||||||
|
_M.SSLPORT = 443
|
||||||
|
_M.SSLPROTOCOL = "tlsv1_2"
|
||||||
|
_M.SSLOPTIONS = "all"
|
||||||
|
_M.SSLVERIFY = "none"
|
||||||
|
_M.SSLSNISTRICT = false
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Reads MIME headers from a connection, unfolding where needed
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local function receiveheaders(sock, headers)
|
||||||
|
local line, name, value, err
|
||||||
|
headers = headers or {}
|
||||||
|
-- get first line
|
||||||
|
line, err = sock:receive()
|
||||||
|
if err then return nil, err end
|
||||||
|
-- headers go until a blank line is found
|
||||||
|
while line ~= "" do
|
||||||
|
-- get field-name and value
|
||||||
|
name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)"))
|
||||||
|
if not (name and value) then return nil, "malformed reponse headers" end
|
||||||
|
name = string.lower(name)
|
||||||
|
-- get next line (value might be folded)
|
||||||
|
line, err = sock:receive()
|
||||||
|
if err then return nil, err end
|
||||||
|
-- unfold any folded values
|
||||||
|
while string.find(line, "^%s") do
|
||||||
|
value = value .. line
|
||||||
|
line, err = sock:receive()
|
||||||
|
if err then return nil, err end
|
||||||
|
end
|
||||||
|
-- save pair in table
|
||||||
|
if headers[name] then headers[name] = headers[name] .. ", " .. value
|
||||||
|
else headers[name] = value end
|
||||||
|
end
|
||||||
|
return headers
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Extra sources and sinks
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
socket.sourcet["http-chunked"] = function(sock, headers)
|
||||||
|
return base.setmetatable({
|
||||||
|
getfd = function() return sock:getfd() end,
|
||||||
|
dirty = function() return sock:dirty() end
|
||||||
|
}, {
|
||||||
|
__call = function()
|
||||||
|
-- get chunk size, skip extention
|
||||||
|
local line, err = sock:receive()
|
||||||
|
if err then return nil, err end
|
||||||
|
local size = base.tonumber(string.gsub(line, ";.*", ""), 16)
|
||||||
|
if not size then return nil, "invalid chunk size" end
|
||||||
|
-- was it the last chunk?
|
||||||
|
if size > 0 then
|
||||||
|
-- if not, get chunk and skip terminating CRLF
|
||||||
|
local chunk, err = sock:receive(size)
|
||||||
|
if chunk then sock:receive() end
|
||||||
|
return chunk, err
|
||||||
|
else
|
||||||
|
-- if it was, read trailers into headers table
|
||||||
|
headers, err = receiveheaders(sock, headers)
|
||||||
|
if not headers then return nil, err end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
socket.sinkt["http-chunked"] = function(sock)
|
||||||
|
return base.setmetatable({
|
||||||
|
getfd = function() return sock:getfd() end,
|
||||||
|
dirty = function() return sock:dirty() end
|
||||||
|
}, {
|
||||||
|
__call = function(self, chunk, err)
|
||||||
|
if not chunk then return sock:send("0\r\n\r\n") end
|
||||||
|
local size = string.format("%X\r\n", string.len(chunk))
|
||||||
|
return sock:send(size .. chunk .. "\r\n")
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Low level HTTP API
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local metat = { __index = {} }
|
||||||
|
|
||||||
|
function _M.open(reqt)
|
||||||
|
-- create socket with user connect function
|
||||||
|
local c = socket.try(reqt:create()) -- method call, passing reqt table as self!
|
||||||
|
local h = base.setmetatable({ c = c }, metat)
|
||||||
|
-- create finalized try
|
||||||
|
h.try = socket.newtry(function() h:close() end)
|
||||||
|
-- set timeout before connecting
|
||||||
|
local to = reqt.timeout or _M.TIMEOUT
|
||||||
|
if type(to) == "table" then
|
||||||
|
h.try(c:settimeouts(
|
||||||
|
to.connect or _M.TIMEOUT,
|
||||||
|
to.send or _M.TIMEOUT,
|
||||||
|
to.receive or _M.TIMEOUT))
|
||||||
|
else
|
||||||
|
h.try(c:settimeout(to))
|
||||||
|
end
|
||||||
|
h.try(c:connect(reqt.host, reqt.port or _M.PORT))
|
||||||
|
-- here everything worked
|
||||||
|
return h
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:sendrequestline(method, uri)
|
||||||
|
local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri)
|
||||||
|
return self.try(self.c:send(reqline))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:sendheaders(tosend)
|
||||||
|
local canonic = headers.canonic
|
||||||
|
local h = "\r\n"
|
||||||
|
for f, v in base.pairs(tosend) do
|
||||||
|
h = (canonic[f] or f) .. ": " .. v .. "\r\n" .. h
|
||||||
|
end
|
||||||
|
self.try(self.c:send(h))
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:sendbody(headers, source, step)
|
||||||
|
source = source or ltn12.source.empty()
|
||||||
|
step = step or ltn12.pump.step
|
||||||
|
-- if we don't know the size in advance, send chunked and hope for the best
|
||||||
|
local mode = "http-chunked"
|
||||||
|
if headers["content-length"] then mode = "keep-open" end
|
||||||
|
return self.try(ltn12.pump.all(source, socket.sink(mode, self.c), step))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:receivestatusline()
|
||||||
|
local status = self.try(self.c:receive(5))
|
||||||
|
-- identify HTTP/0.9 responses, which do not contain a status line
|
||||||
|
-- this is just a heuristic, but is what the RFC recommends
|
||||||
|
if status ~= "HTTP/" then return nil, status end
|
||||||
|
-- otherwise proceed reading a status line
|
||||||
|
status = self.try(self.c:receive("*l", status))
|
||||||
|
local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)"))
|
||||||
|
return self.try(base.tonumber(code), status)
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:receiveheaders()
|
||||||
|
return self.try(receiveheaders(self.c))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:receivebody(headers, sink, step)
|
||||||
|
sink = sink or ltn12.sink.null()
|
||||||
|
step = step or ltn12.pump.step
|
||||||
|
local length = base.tonumber(headers["content-length"])
|
||||||
|
local t = headers["transfer-encoding"] -- shortcut
|
||||||
|
local mode = "default" -- connection close
|
||||||
|
if t and t ~= "identity" then mode = "http-chunked"
|
||||||
|
elseif base.tonumber(headers["content-length"]) then mode = "by-length" end
|
||||||
|
return self.try(ltn12.pump.all(socket.source(mode, self.c, length),
|
||||||
|
sink, step))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:receive09body(status, sink, step)
|
||||||
|
local source = ltn12.source.rewind(socket.source("until-closed", self.c))
|
||||||
|
source(status)
|
||||||
|
return self.try(ltn12.pump.all(source, sink, step))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:close()
|
||||||
|
return self.c:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- High level HTTP API
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local function adjusturi(reqt)
|
||||||
|
local u = reqt
|
||||||
|
-- if there is a proxy, we need the full url. otherwise, just a part.
|
||||||
|
if not reqt.proxy and not _M.PROXY then
|
||||||
|
u = {
|
||||||
|
path = socket.try(reqt.path, "invalid path 'nil'"),
|
||||||
|
params = reqt.params,
|
||||||
|
query = reqt.query,
|
||||||
|
fragment = reqt.fragment
|
||||||
|
}
|
||||||
|
end
|
||||||
|
return url.build(u)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function adjustproxy(reqt)
|
||||||
|
local proxy = reqt.proxy or _M.PROXY
|
||||||
|
if proxy then
|
||||||
|
proxy = url.parse(proxy)
|
||||||
|
return proxy.host, proxy.port or 3128
|
||||||
|
else
|
||||||
|
return reqt.host, reqt.port
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function adjustheaders(reqt)
|
||||||
|
-- default headers
|
||||||
|
local host = string.gsub(reqt.authority, "^.-@", "")
|
||||||
|
local lower = {
|
||||||
|
["user-agent"] = _M.USERAGENT,
|
||||||
|
["host"] = host,
|
||||||
|
["connection"] = "close, TE",
|
||||||
|
["te"] = "trailers"
|
||||||
|
}
|
||||||
|
-- if we have authentication information, pass it along
|
||||||
|
if reqt.user and reqt.password then
|
||||||
|
lower["authorization"] =
|
||||||
|
"Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password))
|
||||||
|
end
|
||||||
|
-- override with user headers
|
||||||
|
for i,v in base.pairs(reqt.headers or lower) do
|
||||||
|
lower[string.lower(i)] = v
|
||||||
|
end
|
||||||
|
return lower
|
||||||
|
end
|
||||||
|
|
||||||
|
-- default url parts
|
||||||
|
local default = {
|
||||||
|
host = "",
|
||||||
|
port = _M.PORT,
|
||||||
|
path ="/",
|
||||||
|
scheme = "http"
|
||||||
|
}
|
||||||
|
|
||||||
|
local function adjustrequest(reqt)
|
||||||
|
-- parse url if provided
|
||||||
|
local nreqt = reqt.url and url.parse(reqt.url, default) or {}
|
||||||
|
-- explicit components override url
|
||||||
|
for i,v in base.pairs(reqt) do nreqt[i] = v end
|
||||||
|
if nreqt.port == "" then nreqt.port = 80 end
|
||||||
|
socket.try(nreqt.host and nreqt.host ~= "",
|
||||||
|
"invalid host '" .. base.tostring(nreqt.host) .. "'")
|
||||||
|
-- compute uri if user hasn't overriden
|
||||||
|
nreqt.uri = reqt.uri or adjusturi(nreqt)
|
||||||
|
-- ajust host and port if there is a proxy
|
||||||
|
nreqt.host, nreqt.port = adjustproxy(nreqt)
|
||||||
|
-- adjust headers in request
|
||||||
|
nreqt.headers = adjustheaders(nreqt)
|
||||||
|
return nreqt
|
||||||
|
end
|
||||||
|
|
||||||
|
local function shouldredirect(reqt, code, headers)
|
||||||
|
return headers.location and
|
||||||
|
string.gsub(headers.location, "%s", "") ~= "" and
|
||||||
|
(reqt.redirect ~= false) and
|
||||||
|
(code == 301 or code == 302 or code == 303 or code == 307) and
|
||||||
|
(not reqt.method or reqt.method == "GET" or reqt.method == "HEAD")
|
||||||
|
and (not reqt.nredirects or reqt.nredirects < 5)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function shouldreceivebody(reqt, code)
|
||||||
|
if reqt.method == "HEAD" then return nil end
|
||||||
|
if code == 204 or code == 304 then return nil end
|
||||||
|
if code >= 100 and code < 200 then return nil end
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- forward declarations
|
||||||
|
local trequest, tredirect
|
||||||
|
|
||||||
|
--[[local]] function tredirect(reqt, location)
|
||||||
|
local result, code, headers, status = trequest {
|
||||||
|
-- the RFC says the redirect URL has to be absolute, but some
|
||||||
|
-- servers do not respect that
|
||||||
|
url = url.absolute(reqt.url, location),
|
||||||
|
source = reqt.source,
|
||||||
|
sink = reqt.sink,
|
||||||
|
headers = reqt.headers,
|
||||||
|
proxy = reqt.proxy,
|
||||||
|
nredirects = (reqt.nredirects or 0) + 1,
|
||||||
|
create = reqt.create,
|
||||||
|
timeout = reqt.timeout,
|
||||||
|
}
|
||||||
|
-- pass location header back as a hint we redirected
|
||||||
|
headers = headers or {}
|
||||||
|
headers.location = headers.location or location
|
||||||
|
return result, code, headers, status
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[local]] function trequest(reqt)
|
||||||
|
-- we loop until we get what we want, or
|
||||||
|
-- until we are sure there is no way to get it
|
||||||
|
local nreqt = adjustrequest(reqt)
|
||||||
|
local h = _M.open(nreqt)
|
||||||
|
-- send request line and headers
|
||||||
|
h:sendrequestline(nreqt.method, nreqt.uri)
|
||||||
|
h:sendheaders(nreqt.headers)
|
||||||
|
-- if there is a body, send it
|
||||||
|
if nreqt.source then
|
||||||
|
h:sendbody(nreqt.headers, nreqt.source, nreqt.step)
|
||||||
|
end
|
||||||
|
local code, status = h:receivestatusline()
|
||||||
|
-- if it is an HTTP/0.9 server, simply get the body and we are done
|
||||||
|
if not code then
|
||||||
|
h:receive09body(status, nreqt.sink, nreqt.step)
|
||||||
|
return 1, 200
|
||||||
|
end
|
||||||
|
local headers
|
||||||
|
-- ignore any 100-continue messages
|
||||||
|
while code == 100 do
|
||||||
|
h:receiveheaders()
|
||||||
|
code, status = h:receivestatusline()
|
||||||
|
end
|
||||||
|
headers = h:receiveheaders()
|
||||||
|
-- at this point we should have a honest reply from the server
|
||||||
|
-- we can't redirect if we already used the source, so we report the error
|
||||||
|
if shouldredirect(nreqt, code, headers) and not nreqt.source then
|
||||||
|
h:close()
|
||||||
|
return tredirect(reqt, headers.location)
|
||||||
|
end
|
||||||
|
-- here we are finally done
|
||||||
|
if shouldreceivebody(nreqt, code) then
|
||||||
|
h:receivebody(headers, nreqt.sink, nreqt.step)
|
||||||
|
end
|
||||||
|
h:close()
|
||||||
|
return 1, code, headers, status
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return a function which creates a tcp socket that will
|
||||||
|
-- include the optional SSL/TLS connection, and unsafe redirect checks
|
||||||
|
function _M.getcreatefunc(params)
|
||||||
|
params = params or {}
|
||||||
|
local ssl_params = params.sslparams or {}
|
||||||
|
ssl_params.wrap = ssl_params.wrap or {
|
||||||
|
-- backward compatibility
|
||||||
|
protocol = params.protocol,
|
||||||
|
options = params.options,
|
||||||
|
verify = params.verify,
|
||||||
|
}
|
||||||
|
ssl_params.sni = ssl_params.sni or {
|
||||||
|
strict = _M.SSLSNISTRICT
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Default settings
|
||||||
|
ssl_params.wrap.protocol = ssl_params.wrap.protocol or _M.SSLPROTOCOL
|
||||||
|
ssl_params.wrap.options = ssl_params.wrap.options or _M.SSLOPTIONS
|
||||||
|
if ssl_params.wrap.verify == nil then
|
||||||
|
ssl_params.wrap.verify = _M.SSLVERIFY
|
||||||
|
end
|
||||||
|
ssl_params.wrap.mode = "client" -- Force client mode
|
||||||
|
|
||||||
|
if not ssl_params.sni.names then
|
||||||
|
-- names haven't been set, and hence will be set below. Since this alters
|
||||||
|
-- the table, we must make a copy. Otherwise the altered table might be
|
||||||
|
-- reused if a redirect is encountered.
|
||||||
|
local old_params = ssl_params
|
||||||
|
ssl_params = {}
|
||||||
|
for k,v in pairs(old_params) do
|
||||||
|
ssl_params[k] = v
|
||||||
|
end
|
||||||
|
ssl_params.sni = { strict = old_params.sni.strict }
|
||||||
|
end
|
||||||
|
|
||||||
|
-- upvalue to track https -> http redirection
|
||||||
|
local washttps = false
|
||||||
|
|
||||||
|
-- 'create' function for LuaSocket
|
||||||
|
return function (reqt)
|
||||||
|
local u = url.parse(reqt.url)
|
||||||
|
if (reqt.scheme or u.scheme) == "https" then
|
||||||
|
-- set SNI name to host if not given
|
||||||
|
ssl_params.sni.names = ssl_params.sni.names or u.host
|
||||||
|
-- https, provide an ssl wrapped socket
|
||||||
|
local conn = copas.wrap(socket.tcp(), ssl_params)
|
||||||
|
-- insert https default port, overriding http port inserted by LuaSocket
|
||||||
|
if not u.port then
|
||||||
|
u.port = _M.SSLPORT
|
||||||
|
reqt.url = url.build(u)
|
||||||
|
reqt.port = _M.SSLPORT
|
||||||
|
end
|
||||||
|
washttps = true
|
||||||
|
return conn
|
||||||
|
else
|
||||||
|
-- regular http, needs just a socket...
|
||||||
|
if washttps and params.redirect ~= "all" then
|
||||||
|
socket.try(nil, "Unallowed insecure redirect https to http")
|
||||||
|
end
|
||||||
|
return copas.wrap(socket.tcp())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- parses a shorthand form into the advanced table form.
|
||||||
|
-- adds field `target` to the table. This will hold the return values.
|
||||||
|
_M.parseRequest = function(u, b)
|
||||||
|
local reqt = {
|
||||||
|
url = u,
|
||||||
|
target = {},
|
||||||
|
}
|
||||||
|
reqt.sink = ltn12.sink.table(reqt.target)
|
||||||
|
if b then
|
||||||
|
reqt.source = ltn12.source.string(b)
|
||||||
|
reqt.headers = {
|
||||||
|
["content-length"] = string.len(b),
|
||||||
|
["content-type"] = "application/x-www-form-urlencoded"
|
||||||
|
}
|
||||||
|
reqt.method = "POST"
|
||||||
|
end
|
||||||
|
return reqt
|
||||||
|
end
|
||||||
|
|
||||||
|
_M.request = socket.protect(function(reqt, body)
|
||||||
|
if base.type(reqt) == "string" then
|
||||||
|
reqt = _M.parseRequest(reqt, body)
|
||||||
|
local ok, code, headers, status = _M.request(reqt)
|
||||||
|
|
||||||
|
if ok then
|
||||||
|
return table.concat(reqt.target), code, headers, status
|
||||||
|
else
|
||||||
|
return nil, code
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- strict check on timeout table to prevent typo's from going unnoticed
|
||||||
|
if type(reqt.timeout) == "table" then
|
||||||
|
local allowed = { connect = true, send = true, receive = true }
|
||||||
|
for k in pairs(reqt.timeout) do
|
||||||
|
assert(allowed[k], "'"..tostring(k).."' is not a valid timeout option. Valid: 'connect', 'send', 'receive'")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
reqt.create = reqt.create or _M.getcreatefunc(reqt)
|
||||||
|
return trequest(reqt)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
return _M
|
191
thirdparty/copas/src/copas/lock.lua
vendored
Normal file
191
thirdparty/copas/src/copas/lock.lua
vendored
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
local copas = require("copas")
|
||||||
|
local gettime = require("socket").gettime
|
||||||
|
|
||||||
|
local DEFAULT_TIMEOUT = 10
|
||||||
|
|
||||||
|
local lock = {}
|
||||||
|
lock.__index = lock
|
||||||
|
|
||||||
|
|
||||||
|
-- registry, locks indexed by the coroutines using them.
|
||||||
|
local registry = setmetatable({}, { __mode="kv" })
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Creates a new lock.
|
||||||
|
-- @param seconds (optional) default timeout in seconds when acquiring the lock (defaults to 10),
|
||||||
|
-- set to `math.huge` to have no timeout.
|
||||||
|
-- @param not_reentrant (optional) if truthy the lock will not allow a coroutine to grab the same lock multiple times
|
||||||
|
-- @return the lock object
|
||||||
|
function lock.new(seconds, not_reentrant)
|
||||||
|
local timeout = tonumber(seconds or DEFAULT_TIMEOUT) or -1
|
||||||
|
if timeout < 0 then
|
||||||
|
error("expected timeout (1st argument) to be a number greater than or equal to 0, got: " .. tostring(seconds), 2)
|
||||||
|
end
|
||||||
|
return setmetatable({
|
||||||
|
timeout = timeout,
|
||||||
|
not_reentrant = not_reentrant,
|
||||||
|
queue = {},
|
||||||
|
q_tip = 0, -- index of the first in line waiting
|
||||||
|
q_tail = 0, -- index where the next one will be inserted
|
||||||
|
owner = nil, -- coroutine holding lock currently
|
||||||
|
call_count = nil, -- recursion call count
|
||||||
|
errors = setmetatable({}, { __mode = "k" }), -- error indexed by coroutine
|
||||||
|
}, lock)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
do
|
||||||
|
local destroyed_func = function()
|
||||||
|
return nil, "destroyed"
|
||||||
|
end
|
||||||
|
|
||||||
|
local destroyed_lock_mt = {
|
||||||
|
__index = function()
|
||||||
|
return destroyed_func
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
--- destroy a lock.
|
||||||
|
-- Releases all waiting threads with `nil+"destroyed"`
|
||||||
|
function lock:destroy()
|
||||||
|
--print("destroying ",self)
|
||||||
|
for i = self.q_tip, self.q_tail do
|
||||||
|
local co = self.queue[i]
|
||||||
|
self.queue[i] = nil
|
||||||
|
|
||||||
|
if co then
|
||||||
|
self.errors[co] = "destroyed"
|
||||||
|
--print("marked destroyed ", co)
|
||||||
|
copas.wakeup(co)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.owner then
|
||||||
|
self.errors[self.owner] = "destroyed"
|
||||||
|
--print("marked destroyed ", co)
|
||||||
|
end
|
||||||
|
self.queue = {}
|
||||||
|
self.q_tip = 0
|
||||||
|
self.q_tail = 0
|
||||||
|
self.destroyed = true
|
||||||
|
|
||||||
|
setmetatable(self, destroyed_lock_mt)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function timeout_handler(co)
|
||||||
|
local self = registry[co]
|
||||||
|
if not self then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = self.q_tip, self.q_tail do
|
||||||
|
if co == self.queue[i] then
|
||||||
|
self.queue[i] = nil
|
||||||
|
self.errors[co] = "timeout"
|
||||||
|
--print("marked timeout ", co)
|
||||||
|
copas.wakeup(co)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- if we get here, we own it currently, or we finished it by now, or
|
||||||
|
-- the lock was destroyed. Anyway, nothing to do here...
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Acquires the lock.
|
||||||
|
-- If the lock is owned by another thread, this will yield control, until the
|
||||||
|
-- lock becomes available, or it times out.
|
||||||
|
-- If `timeout == 0` then it will immediately return (without yielding).
|
||||||
|
-- @param timeout (optional) timeout in seconds, defaults to the timeout passed to `new` (use `math.huge` to have no timeout).
|
||||||
|
-- @return wait-time on success, or nil+error+wait_time on failure. Errors can be "timeout", "destroyed", or "lock is not re-entrant"
|
||||||
|
function lock:get(timeout)
|
||||||
|
local co = coroutine.running()
|
||||||
|
local start_time
|
||||||
|
|
||||||
|
-- is the lock already taken?
|
||||||
|
if self.owner then
|
||||||
|
-- are we re-entering?
|
||||||
|
if co == self.owner and not self.not_reentrant then
|
||||||
|
self.call_count = self.call_count + 1
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
self.queue[self.q_tail] = co
|
||||||
|
self.q_tail = self.q_tail + 1
|
||||||
|
timeout = timeout or self.timeout
|
||||||
|
if timeout == 0 then
|
||||||
|
return nil, "timeout", 0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- set up timeout
|
||||||
|
registry[co] = self
|
||||||
|
copas.timeout(timeout, timeout_handler)
|
||||||
|
|
||||||
|
start_time = gettime()
|
||||||
|
copas.pauseforever()
|
||||||
|
|
||||||
|
local err = self.errors[co]
|
||||||
|
self.errors[co] = nil
|
||||||
|
registry[co] = nil
|
||||||
|
|
||||||
|
--print("released ", co, err)
|
||||||
|
if err ~= "timeout" then
|
||||||
|
copas.timeout(0)
|
||||||
|
end
|
||||||
|
if err then
|
||||||
|
return nil, err, gettime() - start_time
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- it's ours to have
|
||||||
|
self.owner = co
|
||||||
|
self.call_count = 1
|
||||||
|
return start_time and (gettime() - start_time) or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Releases the lock currently held.
|
||||||
|
-- Releasing a lock that is not owned by the current co-routine will return
|
||||||
|
-- an error.
|
||||||
|
-- returns true, or nil+err on an error
|
||||||
|
function lock:release()
|
||||||
|
local co = coroutine.running()
|
||||||
|
|
||||||
|
if co ~= self.owner then
|
||||||
|
return nil, "cannot release a lock not owned"
|
||||||
|
end
|
||||||
|
|
||||||
|
self.call_count = self.call_count - 1
|
||||||
|
if self.call_count > 0 then
|
||||||
|
-- same coro is still holding it
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- need a loop, since individual coroutines might have been removed
|
||||||
|
-- so there might be holes
|
||||||
|
while self.q_tip < self.q_tail do
|
||||||
|
local next_up = self.queue[self.q_tip]
|
||||||
|
if next_up then
|
||||||
|
self.owner = next_up
|
||||||
|
self.queue[self.q_tip] = nil
|
||||||
|
self.q_tip = self.q_tip + 1
|
||||||
|
copas.wakeup(next_up)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
self.q_tip = self.q_tip + 1
|
||||||
|
end
|
||||||
|
-- queue is empty, reset pointers
|
||||||
|
self.owner = nil
|
||||||
|
self.q_tip = 0
|
||||||
|
self.q_tail = 0
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return lock
|
191
thirdparty/copas/src/copas/queue.lua
vendored
Normal file
191
thirdparty/copas/src/copas/queue.lua
vendored
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
local copas = require "copas"
|
||||||
|
local Sema = copas.semaphore
|
||||||
|
local Lock = copas.lock
|
||||||
|
|
||||||
|
|
||||||
|
local Queue = {}
|
||||||
|
Queue.__index = Queue
|
||||||
|
|
||||||
|
|
||||||
|
local new_name do
|
||||||
|
local count = 0
|
||||||
|
|
||||||
|
function new_name()
|
||||||
|
count = count + 1
|
||||||
|
return "copas_queue_" .. count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Creates a new Queue instance
|
||||||
|
function Queue.new(opts)
|
||||||
|
opts = opts or {}
|
||||||
|
local self = {}
|
||||||
|
setmetatable(self, Queue)
|
||||||
|
self.name = opts.name or new_name()
|
||||||
|
self.sema = Sema.new(10^9)
|
||||||
|
self.head = 1
|
||||||
|
self.tail = 1
|
||||||
|
self.list = {}
|
||||||
|
self.workers = setmetatable({}, { __mode = "k" })
|
||||||
|
self.stopping = false
|
||||||
|
self.worker_id = 0
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Pushes an item in the queue (can be 'nil')
|
||||||
|
-- returns true, or nil+err ("stopping", or "destroyed")
|
||||||
|
function Queue:push(item)
|
||||||
|
if self.stopping then
|
||||||
|
return nil, "stopping"
|
||||||
|
end
|
||||||
|
self.list[self.head] = item
|
||||||
|
self.head = self.head + 1
|
||||||
|
self.sema:give()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Pops and item from the queue. If there are no items in the queue it will yield
|
||||||
|
-- until there are or a timeout happens (exception is when `timeout == 0`, then it will
|
||||||
|
-- not yield but return immediately). If the timeout is `math.huge` it will wait forever.
|
||||||
|
-- Returns item, or nil+err ("timeout", or "destroyed")
|
||||||
|
function Queue:pop(timeout)
|
||||||
|
local ok, err = self.sema:take(1, timeout)
|
||||||
|
if not ok then
|
||||||
|
return ok, err
|
||||||
|
end
|
||||||
|
|
||||||
|
local item = self.list[self.tail]
|
||||||
|
self.list[self.tail] = nil
|
||||||
|
self.tail = self.tail + 1
|
||||||
|
|
||||||
|
if self.tail == self.head then
|
||||||
|
-- reset queue
|
||||||
|
self.list = {}
|
||||||
|
self.tail = 1
|
||||||
|
self.head = 1
|
||||||
|
if self.stopping then
|
||||||
|
-- we're stopping and last item being returned, so we're done
|
||||||
|
self:destroy()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return item
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- return the number of items left in the queue
|
||||||
|
function Queue:get_size()
|
||||||
|
return self.head - self.tail
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- instructs the queue to stop. Will not accept any more 'push' calls.
|
||||||
|
-- will autocall 'destroy' when the queue is empty.
|
||||||
|
-- returns immediately. See `finish`
|
||||||
|
function Queue:stop()
|
||||||
|
if not self.stopping then
|
||||||
|
self.stopping = true
|
||||||
|
self.lock = Lock.new(nil, true)
|
||||||
|
self.lock:get() -- close the lock
|
||||||
|
if self:get_size() == 0 then
|
||||||
|
-- queue is already empty, so "pop" function cannot call destroy on next
|
||||||
|
-- pop, so destroy now.
|
||||||
|
self:destroy()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Finishes a queue. Calls stop and then waits for the queue to run empty (and be
|
||||||
|
-- destroyed) before returning. returns true or nil+err ("timeout", or "destroyed")
|
||||||
|
-- Parameter no_destroy_on_timeout indicates if the queue is not to be forcefully
|
||||||
|
-- destroyed on a timeout.
|
||||||
|
function Queue:finish(timeout, no_destroy_on_timeout)
|
||||||
|
self:stop()
|
||||||
|
local _, err = self.lock:get(timeout)
|
||||||
|
-- the lock never gets released, only destroyed, so we have to check the error string
|
||||||
|
if err == "timeout" then
|
||||||
|
if not no_destroy_on_timeout then
|
||||||
|
self:destroy()
|
||||||
|
end
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
do
|
||||||
|
local destroyed_func = function()
|
||||||
|
return nil, "destroyed"
|
||||||
|
end
|
||||||
|
|
||||||
|
local destroyed_queue_mt = {
|
||||||
|
__index = function()
|
||||||
|
return destroyed_func
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
-- destroys a queue immediately. Abandons what is left in the queue.
|
||||||
|
-- Releases all waiting threads with `nil+"destroyed"`
|
||||||
|
function Queue:destroy()
|
||||||
|
if self.lock then
|
||||||
|
self.lock:destroy()
|
||||||
|
end
|
||||||
|
self.sema:destroy()
|
||||||
|
setmetatable(self, destroyed_queue_mt)
|
||||||
|
|
||||||
|
-- clear anything left in the queue
|
||||||
|
for key in pairs(self.list) do
|
||||||
|
self.list[key] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- adds a worker that will handle whatever is passed into the queue. Can be called
|
||||||
|
-- multiple times to add more workers.
|
||||||
|
-- The threads automatically exit when the queue is destroyed.
|
||||||
|
-- worker function signature: `function(item)` (Note: worker functions run
|
||||||
|
-- unprotected, so wrap code in an (x)pcall if errors are expected, otherwise the
|
||||||
|
-- worker will exit on an error, and queue handling will stop)
|
||||||
|
-- Returns the coroutine added.
|
||||||
|
function Queue:add_worker(worker)
|
||||||
|
assert(type(worker) == "function", "expected worker to be a function")
|
||||||
|
local coro
|
||||||
|
|
||||||
|
self.worker_id = self.worker_id + 1
|
||||||
|
local worker_name = self.name .. ":worker_" .. self.worker_id
|
||||||
|
|
||||||
|
coro = copas.addnamedthread(worker_name, function()
|
||||||
|
while true do
|
||||||
|
local item, err = self:pop(math.huge) -- wait forever
|
||||||
|
if err then
|
||||||
|
break -- queue destroyed, exit
|
||||||
|
end
|
||||||
|
worker(item) -- TODO: wrap in errorhandling
|
||||||
|
end
|
||||||
|
self.workers[coro] = nil
|
||||||
|
end)
|
||||||
|
|
||||||
|
self.workers[coro] = true
|
||||||
|
return coro
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns a list/array of current workers (coroutines) handling the queue.
|
||||||
|
-- (only the workers added by `add_worker`, and still active, will be in this list)
|
||||||
|
function Queue:get_workers()
|
||||||
|
local lst = {}
|
||||||
|
for coro in pairs(self.workers) do
|
||||||
|
if coroutine.status(coro) ~= "dead" then
|
||||||
|
lst[#lst+1] = coro
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return lst
|
||||||
|
end
|
||||||
|
|
||||||
|
return Queue
|
202
thirdparty/copas/src/copas/semaphore.lua
vendored
Normal file
202
thirdparty/copas/src/copas/semaphore.lua
vendored
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
local copas = require("copas")
|
||||||
|
|
||||||
|
local DEFAULT_TIMEOUT = 10
|
||||||
|
|
||||||
|
local semaphore = {}
|
||||||
|
semaphore.__index = semaphore
|
||||||
|
|
||||||
|
|
||||||
|
-- registry, semaphore indexed by the coroutines using them.
|
||||||
|
local registry = setmetatable({}, { __mode="kv" })
|
||||||
|
|
||||||
|
|
||||||
|
-- create a new semaphore
|
||||||
|
-- @param max maximum number of resources the semaphore can hold (this maximum does NOT include resources that have been given but not yet returned).
|
||||||
|
-- @param start (optional, default 0) the initial resources available
|
||||||
|
-- @param seconds (optional, default 10) default semaphore timeout in seconds, or `math.huge` to have no timeout.
|
||||||
|
function semaphore.new(max, start, seconds)
|
||||||
|
local timeout = tonumber(seconds or DEFAULT_TIMEOUT) or -1
|
||||||
|
if timeout < 0 then
|
||||||
|
error("expected timeout (2nd argument) to be a number greater than or equal to 0, got: " .. tostring(seconds), 2)
|
||||||
|
end
|
||||||
|
if type(max) ~= "number" or max < 1 then
|
||||||
|
error("expected max resources (1st argument) to be a number greater than 0, got: " .. tostring(max), 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
local self = setmetatable({
|
||||||
|
count = start or 0,
|
||||||
|
max = max,
|
||||||
|
timeout = timeout,
|
||||||
|
q_tip = 1, -- position of next entry waiting
|
||||||
|
q_tail = 1, -- position where next one will be inserted
|
||||||
|
queue = {},
|
||||||
|
to_flags = setmetatable({}, { __mode = "k" }), -- timeout flags indexed by coroutine
|
||||||
|
}, semaphore)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
do
|
||||||
|
local destroyed_func = function()
|
||||||
|
return nil, "destroyed"
|
||||||
|
end
|
||||||
|
|
||||||
|
local destroyed_semaphore_mt = {
|
||||||
|
__index = function()
|
||||||
|
return destroyed_func
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
-- destroy a semaphore.
|
||||||
|
-- Releases all waiting threads with `nil+"destroyed"`
|
||||||
|
function semaphore:destroy()
|
||||||
|
self:give(math.huge)
|
||||||
|
self.destroyed = true
|
||||||
|
setmetatable(self, destroyed_semaphore_mt)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Gives resources.
|
||||||
|
-- @param given (optional, default 1) number of resources to return. If more
|
||||||
|
-- than the maximum are returned then it will be capped at the maximum and
|
||||||
|
-- error "too many" will be returned.
|
||||||
|
function semaphore:give(given)
|
||||||
|
local err
|
||||||
|
given = given or 1
|
||||||
|
local count = self.count + given
|
||||||
|
--print("now at",count, ", after +"..given)
|
||||||
|
if count > self.max then
|
||||||
|
count = self.max
|
||||||
|
err = "too many"
|
||||||
|
end
|
||||||
|
|
||||||
|
while self.q_tip < self.q_tail do
|
||||||
|
local i = self.q_tip
|
||||||
|
local nxt = self.queue[i] -- there can be holes, so nxt might be nil
|
||||||
|
if not nxt then
|
||||||
|
self.q_tip = i + 1
|
||||||
|
else
|
||||||
|
if count >= nxt.requested then
|
||||||
|
-- release it
|
||||||
|
self.queue[i] = nil
|
||||||
|
self.to_flags[nxt.co] = nil
|
||||||
|
count = count - nxt.requested
|
||||||
|
self.q_tip = i + 1
|
||||||
|
copas.wakeup(nxt.co)
|
||||||
|
nxt.co = nil
|
||||||
|
else
|
||||||
|
break -- we ran out of resources
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.q_tip == self.q_tail then -- reset queue
|
||||||
|
self.queue = {}
|
||||||
|
self.q_tip = 1
|
||||||
|
self.q_tail = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
self.count = count
|
||||||
|
if err then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
local function timeout_handler(co)
|
||||||
|
local self = registry[co]
|
||||||
|
--print("checking timeout ", co)
|
||||||
|
if not self then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = self.q_tip, self.q_tail do
|
||||||
|
local item = self.queue[i]
|
||||||
|
if item and co == item.co then
|
||||||
|
self.queue[i] = nil
|
||||||
|
self.to_flags[co] = true
|
||||||
|
--print("marked timeout ", co)
|
||||||
|
copas.wakeup(co)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- nothing to do here...
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Requests resources from the semaphore.
|
||||||
|
-- Waits if there are not enough resources available before returning.
|
||||||
|
-- @param requested (optional, default 1) the number of resources requested
|
||||||
|
-- @param timeout (optional, defaults to semaphore timeout) timeout in
|
||||||
|
-- seconds. If 0 it will either succeed or return immediately with error "timeout".
|
||||||
|
-- If `math.huge` it will wait forever.
|
||||||
|
-- @return true, or nil+"destroyed"
|
||||||
|
function semaphore:take(requested, timeout)
|
||||||
|
requested = requested or 1
|
||||||
|
if self.q_tail == 1 and self.count >= requested then
|
||||||
|
-- nobody is waiting before us, and there is enough in store
|
||||||
|
self.count = self.count - requested
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if requested > self.max then
|
||||||
|
return nil, "too many"
|
||||||
|
end
|
||||||
|
|
||||||
|
local to = timeout or self.timeout
|
||||||
|
if to == 0 then
|
||||||
|
return nil, "timeout"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get in line
|
||||||
|
local co = coroutine.running()
|
||||||
|
self.to_flags[co] = nil
|
||||||
|
registry[co] = self
|
||||||
|
copas.timeout(to, timeout_handler)
|
||||||
|
|
||||||
|
self.queue[self.q_tail] = {
|
||||||
|
co = co,
|
||||||
|
requested = requested,
|
||||||
|
--timeout = nil, -- flag indicating timeout
|
||||||
|
}
|
||||||
|
self.q_tail = self.q_tail + 1
|
||||||
|
|
||||||
|
copas.pauseforever() -- block until woken
|
||||||
|
registry[co] = nil
|
||||||
|
|
||||||
|
if self.to_flags[co] then
|
||||||
|
-- a timeout happened
|
||||||
|
self.to_flags[co] = nil
|
||||||
|
return nil, "timeout"
|
||||||
|
end
|
||||||
|
|
||||||
|
copas.timeout(0)
|
||||||
|
|
||||||
|
if self.destroyed then
|
||||||
|
return nil, "destroyed"
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns current available resources
|
||||||
|
function semaphore:get_count()
|
||||||
|
return self.count
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns total shortage for requested resources
|
||||||
|
function semaphore:get_wait()
|
||||||
|
local wait = 0
|
||||||
|
for i = self.q_tip, self.q_tail - 1 do
|
||||||
|
wait = wait + ((self.queue[i] or {}).requested or 0)
|
||||||
|
end
|
||||||
|
return wait - self.count
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return semaphore
|
34
thirdparty/copas/src/copas/smtp.lua
vendored
Normal file
34
thirdparty/copas/src/copas/smtp.lua
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
-- identical to the socket.smtp module except that it uses
|
||||||
|
-- async wrapped Copas sockets
|
||||||
|
|
||||||
|
local copas = require("copas")
|
||||||
|
local smtp = require("socket.smtp")
|
||||||
|
local socket = require("socket")
|
||||||
|
|
||||||
|
local create = function() return copas.wrap(socket.tcp()) end
|
||||||
|
local forwards = { -- setting these will be forwarded to the original smtp module
|
||||||
|
PORT = true,
|
||||||
|
SERVER = true,
|
||||||
|
TIMEOUT = true,
|
||||||
|
DOMAIN = true,
|
||||||
|
TIMEZONE = true
|
||||||
|
}
|
||||||
|
|
||||||
|
copas.smtp = setmetatable({}, {
|
||||||
|
-- use original module as metatable, to lookup constants like socket.SERVER, etc.
|
||||||
|
__index = smtp,
|
||||||
|
-- Setting constants is forwarded to the luasocket.smtp module.
|
||||||
|
__newindex = function(self, key, value)
|
||||||
|
if forwards[key] then smtp[key] = value return end
|
||||||
|
return rawset(self, key, value)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
local _M = copas.smtp
|
||||||
|
|
||||||
|
_M.send = function(mailt)
|
||||||
|
mailt.create = mailt.create or create
|
||||||
|
return smtp.send(mailt)
|
||||||
|
end
|
||||||
|
|
||||||
|
return _M
|
130
thirdparty/copas/src/copas/timer.lua
vendored
Normal file
130
thirdparty/copas/src/copas/timer.lua
vendored
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
local copas = require("copas")
|
||||||
|
|
||||||
|
local xpcall = xpcall
|
||||||
|
local coroutine_running = coroutine.running
|
||||||
|
|
||||||
|
if _VERSION=="Lua 5.1" and not jit then -- obsolete: only for Lua 5.1 compatibility
|
||||||
|
xpcall = require("coxpcall").xpcall
|
||||||
|
coroutine_running = require("coxpcall").running
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local timer = {}
|
||||||
|
timer.__index = timer
|
||||||
|
|
||||||
|
|
||||||
|
local new_name do
|
||||||
|
local count = 0
|
||||||
|
|
||||||
|
function new_name()
|
||||||
|
count = count + 1
|
||||||
|
return "copas_timer_" .. count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
do
|
||||||
|
local function expire_func(self, initial_delay)
|
||||||
|
if self.errorhandler then
|
||||||
|
copas.seterrorhandler(self.errorhandler)
|
||||||
|
end
|
||||||
|
copas.pause(initial_delay)
|
||||||
|
while true do
|
||||||
|
if not self.cancelled then
|
||||||
|
if not self.recurring then
|
||||||
|
-- non-recurring timer
|
||||||
|
self.cancelled = true
|
||||||
|
self.co = nil
|
||||||
|
|
||||||
|
self:callback(self.params)
|
||||||
|
return
|
||||||
|
|
||||||
|
else
|
||||||
|
-- recurring timer
|
||||||
|
self:callback(self.params)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.cancelled then
|
||||||
|
-- clean up and exit the thread
|
||||||
|
self.co = nil
|
||||||
|
self.cancelled = true
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
copas.pause(self.delay)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Arms the timer object.
|
||||||
|
-- @param initial_delay (optional) the first delay to use, if not provided uses the timer delay
|
||||||
|
-- @return timer object, nil+error, or throws an error on bad input
|
||||||
|
function timer:arm(initial_delay)
|
||||||
|
assert(initial_delay == nil or initial_delay >= 0, "delay must be greater than or equal to 0")
|
||||||
|
if self.co then
|
||||||
|
return nil, "already armed"
|
||||||
|
end
|
||||||
|
|
||||||
|
self.cancelled = false
|
||||||
|
self.co = copas.addnamedthread(self.name, expire_func, self, initial_delay or self.delay)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Cancels a running timer.
|
||||||
|
-- @return timer object, or nil+error
|
||||||
|
function timer:cancel()
|
||||||
|
if not self.co then
|
||||||
|
return nil, "not armed"
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.cancelled then
|
||||||
|
return nil, "already cancelled"
|
||||||
|
end
|
||||||
|
|
||||||
|
self.cancelled = true
|
||||||
|
copas.wakeup(self.co) -- resume asap
|
||||||
|
copas.removethread(self.co) -- will immediately drop the thread upon resuming
|
||||||
|
self.co = nil
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
do
|
||||||
|
-- xpcall error handler that forwards to the copas errorhandler
|
||||||
|
local ehandler = function(err_obj)
|
||||||
|
return copas.geterrorhandler()(err_obj, coroutine_running(), nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Creates a new timer object.
|
||||||
|
-- Note: the callback signature is: `function(timer_obj, params)`.
|
||||||
|
-- @param opts (table) `opts.delay` timer delay in seconds, `opts.callback` function to execute, `opts.recurring` boolean
|
||||||
|
-- `opts.params` (optional) this value will be passed to the timer callback, `opts.initial_delay` (optional) the first delay to use, defaults to `delay`.
|
||||||
|
-- @return timer object, or throws an error on bad input
|
||||||
|
function timer.new(opts)
|
||||||
|
assert(opts.delay or -1 >= 0, "delay must be greater than or equal to 0")
|
||||||
|
assert(type(opts.callback) == "function", "expected callback to be a function")
|
||||||
|
|
||||||
|
local callback = function(timer_obj, params)
|
||||||
|
xpcall(opts.callback, ehandler, timer_obj, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
return setmetatable({
|
||||||
|
name = opts.name or new_name(),
|
||||||
|
delay = opts.delay,
|
||||||
|
callback = callback,
|
||||||
|
recurring = not not opts.recurring,
|
||||||
|
params = opts.params,
|
||||||
|
cancelled = false,
|
||||||
|
errorhandler = opts.errorhandler,
|
||||||
|
}, timer):arm(opts.initial_delay)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return timer
|
3
thirdparty/copas/tests/certs/_readme.md
vendored
Normal file
3
thirdparty/copas/tests/certs/_readme.md
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
The certificate generation scripts here are copied from LuaSec
|
||||||
|
|
||||||
|
|
14
thirdparty/copas/tests/certs/all.bat
vendored
Normal file
14
thirdparty/copas/tests/certs/all.bat
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
REM make sure the 'openssl.exe' commandline tool is in your path before starting!
|
||||||
|
REM set the path below;
|
||||||
|
set opensslpath=c:\program files (x86)\openssl-win32\bin
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
set path=%opensslpath%;%path%
|
||||||
|
call roota.bat
|
||||||
|
call rootb.bat
|
||||||
|
call servera.bat
|
||||||
|
call serverb.bat
|
||||||
|
call clienta.bat
|
||||||
|
call clientb.bat
|
13
thirdparty/copas/tests/certs/all.sh
vendored
Executable file
13
thirdparty/copas/tests/certs/all.sh
vendored
Executable file
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
CWD=$(PWD)
|
||||||
|
cd $( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
|
./rootA.sh
|
||||||
|
./rootB.sh
|
||||||
|
./serverA.sh
|
||||||
|
./serverB.sh
|
||||||
|
./clientA.sh
|
||||||
|
./clientB.sh
|
||||||
|
|
||||||
|
cd $CWD
|
9
thirdparty/copas/tests/certs/clientA.bat
vendored
Normal file
9
thirdparty/copas/tests/certs/clientA.bat
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
rem #!/bin/sh
|
||||||
|
|
||||||
|
openssl req -newkey rsa:1024 -sha1 -keyout clientAkey.pem -out clientAreq.pem -nodes -config ./clientA.cnf -days 365 -batch
|
||||||
|
|
||||||
|
openssl x509 -req -in clientAreq.pem -sha1 -extfile ./clientA.cnf -extensions usr_cert -CA rootA.pem -CAkey rootAkey.pem -CAcreateserial -out clientAcert.pem -days 365
|
||||||
|
|
||||||
|
copy clientAcert.pem + rootA.pem clientA.pem
|
||||||
|
|
||||||
|
openssl x509 -subject -issuer -noout -in clientA.pem
|
316
thirdparty/copas/tests/certs/clientA.cnf
vendored
Normal file
316
thirdparty/copas/tests/certs/clientA.cnf
vendored
Normal file
|
@ -0,0 +1,316 @@
|
||||||
|
#
|
||||||
|
# OpenSSL example configuration file.
|
||||||
|
# This is mostly being used for generation of certificate requests.
|
||||||
|
#
|
||||||
|
|
||||||
|
# This definition stops the following lines choking if HOME isn't
|
||||||
|
# defined.
|
||||||
|
HOME = .
|
||||||
|
RANDFILE = $ENV::HOME/.rnd
|
||||||
|
|
||||||
|
# Extra OBJECT IDENTIFIER info:
|
||||||
|
#oid_file = $ENV::HOME/.oid
|
||||||
|
oid_section = new_oids
|
||||||
|
|
||||||
|
# To use this configuration file with the "-extfile" option of the
|
||||||
|
# "openssl x509" utility, name here the section containing the
|
||||||
|
# X.509v3 extensions to use:
|
||||||
|
# extensions =
|
||||||
|
# (Alternatively, use a configuration file that has only
|
||||||
|
# X.509v3 extensions in its main [= default] section.)
|
||||||
|
|
||||||
|
[ new_oids ]
|
||||||
|
|
||||||
|
# We can add new OIDs in here for use by 'ca' and 'req'.
|
||||||
|
# Add a simple OID like this:
|
||||||
|
# testoid1=1.2.3.4
|
||||||
|
# Or use config file substitution like this:
|
||||||
|
# testoid2=${testoid1}.5.6
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ ca ]
|
||||||
|
default_ca = CA_default # The default ca section
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ CA_default ]
|
||||||
|
|
||||||
|
dir = ./demoCA # Where everything is kept
|
||||||
|
certs = $dir/certs # Where the issued certs are kept
|
||||||
|
crl_dir = $dir/crl # Where the issued crl are kept
|
||||||
|
database = $dir/index.txt # database index file.
|
||||||
|
#unique_subject = no # Set to 'no' to allow creation of
|
||||||
|
# several ctificates with same subject.
|
||||||
|
new_certs_dir = $dir/newcerts # default place for new certs.
|
||||||
|
|
||||||
|
certificate = $dir/cacert.pem # The CA certificate
|
||||||
|
serial = $dir/serial # The current serial number
|
||||||
|
crlnumber = $dir/crlnumber # the current crl number
|
||||||
|
# must be commented out to leave a V1 CRL
|
||||||
|
crl = $dir/crl.pem # The current CRL
|
||||||
|
private_key = $dir/private/cakey.pem # The private key
|
||||||
|
RANDFILE = $dir/private/.rand # private random number file
|
||||||
|
|
||||||
|
x509_extensions = usr_cert # The extensions to add to the cert
|
||||||
|
|
||||||
|
# Comment out the following two lines for the "traditional"
|
||||||
|
# (and highly broken) format.
|
||||||
|
name_opt = ca_default # Subject Name options
|
||||||
|
cert_opt = ca_default # Certificate field options
|
||||||
|
|
||||||
|
# Extension copying option: use with caution.
|
||||||
|
# copy_extensions = copy
|
||||||
|
|
||||||
|
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
|
||||||
|
# so this is commented out by default to leave a V1 CRL.
|
||||||
|
# crlnumber must also be commented out to leave a V1 CRL.
|
||||||
|
# crl_extensions = crl_ext
|
||||||
|
|
||||||
|
default_days = 365 # how long to certify for
|
||||||
|
default_crl_days= 30 # how long before next CRL
|
||||||
|
default_md = sha1 # which md to use.
|
||||||
|
preserve = no # keep passed DN ordering
|
||||||
|
|
||||||
|
# A few difference way of specifying how similar the request should look
|
||||||
|
# For type CA, the listed attributes must be the same, and the optional
|
||||||
|
# and supplied fields are just that :-)
|
||||||
|
policy = policy_match
|
||||||
|
|
||||||
|
# For the CA policy
|
||||||
|
[ policy_match ]
|
||||||
|
countryName = match
|
||||||
|
stateOrProvinceName = match
|
||||||
|
organizationName = match
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
# For the 'anything' policy
|
||||||
|
# At this point in time, you must list all acceptable 'object'
|
||||||
|
# types.
|
||||||
|
[ policy_anything ]
|
||||||
|
countryName = optional
|
||||||
|
stateOrProvinceName = optional
|
||||||
|
localityName = optional
|
||||||
|
organizationName = optional
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ req ]
|
||||||
|
default_bits = 1024
|
||||||
|
default_keyfile = privkey.pem
|
||||||
|
distinguished_name = req_distinguished_name
|
||||||
|
attributes = req_attributes
|
||||||
|
x509_extensions = v3_ca # The extensions to add to the self signed cert
|
||||||
|
|
||||||
|
# Passwords for private keys if not present they will be prompted for
|
||||||
|
# input_password = secret
|
||||||
|
# output_password = secret
|
||||||
|
|
||||||
|
# This sets a mask for permitted string types. There are several options.
|
||||||
|
# default: PrintableString, T61String, BMPString.
|
||||||
|
# pkix : PrintableString, BMPString.
|
||||||
|
# utf8only: only UTF8Strings.
|
||||||
|
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
|
||||||
|
# MASK:XXXX a literal mask value.
|
||||||
|
# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
|
||||||
|
# so use this option with caution!
|
||||||
|
string_mask = nombstr
|
||||||
|
|
||||||
|
# req_extensions = v3_req # The extensions to add to a certificate request
|
||||||
|
|
||||||
|
[ req_distinguished_name ]
|
||||||
|
countryName = Country Name (2 letter code)
|
||||||
|
countryName_default = BR
|
||||||
|
countryName_min = 2
|
||||||
|
countryName_max = 2
|
||||||
|
|
||||||
|
stateOrProvinceName = State or Province Name (full name)
|
||||||
|
stateOrProvinceName_default = Some-State
|
||||||
|
stateOrProvinceName_default = Espirito Santo
|
||||||
|
|
||||||
|
localityName = Locality Name (eg, city)
|
||||||
|
localityName_default = Santo Antonio do Canaa
|
||||||
|
|
||||||
|
0.organizationName = Organization Name (eg, company)
|
||||||
|
0.organizationName_default = Sao Tonico Ltda
|
||||||
|
|
||||||
|
# we can do this but it is not needed normally :-)
|
||||||
|
#1.organizationName = Second Organization Name (eg, company)
|
||||||
|
#1.organizationName_default = World Wide Web Pty Ltd
|
||||||
|
|
||||||
|
organizationalUnitName = Organizational Unit Name (eg, section)
|
||||||
|
organizationalUnitName_default = Department of Computer Science
|
||||||
|
|
||||||
|
commonName = Common Name (eg, YOUR name)
|
||||||
|
commonName_default = Client A
|
||||||
|
commonName_max = 64
|
||||||
|
|
||||||
|
emailAddress = Email Address
|
||||||
|
emailAddress_max = 64
|
||||||
|
|
||||||
|
# SET-ex3 = SET extension number 3
|
||||||
|
|
||||||
|
[ req_attributes ]
|
||||||
|
challengePassword = A challenge password
|
||||||
|
challengePassword_min = 4
|
||||||
|
challengePassword_max = 20
|
||||||
|
|
||||||
|
unstructuredName = An optional company name
|
||||||
|
|
||||||
|
[ usr_cert ]
|
||||||
|
|
||||||
|
# These extensions are added when 'ca' signs a request.
|
||||||
|
|
||||||
|
# This goes against PKIX guidelines but some CAs do it and some software
|
||||||
|
# requires this to avoid interpreting an end user certificate as a CA.
|
||||||
|
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
|
||||||
|
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||||
|
# the certificate can be used for anything *except* object signing.
|
||||||
|
|
||||||
|
# This is OK for an SSL server.
|
||||||
|
# nsCertType = server
|
||||||
|
|
||||||
|
# For an object signing certificate this would be used.
|
||||||
|
# nsCertType = objsign
|
||||||
|
|
||||||
|
# For normal client use this is typical
|
||||||
|
# nsCertType = client, email
|
||||||
|
|
||||||
|
# and for everything including object signing:
|
||||||
|
# nsCertType = client, email, objsign
|
||||||
|
|
||||||
|
# This is typical in keyUsage for a client certificate.
|
||||||
|
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
# This will be displayed in Netscape's comment listbox.
|
||||||
|
nsComment = "OpenSSL Generated Certificate"
|
||||||
|
|
||||||
|
# PKIX recommendations harmless if included in all certificates.
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer
|
||||||
|
|
||||||
|
# This stuff is for subjectAltName and issuerAltname.
|
||||||
|
# Import the email address.
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# An alternative to produce certificates that aren't
|
||||||
|
# deprecated according to PKIX.
|
||||||
|
# subjectAltName=email:move
|
||||||
|
|
||||||
|
# Copy subject details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||||
|
#nsBaseUrl
|
||||||
|
#nsRevocationUrl
|
||||||
|
#nsRenewalUrl
|
||||||
|
#nsCaPolicyUrl
|
||||||
|
#nsSslServerName
|
||||||
|
|
||||||
|
[ v3_req ]
|
||||||
|
|
||||||
|
# Extensions to add to a certificate request
|
||||||
|
|
||||||
|
basicConstraints = CA:FALSE
|
||||||
|
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
[ v3_ca ]
|
||||||
|
|
||||||
|
|
||||||
|
# Extensions for a typical CA
|
||||||
|
|
||||||
|
|
||||||
|
# PKIX recommendation.
|
||||||
|
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
|
||||||
|
# This is what PKIX recommends but some broken software chokes on critical
|
||||||
|
# extensions.
|
||||||
|
#basicConstraints = critical,CA:true
|
||||||
|
# So we do this instead.
|
||||||
|
basicConstraints = CA:true
|
||||||
|
|
||||||
|
# Key usage: this is typical for a CA certificate. However since it will
|
||||||
|
# prevent it being used as an test self-signed certificate it is best
|
||||||
|
# left out by default.
|
||||||
|
# keyUsage = cRLSign, keyCertSign
|
||||||
|
|
||||||
|
# Some might want this also
|
||||||
|
# nsCertType = sslCA, emailCA
|
||||||
|
|
||||||
|
# Include email address in subject alt name: another PKIX recommendation
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# Copy issuer details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
# DER hex encoding of an extension: beware experts only!
|
||||||
|
# obj=DER:02:03
|
||||||
|
# Where 'obj' is a standard or added object
|
||||||
|
# You can even override a supported extension:
|
||||||
|
# basicConstraints= critical, DER:30:03:01:01:FF
|
||||||
|
|
||||||
|
[ crl_ext ]
|
||||||
|
|
||||||
|
# CRL extensions.
|
||||||
|
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
|
||||||
|
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
|
||||||
|
[ proxy_cert_ext ]
|
||||||
|
# These extensions should be added when creating a proxy certificate
|
||||||
|
|
||||||
|
# This goes against PKIX guidelines but some CAs do it and some software
|
||||||
|
# requires this to avoid interpreting an end user certificate as a CA.
|
||||||
|
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
|
||||||
|
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||||
|
# the certificate can be used for anything *except* object signing.
|
||||||
|
|
||||||
|
# This is OK for an SSL server.
|
||||||
|
# nsCertType = server
|
||||||
|
|
||||||
|
# For an object signing certificate this would be used.
|
||||||
|
# nsCertType = objsign
|
||||||
|
|
||||||
|
# For normal client use this is typical
|
||||||
|
# nsCertType = client, email
|
||||||
|
|
||||||
|
# and for everything including object signing:
|
||||||
|
# nsCertType = client, email, objsign
|
||||||
|
|
||||||
|
# This is typical in keyUsage for a client certificate.
|
||||||
|
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
# This will be displayed in Netscape's comment listbox.
|
||||||
|
nsComment = "OpenSSL Generated Certificate"
|
||||||
|
|
||||||
|
# PKIX recommendations harmless if included in all certificates.
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer:always
|
||||||
|
|
||||||
|
# This stuff is for subjectAltName and issuerAltname.
|
||||||
|
# Import the email address.
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# An alternative to produce certificates that aren't
|
||||||
|
# deprecated according to PKIX.
|
||||||
|
# subjectAltName=email:move
|
||||||
|
|
||||||
|
# Copy subject details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||||
|
#nsBaseUrl
|
||||||
|
#nsRevocationUrl
|
||||||
|
#nsRenewalUrl
|
||||||
|
#nsCaPolicyUrl
|
||||||
|
#nsSslServerName
|
||||||
|
|
||||||
|
# This really needs to be in place for it to be a proxy certificate.
|
||||||
|
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
|
12
thirdparty/copas/tests/certs/clientA.sh
vendored
Executable file
12
thirdparty/copas/tests/certs/clientA.sh
vendored
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
openssl req -newkey rsa:1024 -sha1 -keyout clientAkey.pem -out clientAreq.pem \
|
||||||
|
-nodes -config ./clientA.cnf -days 365 -batch
|
||||||
|
|
||||||
|
openssl x509 -req -in clientAreq.pem -sha1 -extfile ./clientA.cnf \
|
||||||
|
-extensions usr_cert -CA rootA.pem -CAkey rootAkey.pem -CAcreateserial \
|
||||||
|
-out clientAcert.pem -days 365
|
||||||
|
|
||||||
|
cat clientAcert.pem rootA.pem > clientA.pem
|
||||||
|
|
||||||
|
openssl x509 -subject -issuer -noout -in clientA.pem
|
9
thirdparty/copas/tests/certs/clientB.bat
vendored
Normal file
9
thirdparty/copas/tests/certs/clientB.bat
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
rem #!/bin/sh
|
||||||
|
|
||||||
|
openssl req -newkey rsa:1024 -sha1 -keyout clientBkey.pem -out clientBreq.pem -nodes -config ./clientB.cnf -days 365 -batch
|
||||||
|
|
||||||
|
openssl x509 -req -in clientBreq.pem -sha1 -extfile ./clientB.cnf -extensions usr_cert -CA rootB.pem -CAkey rootBkey.pem -CAcreateserial -out clientBcert.pem -days 365
|
||||||
|
|
||||||
|
copy clientBcert.pem + rootB.pem clientB.pem
|
||||||
|
|
||||||
|
openssl x509 -subject -issuer -noout -in clientB.pem
|
316
thirdparty/copas/tests/certs/clientB.cnf
vendored
Normal file
316
thirdparty/copas/tests/certs/clientB.cnf
vendored
Normal file
|
@ -0,0 +1,316 @@
|
||||||
|
#
|
||||||
|
# OpenSSL example configuration file.
|
||||||
|
# This is mostly being used for generation of certificate requests.
|
||||||
|
#
|
||||||
|
|
||||||
|
# This definition stops the following lines choking if HOME isn't
|
||||||
|
# defined.
|
||||||
|
HOME = .
|
||||||
|
RANDFILE = $ENV::HOME/.rnd
|
||||||
|
|
||||||
|
# Extra OBJECT IDENTIFIER info:
|
||||||
|
#oid_file = $ENV::HOME/.oid
|
||||||
|
oid_section = new_oids
|
||||||
|
|
||||||
|
# To use this configuration file with the "-extfile" option of the
|
||||||
|
# "openssl x509" utility, name here the section containing the
|
||||||
|
# X.509v3 extensions to use:
|
||||||
|
# extensions =
|
||||||
|
# (Alternatively, use a configuration file that has only
|
||||||
|
# X.509v3 extensions in its main [= default] section.)
|
||||||
|
|
||||||
|
[ new_oids ]
|
||||||
|
|
||||||
|
# We can add new OIDs in here for use by 'ca' and 'req'.
|
||||||
|
# Add a simple OID like this:
|
||||||
|
# testoid1=1.2.3.4
|
||||||
|
# Or use config file substitution like this:
|
||||||
|
# testoid2=${testoid1}.5.6
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ ca ]
|
||||||
|
default_ca = CA_default # The default ca section
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ CA_default ]
|
||||||
|
|
||||||
|
dir = ./demoCA # Where everything is kept
|
||||||
|
certs = $dir/certs # Where the issued certs are kept
|
||||||
|
crl_dir = $dir/crl # Where the issued crl are kept
|
||||||
|
database = $dir/index.txt # database index file.
|
||||||
|
#unique_subject = no # Set to 'no' to allow creation of
|
||||||
|
# several ctificates with same subject.
|
||||||
|
new_certs_dir = $dir/newcerts # default place for new certs.
|
||||||
|
|
||||||
|
certificate = $dir/cacert.pem # The CA certificate
|
||||||
|
serial = $dir/serial # The current serial number
|
||||||
|
crlnumber = $dir/crlnumber # the current crl number
|
||||||
|
# must be commented out to leave a V1 CRL
|
||||||
|
crl = $dir/crl.pem # The current CRL
|
||||||
|
private_key = $dir/private/cakey.pem # The private key
|
||||||
|
RANDFILE = $dir/private/.rand # private random number file
|
||||||
|
|
||||||
|
x509_extensions = usr_cert # The extensions to add to the cert
|
||||||
|
|
||||||
|
# Comment out the following two lines for the "traditional"
|
||||||
|
# (and highly broken) format.
|
||||||
|
name_opt = ca_default # Subject Name options
|
||||||
|
cert_opt = ca_default # Certificate field options
|
||||||
|
|
||||||
|
# Extension copying option: use with caution.
|
||||||
|
# copy_extensions = copy
|
||||||
|
|
||||||
|
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
|
||||||
|
# so this is commented out by default to leave a V1 CRL.
|
||||||
|
# crlnumber must also be commented out to leave a V1 CRL.
|
||||||
|
# crl_extensions = crl_ext
|
||||||
|
|
||||||
|
default_days = 365 # how long to certify for
|
||||||
|
default_crl_days= 30 # how long before next CRL
|
||||||
|
default_md = sha1 # which md to use.
|
||||||
|
preserve = no # keep passed DN ordering
|
||||||
|
|
||||||
|
# A few difference way of specifying how similar the request should look
|
||||||
|
# For type CA, the listed attributes must be the same, and the optional
|
||||||
|
# and supplied fields are just that :-)
|
||||||
|
policy = policy_match
|
||||||
|
|
||||||
|
# For the CA policy
|
||||||
|
[ policy_match ]
|
||||||
|
countryName = match
|
||||||
|
stateOrProvinceName = match
|
||||||
|
organizationName = match
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
# For the 'anything' policy
|
||||||
|
# At this point in time, you must list all acceptable 'object'
|
||||||
|
# types.
|
||||||
|
[ policy_anything ]
|
||||||
|
countryName = optional
|
||||||
|
stateOrProvinceName = optional
|
||||||
|
localityName = optional
|
||||||
|
organizationName = optional
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ req ]
|
||||||
|
default_bits = 1024
|
||||||
|
default_keyfile = privkey.pem
|
||||||
|
distinguished_name = req_distinguished_name
|
||||||
|
attributes = req_attributes
|
||||||
|
x509_extensions = v3_ca # The extensions to add to the self signed cert
|
||||||
|
|
||||||
|
# Passwords for private keys if not present they will be prompted for
|
||||||
|
# input_password = secret
|
||||||
|
# output_password = secret
|
||||||
|
|
||||||
|
# This sets a mask for permitted string types. There are several options.
|
||||||
|
# default: PrintableString, T61String, BMPString.
|
||||||
|
# pkix : PrintableString, BMPString.
|
||||||
|
# utf8only: only UTF8Strings.
|
||||||
|
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
|
||||||
|
# MASK:XXXX a literal mask value.
|
||||||
|
# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
|
||||||
|
# so use this option with caution!
|
||||||
|
string_mask = nombstr
|
||||||
|
|
||||||
|
# req_extensions = v3_req # The extensions to add to a certificate request
|
||||||
|
|
||||||
|
[ req_distinguished_name ]
|
||||||
|
countryName = Country Name (2 letter code)
|
||||||
|
countryName_default = BR
|
||||||
|
countryName_min = 2
|
||||||
|
countryName_max = 2
|
||||||
|
|
||||||
|
stateOrProvinceName = State or Province Name (full name)
|
||||||
|
stateOrProvinceName_default = Some-State
|
||||||
|
stateOrProvinceName_default = Espirito Santo
|
||||||
|
|
||||||
|
localityName = Locality Name (eg, city)
|
||||||
|
localityName_default = Santo Antonio do Canaa
|
||||||
|
|
||||||
|
0.organizationName = Organization Name (eg, company)
|
||||||
|
0.organizationName_default = Sao Tonico Ltda
|
||||||
|
|
||||||
|
# we can do this but it is not needed normally :-)
|
||||||
|
#1.organizationName = Second Organization Name (eg, company)
|
||||||
|
#1.organizationName_default = World Wide Web Pty Ltd
|
||||||
|
|
||||||
|
organizationalUnitName = Organizational Unit Name (eg, section)
|
||||||
|
organizationalUnitName_default = Department of Computer Science
|
||||||
|
|
||||||
|
commonName = Common Name (eg, YOUR name)
|
||||||
|
commonName_default = Client B
|
||||||
|
commonName_max = 64
|
||||||
|
|
||||||
|
emailAddress = Email Address
|
||||||
|
emailAddress_max = 64
|
||||||
|
|
||||||
|
# SET-ex3 = SET extension number 3
|
||||||
|
|
||||||
|
[ req_attributes ]
|
||||||
|
challengePassword = A challenge password
|
||||||
|
challengePassword_min = 4
|
||||||
|
challengePassword_max = 20
|
||||||
|
|
||||||
|
unstructuredName = An optional company name
|
||||||
|
|
||||||
|
[ usr_cert ]
|
||||||
|
|
||||||
|
# These extensions are added when 'ca' signs a request.
|
||||||
|
|
||||||
|
# This goes against PKIX guidelines but some CAs do it and some software
|
||||||
|
# requires this to avoid interpreting an end user certificate as a CA.
|
||||||
|
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
|
||||||
|
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||||
|
# the certificate can be used for anything *except* object signing.
|
||||||
|
|
||||||
|
# This is OK for an SSL server.
|
||||||
|
# nsCertType = server
|
||||||
|
|
||||||
|
# For an object signing certificate this would be used.
|
||||||
|
# nsCertType = objsign
|
||||||
|
|
||||||
|
# For normal client use this is typical
|
||||||
|
# nsCertType = client, email
|
||||||
|
|
||||||
|
# and for everything including object signing:
|
||||||
|
# nsCertType = client, email, objsign
|
||||||
|
|
||||||
|
# This is typical in keyUsage for a client certificate.
|
||||||
|
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
# This will be displayed in Netscape's comment listbox.
|
||||||
|
nsComment = "OpenSSL Generated Certificate"
|
||||||
|
|
||||||
|
# PKIX recommendations harmless if included in all certificates.
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer
|
||||||
|
|
||||||
|
# This stuff is for subjectAltName and issuerAltname.
|
||||||
|
# Import the email address.
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# An alternative to produce certificates that aren't
|
||||||
|
# deprecated according to PKIX.
|
||||||
|
# subjectAltName=email:move
|
||||||
|
|
||||||
|
# Copy subject details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||||
|
#nsBaseUrl
|
||||||
|
#nsRevocationUrl
|
||||||
|
#nsRenewalUrl
|
||||||
|
#nsCaPolicyUrl
|
||||||
|
#nsSslServerName
|
||||||
|
|
||||||
|
[ v3_req ]
|
||||||
|
|
||||||
|
# Extensions to add to a certificate request
|
||||||
|
|
||||||
|
basicConstraints = CA:FALSE
|
||||||
|
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
[ v3_ca ]
|
||||||
|
|
||||||
|
|
||||||
|
# Extensions for a typical CA
|
||||||
|
|
||||||
|
|
||||||
|
# PKIX recommendation.
|
||||||
|
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
|
||||||
|
# This is what PKIX recommends but some broken software chokes on critical
|
||||||
|
# extensions.
|
||||||
|
#basicConstraints = critical,CA:true
|
||||||
|
# So we do this instead.
|
||||||
|
basicConstraints = CA:true
|
||||||
|
|
||||||
|
# Key usage: this is typical for a CA certificate. However since it will
|
||||||
|
# prevent it being used as an test self-signed certificate it is best
|
||||||
|
# left out by default.
|
||||||
|
# keyUsage = cRLSign, keyCertSign
|
||||||
|
|
||||||
|
# Some might want this also
|
||||||
|
# nsCertType = sslCA, emailCA
|
||||||
|
|
||||||
|
# Include email address in subject alt name: another PKIX recommendation
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# Copy issuer details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
# DER hex encoding of an extension: beware experts only!
|
||||||
|
# obj=DER:02:03
|
||||||
|
# Where 'obj' is a standard or added object
|
||||||
|
# You can even override a supported extension:
|
||||||
|
# basicConstraints= critical, DER:30:03:01:01:FF
|
||||||
|
|
||||||
|
[ crl_ext ]
|
||||||
|
|
||||||
|
# CRL extensions.
|
||||||
|
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
|
||||||
|
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
|
||||||
|
[ proxy_cert_ext ]
|
||||||
|
# These extensions should be added when creating a proxy certificate
|
||||||
|
|
||||||
|
# This goes against PKIX guidelines but some CAs do it and some software
|
||||||
|
# requires this to avoid interpreting an end user certificate as a CA.
|
||||||
|
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
|
||||||
|
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||||
|
# the certificate can be used for anything *except* object signing.
|
||||||
|
|
||||||
|
# This is OK for an SSL server.
|
||||||
|
# nsCertType = server
|
||||||
|
|
||||||
|
# For an object signing certificate this would be used.
|
||||||
|
# nsCertType = objsign
|
||||||
|
|
||||||
|
# For normal client use this is typical
|
||||||
|
# nsCertType = client, email
|
||||||
|
|
||||||
|
# and for everything including object signing:
|
||||||
|
# nsCertType = client, email, objsign
|
||||||
|
|
||||||
|
# This is typical in keyUsage for a client certificate.
|
||||||
|
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
# This will be displayed in Netscape's comment listbox.
|
||||||
|
nsComment = "OpenSSL Generated Certificate"
|
||||||
|
|
||||||
|
# PKIX recommendations harmless if included in all certificates.
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer:always
|
||||||
|
|
||||||
|
# This stuff is for subjectAltName and issuerAltname.
|
||||||
|
# Import the email address.
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# An alternative to produce certificates that aren't
|
||||||
|
# deprecated according to PKIX.
|
||||||
|
# subjectAltName=email:move
|
||||||
|
|
||||||
|
# Copy subject details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||||
|
#nsBaseUrl
|
||||||
|
#nsRevocationUrl
|
||||||
|
#nsRenewalUrl
|
||||||
|
#nsCaPolicyUrl
|
||||||
|
#nsSslServerName
|
||||||
|
|
||||||
|
# This really needs to be in place for it to be a proxy certificate.
|
||||||
|
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
|
12
thirdparty/copas/tests/certs/clientB.sh
vendored
Executable file
12
thirdparty/copas/tests/certs/clientB.sh
vendored
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
openssl req -newkey rsa:1024 -sha1 -keyout clientBkey.pem -out clientBreq.pem \
|
||||||
|
-nodes -config ./clientB.cnf -days 365 -batch
|
||||||
|
|
||||||
|
openssl x509 -req -in clientBreq.pem -sha1 -extfile ./clientB.cnf \
|
||||||
|
-extensions usr_cert -CA rootB.pem -CAkey rootBkey.pem -CAcreateserial \
|
||||||
|
-out clientBcert.pem -days 365
|
||||||
|
|
||||||
|
cat clientBcert.pem rootB.pem > clientB.pem
|
||||||
|
|
||||||
|
openssl x509 -subject -issuer -noout -in clientB.pem
|
7
thirdparty/copas/tests/certs/rootA.bat
vendored
Normal file
7
thirdparty/copas/tests/certs/rootA.bat
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
REM #!/bin/sh
|
||||||
|
|
||||||
|
openssl req -newkey rsa:1024 -sha1 -keyout rootAkey.pem -out rootAreq.pem -nodes -config ./rootA.cnf -days 365 -batch
|
||||||
|
|
||||||
|
openssl x509 -req -in rootAreq.pem -sha1 -extfile ./rootA.cnf -extensions v3_ca -signkey rootAkey.pem -out rootA.pem -days 365
|
||||||
|
|
||||||
|
openssl x509 -subject -issuer -noout -in rootA.pem
|
315
thirdparty/copas/tests/certs/rootA.cnf
vendored
Normal file
315
thirdparty/copas/tests/certs/rootA.cnf
vendored
Normal file
|
@ -0,0 +1,315 @@
|
||||||
|
#
|
||||||
|
# OpenSSL example configuration file.
|
||||||
|
# This is mostly being used for generation of certificate requests.
|
||||||
|
#
|
||||||
|
|
||||||
|
# This definition stops the following lines choking if HOME isn't
|
||||||
|
# defined.
|
||||||
|
HOME = .
|
||||||
|
RANDFILE = $ENV::HOME/.rnd
|
||||||
|
|
||||||
|
# Extra OBJECT IDENTIFIER info:
|
||||||
|
#oid_file = $ENV::HOME/.oid
|
||||||
|
oid_section = new_oids
|
||||||
|
|
||||||
|
# To use this configuration file with the "-extfile" option of the
|
||||||
|
# "openssl x509" utility, name here the section containing the
|
||||||
|
# X.509v3 extensions to use:
|
||||||
|
# extensions =
|
||||||
|
# (Alternatively, use a configuration file that has only
|
||||||
|
# X.509v3 extensions in its main [= default] section.)
|
||||||
|
|
||||||
|
[ new_oids ]
|
||||||
|
|
||||||
|
# We can add new OIDs in here for use by 'ca' and 'req'.
|
||||||
|
# Add a simple OID like this:
|
||||||
|
# testoid1=1.2.3.4
|
||||||
|
# Or use config file substitution like this:
|
||||||
|
# testoid2=${testoid1}.5.6
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ ca ]
|
||||||
|
default_ca = CA_default # The default ca section
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ CA_default ]
|
||||||
|
|
||||||
|
dir = ./demoCA # Where everything is kept
|
||||||
|
certs = $dir/certs # Where the issued certs are kept
|
||||||
|
crl_dir = $dir/crl # Where the issued crl are kept
|
||||||
|
database = $dir/index.txt # database index file.
|
||||||
|
#unique_subject = no # Set to 'no' to allow creation of
|
||||||
|
# several ctificates with same subject.
|
||||||
|
new_certs_dir = $dir/newcerts # default place for new certs.
|
||||||
|
|
||||||
|
certificate = $dir/cacert.pem # The CA certificate
|
||||||
|
serial = $dir/serial # The current serial number
|
||||||
|
crlnumber = $dir/crlnumber # the current crl number
|
||||||
|
# must be commented out to leave a V1 CRL
|
||||||
|
crl = $dir/crl.pem # The current CRL
|
||||||
|
private_key = $dir/private/cakey.pem # The private key
|
||||||
|
RANDFILE = $dir/private/.rand # private random number file
|
||||||
|
|
||||||
|
x509_extensions = usr_cert # The extensions to add to the cert
|
||||||
|
|
||||||
|
# Comment out the following two lines for the "traditional"
|
||||||
|
# (and highly broken) format.
|
||||||
|
name_opt = ca_default # Subject Name options
|
||||||
|
cert_opt = ca_default # Certificate field options
|
||||||
|
|
||||||
|
# Extension copying option: use with caution.
|
||||||
|
# copy_extensions = copy
|
||||||
|
|
||||||
|
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
|
||||||
|
# so this is commented out by default to leave a V1 CRL.
|
||||||
|
# crlnumber must also be commented out to leave a V1 CRL.
|
||||||
|
# crl_extensions = crl_ext
|
||||||
|
|
||||||
|
default_days = 365 # how long to certify for
|
||||||
|
default_crl_days= 30 # how long before next CRL
|
||||||
|
default_md = sha1 # which md to use.
|
||||||
|
preserve = no # keep passed DN ordering
|
||||||
|
|
||||||
|
# A few difference way of specifying how similar the request should look
|
||||||
|
# For type CA, the listed attributes must be the same, and the optional
|
||||||
|
# and supplied fields are just that :-)
|
||||||
|
policy = policy_match
|
||||||
|
|
||||||
|
# For the CA policy
|
||||||
|
[ policy_match ]
|
||||||
|
countryName = match
|
||||||
|
stateOrProvinceName = match
|
||||||
|
organizationName = match
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
# For the 'anything' policy
|
||||||
|
# At this point in time, you must list all acceptable 'object'
|
||||||
|
# types.
|
||||||
|
[ policy_anything ]
|
||||||
|
countryName = optional
|
||||||
|
stateOrProvinceName = optional
|
||||||
|
localityName = optional
|
||||||
|
organizationName = optional
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ req ]
|
||||||
|
default_bits = 1024
|
||||||
|
default_keyfile = privkey.pem
|
||||||
|
distinguished_name = req_distinguished_name
|
||||||
|
attributes = req_attributes
|
||||||
|
x509_extensions = v3_ca # The extensions to add to the self signed cert
|
||||||
|
|
||||||
|
# Passwords for private keys if not present they will be prompted for
|
||||||
|
# input_password = secret
|
||||||
|
# output_password = secret
|
||||||
|
|
||||||
|
# This sets a mask for permitted string types. There are several options.
|
||||||
|
# default: PrintableString, T61String, BMPString.
|
||||||
|
# pkix : PrintableString, BMPString.
|
||||||
|
# utf8only: only UTF8Strings.
|
||||||
|
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
|
||||||
|
# MASK:XXXX a literal mask value.
|
||||||
|
# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
|
||||||
|
# so use this option with caution!
|
||||||
|
string_mask = nombstr
|
||||||
|
|
||||||
|
# req_extensions = v3_req # The extensions to add to a certificate request
|
||||||
|
|
||||||
|
[ req_distinguished_name ]
|
||||||
|
countryName = Country Name (2 letter code)
|
||||||
|
countryName_default = BR
|
||||||
|
countryName_min = 2
|
||||||
|
countryName_max = 2
|
||||||
|
|
||||||
|
stateOrProvinceName = State or Province Name (full name)
|
||||||
|
stateOrProvinceName_default = Espirito Santo
|
||||||
|
|
||||||
|
localityName = Locality Name (eg, city)
|
||||||
|
localityName_default = Santo Antonio do Canaa
|
||||||
|
|
||||||
|
0.organizationName = Organization Name (eg, company)
|
||||||
|
0.organizationName_default = Santo Tonico Ltda
|
||||||
|
|
||||||
|
# we can do this but it is not needed normally :-)
|
||||||
|
#1.organizationName = Second Organization Name (eg, company)
|
||||||
|
#1.organizationName_default = World Wide Web Pty Ltd
|
||||||
|
|
||||||
|
organizationalUnitName = Organizational Unit Name (eg, section)
|
||||||
|
organizationalUnitName_default = Department of Computer Science
|
||||||
|
|
||||||
|
commonName = Common Name (eg, YOUR name)
|
||||||
|
commonName_max = 64
|
||||||
|
commonName_default = Root A
|
||||||
|
|
||||||
|
emailAddress = Email Address
|
||||||
|
emailAddress_max = 64
|
||||||
|
|
||||||
|
# SET-ex3 = SET extension number 3
|
||||||
|
|
||||||
|
[ req_attributes ]
|
||||||
|
challengePassword = A challenge password
|
||||||
|
challengePassword_min = 4
|
||||||
|
challengePassword_max = 20
|
||||||
|
|
||||||
|
unstructuredName = An optional company name
|
||||||
|
|
||||||
|
[ usr_cert ]
|
||||||
|
|
||||||
|
# These extensions are added when 'ca' signs a request.
|
||||||
|
|
||||||
|
# This goes against PKIX guidelines but some CAs do it and some software
|
||||||
|
# requires this to avoid interpreting an end user certificate as a CA.
|
||||||
|
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
|
||||||
|
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||||
|
# the certificate can be used for anything *except* object signing.
|
||||||
|
|
||||||
|
# This is OK for an SSL server.
|
||||||
|
# nsCertType = server
|
||||||
|
|
||||||
|
# For an object signing certificate this would be used.
|
||||||
|
# nsCertType = objsign
|
||||||
|
|
||||||
|
# For normal client use this is typical
|
||||||
|
# nsCertType = client, email
|
||||||
|
|
||||||
|
# and for everything including object signing:
|
||||||
|
# nsCertType = client, email, objsign
|
||||||
|
|
||||||
|
# This is typical in keyUsage for a client certificate.
|
||||||
|
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
# This will be displayed in Netscape's comment listbox.
|
||||||
|
nsComment = "OpenSSL Generated Certificate"
|
||||||
|
|
||||||
|
# PKIX recommendations harmless if included in all certificates.
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer
|
||||||
|
|
||||||
|
# This stuff is for subjectAltName and issuerAltname.
|
||||||
|
# Import the email address.
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# An alternative to produce certificates that aren't
|
||||||
|
# deprecated according to PKIX.
|
||||||
|
# subjectAltName=email:move
|
||||||
|
|
||||||
|
# Copy subject details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||||
|
#nsBaseUrl
|
||||||
|
#nsRevocationUrl
|
||||||
|
#nsRenewalUrl
|
||||||
|
#nsCaPolicyUrl
|
||||||
|
#nsSslServerName
|
||||||
|
|
||||||
|
[ v3_req ]
|
||||||
|
|
||||||
|
# Extensions to add to a certificate request
|
||||||
|
|
||||||
|
basicConstraints = CA:FALSE
|
||||||
|
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
[ v3_ca ]
|
||||||
|
|
||||||
|
|
||||||
|
# Extensions for a typical CA
|
||||||
|
|
||||||
|
|
||||||
|
# PKIX recommendation.
|
||||||
|
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
|
||||||
|
# This is what PKIX recommends but some broken software chokes on critical
|
||||||
|
# extensions.
|
||||||
|
#basicConstraints = critical,CA:true
|
||||||
|
# So we do this instead.
|
||||||
|
basicConstraints = CA:true
|
||||||
|
|
||||||
|
# Key usage: this is typical for a CA certificate. However since it will
|
||||||
|
# prevent it being used as an test self-signed certificate it is best
|
||||||
|
# left out by default.
|
||||||
|
# keyUsage = cRLSign, keyCertSign
|
||||||
|
|
||||||
|
# Some might want this also
|
||||||
|
# nsCertType = sslCA, emailCA
|
||||||
|
|
||||||
|
# Include email address in subject alt name: another PKIX recommendation
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# Copy issuer details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
# DER hex encoding of an extension: beware experts only!
|
||||||
|
# obj=DER:02:03
|
||||||
|
# Where 'obj' is a standard or added object
|
||||||
|
# You can even override a supported extension:
|
||||||
|
# basicConstraints= critical, DER:30:03:01:01:FF
|
||||||
|
|
||||||
|
[ crl_ext ]
|
||||||
|
|
||||||
|
# CRL extensions.
|
||||||
|
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
|
||||||
|
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
|
||||||
|
[ proxy_cert_ext ]
|
||||||
|
# These extensions should be added when creating a proxy certificate
|
||||||
|
|
||||||
|
# This goes against PKIX guidelines but some CAs do it and some software
|
||||||
|
# requires this to avoid interpreting an end user certificate as a CA.
|
||||||
|
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
|
||||||
|
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||||
|
# the certificate can be used for anything *except* object signing.
|
||||||
|
|
||||||
|
# This is OK for an SSL server.
|
||||||
|
# nsCertType = server
|
||||||
|
|
||||||
|
# For an object signing certificate this would be used.
|
||||||
|
# nsCertType = objsign
|
||||||
|
|
||||||
|
# For normal client use this is typical
|
||||||
|
# nsCertType = client, email
|
||||||
|
|
||||||
|
# and for everything including object signing:
|
||||||
|
# nsCertType = client, email, objsign
|
||||||
|
|
||||||
|
# This is typical in keyUsage for a client certificate.
|
||||||
|
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
# This will be displayed in Netscape's comment listbox.
|
||||||
|
nsComment = "OpenSSL Generated Certificate"
|
||||||
|
|
||||||
|
# PKIX recommendations harmless if included in all certificates.
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer:always
|
||||||
|
|
||||||
|
# This stuff is for subjectAltName and issuerAltname.
|
||||||
|
# Import the email address.
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# An alternative to produce certificates that aren't
|
||||||
|
# deprecated according to PKIX.
|
||||||
|
# subjectAltName=email:move
|
||||||
|
|
||||||
|
# Copy subject details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||||
|
#nsBaseUrl
|
||||||
|
#nsRevocationUrl
|
||||||
|
#nsRenewalUrl
|
||||||
|
#nsCaPolicyUrl
|
||||||
|
#nsSslServerName
|
||||||
|
|
||||||
|
# This really needs to be in place for it to be a proxy certificate.
|
||||||
|
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
|
7
thirdparty/copas/tests/certs/rootA.sh
vendored
Executable file
7
thirdparty/copas/tests/certs/rootA.sh
vendored
Executable file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
openssl req -newkey rsa:1024 -sha1 -keyout rootAkey.pem -out rootAreq.pem -nodes -config ./rootA.cnf -days 365 -batch
|
||||||
|
|
||||||
|
openssl x509 -req -in rootAreq.pem -sha1 -extfile ./rootA.cnf -extensions v3_ca -signkey rootAkey.pem -out rootA.pem -days 365
|
||||||
|
|
||||||
|
openssl x509 -subject -issuer -noout -in rootA.pem
|
7
thirdparty/copas/tests/certs/rootB.bat
vendored
Normal file
7
thirdparty/copas/tests/certs/rootB.bat
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
rem #!/bin/sh
|
||||||
|
|
||||||
|
openssl req -newkey rsa:1024 -sha1 -keyout rootBkey.pem -out rootBreq.pem -nodes -config ./rootB.cnf -days 365 -batch
|
||||||
|
|
||||||
|
openssl x509 -req -in rootBreq.pem -sha1 -extfile ./rootB.cnf -extensions v3_ca -signkey rootBkey.pem -out rootB.pem -days 365
|
||||||
|
|
||||||
|
openssl x509 -subject -issuer -noout -in rootB.pem
|
315
thirdparty/copas/tests/certs/rootB.cnf
vendored
Normal file
315
thirdparty/copas/tests/certs/rootB.cnf
vendored
Normal file
|
@ -0,0 +1,315 @@
|
||||||
|
#
|
||||||
|
# OpenSSL example configuration file.
|
||||||
|
# This is mostly being used for generation of certificate requests.
|
||||||
|
#
|
||||||
|
|
||||||
|
# This definition stops the following lines choking if HOME isn't
|
||||||
|
# defined.
|
||||||
|
HOME = .
|
||||||
|
RANDFILE = $ENV::HOME/.rnd
|
||||||
|
|
||||||
|
# Extra OBJECT IDENTIFIER info:
|
||||||
|
#oid_file = $ENV::HOME/.oid
|
||||||
|
oid_section = new_oids
|
||||||
|
|
||||||
|
# To use this configuration file with the "-extfile" option of the
|
||||||
|
# "openssl x509" utility, name here the section containing the
|
||||||
|
# X.509v3 extensions to use:
|
||||||
|
# extensions =
|
||||||
|
# (Alternatively, use a configuration file that has only
|
||||||
|
# X.509v3 extensions in its main [= default] section.)
|
||||||
|
|
||||||
|
[ new_oids ]
|
||||||
|
|
||||||
|
# We can add new OIDs in here for use by 'ca' and 'req'.
|
||||||
|
# Add a simple OID like this:
|
||||||
|
# testoid1=1.2.3.4
|
||||||
|
# Or use config file substitution like this:
|
||||||
|
# testoid2=${testoid1}.5.6
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ ca ]
|
||||||
|
default_ca = CA_default # The default ca section
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ CA_default ]
|
||||||
|
|
||||||
|
dir = ./demoCA # Where everything is kept
|
||||||
|
certs = $dir/certs # Where the issued certs are kept
|
||||||
|
crl_dir = $dir/crl # Where the issued crl are kept
|
||||||
|
database = $dir/index.txt # database index file.
|
||||||
|
#unique_subject = no # Set to 'no' to allow creation of
|
||||||
|
# several ctificates with same subject.
|
||||||
|
new_certs_dir = $dir/newcerts # default place for new certs.
|
||||||
|
|
||||||
|
certificate = $dir/cacert.pem # The CA certificate
|
||||||
|
serial = $dir/serial # The current serial number
|
||||||
|
crlnumber = $dir/crlnumber # the current crl number
|
||||||
|
# must be commented out to leave a V1 CRL
|
||||||
|
crl = $dir/crl.pem # The current CRL
|
||||||
|
private_key = $dir/private/cakey.pem # The private key
|
||||||
|
RANDFILE = $dir/private/.rand # private random number file
|
||||||
|
|
||||||
|
x509_extensions = usr_cert # The extensions to add to the cert
|
||||||
|
|
||||||
|
# Comment out the following two lines for the "traditional"
|
||||||
|
# (and highly broken) format.
|
||||||
|
name_opt = ca_default # Subject Name options
|
||||||
|
cert_opt = ca_default # Certificate field options
|
||||||
|
|
||||||
|
# Extension copying option: use with caution.
|
||||||
|
# copy_extensions = copy
|
||||||
|
|
||||||
|
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
|
||||||
|
# so this is commented out by default to leave a V1 CRL.
|
||||||
|
# crlnumber must also be commented out to leave a V1 CRL.
|
||||||
|
# crl_extensions = crl_ext
|
||||||
|
|
||||||
|
default_days = 365 # how long to certify for
|
||||||
|
default_crl_days= 30 # how long before next CRL
|
||||||
|
default_md = sha1 # which md to use.
|
||||||
|
preserve = no # keep passed DN ordering
|
||||||
|
|
||||||
|
# A few difference way of specifying how similar the request should look
|
||||||
|
# For type CA, the listed attributes must be the same, and the optional
|
||||||
|
# and supplied fields are just that :-)
|
||||||
|
policy = policy_match
|
||||||
|
|
||||||
|
# For the CA policy
|
||||||
|
[ policy_match ]
|
||||||
|
countryName = match
|
||||||
|
stateOrProvinceName = match
|
||||||
|
organizationName = match
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
# For the 'anything' policy
|
||||||
|
# At this point in time, you must list all acceptable 'object'
|
||||||
|
# types.
|
||||||
|
[ policy_anything ]
|
||||||
|
countryName = optional
|
||||||
|
stateOrProvinceName = optional
|
||||||
|
localityName = optional
|
||||||
|
organizationName = optional
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ req ]
|
||||||
|
default_bits = 1024
|
||||||
|
default_keyfile = privkey.pem
|
||||||
|
distinguished_name = req_distinguished_name
|
||||||
|
attributes = req_attributes
|
||||||
|
x509_extensions = v3_ca # The extensions to add to the self signed cert
|
||||||
|
|
||||||
|
# Passwords for private keys if not present they will be prompted for
|
||||||
|
# input_password = secret
|
||||||
|
# output_password = secret
|
||||||
|
|
||||||
|
# This sets a mask for permitted string types. There are several options.
|
||||||
|
# default: PrintableString, T61String, BMPString.
|
||||||
|
# pkix : PrintableString, BMPString.
|
||||||
|
# utf8only: only UTF8Strings.
|
||||||
|
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
|
||||||
|
# MASK:XXXX a literal mask value.
|
||||||
|
# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
|
||||||
|
# so use this option with caution!
|
||||||
|
string_mask = nombstr
|
||||||
|
|
||||||
|
# req_extensions = v3_req # The extensions to add to a certificate request
|
||||||
|
|
||||||
|
[ req_distinguished_name ]
|
||||||
|
countryName = Country Name (2 letter code)
|
||||||
|
countryName_default = BR
|
||||||
|
countryName_min = 2
|
||||||
|
countryName_max = 2
|
||||||
|
|
||||||
|
stateOrProvinceName = State or Province Name (full name)
|
||||||
|
stateOrProvinceName_default = Espirito Santo
|
||||||
|
|
||||||
|
localityName = Locality Name (eg, city)
|
||||||
|
localityName_default = Santo Antonio do Canaa
|
||||||
|
|
||||||
|
0.organizationName = Organization Name (eg, company)
|
||||||
|
0.organizationName_default = Sao Tonico Ltda
|
||||||
|
|
||||||
|
# we can do this but it is not needed normally :-)
|
||||||
|
#1.organizationName = Second Organization Name (eg, company)
|
||||||
|
#1.organizationName_default = World Wide Web Pty Ltd
|
||||||
|
|
||||||
|
organizationalUnitName = Organizational Unit Name (eg, section)
|
||||||
|
organizationalUnitName_default = Department of Computer Science
|
||||||
|
|
||||||
|
commonName = Common Name (eg, YOUR name)
|
||||||
|
commonName_default = Root B
|
||||||
|
commonName_max = 64
|
||||||
|
|
||||||
|
emailAddress = Email Address
|
||||||
|
emailAddress_max = 64
|
||||||
|
|
||||||
|
# SET-ex3 = SET extension number 3
|
||||||
|
|
||||||
|
[ req_attributes ]
|
||||||
|
challengePassword = A challenge password
|
||||||
|
challengePassword_min = 4
|
||||||
|
challengePassword_max = 20
|
||||||
|
|
||||||
|
unstructuredName = An optional company name
|
||||||
|
|
||||||
|
[ usr_cert ]
|
||||||
|
|
||||||
|
# These extensions are added when 'ca' signs a request.
|
||||||
|
|
||||||
|
# This goes against PKIX guidelines but some CAs do it and some software
|
||||||
|
# requires this to avoid interpreting an end user certificate as a CA.
|
||||||
|
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
|
||||||
|
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||||
|
# the certificate can be used for anything *except* object signing.
|
||||||
|
|
||||||
|
# This is OK for an SSL server.
|
||||||
|
# nsCertType = server
|
||||||
|
|
||||||
|
# For an object signing certificate this would be used.
|
||||||
|
# nsCertType = objsign
|
||||||
|
|
||||||
|
# For normal client use this is typical
|
||||||
|
# nsCertType = client, email
|
||||||
|
|
||||||
|
# and for everything including object signing:
|
||||||
|
# nsCertType = client, email, objsign
|
||||||
|
|
||||||
|
# This is typical in keyUsage for a client certificate.
|
||||||
|
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
# This will be displayed in Netscape's comment listbox.
|
||||||
|
nsComment = "OpenSSL Generated Certificate"
|
||||||
|
|
||||||
|
# PKIX recommendations harmless if included in all certificates.
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer
|
||||||
|
|
||||||
|
# This stuff is for subjectAltName and issuerAltname.
|
||||||
|
# Import the email address.
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# An alternative to produce certificates that aren't
|
||||||
|
# deprecated according to PKIX.
|
||||||
|
# subjectAltName=email:move
|
||||||
|
|
||||||
|
# Copy subject details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||||
|
#nsBaseUrl
|
||||||
|
#nsRevocationUrl
|
||||||
|
#nsRenewalUrl
|
||||||
|
#nsCaPolicyUrl
|
||||||
|
#nsSslServerName
|
||||||
|
|
||||||
|
[ v3_req ]
|
||||||
|
|
||||||
|
# Extensions to add to a certificate request
|
||||||
|
|
||||||
|
basicConstraints = CA:FALSE
|
||||||
|
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
[ v3_ca ]
|
||||||
|
|
||||||
|
|
||||||
|
# Extensions for a typical CA
|
||||||
|
|
||||||
|
|
||||||
|
# PKIX recommendation.
|
||||||
|
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
|
||||||
|
# This is what PKIX recommends but some broken software chokes on critical
|
||||||
|
# extensions.
|
||||||
|
#basicConstraints = critical,CA:true
|
||||||
|
# So we do this instead.
|
||||||
|
basicConstraints = CA:true
|
||||||
|
|
||||||
|
# Key usage: this is typical for a CA certificate. However since it will
|
||||||
|
# prevent it being used as an test self-signed certificate it is best
|
||||||
|
# left out by default.
|
||||||
|
# keyUsage = cRLSign, keyCertSign
|
||||||
|
|
||||||
|
# Some might want this also
|
||||||
|
# nsCertType = sslCA, emailCA
|
||||||
|
|
||||||
|
# Include email address in subject alt name: another PKIX recommendation
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# Copy issuer details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
# DER hex encoding of an extension: beware experts only!
|
||||||
|
# obj=DER:02:03
|
||||||
|
# Where 'obj' is a standard or added object
|
||||||
|
# You can even override a supported extension:
|
||||||
|
# basicConstraints= critical, DER:30:03:01:01:FF
|
||||||
|
|
||||||
|
[ crl_ext ]
|
||||||
|
|
||||||
|
# CRL extensions.
|
||||||
|
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
|
||||||
|
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
|
||||||
|
[ proxy_cert_ext ]
|
||||||
|
# These extensions should be added when creating a proxy certificate
|
||||||
|
|
||||||
|
# This goes against PKIX guidelines but some CAs do it and some software
|
||||||
|
# requires this to avoid interpreting an end user certificate as a CA.
|
||||||
|
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
|
||||||
|
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||||
|
# the certificate can be used for anything *except* object signing.
|
||||||
|
|
||||||
|
# This is OK for an SSL server.
|
||||||
|
# nsCertType = server
|
||||||
|
|
||||||
|
# For an object signing certificate this would be used.
|
||||||
|
# nsCertType = objsign
|
||||||
|
|
||||||
|
# For normal client use this is typical
|
||||||
|
# nsCertType = client, email
|
||||||
|
|
||||||
|
# and for everything including object signing:
|
||||||
|
# nsCertType = client, email, objsign
|
||||||
|
|
||||||
|
# This is typical in keyUsage for a client certificate.
|
||||||
|
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
# This will be displayed in Netscape's comment listbox.
|
||||||
|
nsComment = "OpenSSL Generated Certificate"
|
||||||
|
|
||||||
|
# PKIX recommendations harmless if included in all certificates.
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer:always
|
||||||
|
|
||||||
|
# This stuff is for subjectAltName and issuerAltname.
|
||||||
|
# Import the email address.
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# An alternative to produce certificates that aren't
|
||||||
|
# deprecated according to PKIX.
|
||||||
|
# subjectAltName=email:move
|
||||||
|
|
||||||
|
# Copy subject details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||||
|
#nsBaseUrl
|
||||||
|
#nsRevocationUrl
|
||||||
|
#nsRenewalUrl
|
||||||
|
#nsCaPolicyUrl
|
||||||
|
#nsSslServerName
|
||||||
|
|
||||||
|
# This really needs to be in place for it to be a proxy certificate.
|
||||||
|
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
|
7
thirdparty/copas/tests/certs/rootB.sh
vendored
Executable file
7
thirdparty/copas/tests/certs/rootB.sh
vendored
Executable file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
openssl req -newkey rsa:1024 -sha1 -keyout rootBkey.pem -out rootBreq.pem -nodes -config ./rootB.cnf -days 365 -batch
|
||||||
|
|
||||||
|
openssl x509 -req -in rootBreq.pem -sha1 -extfile ./rootB.cnf -extensions v3_ca -signkey rootBkey.pem -out rootB.pem -days 365
|
||||||
|
|
||||||
|
openssl x509 -subject -issuer -noout -in rootB.pem
|
9
thirdparty/copas/tests/certs/serverA.bat
vendored
Normal file
9
thirdparty/copas/tests/certs/serverA.bat
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
rem #!/bin/sh
|
||||||
|
|
||||||
|
openssl req -newkey rsa:1024 -keyout serverAkey.pem -out serverAreq.pem -config ./serverA.cnf -nodes -days 365 -batch
|
||||||
|
|
||||||
|
openssl x509 -req -in serverAreq.pem -sha1 -extfile ./serverA.cnf -extensions usr_cert -CA rootA.pem -CAkey rootAkey.pem -CAcreateserial -out serverAcert.pem -days 365
|
||||||
|
|
||||||
|
copy serverAcert.pem + rootA.pem serverA.pem
|
||||||
|
|
||||||
|
openssl x509 -subject -issuer -noout -in serverA.pem
|
316
thirdparty/copas/tests/certs/serverA.cnf
vendored
Normal file
316
thirdparty/copas/tests/certs/serverA.cnf
vendored
Normal file
|
@ -0,0 +1,316 @@
|
||||||
|
#
|
||||||
|
# OpenSSL example configuration file.
|
||||||
|
# This is mostly being used for generation of certificate requests.
|
||||||
|
#
|
||||||
|
|
||||||
|
# This definition stops the following lines choking if HOME isn't
|
||||||
|
# defined.
|
||||||
|
HOME = .
|
||||||
|
RANDFILE = $ENV::HOME/.rnd
|
||||||
|
|
||||||
|
# Extra OBJECT IDENTIFIER info:
|
||||||
|
#oid_file = $ENV::HOME/.oid
|
||||||
|
oid_section = new_oids
|
||||||
|
|
||||||
|
# To use this configuration file with the "-extfile" option of the
|
||||||
|
# "openssl x509" utility, name here the section containing the
|
||||||
|
# X.509v3 extensions to use:
|
||||||
|
# extensions =
|
||||||
|
# (Alternatively, use a configuration file that has only
|
||||||
|
# X.509v3 extensions in its main [= default] section.)
|
||||||
|
|
||||||
|
[ new_oids ]
|
||||||
|
|
||||||
|
# We can add new OIDs in here for use by 'ca' and 'req'.
|
||||||
|
# Add a simple OID like this:
|
||||||
|
# testoid1=1.2.3.4
|
||||||
|
# Or use config file substitution like this:
|
||||||
|
# testoid2=${testoid1}.5.6
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ ca ]
|
||||||
|
default_ca = CA_default # The default ca section
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ CA_default ]
|
||||||
|
|
||||||
|
dir = ./demoCA # Where everything is kept
|
||||||
|
certs = $dir/certs # Where the issued certs are kept
|
||||||
|
crl_dir = $dir/crl # Where the issued crl are kept
|
||||||
|
database = $dir/index.txt # database index file.
|
||||||
|
#unique_subject = no # Set to 'no' to allow creation of
|
||||||
|
# several ctificates with same subject.
|
||||||
|
new_certs_dir = $dir/newcerts # default place for new certs.
|
||||||
|
|
||||||
|
certificate = $dir/cacert.pem # The CA certificate
|
||||||
|
serial = $dir/serial # The current serial number
|
||||||
|
crlnumber = $dir/crlnumber # the current crl number
|
||||||
|
# must be commented out to leave a V1 CRL
|
||||||
|
crl = $dir/crl.pem # The current CRL
|
||||||
|
private_key = $dir/private/cakey.pem # The private key
|
||||||
|
RANDFILE = $dir/private/.rand # private random number file
|
||||||
|
|
||||||
|
x509_extensions = usr_cert # The extensions to add to the cert
|
||||||
|
|
||||||
|
# Comment out the following two lines for the "traditional"
|
||||||
|
# (and highly broken) format.
|
||||||
|
name_opt = ca_default # Subject Name options
|
||||||
|
cert_opt = ca_default # Certificate field options
|
||||||
|
|
||||||
|
# Extension copying option: use with caution.
|
||||||
|
# copy_extensions = copy
|
||||||
|
|
||||||
|
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
|
||||||
|
# so this is commented out by default to leave a V1 CRL.
|
||||||
|
# crlnumber must also be commented out to leave a V1 CRL.
|
||||||
|
# crl_extensions = crl_ext
|
||||||
|
|
||||||
|
default_days = 365 # how long to certify for
|
||||||
|
default_crl_days= 30 # how long before next CRL
|
||||||
|
default_md = sha1 # which md to use.
|
||||||
|
preserve = no # keep passed DN ordering
|
||||||
|
|
||||||
|
# A few difference way of specifying how similar the request should look
|
||||||
|
# For type CA, the listed attributes must be the same, and the optional
|
||||||
|
# and supplied fields are just that :-)
|
||||||
|
policy = policy_match
|
||||||
|
|
||||||
|
# For the CA policy
|
||||||
|
[ policy_match ]
|
||||||
|
countryName = match
|
||||||
|
stateOrProvinceName = match
|
||||||
|
organizationName = match
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
# For the 'anything' policy
|
||||||
|
# At this point in time, you must list all acceptable 'object'
|
||||||
|
# types.
|
||||||
|
[ policy_anything ]
|
||||||
|
countryName = optional
|
||||||
|
stateOrProvinceName = optional
|
||||||
|
localityName = optional
|
||||||
|
organizationName = optional
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ req ]
|
||||||
|
default_bits = 1024
|
||||||
|
default_keyfile = privkey.pem
|
||||||
|
distinguished_name = req_distinguished_name
|
||||||
|
attributes = req_attributes
|
||||||
|
x509_extensions = v3_ca # The extensions to add to the self signed cert
|
||||||
|
|
||||||
|
# Passwords for private keys if not present they will be prompted for
|
||||||
|
# input_password = secret
|
||||||
|
# output_password = secret
|
||||||
|
|
||||||
|
# This sets a mask for permitted string types. There are several options.
|
||||||
|
# default: PrintableString, T61String, BMPString.
|
||||||
|
# pkix : PrintableString, BMPString.
|
||||||
|
# utf8only: only UTF8Strings.
|
||||||
|
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
|
||||||
|
# MASK:XXXX a literal mask value.
|
||||||
|
# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
|
||||||
|
# so use this option with caution!
|
||||||
|
string_mask = nombstr
|
||||||
|
|
||||||
|
# req_extensions = v3_req # The extensions to add to a certificate request
|
||||||
|
|
||||||
|
[ req_distinguished_name ]
|
||||||
|
countryName = Country Name (2 letter code)
|
||||||
|
countryName_default = BR
|
||||||
|
countryName_min = 2
|
||||||
|
countryName_max = 2
|
||||||
|
|
||||||
|
stateOrProvinceName = State or Province Name (full name)
|
||||||
|
stateOrProvinceName_default = Some-State
|
||||||
|
stateOrProvinceName_default = Espirito Santo
|
||||||
|
|
||||||
|
localityName = Locality Name (eg, city)
|
||||||
|
localityName_default = Santo Antonio do Canaa
|
||||||
|
|
||||||
|
0.organizationName = Organization Name (eg, company)
|
||||||
|
0.organizationName_default = Sao Tonico Ltda
|
||||||
|
|
||||||
|
# we can do this but it is not needed normally :-)
|
||||||
|
#1.organizationName = Second Organization Name (eg, company)
|
||||||
|
#1.organizationName_default = World Wide Web Pty Ltd
|
||||||
|
|
||||||
|
organizationalUnitName = Organizational Unit Name (eg, section)
|
||||||
|
organizationalUnitName_default = Department of Computer Science
|
||||||
|
|
||||||
|
commonName = Common Name (eg, YOUR name)
|
||||||
|
commonName_default = Server A
|
||||||
|
commonName_max = 64
|
||||||
|
|
||||||
|
emailAddress = Email Address
|
||||||
|
emailAddress_max = 64
|
||||||
|
|
||||||
|
# SET-ex3 = SET extension number 3
|
||||||
|
|
||||||
|
[ req_attributes ]
|
||||||
|
challengePassword = A challenge password
|
||||||
|
challengePassword_min = 4
|
||||||
|
challengePassword_max = 20
|
||||||
|
|
||||||
|
unstructuredName = An optional company name
|
||||||
|
|
||||||
|
[ usr_cert ]
|
||||||
|
|
||||||
|
# These extensions are added when 'ca' signs a request.
|
||||||
|
|
||||||
|
# This goes against PKIX guidelines but some CAs do it and some software
|
||||||
|
# requires this to avoid interpreting an end user certificate as a CA.
|
||||||
|
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
|
||||||
|
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||||
|
# the certificate can be used for anything *except* object signing.
|
||||||
|
|
||||||
|
# This is OK for an SSL server.
|
||||||
|
nsCertType = server
|
||||||
|
|
||||||
|
# For an object signing certificate this would be used.
|
||||||
|
# nsCertType = objsign
|
||||||
|
|
||||||
|
# For normal client use this is typical
|
||||||
|
# nsCertType = client, email
|
||||||
|
|
||||||
|
# and for everything including object signing:
|
||||||
|
# nsCertType = client, email, objsign
|
||||||
|
|
||||||
|
# This is typical in keyUsage for a client certificate.
|
||||||
|
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
# This will be displayed in Netscape's comment listbox.
|
||||||
|
nsComment = "OpenSSL Generated Certificate"
|
||||||
|
|
||||||
|
# PKIX recommendations harmless if included in all certificates.
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer
|
||||||
|
|
||||||
|
# This stuff is for subjectAltName and issuerAltname.
|
||||||
|
# Import the email address.
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# An alternative to produce certificates that aren't
|
||||||
|
# deprecated according to PKIX.
|
||||||
|
# subjectAltName=email:move
|
||||||
|
|
||||||
|
# Copy subject details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||||
|
#nsBaseUrl
|
||||||
|
#nsRevocationUrl
|
||||||
|
#nsRenewalUrl
|
||||||
|
#nsCaPolicyUrl
|
||||||
|
#nsSslServerName
|
||||||
|
|
||||||
|
[ v3_req ]
|
||||||
|
|
||||||
|
# Extensions to add to a certificate request
|
||||||
|
|
||||||
|
basicConstraints = CA:FALSE
|
||||||
|
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
[ v3_ca ]
|
||||||
|
|
||||||
|
|
||||||
|
# Extensions for a typical CA
|
||||||
|
|
||||||
|
|
||||||
|
# PKIX recommendation.
|
||||||
|
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
|
||||||
|
# This is what PKIX recommends but some broken software chokes on critical
|
||||||
|
# extensions.
|
||||||
|
#basicConstraints = critical,CA:true
|
||||||
|
# So we do this instead.
|
||||||
|
basicConstraints = CA:true
|
||||||
|
|
||||||
|
# Key usage: this is typical for a CA certificate. However since it will
|
||||||
|
# prevent it being used as an test self-signed certificate it is best
|
||||||
|
# left out by default.
|
||||||
|
# keyUsage = cRLSign, keyCertSign
|
||||||
|
|
||||||
|
# Some might want this also
|
||||||
|
# nsCertType = sslCA, emailCA
|
||||||
|
|
||||||
|
# Include email address in subject alt name: another PKIX recommendation
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# Copy issuer details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
# DER hex encoding of an extension: beware experts only!
|
||||||
|
# obj=DER:02:03
|
||||||
|
# Where 'obj' is a standard or added object
|
||||||
|
# You can even override a supported extension:
|
||||||
|
# basicConstraints= critical, DER:30:03:01:01:FF
|
||||||
|
|
||||||
|
[ crl_ext ]
|
||||||
|
|
||||||
|
# CRL extensions.
|
||||||
|
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
|
||||||
|
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
|
||||||
|
[ proxy_cert_ext ]
|
||||||
|
# These extensions should be added when creating a proxy certificate
|
||||||
|
|
||||||
|
# This goes against PKIX guidelines but some CAs do it and some software
|
||||||
|
# requires this to avoid interpreting an end user certificate as a CA.
|
||||||
|
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
|
||||||
|
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||||
|
# the certificate can be used for anything *except* object signing.
|
||||||
|
|
||||||
|
# This is OK for an SSL server.
|
||||||
|
# nsCertType = server
|
||||||
|
|
||||||
|
# For an object signing certificate this would be used.
|
||||||
|
# nsCertType = objsign
|
||||||
|
|
||||||
|
# For normal client use this is typical
|
||||||
|
# nsCertType = client, email
|
||||||
|
|
||||||
|
# and for everything including object signing:
|
||||||
|
# nsCertType = client, email, objsign
|
||||||
|
|
||||||
|
# This is typical in keyUsage for a client certificate.
|
||||||
|
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
# This will be displayed in Netscape's comment listbox.
|
||||||
|
nsComment = "OpenSSL Generated Certificate"
|
||||||
|
|
||||||
|
# PKIX recommendations harmless if included in all certificates.
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer:always
|
||||||
|
|
||||||
|
# This stuff is for subjectAltName and issuerAltname.
|
||||||
|
# Import the email address.
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# An alternative to produce certificates that aren't
|
||||||
|
# deprecated according to PKIX.
|
||||||
|
# subjectAltName=email:move
|
||||||
|
|
||||||
|
# Copy subject details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||||
|
#nsBaseUrl
|
||||||
|
#nsRevocationUrl
|
||||||
|
#nsRenewalUrl
|
||||||
|
#nsCaPolicyUrl
|
||||||
|
#nsSslServerName
|
||||||
|
|
||||||
|
# This really needs to be in place for it to be a proxy certificate.
|
||||||
|
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
|
12
thirdparty/copas/tests/certs/serverA.sh
vendored
Executable file
12
thirdparty/copas/tests/certs/serverA.sh
vendored
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
openssl req -newkey rsa:1024 -keyout serverAkey.pem -out serverAreq.pem \
|
||||||
|
-config ./serverA.cnf -nodes -days 365 -batch
|
||||||
|
|
||||||
|
openssl x509 -req -in serverAreq.pem -sha1 -extfile ./serverA.cnf \
|
||||||
|
-extensions usr_cert -CA rootA.pem -CAkey rootAkey.pem -CAcreateserial \
|
||||||
|
-out serverAcert.pem -days 365
|
||||||
|
|
||||||
|
cat serverAcert.pem rootA.pem > serverA.pem
|
||||||
|
|
||||||
|
openssl x509 -subject -issuer -noout -in serverA.pem
|
9
thirdparty/copas/tests/certs/serverB.bat
vendored
Normal file
9
thirdparty/copas/tests/certs/serverB.bat
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
rem #!/bin/sh
|
||||||
|
|
||||||
|
openssl req -newkey rsa:1024 -keyout serverBkey.pem -out serverBreq.pem -config ./serverB.cnf -nodes -days 365 -batch
|
||||||
|
|
||||||
|
openssl x509 -req -in serverBreq.pem -sha1 -extfile ./serverB.cnf -extensions usr_cert -CA rootB.pem -CAkey rootBkey.pem -CAcreateserial -out serverBcert.pem -days 365
|
||||||
|
|
||||||
|
copy serverBcert.pem + rootB.pem serverB.pem
|
||||||
|
|
||||||
|
openssl x509 -subject -issuer -noout -in serverB.pem
|
316
thirdparty/copas/tests/certs/serverB.cnf
vendored
Normal file
316
thirdparty/copas/tests/certs/serverB.cnf
vendored
Normal file
|
@ -0,0 +1,316 @@
|
||||||
|
#
|
||||||
|
# OpenSSL example configuration file.
|
||||||
|
# This is mostly being used for generation of certificate requests.
|
||||||
|
#
|
||||||
|
|
||||||
|
# This definition stops the following lines choking if HOME isn't
|
||||||
|
# defined.
|
||||||
|
HOME = .
|
||||||
|
RANDFILE = $ENV::HOME/.rnd
|
||||||
|
|
||||||
|
# Extra OBJECT IDENTIFIER info:
|
||||||
|
#oid_file = $ENV::HOME/.oid
|
||||||
|
oid_section = new_oids
|
||||||
|
|
||||||
|
# To use this configuration file with the "-extfile" option of the
|
||||||
|
# "openssl x509" utility, name here the section containing the
|
||||||
|
# X.509v3 extensions to use:
|
||||||
|
# extensions =
|
||||||
|
# (Alternatively, use a configuration file that has only
|
||||||
|
# X.509v3 extensions in its main [= default] section.)
|
||||||
|
|
||||||
|
[ new_oids ]
|
||||||
|
|
||||||
|
# We can add new OIDs in here for use by 'ca' and 'req'.
|
||||||
|
# Add a simple OID like this:
|
||||||
|
# testoid1=1.2.3.4
|
||||||
|
# Or use config file substitution like this:
|
||||||
|
# testoid2=${testoid1}.5.6
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ ca ]
|
||||||
|
default_ca = CA_default # The default ca section
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ CA_default ]
|
||||||
|
|
||||||
|
dir = ./demoCA # Where everything is kept
|
||||||
|
certs = $dir/certs # Where the issued certs are kept
|
||||||
|
crl_dir = $dir/crl # Where the issued crl are kept
|
||||||
|
database = $dir/index.txt # database index file.
|
||||||
|
#unique_subject = no # Set to 'no' to allow creation of
|
||||||
|
# several ctificates with same subject.
|
||||||
|
new_certs_dir = $dir/newcerts # default place for new certs.
|
||||||
|
|
||||||
|
certificate = $dir/cacert.pem # The CA certificate
|
||||||
|
serial = $dir/serial # The current serial number
|
||||||
|
crlnumber = $dir/crlnumber # the current crl number
|
||||||
|
# must be commented out to leave a V1 CRL
|
||||||
|
crl = $dir/crl.pem # The current CRL
|
||||||
|
private_key = $dir/private/cakey.pem # The private key
|
||||||
|
RANDFILE = $dir/private/.rand # private random number file
|
||||||
|
|
||||||
|
x509_extensions = usr_cert # The extensions to add to the cert
|
||||||
|
|
||||||
|
# Comment out the following two lines for the "traditional"
|
||||||
|
# (and highly broken) format.
|
||||||
|
name_opt = ca_default # Subject Name options
|
||||||
|
cert_opt = ca_default # Certificate field options
|
||||||
|
|
||||||
|
# Extension copying option: use with caution.
|
||||||
|
# copy_extensions = copy
|
||||||
|
|
||||||
|
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
|
||||||
|
# so this is commented out by default to leave a V1 CRL.
|
||||||
|
# crlnumber must also be commented out to leave a V1 CRL.
|
||||||
|
# crl_extensions = crl_ext
|
||||||
|
|
||||||
|
default_days = 365 # how long to certify for
|
||||||
|
default_crl_days= 30 # how long before next CRL
|
||||||
|
default_md = sha1 # which md to use.
|
||||||
|
preserve = no # keep passed DN ordering
|
||||||
|
|
||||||
|
# A few difference way of specifying how similar the request should look
|
||||||
|
# For type CA, the listed attributes must be the same, and the optional
|
||||||
|
# and supplied fields are just that :-)
|
||||||
|
policy = policy_match
|
||||||
|
|
||||||
|
# For the CA policy
|
||||||
|
[ policy_match ]
|
||||||
|
countryName = match
|
||||||
|
stateOrProvinceName = match
|
||||||
|
organizationName = match
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
# For the 'anything' policy
|
||||||
|
# At this point in time, you must list all acceptable 'object'
|
||||||
|
# types.
|
||||||
|
[ policy_anything ]
|
||||||
|
countryName = optional
|
||||||
|
stateOrProvinceName = optional
|
||||||
|
localityName = optional
|
||||||
|
organizationName = optional
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ req ]
|
||||||
|
default_bits = 1024
|
||||||
|
default_keyfile = privkey.pem
|
||||||
|
distinguished_name = req_distinguished_name
|
||||||
|
attributes = req_attributes
|
||||||
|
x509_extensions = v3_ca # The extensions to add to the self signed cert
|
||||||
|
|
||||||
|
# Passwords for private keys if not present they will be prompted for
|
||||||
|
# input_password = secret
|
||||||
|
# output_password = secret
|
||||||
|
|
||||||
|
# This sets a mask for permitted string types. There are several options.
|
||||||
|
# default: PrintableString, T61String, BMPString.
|
||||||
|
# pkix : PrintableString, BMPString.
|
||||||
|
# utf8only: only UTF8Strings.
|
||||||
|
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
|
||||||
|
# MASK:XXXX a literal mask value.
|
||||||
|
# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
|
||||||
|
# so use this option with caution!
|
||||||
|
string_mask = nombstr
|
||||||
|
|
||||||
|
# req_extensions = v3_req # The extensions to add to a certificate request
|
||||||
|
|
||||||
|
[ req_distinguished_name ]
|
||||||
|
countryName = Country Name (2 letter code)
|
||||||
|
countryName_default = BR
|
||||||
|
countryName_min = 2
|
||||||
|
countryName_max = 2
|
||||||
|
|
||||||
|
stateOrProvinceName = State or Province Name (full name)
|
||||||
|
stateOrProvinceName_default = Some-State
|
||||||
|
stateOrProvinceName_default = Espirito Santo
|
||||||
|
|
||||||
|
localityName = Locality Name (eg, city)
|
||||||
|
localityName_default = Santo Antonio do Canaa
|
||||||
|
|
||||||
|
0.organizationName = Organization Name (eg, company)
|
||||||
|
0.organizationName_default = Sao Tonico Ltda
|
||||||
|
|
||||||
|
# we can do this but it is not needed normally :-)
|
||||||
|
#1.organizationName = Second Organization Name (eg, company)
|
||||||
|
#1.organizationName_default = World Wide Web Pty Ltd
|
||||||
|
|
||||||
|
organizationalUnitName = Organizational Unit Name (eg, section)
|
||||||
|
organizationalUnitName_default = Department of Computer Science
|
||||||
|
|
||||||
|
commonName = Common Name (eg, YOUR name)
|
||||||
|
commonName_default = Server B
|
||||||
|
commonName_max = 64
|
||||||
|
|
||||||
|
emailAddress = Email Address
|
||||||
|
emailAddress_max = 64
|
||||||
|
|
||||||
|
# SET-ex3 = SET extension number 3
|
||||||
|
|
||||||
|
[ req_attributes ]
|
||||||
|
challengePassword = A challenge password
|
||||||
|
challengePassword_min = 4
|
||||||
|
challengePassword_max = 20
|
||||||
|
|
||||||
|
unstructuredName = An optional company name
|
||||||
|
|
||||||
|
[ usr_cert ]
|
||||||
|
|
||||||
|
# These extensions are added when 'ca' signs a request.
|
||||||
|
|
||||||
|
# This goes against PKIX guidelines but some CAs do it and some software
|
||||||
|
# requires this to avoid interpreting an end user certificate as a CA.
|
||||||
|
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
|
||||||
|
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||||
|
# the certificate can be used for anything *except* object signing.
|
||||||
|
|
||||||
|
# This is OK for an SSL server.
|
||||||
|
nsCertType = server
|
||||||
|
|
||||||
|
# For an object signing certificate this would be used.
|
||||||
|
# nsCertType = objsign
|
||||||
|
|
||||||
|
# For normal client use this is typical
|
||||||
|
# nsCertType = client, email
|
||||||
|
|
||||||
|
# and for everything including object signing:
|
||||||
|
# nsCertType = client, email, objsign
|
||||||
|
|
||||||
|
# This is typical in keyUsage for a client certificate.
|
||||||
|
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
# This will be displayed in Netscape's comment listbox.
|
||||||
|
nsComment = "OpenSSL Generated Certificate"
|
||||||
|
|
||||||
|
# PKIX recommendations harmless if included in all certificates.
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer
|
||||||
|
|
||||||
|
# This stuff is for subjectAltName and issuerAltname.
|
||||||
|
# Import the email address.
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# An alternative to produce certificates that aren't
|
||||||
|
# deprecated according to PKIX.
|
||||||
|
# subjectAltName=email:move
|
||||||
|
|
||||||
|
# Copy subject details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||||
|
#nsBaseUrl
|
||||||
|
#nsRevocationUrl
|
||||||
|
#nsRenewalUrl
|
||||||
|
#nsCaPolicyUrl
|
||||||
|
#nsSslServerName
|
||||||
|
|
||||||
|
[ v3_req ]
|
||||||
|
|
||||||
|
# Extensions to add to a certificate request
|
||||||
|
|
||||||
|
basicConstraints = CA:FALSE
|
||||||
|
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
[ v3_ca ]
|
||||||
|
|
||||||
|
|
||||||
|
# Extensions for a typical CA
|
||||||
|
|
||||||
|
|
||||||
|
# PKIX recommendation.
|
||||||
|
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
|
||||||
|
# This is what PKIX recommends but some broken software chokes on critical
|
||||||
|
# extensions.
|
||||||
|
#basicConstraints = critical,CA:true
|
||||||
|
# So we do this instead.
|
||||||
|
basicConstraints = CA:true
|
||||||
|
|
||||||
|
# Key usage: this is typical for a CA certificate. However since it will
|
||||||
|
# prevent it being used as an test self-signed certificate it is best
|
||||||
|
# left out by default.
|
||||||
|
# keyUsage = cRLSign, keyCertSign
|
||||||
|
|
||||||
|
# Some might want this also
|
||||||
|
# nsCertType = sslCA, emailCA
|
||||||
|
|
||||||
|
# Include email address in subject alt name: another PKIX recommendation
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# Copy issuer details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
# DER hex encoding of an extension: beware experts only!
|
||||||
|
# obj=DER:02:03
|
||||||
|
# Where 'obj' is a standard or added object
|
||||||
|
# You can even override a supported extension:
|
||||||
|
# basicConstraints= critical, DER:30:03:01:01:FF
|
||||||
|
|
||||||
|
[ crl_ext ]
|
||||||
|
|
||||||
|
# CRL extensions.
|
||||||
|
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
|
||||||
|
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
|
||||||
|
[ proxy_cert_ext ]
|
||||||
|
# These extensions should be added when creating a proxy certificate
|
||||||
|
|
||||||
|
# This goes against PKIX guidelines but some CAs do it and some software
|
||||||
|
# requires this to avoid interpreting an end user certificate as a CA.
|
||||||
|
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
|
||||||
|
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||||
|
# the certificate can be used for anything *except* object signing.
|
||||||
|
|
||||||
|
# This is OK for an SSL server.
|
||||||
|
# nsCertType = server
|
||||||
|
|
||||||
|
# For an object signing certificate this would be used.
|
||||||
|
# nsCertType = objsign
|
||||||
|
|
||||||
|
# For normal client use this is typical
|
||||||
|
# nsCertType = client, email
|
||||||
|
|
||||||
|
# and for everything including object signing:
|
||||||
|
# nsCertType = client, email, objsign
|
||||||
|
|
||||||
|
# This is typical in keyUsage for a client certificate.
|
||||||
|
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
# This will be displayed in Netscape's comment listbox.
|
||||||
|
nsComment = "OpenSSL Generated Certificate"
|
||||||
|
|
||||||
|
# PKIX recommendations harmless if included in all certificates.
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer:always
|
||||||
|
|
||||||
|
# This stuff is for subjectAltName and issuerAltname.
|
||||||
|
# Import the email address.
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# An alternative to produce certificates that aren't
|
||||||
|
# deprecated according to PKIX.
|
||||||
|
# subjectAltName=email:move
|
||||||
|
|
||||||
|
# Copy subject details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||||
|
#nsBaseUrl
|
||||||
|
#nsRevocationUrl
|
||||||
|
#nsRenewalUrl
|
||||||
|
#nsCaPolicyUrl
|
||||||
|
#nsSslServerName
|
||||||
|
|
||||||
|
# This really needs to be in place for it to be a proxy certificate.
|
||||||
|
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
|
12
thirdparty/copas/tests/certs/serverB.sh
vendored
Executable file
12
thirdparty/copas/tests/certs/serverB.sh
vendored
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
openssl req -newkey rsa:1024 -keyout serverBkey.pem -out serverBreq.pem \
|
||||||
|
-config ./serverB.cnf -nodes -days 365 -batch
|
||||||
|
|
||||||
|
openssl x509 -req -in serverBreq.pem -sha1 -extfile ./serverB.cnf \
|
||||||
|
-extensions usr_cert -CA rootB.pem -CAkey rootBkey.pem -CAcreateserial \
|
||||||
|
-out serverBcert.pem -days 365
|
||||||
|
|
||||||
|
cat serverBcert.pem rootB.pem > serverB.pem
|
||||||
|
|
||||||
|
openssl x509 -subject -issuer -noout -in serverB.pem
|
75
thirdparty/copas/tests/close.lua
vendored
Normal file
75
thirdparty/copas/tests/close.lua
vendored
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
-- when a socket is being closed, while another coroutine
|
||||||
|
-- is reading on it, the `select` call does not return an event on that
|
||||||
|
-- socket. Hence the loop keeps running until the watch-dog kicks-in, reads
|
||||||
|
-- on the socket, and that returns the final "closed" error to the reading
|
||||||
|
-- coroutine.
|
||||||
|
--
|
||||||
|
-- when a socket is closed, any read/write operation should return immediately
|
||||||
|
-- with a "closed" error.
|
||||||
|
|
||||||
|
local copas = require "copas"
|
||||||
|
local socket = require "socket"
|
||||||
|
|
||||||
|
copas.loop(function()
|
||||||
|
|
||||||
|
local client_socket
|
||||||
|
local close_time
|
||||||
|
local send_end_time
|
||||||
|
local receive_end_time
|
||||||
|
|
||||||
|
print "------------- starting close test ---------------"
|
||||||
|
|
||||||
|
local function check_exit()
|
||||||
|
if receive_end_time and send_end_time then
|
||||||
|
-- both set, so we're done
|
||||||
|
print "success!"
|
||||||
|
os.exit(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
do -- set up a server that accepts but doesn't read or write anything
|
||||||
|
local server = socket.bind("localhost", 20000)
|
||||||
|
|
||||||
|
copas.addserver(server, copas.handler(function(conn_skt)
|
||||||
|
-- client connected, we're not doing anything, let the client
|
||||||
|
-- wait in the read/write queues
|
||||||
|
copas.pause(2)
|
||||||
|
-- now we're closing the connecting_socket
|
||||||
|
close_time = socket.gettime()
|
||||||
|
print("closing client socket now, client receive and send operation should immediately error out now")
|
||||||
|
client_socket:close()
|
||||||
|
|
||||||
|
copas.pause(10)
|
||||||
|
conn_skt:close()
|
||||||
|
copas.removeserver(server)
|
||||||
|
print "timeout, test failed"
|
||||||
|
os.exit(1)
|
||||||
|
end))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
do -- create a client that connect to the server
|
||||||
|
client_socket = copas.wrap(socket.connect("localhost", 20000))
|
||||||
|
|
||||||
|
copas.addthread(function()
|
||||||
|
local data, err = client_socket:receive(1)
|
||||||
|
print("receive result: ", tostring(data), tostring(err))
|
||||||
|
receive_end_time = socket.gettime()
|
||||||
|
print("receive took: ", receive_end_time - close_time)
|
||||||
|
check_exit()
|
||||||
|
end)
|
||||||
|
|
||||||
|
copas.addthread(function()
|
||||||
|
local ok, err = true, nil
|
||||||
|
while ok do -- loop to fill any buffers, until we get stuck
|
||||||
|
ok, err = client_socket:send(("hello world"):rep(100))
|
||||||
|
end
|
||||||
|
print("send result: ", tostring(ok), tostring(err))
|
||||||
|
send_end_time = socket.gettime()
|
||||||
|
print("send took: ", send_end_time - close_time)
|
||||||
|
check_exit()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
end)
|
36
thirdparty/copas/tests/connecttwice.lua
vendored
Normal file
36
thirdparty/copas/tests/connecttwice.lua
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
-- test reconnecting a socket, should return an error "already connected"
|
||||||
|
-- test based on Windows behaviour, see comments in `copas.connect()` function
|
||||||
|
local copas = require("copas")
|
||||||
|
local socket = require("socket")
|
||||||
|
|
||||||
|
local skt = copas.wrap(socket.tcp())
|
||||||
|
local done = false
|
||||||
|
|
||||||
|
copas.addthread(function()
|
||||||
|
print("First try... (should succeed)")
|
||||||
|
local ok, err = skt:connect("google.com", 80)
|
||||||
|
if ok then
|
||||||
|
print("Success")
|
||||||
|
else
|
||||||
|
print("Failed: "..err)
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
print("\nSecond try... (should error as already connected)")
|
||||||
|
ok, err = skt:connect("thijsschreijer.nl", 80)
|
||||||
|
if ok then
|
||||||
|
print("Unexpected success")
|
||||||
|
os.exit(1)
|
||||||
|
else
|
||||||
|
print("Failed: "..err)
|
||||||
|
end
|
||||||
|
|
||||||
|
done = true
|
||||||
|
end)
|
||||||
|
|
||||||
|
copas.loop()
|
||||||
|
|
||||||
|
if not done then
|
||||||
|
print("Loop completed with test not finished")
|
||||||
|
os.exit(1)
|
||||||
|
end
|
160
thirdparty/copas/tests/errhandlers.lua
vendored
Normal file
160
thirdparty/copas/tests/errhandlers.lua
vendored
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
-- Tests Copas socket timeouts
|
||||||
|
--
|
||||||
|
-- Run the test file, it should exit successfully without hanging.
|
||||||
|
|
||||||
|
-- make sure we are pointing to the local copas first
|
||||||
|
package.path = string.format("../src/?.lua;%s", package.path)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--local platform = "unix"
|
||||||
|
--if package.config:sub(1,1) == "\\" then
|
||||||
|
-- platform = "windows"
|
||||||
|
--elseif io.popen("uname", "r"):read("*a"):find("Darwin") then
|
||||||
|
-- platform = "mac"
|
||||||
|
--end
|
||||||
|
--print("Testing platform: " .. platform)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
local copas = require("copas")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
local tests = {}
|
||||||
|
|
||||||
|
if _VERSION ~= "Lua 5.1" then
|
||||||
|
-- do not run these for Lua 5.1 since it has a different stacktrace
|
||||||
|
|
||||||
|
tests.default_properly_formats_coro_errors = function()
|
||||||
|
local old_print = print
|
||||||
|
local msg
|
||||||
|
print = function(errmsg) --luacheck: ignore
|
||||||
|
msg = errmsg
|
||||||
|
--old_print(msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
copas.loop(function()
|
||||||
|
local f = function()
|
||||||
|
error("hi there!")
|
||||||
|
end
|
||||||
|
f()
|
||||||
|
end)
|
||||||
|
|
||||||
|
print = old_print --luacheck: ignore
|
||||||
|
|
||||||
|
assert(msg:find("errhandlers%.lua:%d-: hi there! %(coroutine: copas_initializer, socket: nil%)"), "got:\n"..msg)
|
||||||
|
assert(msg:find("stack traceback:.+errhandlers%.lua"), "got:\n"..msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
tests.default_properly_formats_timerwheel_errors = function()
|
||||||
|
local old_print = print
|
||||||
|
local msg
|
||||||
|
print = function(errmsg) --luacheck: ignore
|
||||||
|
msg = errmsg
|
||||||
|
--old_print(msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
copas.loop(function()
|
||||||
|
copas.timeout(0.01, function(co)
|
||||||
|
local f = function()
|
||||||
|
error("hi there!")
|
||||||
|
end
|
||||||
|
f()
|
||||||
|
end)
|
||||||
|
copas.pause(1)
|
||||||
|
end)
|
||||||
|
|
||||||
|
print = old_print --luacheck: ignore
|
||||||
|
|
||||||
|
assert(msg:find("errhandlers%.lua:%d-: hi there! %(coroutine: copas_core_timer, socket: nil%)"), "got:\n"..msg)
|
||||||
|
assert(msg:find("stack traceback:.+errhandlers%.lua"), "got:\n"..msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
tests.yielding_from_user_code_fails = function()
|
||||||
|
local old_print = print
|
||||||
|
local msg
|
||||||
|
print = function(errmsg) --luacheck: ignore
|
||||||
|
msg = errmsg
|
||||||
|
--old_print(msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
copas.loop(function()
|
||||||
|
copas.pause(1)
|
||||||
|
coroutine.yield() -- directly yield to Copas
|
||||||
|
end)
|
||||||
|
|
||||||
|
print = old_print --luacheck: ignore
|
||||||
|
|
||||||
|
assert(msg:find("coroutine.yield was called without a resume first, user-code cannot yield to Copas", 1, true), "got:\n"..msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
tests.handler_gets_called_if_set = function()
|
||||||
|
local call_count = 0
|
||||||
|
copas.loop(function()
|
||||||
|
copas.setErrorHandler(function() call_count = call_count + 1 end)
|
||||||
|
|
||||||
|
error("end of the world!")
|
||||||
|
end)
|
||||||
|
|
||||||
|
assert(call_count == 1, "expected callcount 1, got: " .. tostring(call_count))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
tests.default_handler_gets_called_if_set = function()
|
||||||
|
local call_count = 0
|
||||||
|
copas.setErrorHandler(function() call_count = call_count + 10 end, true)
|
||||||
|
copas.loop(function()
|
||||||
|
|
||||||
|
error("end of the world!")
|
||||||
|
end)
|
||||||
|
|
||||||
|
assert(call_count == 10, "expected callcount 10, got: " .. tostring(call_count))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
tests.default_handler_doesnt_get_called_if_overridden = function()
|
||||||
|
local call_count = 0
|
||||||
|
copas.setErrorHandler(function() call_count = call_count + 10 end, true)
|
||||||
|
copas.loop(function()
|
||||||
|
copas.setErrorHandler(function() call_count = call_count + 1 end)
|
||||||
|
|
||||||
|
error("end of the world!")
|
||||||
|
end)
|
||||||
|
|
||||||
|
assert(call_count == 1, "expected callcount 1, got: " .. tostring(call_count))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
tests.timerwheel_callbacks_call_the_default_error_handler = function()
|
||||||
|
local call_count = 0
|
||||||
|
copas.setErrorHandler(function() call_count = call_count - 10 end, true)
|
||||||
|
copas.loop(function()
|
||||||
|
copas.timeout(0.01, function(co) error("hi there!") end)
|
||||||
|
copas.pause(1)
|
||||||
|
end)
|
||||||
|
|
||||||
|
assert(call_count == -10, "expected callcount -10, got: " .. tostring(call_count))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- test "framework"
|
||||||
|
for name, test in pairs(tests) do
|
||||||
|
-- reload copas, to clear default err handlers
|
||||||
|
package.loaded.copas = nil
|
||||||
|
copas = require "copas"
|
||||||
|
|
||||||
|
print("testing: "..tostring(name))
|
||||||
|
local status, err = pcall(test)
|
||||||
|
if not status then
|
||||||
|
error(err)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
print("[✓] all tests completed successuly")
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue