Skip to content

Commit 088e77c

Browse files
committed
完善 socket 库
1 parent 0d53e2e commit 088e77c

4 files changed

Lines changed: 147 additions & 6 deletions

File tree

src/extensions/ext.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,11 @@
4646
symbol.v.fun->ret.type = rettype;
4747

4848
#define LGX_FUNCTION_ARG(pos, argtype) \
49+
assert(pos < symbol.v.fun->args_num); \
4950
symbol.v.fun->args[pos].type = argtype;
5051

5152
#define LGX_FUNCTION_ARG_OPTIONAL(pos, argtype, argvalue) \
53+
assert(pos < symbol.v.fun->args_num); \
5254
symbol.v.fun->args[pos].type = argtype; \
5355
symbol.v.fun->args[pos].v.l = (long long)(argvalue); \
5456
symbol.v.fun->args[pos].u.c.init = 1;
@@ -104,17 +106,20 @@
104106
} while (0);
105107

106108
#define LGX_METHOD_ARG(pos, argtype) \
109+
assert(pos < symbol.v.v.fun->args_num); \
107110
symbol.v.v.fun->args[pos].type = argtype;
108111

109112
#define LGX_METHOD_ARG_OBJECT(pos, objname) \
110113
do { \
114+
assert(pos < symbol.v.v.fun->args_num); \
111115
lgx_val_t *objval = lgx_ext_get_symbol(hash, #objname); \
112116
assert(objval && objval->type == T_OBJECT); \
113117
symbol.v.v.fun->args[pos].type = T_OBJECT; \
114118
symbol.v.v.fun->args[pos].v.obj = objval->v.obj; \
115119
} while (0);
116120

117121
#define LGX_METHOD_ARG_OPTIONAL(pos, argtype, argvalue) \
122+
assert(pos < symbol.v.v.fun->args_num); \
118123
symbol.v.v.fun->args[pos].type = argtype; \
119124
symbol.v.v.fun->args[pos].v.l = (long long)(argvalue); \
120125
symbol.v.v.fun->args[pos].u.c.init = 1;

src/extensions/std_net_socket.c

Lines changed: 131 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,12 +335,138 @@ static wbt_status on_timeout(wbt_timer_t *timer) {
335335
return WBT_OK;
336336
}
337337

338+
static wbt_status try_connect(wbt_socket_t fd, char *ip, int port) {
339+
struct sockaddr_in addr;
340+
addr.sin_family = AF_INET;
341+
addr.sin_port = htons(port);
342+
#ifdef WIN32
343+
addr.sin_addr.S_un.S_addr = inet_addr(ip);
344+
#else
345+
addr.sin_addr.s_addr = inet_addr(ip);
346+
#endif
347+
memset(addr.sin_zero, 0x00, 8);
348+
349+
int ret = connect(fd, (struct sockaddr*)&addr, sizeof(addr));
350+
if (ret < 0) {
351+
wbt_err_t err = wbt_socket_errno;
352+
353+
if (err != WBT_EINPROGRESS
354+
#ifdef WIN32
355+
/* Winsock returns WSAEWOULDBLOCK (WBT_EAGAIN) */
356+
&& err != WBT_EAGAIN
357+
#endif
358+
)
359+
{
360+
if (err == WBT_ECONNREFUSED
361+
#ifndef WIN32 // TODO 判断 LINUX 平台
362+
/*
363+
* Linux returns EAGAIN instead of ECONNREFUSED
364+
* for unix sockets if listen queue is full
365+
*/
366+
|| err == WBT_EAGAIN
367+
#endif
368+
|| err == WBT_ECONNRESET
369+
|| err == WBT_ENETDOWN
370+
|| err == WBT_ENETUNREACH
371+
|| err == WBT_EHOSTDOWN
372+
|| err == WBT_EHOSTUNREACH)
373+
{
374+
// 普通错误
375+
return WBT_ERROR;
376+
} else {
377+
// 未知错误
378+
return WBT_ERROR;
379+
}
380+
} else {
381+
return WBT_AGAIN;
382+
}
383+
}
384+
385+
return WBT_OK;
386+
}
387+
388+
static wbt_status on_connect(wbt_event_t *ev) {
389+
lgx_socket_t *sock = (lgx_socket_t *)ev->ctx;
390+
391+
wbt_debug("socket:on_connect %d", ev->fd);
392+
393+
wbt_event_del(sock->co->vm->events, ev);
394+
395+
lgx_co_resume(sock->co->vm, sock->co);
396+
397+
sock->co = NULL;
398+
399+
return WBT_OK;
400+
}
401+
338402
LGX_METHOD(Socket, connect) {
339403
LGX_METHOD_ARGS_INIT();
340404
LGX_METHOD_ARGS_THIS(obj);
405+
LGX_METHOD_ARGS_GET(ip, 0, T_STRING);
406+
LGX_METHOD_ARGS_GET(port, 1, T_LONG);
341407

342-
LGX_RETURN_TRUE();
343-
return 0;
408+
if (ip->v.str->length > 32) {
409+
lgx_vm_throw_s(vm, "invalid param `ip`");
410+
return 1;
411+
}
412+
413+
if (port->v.l <= 0 || port->v.l >= 65535) {
414+
lgx_vm_throw_s(vm, "invalid param `port`");
415+
return 1;
416+
}
417+
418+
lgx_val_t *res = lgx_obj_get_s(obj->v.obj, "ctx");
419+
if (!res || res->type != T_RESOURCE) {
420+
lgx_vm_throw_s(vm, "invalid property `ctx`");
421+
return 1;
422+
}
423+
424+
lgx_socket_t *sock = (lgx_socket_t *)res->v.res->buf;
425+
if (sock->fd < 0) {
426+
lgx_vm_throw_s(vm, "socket alreay closed");
427+
return 1;
428+
}
429+
430+
// 不能在多个协程中并发执行
431+
if (sock->co) {
432+
lgx_vm_throw_s(vm, "concurrent connect");
433+
return 1;
434+
}
435+
sock->co = vm->co_running;
436+
437+
char ip_str[32];
438+
memcpy(ip_str, ip->v.str->buffer, ip->v.str->length);
439+
ip_str[ip->v.str->length] = '\0';
440+
441+
wbt_status ret = try_connect(sock->fd, ip_str, port->v.l);
442+
443+
if (ret == WBT_ERROR) {
444+
sock->co = NULL;
445+
lgx_vm_throw_s(vm, "connect faild");
446+
return 1;
447+
} else if (ret == WBT_OK) {
448+
sock->co = NULL;
449+
LGX_RETURN_TRUE();
450+
return 0;
451+
} else { // ret == WBT_AGAIN
452+
// 添加事件
453+
wbt_event_t *p_ev, tmp_ev;
454+
tmp_ev.timer.on_timeout = on_timeout;
455+
tmp_ev.timer.timeout = wbt_cur_mtime + 15 * 1000;
456+
tmp_ev.on_recv = NULL;
457+
tmp_ev.on_send = on_connect;
458+
tmp_ev.events = WBT_EV_WRITE | WBT_EV_ET;
459+
tmp_ev.fd = sock->fd;
460+
461+
if((p_ev = wbt_event_add(vm->events, &tmp_ev)) == NULL) {
462+
lgx_vm_throw_s(vm, "add event faild");
463+
return 1;
464+
}
465+
466+
p_ev->ctx = sock;
467+
lgx_co_suspend(vm);
468+
return 0;
469+
}
344470
}
345471

346472
static wbt_status on_send(wbt_event_t *ev);
@@ -610,8 +736,10 @@ LGX_CLASS(Socket) {
610736
LGX_METHOD_ACCESS(P_PUBLIC)
611737
LGX_METHOD_END
612738

613-
LGX_METHOD_BEGIN(Socket, connect, 0)
739+
LGX_METHOD_BEGIN(Socket, connect, 2)
614740
LGX_METHOD_RET(T_BOOL)
741+
LGX_METHOD_ARG(0, T_STRING)
742+
LGX_METHOD_ARG(1, T_LONG)
615743
LGX_METHOD_ACCESS(P_PUBLIC)
616744
LGX_METHOD_END
617745

src/interpreter/vm.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,13 @@ int lgx_vm_cleanup(lgx_vm_t *vm) {
9393
// 释放主协程堆栈
9494
assert(vm->co_main);
9595
lgx_co_t *co = vm->co_main;
96-
assert(co->stack.buf[0].type == T_FUNCTION);
97-
unsigned size = co->stack.buf[0].v.fun->stack_size;
96+
unsigned base = co->stack.base;
97+
assert(co->stack.buf[base].type == T_FUNCTION);
98+
unsigned size = base + co->stack.buf[base].v.fun->stack_size;
9899
int n;
99100
for (n = 0; n < size; n ++) {
100101
lgx_gc_ref_del(&co->stack.buf[n]);
101-
R(n).type = T_UNDEFINED;
102+
co->stack.buf[n].type = T_UNDEFINED;
102103
}
103104

104105
// 释放主协程

test/socket_client.x

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Socket socket = new Socket;
2+
socket->connect("127.0.0.1", 8888);
3+
4+
socket->send("hello");
5+
echo socket->recv(1024);
6+
7+
socket->close();

0 commit comments

Comments
 (0)