int snlua_init(struct snlua *l, struct server_context *ctx, const char * args) { int sz = strlen(args); char * tmp = server_malloc(sz); memcpy(tmp, args, sz); server_callback(ctx, l , _launch);//设置回调函数 const char * self = server_cmd_command(ctx, "REG", NULL); uint32_t handle_id = strtoul(self+1, NULL, 16); server_send(ctx, 0, handle_id, PTYPE_TAG_DONTCOPY, 0, tmp, sz);//初始化完毕发送一条消息给自身,然后通过callback 回调到 _launch return 0; }
static int _launch(struct server_context * context, void *ud, int type, int session, uint32_t source , const void * msg, size_t sz) { assert(type == 0 && session == 0); struct snlua *l = ud; server_callback(context, NULL, NULL);//消除callback, snlua 的回调函数只用于初始化 lua 服务, lua服务调用中层skynet.start 时会重新设置lua 服务的回调函数 int err = _init(l, context, msg, sz); if (err) { server_cmd_command(context, "EXIT", NULL); } return 0; }
//设置消息处理回调函数 static int _callback(lua_State *L) { struct server_context * context = lua_touserdata(L, lua_upvalueindex(1));//lua_upvalueindex 返回当前运行的函数的第i个上值的伪索引 int forward = lua_toboolean(L, 2); luaL_checktype(L,1,LUA_TFUNCTION); lua_settop(L,1); lua_rawsetp(L, LUA_REGISTRYINDEX, _cb); /* 获取lua 创建时 main thread 的 L http://blog.codingnow.com/2012/07/lua_c_callback.html */ lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); lua_State *gL = lua_tothread(L,-1); if (forward) { server_callback(context, gL, forward_cb); } else { server_callback(context, gL, _cb); } return 0; }
int main(int argc, char **argv) { char *url = NULL; char *address = "queue"; char *mechanism = "ANONYMOUS"; int count = 1; bool quiet = false; int high = 100; int low = 50; int size = 32; int opt; while ((opt = getopt(argc, argv, "c:a:m:n:s:u:l:qhVXY")) != -1) { switch (opt) { case 'c': if (url) pn_fatal("multiple connect urls not allowed\n"); url = optarg; break; case 'a': address = optarg; break; case 'm': mechanism = optarg; break; case 'n': count = atoi(optarg); break; case 's': size = atoi(optarg); break; case 'u': high = atoi(optarg); break; case 'l': low = atoi(optarg); break; case 'q': quiet = true; break; case 'V': printf("proton version %i.%i\n", PN_VERSION_MAJOR, PN_VERSION_MINOR); exit(EXIT_SUCCESS); case 'X': value(argc, argv); exit(EXIT_SUCCESS); case 'Y': buffer(argc, argv); exit(EXIT_SUCCESS); case 'h': printf("Usage: %s [-h] [-c [user[:password]@]host[:port]] [-a <address>] [-m <sasl-mech>]\n", argv[0]); printf("\n"); printf(" -c The connect url.\n"); printf(" -a The AMQP address.\n"); printf(" -m The SASL mechanism.\n"); printf(" -n The number of messages.\n"); printf(" -s Message size.\n"); printf(" -u Upper flow threshold.\n"); printf(" -l Lower flow threshold.\n"); printf(" -q Supress printouts.\n"); printf(" -h Print this help.\n"); exit(EXIT_SUCCESS); default: /* '?' */ pn_fatal("Usage: %s -h\n", argv[0]); } } char *user = NULL; char *pass = NULL; char *host = "0.0.0.0"; char *port = "5672"; parse_url(url, &user, &pass, &host, &port); pn_driver_t *drv = pn_driver(); if (url) { struct client_context ctx = {false, false, count, count, drv, quiet, size, high, low}; ctx.username = user; ctx.password = pass; ctx.mechanism = mechanism; ctx.hostname = host; ctx.address = address; pn_connector_t *ctor = pn_connector(drv, host, port, &ctx); if (!ctor) pn_fatal("connector failed\n"); pn_connector_set_connection(ctor, pn_connection()); while (!ctx.done) { pn_driver_wait(drv, -1); pn_connector_t *c; while ((c = pn_driver_connector(drv))) { pn_connector_process(c); client_callback(c); if (pn_connector_closed(c)) { pn_connection_free(pn_connector_connection(c)); pn_connector_free(c); } else { pn_connector_process(c); } } } } else { struct server_context ctx = {0, quiet, size}; if (!pn_listener(drv, host, port, &ctx)) pn_fatal("listener failed\n"); while (true) { pn_driver_wait(drv, -1); pn_listener_t *l; pn_connector_t *c; while ((l = pn_driver_listener(drv))) { c = pn_listener_accept(l); pn_connector_set_context(c, &ctx); } while ((c = pn_driver_connector(drv))) { pn_connector_process(c); server_callback(c); if (pn_connector_closed(c)) { pn_connection_free(pn_connector_connection(c)); pn_connector_free(c); } else { pn_connector_process(c); } } } } pn_driver_free(drv); return 0; }