├── .gitignore ├── .gitmodules ├── 3rd ├── lpeg │ ├── HISTORY │ ├── lpcap.c │ ├── lpcap.h │ ├── lpcode.c │ ├── lpcode.h │ ├── lpeg-128.gif │ ├── lpeg.html │ ├── lpprint.c │ ├── lpprint.h │ ├── lptree.c │ ├── lptree.h │ ├── lptypes.h │ ├── lpvm.c │ ├── lpvm.h │ ├── makefile │ ├── re.html │ ├── re.lua │ └── test.lua ├── lua-cjson │ ├── LICENSE │ ├── dtoa.c │ ├── dtoa_config.h │ ├── fpconv.c │ ├── fpconv.h │ ├── g_fmt.c │ ├── lua_cjson.c │ ├── strbuf.c │ └── strbuf.h ├── lua-md5 │ ├── README │ ├── compat-5.2.c │ ├── compat-5.2.h │ ├── md5.c │ ├── md5.h │ └── md5lib.c └── lua │ ├── Makefile │ ├── README │ ├── lapi.c │ ├── lapi.h │ ├── lauxlib.c │ ├── lauxlib.h │ ├── lbaselib.c │ ├── lcode.c │ ├── lcode.h │ ├── lcorolib.c │ ├── lctype.c │ ├── lctype.h │ ├── ldblib.c │ ├── ldebug.c │ ├── ldebug.h │ ├── ldo.c │ ├── ldo.h │ ├── ldump.c │ ├── lfunc.c │ ├── lfunc.h │ ├── lgc.c │ ├── lgc.h │ ├── linit.c │ ├── liolib.c │ ├── ljumptab.h │ ├── llex.c │ ├── llex.h │ ├── llimits.h │ ├── lmathlib.c │ ├── lmem.c │ ├── lmem.h │ ├── loadlib.c │ ├── lobject.c │ ├── lobject.h │ ├── lopcodes.c │ ├── lopcodes.h │ ├── lopnames.h │ ├── loslib.c │ ├── lparser.c │ ├── lparser.h │ ├── lprefix.h │ ├── lstate.c │ ├── lstate.h │ ├── lstring.c │ ├── lstring.h │ ├── lstrlib.c │ ├── ltable.c │ ├── ltable.h │ ├── ltablib.c │ ├── ltm.c │ ├── ltm.h │ ├── lua.c │ ├── lua.h │ ├── lua.hpp │ ├── luac.c │ ├── luaconf.h │ ├── lualib.h │ ├── lundump.c │ ├── lundump.h │ ├── lutf8lib.c │ ├── lvm.c │ ├── lvm.h │ ├── lzio.c │ └── lzio.h ├── HISTORY.md ├── LICENSE ├── Makefile ├── README.md ├── examples ├── abort.lua ├── agent.lua ├── checkdeadloop.lua ├── client.lua ├── cluster1.lua ├── cluster2.lua ├── clustername.lua ├── config ├── config.c1 ├── config.c2 ├── config.login ├── config.mc ├── config.mongodb ├── config.mysql ├── config.path ├── config.userlog ├── config_log ├── config_vsc ├── globallog.lua ├── injectlaunch.lua ├── login │ ├── client.lua │ ├── gated.lua │ ├── logind.lua │ ├── main.lua │ └── msgagent.lua ├── main.lua ├── main_log.lua ├── main_mongodb.lua ├── main_mysql.lua ├── preload.lua ├── proto.lua ├── protoloader.lua ├── share.lua ├── simpledb.lua ├── simplemonitor.lua ├── simpleweb.lua ├── simplewebsocket.lua ├── userlog.lua └── watchdog.lua ├── lualib-src ├── lsha1.c ├── ltls.c ├── lua-bson.c ├── lua-clientsocket.c ├── lua-cluster.c ├── lua-crypt.c ├── lua-datasheet.c ├── lua-debugchannel.c ├── lua-memory.c ├── lua-mongo.c ├── lua-multicast.c ├── lua-netpack.c ├── lua-seri.c ├── lua-seri.h ├── lua-sharedata.c ├── lua-sharetable.c ├── lua-skynet.c ├── lua-socket.c ├── lua-stm.c ├── lua-vscdebugaux.c └── sproto │ ├── README │ ├── README.md │ ├── lsproto.c │ ├── msvcint.h │ ├── sproto.c │ └── sproto.h ├── lualib ├── compat10 │ ├── cluster.lua │ ├── crypt.lua │ ├── datacenter.lua │ ├── dns.lua │ ├── memory.lua │ ├── mongo.lua │ ├── mqueue.lua │ ├── multicast.lua │ ├── mysql.lua │ ├── netpack.lua │ ├── profile.lua │ ├── redis.lua │ ├── sharedata.lua │ ├── sharemap.lua │ ├── snax.lua │ ├── socket.lua │ ├── socketchannel.lua │ ├── socketdriver.lua │ └── stm.lua ├── http │ ├── httpc.lua │ ├── httpd.lua │ ├── internal.lua │ ├── sockethelper.lua │ ├── tlshelper.lua │ ├── url.lua │ └── websocket.lua ├── loader.lua ├── md5.lua ├── skynet.lua ├── skynet │ ├── cluster.lua │ ├── coroutine.lua │ ├── datacenter.lua │ ├── datasheet │ │ ├── builder.lua │ │ ├── dump.lua │ │ └── init.lua │ ├── db │ │ ├── mongo.lua │ │ ├── mysql.lua │ │ ├── redis.lua │ │ └── redis │ │ │ ├── cluster.lua │ │ │ └── crc16.lua │ ├── debug.lua │ ├── dns.lua │ ├── harbor.lua │ ├── inject.lua │ ├── injectcode.lua │ ├── manager.lua │ ├── mqueue.lua │ ├── multicast.lua │ ├── queue.lua │ ├── remotedebug.lua │ ├── require.lua │ ├── service.lua │ ├── sharedata.lua │ ├── sharedata │ │ └── corelib.lua │ ├── sharemap.lua │ ├── sharetable.lua │ ├── snax.lua │ ├── socket.lua │ ├── socketchannel.lua │ └── vscdebug.lua ├── snax │ ├── gateserver.lua │ ├── hotfix.lua │ ├── interface.lua │ ├── loginserver.lua │ └── msgserver.lua ├── sproto.lua ├── sprotoloader.lua └── sprotoparser.lua ├── platform.mk ├── service-src ├── databuffer.h ├── hashid.h ├── service_gate.c ├── service_harbor.c ├── service_logger.c └── service_snlua.c ├── service ├── bootstrap.lua ├── cdummy.lua ├── clusteragent.lua ├── clusterd.lua ├── clusterproxy.lua ├── clustersender.lua ├── cmaster.lua ├── cmemory.lua ├── console.lua ├── cslave.lua ├── datacenterd.lua ├── dbg.lua ├── debug_agent.lua ├── debug_console.lua ├── gate.lua ├── launcher.lua ├── multicastd.lua ├── service_cell.lua ├── service_mgr.lua ├── service_provider.lua ├── sharedatad.lua ├── snaxd.lua ├── vscdebugd.lua └── vscdebuglog.lua ├── skynet-src ├── atomic.h ├── malloc_hook.c ├── malloc_hook.h ├── rwlock.h ├── skynet.h ├── skynet_daemon.c ├── skynet_daemon.h ├── skynet_env.c ├── skynet_env.h ├── skynet_error.c ├── skynet_handle.c ├── skynet_handle.h ├── skynet_harbor.c ├── skynet_harbor.h ├── skynet_imp.h ├── skynet_log.c ├── skynet_log.h ├── skynet_main.c ├── skynet_malloc.h ├── skynet_module.c ├── skynet_module.h ├── skynet_monitor.c ├── skynet_monitor.h ├── skynet_mq.c ├── skynet_mq.h ├── skynet_server.c ├── skynet_server.h ├── skynet_socket.c ├── skynet_socket.h ├── skynet_start.c ├── skynet_timer.c ├── skynet_timer.h ├── socket_buffer.h ├── socket_epoll.h ├── socket_info.h ├── socket_kqueue.h ├── socket_poll.h ├── socket_server.c ├── socket_server.h └── spinlock.h ├── test ├── pingserver.lua ├── sharemap.sp ├── testbson.lua ├── testcoroutine.lua ├── testcrypt.lua ├── testdatacenter.lua ├── testdatasheet.lua ├── testdeadcall.lua ├── testdeadloop.lua ├── testdns.lua ├── testecho.lua ├── testendless.lua ├── testharborlink.lua ├── testhttp.lua ├── testmemlimit.lua ├── testmongodb.lua ├── testmulticast.lua ├── testmulticast2.lua ├── testmysql.lua ├── testoverload.lua ├── testping.lua ├── testpipeline.lua ├── testqueue.lua ├── testredis.lua ├── testredis2.lua ├── testrediscluster.lua ├── testresponse.lua ├── testselect.lua ├── testservice │ ├── init.lua │ └── kvdb.lua ├── testsha.lua ├── testsharetable.lua ├── testsm.lua ├── testsocket.lua ├── teststm.lua ├── testterm.lua ├── testtimeout.lua ├── testtimer.lua ├── testtobeclosed.lua ├── testudp.lua ├── testvscdebug.lua └── time.lua └── xmake.lua /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | /skynet 4 | /skynet.pid 5 | 3rd/lua/lua 6 | 3rd/lua/luac 7 | /cservice 8 | /luaclib 9 | *.so 10 | *.dSYM 11 | .DS_Store 12 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "3rd/jemalloc"] 2 | path = 3rd/jemalloc 3 | url = https://github.com/jemalloc/jemalloc.git 4 | -------------------------------------------------------------------------------- /3rd/lpeg/lpcap.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lpcap.h,v 1.3 2016/09/13 17:45:58 roberto Exp $ 3 | */ 4 | 5 | #if !defined(lpcap_h) 6 | #define lpcap_h 7 | 8 | 9 | #include "lptypes.h" 10 | 11 | 12 | /* kinds of captures */ 13 | typedef enum CapKind { 14 | Cclose, /* not used in trees */ 15 | Cposition, 16 | Cconst, /* ktable[key] is Lua constant */ 17 | Cbackref, /* ktable[key] is "name" of group to get capture */ 18 | Carg, /* 'key' is arg's number */ 19 | Csimple, /* next node is pattern */ 20 | Ctable, /* next node is pattern */ 21 | Cfunction, /* ktable[key] is function; next node is pattern */ 22 | Cquery, /* ktable[key] is table; next node is pattern */ 23 | Cstring, /* ktable[key] is string; next node is pattern */ 24 | Cnum, /* numbered capture; 'key' is number of value to return */ 25 | Csubst, /* substitution capture; next node is pattern */ 26 | Cfold, /* ktable[key] is function; next node is pattern */ 27 | Cruntime, /* not used in trees (is uses another type for tree) */ 28 | Cgroup /* ktable[key] is group's "name" */ 29 | } CapKind; 30 | 31 | 32 | typedef struct Capture { 33 | const char *s; /* subject position */ 34 | unsigned short idx; /* extra info (group name, arg index, etc.) */ 35 | byte kind; /* kind of capture */ 36 | byte siz; /* size of full capture + 1 (0 = not a full capture) */ 37 | } Capture; 38 | 39 | 40 | typedef struct CapState { 41 | Capture *cap; /* current capture */ 42 | Capture *ocap; /* (original) capture list */ 43 | lua_State *L; 44 | int ptop; /* index of last argument to 'match' */ 45 | const char *s; /* original string */ 46 | int valuecached; /* value stored in cache slot */ 47 | } CapState; 48 | 49 | 50 | int runtimecap (CapState *cs, Capture *close, const char *s, int *rem); 51 | int getcaptures (lua_State *L, const char *s, const char *r, int ptop); 52 | int finddyncap (Capture *cap, Capture *last); 53 | 54 | #endif 55 | 56 | 57 | -------------------------------------------------------------------------------- /3rd/lpeg/lpcode.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lpcode.h,v 1.8 2016/09/15 17:46:13 roberto Exp $ 3 | */ 4 | 5 | #if !defined(lpcode_h) 6 | #define lpcode_h 7 | 8 | #include "lua.h" 9 | 10 | #include "lptypes.h" 11 | #include "lptree.h" 12 | #include "lpvm.h" 13 | 14 | int tocharset (TTree *tree, Charset *cs); 15 | int checkaux (TTree *tree, int pred); 16 | int fixedlen (TTree *tree); 17 | int hascaptures (TTree *tree); 18 | int lp_gc (lua_State *L); 19 | Instruction *compile (lua_State *L, Pattern *p); 20 | void realloccode (lua_State *L, Pattern *p, int nsize); 21 | int sizei (const Instruction *i); 22 | 23 | 24 | #define PEnullable 0 25 | #define PEnofail 1 26 | 27 | /* 28 | ** nofail(t) implies that 't' cannot fail with any input 29 | */ 30 | #define nofail(t) checkaux(t, PEnofail) 31 | 32 | /* 33 | ** (not nullable(t)) implies 't' cannot match without consuming 34 | ** something 35 | */ 36 | #define nullable(t) checkaux(t, PEnullable) 37 | 38 | 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /3rd/lpeg/lpeg-128.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinsusie/skynet/10aae3170c4d9d960b28269e7ba0c4e7d05c3c7a/3rd/lpeg/lpeg-128.gif -------------------------------------------------------------------------------- /3rd/lpeg/lpprint.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lpprint.h,v 1.2 2015/06/12 18:18:08 roberto Exp $ 3 | */ 4 | 5 | 6 | #if !defined(lpprint_h) 7 | #define lpprint_h 8 | 9 | 10 | #include "lptree.h" 11 | #include "lpvm.h" 12 | 13 | 14 | #if defined(LPEG_DEBUG) 15 | 16 | void printpatt (Instruction *p, int n); 17 | void printtree (TTree *tree, int ident); 18 | void printktable (lua_State *L, int idx); 19 | void printcharset (const byte *st); 20 | void printcaplist (Capture *cap, Capture *limit); 21 | void printinst (const Instruction *op, const Instruction *p); 22 | 23 | #else 24 | 25 | #define printktable(L,idx) \ 26 | luaL_error(L, "function only implemented in debug mode") 27 | #define printtree(tree,i) \ 28 | luaL_error(L, "function only implemented in debug mode") 29 | #define printpatt(p,n) \ 30 | luaL_error(L, "function only implemented in debug mode") 31 | 32 | #endif 33 | 34 | 35 | #endif 36 | 37 | -------------------------------------------------------------------------------- /3rd/lpeg/lptree.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lptree.h,v 1.3 2016/09/13 18:07:51 roberto Exp $ 3 | */ 4 | 5 | #if !defined(lptree_h) 6 | #define lptree_h 7 | 8 | 9 | #include "lptypes.h" 10 | 11 | 12 | /* 13 | ** types of trees 14 | */ 15 | typedef enum TTag { 16 | TChar = 0, /* 'n' = char */ 17 | TSet, /* the set is stored in next CHARSETSIZE bytes */ 18 | TAny, 19 | TTrue, 20 | TFalse, 21 | TRep, /* 'sib1'* */ 22 | TSeq, /* 'sib1' 'sib2' */ 23 | TChoice, /* 'sib1' / 'sib2' */ 24 | TNot, /* !'sib1' */ 25 | TAnd, /* &'sib1' */ 26 | TCall, /* ktable[key] is rule's key; 'sib2' is rule being called */ 27 | TOpenCall, /* ktable[key] is rule's key */ 28 | TRule, /* ktable[key] is rule's key (but key == 0 for unused rules); 29 | 'sib1' is rule's pattern; 30 | 'sib2' is next rule; 'cap' is rule's sequential number */ 31 | TGrammar, /* 'sib1' is initial (and first) rule */ 32 | TBehind, /* 'sib1' is pattern, 'n' is how much to go back */ 33 | TCapture, /* captures: 'cap' is kind of capture (enum 'CapKind'); 34 | ktable[key] is Lua value associated with capture; 35 | 'sib1' is capture body */ 36 | TRunTime /* run-time capture: 'key' is Lua function; 37 | 'sib1' is capture body */ 38 | } TTag; 39 | 40 | 41 | /* 42 | ** Tree trees 43 | ** The first child of a tree (if there is one) is immediately after 44 | ** the tree. A reference to a second child (ps) is its position 45 | ** relative to the position of the tree itself. 46 | */ 47 | typedef struct TTree { 48 | byte tag; 49 | byte cap; /* kind of capture (if it is a capture) */ 50 | unsigned short key; /* key in ktable for Lua data (0 if no key) */ 51 | union { 52 | int ps; /* occasional second child */ 53 | int n; /* occasional counter */ 54 | } u; 55 | } TTree; 56 | 57 | 58 | /* 59 | ** A complete pattern has its tree plus, if already compiled, 60 | ** its corresponding code 61 | */ 62 | typedef struct Pattern { 63 | union Instruction *code; 64 | int codesize; 65 | TTree tree[1]; 66 | } Pattern; 67 | 68 | 69 | /* number of children for each tree */ 70 | extern const byte numsiblings[]; 71 | 72 | /* access to children */ 73 | #define sib1(t) ((t) + 1) 74 | #define sib2(t) ((t) + (t)->u.ps) 75 | 76 | 77 | 78 | 79 | 80 | 81 | #endif 82 | 83 | -------------------------------------------------------------------------------- /3rd/lpeg/lpvm.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lpvm.h,v 1.3 2014/02/21 13:06:41 roberto Exp $ 3 | */ 4 | 5 | #if !defined(lpvm_h) 6 | #define lpvm_h 7 | 8 | #include "lpcap.h" 9 | 10 | 11 | /* Virtual Machine's instructions */ 12 | typedef enum Opcode { 13 | IAny, /* if no char, fail */ 14 | IChar, /* if char != aux, fail */ 15 | ISet, /* if char not in buff, fail */ 16 | ITestAny, /* in no char, jump to 'offset' */ 17 | ITestChar, /* if char != aux, jump to 'offset' */ 18 | ITestSet, /* if char not in buff, jump to 'offset' */ 19 | ISpan, /* read a span of chars in buff */ 20 | IBehind, /* walk back 'aux' characters (fail if not possible) */ 21 | IRet, /* return from a rule */ 22 | IEnd, /* end of pattern */ 23 | IChoice, /* stack a choice; next fail will jump to 'offset' */ 24 | IJmp, /* jump to 'offset' */ 25 | ICall, /* call rule at 'offset' */ 26 | IOpenCall, /* call rule number 'key' (must be closed to a ICall) */ 27 | ICommit, /* pop choice and jump to 'offset' */ 28 | IPartialCommit, /* update top choice to current position and jump */ 29 | IBackCommit, /* "fails" but jump to its own 'offset' */ 30 | IFailTwice, /* pop one choice and then fail */ 31 | IFail, /* go back to saved state on choice and jump to saved offset */ 32 | IGiveup, /* internal use */ 33 | IFullCapture, /* complete capture of last 'off' chars */ 34 | IOpenCapture, /* start a capture */ 35 | ICloseCapture, 36 | ICloseRunTime 37 | } Opcode; 38 | 39 | 40 | 41 | typedef union Instruction { 42 | struct Inst { 43 | byte code; 44 | byte aux; 45 | short key; 46 | } i; 47 | int offset; 48 | byte buff[1]; 49 | } Instruction; 50 | 51 | 52 | void printpatt (Instruction *p, int n); 53 | const char *match (lua_State *L, const char *o, const char *s, const char *e, 54 | Instruction *op, Capture *capture, int ptop); 55 | 56 | 57 | #endif 58 | 59 | -------------------------------------------------------------------------------- /3rd/lpeg/makefile: -------------------------------------------------------------------------------- 1 | LIBNAME = lpeg 2 | LUADIR = ../lua/ 3 | 4 | COPT = -O2 5 | # COPT = -DLPEG_DEBUG -g 6 | 7 | CWARNS = -Wall -Wextra -pedantic \ 8 | -Waggregate-return \ 9 | -Wcast-align \ 10 | -Wcast-qual \ 11 | -Wdisabled-optimization \ 12 | -Wpointer-arith \ 13 | -Wshadow \ 14 | -Wsign-compare \ 15 | -Wundef \ 16 | -Wwrite-strings \ 17 | -Wbad-function-cast \ 18 | -Wdeclaration-after-statement \ 19 | -Wmissing-prototypes \ 20 | -Wnested-externs \ 21 | -Wstrict-prototypes \ 22 | # -Wunreachable-code \ 23 | 24 | 25 | CFLAGS = $(CWARNS) $(COPT) -std=c99 -I$(LUADIR) -fPIC 26 | CC = gcc 27 | 28 | FILES = lpvm.o lpcap.o lptree.o lpcode.o lpprint.o 29 | 30 | # For Linux 31 | linux: 32 | make lpeg.so "DLLFLAGS = -shared -fPIC" 33 | 34 | # For Mac OS 35 | macosx: 36 | make lpeg.so "DLLFLAGS = -bundle -undefined dynamic_lookup" 37 | 38 | lpeg.so: $(FILES) 39 | env $(CC) $(DLLFLAGS) $(FILES) -o lpeg.so 40 | 41 | $(FILES): makefile 42 | 43 | test: test.lua re.lua lpeg.so 44 | ./test.lua 45 | 46 | clean: 47 | rm -f $(FILES) lpeg.so 48 | 49 | 50 | lpcap.o: lpcap.c lpcap.h lptypes.h 51 | lpcode.o: lpcode.c lptypes.h lpcode.h lptree.h lpvm.h lpcap.h 52 | lpprint.o: lpprint.c lptypes.h lpprint.h lptree.h lpvm.h lpcap.h 53 | lptree.o: lptree.c lptypes.h lpcap.h lpcode.h lptree.h lpvm.h lpprint.h 54 | lpvm.o: lpvm.c lpcap.h lptypes.h lpvm.h lpprint.h lptree.h 55 | 56 | -------------------------------------------------------------------------------- /3rd/lua-cjson/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2012 Mark Pulford 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /3rd/lua-cjson/dtoa_config.h: -------------------------------------------------------------------------------- 1 | #ifndef _DTOA_CONFIG_H 2 | #define _DTOA_CONFIG_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | /* Ensure dtoa.c does not USE_LOCALE. Lua CJSON must not use locale 9 | * aware conversion routines. */ 10 | #undef USE_LOCALE 11 | 12 | /* dtoa.c should not touch errno, Lua CJSON does not use it, and it 13 | * may not be threadsafe */ 14 | #define NO_ERRNO 15 | 16 | #define Long int32_t 17 | #define ULong uint32_t 18 | #define Llong int64_t 19 | #define ULLong uint64_t 20 | 21 | #ifdef IEEE_BIG_ENDIAN 22 | #define IEEE_MC68k 23 | #else 24 | #define IEEE_8087 25 | #endif 26 | 27 | #define MALLOC(n) xmalloc(n) 28 | 29 | static void *xmalloc(size_t size) 30 | { 31 | void *p; 32 | 33 | p = malloc(size); 34 | if (!p) { 35 | fprintf(stderr, "Out of memory"); 36 | abort(); 37 | } 38 | 39 | return p; 40 | } 41 | 42 | #ifdef MULTIPLE_THREADS 43 | 44 | /* Enable locking to support multi-threaded applications */ 45 | 46 | #include 47 | 48 | static pthread_mutex_t private_dtoa_lock[2] = { 49 | PTHREAD_MUTEX_INITIALIZER, 50 | PTHREAD_MUTEX_INITIALIZER 51 | }; 52 | 53 | #define ACQUIRE_DTOA_LOCK(n) do { \ 54 | int r = pthread_mutex_lock(&private_dtoa_lock[n]); \ 55 | if (r) { \ 56 | fprintf(stderr, "pthread_mutex_lock failed with %d\n", r); \ 57 | abort(); \ 58 | } \ 59 | } while (0) 60 | 61 | #define FREE_DTOA_LOCK(n) do { \ 62 | int r = pthread_mutex_unlock(&private_dtoa_lock[n]); \ 63 | if (r) { \ 64 | fprintf(stderr, "pthread_mutex_unlock failed with %d\n", r);\ 65 | abort(); \ 66 | } \ 67 | } while (0) 68 | 69 | #endif /* MULTIPLE_THREADS */ 70 | 71 | #endif /* _DTOA_CONFIG_H */ 72 | 73 | /* vi:ai et sw=4 ts=4: 74 | */ 75 | -------------------------------------------------------------------------------- /3rd/lua-cjson/fpconv.h: -------------------------------------------------------------------------------- 1 | /* Lua CJSON floating point conversion routines */ 2 | 3 | /* Buffer required to store the largest string representation of a double. 4 | * 5 | * Longest double printed with %.14g is 21 characters long: 6 | * -1.7976931348623e+308 */ 7 | # define FPCONV_G_FMT_BUFSIZE 32 8 | 9 | #ifdef USE_INTERNAL_FPCONV 10 | static inline void fpconv_init() 11 | { 12 | /* Do nothing - not required */ 13 | } 14 | #else 15 | extern void fpconv_init(); 16 | #endif 17 | 18 | extern int fpconv_g_fmt(char*, double, int); 19 | extern double fpconv_strtod(const char*, char**); 20 | 21 | /* vi:ai et sw=4 ts=4: 22 | */ 23 | -------------------------------------------------------------------------------- /3rd/lua-md5/README: -------------------------------------------------------------------------------- 1 | MD5 - Cryptographic Library for Lua 2 | Copyright 2003 PUC-Rio 3 | http://www.keplerproject.org/md5 4 | 5 | MD5 offers basic cryptographic facilities for Lua 5.1: a hash (digest) 6 | function, a pair crypt/decrypt based on MD5 and CFB, and a pair crypt/decrypt based 7 | on DES with 56-bit keys. 8 | 9 | MD5 current version is 1.1.2. 10 | 11 | This version is copy from https://github.com/keplerproject/md5 12 | 13 | -------------------------------------------------------------------------------- /3rd/lua-md5/compat-5.2.c: -------------------------------------------------------------------------------- 1 | #include "lua.h" 2 | #include "lauxlib.h" 3 | #include "compat-5.2.h" 4 | 5 | #if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501 6 | /* 7 | ** Adapted from Lua 5.2.0 8 | */ 9 | void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { 10 | luaL_checkstack(L, nup+1, "too many upvalues"); 11 | for (; l->name != NULL; l++) { /* fill the table with given functions */ 12 | int i; 13 | lua_pushstring(L, l->name); 14 | for (i = 0; i < nup; i++) /* copy upvalues to the top */ 15 | lua_pushvalue(L, -(nup + 1)); 16 | lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ 17 | lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */ 18 | } 19 | lua_pop(L, nup); /* remove upvalues */ 20 | } 21 | #endif 22 | -------------------------------------------------------------------------------- /3rd/lua-md5/compat-5.2.h: -------------------------------------------------------------------------------- 1 | #if !defined LUA_VERSION_NUM 2 | /* Lua 5.0 */ 3 | #define luaL_Reg luaL_reg 4 | 5 | #define luaL_addchar(B,c) \ 6 | ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ 7 | (*(B)->p++ = (char)(c))) 8 | #endif 9 | 10 | #if LUA_VERSION_NUM==501 11 | /* Lua 5.1 */ 12 | #define lua_rawlen lua_objlen 13 | #endif 14 | 15 | void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup); 16 | -------------------------------------------------------------------------------- /3rd/lua-md5/md5.h: -------------------------------------------------------------------------------- 1 | /** 2 | * $Id: md5.h,v 1.2 2006/03/03 15:04:49 tomas Exp $ 3 | * Cryptographic module for Lua. 4 | * @author Roberto Ierusalimschy 5 | */ 6 | 7 | 8 | #ifndef md5_h 9 | #define md5_h 10 | 11 | #include 12 | 13 | 14 | #define HASHSIZE 16 15 | 16 | void md5 (const char *message, long len, char *output); 17 | int luaopen_md5_core (lua_State *L); 18 | 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /3rd/lua/README: -------------------------------------------------------------------------------- 1 | This is a modify version of lua 5.4.3 . 2 | 3 | For detail , 4 | Shared Proto : http://lua-users.org/lists/lua-l/2014-03/msg00489.html 5 | Shared short string table : http://blog.codingnow.com/2015/08/lua_vm_share_string.html 6 | Signal for debug use : http://blog.codingnow.com/2015/03/skynet_signal.html 7 | -------------------------------------------------------------------------------- /3rd/lua/lapi.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lapi.h $ 3 | ** Auxiliary functions from Lua API 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lapi_h 8 | #define lapi_h 9 | 10 | 11 | #include "llimits.h" 12 | #include "lstate.h" 13 | 14 | 15 | /* Increments 'L->top', checking for stack overflows */ 16 | #define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ 17 | "stack overflow");} 18 | 19 | 20 | /* 21 | ** If a call returns too many multiple returns, the callee may not have 22 | ** stack space to accommodate all results. In this case, this macro 23 | ** increases its stack space ('L->ci->top'). 24 | */ 25 | #define adjustresults(L,nres) \ 26 | { if ((nres) <= LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } 27 | 28 | 29 | /* Ensure the stack has at least 'n' elements */ 30 | #define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ 31 | "not enough elements in the stack") 32 | 33 | 34 | /* 35 | ** To reduce the overhead of returning from C functions, the presence of 36 | ** to-be-closed variables in these functions is coded in the CallInfo's 37 | ** field 'nresults', in a way that functions with no to-be-closed variables 38 | ** with zero, one, or "all" wanted results have no overhead. Functions 39 | ** with other number of wanted results, as well as functions with 40 | ** variables to be closed, have an extra check. 41 | */ 42 | 43 | #define hastocloseCfunc(n) ((n) < LUA_MULTRET) 44 | 45 | /* Map [-1, inf) (range of 'nresults') into (-inf, -2] */ 46 | #define codeNresults(n) (-(n) - 3) 47 | #define decodeNresults(n) (-(n) - 3) 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /3rd/lua/lctype.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lctype.c $ 3 | ** 'ctype' functions for Lua 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lctype_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include "lctype.h" 14 | 15 | #if !LUA_USE_CTYPE /* { */ 16 | 17 | #include 18 | 19 | 20 | #if defined (LUA_UCID) /* accept UniCode IDentifiers? */ 21 | /* consider all non-ascii codepoints to be alphabetic */ 22 | #define NONA 0x01 23 | #else 24 | #define NONA 0x00 /* default */ 25 | #endif 26 | 27 | 28 | LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { 29 | 0x00, /* EOZ */ 30 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ 31 | 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 32 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ 33 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 34 | 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ 35 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 36 | 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ 37 | 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 38 | 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ 39 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 40 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ 41 | 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, 42 | 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ 43 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 44 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ 45 | 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, 46 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* 8. */ 47 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, 48 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* 9. */ 49 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, 50 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* a. */ 51 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, 52 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* b. */ 53 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, 54 | 0x00, 0x00, NONA, NONA, NONA, NONA, NONA, NONA, /* c. */ 55 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, 56 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* d. */ 57 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, 58 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* e. */ 59 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, 60 | NONA, NONA, NONA, NONA, NONA, 0x00, 0x00, 0x00, /* f. */ 61 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 62 | }; 63 | 64 | #endif /* } */ 65 | -------------------------------------------------------------------------------- /3rd/lua/lctype.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lctype.h $ 3 | ** 'ctype' functions for Lua 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lctype_h 8 | #define lctype_h 9 | 10 | #include "lua.h" 11 | 12 | 13 | /* 14 | ** WARNING: the functions defined here do not necessarily correspond 15 | ** to the similar functions in the standard C ctype.h. They are 16 | ** optimized for the specific needs of Lua. 17 | */ 18 | 19 | #if !defined(LUA_USE_CTYPE) 20 | 21 | #if 'A' == 65 && '0' == 48 22 | /* ASCII case: can use its own tables; faster and fixed */ 23 | #define LUA_USE_CTYPE 0 24 | #else 25 | /* must use standard C ctype */ 26 | #define LUA_USE_CTYPE 1 27 | #endif 28 | 29 | #endif 30 | 31 | 32 | #if !LUA_USE_CTYPE /* { */ 33 | 34 | #include 35 | 36 | #include "llimits.h" 37 | 38 | 39 | #define ALPHABIT 0 40 | #define DIGITBIT 1 41 | #define PRINTBIT 2 42 | #define SPACEBIT 3 43 | #define XDIGITBIT 4 44 | 45 | 46 | #define MASK(B) (1 << (B)) 47 | 48 | 49 | /* 50 | ** add 1 to char to allow index -1 (EOZ) 51 | */ 52 | #define testprop(c,p) (luai_ctype_[(c)+1] & (p)) 53 | 54 | /* 55 | ** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' 56 | */ 57 | #define lislalpha(c) testprop(c, MASK(ALPHABIT)) 58 | #define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) 59 | #define lisdigit(c) testprop(c, MASK(DIGITBIT)) 60 | #define lisspace(c) testprop(c, MASK(SPACEBIT)) 61 | #define lisprint(c) testprop(c, MASK(PRINTBIT)) 62 | #define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) 63 | 64 | 65 | /* 66 | ** In ASCII, this 'ltolower' is correct for alphabetic characters and 67 | ** for '.'. That is enough for Lua needs. ('check_exp' ensures that 68 | ** the character either is an upper-case letter or is unchanged by 69 | ** the transformation, which holds for lower-case letters and '.'.) 70 | */ 71 | #define ltolower(c) \ 72 | check_exp(('A' <= (c) && (c) <= 'Z') || (c) == ((c) | ('A' ^ 'a')), \ 73 | (c) | ('A' ^ 'a')) 74 | 75 | 76 | /* one entry for each character and for -1 (EOZ) */ 77 | LUAI_DDEC(const lu_byte luai_ctype_[UCHAR_MAX + 2];) 78 | 79 | 80 | #else /* }{ */ 81 | 82 | /* 83 | ** use standard C ctypes 84 | */ 85 | 86 | #include 87 | 88 | 89 | #define lislalpha(c) (isalpha(c) || (c) == '_') 90 | #define lislalnum(c) (isalnum(c) || (c) == '_') 91 | #define lisdigit(c) (isdigit(c)) 92 | #define lisspace(c) (isspace(c)) 93 | #define lisprint(c) (isprint(c)) 94 | #define lisxdigit(c) (isxdigit(c)) 95 | 96 | #define ltolower(c) (tolower(c)) 97 | 98 | #endif /* } */ 99 | 100 | #endif 101 | 102 | -------------------------------------------------------------------------------- /3rd/lua/ldebug.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ldebug.h $ 3 | ** Auxiliary functions from Debug Interface module 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ldebug_h 8 | #define ldebug_h 9 | 10 | 11 | #include "lstate.h" 12 | 13 | 14 | #define pcRel(pc, p) (cast_int((pc) - (p)->code) - 1) 15 | 16 | 17 | /* Active Lua function (given call info) */ 18 | #define ci_func(ci) (clLvalue(s2v((ci)->func))) 19 | 20 | 21 | #define resethookcount(L) (L->hookcount = L->basehookcount) 22 | 23 | /* 24 | ** mark for entries in 'lineinfo' array that has absolute information in 25 | ** 'abslineinfo' array 26 | */ 27 | #define ABSLINEINFO (-0x80) 28 | 29 | 30 | /* 31 | ** MAXimum number of successive Instructions WiTHout ABSolute line 32 | ** information. (A power of two allows fast divisions.) 33 | */ 34 | #if !defined(MAXIWTHABS) 35 | #define MAXIWTHABS 128 36 | #endif 37 | 38 | 39 | LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc); 40 | LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, 41 | StkId *pos); 42 | LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, 43 | const char *opname); 44 | LUAI_FUNC l_noret luaG_callerror (lua_State *L, const TValue *o); 45 | LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o, 46 | const char *what); 47 | LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, 48 | const TValue *p2); 49 | LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1, 50 | const TValue *p2, 51 | const char *msg); 52 | LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1, 53 | const TValue *p2); 54 | LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, 55 | const TValue *p2); 56 | LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); 57 | LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg, 58 | TString *src, int line); 59 | LUAI_FUNC l_noret luaG_errormsg (lua_State *L); 60 | LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc); 61 | 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /3rd/lua/lfunc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lfunc.h $ 3 | ** Auxiliary functions to manipulate prototypes and closures 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lfunc_h 8 | #define lfunc_h 9 | 10 | 11 | #include "lobject.h" 12 | 13 | 14 | #define sizeCclosure(n) (cast_int(offsetof(CClosure, upvalue)) + \ 15 | cast_int(sizeof(TValue)) * (n)) 16 | 17 | #define sizeLclosure(n) (cast_int(offsetof(LClosure, upvals)) + \ 18 | cast_int(sizeof(TValue *)) * (n)) 19 | 20 | 21 | /* test whether thread is in 'twups' list */ 22 | #define isintwups(L) (L->twups != L) 23 | 24 | 25 | /* 26 | ** maximum number of upvalues in a closure (both C and Lua). (Value 27 | ** must fit in a VM register.) 28 | */ 29 | #define MAXUPVAL 255 30 | 31 | 32 | #define upisopen(up) ((up)->v != &(up)->u.value) 33 | 34 | 35 | #define uplevel(up) check_exp(upisopen(up), cast(StkId, (up)->v)) 36 | 37 | 38 | /* 39 | ** maximum number of misses before giving up the cache of closures 40 | ** in prototypes 41 | */ 42 | #define MAXMISS 10 43 | 44 | 45 | 46 | /* special status to close upvalues preserving the top of the stack */ 47 | #define CLOSEKTOP (-1) 48 | 49 | 50 | LUAI_FUNC Proto *luaF_newproto (lua_State *L); 51 | LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nupvals); 52 | LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nupvals); 53 | LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); 54 | LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); 55 | LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level); 56 | LUAI_FUNC void luaF_closeupval (lua_State *L, StkId level); 57 | LUAI_FUNC void luaF_close (lua_State *L, StkId level, int status, int yy); 58 | LUAI_FUNC void luaF_unlinkupval (UpVal *uv); 59 | LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); 60 | LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, 61 | int pc); 62 | LUAI_FUNC void luaF_shareproto (Proto *func); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /3rd/lua/linit.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: linit.c $ 3 | ** Initialization of libraries for lua.c and other clients 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #define linit_c 9 | #define LUA_LIB 10 | 11 | /* 12 | ** If you embed Lua in your program and need to open the standard 13 | ** libraries, call luaL_openlibs in your program. If you need a 14 | ** different set of libraries, copy this file to your project and edit 15 | ** it to suit your needs. 16 | ** 17 | ** You can also *preload* libraries, so that a later 'require' can 18 | ** open the library, which is already linked to the application. 19 | ** For that, do the following code: 20 | ** 21 | ** luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); 22 | ** lua_pushcfunction(L, luaopen_modname); 23 | ** lua_setfield(L, -2, modname); 24 | ** lua_pop(L, 1); // remove PRELOAD table 25 | */ 26 | 27 | #include "lprefix.h" 28 | 29 | 30 | #include 31 | 32 | #include "lua.h" 33 | 34 | #include "lualib.h" 35 | #include "lauxlib.h" 36 | 37 | 38 | /* 39 | ** these libs are loaded by lua.c and are readily available to any Lua 40 | ** program 41 | */ 42 | static const luaL_Reg loadedlibs[] = { 43 | {LUA_GNAME, luaopen_base}, 44 | {LUA_LOADLIBNAME, luaopen_package}, 45 | {LUA_COLIBNAME, luaopen_coroutine}, 46 | {LUA_TABLIBNAME, luaopen_table}, 47 | {LUA_IOLIBNAME, luaopen_io}, 48 | {LUA_OSLIBNAME, luaopen_os}, 49 | {LUA_STRLIBNAME, luaopen_string}, 50 | {LUA_MATHLIBNAME, luaopen_math}, 51 | {LUA_UTF8LIBNAME, luaopen_utf8}, 52 | {LUA_DBLIBNAME, luaopen_debug}, 53 | {NULL, NULL} 54 | }; 55 | 56 | 57 | LUALIB_API void luaL_openlibs (lua_State *L) { 58 | const luaL_Reg *lib; 59 | /* "require" functions from 'loadedlibs' and set results to global table */ 60 | for (lib = loadedlibs; lib->func; lib++) { 61 | luaL_requiref(L, lib->name, lib->func, 1); 62 | lua_pop(L, 1); /* remove lib */ 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /3rd/lua/ljumptab.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ljumptab.h $ 3 | ** Jump Table for the Lua interpreter 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #undef vmdispatch 9 | #undef vmcase 10 | #undef vmbreak 11 | 12 | #define vmdispatch(x) goto *disptab[x]; 13 | 14 | #define vmcase(l) L_##l: 15 | 16 | #define vmbreak vmfetch(); vmdispatch(GET_OPCODE(i)); 17 | 18 | 19 | static const void *const disptab[NUM_OPCODES] = { 20 | 21 | #if 0 22 | ** you can update the following list with this command: 23 | ** 24 | ** sed -n '/^OP_/\!d; s/OP_/\&\&L_OP_/ ; s/,.*/,/ ; s/\/.*// ; p' lopcodes.h 25 | ** 26 | #endif 27 | 28 | &&L_OP_MOVE, 29 | &&L_OP_LOADI, 30 | &&L_OP_LOADF, 31 | &&L_OP_LOADK, 32 | &&L_OP_LOADKX, 33 | &&L_OP_LOADFALSE, 34 | &&L_OP_LFALSESKIP, 35 | &&L_OP_LOADTRUE, 36 | &&L_OP_LOADNIL, 37 | &&L_OP_GETUPVAL, 38 | &&L_OP_SETUPVAL, 39 | &&L_OP_GETTABUP, 40 | &&L_OP_GETTABLE, 41 | &&L_OP_GETI, 42 | &&L_OP_GETFIELD, 43 | &&L_OP_SETTABUP, 44 | &&L_OP_SETTABLE, 45 | &&L_OP_SETI, 46 | &&L_OP_SETFIELD, 47 | &&L_OP_NEWTABLE, 48 | &&L_OP_SELF, 49 | &&L_OP_ADDI, 50 | &&L_OP_ADDK, 51 | &&L_OP_SUBK, 52 | &&L_OP_MULK, 53 | &&L_OP_MODK, 54 | &&L_OP_POWK, 55 | &&L_OP_DIVK, 56 | &&L_OP_IDIVK, 57 | &&L_OP_BANDK, 58 | &&L_OP_BORK, 59 | &&L_OP_BXORK, 60 | &&L_OP_SHRI, 61 | &&L_OP_SHLI, 62 | &&L_OP_ADD, 63 | &&L_OP_SUB, 64 | &&L_OP_MUL, 65 | &&L_OP_MOD, 66 | &&L_OP_POW, 67 | &&L_OP_DIV, 68 | &&L_OP_IDIV, 69 | &&L_OP_BAND, 70 | &&L_OP_BOR, 71 | &&L_OP_BXOR, 72 | &&L_OP_SHL, 73 | &&L_OP_SHR, 74 | &&L_OP_MMBIN, 75 | &&L_OP_MMBINI, 76 | &&L_OP_MMBINK, 77 | &&L_OP_UNM, 78 | &&L_OP_BNOT, 79 | &&L_OP_NOT, 80 | &&L_OP_LEN, 81 | &&L_OP_CONCAT, 82 | &&L_OP_CLOSE, 83 | &&L_OP_TBC, 84 | &&L_OP_JMP, 85 | &&L_OP_EQ, 86 | &&L_OP_LT, 87 | &&L_OP_LE, 88 | &&L_OP_EQK, 89 | &&L_OP_EQI, 90 | &&L_OP_LTI, 91 | &&L_OP_LEI, 92 | &&L_OP_GTI, 93 | &&L_OP_GEI, 94 | &&L_OP_TEST, 95 | &&L_OP_TESTSET, 96 | &&L_OP_CALL, 97 | &&L_OP_TAILCALL, 98 | &&L_OP_RETURN, 99 | &&L_OP_RETURN0, 100 | &&L_OP_RETURN1, 101 | &&L_OP_FORLOOP, 102 | &&L_OP_FORPREP, 103 | &&L_OP_TFORPREP, 104 | &&L_OP_TFORCALL, 105 | &&L_OP_TFORLOOP, 106 | &&L_OP_SETLIST, 107 | &&L_OP_CLOSURE, 108 | &&L_OP_VARARG, 109 | &&L_OP_VARARGPREP, 110 | &&L_OP_EXTRAARG 111 | 112 | }; 113 | -------------------------------------------------------------------------------- /3rd/lua/llex.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: llex.h $ 3 | ** Lexical Analyzer 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef llex_h 8 | #define llex_h 9 | 10 | #include 11 | 12 | #include "lobject.h" 13 | #include "lzio.h" 14 | 15 | 16 | /* 17 | ** Single-char tokens (terminal symbols) are represented by their own 18 | ** numeric code. Other tokens start at the following value. 19 | */ 20 | #define FIRST_RESERVED (UCHAR_MAX + 1) 21 | 22 | 23 | #if !defined(LUA_ENV) 24 | #define LUA_ENV "_ENV" 25 | #endif 26 | 27 | 28 | /* 29 | * WARNING: if you change the order of this enumeration, 30 | * grep "ORDER RESERVED" 31 | */ 32 | enum RESERVED { 33 | /* terminal symbols denoted by reserved words */ 34 | TK_AND = FIRST_RESERVED, TK_BREAK, 35 | TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, 36 | TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, 37 | TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, 38 | /* other terminal symbols */ 39 | TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, 40 | TK_SHL, TK_SHR, 41 | TK_DBCOLON, TK_EOS, 42 | TK_FLT, TK_INT, TK_NAME, TK_STRING 43 | }; 44 | 45 | /* number of reserved words */ 46 | #define NUM_RESERVED (cast_int(TK_WHILE-FIRST_RESERVED + 1)) 47 | 48 | 49 | typedef union { 50 | lua_Number r; 51 | lua_Integer i; 52 | TString *ts; 53 | } SemInfo; /* semantics information */ 54 | 55 | 56 | typedef struct Token { 57 | int token; 58 | SemInfo seminfo; 59 | } Token; 60 | 61 | 62 | /* state of the lexer plus state of the parser when shared by all 63 | functions */ 64 | typedef struct LexState { 65 | int current; /* current character (charint) */ 66 | int linenumber; /* input line counter */ 67 | int lastline; /* line of last token 'consumed' */ 68 | Token t; /* current token */ 69 | Token lookahead; /* look ahead token */ 70 | struct FuncState *fs; /* current function (parser) */ 71 | struct lua_State *L; 72 | ZIO *z; /* input stream */ 73 | Mbuffer *buff; /* buffer for tokens */ 74 | Table *h; /* to avoid collection/reuse strings */ 75 | struct Dyndata *dyd; /* dynamic structures used by the parser */ 76 | TString *source; /* current source name */ 77 | TString *envn; /* environment variable name */ 78 | } LexState; 79 | 80 | 81 | LUAI_FUNC void luaX_init (lua_State *L); 82 | LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, 83 | TString *source, int firstchar); 84 | LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); 85 | LUAI_FUNC void luaX_next (LexState *ls); 86 | LUAI_FUNC int luaX_lookahead (LexState *ls); 87 | LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); 88 | LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); 89 | 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /3rd/lua/lopnames.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lopnames.h $ 3 | ** Opcode names 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #if !defined(lopnames_h) 8 | #define lopnames_h 9 | 10 | #include 11 | 12 | 13 | /* ORDER OP */ 14 | 15 | static const char *const opnames[] = { 16 | "MOVE", 17 | "LOADI", 18 | "LOADF", 19 | "LOADK", 20 | "LOADKX", 21 | "LOADFALSE", 22 | "LFALSESKIP", 23 | "LOADTRUE", 24 | "LOADNIL", 25 | "GETUPVAL", 26 | "SETUPVAL", 27 | "GETTABUP", 28 | "GETTABLE", 29 | "GETI", 30 | "GETFIELD", 31 | "SETTABUP", 32 | "SETTABLE", 33 | "SETI", 34 | "SETFIELD", 35 | "NEWTABLE", 36 | "SELF", 37 | "ADDI", 38 | "ADDK", 39 | "SUBK", 40 | "MULK", 41 | "MODK", 42 | "POWK", 43 | "DIVK", 44 | "IDIVK", 45 | "BANDK", 46 | "BORK", 47 | "BXORK", 48 | "SHRI", 49 | "SHLI", 50 | "ADD", 51 | "SUB", 52 | "MUL", 53 | "MOD", 54 | "POW", 55 | "DIV", 56 | "IDIV", 57 | "BAND", 58 | "BOR", 59 | "BXOR", 60 | "SHL", 61 | "SHR", 62 | "MMBIN", 63 | "MMBINI", 64 | "MMBINK", 65 | "UNM", 66 | "BNOT", 67 | "NOT", 68 | "LEN", 69 | "CONCAT", 70 | "CLOSE", 71 | "TBC", 72 | "JMP", 73 | "EQ", 74 | "LT", 75 | "LE", 76 | "EQK", 77 | "EQI", 78 | "LTI", 79 | "LEI", 80 | "GTI", 81 | "GEI", 82 | "TEST", 83 | "TESTSET", 84 | "CALL", 85 | "TAILCALL", 86 | "RETURN", 87 | "RETURN0", 88 | "RETURN1", 89 | "FORLOOP", 90 | "FORPREP", 91 | "TFORPREP", 92 | "TFORCALL", 93 | "TFORLOOP", 94 | "SETLIST", 95 | "CLOSURE", 96 | "VARARG", 97 | "VARARGPREP", 98 | "EXTRAARG", 99 | NULL 100 | }; 101 | 102 | #endif 103 | 104 | -------------------------------------------------------------------------------- /3rd/lua/lprefix.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lprefix.h $ 3 | ** Definitions for Lua code that must come before any other header file 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lprefix_h 8 | #define lprefix_h 9 | 10 | 11 | /* 12 | ** Allows POSIX/XSI stuff 13 | */ 14 | #if !defined(LUA_USE_C89) /* { */ 15 | 16 | #if !defined(_XOPEN_SOURCE) 17 | #define _XOPEN_SOURCE 600 18 | #elif _XOPEN_SOURCE == 0 19 | #undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */ 20 | #endif 21 | 22 | /* 23 | ** Allows manipulation of large files in gcc and some other compilers 24 | */ 25 | #if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS) 26 | #define _LARGEFILE_SOURCE 1 27 | #define _FILE_OFFSET_BITS 64 28 | #endif 29 | 30 | #endif /* } */ 31 | 32 | 33 | /* 34 | ** Windows stuff 35 | */ 36 | #if defined(_WIN32) /* { */ 37 | 38 | #if !defined(_CRT_SECURE_NO_WARNINGS) 39 | #define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */ 40 | #endif 41 | 42 | #endif /* } */ 43 | 44 | #endif 45 | 46 | -------------------------------------------------------------------------------- /3rd/lua/lstring.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lstring.h $ 3 | ** String table (keep all strings handled by Lua) 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lstring_h 8 | #define lstring_h 9 | 10 | #include "lgc.h" 11 | #include "lobject.h" 12 | #include "lstate.h" 13 | 14 | 15 | /* 16 | ** Memory-allocation error message must be preallocated (it cannot 17 | ** be created after memory is exhausted) 18 | */ 19 | #define MEMERRMSG "not enough memory" 20 | 21 | 22 | /* 23 | ** Size of a TString: Size of the header plus space for the string 24 | ** itself (including final '\0'). 25 | */ 26 | #define sizelstring(l) (offsetof(TString, contents) + ((l) + 1) * sizeof(char)) 27 | 28 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ 29 | (sizeof(s)/sizeof(char))-1)) 30 | 31 | 32 | /* 33 | ** test whether a string is a reserved word 34 | */ 35 | #define isreserved(s) ((s)->tt == LUA_VSHRSTR && (s)->extra > 0) 36 | 37 | 38 | /* 39 | ** equality for short strings, compare id first 40 | */ 41 | #define eqshrstr(a,b) check_exp((a)->tt == LUA_VSHRSTR, (a) == (b) || \ 42 | ( ((a)->id == (b)->id) ? ((a)->id != 0) : ((a)->hash == (b)->hash && luaS_eqshrstr(a,b)) ) ) 43 | 44 | LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); 45 | LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts); 46 | LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); 47 | LUAI_FUNC int luaS_eqshrstr (TString *a, TString *b); 48 | LUAI_FUNC void luaS_resize (lua_State *L, int newsize); 49 | LUAI_FUNC void luaS_clearcache (global_State *g); 50 | LUAI_FUNC void luaS_init (lua_State *L); 51 | LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); 52 | LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue); 53 | LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); 54 | LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); 55 | LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); 56 | LUAI_FUNC void luaS_share(TString *ts); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /3rd/lua/ltable.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltable.h $ 3 | ** Lua tables (hash) 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ltable_h 8 | #define ltable_h 9 | 10 | #include "lobject.h" 11 | 12 | 13 | #define gnode(t,i) (&(t)->node[i]) 14 | #define gval(n) (&(n)->i_val) 15 | #define gnext(n) ((n)->u.next) 16 | 17 | 18 | /* 19 | ** Clear all bits of fast-access metamethods, which means that the table 20 | ** may have any of these metamethods. (First access that fails after the 21 | ** clearing will set the bit again.) 22 | */ 23 | #define invalidateTMcache(t) ((t)->flags &= ~maskflags) 24 | 25 | 26 | /* true when 't' is using 'dummynode' as its hash part */ 27 | #define isdummy(t) ((t)->lastfree == NULL) 28 | 29 | 30 | /* allocated size for hash nodes */ 31 | #define allocsizenode(t) (isdummy(t) ? 0 : sizenode(t)) 32 | 33 | 34 | /* returns the Node, given the value of a table entry */ 35 | #define nodefromval(v) cast(Node *, (v)) 36 | 37 | 38 | LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); 39 | LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, 40 | TValue *value); 41 | LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key); 42 | LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); 43 | LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); 44 | LUAI_FUNC void luaH_newkey (lua_State *L, Table *t, const TValue *key, 45 | TValue *value); 46 | LUAI_FUNC void luaH_set (lua_State *L, Table *t, const TValue *key, 47 | TValue *value); 48 | LUAI_FUNC void luaH_finishset (lua_State *L, Table *t, const TValue *key, 49 | const TValue *slot, TValue *value); 50 | LUAI_FUNC Table *luaH_new (lua_State *L); 51 | LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize, 52 | unsigned int nhsize); 53 | LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize); 54 | LUAI_FUNC void luaH_free (lua_State *L, Table *t); 55 | LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); 56 | LUAI_FUNC lua_Unsigned luaH_getn (Table *t); 57 | LUAI_FUNC unsigned int luaH_realasize (const Table *t); 58 | 59 | 60 | #if defined(LUA_DEBUG) 61 | LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); 62 | LUAI_FUNC int luaH_isdummy (const Table *t); 63 | #endif 64 | 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /3rd/lua/lua.hpp: -------------------------------------------------------------------------------- 1 | // lua.hpp 2 | // Lua header files for C++ 3 | // <> not supplied automatically because Lua also compiles as C++ 4 | 5 | extern "C" { 6 | #include "lua.h" 7 | #include "lualib.h" 8 | #include "lauxlib.h" 9 | } 10 | -------------------------------------------------------------------------------- /3rd/lua/lualib.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lualib.h $ 3 | ** Lua standard libraries 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #ifndef lualib_h 9 | #define lualib_h 10 | 11 | #include "lua.h" 12 | 13 | 14 | /* version suffix for environment variable names */ 15 | #define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR 16 | 17 | 18 | LUAMOD_API int (luaopen_base) (lua_State *L); 19 | 20 | #define LUA_COLIBNAME "coroutine" 21 | LUAMOD_API int (luaopen_coroutine) (lua_State *L); 22 | 23 | #define LUA_TABLIBNAME "table" 24 | LUAMOD_API int (luaopen_table) (lua_State *L); 25 | 26 | #define LUA_IOLIBNAME "io" 27 | LUAMOD_API int (luaopen_io) (lua_State *L); 28 | 29 | #define LUA_OSLIBNAME "os" 30 | LUAMOD_API int (luaopen_os) (lua_State *L); 31 | 32 | #define LUA_STRLIBNAME "string" 33 | LUAMOD_API int (luaopen_string) (lua_State *L); 34 | 35 | #define LUA_UTF8LIBNAME "utf8" 36 | LUAMOD_API int (luaopen_utf8) (lua_State *L); 37 | 38 | #define LUA_MATHLIBNAME "math" 39 | LUAMOD_API int (luaopen_math) (lua_State *L); 40 | 41 | #define LUA_DBLIBNAME "debug" 42 | LUAMOD_API int (luaopen_debug) (lua_State *L); 43 | 44 | #define LUA_LOADLIBNAME "package" 45 | LUAMOD_API int (luaopen_package) (lua_State *L); 46 | 47 | #define LUA_CACHELIB 48 | LUAMOD_API int (luaopen_cache) (lua_State *L); 49 | LUALIB_API void (luaL_initcodecache) (void); 50 | 51 | /* open all previous libraries */ 52 | LUALIB_API void (luaL_openlibs) (lua_State *L); 53 | 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /3rd/lua/lundump.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lundump.h $ 3 | ** load precompiled Lua chunks 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lundump_h 8 | #define lundump_h 9 | 10 | #include "llimits.h" 11 | #include "lobject.h" 12 | #include "lzio.h" 13 | 14 | 15 | /* data to catch conversion errors */ 16 | #define LUAC_DATA "\x19\x93\r\n\x1a\n" 17 | 18 | #define LUAC_INT 0x5678 19 | #define LUAC_NUM cast_num(370.5) 20 | 21 | /* 22 | ** Encode major-minor version in one byte, one nibble for each 23 | */ 24 | #define MYINT(s) (s[0]-'0') /* assume one-digit numerals */ 25 | #define LUAC_VERSION (MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR)) 26 | 27 | #define LUAC_FORMAT 0 /* this is the official format */ 28 | 29 | /* load one chunk; from lundump.c */ 30 | LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name); 31 | 32 | /* dump one chunk; from ldump.c */ 33 | LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, 34 | void* data, int strip); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /3rd/lua/lzio.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lzio.c $ 3 | ** Buffered streams 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lzio_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "llimits.h" 18 | #include "lmem.h" 19 | #include "lstate.h" 20 | #include "lzio.h" 21 | 22 | 23 | int luaZ_fill (ZIO *z) { 24 | size_t size; 25 | lua_State *L = z->L; 26 | const char *buff; 27 | lua_unlock(L); 28 | buff = z->reader(L, z->data, &size); 29 | lua_lock(L); 30 | if (buff == NULL || size == 0) 31 | return EOZ; 32 | z->n = size - 1; /* discount char being returned */ 33 | z->p = buff; 34 | return cast_uchar(*(z->p++)); 35 | } 36 | 37 | 38 | void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { 39 | z->L = L; 40 | z->reader = reader; 41 | z->data = data; 42 | z->n = 0; 43 | z->p = NULL; 44 | } 45 | 46 | 47 | /* --------------------------------------------------------------- read --- */ 48 | size_t luaZ_read (ZIO *z, void *b, size_t n) { 49 | while (n) { 50 | size_t m; 51 | if (z->n == 0) { /* no bytes in buffer? */ 52 | if (luaZ_fill(z) == EOZ) /* try to read more */ 53 | return n; /* no more input; return number of missing bytes */ 54 | else { 55 | z->n++; /* luaZ_fill consumed first byte; put it back */ 56 | z->p--; 57 | } 58 | } 59 | m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ 60 | memcpy(b, z->p, m); 61 | z->n -= m; 62 | z->p += m; 63 | b = (char *)b + m; 64 | n -= m; 65 | } 66 | return 0; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /3rd/lua/lzio.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lzio.h $ 3 | ** Buffered streams 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #ifndef lzio_h 9 | #define lzio_h 10 | 11 | #include "lua.h" 12 | 13 | #include "lmem.h" 14 | 15 | 16 | #define EOZ (-1) /* end of stream */ 17 | 18 | typedef struct Zio ZIO; 19 | 20 | #define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) 21 | 22 | 23 | typedef struct Mbuffer { 24 | char *buffer; 25 | size_t n; 26 | size_t buffsize; 27 | } Mbuffer; 28 | 29 | #define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) 30 | 31 | #define luaZ_buffer(buff) ((buff)->buffer) 32 | #define luaZ_sizebuffer(buff) ((buff)->buffsize) 33 | #define luaZ_bufflen(buff) ((buff)->n) 34 | 35 | #define luaZ_buffremove(buff,i) ((buff)->n -= (i)) 36 | #define luaZ_resetbuffer(buff) ((buff)->n = 0) 37 | 38 | 39 | #define luaZ_resizebuffer(L, buff, size) \ 40 | ((buff)->buffer = luaM_reallocvchar(L, (buff)->buffer, \ 41 | (buff)->buffsize, size), \ 42 | (buff)->buffsize = size) 43 | 44 | #define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) 45 | 46 | 47 | LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, 48 | void *data); 49 | LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */ 50 | 51 | 52 | 53 | /* --------- Private Part ------------------ */ 54 | 55 | struct Zio { 56 | size_t n; /* bytes still unread */ 57 | const char *p; /* current position in buffer */ 58 | lua_Reader reader; /* reader function */ 59 | void *data; /* additional data */ 60 | lua_State *L; /* Lua state (for reader) */ 61 | }; 62 | 63 | 64 | LUAI_FUNC int luaZ_fill (ZIO *z); 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012-2022 codingnow.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## ![skynet logo](https://github.com/cloudwu/skynet/wiki/image/skynet_metro.jpg) 2 | 3 | Skynet is a lightweight online game framework which can be used in many other fields. 4 | 5 | ## Build 6 | 7 | For Linux, install autoconf first for jemalloc: 8 | 9 | ``` 10 | git clone https://github.com/cloudwu/skynet.git 11 | cd skynet 12 | make 'PLATFORM' # PLATFORM can be linux, macosx, freebsd now 13 | ``` 14 | 15 | Or: 16 | 17 | ``` 18 | export PLAT=linux 19 | make 20 | ``` 21 | 22 | For FreeBSD , use gmake instead of make. 23 | 24 | ## Test 25 | 26 | Run these in different consoles: 27 | 28 | ``` 29 | ./skynet examples/config # Launch first skynet node (Gate server) and a skynet-master (see config for standalone option) 30 | ./3rd/lua/lua examples/client.lua # Launch a client, and try to input hello. 31 | ``` 32 | 33 | ## About Lua version 34 | 35 | Skynet now uses a modified version of lua 5.4.4 ( https://github.com/ejoy/lua/tree/skynet54 ) for multiple lua states. 36 | 37 | Official Lua versions can also be used as long as the Makefile is edited. 38 | 39 | ## How To Use 40 | 41 | * Read Wiki for documents https://github.com/cloudwu/skynet/wiki 42 | * The FAQ in wiki https://github.com/cloudwu/skynet/wiki/FAQ 43 | -------------------------------------------------------------------------------- /examples/abort.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | require "skynet.manager" -- import skynet.abort 3 | 4 | skynet.abort() 5 | -------------------------------------------------------------------------------- /examples/agent.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local socket = require "skynet.socket" 3 | local sproto = require "sproto" 4 | local sprotoloader = require "sprotoloader" 5 | 6 | local WATCHDOG 7 | local host 8 | local send_request 9 | 10 | local CMD = {} 11 | local REQUEST = {} 12 | local client_fd 13 | 14 | function REQUEST:get() 15 | print("get", self.what) 16 | local r = skynet.call("SIMPLEDB", "lua", "get", self.what) 17 | return { result = r } 18 | end 19 | 20 | function REQUEST:set() 21 | print("set", self.what, self.value) 22 | local r = skynet.call("SIMPLEDB", "lua", "set", self.what, self.value) 23 | end 24 | 25 | function REQUEST:handshake() 26 | return { msg = "Welcome to skynet, I will send heartbeat every 5 sec." } 27 | end 28 | 29 | function REQUEST:quit() 30 | skynet.call(WATCHDOG, "lua", "close", client_fd) 31 | end 32 | 33 | local function request(name, args, response) 34 | local f = assert(REQUEST[name]) 35 | local r = f(args) 36 | if response then 37 | return response(r) 38 | end 39 | end 40 | 41 | local function send_package(pack) 42 | local package = string.pack(">s2", pack) 43 | socket.write(client_fd, package) 44 | end 45 | 46 | skynet.register_protocol { 47 | name = "client", 48 | id = skynet.PTYPE_CLIENT, 49 | unpack = function (msg, sz) 50 | return host:dispatch(msg, sz) 51 | end, 52 | dispatch = function (fd, _, type, ...) 53 | assert(fd == client_fd) -- You can use fd to reply message 54 | skynet.ignoreret() -- session is fd, don't call skynet.ret 55 | skynet.trace() 56 | if type == "REQUEST" then 57 | local ok, result = pcall(request, ...) 58 | if ok then 59 | if result then 60 | send_package(result) 61 | end 62 | else 63 | skynet.error(result) 64 | end 65 | else 66 | assert(type == "RESPONSE") 67 | error "This example doesn't support request client" 68 | end 69 | end 70 | } 71 | 72 | function CMD.start(conf) 73 | local fd = conf.client 74 | local gate = conf.gate 75 | WATCHDOG = conf.watchdog 76 | -- slot 1,2 set at main.lua 77 | host = sprotoloader.load(1):host "package" 78 | send_request = host:attach(sprotoloader.load(2)) 79 | skynet.fork(function() 80 | while true do 81 | send_package(send_request "heartbeat") 82 | skynet.sleep(500) 83 | end 84 | end) 85 | 86 | client_fd = fd 87 | skynet.call(gate, "lua", "forward", fd) 88 | end 89 | 90 | function CMD.disconnect() 91 | -- todo: do something before exit 92 | skynet.exit() 93 | end 94 | 95 | skynet.start(function() 96 | skynet.dispatch("lua", function(_,_, command, ...) 97 | skynet.trace() 98 | local f = CMD[command] 99 | skynet.ret(skynet.pack(f(...))) 100 | end) 101 | end) 102 | -------------------------------------------------------------------------------- /examples/checkdeadloop.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local list = {} 4 | 5 | local function timeout_check(ti) 6 | if not next(list) then 7 | return 8 | end 9 | skynet.sleep(ti) -- sleep 10 sec 10 | for k,v in pairs(list) do 11 | skynet.error("timout",ti,k,v) 12 | end 13 | end 14 | 15 | skynet.start(function() 16 | skynet.error("ping all") 17 | local list_ret = skynet.call(".launcher", "lua", "LIST") 18 | for addr, desc in pairs(list_ret) do 19 | list[addr] = desc 20 | skynet.fork(function() 21 | skynet.call(addr,"debug","INFO") 22 | list[addr] = nil 23 | end) 24 | end 25 | skynet.sleep(0) 26 | timeout_check(100) 27 | timeout_check(400) 28 | timeout_check(500) 29 | skynet.exit() 30 | end) 31 | -------------------------------------------------------------------------------- /examples/client.lua: -------------------------------------------------------------------------------- 1 | package.cpath = "luaclib/?.so" 2 | package.path = "lualib/?.lua;examples/?.lua" 3 | 4 | if _VERSION ~= "Lua 5.4" then 5 | error "Use lua 5.4" 6 | end 7 | 8 | local socket = require "client.socket" 9 | local proto = require "proto" 10 | local sproto = require "sproto" 11 | 12 | local host = sproto.new(proto.s2c):host "package" 13 | local request = host:attach(sproto.new(proto.c2s)) 14 | 15 | local fd = assert(socket.connect("127.0.0.1", 8888)) 16 | 17 | local function send_package(fd, pack) 18 | local package = string.pack(">s2", pack) 19 | socket.send(fd, package) 20 | end 21 | 22 | local function unpack_package(text) 23 | local size = #text 24 | if size < 2 then 25 | return nil, text 26 | end 27 | local s = text:byte(1) * 256 + text:byte(2) 28 | if size < s+2 then 29 | return nil, text 30 | end 31 | 32 | return text:sub(3,2+s), text:sub(3+s) 33 | end 34 | 35 | local function recv_package(last) 36 | local result 37 | result, last = unpack_package(last) 38 | if result then 39 | return result, last 40 | end 41 | local r = socket.recv(fd) 42 | if not r then 43 | return nil, last 44 | end 45 | if r == "" then 46 | error "Server closed" 47 | end 48 | return unpack_package(last .. r) 49 | end 50 | 51 | local session = 0 52 | 53 | local function send_request(name, args) 54 | session = session + 1 55 | local str = request(name, args, session) 56 | send_package(fd, str) 57 | print("Request:", session) 58 | end 59 | 60 | local last = "" 61 | 62 | local function print_request(name, args) 63 | print("REQUEST", name) 64 | if args then 65 | for k,v in pairs(args) do 66 | print(k,v) 67 | end 68 | end 69 | end 70 | 71 | local function print_response(session, args) 72 | print("RESPONSE", session) 73 | if args then 74 | for k,v in pairs(args) do 75 | print(k,v) 76 | end 77 | end 78 | end 79 | 80 | local function print_package(t, ...) 81 | if t == "REQUEST" then 82 | print_request(...) 83 | else 84 | assert(t == "RESPONSE") 85 | print_response(...) 86 | end 87 | end 88 | 89 | local function dispatch_package() 90 | while true do 91 | local v 92 | v, last = recv_package(last) 93 | if not v then 94 | break 95 | end 96 | 97 | print_package(host:dispatch(v)) 98 | end 99 | end 100 | 101 | send_request("handshake") 102 | send_request("set", { what = "hello", value = "world" }) 103 | while true do 104 | dispatch_package() 105 | local cmd = socket.readstdin() 106 | if cmd then 107 | if cmd == "quit" then 108 | send_request("quit") 109 | else 110 | send_request("get", { what = cmd }) 111 | end 112 | else 113 | socket.usleep(100) 114 | end 115 | end 116 | -------------------------------------------------------------------------------- /examples/cluster1.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local cluster = require "skynet.cluster" 3 | local snax = require "skynet.snax" 4 | 5 | skynet.start(function() 6 | cluster.reload { 7 | db = "127.0.0.1:2528", 8 | db2 = "127.0.0.1:2529", 9 | } 10 | 11 | local sdb = skynet.newservice("simpledb") 12 | -- register name "sdb" for simpledb, you can use cluster.query() later. 13 | -- See cluster2.lua 14 | cluster.register("sdb", sdb) 15 | 16 | print(skynet.call(sdb, "lua", "SET", "a", "foobar")) 17 | print(skynet.call(sdb, "lua", "SET", "b", "foobar2")) 18 | print(skynet.call(sdb, "lua", "GET", "a")) 19 | print(skynet.call(sdb, "lua", "GET", "b")) 20 | cluster.open "db" 21 | cluster.open "db2" 22 | -- unique snax service 23 | snax.uniqueservice "pingserver" 24 | end) 25 | -------------------------------------------------------------------------------- /examples/cluster2.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local cluster = require "skynet.cluster" 3 | 4 | skynet.start(function() 5 | local proxy = cluster.proxy "db@sdb" -- cluster.proxy("db", "@sdb") 6 | local largekey = string.rep("X", 128*1024) 7 | local largevalue = string.rep("R", 100 * 1024) 8 | skynet.call(proxy, "lua", "SET", largekey, largevalue) 9 | local v = skynet.call(proxy, "lua", "GET", largekey) 10 | assert(largevalue == v) 11 | skynet.send(proxy, "lua", "PING", "proxy") 12 | 13 | skynet.fork(function() 14 | skynet.trace("cluster") 15 | print(cluster.call("db", "@sdb", "GET", "a")) 16 | print(cluster.call("db2", "@sdb", "GET", "b")) 17 | cluster.send("db2", "@sdb", "PING", "db2:longstring" .. largevalue) 18 | end) 19 | 20 | -- test snax service 21 | skynet.timeout(300,function() 22 | cluster.reload { 23 | db = false, -- db is down 24 | db3 = "127.0.0.1:2529" 25 | } 26 | print(pcall(cluster.call, "db", "@sdb", "GET", "a")) -- db is down 27 | end) 28 | cluster.reload { __nowaiting = false } 29 | local pingserver = cluster.snax("db3", "pingserver") 30 | print(pingserver.req.ping "hello") 31 | end) 32 | -------------------------------------------------------------------------------- /examples/clustername.lua: -------------------------------------------------------------------------------- 1 | __nowaiting = true -- If you turn this flag off, cluster.call would block when node name is absent 2 | 3 | db = "127.0.0.1:2528" 4 | db2 = "127.0.0.1:2529" 5 | -------------------------------------------------------------------------------- /examples/config: -------------------------------------------------------------------------------- 1 | include "config.path" 2 | 3 | -- preload = "./examples/preload.lua" -- run preload.lua before every lua service run 4 | thread = 8 5 | logger = nil 6 | logpath = "." 7 | harbor = 1 8 | address = "127.0.0.1:2526" 9 | master = "127.0.0.1:2013" 10 | start = "main" -- main script 11 | bootstrap = "snlua bootstrap" -- The service for bootstrap 12 | standalone = "0.0.0.0:2013" 13 | -- snax_interface_g = "snax_g" 14 | cpath = root.."cservice/?.so" 15 | -- daemon = "./skynet.pid" 16 | -------------------------------------------------------------------------------- /examples/config.c1: -------------------------------------------------------------------------------- 1 | thread = 8 2 | logger = nil 3 | harbor = 0 4 | start = "cluster1" 5 | bootstrap = "snlua bootstrap" -- The service for bootstrap 6 | luaservice = "./service/?.lua;./test/?.lua;./examples/?.lua" 7 | lualoader = "lualib/loader.lua" 8 | cpath = "./cservice/?.so" 9 | -- use cluster.reload instead, see cluster1.lua 10 | -- cluster = "./examples/clustername.lua" 11 | snax = "./test/?.lua" 12 | -------------------------------------------------------------------------------- /examples/config.c2: -------------------------------------------------------------------------------- 1 | thread = 8 2 | logger = nil 3 | harbor = 0 4 | start = "cluster2" 5 | bootstrap = "snlua bootstrap" -- The service for bootstrap 6 | luaservice = "./service/?.lua;./test/?.lua;./examples/?.lua" 7 | lualoader = "lualib/loader.lua" 8 | cpath = "./cservice/?.so" 9 | cluster = "./examples/clustername.lua" 10 | snax = "./test/?.lua" 11 | -------------------------------------------------------------------------------- /examples/config.login: -------------------------------------------------------------------------------- 1 | thread = 8 2 | logger = nil 3 | harbor = 0 4 | start = "main" 5 | bootstrap = "snlua bootstrap" -- The service for bootstrap 6 | luaservice = "./service/?.lua;./examples/login/?.lua" 7 | lualoader = "lualib/loader.lua" 8 | cpath = "./cservice/?.so" 9 | -------------------------------------------------------------------------------- /examples/config.mc: -------------------------------------------------------------------------------- 1 | root = "./" 2 | thread = 8 3 | logger = nil 4 | harbor = 2 5 | address = "127.0.0.1:2527" 6 | master = "127.0.0.1:2013" 7 | start = "testmulticast2" -- main script 8 | bootstrap = "snlua bootstrap" -- The service for bootstrap 9 | --standalone = "0.0.0.0:2013" 10 | luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua" 11 | lualoader = "lualib/loader.lua" 12 | -- preload = "./examples/preload.lua" -- run preload.lua before every lua service run 13 | snax = root.."examples/?.lua;"..root.."test/?.lua" 14 | cpath = root.."cservice/?.so" 15 | -------------------------------------------------------------------------------- /examples/config.mongodb: -------------------------------------------------------------------------------- 1 | root = "./" 2 | thread = 8 3 | logger = nil 4 | harbor = 0 5 | start = "main_mongodb" -- main script 6 | bootstrap = "snlua bootstrap" -- The service for bootstrap 7 | luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua" 8 | lualoader = "lualib/loader.lua" 9 | snax = root.."examples/?.lua;"..root.."test/?.lua" 10 | cpath = root.."cservice/?.so" 11 | -- daemon = "./skynet.pid" 12 | -------------------------------------------------------------------------------- /examples/config.mysql: -------------------------------------------------------------------------------- 1 | root = "./" 2 | thread = 8 3 | logger = nil 4 | harbor = 0 5 | start = "main_mysql" -- main script 6 | bootstrap = "snlua bootstrap" -- The service for bootstrap 7 | luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua" 8 | lualoader = "lualib/loader.lua" 9 | snax = root.."examples/?.lua;"..root.."test/?.lua" 10 | cpath = root.."cservice/?.so" 11 | -- daemon = "./skynet.pid" 12 | -------------------------------------------------------------------------------- /examples/config.path: -------------------------------------------------------------------------------- 1 | root = "./" 2 | luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua;"..root.."test/?/init.lua" 3 | lualoader = root .. "lualib/loader.lua" 4 | lua_path = root.."lualib/?.lua;"..root.."lualib/?/init.lua" 5 | lua_cpath = root .. "luaclib/?.so" 6 | snax = root.."examples/?.lua;"..root.."test/?.lua" 7 | -------------------------------------------------------------------------------- /examples/config.userlog: -------------------------------------------------------------------------------- 1 | root = "./" 2 | thread = 8 3 | logger = "userlog" 4 | logservice = "snlua" 5 | logpath = "." 6 | harbor = 0 7 | start = "main" -- main script 8 | bootstrap = "snlua bootstrap" -- The service for bootstrap 9 | luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua" 10 | lualoader = "lualib/loader.lua" 11 | -- preload = "./examples/preload.lua" -- run preload.lua before every lua service run 12 | snax = root.."examples/?.lua;"..root.."test/?.lua" 13 | -- snax_interface_g = "snax_g" 14 | cpath = root.."cservice/?.so" 15 | -- daemon = "./skynet.pid" 16 | -------------------------------------------------------------------------------- /examples/config_log: -------------------------------------------------------------------------------- 1 | thread = 8 2 | mqueue = 256 3 | cpath = "./cservice/?.so" 4 | logger = nil 5 | harbor = 2 6 | address = "127.0.0.1:2527" 7 | master = "127.0.0.1:2013" 8 | start = "main_log" 9 | luaservice ="./service/?.lua;./test/?.lua;./examples/?.lua" 10 | snax = "./examples/?.lua;./test/?.lua" 11 | -------------------------------------------------------------------------------- /examples/config_vsc: -------------------------------------------------------------------------------- 1 | root = "./" 2 | thread = 4 3 | logger = "vscdebuglog" 4 | logservice = "snlua" 5 | 6 | logpath = "." 7 | harbor = 0 8 | start = "testvscdebug" -- main script 9 | bootstrap = "snlua bootstrap" -- The service for bootstrap 10 | 11 | luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua;"..root.."test/?/init.lua" 12 | lualoader = root .. "lualib/loader.lua" 13 | lua_path = root.."lualib/?.lua;"..root.."lualib/?/init.lua" 14 | lua_cpath = root .. "luaclib/?.so" 15 | snax = root.."examples/?.lua;"..root.."test/?.lua" 16 | cpath = root.."cservice/?.so" -------------------------------------------------------------------------------- /examples/globallog.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | require "skynet.manager" -- import skynet.register 3 | 4 | skynet.start(function() 5 | skynet.dispatch("lua", function(session, address, ...) 6 | print("[GLOBALLOG]", skynet.address(address), ...) 7 | end) 8 | skynet.register ".log" 9 | skynet.register "LOG" 10 | end) 11 | -------------------------------------------------------------------------------- /examples/injectlaunch.lua: -------------------------------------------------------------------------------- 1 | if not _P then 2 | print[[ 3 | This file is examples to show how to inject code into lua service. 4 | It is used to inject into launcher service to change the command.LAUNCH to command.LOGLAUNCH. 5 | telnet the debug_console service (nc 127.0.0.1 8000), and run: 6 | inject 3 examples/injectlaunch.lua -- 3 means launcher service 7 | ]] 8 | return 9 | end 10 | local command = _P.lua.command 11 | 12 | if command.RAWLAUNCH then 13 | command.LAUNCH, command.RAWLAUNCH = command.RAWLAUNCH 14 | print "restore command.LAUNCH" 15 | else 16 | command.RAWLAUNCH = command.LAUNCH 17 | command.LAUNCH = command.LOGLAUNCH 18 | print "replace command.LAUNCH" 19 | end 20 | -------------------------------------------------------------------------------- /examples/login/gated.lua: -------------------------------------------------------------------------------- 1 | local msgserver = require "snax.msgserver" 2 | local crypt = require "skynet.crypt" 3 | local skynet = require "skynet" 4 | 5 | local loginservice = tonumber(...) 6 | 7 | local server = {} 8 | local users = {} 9 | local username_map = {} 10 | local internal_id = 0 11 | 12 | -- login server disallow multi login, so login_handler never be reentry 13 | -- call by login server 14 | function server.login_handler(uid, secret) 15 | if users[uid] then 16 | error(string.format("%s is already login", uid)) 17 | end 18 | 19 | internal_id = internal_id + 1 20 | local id = internal_id -- don't use internal_id directly 21 | local username = msgserver.username(uid, id, servername) 22 | 23 | -- you can use a pool to alloc new agent 24 | local agent = skynet.newservice "msgagent" 25 | local u = { 26 | username = username, 27 | agent = agent, 28 | uid = uid, 29 | subid = id, 30 | } 31 | 32 | -- trash subid (no used) 33 | skynet.call(agent, "lua", "login", uid, id, secret) 34 | 35 | users[uid] = u 36 | username_map[username] = u 37 | 38 | msgserver.login(username, secret) 39 | 40 | -- you should return unique subid 41 | return id 42 | end 43 | 44 | -- call by agent 45 | function server.logout_handler(uid, subid) 46 | local u = users[uid] 47 | if u then 48 | local username = msgserver.username(uid, subid, servername) 49 | assert(u.username == username) 50 | msgserver.logout(u.username) 51 | users[uid] = nil 52 | username_map[u.username] = nil 53 | skynet.call(loginservice, "lua", "logout",uid, subid) 54 | end 55 | end 56 | 57 | -- call by login server 58 | function server.kick_handler(uid, subid) 59 | local u = users[uid] 60 | if u then 61 | local username = msgserver.username(uid, subid, servername) 62 | assert(u.username == username) 63 | -- NOTICE: logout may call skynet.exit, so you should use pcall. 64 | pcall(skynet.call, u.agent, "lua", "logout") 65 | end 66 | end 67 | 68 | -- call by self (when socket disconnect) 69 | function server.disconnect_handler(username) 70 | local u = username_map[username] 71 | if u then 72 | skynet.call(u.agent, "lua", "afk") 73 | end 74 | end 75 | 76 | -- call by self (when recv a request from client) 77 | function server.request_handler(username, msg) 78 | local u = username_map[username] 79 | return skynet.tostring(skynet.rawcall(u.agent, "client", msg)) 80 | end 81 | 82 | -- call by self (when gate open) 83 | function server.register_handler(name) 84 | servername = name 85 | skynet.call(loginservice, "lua", "register_gate", servername, skynet.self()) 86 | end 87 | 88 | msgserver.start(server) 89 | 90 | -------------------------------------------------------------------------------- /examples/login/logind.lua: -------------------------------------------------------------------------------- 1 | local login = require "snax.loginserver" 2 | local crypt = require "skynet.crypt" 3 | local skynet = require "skynet" 4 | 5 | local server = { 6 | host = "127.0.0.1", 7 | port = 8001, 8 | multilogin = false, -- disallow multilogin 9 | name = "login_master", 10 | } 11 | 12 | local server_list = {} 13 | local user_online = {} 14 | local user_login = {} 15 | 16 | function server.auth_handler(token) 17 | -- the token is base64(user)@base64(server):base64(password) 18 | local user, server, password = token:match("([^@]+)@([^:]+):(.+)") 19 | user = crypt.base64decode(user) 20 | server = crypt.base64decode(server) 21 | password = crypt.base64decode(password) 22 | assert(password == "password", "Invalid password") 23 | return server, user 24 | end 25 | 26 | function server.login_handler(server, uid, secret) 27 | print(string.format("%s@%s is login, secret is %s", uid, server, crypt.hexencode(secret))) 28 | local gameserver = assert(server_list[server], "Unknown server") 29 | -- only one can login, because disallow multilogin 30 | local last = user_online[uid] 31 | if last then 32 | skynet.call(last.address, "lua", "kick", uid, last.subid) 33 | end 34 | if user_online[uid] then 35 | error(string.format("user %s is already online", uid)) 36 | end 37 | 38 | local subid = tostring(skynet.call(gameserver, "lua", "login", uid, secret)) 39 | user_online[uid] = { address = gameserver, subid = subid , server = server} 40 | return subid 41 | end 42 | 43 | local CMD = {} 44 | 45 | function CMD.register_gate(server, address) 46 | server_list[server] = address 47 | end 48 | 49 | function CMD.logout(uid, subid) 50 | local u = user_online[uid] 51 | if u then 52 | print(string.format("%s@%s is logout", uid, u.server)) 53 | user_online[uid] = nil 54 | end 55 | end 56 | 57 | function server.command_handler(command, ...) 58 | local f = assert(CMD[command]) 59 | return f(...) 60 | end 61 | 62 | login(server) 63 | -------------------------------------------------------------------------------- /examples/login/main.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | skynet.start(function() 4 | local loginserver = skynet.newservice("logind") 5 | local gate = skynet.newservice("gated", loginserver) 6 | 7 | skynet.call(gate, "lua", "open" , { 8 | port = 8888, 9 | maxclient = 64, 10 | servername = "sample", 11 | }) 12 | end) 13 | -------------------------------------------------------------------------------- /examples/login/msgagent.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | skynet.register_protocol { 4 | name = "client", 5 | id = skynet.PTYPE_CLIENT, 6 | unpack = skynet.tostring, 7 | } 8 | 9 | local gate 10 | local userid, subid 11 | 12 | local CMD = {} 13 | 14 | function CMD.login(source, uid, sid, secret) 15 | -- you may use secret to make a encrypted data stream 16 | skynet.error(string.format("%s is login", uid)) 17 | gate = source 18 | userid = uid 19 | subid = sid 20 | -- you may load user data from database 21 | end 22 | 23 | local function logout() 24 | if gate then 25 | skynet.call(gate, "lua", "logout", userid, subid) 26 | end 27 | skynet.exit() 28 | end 29 | 30 | function CMD.logout(source) 31 | -- NOTICE: The logout MAY be reentry 32 | skynet.error(string.format("%s is logout", userid)) 33 | logout() 34 | end 35 | 36 | function CMD.afk(source) 37 | -- the connection is broken, but the user may back 38 | skynet.error(string.format("AFK")) 39 | end 40 | 41 | skynet.start(function() 42 | -- If you want to fork a work thread , you MUST do it in CMD.login 43 | skynet.dispatch("lua", function(session, source, command, ...) 44 | local f = assert(CMD[command]) 45 | skynet.ret(skynet.pack(f(source, ...))) 46 | end) 47 | 48 | skynet.dispatch("client", function(_,_, msg) 49 | -- the simple echo service 50 | skynet.sleep(10) -- sleep a while 51 | skynet.ret(msg) 52 | end) 53 | end) 54 | -------------------------------------------------------------------------------- /examples/main.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local sprotoloader = require "sprotoloader" 3 | 4 | local max_client = 64 5 | 6 | skynet.start(function() 7 | skynet.error("Server start") 8 | skynet.uniqueservice("protoloader") 9 | if not skynet.getenv "daemon" then 10 | local console = skynet.newservice("console") 11 | end 12 | skynet.newservice("debug_console",8000) 13 | skynet.newservice("simpledb") 14 | local watchdog = skynet.newservice("watchdog") 15 | skynet.call(watchdog, "lua", "start", { 16 | port = 8888, 17 | maxclient = max_client, 18 | nodelay = true, 19 | }) 20 | skynet.error("Watchdog listen on", 8888) 21 | skynet.exit() 22 | end) 23 | -------------------------------------------------------------------------------- /examples/main_log.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local harbor = require "skynet.harbor" 3 | require "skynet.manager" -- import skynet.monitor 4 | 5 | local function monitor_master() 6 | harbor.linkmaster() 7 | print("master is down") 8 | skynet.exit() 9 | end 10 | 11 | skynet.start(function() 12 | print("Log server start") 13 | skynet.monitor "simplemonitor" 14 | local log = skynet.newservice("globallog") 15 | skynet.fork(monitor_master) 16 | end) 17 | 18 | -------------------------------------------------------------------------------- /examples/main_mongodb.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | 4 | skynet.start(function() 5 | print("Main Server start") 6 | local console = skynet.newservice( 7 | "testmongodb", "127.0.0.1", 27017, "testdb", "test", "test" 8 | ) 9 | 10 | print("Main Server exit") 11 | skynet.exit() 12 | end) 13 | -------------------------------------------------------------------------------- /examples/main_mysql.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | 4 | skynet.start(function() 5 | print("Main Server start") 6 | local console = skynet.newservice("testmysql") 7 | 8 | print("Main Server exit") 9 | skynet.exit() 10 | end) 11 | -------------------------------------------------------------------------------- /examples/preload.lua: -------------------------------------------------------------------------------- 1 | -- This file will execute before every lua service start 2 | -- See config 3 | 4 | print("PRELOAD", ...) 5 | 6 | -------------------------------------------------------------------------------- /examples/proto.lua: -------------------------------------------------------------------------------- 1 | local sprotoparser = require "sprotoparser" 2 | 3 | local proto = {} 4 | 5 | proto.c2s = sprotoparser.parse [[ 6 | .package { 7 | type 0 : integer 8 | session 1 : integer 9 | } 10 | 11 | handshake 1 { 12 | response { 13 | msg 0 : string 14 | } 15 | } 16 | 17 | get 2 { 18 | request { 19 | what 0 : string 20 | } 21 | response { 22 | result 0 : string 23 | } 24 | } 25 | 26 | set 3 { 27 | request { 28 | what 0 : string 29 | value 1 : string 30 | } 31 | } 32 | 33 | quit 4 {} 34 | 35 | ]] 36 | 37 | proto.s2c = sprotoparser.parse [[ 38 | .package { 39 | type 0 : integer 40 | session 1 : integer 41 | } 42 | 43 | heartbeat 1 {} 44 | ]] 45 | 46 | return proto 47 | -------------------------------------------------------------------------------- /examples/protoloader.lua: -------------------------------------------------------------------------------- 1 | -- module proto as examples/proto.lua 2 | package.path = "./examples/?.lua;" .. package.path 3 | 4 | local skynet = require "skynet" 5 | local sprotoparser = require "sprotoparser" 6 | local sprotoloader = require "sprotoloader" 7 | local proto = require "proto" 8 | 9 | skynet.start(function() 10 | sprotoloader.save(proto.c2s, 1) 11 | sprotoloader.save(proto.s2c, 2) 12 | -- don't call skynet.exit() , because sproto.core may unload and the global slot become invalid 13 | end) 14 | -------------------------------------------------------------------------------- /examples/share.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local sharedata = require "skynet.sharedata" 3 | 4 | local mode = ... 5 | 6 | if mode == "host" then 7 | 8 | skynet.start(function() 9 | skynet.error("new foobar") 10 | sharedata.new("foobar", { a=1, b= { "hello", "world" } }) 11 | 12 | skynet.fork(function() 13 | skynet.sleep(200) -- sleep 2s 14 | skynet.error("update foobar a = 2") 15 | sharedata.update("foobar", { a =2 }) 16 | skynet.sleep(200) -- sleep 2s 17 | skynet.error("update foobar a = 3") 18 | sharedata.update("foobar", { a = 3, b = { "change" } }) 19 | skynet.sleep(100) 20 | skynet.error("delete foobar") 21 | sharedata.delete "foobar" 22 | end) 23 | end) 24 | 25 | else 26 | 27 | 28 | skynet.start(function() 29 | skynet.newservice(SERVICE_NAME, "host") 30 | 31 | local obj = sharedata.query "foobar" 32 | 33 | local b = obj.b 34 | skynet.error(string.format("a=%d", obj.a)) 35 | 36 | for k,v in ipairs(b) do 37 | skynet.error(string.format("b[%d]=%s", k,v)) 38 | end 39 | 40 | -- test lua serialization 41 | local s = skynet.packstring(obj) 42 | local nobj = skynet.unpack(s) 43 | for k,v in pairs(nobj) do 44 | skynet.error(string.format("nobj[%s]=%s", k,v)) 45 | end 46 | for k,v in ipairs(nobj.b) do 47 | skynet.error(string.format("nobj.b[%d]=%s", k,v)) 48 | end 49 | 50 | for i = 1, 5 do 51 | skynet.sleep(100) 52 | skynet.error("second " ..i) 53 | for k,v in pairs(obj) do 54 | skynet.error(string.format("%s = %s", k , tostring(v))) 55 | end 56 | end 57 | 58 | local ok, err = pcall(function() 59 | local tmp = { b[1], b[2] } -- b is invalid , so pcall should failed 60 | end) 61 | 62 | if not ok then 63 | skynet.error(err) 64 | end 65 | 66 | -- obj. b is not the same with local b 67 | for k,v in ipairs(obj.b) do 68 | skynet.error(string.format("b[%d] = %s", k , tostring(v))) 69 | end 70 | 71 | collectgarbage() 72 | skynet.error("sleep") 73 | skynet.sleep(100) 74 | b = nil 75 | collectgarbage() 76 | skynet.error("sleep") 77 | skynet.sleep(100) 78 | 79 | skynet.exit() 80 | end) 81 | 82 | end 83 | -------------------------------------------------------------------------------- /examples/simpledb.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | require "skynet.manager" -- import skynet.register 3 | local db = {} 4 | 5 | local command = {} 6 | 7 | function command.GET(key) 8 | return db[key] 9 | end 10 | 11 | function command.SET(key, value) 12 | local last = db[key] 13 | db[key] = value 14 | return last 15 | end 16 | 17 | skynet.start(function() 18 | skynet.dispatch("lua", function(session, address, cmd, ...) 19 | cmd = cmd:upper() 20 | if cmd == "PING" then 21 | assert(session == 0) 22 | local str = (...) 23 | if #str > 20 then 24 | str = str:sub(1,20) .. "...(" .. #str .. ")" 25 | end 26 | skynet.error(string.format("%s ping %s", skynet.address(address), str)) 27 | return 28 | end 29 | local f = command[cmd] 30 | if f then 31 | skynet.ret(skynet.pack(f(...))) 32 | else 33 | error(string.format("Unknown command %s", tostring(cmd))) 34 | end 35 | end) 36 | -- skynet.traceproto("lua", false) -- true off tracelog 37 | skynet.register "SIMPLEDB" 38 | end) 39 | -------------------------------------------------------------------------------- /examples/simplemonitor.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | -- It's a simple service exit monitor, you can do something more when a service exit. 4 | 5 | local service_map = {} 6 | 7 | skynet.register_protocol { 8 | name = "client", 9 | id = skynet.PTYPE_CLIENT, -- PTYPE_CLIENT = 3 10 | unpack = function() end, 11 | dispatch = function(_, address) 12 | local w = service_map[address] 13 | if w then 14 | for watcher in pairs(w) do 15 | skynet.redirect(watcher, address, "error", 0, "") 16 | end 17 | service_map[address] = false 18 | end 19 | end 20 | } 21 | 22 | local function monitor(session, watcher, command, service) 23 | assert(command, "WATCH") 24 | local w = service_map[service] 25 | if not w then 26 | if w == false then 27 | skynet.ret(skynet.pack(false)) 28 | return 29 | end 30 | w = {} 31 | service_map[service] = w 32 | end 33 | w[watcher] = true 34 | skynet.ret(skynet.pack(true)) 35 | end 36 | 37 | skynet.start(function() 38 | skynet.dispatch("lua", monitor) 39 | end) 40 | -------------------------------------------------------------------------------- /examples/userlog.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | require "skynet.manager" 3 | 4 | -- register protocol text before skynet.start would be better. 5 | skynet.register_protocol { 6 | name = "text", 7 | id = skynet.PTYPE_TEXT, 8 | unpack = skynet.tostring, 9 | dispatch = function(_, address, msg) 10 | print(string.format(":%08x(%.2f): %s", address, skynet.time(), msg)) 11 | end 12 | } 13 | 14 | skynet.register_protocol { 15 | name = "SYSTEM", 16 | id = skynet.PTYPE_SYSTEM, 17 | unpack = function(...) return ... end, 18 | dispatch = function() 19 | -- reopen signal 20 | print("SIGHUP") 21 | end 22 | } 23 | 24 | skynet.start(function() 25 | end) -------------------------------------------------------------------------------- /examples/watchdog.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local CMD = {} 4 | local SOCKET = {} 5 | local gate 6 | local agent = {} 7 | 8 | function SOCKET.open(fd, addr) 9 | skynet.error("New client from : " .. addr) 10 | agent[fd] = skynet.newservice("agent") 11 | skynet.call(agent[fd], "lua", "start", { gate = gate, client = fd, watchdog = skynet.self() }) 12 | end 13 | 14 | local function close_agent(fd) 15 | local a = agent[fd] 16 | agent[fd] = nil 17 | if a then 18 | skynet.call(gate, "lua", "kick", fd) 19 | -- disconnect never return 20 | skynet.send(a, "lua", "disconnect") 21 | end 22 | end 23 | 24 | function SOCKET.close(fd) 25 | print("socket close",fd) 26 | close_agent(fd) 27 | end 28 | 29 | function SOCKET.error(fd, msg) 30 | print("socket error",fd, msg) 31 | close_agent(fd) 32 | end 33 | 34 | function SOCKET.warning(fd, size) 35 | -- size K bytes havn't send out in fd 36 | print("socket warning", fd, size) 37 | end 38 | 39 | function SOCKET.data(fd, msg) 40 | end 41 | 42 | function CMD.start(conf) 43 | skynet.call(gate, "lua", "open" , conf) 44 | end 45 | 46 | function CMD.close(fd) 47 | close_agent(fd) 48 | end 49 | 50 | skynet.start(function() 51 | skynet.dispatch("lua", function(session, source, cmd, subcmd, ...) 52 | if cmd == "socket" then 53 | local f = SOCKET[subcmd] 54 | f(...) 55 | -- socket api don't need return 56 | else 57 | local f = assert(CMD[cmd]) 58 | skynet.ret(skynet.pack(f(subcmd, ...))) 59 | end 60 | end) 61 | 62 | gate = skynet.newservice("gate") 63 | end) 64 | -------------------------------------------------------------------------------- /lualib-src/lua-memory.c: -------------------------------------------------------------------------------- 1 | #define LUA_LIB 2 | 3 | #include 4 | #include 5 | 6 | #include "malloc_hook.h" 7 | 8 | static int 9 | ltotal(lua_State *L) { 10 | size_t t = malloc_used_memory(); 11 | lua_pushinteger(L, (lua_Integer)t); 12 | 13 | return 1; 14 | } 15 | 16 | static int 17 | lblock(lua_State *L) { 18 | size_t t = malloc_memory_block(); 19 | lua_pushinteger(L, (lua_Integer)t); 20 | 21 | return 1; 22 | } 23 | 24 | static int 25 | ldumpinfo(lua_State *L) { 26 | const char *opts = NULL; 27 | if (lua_isstring(L, 1)) { 28 | opts = luaL_checkstring(L,1); 29 | } 30 | memory_info_dump(opts); 31 | 32 | return 0; 33 | } 34 | 35 | static int 36 | ljestat(lua_State *L) { 37 | static const char* names[] = { 38 | "stats.allocated", 39 | "stats.resident", 40 | "stats.retained", 41 | "stats.mapped", 42 | "stats.active" }; 43 | static size_t flush = 1; 44 | mallctl_int64("epoch", &flush); // refresh je.stats.cache 45 | lua_newtable(L); 46 | int i; 47 | for (i = 0; i < (sizeof(names)/sizeof(names[0])); i++) { 48 | lua_pushstring(L, names[i]); 49 | lua_pushinteger(L, (lua_Integer) mallctl_int64(names[i], NULL)); 50 | lua_settable(L, -3); 51 | } 52 | return 1; 53 | } 54 | 55 | static int 56 | lmallctl(lua_State *L) { 57 | const char *name = luaL_checkstring(L,1); 58 | lua_pushinteger(L, (lua_Integer) mallctl_int64(name, NULL)); 59 | return 1; 60 | } 61 | 62 | static int 63 | ldump(lua_State *L) { 64 | dump_c_mem(); 65 | 66 | return 0; 67 | } 68 | 69 | static int 70 | lcurrent(lua_State *L) { 71 | lua_pushinteger(L, malloc_current_memory()); 72 | return 1; 73 | } 74 | 75 | static int 76 | ldumpheap(lua_State *L) { 77 | mallctl_cmd("prof.dump"); 78 | return 0; 79 | } 80 | 81 | static int 82 | lprofactive(lua_State *L) { 83 | bool *pval, active; 84 | if (lua_isnone(L, 1)) { 85 | pval = NULL; 86 | } else { 87 | active = lua_toboolean(L, 1) ? true : false; 88 | pval = &active; 89 | } 90 | bool ret = mallctl_bool("prof.active", pval); 91 | lua_pushboolean(L, ret); 92 | return 1; 93 | } 94 | 95 | LUAMOD_API int 96 | luaopen_skynet_memory(lua_State *L) { 97 | luaL_checkversion(L); 98 | 99 | luaL_Reg l[] = { 100 | { "total", ltotal }, 101 | { "block", lblock }, 102 | { "dumpinfo", ldumpinfo }, 103 | { "jestat", ljestat }, 104 | { "mallctl", lmallctl }, 105 | { "dump", ldump }, 106 | { "info", dump_mem_lua }, 107 | { "current", lcurrent }, 108 | { "dumpheap", ldumpheap }, 109 | { "profactive", lprofactive }, 110 | { NULL, NULL }, 111 | }; 112 | 113 | luaL_newlib(L,l); 114 | 115 | return 1; 116 | } 117 | -------------------------------------------------------------------------------- /lualib-src/lua-seri.h: -------------------------------------------------------------------------------- 1 | #ifndef LUA_SERIALIZE_H 2 | #define LUA_SERIALIZE_H 3 | 4 | #include 5 | 6 | int luaseri_pack(lua_State *L); 7 | int luaseri_unpack(lua_State *L); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /lualib-src/sproto/README: -------------------------------------------------------------------------------- 1 | Check https://github.com/cloudwu/sproto for more 2 | -------------------------------------------------------------------------------- /lualib-src/sproto/msvcint.h: -------------------------------------------------------------------------------- 1 | #ifndef msvc_int_h 2 | #define msvc_int_h 3 | 4 | #ifdef _MSC_VER 5 | # define inline __inline 6 | # ifndef _MSC_STDINT_H_ 7 | # if (_MSC_VER < 1300) 8 | typedef signed char int8_t; 9 | typedef signed short int16_t; 10 | typedef signed int int32_t; 11 | typedef unsigned char uint8_t; 12 | typedef unsigned short uint16_t; 13 | typedef unsigned int uint32_t; 14 | # else 15 | typedef signed __int8 int8_t; 16 | typedef signed __int16 int16_t; 17 | typedef signed __int32 int32_t; 18 | typedef unsigned __int8 uint8_t; 19 | typedef unsigned __int16 uint16_t; 20 | typedef unsigned __int32 uint32_t; 21 | # endif 22 | typedef signed __int64 int64_t; 23 | typedef unsigned __int64 uint64_t; 24 | # endif 25 | 26 | #else 27 | 28 | #include 29 | 30 | #endif 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /lualib-src/sproto/sproto.h: -------------------------------------------------------------------------------- 1 | #ifndef sproto_h 2 | #define sproto_h 3 | 4 | #include 5 | 6 | struct sproto; 7 | struct sproto_type; 8 | 9 | #define SPROTO_REQUEST 0 10 | #define SPROTO_RESPONSE 1 11 | 12 | // type (sproto_arg.type) 13 | #define SPROTO_TINTEGER 0 14 | #define SPROTO_TBOOLEAN 1 15 | #define SPROTO_TSTRING 2 16 | #define SPROTO_TDOUBLE 3 17 | #define SPROTO_TSTRUCT 4 18 | 19 | // container type 20 | #define SPROTO_TARRAY 0x80 21 | 22 | // sub type of string (sproto_arg.extra) 23 | #define SPROTO_TSTRING_STRING 0 24 | #define SPROTO_TSTRING_BINARY 1 25 | 26 | #define SPROTO_CB_ERROR -1 27 | #define SPROTO_CB_NIL -2 28 | #define SPROTO_CB_NOARRAY -3 29 | 30 | struct sproto * sproto_create(const void * proto, size_t sz); 31 | void sproto_release(struct sproto *); 32 | 33 | int sproto_prototag(const struct sproto *, const char * name); 34 | const char * sproto_protoname(const struct sproto *, int proto); 35 | // SPROTO_REQUEST(0) : request, SPROTO_RESPONSE(1): response 36 | struct sproto_type * sproto_protoquery(const struct sproto *, int proto, int what); 37 | int sproto_protoresponse(const struct sproto *, int proto); 38 | 39 | struct sproto_type * sproto_type(const struct sproto *, const char * type_name); 40 | 41 | int sproto_pack(const void * src, int srcsz, void * buffer, int bufsz); 42 | int sproto_unpack(const void * src, int srcsz, void * buffer, int bufsz); 43 | 44 | struct sproto_arg { 45 | void *ud; 46 | const char *tagname; 47 | int tagid; 48 | int type; 49 | struct sproto_type *subtype; 50 | void *value; 51 | int length; 52 | int index; // array base 1, negative value indicates that it is a empty array 53 | int mainindex; // for map 54 | int extra; // SPROTO_TINTEGER: decimal ; SPROTO_TSTRING 0:utf8 string 1:binary 55 | 56 | // When interpretd two fields struct as map, the following fields must not be NULL. 57 | const char *ktagname; 58 | const char *vtagname; 59 | }; 60 | 61 | typedef int (*sproto_callback)(const struct sproto_arg *args); 62 | 63 | int sproto_decode(const struct sproto_type *, const void * data, int size, sproto_callback cb, void *ud); 64 | int sproto_encode(const struct sproto_type *, void * buffer, int size, sproto_callback cb, void *ud); 65 | 66 | // for debug use 67 | void sproto_dump(struct sproto *); 68 | const char * sproto_name(struct sproto_type *); 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /lualib/compat10/cluster.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.cluster" -------------------------------------------------------------------------------- /lualib/compat10/crypt.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.crypt" -------------------------------------------------------------------------------- /lualib/compat10/datacenter.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.datacenter" -------------------------------------------------------------------------------- /lualib/compat10/dns.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.dns" -------------------------------------------------------------------------------- /lualib/compat10/memory.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.memory" -------------------------------------------------------------------------------- /lualib/compat10/mongo.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.db.mongo" -------------------------------------------------------------------------------- /lualib/compat10/mqueue.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.mqueue" -------------------------------------------------------------------------------- /lualib/compat10/multicast.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.multicast" -------------------------------------------------------------------------------- /lualib/compat10/mysql.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.db.mysql" -------------------------------------------------------------------------------- /lualib/compat10/netpack.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.netpack" -------------------------------------------------------------------------------- /lualib/compat10/profile.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.profile" -------------------------------------------------------------------------------- /lualib/compat10/redis.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.db.redis" -------------------------------------------------------------------------------- /lualib/compat10/sharedata.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.sharedata" -------------------------------------------------------------------------------- /lualib/compat10/sharemap.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.sharemap" -------------------------------------------------------------------------------- /lualib/compat10/snax.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.snax" -------------------------------------------------------------------------------- /lualib/compat10/socket.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.socket" -------------------------------------------------------------------------------- /lualib/compat10/socketchannel.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.socketchannel" -------------------------------------------------------------------------------- /lualib/compat10/socketdriver.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.socketdriver" -------------------------------------------------------------------------------- /lualib/compat10/stm.lua: -------------------------------------------------------------------------------- 1 | return require "skynet.stm" -------------------------------------------------------------------------------- /lualib/http/sockethelper.lua: -------------------------------------------------------------------------------- 1 | local socket = require "skynet.socket" 2 | local skynet = require "skynet" 3 | 4 | local readbytes = socket.read 5 | local writebytes = socket.write 6 | 7 | local sockethelper = {} 8 | local socket_error = setmetatable({} , { __tostring = function() return "[Socket Error]" end }) 9 | 10 | sockethelper.socket_error = socket_error 11 | 12 | local function preread(fd, str) 13 | return function (sz) 14 | if str then 15 | if sz == #str or sz == nil then 16 | local ret = str 17 | str = nil 18 | return ret 19 | else 20 | if sz < #str then 21 | local ret = str:sub(1,sz) 22 | str = str:sub(sz + 1) 23 | return ret 24 | else 25 | sz = sz - #str 26 | local ret = readbytes(fd, sz) 27 | if ret then 28 | return str .. ret 29 | else 30 | error(socket_error) 31 | end 32 | end 33 | end 34 | else 35 | local ret = readbytes(fd, sz) 36 | if ret then 37 | return ret 38 | else 39 | error(socket_error) 40 | end 41 | end 42 | end 43 | end 44 | 45 | function sockethelper.readfunc(fd, pre) 46 | if pre then 47 | return preread(fd, pre) 48 | end 49 | return function (sz) 50 | local ret = readbytes(fd, sz) 51 | if ret then 52 | return ret 53 | else 54 | error(socket_error) 55 | end 56 | end 57 | end 58 | 59 | sockethelper.readall = socket.readall 60 | 61 | function sockethelper.writefunc(fd) 62 | return function(content) 63 | local ok = writebytes(fd, content) 64 | if not ok then 65 | error(socket_error) 66 | end 67 | end 68 | end 69 | 70 | function sockethelper.connect(host, port, timeout) 71 | local fd 72 | if timeout then 73 | local drop_fd 74 | local co = coroutine.running() 75 | -- asynchronous connect 76 | skynet.fork(function() 77 | fd = socket.open(host, port) 78 | if drop_fd then 79 | -- sockethelper.connect already return, and raise socket_error 80 | socket.close(fd) 81 | else 82 | -- socket.open before sleep, wakeup. 83 | skynet.wakeup(co) 84 | end 85 | end) 86 | skynet.sleep(timeout) 87 | if not fd then 88 | -- not connect yet 89 | drop_fd = true 90 | end 91 | else 92 | -- block connect 93 | fd = socket.open(host, port) 94 | end 95 | if fd then 96 | return fd 97 | end 98 | error(socket_error) 99 | end 100 | 101 | function sockethelper.close(fd) 102 | socket.close(fd) 103 | end 104 | 105 | function sockethelper.shutdown(fd) 106 | socket.shutdown(fd) 107 | end 108 | 109 | return sockethelper 110 | -------------------------------------------------------------------------------- /lualib/http/tlshelper.lua: -------------------------------------------------------------------------------- 1 | local socket = require "http.sockethelper" 2 | local c = require "ltls.c" 3 | 4 | local tlshelper = {} 5 | 6 | function tlshelper.init_requestfunc(fd, tls_ctx) 7 | local readfunc = socket.readfunc(fd) 8 | local writefunc = socket.writefunc(fd) 9 | return function () 10 | local ds1 = tls_ctx:handshake() 11 | writefunc(ds1) 12 | while not tls_ctx:finished() do 13 | local ds2 = readfunc() 14 | local ds3 = tls_ctx:handshake(ds2) 15 | if ds3 then 16 | writefunc(ds3) 17 | end 18 | end 19 | end 20 | end 21 | 22 | 23 | function tlshelper.init_responsefunc(fd, tls_ctx) 24 | local readfunc = socket.readfunc(fd) 25 | local writefunc = socket.writefunc(fd) 26 | return function () 27 | while not tls_ctx:finished() do 28 | local ds1 = readfunc() 29 | local ds2 = tls_ctx:handshake(ds1) 30 | if ds2 then 31 | writefunc(ds2) 32 | end 33 | end 34 | local ds3 = tls_ctx:write() 35 | writefunc(ds3) 36 | end 37 | end 38 | 39 | function tlshelper.closefunc(tls_ctx) 40 | return function () 41 | tls_ctx:close() 42 | end 43 | end 44 | 45 | function tlshelper.readfunc(fd, tls_ctx) 46 | local function readfunc() 47 | readfunc = socket.readfunc(fd) 48 | return "" 49 | end 50 | local read_buff = "" 51 | return function (sz) 52 | if not sz then 53 | local s = "" 54 | if #read_buff == 0 then 55 | local ds = readfunc() 56 | s = tls_ctx:read(ds) 57 | end 58 | s = read_buff .. s 59 | read_buff = "" 60 | return s 61 | else 62 | while #read_buff < sz do 63 | local ds = readfunc() 64 | local s = tls_ctx:read(ds) 65 | read_buff = read_buff .. s 66 | end 67 | local s = string.sub(read_buff, 1, sz) 68 | read_buff = string.sub(read_buff, sz+1, #read_buff) 69 | return s 70 | end 71 | end 72 | end 73 | 74 | function tlshelper.writefunc(fd, tls_ctx) 75 | local writefunc = socket.writefunc(fd) 76 | return function (s) 77 | local ds = tls_ctx:write(s) 78 | return writefunc(ds) 79 | end 80 | end 81 | 82 | function tlshelper.readallfunc(fd, tls_ctx) 83 | return function () 84 | local ds = socket.readall(fd) 85 | local s = tls_ctx:read(ds) 86 | return s 87 | end 88 | end 89 | 90 | function tlshelper.newctx() 91 | return c.newctx() 92 | end 93 | 94 | function tlshelper.newtls(method, ssl_ctx, hostname) 95 | return c.newtls(method, ssl_ctx, hostname) 96 | end 97 | 98 | return tlshelper -------------------------------------------------------------------------------- /lualib/http/url.lua: -------------------------------------------------------------------------------- 1 | local url = {} 2 | 3 | local function decode_func(c) 4 | return string.char(tonumber(c, 16)) 5 | end 6 | 7 | local function decode(str) 8 | local str = str:gsub('+', ' ') 9 | return str:gsub("%%(..)", decode_func) 10 | end 11 | 12 | function url.parse(u) 13 | local path,query = u:match "([^?]*)%??(.*)" 14 | if path then 15 | path = decode(path) 16 | end 17 | return path, query 18 | end 19 | 20 | function url.parse_query(q) 21 | local r = {} 22 | for k,v in q:gmatch "(.-)=([^&]*)&?" do 23 | r[decode(k)] = decode(v) 24 | end 25 | return r 26 | end 27 | 28 | return url 29 | -------------------------------------------------------------------------------- /lualib/loader.lua: -------------------------------------------------------------------------------- 1 | local args = {} 2 | for word in string.gmatch(..., "%S+") do 3 | table.insert(args, word) 4 | end 5 | 6 | SERVICE_NAME = args[1] 7 | 8 | local main, pattern 9 | 10 | local err = {} 11 | for pat in string.gmatch(LUA_SERVICE, "([^;]+);*") do 12 | local filename = string.gsub(pat, "?", SERVICE_NAME) 13 | local f, msg = loadfile(filename) 14 | if not f then 15 | table.insert(err, msg) 16 | else 17 | pattern = pat 18 | main = f 19 | break 20 | end 21 | end 22 | 23 | if not main then 24 | error(table.concat(err, "\n")) 25 | end 26 | 27 | LUA_SERVICE = nil 28 | package.path , LUA_PATH = LUA_PATH 29 | package.cpath , LUA_CPATH = LUA_CPATH 30 | 31 | local service_path = string.match(pattern, "(.*/)[^/?]+$") 32 | 33 | if service_path then 34 | service_path = string.gsub(service_path, "?", args[1]) 35 | package.path = service_path .. "?.lua;" .. package.path 36 | SERVICE_PATH = service_path 37 | else 38 | local p = string.match(pattern, "(.*/).+$") 39 | SERVICE_PATH = p 40 | end 41 | 42 | if LUA_PRELOAD then 43 | local f = assert(loadfile(LUA_PRELOAD)) 44 | f(table.unpack(args)) 45 | LUA_PRELOAD = nil 46 | end 47 | 48 | _G.require = (require "skynet.require").require 49 | 50 | main(select(2, table.unpack(args))) 51 | -------------------------------------------------------------------------------- /lualib/md5.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- Modify version from https://github.com/keplerproject/md5 3 | ---------------------------------------------------------------------------- 4 | 5 | local core = require "md5.core" 6 | 7 | ---------------------------------------------------------------------------- 8 | -- @param k String with original message. 9 | -- @return String with the md5 hash value converted to hexadecimal digits 10 | 11 | function core.sumhexa (k) 12 | k = core.sum(k) 13 | return (string.gsub(k, ".", function (c) 14 | return string.format("%02x", string.byte(c)) 15 | end)) 16 | end 17 | 18 | local function get_ipad(c) 19 | return string.char(c:byte() ~ 0x36) 20 | end 21 | 22 | local function get_opad(c) 23 | return string.char(c:byte() ~ 0x5c) 24 | end 25 | 26 | function core.hmacmd5(data,key) 27 | if #key>64 then 28 | key=core.sum(key) 29 | key=key:sub(1,16) 30 | end 31 | local ipad_s=key:gsub(".", get_ipad)..string.rep("6",64-#key) 32 | local opad_s=key:gsub(".", get_opad)..string.rep("\\",64-#key) 33 | local istr=core.sum(ipad_s..data) 34 | local ostr=core.sumhexa(opad_s..istr) 35 | return ostr 36 | end 37 | 38 | return core 39 | -------------------------------------------------------------------------------- /lualib/skynet/datacenter.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local datacenter = {} 4 | 5 | function datacenter.get(...) 6 | return skynet.call("DATACENTER", "lua", "QUERY", ...) 7 | end 8 | 9 | function datacenter.set(...) 10 | return skynet.call("DATACENTER", "lua", "UPDATE", ...) 11 | end 12 | 13 | function datacenter.wait(...) 14 | return skynet.call("DATACENTER", "lua", "WAIT", ...) 15 | end 16 | 17 | return datacenter 18 | 19 | -------------------------------------------------------------------------------- /lualib/skynet/datasheet/init.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local service = require "skynet.service" 3 | local core = require "skynet.datasheet.core" 4 | 5 | local datasheet_svr 6 | 7 | skynet.init(function() 8 | datasheet_svr = service.query "datasheet" 9 | end) 10 | 11 | local datasheet = {} 12 | local sheets = setmetatable({}, { 13 | __gc = function(t) 14 | skynet.send(datasheet_svr, "lua", "close") 15 | end, 16 | }) 17 | 18 | local function querysheet(name) 19 | return skynet.call(datasheet_svr, "lua", "query", name) 20 | end 21 | 22 | local function updateobject(name) 23 | local t = sheets[name] 24 | if not t.object then 25 | t.object = core.new(t.handle) 26 | end 27 | local function monitor() 28 | local handle = t.handle 29 | local newhandle = skynet.call(datasheet_svr, "lua", "monitor", handle) 30 | core.update(t.object, newhandle) 31 | t.handle = newhandle 32 | skynet.send(datasheet_svr, "lua", "release", handle) 33 | return monitor() 34 | end 35 | skynet.fork(monitor) 36 | end 37 | 38 | function datasheet.query(name) 39 | local t = sheets[name] 40 | if not t then 41 | t = {} 42 | sheets[name] = t 43 | end 44 | if t.error then 45 | error(t.error) 46 | end 47 | if t.object then 48 | return t.object 49 | end 50 | if t.queue then 51 | local co = coroutine.running() 52 | table.insert(t.queue, co) 53 | skynet.wait(co) 54 | else 55 | t.queue = {} -- create wait queue for other query 56 | local ok, handle = pcall(querysheet, name) 57 | if ok then 58 | t.handle = handle 59 | updateobject(name) 60 | else 61 | t.error = handle 62 | end 63 | local q = t.queue 64 | t.queue = nil 65 | for _, co in ipairs(q) do 66 | skynet.wakeup(co) 67 | end 68 | end 69 | if t.error then 70 | error(t.error) 71 | end 72 | return t.object 73 | end 74 | 75 | return datasheet 76 | -------------------------------------------------------------------------------- /lualib/skynet/harbor.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local harbor = {} 4 | 5 | function harbor.globalname(name, handle) 6 | handle = handle or skynet.self() 7 | skynet.send(".cslave", "lua", "REGISTER", name, handle) 8 | end 9 | 10 | function harbor.queryname(name) 11 | return skynet.call(".cslave", "lua", "QUERYNAME", name) 12 | end 13 | 14 | function harbor.link(id) 15 | skynet.call(".cslave", "lua", "LINK", id) 16 | end 17 | 18 | function harbor.connect(id) 19 | skynet.call(".cslave", "lua", "CONNECT", id) 20 | end 21 | 22 | function harbor.linkmaster() 23 | skynet.call(".cslave", "lua", "LINKMASTER") 24 | end 25 | 26 | return harbor 27 | -------------------------------------------------------------------------------- /lualib/skynet/inject.lua: -------------------------------------------------------------------------------- 1 | local function getupvaluetable(u, func, unique) 2 | local i = 1 3 | while true do 4 | local name, value = debug.getupvalue(func, i) 5 | if name == nil then 6 | return 7 | end 8 | local t = type(value) 9 | if t == "table" then 10 | u[name] = value 11 | elseif t == "function" then 12 | if not unique[value] then 13 | unique[value] = true 14 | getupvaluetable(u, value, unique) 15 | end 16 | end 17 | i=i+1 18 | end 19 | end 20 | 21 | return function(skynet, source, filename, args, ...) 22 | if filename then 23 | filename = "@" .. filename 24 | else 25 | filename = "=(load)" 26 | end 27 | local output = {} 28 | 29 | local function print(...) 30 | local value = { ... } 31 | for k,v in ipairs(value) do 32 | value[k] = tostring(v) 33 | end 34 | table.insert(output, table.concat(value, "\t")) 35 | end 36 | local u = {} 37 | local unique = {} 38 | local funcs = { ... } 39 | for k, func in ipairs(funcs) do 40 | getupvaluetable(u, func, unique) 41 | end 42 | local p = {} 43 | local proto = u.proto 44 | if proto then 45 | for k,v in pairs(proto) do 46 | local name, dispatch = v.name, v.dispatch 47 | if name and dispatch and not p[name] then 48 | local pp = {} 49 | p[name] = pp 50 | getupvaluetable(pp, dispatch, unique) 51 | end 52 | end 53 | end 54 | local env = setmetatable( { print = print , _U = u, _P = p}, { __index = _ENV }) 55 | local func, err = load(source, filename, "bt", env) 56 | if not func then 57 | return false, { err } 58 | end 59 | local ok, err = skynet.pcall(func, table.unpack(args, 1, args.n)) 60 | if not ok then 61 | table.insert(output, err) 62 | return false, output 63 | end 64 | 65 | return true, output 66 | end 67 | -------------------------------------------------------------------------------- /lualib/skynet/manager.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local c = require "skynet.core" 3 | 4 | local function number_address(name) 5 | local t = type(name) 6 | if t == "number" then 7 | return name 8 | elseif t == "string" then 9 | local hex = name:match "^:(%x+)" 10 | if hex then 11 | return tonumber(hex, 16) 12 | end 13 | end 14 | end 15 | 16 | function skynet.launch(...) 17 | local addr = c.command("LAUNCH", table.concat({...}," ")) 18 | if addr then 19 | return tonumber(string.sub(addr , 2), 16) 20 | end 21 | end 22 | 23 | function skynet.kill(name) 24 | local addr = number_address(name) 25 | if addr then 26 | skynet.send(".launcher","lua","REMOVE", addr, true) 27 | name = skynet.address(addr) 28 | end 29 | c.command("KILL",name) 30 | end 31 | 32 | function skynet.abort() 33 | c.command("ABORT") 34 | end 35 | 36 | local function globalname(name, handle) 37 | local c = string.sub(name,1,1) 38 | assert(c ~= ':') 39 | if c == '.' then 40 | return false 41 | end 42 | 43 | assert(#name < 16) -- GLOBALNAME_LENGTH is 16, defined in skynet_harbor.h 44 | assert(tonumber(name) == nil) -- global name can't be number 45 | 46 | local harbor = require "skynet.harbor" 47 | 48 | harbor.globalname(name, handle) 49 | 50 | return true 51 | end 52 | 53 | function skynet.register(name) 54 | if not globalname(name) then 55 | c.command("REG", name) 56 | end 57 | end 58 | 59 | function skynet.name(name, handle) 60 | if not globalname(name, handle) then 61 | c.command("NAME", name .. " " .. skynet.address(handle)) 62 | end 63 | end 64 | 65 | local dispatch_message = skynet.dispatch_message 66 | 67 | function skynet.forward_type(map, start_func) 68 | c.callback(function(ptype, msg, sz, ...) 69 | local prototype = map[ptype] 70 | if prototype then 71 | dispatch_message(prototype, msg, sz, ...) 72 | else 73 | local ok, err = pcall(dispatch_message, ptype, msg, sz, ...) 74 | c.trash(msg, sz) 75 | if not ok then 76 | error(err) 77 | end 78 | end 79 | end, true) 80 | skynet.timeout(0, function() 81 | skynet.init_service(start_func) 82 | end) 83 | end 84 | 85 | function skynet.filter(f ,start_func) 86 | c.callback(function(...) 87 | dispatch_message(f(...)) 88 | end) 89 | skynet.timeout(0, function() 90 | skynet.init_service(start_func) 91 | end) 92 | end 93 | 94 | function skynet.monitor(service, query) 95 | local monitor 96 | if query then 97 | monitor = skynet.queryservice(true, service) 98 | else 99 | monitor = skynet.uniqueservice(true, service) 100 | end 101 | assert(monitor, "Monitor launch failed") 102 | c.command("MONITOR", string.format(":%08x", monitor)) 103 | return monitor 104 | end 105 | 106 | return skynet 107 | -------------------------------------------------------------------------------- /lualib/skynet/mqueue.lua: -------------------------------------------------------------------------------- 1 | -- This is a deprecated module, use skynet.queue instead. 2 | 3 | local skynet = require "skynet" 4 | local c = require "skynet.core" 5 | 6 | local mqueue = {} 7 | local init_once 8 | local thread_id 9 | local message_queue = {} 10 | 11 | skynet.register_protocol { 12 | name = "queue", 13 | -- please read skynet.h for magic number 8 14 | id = 8, 15 | pack = skynet.pack, 16 | unpack = skynet.unpack, 17 | dispatch = function(session, from, ...) 18 | table.insert(message_queue, {session = session, addr = from, ... }) 19 | if thread_id then 20 | skynet.wakeup(thread_id) 21 | thread_id = nil 22 | end 23 | end 24 | } 25 | 26 | local function do_func(f, msg) 27 | return pcall(f, table.unpack(msg)) 28 | end 29 | 30 | local function message_dispatch(f) 31 | while true do 32 | if #message_queue==0 then 33 | thread_id = coroutine.running() 34 | skynet.wait() 35 | else 36 | local msg = table.remove(message_queue,1) 37 | local session = msg.session 38 | if session == 0 then 39 | local ok, msg = do_func(f, msg) 40 | if ok then 41 | if msg then 42 | skynet.fork(message_dispatch,f) 43 | error(string.format("[:%x] send a message to [:%x] return something", msg.addr, skynet.self())) 44 | end 45 | else 46 | skynet.fork(message_dispatch,f) 47 | error(string.format("[:%x] send a message to [:%x] throw an error : %s", msg.addr, skynet.self(),msg)) 48 | end 49 | else 50 | local data, size = skynet.pack(do_func(f,msg)) 51 | -- 1 means response 52 | c.send(msg.addr, 1, session, data, size) 53 | end 54 | end 55 | end 56 | end 57 | 58 | function mqueue.register(f) 59 | assert(init_once == nil) 60 | init_once = true 61 | skynet.fork(message_dispatch,f) 62 | end 63 | 64 | local function catch(succ, ...) 65 | if succ then 66 | return ... 67 | else 68 | error(...) 69 | end 70 | end 71 | 72 | function mqueue.call(addr, ...) 73 | return catch(skynet.call(addr, "queue", ...)) 74 | end 75 | 76 | function mqueue.send(addr, ...) 77 | return skynet.send(addr, "queue", ...) 78 | end 79 | 80 | function mqueue.size() 81 | return #message_queue 82 | end 83 | 84 | return mqueue 85 | -------------------------------------------------------------------------------- /lualib/skynet/multicast.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local mc = require "skynet.multicast.core" 3 | 4 | local multicastd 5 | local multicast = {} 6 | local dispatch = {} 7 | 8 | local chan = {} 9 | local chan_meta = { 10 | __index = chan, 11 | __gc = function(self) 12 | self:unsubscribe() 13 | end, 14 | __tostring = function (self) 15 | return string.format("[Multicast:%x]",self.channel) 16 | end, 17 | } 18 | 19 | function multicast.new(conf) 20 | assert(multicastd, "Init first") 21 | local self = {} 22 | conf = conf or self 23 | self.channel = conf.channel 24 | if self.channel == nil then 25 | self.channel = skynet.call(multicastd, "lua", "NEW") 26 | end 27 | self.__pack = conf.pack or skynet.pack 28 | self.__unpack = conf.unpack or skynet.unpack 29 | self.__dispatch = conf.dispatch 30 | 31 | return setmetatable(self, chan_meta) 32 | end 33 | 34 | function chan:delete() 35 | local c = assert(self.channel) 36 | skynet.send(multicastd, "lua", "DEL", c) 37 | self.channel = nil 38 | self.__subscribe = nil 39 | end 40 | 41 | function chan:publish(...) 42 | local c = assert(self.channel) 43 | skynet.call(multicastd, "lua", "PUB", c, mc.pack(self.__pack(...))) 44 | end 45 | 46 | function chan:subscribe() 47 | local c = assert(self.channel) 48 | if self.__subscribe then 49 | -- already subscribe 50 | return 51 | end 52 | skynet.call(multicastd, "lua", "SUB", c) 53 | self.__subscribe = true 54 | dispatch[c] = self 55 | end 56 | 57 | function chan:unsubscribe() 58 | if not self.__subscribe then 59 | -- already unsubscribe 60 | return 61 | end 62 | local c = assert(self.channel) 63 | skynet.send(multicastd, "lua", "USUB", c) 64 | self.__subscribe = nil 65 | dispatch[c] = nil 66 | end 67 | 68 | local function dispatch_subscribe(channel, source, pack, msg, sz) 69 | -- channel as session, do need response 70 | skynet.ignoreret() 71 | local self = dispatch[channel] 72 | if not self then 73 | mc.close(pack) 74 | -- This channel may unsubscribe first, see #1141 75 | return 76 | end 77 | 78 | if self.__subscribe then 79 | local ok, err = pcall(self.__dispatch, self, source, self.__unpack(msg, sz)) 80 | mc.close(pack) 81 | assert(ok, err) 82 | else 83 | -- maybe unsubscribe first, but the message is send out. drop the message unneed 84 | mc.close(pack) 85 | end 86 | end 87 | 88 | local function init() 89 | multicastd = skynet.uniqueservice "multicastd" 90 | skynet.register_protocol { 91 | name = "multicast", 92 | id = skynet.PTYPE_MULTICAST, 93 | unpack = mc.unpack, 94 | dispatch = dispatch_subscribe, 95 | } 96 | end 97 | 98 | skynet.init(init) 99 | 100 | return multicast -------------------------------------------------------------------------------- /lualib/skynet/queue.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local coroutine = coroutine 3 | local xpcall = xpcall 4 | local traceback = debug.traceback 5 | local table = table 6 | 7 | function skynet.queue() 8 | local current_thread 9 | local ref = 0 10 | local thread_queue = {} 11 | 12 | local function xpcall_ret(ok, ...) 13 | ref = ref - 1 14 | if ref == 0 then 15 | current_thread = table.remove(thread_queue,1) 16 | if current_thread then 17 | skynet.wakeup(current_thread) 18 | end 19 | end 20 | assert(ok, (...)) 21 | return ... 22 | end 23 | 24 | return function(f, ...) 25 | local thread = coroutine.running() 26 | if current_thread and current_thread ~= thread then 27 | table.insert(thread_queue, thread) 28 | skynet.wait() 29 | assert(ref == 0) -- current_thread == thread 30 | end 31 | current_thread = thread 32 | 33 | ref = ref + 1 34 | return xpcall_ret(xpcall(f, traceback, ...)) 35 | end 36 | end 37 | 38 | return skynet.queue 39 | -------------------------------------------------------------------------------- /lualib/skynet/service.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local service = {} 4 | local cache = {} 5 | local provider 6 | 7 | local function get_provider() 8 | provider = provider or skynet.uniqueservice "service_provider" 9 | return provider 10 | end 11 | 12 | local function check(func) 13 | local info = debug.getinfo(func, "u") 14 | assert(info.nups == 1) 15 | assert(debug.getupvalue(func,1) == "_ENV") 16 | end 17 | 18 | function service.new(name, mainfunc, ...) 19 | local p = get_provider() 20 | local addr, booting = skynet.call(p, "lua", "test", name) 21 | local address 22 | if addr then 23 | address = addr 24 | else 25 | if booting then 26 | address = skynet.call(p, "lua", "query", name) 27 | else 28 | check(mainfunc) 29 | local code = string.dump(mainfunc) 30 | address = skynet.call(p, "lua", "launch", name, code, ...) 31 | end 32 | end 33 | cache[name] = address 34 | return address 35 | end 36 | 37 | function service.close(name) 38 | local addr = skynet.call(get_provider(), "lua", "close", name) 39 | if addr then 40 | cache[name] = nil 41 | skynet.kill(addr) 42 | return true 43 | end 44 | return false 45 | end 46 | 47 | function service.query(name) 48 | if not cache[name] then 49 | cache[name] = skynet.call(get_provider(), "lua", "query", name) 50 | end 51 | return cache[name] 52 | end 53 | 54 | return service 55 | -------------------------------------------------------------------------------- /lualib/skynet/sharedata.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local sd = require "skynet.sharedata.corelib" 3 | 4 | local service 5 | 6 | skynet.init(function() 7 | service = skynet.uniqueservice "sharedatad" 8 | end) 9 | 10 | local sharedata = {} 11 | local cache = setmetatable({}, { __mode = "kv" }) 12 | 13 | local function monitor(name, obj, cobj) 14 | local newobj = cobj 15 | while true do 16 | newobj = skynet.call(service, "lua", "monitor", name, newobj) 17 | if newobj == nil then 18 | break 19 | end 20 | sd.update(obj, newobj) 21 | skynet.send(service, "lua", "confirm" , newobj) 22 | end 23 | if cache[name] == obj then 24 | cache[name] = nil 25 | end 26 | end 27 | 28 | function sharedata.query(name) 29 | if cache[name] then 30 | return cache[name] 31 | end 32 | local obj = skynet.call(service, "lua", "query", name) 33 | if cache[name] and cache[name].__obj == obj then 34 | skynet.send(service, "lua", "confirm" , obj) 35 | return cache[name] 36 | end 37 | local r = sd.box(obj) 38 | skynet.send(service, "lua", "confirm" , obj) 39 | skynet.fork(monitor,name, r, obj) 40 | cache[name] = r 41 | return r 42 | end 43 | 44 | function sharedata.new(name, v, ...) 45 | skynet.call(service, "lua", "new", name, v, ...) 46 | end 47 | 48 | function sharedata.update(name, v, ...) 49 | skynet.call(service, "lua", "update", name, v, ...) 50 | end 51 | 52 | function sharedata.delete(name) 53 | skynet.call(service, "lua", "delete", name) 54 | end 55 | 56 | function sharedata.flush() 57 | for name, obj in pairs(cache) do 58 | sd.flush(obj) 59 | end 60 | collectgarbage() 61 | end 62 | 63 | function sharedata.deepcopy(name, ...) 64 | if cache[name] then 65 | local cobj = cache[name].__obj 66 | return sd.copy(cobj, ...) 67 | end 68 | 69 | local cobj = skynet.call(service, "lua", "query", name) 70 | local ret = sd.copy(cobj, ...) 71 | skynet.send(service, "lua", "confirm" , cobj) 72 | return ret 73 | end 74 | 75 | return sharedata 76 | -------------------------------------------------------------------------------- /lualib/skynet/sharemap.lua: -------------------------------------------------------------------------------- 1 | local stm = require "skynet.stm" 2 | local sprotoloader = require "sprotoloader" 3 | local sproto = require "sproto" 4 | local setmetatable = setmetatable 5 | 6 | local sharemap = {} 7 | 8 | function sharemap.register(protofile) 9 | -- use global slot 0 for type define 10 | sprotoloader.register(protofile, 0) 11 | end 12 | 13 | local sprotoobj 14 | local function loadsp() 15 | if sprotoobj == nil then 16 | sprotoobj = sprotoloader.load(0) 17 | end 18 | return sprotoobj 19 | end 20 | 21 | function sharemap:commit() 22 | self.__obj(sprotoobj:encode(self.__typename, self.__data)) 23 | end 24 | 25 | function sharemap:copy() 26 | return stm.copy(self.__obj) 27 | end 28 | 29 | function sharemap.writer(typename, obj) 30 | local sp = loadsp() 31 | obj = obj or {} 32 | local stmobj = stm.new(sp:encode(typename,obj)) 33 | local ret = { 34 | __typename = typename, 35 | __obj = stmobj, 36 | __data = obj, 37 | commit = sharemap.commit, 38 | copy = sharemap.copy, 39 | } 40 | return setmetatable(ret, { __index = obj, __newindex = obj }) 41 | end 42 | 43 | local function decode(msg, sz, self) 44 | local data = self.__data 45 | for k in pairs(data) do 46 | data[k] = nil 47 | end 48 | return sprotoobj:decode(self.__typename, msg, sz, data) 49 | end 50 | 51 | function sharemap:update() 52 | return self.__obj(decode, self) 53 | end 54 | 55 | function sharemap.reader(typename, stmcpy) 56 | local sp = loadsp() 57 | local stmobj = stm.newcopy(stmcpy) 58 | local _, data = stmobj(function(msg, sz) 59 | return sp:decode(typename, msg, sz) 60 | end) 61 | 62 | local obj = { 63 | __typename = typename, 64 | __obj = stmobj, 65 | __data = data, 66 | update = sharemap.update, 67 | } 68 | return setmetatable(obj, { __index = data, __newindex = error }) 69 | end 70 | 71 | return sharemap 72 | -------------------------------------------------------------------------------- /lualib/snax/interface.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local function dft_loader(path, name, G) 4 | local errlist = {} 5 | 6 | for pat in string.gmatch(path,"[^;]+") do 7 | local filename = string.gsub(pat, "?", name) 8 | local f , err = loadfile(filename, "bt", G) 9 | if f then 10 | return f, pat 11 | else 12 | table.insert(errlist, err) 13 | end 14 | end 15 | 16 | error(table.concat(errlist, "\n")) 17 | end 18 | 19 | return function (name , G, loader) 20 | loader = loader or dft_loader 21 | 22 | local function func_id(id, group) 23 | local tmp = {} 24 | local function count( _, name, func) 25 | if type(name) ~= "string" then 26 | error (string.format("%s method only support string", group)) 27 | end 28 | if type(func) ~= "function" then 29 | error (string.format("%s.%s must be function"), group, name) 30 | end 31 | if tmp[name] then 32 | error (string.format("%s.%s duplicate definition", group, name)) 33 | end 34 | tmp[name] = true 35 | table.insert(id, { #id + 1, group, name, func} ) 36 | end 37 | return setmetatable({}, { __newindex = count }) 38 | end 39 | 40 | do 41 | assert(getmetatable(G) == nil) 42 | assert(G.init == nil) 43 | assert(G.exit == nil) 44 | assert(G.accept == nil) 45 | assert(G.response == nil) 46 | end 47 | 48 | local temp_global = {} 49 | local env = setmetatable({} , { __index = temp_global }) 50 | local func = {} 51 | 52 | local system = { "init", "exit", "hotfix", "profile"} 53 | 54 | do 55 | for k, v in ipairs(system) do 56 | system[v] = k 57 | func[k] = { k , "system", v } 58 | end 59 | end 60 | 61 | env.accept = func_id(func, "accept") 62 | env.response = func_id(func, "response") 63 | 64 | local function init_system(t, name, f) 65 | local index = system[name] 66 | if index then 67 | if type(f) ~= "function" then 68 | error (string.format("%s must be a function", name)) 69 | end 70 | func[index][4] = f 71 | else 72 | temp_global[name] = f 73 | end 74 | end 75 | 76 | local path = assert(skynet.getenv "snax" , "please set snax in config file") 77 | local mainfunc, pattern = loader(path, name, G) 78 | 79 | setmetatable(G, { __index = env , __newindex = init_system }) 80 | local ok, err = xpcall(mainfunc, debug.traceback) 81 | setmetatable(G, nil) 82 | assert(ok,err) 83 | 84 | for k,v in pairs(temp_global) do 85 | G[k] = v 86 | end 87 | 88 | return func, pattern 89 | end 90 | -------------------------------------------------------------------------------- /lualib/sprotoloader.lua: -------------------------------------------------------------------------------- 1 | local parser = require "sprotoparser" 2 | local core = require "sproto.core" 3 | local sproto = require "sproto" 4 | 5 | local loader = {} 6 | 7 | function loader.register(filename, index) 8 | local f = assert(io.open(filename), "Can't open sproto file") 9 | local data = f:read "a" 10 | f:close() 11 | local sp = core.newproto(parser.parse(data)) 12 | core.saveproto(sp, index) 13 | end 14 | 15 | function loader.save(bin, index) 16 | local sp = core.newproto(bin) 17 | core.saveproto(sp, index) 18 | end 19 | 20 | function loader.load(index) 21 | local sp = core.loadproto(index) 22 | -- no __gc in metatable 23 | return sproto.sharenew(sp) 24 | end 25 | 26 | return loader 27 | 28 | -------------------------------------------------------------------------------- /platform.mk: -------------------------------------------------------------------------------- 1 | PLAT ?= none 2 | PLATS = linux freebsd macosx 3 | 4 | CC ?= gcc 5 | 6 | .PHONY : none $(PLATS) clean all cleanall 7 | 8 | #ifneq ($(PLAT), none) 9 | 10 | .PHONY : default 11 | 12 | default : 13 | $(MAKE) $(PLAT) 14 | 15 | #endif 16 | 17 | none : 18 | @echo "Please do 'make PLATFORM' where PLATFORM is one of these:" 19 | @echo " $(PLATS)" 20 | 21 | SKYNET_LIBS := -lpthread -lm 22 | SHARED := -fPIC --shared 23 | EXPORT := -Wl,-E 24 | 25 | linux : PLAT = linux 26 | macosx : PLAT = macosx 27 | freebsd : PLAT = freebsd 28 | 29 | macosx : SHARED := -fPIC -dynamiclib -Wl,-undefined,dynamic_lookup 30 | macosx : EXPORT := 31 | macosx linux : SKYNET_LIBS += -ldl 32 | linux freebsd : SKYNET_LIBS += -lrt 33 | 34 | # Turn off jemalloc and malloc hook on macosx 35 | 36 | macosx : MALLOC_STATICLIB := 37 | macosx : SKYNET_DEFINES :=-DNOUSE_JEMALLOC 38 | 39 | linux macosx freebsd : 40 | $(MAKE) all PLAT=$@ SKYNET_LIBS="$(SKYNET_LIBS)" SHARED="$(SHARED)" EXPORT="$(EXPORT)" MALLOC_STATICLIB="$(MALLOC_STATICLIB)" SKYNET_DEFINES="$(SKYNET_DEFINES)" 41 | -------------------------------------------------------------------------------- /service-src/hashid.h: -------------------------------------------------------------------------------- 1 | #ifndef skynet_hashid_h 2 | #define skynet_hashid_h 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | struct hashid_node { 9 | int id; 10 | struct hashid_node *next; 11 | }; 12 | 13 | struct hashid { 14 | int hashmod; 15 | int cap; 16 | int count; 17 | struct hashid_node *id; 18 | struct hashid_node **hash; 19 | }; 20 | 21 | static void 22 | hashid_init(struct hashid *hi, int max) { 23 | int i; 24 | int hashcap; 25 | hashcap = 16; 26 | while (hashcap < max) { 27 | hashcap *= 2; 28 | } 29 | hi->hashmod = hashcap - 1; 30 | hi->cap = max; 31 | hi->count = 0; 32 | hi->id = skynet_malloc(max * sizeof(struct hashid_node)); 33 | for (i=0;iid[i].id = -1; 35 | hi->id[i].next = NULL; 36 | } 37 | hi->hash = skynet_malloc(hashcap * sizeof(struct hashid_node *)); 38 | memset(hi->hash, 0, hashcap * sizeof(struct hashid_node *)); 39 | } 40 | 41 | static void 42 | hashid_clear(struct hashid *hi) { 43 | skynet_free(hi->id); 44 | skynet_free(hi->hash); 45 | hi->id = NULL; 46 | hi->hash = NULL; 47 | hi->hashmod = 1; 48 | hi->cap = 0; 49 | hi->count = 0; 50 | } 51 | 52 | static int 53 | hashid_lookup(struct hashid *hi, int id) { 54 | int h = id & hi->hashmod; 55 | struct hashid_node * c = hi->hash[h]; 56 | while(c) { 57 | if (c->id == id) 58 | return c - hi->id; 59 | c = c->next; 60 | } 61 | return -1; 62 | } 63 | 64 | static int 65 | hashid_remove(struct hashid *hi, int id) { 66 | int h = id & hi->hashmod; 67 | struct hashid_node * c = hi->hash[h]; 68 | if (c == NULL) 69 | return -1; 70 | if (c->id == id) { 71 | hi->hash[h] = c->next; 72 | goto _clear; 73 | } 74 | while(c->next) { 75 | if (c->next->id == id) { 76 | struct hashid_node * temp = c->next; 77 | c->next = temp->next; 78 | c = temp; 79 | goto _clear; 80 | } 81 | c = c->next; 82 | } 83 | return -1; 84 | _clear: 85 | c->id = -1; 86 | c->next = NULL; 87 | --hi->count; 88 | return c - hi->id; 89 | } 90 | 91 | static int 92 | hashid_insert(struct hashid * hi, int id) { 93 | struct hashid_node *c = NULL; 94 | int i; 95 | for (i=0;icap;i++) { 96 | int index = (i+id) % hi->cap; 97 | if (hi->id[index].id == -1) { 98 | c = &hi->id[index]; 99 | break; 100 | } 101 | } 102 | assert(c); 103 | ++hi->count; 104 | c->id = id; 105 | assert(c->next == NULL); 106 | int h = id & hi->hashmod; 107 | if (hi->hash[h]) { 108 | c->next = hi->hash[h]; 109 | } 110 | hi->hash[h] = c; 111 | 112 | return c - hi->id; 113 | } 114 | 115 | static inline int 116 | hashid_full(struct hashid *hi) { 117 | return hi->count == hi->cap; 118 | } 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /service-src/service_logger.c: -------------------------------------------------------------------------------- 1 | #include "skynet.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | struct logger { 10 | FILE * handle; 11 | char * filename; 12 | uint32_t starttime; 13 | int close; 14 | }; 15 | 16 | struct logger * 17 | logger_create(void) { 18 | struct logger * inst = skynet_malloc(sizeof(*inst)); 19 | inst->handle = NULL; 20 | inst->close = 0; 21 | inst->filename = NULL; 22 | 23 | return inst; 24 | } 25 | 26 | void 27 | logger_release(struct logger * inst) { 28 | if (inst->close) { 29 | fclose(inst->handle); 30 | } 31 | skynet_free(inst->filename); 32 | skynet_free(inst); 33 | } 34 | 35 | #define SIZETIMEFMT 250 36 | 37 | static int 38 | timestring(struct logger *inst, char tmp[SIZETIMEFMT]) { 39 | uint64_t now = skynet_now(); 40 | time_t ti = now/100 + inst->starttime; 41 | struct tm info; 42 | (void)localtime_r(&ti,&info); 43 | strftime(tmp, SIZETIMEFMT, "%d/%m/%y %H:%M:%S", &info); 44 | return now % 100; 45 | } 46 | 47 | static int 48 | logger_cb(struct skynet_context * context, void *ud, int type, int session, uint32_t source, const void * msg, size_t sz) { 49 | struct logger * inst = ud; 50 | switch (type) { 51 | case PTYPE_SYSTEM: 52 | if (inst->filename) { 53 | inst->handle = freopen(inst->filename, "a", inst->handle); 54 | } 55 | break; 56 | case PTYPE_TEXT: 57 | if (inst->filename) { 58 | char tmp[SIZETIMEFMT]; 59 | int csec = timestring(ud, tmp); 60 | fprintf(inst->handle, "%s.%02d ", tmp, csec); 61 | } 62 | fprintf(inst->handle, "[:%08x] ", source); 63 | fwrite(msg, sz , 1, inst->handle); 64 | fprintf(inst->handle, "\n"); 65 | fflush(inst->handle); 66 | break; 67 | } 68 | 69 | return 0; 70 | } 71 | 72 | int 73 | logger_init(struct logger * inst, struct skynet_context *ctx, const char * parm) { 74 | const char * r = skynet_command(ctx, "STARTTIME", NULL); 75 | inst->starttime = strtoul(r, NULL, 10); 76 | if (parm) { 77 | inst->handle = fopen(parm,"a"); 78 | if (inst->handle == NULL) { 79 | return 1; 80 | } 81 | inst->filename = skynet_malloc(strlen(parm)+1); 82 | strcpy(inst->filename, parm); 83 | inst->close = 1; 84 | } else { 85 | inst->handle = stdout; 86 | } 87 | if (inst->handle) { 88 | skynet_callback(ctx, inst, logger_cb); 89 | return 0; 90 | } 91 | return 1; 92 | } 93 | -------------------------------------------------------------------------------- /service/bootstrap.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local harbor = require "skynet.harbor" 3 | local service = require "skynet.service" 4 | require "skynet.manager" -- import skynet.launch, ... 5 | 6 | skynet.start(function() 7 | local standalone = skynet.getenv "standalone" 8 | 9 | local launcher = assert(skynet.launch("snlua","launcher")) 10 | skynet.name(".launcher", launcher) 11 | 12 | local harbor_id = tonumber(skynet.getenv "harbor" or 0) 13 | if harbor_id == 0 then 14 | assert(standalone == nil) 15 | standalone = true 16 | skynet.setenv("standalone", "true") 17 | 18 | local ok, slave = pcall(skynet.newservice, "cdummy") 19 | if not ok then 20 | skynet.abort() 21 | end 22 | skynet.name(".cslave", slave) 23 | 24 | else 25 | if standalone then 26 | if not pcall(skynet.newservice,"cmaster") then 27 | skynet.abort() 28 | end 29 | end 30 | 31 | local ok, slave = pcall(skynet.newservice, "cslave") 32 | if not ok then 33 | skynet.abort() 34 | end 35 | skynet.name(".cslave", slave) 36 | end 37 | 38 | if standalone then 39 | local datacenter = skynet.newservice "datacenterd" 40 | skynet.name("DATACENTER", datacenter) 41 | end 42 | skynet.newservice "service_mgr" 43 | 44 | local enablessl = skynet.getenv "enablessl" 45 | if enablessl then 46 | service.new("ltls_holder", function () 47 | local c = require "ltls.init.c" 48 | c.constructor() 49 | end) 50 | end 51 | 52 | pcall(skynet.newservice,skynet.getenv "start" or "main") 53 | skynet.exit() 54 | end) 55 | -------------------------------------------------------------------------------- /service/cdummy.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | require "skynet.manager" -- import skynet.launch, ... 3 | 4 | local globalname = {} 5 | local queryname = {} 6 | local harbor = {} 7 | local harbor_service 8 | 9 | skynet.register_protocol { 10 | name = "harbor", 11 | id = skynet.PTYPE_HARBOR, 12 | pack = function(...) return ... end, 13 | unpack = skynet.tostring, 14 | } 15 | 16 | skynet.register_protocol { 17 | name = "text", 18 | id = skynet.PTYPE_TEXT, 19 | pack = function(...) return ... end, 20 | unpack = skynet.tostring, 21 | } 22 | 23 | local function response_name(name) 24 | local address = globalname[name] 25 | if queryname[name] then 26 | local tmp = queryname[name] 27 | queryname[name] = nil 28 | for _,resp in ipairs(tmp) do 29 | resp(true, address) 30 | end 31 | end 32 | end 33 | 34 | function harbor.REGISTER(name, handle) 35 | assert(globalname[name] == nil) 36 | globalname[name] = handle 37 | response_name(name) 38 | skynet.redirect(harbor_service, handle, "harbor", 0, "N " .. name) 39 | end 40 | 41 | function harbor.QUERYNAME(name) 42 | if name:byte() == 46 then -- "." , local name 43 | skynet.ret(skynet.pack(skynet.localname(name))) 44 | return 45 | end 46 | local result = globalname[name] 47 | if result then 48 | skynet.ret(skynet.pack(result)) 49 | return 50 | end 51 | local queue = queryname[name] 52 | if queue == nil then 53 | queue = { skynet.response() } 54 | queryname[name] = queue 55 | else 56 | table.insert(queue, skynet.response()) 57 | end 58 | end 59 | 60 | function harbor.LINK(id) 61 | skynet.ret() 62 | end 63 | 64 | function harbor.CONNECT(id) 65 | skynet.error("Can't connect to other harbor in single node mode") 66 | end 67 | 68 | skynet.start(function() 69 | local harbor_id = tonumber(skynet.getenv "harbor") 70 | assert(harbor_id == 0) 71 | 72 | skynet.dispatch("lua", function (session,source,command,...) 73 | local f = assert(harbor[command]) 74 | f(...) 75 | end) 76 | skynet.dispatch("text", function(session,source,command) 77 | -- ignore all the command 78 | end) 79 | 80 | harbor_service = assert(skynet.launch("harbor", harbor_id, skynet.self())) 81 | end) 82 | -------------------------------------------------------------------------------- /service/clusterproxy.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local cluster = require "skynet.cluster" 3 | require "skynet.manager" -- inject skynet.forward_type 4 | 5 | local node, address = ... 6 | 7 | skynet.register_protocol { 8 | name = "system", 9 | id = skynet.PTYPE_SYSTEM, 10 | unpack = function (...) return ... end, 11 | } 12 | 13 | local forward_map = { 14 | [skynet.PTYPE_SNAX] = skynet.PTYPE_SYSTEM, 15 | [skynet.PTYPE_LUA] = skynet.PTYPE_SYSTEM, 16 | [skynet.PTYPE_RESPONSE] = skynet.PTYPE_RESPONSE, -- don't free response message 17 | } 18 | 19 | skynet.forward_type( forward_map ,function() 20 | local clusterd = skynet.uniqueservice("clusterd") 21 | local n = tonumber(address) 22 | if n then 23 | address = n 24 | end 25 | local sender = skynet.call(clusterd, "lua", "sender", node) 26 | skynet.dispatch("system", function (session, source, msg, sz) 27 | if session == 0 then 28 | skynet.send(sender, "lua", "push", address, msg, sz) 29 | else 30 | skynet.ret(skynet.rawcall(sender, "lua", skynet.pack("req", address, msg, sz))) 31 | end 32 | end) 33 | end) 34 | -------------------------------------------------------------------------------- /service/clustersender.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local sc = require "skynet.socketchannel" 3 | local socket = require "skynet.socket" 4 | local cluster = require "skynet.cluster.core" 5 | 6 | local channel 7 | local session = 1 8 | local node, nodename, init_host, init_port = ... 9 | 10 | local command = {} 11 | 12 | local function send_request(addr, msg, sz) 13 | -- msg is a local pointer, cluster.packrequest will free it 14 | local current_session = session 15 | local request, new_session, padding = cluster.packrequest(addr, session, msg, sz) 16 | session = new_session 17 | 18 | local tracetag = skynet.tracetag() 19 | if tracetag then 20 | if tracetag:sub(1,1) ~= "(" then 21 | -- add nodename 22 | local newtag = string.format("(%s-%s-%d)%s", nodename, node, session, tracetag) 23 | skynet.tracelog(tracetag, string.format("session %s", newtag)) 24 | tracetag = newtag 25 | end 26 | skynet.tracelog(tracetag, string.format("cluster %s", node)) 27 | channel:request(cluster.packtrace(tracetag)) 28 | end 29 | return channel:request(request, current_session, padding) 30 | end 31 | 32 | function command.req(...) 33 | local ok, msg = pcall(send_request, ...) 34 | if ok then 35 | if type(msg) == "table" then 36 | skynet.ret(cluster.concat(msg)) 37 | else 38 | skynet.ret(msg) 39 | end 40 | else 41 | skynet.error(msg) 42 | skynet.response()(false) 43 | end 44 | end 45 | 46 | function command.push(addr, msg, sz) 47 | local request, new_session, padding = cluster.packpush(addr, session, msg, sz) 48 | if padding then -- is multi push 49 | session = new_session 50 | end 51 | 52 | channel:request(request, nil, padding) 53 | end 54 | 55 | local function read_response(sock) 56 | local sz = socket.header(sock:read(2)) 57 | local msg = sock:read(sz) 58 | return cluster.unpackresponse(msg) -- session, ok, data, padding 59 | end 60 | 61 | function command.changenode(host, port) 62 | if not host then 63 | skynet.error(string.format("Close cluster sender %s:%d", channel.__host, channel.__port)) 64 | channel:close() 65 | else 66 | channel:changehost(host, tonumber(port)) 67 | channel:connect(true) 68 | end 69 | skynet.ret(skynet.pack(nil)) 70 | end 71 | 72 | skynet.start(function() 73 | channel = sc.channel { 74 | host = init_host, 75 | port = tonumber(init_port), 76 | response = read_response, 77 | nodelay = true, 78 | } 79 | skynet.dispatch("lua", function(session , source, cmd, ...) 80 | local f = assert(command[cmd]) 81 | f(...) 82 | end) 83 | end) 84 | -------------------------------------------------------------------------------- /service/cmemory.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local memory = require "skynet.memory" 3 | 4 | memory.dumpinfo() 5 | --memory.dump() 6 | local info = memory.info() 7 | for k,v in pairs(info) do 8 | print(string.format(":%08x %gK",k,v/1024)) 9 | end 10 | 11 | print("Total memory:", memory.total()) 12 | print("Total block:", memory.block()) 13 | 14 | skynet.start(function() skynet.exit() end) 15 | -------------------------------------------------------------------------------- /service/console.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local snax = require "skynet.snax" 3 | local socket = require "skynet.socket" 4 | 5 | local function split_cmdline(cmdline) 6 | local split = {} 7 | for i in string.gmatch(cmdline, "%S+") do 8 | table.insert(split,i) 9 | end 10 | return split 11 | end 12 | 13 | local function console_main_loop() 14 | local stdin = socket.stdin() 15 | while true do 16 | local cmdline = socket.readline(stdin, "\n") 17 | local split = split_cmdline(cmdline) 18 | local command = split[1] 19 | if command == "snax" then 20 | pcall(snax.newservice, select(2, table.unpack(split))) 21 | elseif cmdline ~= "" then 22 | pcall(skynet.newservice, cmdline) 23 | end 24 | end 25 | end 26 | 27 | skynet.start(function() 28 | skynet.fork(console_main_loop) 29 | end) 30 | -------------------------------------------------------------------------------- /service/datacenterd.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local command = {} 4 | local database = {} 5 | local wait_queue = {} 6 | local mode = {} 7 | 8 | local function query(db, key, ...) 9 | if key == nil then 10 | return db 11 | else 12 | return query(db[key], ...) 13 | end 14 | end 15 | 16 | function command.QUERY(key, ...) 17 | local d = database[key] 18 | if d ~= nil then 19 | return query(d, ...) 20 | end 21 | end 22 | 23 | local function update(db, key, value, ...) 24 | if select("#",...) == 0 then 25 | local ret = db[key] 26 | db[key] = value 27 | return ret, value 28 | else 29 | if db[key] == nil then 30 | db[key] = {} 31 | end 32 | return update(db[key], value, ...) 33 | end 34 | end 35 | 36 | local function wakeup(db, key1, ...) 37 | if key1 == nil then 38 | return 39 | end 40 | local q = db[key1] 41 | if q == nil then 42 | return 43 | end 44 | if q[mode] == "queue" then 45 | db[key1] = nil 46 | if select("#", ...) ~= 1 then 47 | -- throw error because can't wake up a branch 48 | for _,response in ipairs(q) do 49 | response(false) 50 | end 51 | else 52 | return q 53 | end 54 | else 55 | -- it's branch 56 | return wakeup(q , ...) 57 | end 58 | end 59 | 60 | function command.UPDATE(...) 61 | local ret, value = update(database, ...) 62 | if ret ~= nil or value == nil then 63 | return ret 64 | end 65 | local q = wakeup(wait_queue, ...) 66 | if q then 67 | for _, response in ipairs(q) do 68 | response(true,value) 69 | end 70 | end 71 | end 72 | 73 | local function waitfor(db, key1, key2, ...) 74 | if key2 == nil then 75 | -- push queue 76 | local q = db[key1] 77 | if q == nil then 78 | q = { [mode] = "queue" } 79 | db[key1] = q 80 | else 81 | assert(q[mode] == "queue") 82 | end 83 | table.insert(q, skynet.response()) 84 | else 85 | local q = db[key1] 86 | if q == nil then 87 | q = { [mode] = "branch" } 88 | db[key1] = q 89 | else 90 | assert(q[mode] == "branch") 91 | end 92 | return waitfor(q, key2, ...) 93 | end 94 | end 95 | 96 | skynet.start(function() 97 | skynet.dispatch("lua", function (_, _, cmd, ...) 98 | if cmd == "WAIT" then 99 | local ret = command.QUERY(...) 100 | if ret ~= nil then 101 | skynet.ret(skynet.pack(ret)) 102 | else 103 | waitfor(wait_queue, ...) 104 | end 105 | else 106 | local f = assert(command[cmd]) 107 | skynet.ret(skynet.pack(f(...))) 108 | end 109 | end) 110 | end) 111 | -------------------------------------------------------------------------------- /service/dbg.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local cmd = { ... } 4 | 5 | local function format_table(t) 6 | local index = {} 7 | for k in pairs(t) do 8 | table.insert(index, k) 9 | end 10 | table.sort(index) 11 | local result = {} 12 | for _,v in ipairs(index) do 13 | table.insert(result, string.format("%s:%s",v,tostring(t[v]))) 14 | end 15 | return table.concat(result,"\t") 16 | end 17 | 18 | local function dump_line(key, value) 19 | if type(value) == "table" then 20 | print(key, format_table(value)) 21 | else 22 | print(key,tostring(value)) 23 | end 24 | end 25 | 26 | local function dump_list(list) 27 | local index = {} 28 | for k in pairs(list) do 29 | table.insert(index, k) 30 | end 31 | table.sort(index) 32 | for _,v in ipairs(index) do 33 | dump_line(v, list[v]) 34 | end 35 | end 36 | 37 | skynet.start(function() 38 | local list = skynet.call(".launcher","lua", table.unpack(cmd)) 39 | if list then 40 | dump_list(list) 41 | end 42 | skynet.exit() 43 | end) -------------------------------------------------------------------------------- /service/debug_agent.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local debugchannel = require "skynet.debugchannel" 3 | 4 | local CMD = {} 5 | 6 | local channel 7 | 8 | function CMD.start(address, fd) 9 | assert(channel == nil, "start more than once") 10 | skynet.error(string.format("Attach to :%08x", address)) 11 | local handle 12 | channel, handle = debugchannel.create() 13 | local ok, err = pcall(skynet.call, address, "debug", "REMOTEDEBUG", fd, handle) 14 | if not ok then 15 | skynet.ret(skynet.pack(false, "Debugger attach failed")) 16 | else 17 | -- todo hook 18 | skynet.ret(skynet.pack(true)) 19 | end 20 | skynet.exit() 21 | end 22 | 23 | function CMD.cmd(cmdline) 24 | channel:write(cmdline) 25 | end 26 | 27 | function CMD.ping() 28 | skynet.ret() 29 | end 30 | 31 | skynet.start(function() 32 | skynet.dispatch("lua", function(_,_,cmd,...) 33 | local f = CMD[cmd] 34 | f(...) 35 | end) 36 | end) 37 | -------------------------------------------------------------------------------- /service/gate.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local gateserver = require "snax.gateserver" 3 | 4 | local watchdog 5 | local connection = {} -- fd -> connection : { fd , client, agent , ip, mode } 6 | local forwarding = {} -- agent -> connection 7 | 8 | skynet.register_protocol { 9 | name = "client", 10 | id = skynet.PTYPE_CLIENT, 11 | } 12 | 13 | local handler = {} 14 | 15 | function handler.open(source, conf) 16 | watchdog = conf.watchdog or source 17 | end 18 | 19 | function handler.message(fd, msg, sz) 20 | -- recv a package, forward it 21 | local c = connection[fd] 22 | local agent = c.agent 23 | if agent then 24 | -- It's safe to redirect msg directly , gateserver framework will not free msg. 25 | skynet.redirect(agent, c.client, "client", fd, msg, sz) 26 | else 27 | skynet.send(watchdog, "lua", "socket", "data", fd, skynet.tostring(msg, sz)) 28 | -- skynet.tostring will copy msg to a string, so we must free msg here. 29 | skynet.trash(msg,sz) 30 | end 31 | end 32 | 33 | function handler.connect(fd, addr) 34 | local c = { 35 | fd = fd, 36 | ip = addr, 37 | } 38 | connection[fd] = c 39 | skynet.send(watchdog, "lua", "socket", "open", fd, addr) 40 | end 41 | 42 | local function unforward(c) 43 | if c.agent then 44 | forwarding[c.agent] = nil 45 | c.agent = nil 46 | c.client = nil 47 | end 48 | end 49 | 50 | local function close_fd(fd) 51 | local c = connection[fd] 52 | if c then 53 | unforward(c) 54 | connection[fd] = nil 55 | end 56 | end 57 | 58 | function handler.disconnect(fd) 59 | close_fd(fd) 60 | skynet.send(watchdog, "lua", "socket", "close", fd) 61 | end 62 | 63 | function handler.error(fd, msg) 64 | close_fd(fd) 65 | skynet.send(watchdog, "lua", "socket", "error", fd, msg) 66 | end 67 | 68 | function handler.warning(fd, size) 69 | skynet.send(watchdog, "lua", "socket", "warning", fd, size) 70 | end 71 | 72 | local CMD = {} 73 | 74 | function CMD.forward(source, fd, client, address) 75 | local c = assert(connection[fd]) 76 | unforward(c) 77 | c.client = client or 0 78 | c.agent = address or source 79 | forwarding[c.agent] = c 80 | gateserver.openclient(fd) 81 | end 82 | 83 | function CMD.accept(source, fd) 84 | local c = assert(connection[fd]) 85 | unforward(c) 86 | gateserver.openclient(fd) 87 | end 88 | 89 | function CMD.kick(source, fd) 90 | gateserver.closeclient(fd) 91 | end 92 | 93 | function handler.command(cmd, source, ...) 94 | local f = assert(CMD[cmd]) 95 | return f(source, ...) 96 | end 97 | 98 | gateserver.start(handler) 99 | -------------------------------------------------------------------------------- /service/service_cell.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local service_name = (...) 4 | local init = {} 5 | 6 | function init.init(code, ...) 7 | local start_func 8 | skynet.start = function(f) 9 | start_func = f 10 | end 11 | skynet.dispatch("lua", function() error("No dispatch function") end) 12 | local mainfunc = assert(load(code, service_name)) 13 | assert(skynet.pcall(mainfunc,...)) 14 | if start_func then 15 | start_func() 16 | end 17 | skynet.ret() 18 | end 19 | 20 | skynet.start(function() 21 | skynet.dispatch("lua", function(_,_,cmd,...) 22 | init[cmd](...) 23 | end) 24 | end) 25 | -------------------------------------------------------------------------------- /service/snaxd.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local c = require "skynet.core" 3 | local snax_interface = require "snax.interface" 4 | local profile = require "skynet.profile" 5 | local snax = require "skynet.snax" 6 | 7 | local snax_name = tostring(...) 8 | local loaderpath = skynet.getenv"snax_loader" 9 | local loader = loaderpath and assert(dofile(loaderpath)) 10 | local func, pattern = snax_interface(snax_name, _ENV, loader) 11 | local snax_path = pattern:sub(1,pattern:find("?", 1, true)-1) .. snax_name .. "/" 12 | package.path = snax_path .. "?.lua;" .. package.path 13 | 14 | SERVICE_NAME = snax_name 15 | SERVICE_PATH = snax_path 16 | 17 | local profile_table = {} 18 | 19 | local function update_stat(name, ti) 20 | local t = profile_table[name] 21 | if t == nil then 22 | t = { count = 0, time = 0 } 23 | profile_table[name] = t 24 | end 25 | t.count = t.count + 1 26 | t.time = t.time + ti 27 | end 28 | 29 | local traceback = debug.traceback 30 | 31 | local function return_f(f, ...) 32 | return skynet.ret(skynet.pack(f(...))) 33 | end 34 | 35 | local function timing( method, ... ) 36 | local err, msg 37 | profile.start() 38 | if method[2] == "accept" then 39 | -- no return 40 | err,msg = xpcall(method[4], traceback, ...) 41 | else 42 | err,msg = xpcall(return_f, traceback, method[4], ...) 43 | end 44 | local ti = profile.stop() 45 | update_stat(method[3], ti) 46 | assert(err,msg) 47 | end 48 | 49 | skynet.start(function() 50 | local init = false 51 | local function dispatcher( session , source , id, ...) 52 | local method = func[id] 53 | 54 | if method[2] == "system" then 55 | local command = method[3] 56 | if command == "hotfix" then 57 | local hotfix = require "snax.hotfix" 58 | skynet.ret(skynet.pack(hotfix(func, ...))) 59 | elseif command == "profile" then 60 | skynet.ret(skynet.pack(profile_table)) 61 | elseif command == "init" then 62 | assert(not init, "Already init") 63 | local initfunc = method[4] or function() end 64 | initfunc(...) 65 | skynet.ret() 66 | skynet.info_func(function() 67 | return profile_table 68 | end) 69 | init = true 70 | else 71 | assert(init, "Never init") 72 | assert(command == "exit") 73 | local exitfunc = method[4] or function() end 74 | exitfunc(...) 75 | skynet.ret() 76 | init = false 77 | skynet.exit() 78 | end 79 | else 80 | assert(init, "Init first") 81 | timing(method, ...) 82 | end 83 | end 84 | skynet.dispatch("snax", dispatcher) 85 | 86 | -- set lua dispatcher 87 | function snax.enablecluster() 88 | skynet.dispatch("lua", dispatcher) 89 | end 90 | end) 91 | -------------------------------------------------------------------------------- /service/vscdebuglog.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | require "skynet.manager" 3 | local cjson = require "cjson" 4 | local vscdebugaux = require "skynet.vscdebugaux" 5 | 6 | local function send_event(event, body) 7 | local res = { 8 | seq = vscdebugaux.nextseq(), 9 | type = "event", 10 | event = event, 11 | body = body, 12 | } 13 | local output = io.stdout 14 | local ok, msg = pcall(cjson.encode, res) 15 | if ok then 16 | local data = string.format("Content-Length: %s\r\n\r\n%s\n", #msg, msg) 17 | output:write(data) 18 | output:flush() 19 | else 20 | output:write(string.format("send_event - error: %s\n", msg)) 21 | end 22 | end 23 | 24 | -- register protocol text before skynet.start would be better. 25 | skynet.register_protocol { 26 | name = "text", 27 | id = skynet.PTYPE_TEXT, 28 | unpack = skynet.tostring, 29 | dispatch = function(_, address, msg) 30 | local line, source 31 | if msg:find("co.vsc.db.", 1, true) == 1 then 32 | line, source, msg = msg:match("co.vsc.db.([^|]+)|([^|]+)|(.+)$") 33 | end 34 | if source then 35 | source = {path = source} 36 | end 37 | send_event("output", { 38 | category = "stdout", 39 | output = string.format("[:%08x] %s\n", address, msg), 40 | source = source, 41 | line = tonumber(line), 42 | }) 43 | end 44 | } 45 | 46 | skynet.register_protocol { 47 | name = "SYSTEM", 48 | id = skynet.PTYPE_SYSTEM, 49 | unpack = function(...) return ... end, 50 | dispatch = function() 51 | -- reopen signal 52 | end 53 | } 54 | 55 | skynet.start(function() 56 | end) -------------------------------------------------------------------------------- /skynet-src/atomic.h: -------------------------------------------------------------------------------- 1 | #ifndef SKYNET_ATOMIC_H 2 | #define SKYNET_ATOMIC_H 3 | 4 | #ifdef __STDC_NO_ATOMICS__ 5 | 6 | #include 7 | 8 | #define ATOM_INT volatile int 9 | #define ATOM_POINTER volatile uintptr_t 10 | #define ATOM_SIZET volatile size_t 11 | #define ATOM_ULONG volatile unsigned long 12 | #define ATOM_INIT(ptr, v) (*(ptr) = v) 13 | #define ATOM_LOAD(ptr) (*(ptr)) 14 | #define ATOM_STORE(ptr, v) (*(ptr) = v) 15 | #define ATOM_CAS(ptr, oval, nval) __sync_bool_compare_and_swap(ptr, oval, nval) 16 | #define ATOM_CAS_POINTER(ptr, oval, nval) __sync_bool_compare_and_swap(ptr, oval, nval) 17 | #define ATOM_FINC(ptr) __sync_fetch_and_add(ptr, 1) 18 | #define ATOM_FDEC(ptr) __sync_fetch_and_sub(ptr, 1) 19 | #define ATOM_FADD(ptr,n) __sync_fetch_and_add(ptr, n) 20 | #define ATOM_FSUB(ptr,n) __sync_fetch_and_sub(ptr, n) 21 | #define ATOM_FAND(ptr,n) __sync_fetch_and_and(ptr, n) 22 | 23 | #else 24 | 25 | #include 26 | 27 | #define ATOM_INT atomic_int 28 | #define ATOM_POINTER atomic_uintptr_t 29 | #define ATOM_SIZET atomic_size_t 30 | #define ATOM_ULONG atomic_ulong 31 | #define ATOM_INIT(ref, v) atomic_init(ref, v) 32 | #define ATOM_LOAD(ptr) atomic_load(ptr) 33 | #define ATOM_STORE(ptr, v) atomic_store(ptr, v) 34 | #define ATOM_CAS(ptr, oval, nval) atomic_compare_exchange_weak(ptr, &(oval), nval) 35 | #define ATOM_CAS_POINTER(ptr, oval, nval) atomic_compare_exchange_weak(ptr, &(oval), nval) 36 | #define ATOM_FINC(ptr) atomic_fetch_add(ptr, 1) 37 | #define ATOM_FDEC(ptr) atomic_fetch_sub(ptr, 1) 38 | #define ATOM_FADD(ptr,n) atomic_fetch_add(ptr, n) 39 | #define ATOM_FSUB(ptr,n) atomic_fetch_sub(ptr, n) 40 | #define ATOM_FAND(ptr,n) atomic_fetch_and(ptr, n) 41 | 42 | #endif 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /skynet-src/malloc_hook.h: -------------------------------------------------------------------------------- 1 | #ifndef SKYNET_MALLOC_HOOK_H 2 | #define SKYNET_MALLOC_HOOK_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | extern size_t malloc_used_memory(void); 9 | extern size_t malloc_memory_block(void); 10 | extern void memory_info_dump(const char *opts); 11 | extern size_t mallctl_int64(const char* name, size_t* newval); 12 | extern int mallctl_opt(const char* name, int* newval); 13 | extern bool mallctl_bool(const char* name, bool* newval); 14 | extern int mallctl_cmd(const char* name); 15 | extern void dump_c_mem(void); 16 | extern int dump_mem_lua(lua_State *L); 17 | extern size_t malloc_current_memory(void); 18 | 19 | #endif /* SKYNET_MALLOC_HOOK_H */ 20 | 21 | -------------------------------------------------------------------------------- /skynet-src/rwlock.h: -------------------------------------------------------------------------------- 1 | #ifndef SKYNET_RWLOCK_H 2 | #define SKYNET_RWLOCK_H 3 | 4 | #ifndef USE_PTHREAD_LOCK 5 | 6 | #include "atomic.h" 7 | 8 | struct rwlock { 9 | ATOM_INT write; 10 | ATOM_INT read; 11 | }; 12 | 13 | static inline void 14 | rwlock_init(struct rwlock *lock) { 15 | ATOM_INIT(&lock->write, 0); 16 | ATOM_INIT(&lock->read, 0); 17 | } 18 | 19 | static inline void 20 | rwlock_rlock(struct rwlock *lock) { 21 | for (;;) { 22 | while(ATOM_LOAD(&lock->write)) {} 23 | ATOM_FINC(&lock->read); 24 | if (ATOM_LOAD(&lock->write)) { 25 | ATOM_FDEC(&lock->read); 26 | } else { 27 | break; 28 | } 29 | } 30 | } 31 | 32 | static inline void 33 | rwlock_wlock(struct rwlock *lock) { 34 | int clear = 0; 35 | while (!ATOM_CAS(&lock->write,clear,1)) {} 36 | while(ATOM_LOAD(&lock->read)) {} 37 | } 38 | 39 | static inline void 40 | rwlock_wunlock(struct rwlock *lock) { 41 | ATOM_STORE(&lock->write, 0); 42 | } 43 | 44 | static inline void 45 | rwlock_runlock(struct rwlock *lock) { 46 | ATOM_FDEC(&lock->read); 47 | } 48 | 49 | #else 50 | 51 | #include 52 | 53 | // only for some platform doesn't have __sync_* 54 | // todo: check the result of pthread api 55 | 56 | struct rwlock { 57 | pthread_rwlock_t lock; 58 | }; 59 | 60 | static inline void 61 | rwlock_init(struct rwlock *lock) { 62 | pthread_rwlock_init(&lock->lock, NULL); 63 | } 64 | 65 | static inline void 66 | rwlock_rlock(struct rwlock *lock) { 67 | pthread_rwlock_rdlock(&lock->lock); 68 | } 69 | 70 | static inline void 71 | rwlock_wlock(struct rwlock *lock) { 72 | pthread_rwlock_wrlock(&lock->lock); 73 | } 74 | 75 | static inline void 76 | rwlock_wunlock(struct rwlock *lock) { 77 | pthread_rwlock_unlock(&lock->lock); 78 | } 79 | 80 | static inline void 81 | rwlock_runlock(struct rwlock *lock) { 82 | pthread_rwlock_unlock(&lock->lock); 83 | } 84 | 85 | #endif 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /skynet-src/skynet.h: -------------------------------------------------------------------------------- 1 | #ifndef SKYNET_H 2 | #define SKYNET_H 3 | 4 | #include "skynet_malloc.h" 5 | 6 | #include 7 | #include 8 | 9 | #define PTYPE_TEXT 0 10 | #define PTYPE_RESPONSE 1 11 | #define PTYPE_MULTICAST 2 12 | #define PTYPE_CLIENT 3 13 | #define PTYPE_SYSTEM 4 14 | #define PTYPE_HARBOR 5 15 | #define PTYPE_SOCKET 6 16 | // read lualib/skynet.lua examples/simplemonitor.lua 17 | #define PTYPE_ERROR 7 18 | // read lualib/skynet.lua lualib/mqueue.lua lualib/snax.lua 19 | #define PTYPE_RESERVED_QUEUE 8 20 | #define PTYPE_RESERVED_DEBUG 9 21 | #define PTYPE_RESERVED_LUA 10 22 | #define PTYPE_RESERVED_SNAX 11 23 | 24 | #define PTYPE_TAG_DONTCOPY 0x10000 25 | #define PTYPE_TAG_ALLOCSESSION 0x20000 26 | 27 | struct skynet_context; 28 | 29 | void skynet_error(struct skynet_context * context, const char *msg, ...); 30 | const char * skynet_command(struct skynet_context * context, const char * cmd , const char * parm); 31 | uint32_t skynet_queryname(struct skynet_context * context, const char * name); 32 | int skynet_send(struct skynet_context * context, uint32_t source, uint32_t destination , int type, int session, void * msg, size_t sz); 33 | int skynet_sendname(struct skynet_context * context, uint32_t source, const char * destination , int type, int session, void * msg, size_t sz); 34 | 35 | int skynet_isremote(struct skynet_context *, uint32_t handle, int * harbor); 36 | 37 | typedef int (*skynet_cb)(struct skynet_context * context, void *ud, int type, int session, uint32_t source , const void * msg, size_t sz); 38 | void skynet_callback(struct skynet_context * context, void *ud, skynet_cb cb); 39 | 40 | uint32_t skynet_current_handle(void); 41 | uint64_t skynet_now(void); 42 | void skynet_debug_memory(const char *info); // for debug use, output current service memory to stderr 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /skynet-src/skynet_daemon.h: -------------------------------------------------------------------------------- 1 | #ifndef skynet_daemon_h 2 | #define skynet_daemon_h 3 | 4 | int daemon_init(const char *pidfile); 5 | int daemon_exit(const char *pidfile); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /skynet-src/skynet_env.c: -------------------------------------------------------------------------------- 1 | #include "skynet.h" 2 | #include "skynet_env.h" 3 | #include "spinlock.h" 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | struct skynet_env { 12 | struct spinlock lock; 13 | lua_State *L; 14 | }; 15 | 16 | static struct skynet_env *E = NULL; 17 | 18 | const char * 19 | skynet_getenv(const char *key) { 20 | SPIN_LOCK(E) 21 | 22 | lua_State *L = E->L; 23 | 24 | lua_getglobal(L, key); 25 | const char * result = lua_tostring(L, -1); 26 | lua_pop(L, 1); 27 | 28 | SPIN_UNLOCK(E) 29 | 30 | return result; 31 | } 32 | 33 | void 34 | skynet_setenv(const char *key, const char *value) { 35 | SPIN_LOCK(E) 36 | 37 | lua_State *L = E->L; 38 | lua_getglobal(L, key); 39 | assert(lua_isnil(L, -1)); 40 | lua_pop(L,1); 41 | lua_pushstring(L,value); 42 | lua_setglobal(L,key); 43 | 44 | SPIN_UNLOCK(E) 45 | } 46 | 47 | void 48 | skynet_env_init() { 49 | E = skynet_malloc(sizeof(*E)); 50 | SPIN_INIT(E) 51 | E->L = luaL_newstate(); 52 | } 53 | -------------------------------------------------------------------------------- /skynet-src/skynet_env.h: -------------------------------------------------------------------------------- 1 | #ifndef SKYNET_ENV_H 2 | #define SKYNET_ENV_H 3 | 4 | const char * skynet_getenv(const char *key); 5 | void skynet_setenv(const char *key, const char *value); 6 | 7 | void skynet_env_init(); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /skynet-src/skynet_error.c: -------------------------------------------------------------------------------- 1 | #include "skynet.h" 2 | #include "skynet_handle.h" 3 | #include "skynet_mq.h" 4 | #include "skynet_server.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define LOG_MESSAGE_SIZE 256 12 | 13 | void 14 | skynet_error(struct skynet_context * context, const char *msg, ...) { 15 | static uint32_t logger = 0; 16 | if (logger == 0) { 17 | logger = skynet_handle_findname("logger"); 18 | } 19 | if (logger == 0) { 20 | return; 21 | } 22 | 23 | char tmp[LOG_MESSAGE_SIZE]; 24 | char *data = NULL; 25 | 26 | va_list ap; 27 | 28 | va_start(ap,msg); 29 | int len = vsnprintf(tmp, LOG_MESSAGE_SIZE, msg, ap); 30 | va_end(ap); 31 | if (len >=0 && len < LOG_MESSAGE_SIZE) { 32 | data = skynet_strdup(tmp); 33 | } else { 34 | int max_size = LOG_MESSAGE_SIZE; 35 | for (;;) { 36 | max_size *= 2; 37 | data = skynet_malloc(max_size); 38 | va_start(ap,msg); 39 | len = vsnprintf(data, max_size, msg, ap); 40 | va_end(ap); 41 | if (len < max_size) { 42 | break; 43 | } 44 | skynet_free(data); 45 | } 46 | } 47 | if (len < 0) { 48 | skynet_free(data); 49 | perror("vsnprintf error :"); 50 | return; 51 | } 52 | 53 | 54 | struct skynet_message smsg; 55 | if (context == NULL) { 56 | smsg.source = 0; 57 | } else { 58 | smsg.source = skynet_context_handle(context); 59 | } 60 | smsg.session = 0; 61 | smsg.data = data; 62 | smsg.sz = len | ((size_t)PTYPE_TEXT << MESSAGE_TYPE_SHIFT); 63 | skynet_context_push(logger, &smsg); 64 | } 65 | 66 | -------------------------------------------------------------------------------- /skynet-src/skynet_handle.h: -------------------------------------------------------------------------------- 1 | #ifndef SKYNET_CONTEXT_HANDLE_H 2 | #define SKYNET_CONTEXT_HANDLE_H 3 | 4 | #include 5 | 6 | // reserve high 8 bits for remote id 7 | #define HANDLE_MASK 0xffffff 8 | #define HANDLE_REMOTE_SHIFT 24 9 | 10 | struct skynet_context; 11 | 12 | uint32_t skynet_handle_register(struct skynet_context *); 13 | int skynet_handle_retire(uint32_t handle); 14 | struct skynet_context * skynet_handle_grab(uint32_t handle); 15 | void skynet_handle_retireall(); 16 | 17 | uint32_t skynet_handle_findname(const char * name); 18 | const char * skynet_handle_namehandle(uint32_t handle, const char *name); 19 | 20 | void skynet_handle_init(int harbor); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /skynet-src/skynet_harbor.c: -------------------------------------------------------------------------------- 1 | #include "skynet.h" 2 | #include "skynet_harbor.h" 3 | #include "skynet_server.h" 4 | #include "skynet_mq.h" 5 | #include "skynet_handle.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | static struct skynet_context * REMOTE = 0; 12 | static unsigned int HARBOR = ~0; 13 | 14 | static inline int 15 | invalid_type(int type) { 16 | return type != PTYPE_SYSTEM && type != PTYPE_HARBOR; 17 | } 18 | 19 | void 20 | skynet_harbor_send(struct remote_message *rmsg, uint32_t source, int session) { 21 | assert(invalid_type(rmsg->type) && REMOTE); 22 | skynet_context_send(REMOTE, rmsg, sizeof(*rmsg) , source, PTYPE_SYSTEM , session); 23 | } 24 | 25 | int 26 | skynet_harbor_message_isremote(uint32_t handle) { 27 | assert(HARBOR != ~0); 28 | int h = (handle & ~HANDLE_MASK); 29 | return h != HARBOR && h !=0; 30 | } 31 | 32 | void 33 | skynet_harbor_init(int harbor) { 34 | HARBOR = (unsigned int)harbor << HANDLE_REMOTE_SHIFT; 35 | } 36 | 37 | void 38 | skynet_harbor_start(void *ctx) { 39 | // the HARBOR must be reserved to ensure the pointer is valid. 40 | // It will be released at last by calling skynet_harbor_exit 41 | skynet_context_reserve(ctx); 42 | REMOTE = ctx; 43 | } 44 | 45 | void 46 | skynet_harbor_exit() { 47 | struct skynet_context * ctx = REMOTE; 48 | REMOTE= NULL; 49 | if (ctx) { 50 | skynet_context_release(ctx); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /skynet-src/skynet_harbor.h: -------------------------------------------------------------------------------- 1 | #ifndef SKYNET_HARBOR_H 2 | #define SKYNET_HARBOR_H 3 | 4 | #include 5 | #include 6 | 7 | #define GLOBALNAME_LENGTH 16 8 | #define REMOTE_MAX 256 9 | 10 | struct remote_name { 11 | char name[GLOBALNAME_LENGTH]; 12 | uint32_t handle; 13 | }; 14 | 15 | struct remote_message { 16 | struct remote_name destination; 17 | const void * message; 18 | size_t sz; 19 | int type; 20 | }; 21 | 22 | void skynet_harbor_send(struct remote_message *rmsg, uint32_t source, int session); 23 | int skynet_harbor_message_isremote(uint32_t handle); 24 | void skynet_harbor_init(int harbor); 25 | void skynet_harbor_start(void * ctx); 26 | void skynet_harbor_exit(); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /skynet-src/skynet_imp.h: -------------------------------------------------------------------------------- 1 | #ifndef SKYNET_IMP_H 2 | #define SKYNET_IMP_H 3 | 4 | struct skynet_config { 5 | int thread; 6 | int harbor; 7 | int profile; 8 | const char * daemon; 9 | const char * module_path; 10 | const char * bootstrap; 11 | const char * logger; 12 | const char * logservice; 13 | }; 14 | 15 | #define THREAD_WORKER 0 16 | #define THREAD_MAIN 1 17 | #define THREAD_SOCKET 2 18 | #define THREAD_TIMER 3 19 | #define THREAD_MONITOR 4 20 | 21 | void skynet_start(struct skynet_config * config); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /skynet-src/skynet_log.c: -------------------------------------------------------------------------------- 1 | #include "skynet_log.h" 2 | #include "skynet_timer.h" 3 | #include "skynet.h" 4 | #include "skynet_socket.h" 5 | #include 6 | #include 7 | 8 | FILE * 9 | skynet_log_open(struct skynet_context * ctx, uint32_t handle) { 10 | const char * logpath = skynet_getenv("logpath"); 11 | if (logpath == NULL) 12 | return NULL; 13 | size_t sz = strlen(logpath); 14 | char tmp[sz + 16]; 15 | sprintf(tmp, "%s/%08x.log", logpath, handle); 16 | FILE *f = fopen(tmp, "ab"); 17 | if (f) { 18 | uint32_t starttime = skynet_starttime(); 19 | uint64_t currenttime = skynet_now(); 20 | time_t ti = starttime + currenttime/100; 21 | skynet_error(ctx, "Open log file %s", tmp); 22 | fprintf(f, "open time: %u %s", (uint32_t)currenttime, ctime(&ti)); 23 | fflush(f); 24 | } else { 25 | skynet_error(ctx, "Open log file %s fail", tmp); 26 | } 27 | return f; 28 | } 29 | 30 | void 31 | skynet_log_close(struct skynet_context * ctx, FILE *f, uint32_t handle) { 32 | skynet_error(ctx, "Close log file :%08x", handle); 33 | fprintf(f, "close time: %u\n", (uint32_t)skynet_now()); 34 | fclose(f); 35 | } 36 | 37 | static void 38 | log_blob(FILE *f, void * buffer, size_t sz) { 39 | size_t i; 40 | uint8_t * buf = buffer; 41 | for (i=0;i!=sz;i++) { 42 | fprintf(f, "%02x", buf[i]); 43 | } 44 | } 45 | 46 | static void 47 | log_socket(FILE * f, struct skynet_socket_message * message, size_t sz) { 48 | fprintf(f, "[socket] %d %d %d ", message->type, message->id, message->ud); 49 | 50 | if (message->buffer == NULL) { 51 | const char *buffer = (const char *)(message + 1); 52 | sz -= sizeof(*message); 53 | const char * eol = memchr(buffer, '\0', sz); 54 | if (eol) { 55 | sz = eol - buffer; 56 | } 57 | fprintf(f, "[%*s]", (int)sz, (const char *)buffer); 58 | } else { 59 | sz = message->ud; 60 | log_blob(f, message->buffer, sz); 61 | } 62 | fprintf(f, "\n"); 63 | fflush(f); 64 | } 65 | 66 | void 67 | skynet_log_output(FILE *f, uint32_t source, int type, int session, void * buffer, size_t sz) { 68 | if (type == PTYPE_SOCKET) { 69 | log_socket(f, buffer, sz); 70 | } else { 71 | uint32_t ti = (uint32_t)skynet_now(); 72 | fprintf(f, ":%08x %d %d %u ", source, type, session, ti); 73 | log_blob(f, buffer, sz); 74 | fprintf(f,"\n"); 75 | fflush(f); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /skynet-src/skynet_log.h: -------------------------------------------------------------------------------- 1 | #ifndef skynet_log_h 2 | #define skynet_log_h 3 | 4 | #include "skynet_env.h" 5 | #include "skynet.h" 6 | 7 | #include 8 | #include 9 | 10 | FILE * skynet_log_open(struct skynet_context * ctx, uint32_t handle); 11 | void skynet_log_close(struct skynet_context * ctx, FILE *f, uint32_t handle); 12 | void skynet_log_output(FILE *f, uint32_t source, int type, int session, void * buffer, size_t sz); 13 | 14 | #endif -------------------------------------------------------------------------------- /skynet-src/skynet_malloc.h: -------------------------------------------------------------------------------- 1 | #ifndef skynet_malloc_h 2 | #define skynet_malloc_h 3 | 4 | #include 5 | 6 | #define skynet_malloc malloc 7 | #define skynet_calloc calloc 8 | #define skynet_realloc realloc 9 | #define skynet_free free 10 | #define skynet_memalign memalign 11 | #define skynet_aligned_alloc aligned_alloc 12 | #define skynet_posix_memalign posix_memalign 13 | 14 | void * skynet_malloc(size_t sz); 15 | void * skynet_calloc(size_t nmemb,size_t size); 16 | void * skynet_realloc(void *ptr, size_t size); 17 | void skynet_free(void *ptr); 18 | char * skynet_strdup(const char *str); 19 | void * skynet_lalloc(void *ptr, size_t osize, size_t nsize); // use for lua 20 | void * skynet_memalign(size_t alignment, size_t size); 21 | void * skynet_aligned_alloc(size_t alignment, size_t size); 22 | int skynet_posix_memalign(void **memptr, size_t alignment, size_t size); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /skynet-src/skynet_module.h: -------------------------------------------------------------------------------- 1 | #ifndef SKYNET_MODULE_H 2 | #define SKYNET_MODULE_H 3 | 4 | struct skynet_context; 5 | 6 | typedef void * (*skynet_dl_create)(void); 7 | typedef int (*skynet_dl_init)(void * inst, struct skynet_context *, const char * parm); 8 | typedef void (*skynet_dl_release)(void * inst); 9 | typedef void (*skynet_dl_signal)(void * inst, int signal); 10 | 11 | struct skynet_module { 12 | const char * name; 13 | void * module; 14 | skynet_dl_create create; 15 | skynet_dl_init init; 16 | skynet_dl_release release; 17 | skynet_dl_signal signal; 18 | }; 19 | 20 | void skynet_module_insert(struct skynet_module *mod); 21 | struct skynet_module * skynet_module_query(const char * name); 22 | void * skynet_module_instance_create(struct skynet_module *); 23 | int skynet_module_instance_init(struct skynet_module *, void * inst, struct skynet_context *ctx, const char * parm); 24 | void skynet_module_instance_release(struct skynet_module *, void *inst); 25 | void skynet_module_instance_signal(struct skynet_module *, void *inst, int signal); 26 | 27 | void skynet_module_init(const char *path); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /skynet-src/skynet_monitor.c: -------------------------------------------------------------------------------- 1 | #include "skynet.h" 2 | 3 | #include "skynet_monitor.h" 4 | #include "skynet_server.h" 5 | #include "skynet.h" 6 | #include "atomic.h" 7 | 8 | #include 9 | #include 10 | 11 | struct skynet_monitor { 12 | ATOM_INT version; 13 | int check_version; 14 | uint32_t source; 15 | uint32_t destination; 16 | }; 17 | 18 | struct skynet_monitor * 19 | skynet_monitor_new() { 20 | struct skynet_monitor * ret = skynet_malloc(sizeof(*ret)); 21 | memset(ret, 0, sizeof(*ret)); 22 | return ret; 23 | } 24 | 25 | void 26 | skynet_monitor_delete(struct skynet_monitor *sm) { 27 | skynet_free(sm); 28 | } 29 | 30 | void 31 | skynet_monitor_trigger(struct skynet_monitor *sm, uint32_t source, uint32_t destination) { 32 | sm->source = source; 33 | sm->destination = destination; 34 | ATOM_FINC(&sm->version); 35 | } 36 | 37 | void 38 | skynet_monitor_check(struct skynet_monitor *sm) { 39 | if (sm->version == sm->check_version) { 40 | if (sm->destination) { 41 | skynet_context_endless(sm->destination); 42 | skynet_error(NULL, "A message from [ :%08x ] to [ :%08x ] maybe in an endless loop (version = %d)", sm->source , sm->destination, sm->version); 43 | } 44 | } else { 45 | sm->check_version = sm->version; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /skynet-src/skynet_monitor.h: -------------------------------------------------------------------------------- 1 | #ifndef SKYNET_MONITOR_H 2 | #define SKYNET_MONITOR_H 3 | 4 | #include 5 | 6 | struct skynet_monitor; 7 | 8 | struct skynet_monitor * skynet_monitor_new(); 9 | void skynet_monitor_delete(struct skynet_monitor *); 10 | void skynet_monitor_trigger(struct skynet_monitor *, uint32_t source, uint32_t destination); 11 | void skynet_monitor_check(struct skynet_monitor *); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /skynet-src/skynet_mq.h: -------------------------------------------------------------------------------- 1 | #ifndef SKYNET_MESSAGE_QUEUE_H 2 | #define SKYNET_MESSAGE_QUEUE_H 3 | 4 | #include 5 | #include 6 | 7 | struct skynet_message { 8 | uint32_t source; 9 | int session; 10 | void * data; 11 | size_t sz; 12 | }; 13 | 14 | // type is encoding in skynet_message.sz high 8bit 15 | #define MESSAGE_TYPE_MASK (SIZE_MAX >> 8) 16 | #define MESSAGE_TYPE_SHIFT ((sizeof(size_t)-1) * 8) 17 | 18 | struct message_queue; 19 | 20 | void skynet_globalmq_push(struct message_queue * queue); 21 | struct message_queue * skynet_globalmq_pop(void); 22 | 23 | struct message_queue * skynet_mq_create(uint32_t handle); 24 | void skynet_mq_mark_release(struct message_queue *q); 25 | 26 | typedef void (*message_drop)(struct skynet_message *, void *); 27 | 28 | void skynet_mq_release(struct message_queue *q, message_drop drop_func, void *ud); 29 | uint32_t skynet_mq_handle(struct message_queue *); 30 | 31 | // 0 for success 32 | int skynet_mq_pop(struct message_queue *q, struct skynet_message *message); 33 | void skynet_mq_push(struct message_queue *q, struct skynet_message *message); 34 | 35 | // return the length of message queue, for debug 36 | int skynet_mq_length(struct message_queue *q); 37 | int skynet_mq_overload(struct message_queue *q); 38 | 39 | void skynet_mq_init(); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /skynet-src/skynet_server.h: -------------------------------------------------------------------------------- 1 | #ifndef SKYNET_SERVER_H 2 | #define SKYNET_SERVER_H 3 | 4 | #include 5 | #include 6 | 7 | struct skynet_context; 8 | struct skynet_message; 9 | struct skynet_monitor; 10 | 11 | struct skynet_context * skynet_context_new(const char * name, const char * parm); 12 | void skynet_context_grab(struct skynet_context *); 13 | void skynet_context_reserve(struct skynet_context *ctx); 14 | struct skynet_context * skynet_context_release(struct skynet_context *); 15 | uint32_t skynet_context_handle(struct skynet_context *); 16 | int skynet_context_push(uint32_t handle, struct skynet_message *message); 17 | void skynet_context_send(struct skynet_context * context, void * msg, size_t sz, uint32_t source, int type, int session); 18 | int skynet_context_newsession(struct skynet_context *); 19 | struct message_queue * skynet_context_message_dispatch(struct skynet_monitor *, struct message_queue *, int weight); // return next queue 20 | int skynet_context_total(); 21 | void skynet_context_dispatchall(struct skynet_context * context); // for skynet_error output before exit 22 | 23 | void skynet_context_endless(uint32_t handle); // for monitor 24 | 25 | void skynet_globalinit(void); 26 | void skynet_globalexit(void); 27 | void skynet_initthread(int m); 28 | 29 | void skynet_profile_enable(int enable); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /skynet-src/skynet_timer.h: -------------------------------------------------------------------------------- 1 | #ifndef SKYNET_TIMER_H 2 | #define SKYNET_TIMER_H 3 | 4 | #include 5 | 6 | int skynet_timeout(uint32_t handle, int time, int session); 7 | void skynet_updatetime(void); 8 | uint32_t skynet_starttime(void); 9 | uint64_t skynet_thread_time(void); // for profile, in micro second 10 | 11 | void skynet_timer_init(void); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /skynet-src/socket_buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef socket_buffer_h 2 | #define socket_buffer_h 3 | 4 | #include 5 | 6 | #define SOCKET_BUFFER_MEMORY 0 7 | #define SOCKET_BUFFER_OBJECT 1 8 | #define SOCKET_BUFFER_RAWPOINTER 2 9 | 10 | struct socket_sendbuffer { 11 | int id; 12 | int type; 13 | const void *buffer; 14 | size_t sz; 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /skynet-src/socket_epoll.h: -------------------------------------------------------------------------------- 1 | #ifndef poll_socket_epoll_h 2 | #define poll_socket_epoll_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | static bool 14 | sp_invalid(int efd) { 15 | return efd == -1; 16 | } 17 | 18 | static int 19 | sp_create() { 20 | return epoll_create(1024); 21 | } 22 | 23 | static void 24 | sp_release(int efd) { 25 | close(efd); 26 | } 27 | 28 | static int 29 | sp_add(int efd, int sock, void *ud) { 30 | struct epoll_event ev; 31 | ev.events = EPOLLIN; 32 | ev.data.ptr = ud; 33 | if (epoll_ctl(efd, EPOLL_CTL_ADD, sock, &ev) == -1) { 34 | return 1; 35 | } 36 | return 0; 37 | } 38 | 39 | static void 40 | sp_del(int efd, int sock) { 41 | epoll_ctl(efd, EPOLL_CTL_DEL, sock , NULL); 42 | } 43 | 44 | static int 45 | sp_enable(int efd, int sock, void *ud, bool read_enable, bool write_enable) { 46 | struct epoll_event ev; 47 | ev.events = (read_enable ? EPOLLIN : 0) | (write_enable ? EPOLLOUT : 0); 48 | ev.data.ptr = ud; 49 | if (epoll_ctl(efd, EPOLL_CTL_MOD, sock, &ev) == -1) { 50 | return 1; 51 | } 52 | return 0; 53 | } 54 | 55 | static int 56 | sp_wait(int efd, struct event *e, int max) { 57 | struct epoll_event ev[max]; 58 | int n = epoll_wait(efd , ev, max, -1); 59 | int i; 60 | for (i=0;i 12 | 13 | struct socket_info { 14 | int id; 15 | int type; 16 | uint64_t opaque; 17 | uint64_t read; 18 | uint64_t write; 19 | uint64_t rtime; 20 | uint64_t wtime; 21 | int64_t wbuffer; 22 | uint8_t reading; 23 | uint8_t writing; 24 | char name[128]; 25 | struct socket_info *next; 26 | }; 27 | 28 | struct socket_info * socket_info_create(struct socket_info *last); 29 | void socket_info_release(struct socket_info *); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /skynet-src/socket_poll.h: -------------------------------------------------------------------------------- 1 | #ifndef socket_poll_h 2 | #define socket_poll_h 3 | 4 | #include 5 | 6 | typedef int poll_fd; 7 | 8 | struct event { 9 | void * s; 10 | bool read; 11 | bool write; 12 | bool error; 13 | bool eof; 14 | }; 15 | 16 | static bool sp_invalid(poll_fd fd); 17 | static poll_fd sp_create(); 18 | static void sp_release(poll_fd fd); 19 | static int sp_add(poll_fd fd, int sock, void *ud); 20 | static void sp_del(poll_fd fd, int sock); 21 | static int sp_enable(poll_fd, int sock, void *ud, bool read_enable, bool write_enable); 22 | static int sp_wait(poll_fd, struct event *e, int max); 23 | static void sp_nonblocking(int sock); 24 | 25 | #ifdef __linux__ 26 | #include "socket_epoll.h" 27 | #endif 28 | 29 | #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined (__NetBSD__) 30 | #include "socket_kqueue.h" 31 | #endif 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /test/pingserver.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local queue = require "skynet.queue" 3 | local snax = require "skynet.snax" 4 | 5 | local i = 0 6 | local hello = "hello" 7 | 8 | function response.ping(hello) 9 | skynet.sleep(100) 10 | return hello 11 | end 12 | 13 | -- response.sleep and accept.hello share one lock 14 | local lock 15 | 16 | function accept.sleep(queue, n) 17 | if queue then 18 | lock( 19 | function() 20 | print("queue=",queue, n) 21 | skynet.sleep(n) 22 | end) 23 | else 24 | print("queue=",queue, n) 25 | skynet.sleep(n) 26 | end 27 | end 28 | 29 | function accept.hello() 30 | lock(function() 31 | i = i + 1 32 | print (i, hello) 33 | end) 34 | end 35 | 36 | function accept.exit(...) 37 | snax.exit(...) 38 | end 39 | 40 | function response.error() 41 | error "throw an error" 42 | end 43 | 44 | function init( ... ) 45 | print ("ping server start:", ...) 46 | snax.enablecluster() -- enable cluster call 47 | -- init queue 48 | lock = queue() 49 | end 50 | 51 | function exit(...) 52 | print ("ping server exit:", ...) 53 | end 54 | -------------------------------------------------------------------------------- /test/sharemap.sp: -------------------------------------------------------------------------------- 1 | .foobar { 2 | x 0 : integer 3 | y 1 : integer 4 | s 2 : string 5 | } 6 | -------------------------------------------------------------------------------- /test/testbson.lua: -------------------------------------------------------------------------------- 1 | local bson = require "bson" 2 | 3 | local sub = bson.encode_order( "hello", 1, "world", 2 ) 4 | 5 | do 6 | -- check decode encode_order 7 | local d = bson.decode(sub) 8 | assert(d.hello == 1 ) 9 | assert(d.world == 2 ) 10 | end 11 | 12 | local function tbl_next(...) 13 | print("--- next.a", ...) 14 | local k, v = next(...) 15 | print("--- next.b", k, v) 16 | return k, v 17 | end 18 | 19 | local function tbl_pairs(obj) 20 | return tbl_next, obj.__data, nil 21 | end 22 | 23 | local obj_a = { 24 | __data = { 25 | ["1"] = 2, 26 | ["3"] = 4, 27 | ["5"] = 6, 28 | } 29 | } 30 | 31 | setmetatable( 32 | obj_a, 33 | { 34 | __index = obj_a.__data, 35 | __pairs = tbl_pairs, 36 | } 37 | ) 38 | 39 | local obj_b = { 40 | __data = { 41 | ["7"] = 8, 42 | ["9"] = 10, 43 | ["11"] = obj_a, 44 | } 45 | } 46 | 47 | setmetatable( 48 | obj_b, 49 | { 50 | __index = obj_b.__data, 51 | __pairs = tbl_pairs, 52 | } 53 | ) 54 | 55 | local metaarray = setmetatable({ n = 5 }, { 56 | __len = function(self) return self.n end, 57 | __index = function(self, idx) return tostring(idx) end, 58 | }) 59 | 60 | b = bson.encode { 61 | a = 1, 62 | b = true, 63 | c = bson.null, 64 | d = { 1,2,3,4 }, 65 | e = bson.binary "hello", 66 | f = bson.regex ("*","i"), 67 | g = bson.regex "hello", 68 | h = bson.date (os.time()), 69 | i = bson.timestamp(os.time()), 70 | j = bson.objectid(), 71 | k = { a = false, b = true }, 72 | l = {}, 73 | m = bson.minkey, 74 | n = bson.maxkey, 75 | o = sub, 76 | p = 2^32-1, 77 | q = obj_b, 78 | r = metaarray, 79 | } 80 | 81 | print "\n[before replace]" 82 | t = b:decode() 83 | 84 | for k, v in pairs(t) do 85 | print(k,type(v)) 86 | end 87 | 88 | for k,v in ipairs(t.r) do 89 | print(k,v) 90 | end 91 | 92 | b:makeindex() 93 | b.a = 2 94 | b.b = false 95 | b.h = bson.date(os.time()) 96 | b.i = bson.timestamp(os.time()) 97 | b.j = bson.objectid() 98 | 99 | print "\n[after replace]" 100 | t = b:decode() 101 | 102 | print("o.hello", bson.type(t.o.hello)) 103 | -------------------------------------------------------------------------------- /test/testcoroutine.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | -- You should use skynet.coroutine instead of origin coroutine in skynet 3 | local coroutine = require "skynet.coroutine" 4 | local profile = require "skynet.profile" 5 | 6 | local function status(co) 7 | repeat 8 | local status = coroutine.status(co) 9 | print("STATUS", status) 10 | skynet.sleep(100) 11 | until status == "suspended" 12 | 13 | repeat 14 | local ok, n = assert(coroutine.resume(co)) 15 | print("status thread", n) 16 | until not n 17 | skynet.exit() 18 | end 19 | 20 | local function test(n) 21 | local co = coroutine.running() 22 | print ("begin", co, coroutine.thread(co)) -- false 23 | skynet.fork(status, co) 24 | for i=1,n do 25 | skynet.sleep(100) 26 | coroutine.yield(i) 27 | end 28 | print ("end", co) 29 | end 30 | 31 | local function main() 32 | local f = coroutine.wrap(test) 33 | coroutine.yield "begin" 34 | for i=1,3 do 35 | local n = f(5) 36 | print("main thread",n) 37 | end 38 | coroutine.yield "end" 39 | print("main thread time:", profile.stop(coroutine.thread())) 40 | end 41 | 42 | skynet.start(function() 43 | print("Main thead :", coroutine.thread()) -- true 44 | print(coroutine.resume(coroutine.running())) -- always return false 45 | 46 | profile.start() 47 | 48 | local f = coroutine.wrap(main) 49 | print("main step", f()) 50 | print("main step", f()) 51 | print("main step", f()) 52 | -- print("main thread time:", profile.stop()) 53 | print("close", coroutine.close(coroutine.create(main))) 54 | end) 55 | -------------------------------------------------------------------------------- /test/testcrypt.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local crypt = require "skynet.crypt" 3 | 4 | local text = "hello world" 5 | local key = "12345678" 6 | 7 | local function desencode(key, text, padding) 8 | local c = crypt.desencode(key, text, crypt.padding[padding or "iso7816_4"]) 9 | return crypt.base64encode(c) 10 | end 11 | 12 | local function desdecode(key, text, padding) 13 | text = crypt.base64decode(text) 14 | return crypt.desdecode(key, text, crypt.padding[padding or "iso7816_4"]) 15 | end 16 | 17 | local etext = desencode(key, text) 18 | assert( etext == "KNugLrX23UcGtcVlk9y+LA==") 19 | assert(desdecode(key, etext) == text) 20 | 21 | local etext = desencode(key, text, "pkcs7") 22 | assert(desdecode(key, etext, "pkcs7") == text) 23 | 24 | assert(desencode(key, "","pkcs7")=="/rlZt9RkL8s=") 25 | assert(desencode(key, "1","pkcs7")=="g6AtgJul6q0=") 26 | assert(desencode(key, "12","pkcs7")=="NefFpG+m1O4=") 27 | assert(desencode(key, "123","pkcs7")=="LDiFUdf0iew=") 28 | assert(desencode(key, "1234","pkcs7")=="T9u7dzBdi+w=") 29 | assert(desencode(key, "12345","pkcs7")=="AGgKdx/Qic8=") 30 | assert(desencode(key, "123456","pkcs7")=="ED5wLgc3Mnw=") 31 | assert(desencode(key, "1234567","pkcs7")=="mYo+BYIT41M=") 32 | assert(desencode(key, "12345678","pkcs7")=="ltACiHjVjIn+uVm31GQvyw==") 33 | 34 | skynet.start(skynet.exit) -------------------------------------------------------------------------------- /test/testdatacenter.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local datacenter = require "skynet.datacenter" 3 | 4 | local function f1() 5 | print("====1==== wait hello") 6 | print("\t1>",datacenter.wait ("hello")) 7 | print("====1==== wait key.foobar") 8 | print("\t1>", pcall(datacenter.wait,"key")) -- will failed, because "key" is a branch 9 | print("\t1>",datacenter.wait ("key", "foobar")) 10 | end 11 | 12 | local function f2() 13 | skynet.sleep(10) 14 | print("====2==== set key.foobar") 15 | datacenter.set("key", "foobar", "bingo") 16 | end 17 | 18 | skynet.start(function() 19 | datacenter.set("hello", "world") 20 | print(datacenter.get "hello") 21 | skynet.fork(f1) 22 | skynet.fork(f2) 23 | end) 24 | -------------------------------------------------------------------------------- /test/testdatasheet.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local mode = ... 4 | 5 | local function dump(t, prefix) 6 | for k,v in pairs(t) do 7 | print(prefix, k, v) 8 | if type(v) == "table" then 9 | dump(v, prefix .. "." .. k) 10 | end 11 | end 12 | end 13 | 14 | if mode == "child" then 15 | 16 | local datasheet = require "skynet.datasheet" 17 | 18 | skynet.start(function() 19 | local t = datasheet.query("foobar") 20 | dump(t, "[CHILD]") 21 | 22 | skynet.sleep(100) 23 | skynet.exit() 24 | end) 25 | 26 | else 27 | 28 | local builder = require "skynet.datasheet.builder" 29 | local datasheet = require "skynet.datasheet" 30 | 31 | skynet.start(function() 32 | builder.new("foobar", {a = 1, b = 2 , c = {3} }) 33 | skynet.newservice(SERVICE_NAME, "child") 34 | local t = datasheet.query "foobar" 35 | local c = t.c 36 | dump(t, "[1]") 37 | builder.update("foobar", { b = 4, c = { 5 } }) 38 | print("sleep") 39 | skynet.sleep(100) 40 | dump(t, "[2]") 41 | dump(c, "[2.c]") 42 | builder.update("foobar", { a = 6, c = 7, d = 8 }) 43 | print("sleep") 44 | skynet.sleep(100) 45 | dump(t, "[3]") 46 | end) 47 | 48 | end -------------------------------------------------------------------------------- /test/testdeadcall.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local mode = ... 4 | 5 | if mode == "test" then 6 | 7 | skynet.start(function() 8 | skynet.dispatch("lua", function (...) 9 | print("====>", ...) 10 | skynet.exit() 11 | end) 12 | end) 13 | 14 | elseif mode == "dead" then 15 | 16 | skynet.start(function() 17 | skynet.dispatch("lua", function (...) 18 | skynet.sleep(100) 19 | print("return", skynet.ret "") 20 | end) 21 | end) 22 | 23 | else 24 | 25 | skynet.start(function() 26 | local test = skynet.newservice(SERVICE_NAME, "test") -- launch self in test mode 27 | 28 | print(pcall(function() 29 | skynet.call(test,"lua", "dead call") 30 | end)) 31 | 32 | local dead = skynet.newservice(SERVICE_NAME, "dead") -- launch self in dead mode 33 | 34 | skynet.timeout(0, skynet.exit) -- exit after a while, so the call never return 35 | skynet.call(dead, "lua", "would not return") 36 | end) 37 | end 38 | -------------------------------------------------------------------------------- /test/testdeadloop.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local function dead_loop() 3 | while true do 4 | skynet.sleep(0) 5 | end 6 | end 7 | 8 | skynet.start(function() 9 | skynet.fork(dead_loop) 10 | end) 11 | -------------------------------------------------------------------------------- /test/testdns.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local dns = require "skynet.dns" 3 | 4 | local resolve_list = { 5 | "github.com", 6 | "stackoverflow.com", 7 | "lua.com", 8 | } 9 | 10 | skynet.start(function() 11 | -- you can specify the server like dns.server("8.8.4.4", 53) 12 | for _ , name in ipairs(resolve_list) do 13 | local ip, ips = dns.resolve(name) 14 | for k,v in ipairs(ips) do 15 | print(name,v) 16 | end 17 | skynet.sleep(500) -- sleep 5 sec 18 | end 19 | end) 20 | -------------------------------------------------------------------------------- /test/testecho.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local mode = ... 4 | 5 | if mode == "slave" then 6 | 7 | skynet.start(function() 8 | skynet.dispatch("lua", function(_,_, ...) 9 | skynet.ret(skynet.pack(...)) 10 | end) 11 | end) 12 | 13 | else 14 | 15 | skynet.start(function() 16 | local slave = skynet.newservice(SERVICE_NAME, "slave") 17 | local n = 100000 18 | local start = skynet.now() 19 | print("call salve", n, "times in queue") 20 | for i=1,n do 21 | skynet.call(slave, "lua") 22 | end 23 | print("qps = ", n/ (skynet.now() - start) * 100) 24 | 25 | start = skynet.now() 26 | 27 | local worker = 10 28 | local task = n/worker 29 | print("call salve", n, "times in parallel, worker = ", worker) 30 | 31 | for i=1,worker do 32 | skynet.fork(function() 33 | for i=1,task do 34 | skynet.call(slave, "lua") 35 | end 36 | worker = worker -1 37 | if worker == 0 then 38 | print("qps = ", n/ (skynet.now() - start) * 100) 39 | end 40 | end) 41 | end 42 | end) 43 | 44 | end 45 | -------------------------------------------------------------------------------- /test/testendless.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | skynet.start(function() 4 | for i = 1, 1000000000 do -- very long loop 5 | if i%100000000 == 0 then 6 | print("Endless = ", skynet.stat "endless") 7 | print("Cost time = ", skynet.stat "time") 8 | end 9 | end 10 | skynet.exit() 11 | end) 12 | -------------------------------------------------------------------------------- /test/testharborlink.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local harbor = require "skynet.harbor" 3 | 4 | skynet.start(function() 5 | print("wait for harbor 2") 6 | print("run skynet examples/config_log please") 7 | harbor.connect(2) 8 | print("harbor 2 connected") 9 | print("LOG =", skynet.address(harbor.queryname "LOG")) 10 | harbor.link(2) 11 | print("disconnected") 12 | end) 13 | -------------------------------------------------------------------------------- /test/testhttp.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local httpc = require "http.httpc" 3 | local dns = require "skynet.dns" 4 | 5 | local function http_test(protocol) 6 | --httpc.dns() -- set dns server 7 | httpc.timeout = 100 -- set timeout 1 second 8 | print("GET baidu.com") 9 | protocol = protocol or "http" 10 | local respheader = {} 11 | local host = string.format("%s://baidu.com", protocol) 12 | print("geting... ".. host) 13 | local status, body = httpc.get(host, "/", respheader) 14 | print("[header] =====>") 15 | for k,v in pairs(respheader) do 16 | print(k,v) 17 | end 18 | print("[body] =====>", status) 19 | print(body) 20 | 21 | local respheader = {} 22 | local ip = dns.resolve "baidu.com" 23 | print(string.format("GET %s (baidu.com)", ip)) 24 | local status, body = httpc.get(host, "/", respheader, { host = "baidu.com" }) 25 | print(status) 26 | end 27 | 28 | local function http_stream_test() 29 | for resp, stream in httpc.request_stream("GET", "http://baidu.com", "/") do 30 | print("STATUS", stream.status) 31 | for k,v in pairs(stream.header) do 32 | print("HEADER",k,v) 33 | end 34 | print("BODY", resp) 35 | end 36 | end 37 | 38 | local function http_head_test() 39 | httpc.timeout = 100 40 | local respheader = {} 41 | local status = httpc.head("http://baidu.com", "/", respheader) 42 | for k,v in pairs(respheader) do 43 | print("HEAD", k, v) 44 | end 45 | end 46 | 47 | local function main() 48 | dns.server() 49 | 50 | http_stream_test() 51 | http_head_test() 52 | 53 | http_test("http") 54 | if not pcall(require,"ltls.c") then 55 | print "No ltls module, https is not supported" 56 | else 57 | http_test("https") 58 | end 59 | end 60 | 61 | skynet.start(function() 62 | print(pcall(main)) 63 | skynet.exit() 64 | end) 65 | -------------------------------------------------------------------------------- /test/testmemlimit.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local names = { 4 | "cluster", 5 | "skynet.db.dns", 6 | "skynet.db.mongo", 7 | "skynet.db.mysql", 8 | "skynet.db.redis", 9 | "sharedata", 10 | "skynet.socket", 11 | "sproto" 12 | } 13 | 14 | -- set sandbox memory limit to 1M, must set here (at start, out of skynet.start) 15 | skynet.memlimit(1 * 1024 * 1024) 16 | 17 | skynet.start(function() 18 | local a = {} 19 | local limit 20 | local ok, err = pcall(function() 21 | for i=1, 12355 do 22 | limit = i 23 | table.insert(a, {}) 24 | end 25 | end) 26 | local libs = {} 27 | for k,v in ipairs(names) do 28 | local ok, m = pcall(require, v) 29 | if ok then 30 | libs[v] = m 31 | end 32 | end 33 | skynet.error(limit, err) 34 | skynet.exit() 35 | end) 36 | -------------------------------------------------------------------------------- /test/testmulticast.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local mc = require "skynet.multicast" 3 | local dc = require "skynet.datacenter" 4 | 5 | local mode = ... 6 | 7 | if mode == "sub" then 8 | 9 | skynet.start(function() 10 | skynet.dispatch("lua", function (_,_, cmd, channel) 11 | assert(cmd == "init") 12 | local c = mc.new { 13 | channel = channel , 14 | dispatch = function (channel, source, ...) 15 | print(string.format("%s <=== %s %s",skynet.address(skynet.self()),skynet.address(source), channel), ...) 16 | end 17 | } 18 | print(skynet.address(skynet.self()), "sub", c) 19 | c:subscribe() 20 | skynet.ret(skynet.pack()) 21 | end) 22 | end) 23 | 24 | else 25 | 26 | skynet.start(function() 27 | local channel = mc.new() 28 | print("New channel", channel) 29 | for i=1,10 do 30 | local sub = skynet.newservice(SERVICE_NAME, "sub") 31 | skynet.call(sub, "lua", "init", channel.channel) 32 | end 33 | 34 | dc.set("MCCHANNEL", channel.channel) -- for multi node test 35 | 36 | print(skynet.address(skynet.self()), "===>", channel) 37 | channel:publish("Hello World") 38 | end) 39 | 40 | end -------------------------------------------------------------------------------- /test/testmulticast2.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local dc = require "skynet.datacenter" 3 | local mc = require "skynet.multicast" 4 | 5 | skynet.start(function() 6 | print("remote start") 7 | local console = skynet.newservice("console") 8 | local channel = dc.get "MCCHANNEL" 9 | if channel then 10 | print("remote channel", channel) 11 | else 12 | print("create local channel") 13 | end 14 | for i=1,10 do 15 | local sub = skynet.newservice("testmulticast", "sub") 16 | skynet.call(sub, "lua", "init", channel) 17 | end 18 | local c = mc.new { 19 | channel = channel , 20 | dispatch = function(...) print("======>", ...) end, 21 | } 22 | c:subscribe() 23 | c:publish("Remote message") 24 | c:unsubscribe() 25 | c:publish("Remote message2") 26 | c:delete() 27 | skynet.exit() 28 | end) 29 | -------------------------------------------------------------------------------- /test/testoverload.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local mode = ... 4 | 5 | if mode == "slave" then 6 | 7 | local CMD = {} 8 | 9 | function CMD.sum(n) 10 | skynet.error("for loop begin") 11 | local s = 0 12 | for i = 1, n do 13 | s = s + i 14 | end 15 | skynet.error("for loop end") 16 | end 17 | 18 | function CMD.blackhole() 19 | end 20 | 21 | skynet.start(function() 22 | skynet.dispatch("lua", function(_,_, cmd, ...) 23 | local f = CMD[cmd] 24 | f(...) 25 | end) 26 | end) 27 | 28 | else 29 | 30 | skynet.start(function() 31 | local slave = skynet.newservice(SERVICE_NAME, "slave") 32 | for step = 1, 20 do 33 | skynet.error("overload test ".. step) 34 | for i = 1, 512 * step do 35 | skynet.send(slave, "lua", "blackhole") 36 | end 37 | skynet.sleep(step) 38 | end 39 | local n = 1000000000 40 | skynet.error(string.format("endless test n=%d", n)) 41 | skynet.send(slave, "lua", "sum", n) 42 | end) 43 | 44 | end 45 | -------------------------------------------------------------------------------- /test/testping.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local snax = require "skynet.snax" 3 | 4 | skynet.start(function() 5 | skynet.trace() 6 | local ps = snax.newservice ("pingserver", "hello world") 7 | print(ps.req.ping("foobar")) 8 | print(ps.post.hello()) 9 | print(pcall(ps.req.error)) 10 | print("Hotfix (i) :", snax.hotfix(ps, [[ 11 | 12 | local i 13 | local hello 14 | 15 | function accept.hello() 16 | i = i + 1 17 | print ("fix", i, hello) 18 | end 19 | 20 | function hotfix(...) 21 | local temp = i 22 | i = 100 23 | return temp 24 | end 25 | 26 | ]])) 27 | print(ps.post.hello()) 28 | 29 | local info = skynet.call(ps.handle, "debug", "INFO") 30 | 31 | for name,v in pairs(info) do 32 | print(string.format("%s\tcount:%d time:%f", name, v.count, v.time)) 33 | end 34 | 35 | print(ps.post.exit("exit")) -- == snax.kill(ps, "exit") 36 | skynet.exit() 37 | end) 38 | -------------------------------------------------------------------------------- /test/testpipeline.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local redis = require "skynet.db.redis" 3 | 4 | local conf = { 5 | host = "127.0.0.1", 6 | port = 6379, 7 | db = 0 8 | } 9 | 10 | local function read_table(t) 11 | local result = { } 12 | for i = 1, #t, 2 do result[t[i]] = t[i + 1] end 13 | return result 14 | end 15 | 16 | skynet.start(function() 17 | local db = redis.connect(conf) 18 | 19 | db.pipelining = function (self, block) 20 | local ops = {} 21 | 22 | block(setmetatable({}, { 23 | __index = function (_, name) 24 | return function (_, ...) 25 | table.insert(ops, {name, ...}) 26 | end 27 | end 28 | })) 29 | 30 | return self:pipeline(ops) 31 | end 32 | 33 | do 34 | print("test function") 35 | local ret = db:pipelining(function (red) 36 | red:multi() 37 | red:hincrby("hello", 1, 1) 38 | red:del("hello") 39 | red:hmset("hello", 1, 1, 2, 2, 3, 3) 40 | red:hgetall("hello") 41 | red:exec() 42 | end) 43 | -- ret is the result of red:exec() 44 | for k, v in pairs(read_table(ret[4])) do 45 | print(k, v) 46 | end 47 | end 48 | 49 | do 50 | print("test table") 51 | local ret = db:pipeline({ 52 | {"hincrby", "hello", 1, 1}, 53 | {"del", "hello"}, 54 | {"hmset", "hello", 1, 1, 2, 2, 3, 3}, 55 | {"hgetall", "hello"}, 56 | }, {}) -- offer a {} for result 57 | 58 | print(ret[1].out) 59 | print(ret[2].out) 60 | print(ret[3].out) 61 | 62 | for k, v in pairs(read_table(ret[4].out)) do 63 | print(k, v) 64 | end 65 | end 66 | 67 | db:disconnect() 68 | skynet.exit() 69 | end) 70 | 71 | -------------------------------------------------------------------------------- /test/testqueue.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local snax = require "skynet.snax" 3 | 4 | skynet.start(function() 5 | local ps = snax.uniqueservice ("pingserver", "test queue") 6 | for i=1, 10 do 7 | ps.post.sleep(true,i*10) 8 | ps.post.hello() 9 | end 10 | for i=1, 10 do 11 | ps.post.sleep(false,i*10) 12 | ps.post.hello() 13 | end 14 | 15 | skynet.exit() 16 | end) 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/testredis.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local redis = require "skynet.db.redis" 3 | 4 | local conf = { 5 | host = "127.0.0.1" , 6 | port = 6379 , 7 | db = 0 8 | } 9 | 10 | local function watching() 11 | local w = redis.watch(conf) 12 | w:subscribe "foo" 13 | w:psubscribe "hello.*" 14 | while true do 15 | print("Watch", w:message()) 16 | end 17 | end 18 | 19 | skynet.start(function() 20 | skynet.fork(watching) 21 | local db = redis.connect(conf) 22 | 23 | db:del "C" 24 | db:set("A", "hello") 25 | db:set("B", "world") 26 | db:sadd("C", "one") 27 | 28 | print(db:get("A")) 29 | print(db:get("B")) 30 | 31 | db:del "D" 32 | for i=1,10 do 33 | db:hset("D",i,i) 34 | end 35 | local r = db:hvals "D" 36 | for k,v in pairs(r) do 37 | print(k,v) 38 | end 39 | 40 | db:multi() 41 | db:get "A" 42 | db:get "B" 43 | local t = db:exec() 44 | for k,v in ipairs(t) do 45 | print("Exec", v) 46 | end 47 | 48 | print(db:exists "A") 49 | print(db:get "A") 50 | print(db:set("A","hello world")) 51 | print(db:get("A")) 52 | print(db:sismember("C","one")) 53 | print(db:sismember("C","two")) 54 | 55 | print("===========publish============") 56 | 57 | for i=1,10 do 58 | db:publish("foo", i) 59 | end 60 | for i=11,20 do 61 | db:publish("hello.foo", i) 62 | end 63 | 64 | db:disconnect() 65 | -- skynet.exit() 66 | end) 67 | 68 | -------------------------------------------------------------------------------- /test/testredis2.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local redis = require "skynet.db.redis" 3 | 4 | local db 5 | 6 | function add1(key, count) 7 | local t = {} 8 | for i = 1, count do 9 | t[2*i -1] = "key" ..i 10 | t[2*i] = "value" .. i 11 | end 12 | db:hmset(key, table.unpack(t)) 13 | end 14 | 15 | function add2(key, count) 16 | local t = {} 17 | for i = 1, count do 18 | t[2*i -1] = "key" ..i 19 | t[2*i] = "value" .. i 20 | end 21 | table.insert(t, 1, key) 22 | db:hmset(t) 23 | end 24 | 25 | function __init__() 26 | db = redis.connect { 27 | host = "127.0.0.1", 28 | port = 6300, 29 | db = 0, 30 | auth = "foobared" 31 | } 32 | print("dbsize:", db:dbsize()) 33 | local ok, msg = xpcall(add1, debug.traceback, "test1", 250000) 34 | if not ok then 35 | print("add1 failed", msg) 36 | else 37 | print("add1 succeed") 38 | 39 | end 40 | 41 | local ok, msg = xpcall(add2, debug.traceback, "test2", 250000) 42 | if not ok then 43 | print("add2 failed", msg) 44 | else 45 | print("add2 succeed") 46 | end 47 | print("dbsize:", db:dbsize()) 48 | 49 | print("redistest launched") 50 | end 51 | 52 | skynet.start(__init__) 53 | 54 | -------------------------------------------------------------------------------- /test/testresponse.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local mode = ... 4 | 5 | if mode == "TICK" then 6 | -- this service whould response the request every 1s. 7 | 8 | local response_queue = {} 9 | 10 | local function response() 11 | while true do 12 | skynet.sleep(100) -- sleep 1s 13 | for k,v in ipairs(response_queue) do 14 | v(true, skynet.now()) -- true means succ, false means error 15 | response_queue[k] = nil 16 | end 17 | end 18 | end 19 | 20 | skynet.start(function() 21 | skynet.fork(response) 22 | skynet.dispatch("lua", function() 23 | table.insert(response_queue, skynet.response()) 24 | end) 25 | end) 26 | 27 | else 28 | 29 | local function request(tick, i) 30 | print(i, "call", skynet.now()) 31 | print(i, "response", skynet.call(tick, "lua")) 32 | print(i, "end", skynet.now()) 33 | end 34 | 35 | skynet.start(function() 36 | local tick = skynet.newservice(SERVICE_NAME, "TICK") 37 | 38 | for i=1,5 do 39 | skynet.fork(request, tick, i) 40 | skynet.sleep(10) 41 | end 42 | end) 43 | 44 | end -------------------------------------------------------------------------------- /test/testselect.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local mode = ... 4 | 5 | if mode == "slave" then 6 | 7 | local COMMAND = {} 8 | 9 | function COMMAND.ping(ti, str) 10 | skynet.sleep(ti) 11 | return str 12 | end 13 | 14 | function COMMAND.error() 15 | error "ERROR" 16 | end 17 | 18 | function COMMAND.exit() 19 | skynet.exit() 20 | end 21 | 22 | skynet.start(function() 23 | skynet.dispatch("lua", function(_,_, cmd, ...) 24 | skynet.ret(skynet.pack(COMMAND[cmd](...))) 25 | end) 26 | end) 27 | 28 | else 29 | 30 | local function info(fmt, ...) 31 | skynet.error(string.format(fmt, ...)) 32 | end 33 | 34 | skynet.start(function() 35 | local slave = skynet.newservice(SERVICE_NAME, "slave") 36 | 37 | for req, resp in skynet.request 38 | { slave, "lua", "ping", 6, "SLEEP 6" } 39 | { slave, "lua", "ping", 5, "SLEEP 5" } 40 | { slave, "lua", "ping", 4, "SLEEP 4" } 41 | { slave, "lua", "ping", 3, "SLEEP 3" } 42 | { slave, "lua", "ping", 2, "SLEEP 2" } 43 | { slave, "lua", "ping", 1, "SLEEP 1" } 44 | :select() do 45 | info("RESP %s", resp[1]) 46 | end 47 | 48 | -- test timeout 49 | local reqs = skynet.request() 50 | 51 | for i = 1, 10 do 52 | reqs:add { slave, "lua", "ping", i*10, "SLEEP " .. i, token = i } 53 | end 54 | 55 | for req, resp in reqs:select(50) do 56 | info("RESP %s token<%s>", resp[1], req.token) 57 | end 58 | 59 | -- test error 60 | 61 | for req, resp in skynet.request 62 | { slave, "lua", "error" } 63 | { slave, "lua", "ping", 0, "PING" } 64 | : select() do 65 | if resp then 66 | info("Ping : %s", resp[1]) 67 | else 68 | info("Error") 69 | end 70 | end 71 | 72 | -- timeout call 73 | 74 | local reqs = skynet.request { slave, "lua", "ping", 100 , "PING" } 75 | for req, resp in reqs:select(10) do 76 | info("%s", resp[1]) 77 | end 78 | 79 | info("Timeout : %s", reqs.timeout) 80 | 81 | -- call in select 82 | for req, resp in skynet.request 83 | { slave, "lua", "ping", 20, "CALL 20" } 84 | { slave, "lua", "ping", 10, "CALL 10" } 85 | : select() do 86 | info("%s", skynet.call( slave, "lua", "ping", 0, "ping in " .. resp[1]) ) 87 | skynet.sleep(50) 88 | end 89 | 90 | skynet.send(slave, "lua", "exit") 91 | skynet.exit() 92 | end) 93 | 94 | end 95 | -------------------------------------------------------------------------------- /test/testservice/init.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local kvdb = require "kvdb" 3 | 4 | local function dbname(i) 5 | return "db"..i 6 | end 7 | skynet.start(function() 8 | for i=1,10 do 9 | kvdb.new(dbname(i)) 10 | end 11 | local idx=1 12 | for i=1,10 do 13 | local db=dbname(i) 14 | kvdb.set(db,"A",idx) 15 | idx=idx+1 16 | kvdb.set(db,"B",idx) 17 | idx=idx+1 18 | end 19 | for i=1,10 do 20 | local db=dbname(i) 21 | print(db,kvdb.get(db,"A"),kvdb.get(db,"B")) 22 | end 23 | end) 24 | -------------------------------------------------------------------------------- /test/testservice/kvdb.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local service = require "skynet.service" 3 | 4 | local kvdb = {} 5 | 6 | function kvdb.get(db,key) 7 | return skynet.call(service.query(db), "lua", "get", key) 8 | end 9 | 10 | function kvdb.set(db,key, value) 11 | skynet.call(service.query(db), "lua", "set", key , value) 12 | end 13 | 14 | -- this function will be injected into an unique service, so don't refer any upvalues 15 | local function service_mainfunc(...) 16 | local skynet = require "skynet" 17 | 18 | skynet.error(...) -- (...) passed from service.new 19 | 20 | local db = {} 21 | 22 | local command = {} 23 | 24 | function command.get(key) 25 | return db[key] 26 | end 27 | 28 | function command.set(key, value) 29 | db[key] = value 30 | end 31 | 32 | -- skynet.start is compatible 33 | skynet.dispatch("lua", function(session, address, cmd, ...) 34 | skynet.ret(skynet.pack(command[cmd](...))) 35 | end) 36 | end 37 | 38 | function kvdb.new(db) 39 | return service.new(db, service_mainfunc, "Service Init") 40 | end 41 | 42 | return kvdb 43 | -------------------------------------------------------------------------------- /test/testsharetable.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local sharetable = require "skynet.sharetable" 3 | 4 | skynet.start(function() 5 | -- You can also use sharetable.loadfile / sharetable.loadstring 6 | sharetable.loadtable ("test", { x=1,y={ 'hello world' },['hello world'] = true }) 7 | local t = sharetable.query("test") 8 | for k,v in pairs(t) do 9 | print(k,v) 10 | end 11 | sharetable.loadstring ("test", "return { ... }", 1,2,3) 12 | local t = sharetable.query("test") 13 | for k,v in pairs(t) do 14 | print(k,v) 15 | end 16 | end) 17 | -------------------------------------------------------------------------------- /test/testsm.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local sharemap = require "skynet.sharemap" 3 | 4 | local mode = ... 5 | 6 | if mode == "slave" then 7 | --slave 8 | 9 | local function dump(reader) 10 | reader:update() 11 | print("x=", reader.x) 12 | print("y=", reader.y) 13 | print("s=", reader.s) 14 | end 15 | 16 | skynet.start(function() 17 | local reader 18 | skynet.dispatch("lua", function(_,_,cmd,...) 19 | if cmd == "init" then 20 | reader = sharemap.reader(...) 21 | else 22 | assert(cmd == "ping") 23 | dump(reader) 24 | end 25 | skynet.ret() 26 | end) 27 | end) 28 | 29 | else 30 | -- master 31 | skynet.start(function() 32 | -- register share type schema 33 | sharemap.register("./test/sharemap.sp") 34 | local slave = skynet.newservice(SERVICE_NAME, "slave") 35 | local writer = sharemap.writer("foobar", { x=0,y=0,s="hello" }) 36 | skynet.call(slave, "lua", "init", "foobar", writer:copy()) 37 | writer.x = 1 38 | writer:commit() 39 | skynet.call(slave, "lua", "ping") 40 | writer.y = 2 41 | writer:commit() 42 | skynet.call(slave, "lua", "ping") 43 | writer.s = "world" 44 | writer:commit() 45 | skynet.call(slave, "lua", "ping") 46 | end) 47 | 48 | end -------------------------------------------------------------------------------- /test/testsocket.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local socket = require "skynet.socket" 3 | 4 | local mode , id = ... 5 | 6 | local function echo(id) 7 | socket.start(id) 8 | socket.write(id, "Hello Skynet\n") 9 | 10 | while true do 11 | local str = socket.read(id) 12 | if str then 13 | socket.write(id, str) 14 | else 15 | socket.close(id) 16 | return 17 | end 18 | end 19 | end 20 | 21 | if mode == "agent" then 22 | id = tonumber(id) 23 | 24 | skynet.start(function() 25 | skynet.fork(function() 26 | echo(id) 27 | skynet.exit() 28 | end) 29 | end) 30 | else 31 | local function accept(id) 32 | skynet.newservice(SERVICE_NAME, "agent", id) 33 | end 34 | 35 | skynet.start(function() 36 | local id = socket.listen("127.0.0.1", 8001) 37 | print("Listen socket :", "127.0.0.1", 8001) 38 | 39 | socket.start(id , function(id, addr) 40 | print("connect from " .. addr .. " " .. id) 41 | -- you have choices : 42 | -- 1. skynet.newservice("testsocket", "agent", id) 43 | -- 2. skynet.fork(echo, id) 44 | -- 3. accept(id) 45 | accept(id) 46 | end) 47 | end) 48 | end -------------------------------------------------------------------------------- /test/teststm.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local stm = require "skynet.stm" 3 | 4 | local mode = ... 5 | 6 | if mode == "slave" then 7 | 8 | skynet.start(function() 9 | skynet.dispatch("lua", function (_,_, obj) 10 | local obj = stm.newcopy(obj) 11 | print("read:", obj(skynet.unpack)) 12 | skynet.ret() 13 | skynet.error("sleep and read") 14 | for i=1,10 do 15 | skynet.sleep(10) 16 | print("read:", obj(skynet.unpack)) 17 | end 18 | skynet.exit() 19 | end) 20 | end) 21 | 22 | else 23 | 24 | skynet.start(function() 25 | local slave = skynet.newservice(SERVICE_NAME, "slave") 26 | local obj = stm.new(skynet.pack(1,2,3,4,5)) 27 | local copy = stm.copy(obj) 28 | skynet.call(slave, "lua", copy) 29 | for i=1,5 do 30 | skynet.sleep(20) 31 | print("write", i) 32 | obj(skynet.pack("hello world", i)) 33 | end 34 | skynet.exit() 35 | end) 36 | end 37 | -------------------------------------------------------------------------------- /test/testterm.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local function term() 4 | skynet.error("Sleep one second, and term the call to UNEXIST") 5 | skynet.sleep(100) 6 | local self = skynet.self() 7 | skynet.send(skynet.self(), "debug", "TERM", "UNEXIST") 8 | end 9 | 10 | skynet.start(function() 11 | skynet.fork(term) 12 | skynet.error("call an unexist named service UNEXIST, may block") 13 | pcall(skynet.call, "UNEXIST", "lua", "test") 14 | skynet.error("unblock the unexisted service call") 15 | end) 16 | -------------------------------------------------------------------------------- /test/testtimeout.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local service = require "skynet.service" 3 | 4 | local function test_service() 5 | local skynet = require "skynet" 6 | 7 | skynet.start(function() 8 | skynet.dispatch("lua", function() 9 | skynet.error("Wait for 1s") 10 | skynet.sleep(100) -- response after 1s for any request 11 | skynet.ret() 12 | end) 13 | end) 14 | end 15 | 16 | local function timeout_call(ti, ...) 17 | local token = {} 18 | local ret 19 | 20 | skynet.fork(function(...) 21 | ret = table.pack(pcall(skynet.call, ...)) 22 | skynet.wakeup(token) 23 | end, ...) 24 | 25 | skynet.sleep(ti, token) 26 | if ret then 27 | if ret[1] then 28 | return table.unpack(ret, 1, ret.n) 29 | else 30 | error(ret[2]) 31 | end 32 | else 33 | -- timeout 34 | return false 35 | end 36 | end 37 | 38 | skynet.start(function() 39 | local test = service.new("testtimeout", test_service) 40 | skynet.error("1", skynet.now()) 41 | skynet.call(test, "lua") 42 | skynet.error("2", skynet.now()) 43 | skynet.error(timeout_call(50, test, "lua")) 44 | skynet.error("3", skynet.now()) 45 | skynet.error(timeout_call(150, test, "lua")) 46 | skynet.error("4", skynet.now()) 47 | skynet.exit() 48 | end) 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /test/testtimer.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local function timeout(t) 4 | print(t) 5 | end 6 | 7 | local function wakeup(co) 8 | for i=1,5 do 9 | skynet.sleep(50) 10 | skynet.wakeup(co) 11 | end 12 | end 13 | 14 | local function test() 15 | skynet.timeout(10, function() print("test timeout 10") end) 16 | local taskinfo = {} 17 | skynet.task(taskinfo) 18 | for session, info in pairs(taskinfo) do 19 | print("session = ", session, "trace = ", info) 20 | end 21 | for i=1,10 do 22 | print("test sleep",i,skynet.now()) 23 | skynet.sleep(1) 24 | end 25 | end 26 | 27 | skynet.start(function() 28 | skynet.trace_timeout(true) -- trun on trace for timeout, skynet.task will returns more info. 29 | test() 30 | 31 | skynet.fork(wakeup, coroutine.running()) 32 | skynet.timeout(300, function() timeout "Hello World" end) 33 | for i = 1, 10 do 34 | print(i, skynet.now()) 35 | print(skynet.sleep(100)) 36 | end 37 | skynet.exit() 38 | print("Test timer exit") 39 | 40 | end) 41 | -------------------------------------------------------------------------------- /test/testtobeclosed.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local function new_test(name) 4 | return setmetatable({}, { __close = function(...) 5 | skynet.error(...) 6 | end, __name = "closemeta:" .. name}) 7 | end 8 | 9 | local i = 0 10 | skynet.dispatch("lua", function() 11 | i = i + 1 12 | if i==2 then 13 | local c = new_test("dispatch_error") 14 | error("dispatch_error") 15 | else 16 | local c = new_test("dispatch_wait") 17 | skynet.wait() 18 | end 19 | end) 20 | 21 | skynet.start(function() 22 | local c = new_test("skynet.exit") 23 | skynet.fork(function() 24 | local a = new_test("stack_raise_error") 25 | error("raise error") 26 | end) 27 | skynet.fork(function() 28 | local a = new_test("session_id_coroutine_wait") 29 | skynet.wait() 30 | end) 31 | skynet.fork(function() 32 | local a = new_test("session_id_coroutine_call") 33 | skynet.call(skynet.self(), "lua") 34 | end) 35 | skynet.fork(function() 36 | skynet.call(skynet.self(), "lua") 37 | end) 38 | skynet.sleep(100) 39 | skynet.fork(function() 40 | local a = new_test("no_running") 41 | skynet.wait() 42 | end) 43 | skynet.exit() 44 | end) 45 | 46 | --[[ 47 | testtobeclosed 48 | ]] -------------------------------------------------------------------------------- /test/testudp.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local socket = require "skynet.socket" 3 | 4 | local function server() 5 | local host 6 | host = socket.udp(function(str, from) 7 | print("server recv", str, socket.udp_address(from)) 8 | socket.sendto(host, from, "OK " .. str) 9 | end , "127.0.0.1", 8765) -- bind an address 10 | end 11 | 12 | local function client() 13 | local c = socket.udp(function(str, from) 14 | print("client recv", str, socket.udp_address(from)) 15 | end) 16 | socket.udp_connect(c, "127.0.0.1", 8765) 17 | for i=1,20 do 18 | socket.write(c, "hello " .. i) -- write to the address by udp_connect binding 19 | end 20 | end 21 | 22 | skynet.start(function() 23 | skynet.fork(server) 24 | skynet.fork(client) 25 | end) 26 | -------------------------------------------------------------------------------- /test/testvscdebug.lua: -------------------------------------------------------------------------------- 1 | -- vscdebug 2 | local skynet = require "skynet" 3 | 4 | 5 | local mode = ... 6 | 7 | if mode and mode:find("slave") then ----------------------------------------- 8 | 9 | local function dosomething() 10 | local a = 10 11 | local s = "hello" 12 | local t = { 13 | name = "tom", 14 | age = 30, 15 | male = true, 16 | record = {10, true, "tttttt"} 17 | } 18 | local function concat(...) 19 | local t = {...} 20 | for i = 1, #t do 21 | t[i] = tostring(t[i]) 22 | end 23 | local msg = table.concat(t, '') 24 | -- skynet.error(mode, coroutine.running(), msg) 25 | error("error") 26 | return msg 27 | end 28 | local msg = pcall(concat, a, s, t) 29 | local addr = skynet.self() 30 | for i = 1, 10 do 31 | a = a + i 32 | end 33 | end 34 | 35 | skynet.start(function() 36 | skynet.dispatch("lua", function(_,_, ...) 37 | dosomething() 38 | skynet.retpack(...) 39 | end) 40 | end) 41 | 42 | else ------------------------------------------------------------ 43 | 44 | skynet.start(function() 45 | local slaves = {} 46 | for i = 1, 5 do 47 | slaves[i] = skynet.newservice(SERVICE_NAME, "slave"..i) 48 | end 49 | 50 | for i = 1, 5 do 51 | skynet.fork(function() 52 | while true do 53 | local msg = skynet.call(slaves[i], "lua", "master fork call: " .. i) 54 | skynet.sleep(100) 55 | -- skynet.error(msg) 56 | end 57 | end) 58 | end 59 | 60 | local i = 0 61 | while true do 62 | local msg = skynet.call(slaves[(i % #slaves)+1], "lua", "master call: " .. i) 63 | i = i + 1 64 | -- skynet.error(msg) 65 | skynet.sleep(300) 66 | end 67 | end) 68 | 69 | end 70 | -------------------------------------------------------------------------------- /test/time.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | skynet.start(function() 3 | print(skynet.starttime()) 4 | print(skynet.now()) 5 | 6 | skynet.timeout(1, function() 7 | print("in 1", skynet.now()) 8 | end) 9 | skynet.timeout(2, function() 10 | print("in 2", skynet.now()) 11 | end) 12 | skynet.timeout(3, function() 13 | print("in 3", skynet.now()) 14 | end) 15 | 16 | skynet.timeout(4, function() 17 | print("in 4", skynet.now()) 18 | end) 19 | skynet.timeout(100, function() 20 | print("in 100", skynet.now()) 21 | end) 22 | end) 23 | --------------------------------------------------------------------------------