mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-22 02:53:09 +00:00
206 lines
4.4 KiB
C
206 lines
4.4 KiB
C
#include <lua.h>
|
|
#include <lauxlib.h>
|
|
#include <string.h>
|
|
|
|
#include "skynet.h"
|
|
|
|
/*
|
|
uint32_t/string addr
|
|
uint32_t/session session
|
|
lightuserdata msg
|
|
uint32_t sz
|
|
|
|
return
|
|
string request
|
|
uint32_t next_session
|
|
*/
|
|
|
|
#define TEMP_LENGTH 0x10002
|
|
|
|
static void
|
|
fill_uint32(uint8_t * buf, uint32_t n) {
|
|
buf[0] = n & 0xff;
|
|
buf[1] = (n >> 8) & 0xff;
|
|
buf[2] = (n >> 16) & 0xff;
|
|
buf[3] = (n >> 24) & 0xff;
|
|
}
|
|
|
|
static void
|
|
fill_header(lua_State *L, uint8_t *buf, int sz, void *msg) {
|
|
if (sz >= 0x10000) {
|
|
skynet_free(msg);
|
|
luaL_error(L, "request message is too long %d", sz);
|
|
}
|
|
buf[0] = (sz >> 8) & 0xff;
|
|
buf[1] = sz & 0xff;
|
|
}
|
|
|
|
static void
|
|
packreq_number(lua_State *L, int session, void * msg, size_t sz) {
|
|
uint32_t addr = lua_tounsigned(L,1);
|
|
uint8_t buf[TEMP_LENGTH];
|
|
fill_header(L, buf, sz+9, msg);
|
|
buf[2] = 0;
|
|
fill_uint32(buf+3, addr);
|
|
fill_uint32(buf+7, (uint32_t)session);
|
|
memcpy(buf+11,msg,sz);
|
|
|
|
lua_pushlstring(L, (const char *)buf, sz+11);
|
|
}
|
|
|
|
static void
|
|
packreq_string(lua_State *L, int session, void * msg, size_t sz) {
|
|
size_t namelen = 0;
|
|
const char *name = lua_tolstring(L, 1, &namelen);
|
|
if (name == NULL || namelen < 1 || namelen > 255) {
|
|
skynet_free(msg);
|
|
luaL_error(L, "name is too long %s", name);
|
|
}
|
|
|
|
uint8_t buf[TEMP_LENGTH];
|
|
fill_header(L, buf, sz+5+namelen, msg);
|
|
buf[2] = (uint8_t)namelen;
|
|
memcpy(buf+3, name, namelen);
|
|
fill_uint32(buf+3+namelen, (uint32_t)session);
|
|
memcpy(buf+7+namelen,msg,sz);
|
|
|
|
lua_pushlstring(L, (const char *)buf, sz+7+namelen);
|
|
}
|
|
|
|
static int
|
|
lpackrequest(lua_State *L) {
|
|
void *msg = lua_touserdata(L,3);
|
|
if (msg == NULL) {
|
|
return luaL_error(L, "Invalid request message");
|
|
}
|
|
size_t sz = luaL_checkunsigned(L,4);
|
|
int session = luaL_checkinteger(L,2);
|
|
if (session <= 0) {
|
|
return luaL_error(L, "Invalid request session %d", session);
|
|
}
|
|
int addr_type = lua_type(L,1);
|
|
if (addr_type == LUA_TNUMBER) {
|
|
packreq_number(L, session, msg, sz);
|
|
} else {
|
|
packreq_string(L, session, msg, sz);
|
|
}
|
|
if (++session < 0) {
|
|
session = 1;
|
|
}
|
|
skynet_free(msg);
|
|
lua_pushinteger(L, session);
|
|
return 2;
|
|
}
|
|
|
|
/*
|
|
string packed message
|
|
return
|
|
uint32_t or string addr
|
|
int session
|
|
string msg
|
|
*/
|
|
|
|
static inline uint32_t
|
|
unpack_uint32(const uint8_t * buf) {
|
|
return buf[0] | buf[1]<<8 | buf[2]<<16 | buf[3]<<24;
|
|
}
|
|
|
|
static int
|
|
unpackreq_number(lua_State *L, const uint8_t * buf, size_t sz) {
|
|
if (sz < 9) {
|
|
return luaL_error(L, "Invalid cluster message");
|
|
}
|
|
uint32_t address = unpack_uint32(buf+1);
|
|
uint32_t session = unpack_uint32(buf+5);
|
|
lua_pushunsigned(L, address);
|
|
lua_pushunsigned(L, session);
|
|
lua_pushlstring(L, (const char *)buf+9, sz-9);
|
|
|
|
return 3;
|
|
}
|
|
|
|
static int
|
|
unpackreq_string(lua_State *L, const uint8_t * buf, size_t sz) {
|
|
size_t namesz = buf[0];
|
|
if (sz < namesz + 5) {
|
|
return luaL_error(L, "Invalid cluster message");
|
|
}
|
|
lua_pushlstring(L, (const char *)buf+1, namesz);
|
|
uint32_t session = unpack_uint32(buf + namesz + 1);
|
|
lua_pushunsigned(L, session);
|
|
lua_pushlstring(L, (const char *)buf+1+namesz+4, sz - namesz - 5);
|
|
|
|
return 3;
|
|
}
|
|
|
|
static int
|
|
lunpackrequest(lua_State *L) {
|
|
size_t sz;
|
|
const char *msg = luaL_checklstring(L,1,&sz);
|
|
if (msg[0] == 0) {
|
|
return unpackreq_number(L, (const uint8_t *)msg, sz);
|
|
} else {
|
|
return unpackreq_string(L, (const uint8_t *)msg, sz);
|
|
}
|
|
}
|
|
|
|
/*
|
|
int session
|
|
lightuserdata msg
|
|
int sz
|
|
return string response
|
|
*/
|
|
static int
|
|
lpackresponse(lua_State *L) {
|
|
uint32_t session = luaL_checkunsigned(L,1);
|
|
// clusterd.lua:command.socket call lpackresponse,
|
|
// and the msg/sz is return by skynet.rawcall , so don't free(msg)
|
|
void * msg = lua_touserdata(L,2);
|
|
size_t sz = luaL_checkunsigned(L, 3);
|
|
|
|
uint8_t buf[TEMP_LENGTH];
|
|
fill_header(L, buf, sz+4, msg);
|
|
fill_uint32(buf+2, session);
|
|
memcpy(buf+6,msg,sz);
|
|
|
|
lua_pushlstring(L, (const char *)buf, sz+6);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
string packed response
|
|
return integer session
|
|
boolean ok
|
|
string msg
|
|
*/
|
|
static int
|
|
lunpackresponse(lua_State *L) {
|
|
size_t sz;
|
|
const char * buf = luaL_checklstring(L, 1, &sz);
|
|
if (sz < 4) {
|
|
return 0;
|
|
}
|
|
uint32_t session = unpack_uint32((const uint8_t *)buf);
|
|
lua_pushunsigned(L, session);
|
|
lua_pushboolean(L, 1);
|
|
lua_pushlstring(L, buf+4, sz-4);
|
|
|
|
return 3;
|
|
}
|
|
|
|
int
|
|
luaopen_cluster_c(lua_State *L) {
|
|
luaL_Reg l[] = {
|
|
{ "packrequest", lpackrequest },
|
|
{ "unpackrequest", lunpackrequest },
|
|
{ "packresponse", lpackresponse },
|
|
{ "unpackresponse", lunpackresponse },
|
|
{ NULL, NULL },
|
|
};
|
|
luaL_checkversion(L);
|
|
luaL_newlib(L,l);
|
|
|
|
return 1;
|
|
}
|