add UDP support, and TCP listen support ipv6 now

This commit is contained in:
Cloud Wu
2014-11-12 23:00:44 +08:00
parent fa78623b1c
commit cfe9506a5a
7 changed files with 773 additions and 98 deletions

View File

@@ -9,6 +9,8 @@
#include <lua.h>
#include <lauxlib.h>
#include <arpa/inet.h>
#include "skynet_socket.h"
#define BACKLOG 32
@@ -372,28 +374,64 @@ lunpack(lua_State *L) {
} else {
lua_pushlightuserdata(L, message->buffer);
}
if (message->type == SKYNET_SOCKET_TYPE_UDP) {
int addrsz = 0;
const char * addrstring = skynet_socket_udp_address(message, &addrsz);
if (addrstring) {
lua_pushlstring(L, addrstring, addrsz);
return 5;
}
}
return 4;
}
static const char *
address_port(lua_State *L, char *tmp, const char * addr, int port_index, int *port) {
const char * host;
if (lua_isnoneornil(L,port_index)) {
host = strchr(addr, '[');
if (host) {
// is ipv6
++host;
const char * sep = strchr(addr,']');
if (sep == NULL) {
luaL_error(L, "Invalid address %s.",addr);
}
memcpy(tmp, host, sep-host);
tmp[sep-host] = '\0';
host = tmp;
sep = strchr(sep + 1, ':');
if (sep == NULL) {
luaL_error(L, "Invalid address %s.",addr);
}
*port = strtoul(sep+1,NULL,10);
} else {
// is ipv4
const char * sep = strchr(addr,':');
if (sep == NULL) {
luaL_error(L, "Invalid address %s.",addr);
}
memcpy(tmp, addr, sep-addr);
tmp[sep-addr] = '\0';
host = tmp;
*port = strtoul(sep+1,NULL,10);
}
} else {
host = addr;
*port = luaL_optinteger(L,port_index, 0);
}
return host;
}
static int
lconnect(lua_State *L) {
size_t sz = 0;
const char * addr = luaL_checklstring(L,1,&sz);
char tmp[sz];
int port;
const char * host;
if (lua_isnoneornil(L,2)) {
const char * sep = strchr(addr,':');
if (sep == NULL) {
return luaL_error(L, "Connect to invalid address %s.",addr);
}
memcpy(tmp, addr, sep-addr);
tmp[sep-addr] = '\0';
host = tmp;
port = strtoul(sep+1,NULL,10);
} else {
host = addr;
port = luaL_checkinteger(L,2);
int port = 0;
const char * host = address_port(L, tmp, addr, 2, &port);
if (port == 0) {
return luaL_error(L, "Invalid port");
}
struct skynet_context * ctx = lua_touserdata(L, lua_upvalueindex(1));
int id = skynet_socket_connect(ctx, host, port);
@@ -426,14 +464,14 @@ llisten(lua_State *L) {
}
static void *
get_buffer(lua_State *L, int *sz) {
get_buffer(lua_State *L, int index, int *sz) {
void *buffer;
if (lua_isuserdata(L,2)) {
buffer = lua_touserdata(L,2);
*sz = luaL_checkinteger(L,3);
if (lua_isuserdata(L,index)) {
buffer = lua_touserdata(L,index);
*sz = luaL_checkinteger(L,index+1);
} else {
size_t len = 0;
const char * str = luaL_checklstring(L, 2, &len);
const char * str = luaL_checklstring(L, index, &len);
buffer = skynet_malloc(len);
memcpy(buffer, str, len);
*sz = (int)len;
@@ -446,7 +484,7 @@ lsend(lua_State *L) {
struct skynet_context * ctx = lua_touserdata(L, lua_upvalueindex(1));
int id = luaL_checkinteger(L, 1);
int sz = 0;
void *buffer = get_buffer(L, &sz);
void *buffer = get_buffer(L, 2, &sz);
int err = skynet_socket_send(ctx, id, buffer, sz);
lua_pushboolean(L, !err);
return 1;
@@ -457,7 +495,7 @@ lsendlow(lua_State *L) {
struct skynet_context * ctx = lua_touserdata(L, lua_upvalueindex(1));
int id = luaL_checkinteger(L, 1);
int sz = 0;
void *buffer = get_buffer(L, &sz);
void *buffer = get_buffer(L, 2, &sz);
skynet_socket_send_lowpriority(ctx, id, buffer, sz);
return 0;
}
@@ -486,6 +524,90 @@ lnodelay(lua_State *L) {
skynet_socket_nodelay(ctx,id);
return 0;
}
/*
int skynet_socket_udp(struct skynet_context *ctx, const char * addr, int port);
int skynet_socket_udp_connect(struct skynet_context *ctx, int id, const char * addr, int port);
int skynet_socket_udp_send(struct skynet_context *ctx, int id, const char * address, const void *buffer, int sz);
const char * skynet_socket_udp_address(struct skynet_context *ctx, struct skynet_socket_message *, int *addrsz);
*/
static int
ludp(lua_State *L) {
struct skynet_context * ctx = lua_touserdata(L, lua_upvalueindex(1));
size_t sz = 0;
const char * addr = lua_tolstring(L,1,&sz);
char tmp[sz];
int port = 0;
const char * host = NULL;
if (addr) {
host = address_port(L, tmp, addr, 2, &port);
}
int id = skynet_socket_udp(ctx, host, port);
if (id < 0) {
return luaL_error(L, "udp init failed");
}
lua_pushinteger(L, id);
return 1;
}
static int
ludp_connect(lua_State *L) {
struct skynet_context * ctx = lua_touserdata(L, lua_upvalueindex(1));
int id = luaL_checkinteger(L, 1);
size_t sz = 0;
const char * addr = luaL_checklstring(L,2,&sz);
char tmp[sz];
int port = 0;
const char * host = NULL;
if (addr) {
host = address_port(L, tmp, addr, 3, &port);
}
if (skynet_socket_udp_connect(ctx, id, host, port)) {
return luaL_error(L, "udp connect failed");
}
return 0;
}
static int
ludp_send(lua_State *L) {
struct skynet_context * ctx = lua_touserdata(L, lua_upvalueindex(1));
int id = luaL_checkinteger(L, 1);
const char * address = luaL_checkstring(L, 2);
int sz = 0;
void *buffer = get_buffer(L, 3, &sz);
int err = skynet_socket_udp_send(ctx, id, address, buffer, sz);
lua_pushboolean(L, !err);
return 1;
}
static int
ludp_address(lua_State *L) {
size_t sz = 0;
const uint8_t * addr = (const uint8_t *)luaL_checklstring(L, 1, &sz);
int port = addr[1] * 256 + addr[2];
const void * src = addr+3;
char tmp[256];
int family;
if (sz == 1+2+4) {
family = AF_INET;
} else {
if (sz != 1+2+16) {
return luaL_error(L, "Invalid udp address");
}
family = AF_INET6;
}
if (inet_ntop(family, src, tmp, sizeof(tmp)) == NULL) {
return luaL_error(L, "Invalid udp address");
}
lua_pushstring(L, tmp);
lua_pushinteger(L, port);
return 2;
}
int
luaopen_socketdriver(lua_State *L) {
@@ -514,6 +636,10 @@ luaopen_socketdriver(lua_State *L) {
{ "bind", lbind },
{ "start", lstart },
{ "nodelay", lnodelay },
{ "udp", ludp },
{ "udp_connect", ludp_connect },
{ "udp_send", ludp_send },
{ "udp_address", ludp_address },
{ NULL, NULL },
};
lua_getfield(L, LUA_REGISTRYINDEX, "skynet_context");