🚀 finish socket library:
socket.socket() socket.closesocket() socket.shutdown() socket.bind() socket.listen() socket.connect() socket.accept() socket.send() socket.sendto() socket.recv() socket.recvfrom() socket.errno()
This commit is contained in:
parent
53b85cd459
commit
12d7dde42d
1
makefile
1
makefile
|
@ -23,6 +23,7 @@ test:nasal
|
|||
@ ./nasal -op -t -d test/fib.nas
|
||||
@ ./nasal -op -e test/filesystem.nas
|
||||
@ ./nasal -op -e -d test/hexdump.nas
|
||||
@ ./nasal -op -c test/httptest.nas
|
||||
@ ./nasal -op -e test/json.nas
|
||||
@ ./nasal -op -e test/leetcode1319.nas
|
||||
@ ./nasal -op -e -d test/lexer.nas
|
||||
|
|
|
@ -2,6 +2,16 @@ var socket=func(){
|
|||
var lib=dylib.dlopen("./module/libnasock"~(os.platform()=="windows"?".dll":".so"));
|
||||
var sock=dylib.dlsym(lib,"nas_socket");
|
||||
var closesocket=dylib.dlsym(lib,"nas_closesocket");
|
||||
var shutdown=dylib.dlsym(lib,"nas_shutdown");
|
||||
var bind=dylib.dlsym(lib,"nas_bind");
|
||||
var listen=dylib.dlsym(lib,"nas_listen");
|
||||
var connect=dylib.dlsym(lib,"nas_connect");
|
||||
var accept=dylib.dlsym(lib,"nas_accept");
|
||||
var send=dylib.dlsym(lib,"nas_send");
|
||||
var sendto=dylib.dlsym(lib,"nas_sendto");
|
||||
var recv=dylib.dlsym(lib,"nas_recv");
|
||||
var recvfrom=dylib.dlsym(lib,"nas_recvfrom");
|
||||
var errno=dylib.dlsym(lib,"nas_errno");
|
||||
var call=dylib.dlcall;
|
||||
return {
|
||||
AF_UNSPEC:0,AF_UNIX:1,AF_INET:2,AF_IMPLINK:3,
|
||||
|
@ -27,11 +37,49 @@ var socket=func(){
|
|||
IPPORT_EFSSERVER:520,IPPORT_BIFFUDP:512,IPPORT_WHOSERVER:513,IPPORT_ROUTESERVER:520,
|
||||
IPPORT_RESERVED:1024,
|
||||
|
||||
SHUT_RD :0x00,
|
||||
SHUT_WR :0x01,
|
||||
SHUT_RDWR:0x02,
|
||||
|
||||
MSG_OOB:0x1,
|
||||
MSG_PEEK:0x2,
|
||||
MSG_DONTROUTE:0x4,
|
||||
|
||||
socket:func(af,type,proto){
|
||||
return call(sock,af,type,proto);
|
||||
},
|
||||
closesocket:func(sd){
|
||||
return call(closesocket,sd);
|
||||
},
|
||||
shutdown: func(sd,how){
|
||||
return call(shutdown,sd,how);
|
||||
},
|
||||
bind: func(sd,ip,port){
|
||||
return call(bind,sd,ip,port);
|
||||
},
|
||||
listen: func(sd,backlog){
|
||||
return call(listen,sd,backlog);
|
||||
},
|
||||
connect: func(sd,hostname,port){
|
||||
return call(connect,sd,hostname,port);
|
||||
},
|
||||
accept: func(sd){
|
||||
return call(accept,sd);
|
||||
},
|
||||
send: func(sd,buff,flags=0){
|
||||
return call(send,sd,buff,flags);
|
||||
},
|
||||
sendto: func(sd,hostname,port,buff,flags=0){
|
||||
return call(sendto,sd,hostname,port,buff,flags);
|
||||
},
|
||||
recv: func(sd,len,flags=0){
|
||||
return call(recv,sd,len,flags);
|
||||
},
|
||||
recvfrom: func(sd,len,flags=0){
|
||||
return call(recvfrom,sd,len,flags);
|
||||
},
|
||||
errno: func(){
|
||||
return call(errno);
|
||||
}
|
||||
};
|
||||
}();
|
|
@ -25,7 +25,7 @@ libnasock.dll: nasocket.cpp
|
|||
|
||||
clean:
|
||||
rm *.o *.so *.dll *.dylib
|
||||
all: libfib.so libkey.so
|
||||
all: libfib.so libkey.so libnasock.so
|
||||
@ echo "build done"
|
||||
mingw-all: libfib.dll libkey.dll
|
||||
mingw-all: libfib.dll libkey.dll libnasock.dll
|
||||
@ echo "build done"
|
|
@ -1,4 +1,5 @@
|
|||
#include "../nasal.h"
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock.h>
|
||||
|
@ -18,12 +19,13 @@ public:
|
|||
|
||||
static WSAmanager win;
|
||||
#else
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
extern "C" nasal_ref nas_socket(std::vector<nasal_ref>& args,nasal_gc& gc){
|
||||
if(args.size()!=3)
|
||||
return builtin_err("socket","invalid arguments");
|
||||
if(args[0].type!=vm_num || args[1].type!=vm_num || args[2].type!=vm_num)
|
||||
return builtin_err("socket","\"af\", \"type\", \"protocol\" should be number");
|
||||
int sd=socket(args[0].num(),args[1].num(),args[2].num());
|
||||
|
@ -31,8 +33,6 @@ extern "C" nasal_ref nas_socket(std::vector<nasal_ref>& args,nasal_gc& gc){
|
|||
}
|
||||
|
||||
extern "C" nasal_ref nas_closesocket(std::vector<nasal_ref>& args,nasal_gc& gc){
|
||||
if(args.size()!=1)
|
||||
return builtin_err("closesocket","invalid arguments");
|
||||
if(args[0].type!=vm_num)
|
||||
return builtin_err("closesocket","\"\" should be number");
|
||||
#ifdef _WIN32
|
||||
|
@ -41,3 +41,161 @@ extern "C" nasal_ref nas_closesocket(std::vector<nasal_ref>& args,nasal_gc& gc){
|
|||
return {vm_num,(double)close(args[0].num())};
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" nasal_ref nas_shutdown(std::vector<nasal_ref>& args,nasal_gc& gc){
|
||||
//shutdown();
|
||||
if(args[0].type!=vm_num)
|
||||
return builtin_err("shutdown","\"sd\" must be a number");
|
||||
if(args[1].type!=vm_num)
|
||||
return builtin_err("shutdown","\"how\" must be a number");
|
||||
return {vm_num,(double)shutdown(args[0].num(),args[1].num())};
|
||||
}
|
||||
|
||||
extern "C" nasal_ref nas_bind(std::vector<nasal_ref>& args,nasal_gc& gc){
|
||||
if(args[0].type!=vm_num)
|
||||
return builtin_err("bind","\"sd\" muse be a number");
|
||||
if(args[1].type!=vm_str)
|
||||
return builtin_err("bind","\"ip\" should be a string including an ip with correct format");
|
||||
if(args[2].type!=vm_num)
|
||||
return builtin_err("bind","\"port\" must be a number");
|
||||
sockaddr_in server;
|
||||
memset(&server,0,sizeof(sockaddr_in));
|
||||
server.sin_family=AF_INET;
|
||||
server.sin_addr.s_addr=inet_addr(args[1].str().c_str());
|
||||
server.sin_port=htons(args[2].num());
|
||||
return {vm_num,(double)bind(args[0].num(),(sockaddr*)&server,sizeof(server))};
|
||||
}
|
||||
|
||||
extern "C" nasal_ref nas_listen(std::vector<nasal_ref>& args,nasal_gc& gc){
|
||||
if(args[0].type!=vm_num)
|
||||
return builtin_err("listen","\"sd\" must be a number");
|
||||
if(args[1].type!=vm_num)
|
||||
return builtin_err("listen","\"backlog\" must be a number");
|
||||
return{vm_num,(double)listen(args[0].num(),args[1].num())};
|
||||
}
|
||||
|
||||
extern "C" nasal_ref nas_connect(std::vector<nasal_ref>& args,nasal_gc& gc){
|
||||
if(args[0].type!=vm_num)
|
||||
return builtin_err("connect","\"sd\" must be a number");
|
||||
if(args[1].type!=vm_str)
|
||||
return builtin_err("connect","\"hostname\" must be a string");
|
||||
if(args[2].type!=vm_num)
|
||||
return builtin_err("connect","\"port\" must be a number");
|
||||
sockaddr_in addr;
|
||||
memset(&addr,0,sizeof(sockaddr_in));
|
||||
addr.sin_family=AF_INET;
|
||||
addr.sin_port=htons(args[2].num());
|
||||
hostent* entry=gethostbyname(args[1].str().c_str());
|
||||
memcpy(&addr.sin_addr,entry->h_addr,entry->h_length);
|
||||
return {vm_num,(double)connect(args[0].num(),(sockaddr*)&addr,sizeof(sockaddr_in))};
|
||||
}
|
||||
|
||||
extern "C" nasal_ref nas_accept(std::vector<nasal_ref>& args,nasal_gc& gc){
|
||||
if(args[0].type!=vm_num)
|
||||
return builtin_err("accept","\"sd\" must be a number");
|
||||
sockaddr_in client;
|
||||
int socklen=sizeof(sockaddr_in);
|
||||
#ifdef _WIN32
|
||||
int client_sd=accept(args[0].num(),(sockaddr*)&client,&socklen);
|
||||
#else
|
||||
int client_sd=accept(args[0].num(),(sockaddr*)&client,(socklen_t*)&socklen);
|
||||
#endif
|
||||
if(gc.top+1>=gc.canary)
|
||||
return builtin_err("accept","expand temporary space error:stackoverflow");
|
||||
(++gc.top)[0]=gc.alloc(vm_hash);
|
||||
auto& hash=gc.top[0].hash().elems;
|
||||
hash["sd"]={vm_num,(double)client_sd};
|
||||
hash["ip"]=gc.alloc(vm_str);
|
||||
hash["ip"].str()=inet_ntoa(client.sin_addr);
|
||||
--gc.top;
|
||||
return gc.top[1];
|
||||
}
|
||||
|
||||
extern "C" nasal_ref nas_send(std::vector<nasal_ref>& args,nasal_gc& gc){
|
||||
if(args[0].type!=vm_num)
|
||||
return builtin_err("send","\"sd\" must be a number");
|
||||
if(args[1].type!=vm_str)
|
||||
return builtin_err("send","\"buff\" must be a string");
|
||||
if(args[2].type!=vm_num)
|
||||
return builtin_err("send","\"flags\" muse be a number");
|
||||
return {vm_num,(double)send(args[0].num(),args[1].str().c_str(),args[1].str().length(),args[2].num())};
|
||||
}
|
||||
|
||||
extern "C" nasal_ref nas_sendto(std::vector<nasal_ref>& args,nasal_gc& gc){
|
||||
if(args[0].type!=vm_num)
|
||||
return builtin_err("sendto","\"sd\" must be a number");
|
||||
if(args[1].type!=vm_str)
|
||||
return builtin_err("sendto","\"hostname\" must be a string");
|
||||
if(args[2].type!=vm_num)
|
||||
return builtin_err("sendto","\"port\" must be a number");
|
||||
if(args[3].type!=vm_str)
|
||||
return builtin_err("sendto","\"buff\" must be a string");
|
||||
if(args[4].type!=vm_num)
|
||||
return builtin_err("sendto","\"flags\" must be a number");
|
||||
sockaddr_in addr;
|
||||
memset(&addr,0,sizeof(sockaddr_in));
|
||||
addr.sin_family=AF_INET;
|
||||
addr.sin_port=htons(args[2].num());
|
||||
hostent* entry=gethostbyname(args[1].str().c_str());
|
||||
memcpy(&addr.sin_addr,entry->h_addr,entry->h_length);
|
||||
return {vm_num,(double)sendto(args[0].num(),args[3].str().c_str(),args[3].str().length(),args[4].num(),(sockaddr*)&addr,sizeof(sockaddr_in))};
|
||||
}
|
||||
|
||||
extern "C" nasal_ref nas_recv(std::vector<nasal_ref>& args,nasal_gc& gc){
|
||||
if(args[0].type!=vm_num)
|
||||
return builtin_err("recv","\"sd\" must be a number");
|
||||
if(args[1].type!=vm_num)
|
||||
return builtin_err("recv","\"len\" must be a number");
|
||||
if(args[1].num()<=0 || args[1].num()>16*1024*1024)
|
||||
return builtin_err("recv","\"len\" out of range");
|
||||
if(args[2].type!=vm_num)
|
||||
return builtin_err("recv","\"flags\" muse be a number");
|
||||
if(gc.top+1>=gc.canary)
|
||||
return builtin_err("recv","expand temporary space error:stackoverflow");
|
||||
(++gc.top)[0]=gc.alloc(vm_hash);
|
||||
auto& hash=gc.top[0].hash().elems;
|
||||
hash["str"]=gc.alloc(vm_str);
|
||||
char* buf=new char[(int)args[1].num()];
|
||||
hash["size"]={vm_num,(double)recv(args[0].num(),buf,args[1].num(),args[2].num())};
|
||||
hash["str"].str()=buf;
|
||||
delete[] buf;
|
||||
--gc.top;
|
||||
return gc.top[1];
|
||||
}
|
||||
|
||||
extern "C" nasal_ref nas_recvfrom(std::vector<nasal_ref>& args,nasal_gc& gc){
|
||||
if(args[0].type!=vm_num)
|
||||
return builtin_err("recvfrom","\"sd\" must be a number");
|
||||
if(args[1].type!=vm_num)
|
||||
return builtin_err("recvfrom","\"len\" must be a number");
|
||||
if(args[1].num()<=0 || args[1].num()>16*1024*1024)
|
||||
return builtin_err("recvfrom","\"len\" out of range");
|
||||
if(args[2].type!=vm_num)
|
||||
return builtin_err("recvfrom","\"flags\" muse be a number");
|
||||
if(gc.top+1>=gc.canary)
|
||||
return builtin_err("recvfrom","expand temporary space error:stackoverflow");
|
||||
sockaddr_in addr;
|
||||
int socklen=sizeof(sockaddr_in);
|
||||
(++gc.top)[0]=gc.alloc(vm_hash);
|
||||
auto& hash=gc.top[0].hash().elems;
|
||||
hash["str"]=gc.alloc(vm_str);
|
||||
char* buf=new char[(int)args[1].num()+1];
|
||||
#ifdef _WIN32
|
||||
hash["size"]={vm_num,(double)recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,&socklen)};
|
||||
#else
|
||||
hash["size"]={vm_num,(double)recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,(socklen_t*)&socklen)};
|
||||
#endif
|
||||
buf[(int)hash["size"].num()]=0;
|
||||
hash["str"].str()=buf;
|
||||
delete[] buf;
|
||||
hash["fromip"]=gc.alloc(vm_str);
|
||||
hash["fromip"].str()=inet_ntoa(addr.sin_addr);
|
||||
--gc.top;
|
||||
return gc.top[1];
|
||||
}
|
||||
|
||||
extern "C" nasal_ref nas_errno(std::vector<nasal_ref>& args,nasal_gc& gc){
|
||||
nasal_ref res=gc.alloc(vm_str);
|
||||
res.str()=strerror(errno);
|
||||
return res;
|
||||
}
|
|
@ -44,6 +44,7 @@ var testfile=[
|
|||
"test/fib.nas ",
|
||||
"test/filesystem.nas ",
|
||||
"test/hexdump.nas ",
|
||||
"test/httptest.nas ",
|
||||
"test/json.nas ",
|
||||
"test/leetcode1319.nas ",
|
||||
"test/lexer.nas ",
|
||||
|
@ -73,8 +74,10 @@ var testfile=[
|
|||
var module=[
|
||||
"module/fib.cpp ",
|
||||
"module/keyboard.cpp ",
|
||||
"module/nasocket.cpp ",
|
||||
"module/libfib.nas ",
|
||||
"module/libkey.nas "
|
||||
"module/libkey.nas ",
|
||||
"module/libsock.nas "
|
||||
];
|
||||
|
||||
var getname=func(s){
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import("module/libsock.nas");
|
||||
|
||||
var sd=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.IPPROTO_IP);
|
||||
socket.bind(sd,"127.0.0.1",8080);
|
||||
socket.listen(sd,1);
|
||||
|
||||
var client=socket.accept(sd);
|
||||
println("request ip: ",client.ip);
|
||||
var rv=socket.recv(client.sd,1024);
|
||||
println(rv.str);
|
||||
socket.send(client.sd,"Http/1.1 200 OK
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title> nasal-http-test-web </title>
|
||||
</head>
|
||||
<body>
|
||||
<text>
|
||||
Hello, this is a simple HTML document just for test.<br />
|
||||
This simple http server is written in nasal.<br />
|
||||
Nasal is an ECMAscript-like programming language that used in Flightgear.<br />
|
||||
This language is designed by Andy Ross.<br />
|
||||
|
||||
The interpreter is totally rewritten by ValKmjolnir using C++(-std=c++11) without reusing the code in Andy Ross's nasal interpreter.<br />
|
||||
But we really appreciate that Andy created this amazing programming language and his interpreter project.<br />
|
||||
|
||||
Now this project uses MIT license(2021/5/4). Edit it if you want, use this project to learn or create more interesting things(But don't forget me XD).
|
||||
</text>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
");
|
||||
socket.closesocket(client.sd);
|
||||
socket.closesocket(sd);
|
|
@ -75,6 +75,7 @@ var filechecksum=func(){
|
|||
"./test/fib.nas ",
|
||||
"./test/filesystem.nas ",
|
||||
"./test/hexdump.nas ",
|
||||
"./test/httptest.nas ",
|
||||
"./test/json.nas ",
|
||||
"./test/leetcode1319.nas ",
|
||||
"./test/lexer.nas ",
|
||||
|
|
Loading…
Reference in New Issue