Skip to content

Commit 8b40c09

Browse files
committed
added socket_send_to and socket_recv_from for UDP
1 parent 90b2e4f commit 8b40c09

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

libs/std/socket.c

+85
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ DEFINE_KIND(k_poll);
8484
#define val_sock(o) ((SOCKET)(int_val)val_data(o))
8585
#define val_poll(o) ((polldata*)val_data(o))
8686

87+
static field f_host;
88+
static field f_port;
89+
8790
/**
8891
<doc>
8992
<h1>Socket</h1>
@@ -119,6 +122,8 @@ static value socket_init() {
119122
init_done = true;
120123
}
121124
#endif
125+
f_host = val_id("host");
126+
f_port = val_id("port");
122127
return val_true;
123128
}
124129

@@ -849,6 +854,83 @@ static value socket_set_fast_send( value s, value f ) {
849854
return val_null;
850855
}
851856

857+
/**
858+
socket_send_to : 'socket -> buf:string -> pos:int -> length:int -> addr:{host:'int32,port:int} -> int
859+
<doc>
860+
Send data from an unconnected UDP socket to the given address.
861+
</doc>
862+
**/
863+
static value socket_send_to( value o, value data, value pos, value len, value vaddr ) {
864+
int p,l,dlen;
865+
value host, port;
866+
struct sockaddr_in addr;
867+
val_check_kind(o,k_socket);
868+
val_check(data,string);
869+
val_check(pos,int);
870+
val_check(len,int);
871+
val_check(vaddr,object);
872+
host = val_field(vaddr, f_host);
873+
port = val_field(vaddr, f_port);
874+
val_check(host,int32);
875+
val_check(port,int);
876+
p = val_int(pos);
877+
l = val_int(len);
878+
dlen = val_strlen(data);
879+
memset(&addr,0,sizeof(addr));
880+
addr.sin_family = AF_INET;
881+
addr.sin_port = htons(val_int(port));
882+
*(int*)&addr.sin_addr.s_addr = val_int32(host);
883+
if( p < 0 || l < 0 || p > dlen || p + l > dlen )
884+
neko_error();
885+
POSIX_LABEL(send_again);
886+
dlen = sendto(val_sock(o), val_string(data) + p , l, MSG_NOSIGNAL, (struct sockaddr*)&addr, sizeof(addr));
887+
if( dlen == SOCKET_ERROR ) {
888+
HANDLE_EINTR(send_again);
889+
return block_error();
890+
}
891+
return alloc_int(dlen);
892+
}
893+
894+
/**
895+
socket_recv_from : 'socket -> buf:string -> pos:int -> length:int -> addr:{host:'int32,port:int} -> int
896+
<doc>
897+
Read data from an unconnected UDP socket, store the address from which we received data in addr.
898+
</doc>
899+
**/
900+
static value socket_recv_from( value o, value data, value pos, value len, value addr ) {
901+
int p,l,dlen,ret;
902+
int retry = 0;
903+
struct sockaddr_in saddr;
904+
int slen = sizeof(saddr);
905+
val_check_kind(o,k_socket);
906+
val_check(data,string);
907+
val_check(pos,int);
908+
val_check(len,int);
909+
val_check(addr,object);
910+
p = val_int(pos);
911+
l = val_int(len);
912+
dlen = val_strlen(data);
913+
if( p < 0 || l < 0 || p > dlen || p + l > dlen )
914+
neko_error();
915+
POSIX_LABEL(recv_from_again);
916+
if( retry++ > NRETRYS ) {
917+
sock_tmp t;
918+
t.sock = val_sock(o);
919+
t.buf = val_string(data) + p;
920+
t.size = l;
921+
neko_thread_blocking(tmp_recv,&t);
922+
ret = t.ret;
923+
} else
924+
ret = recvfrom(val_sock(o), val_string(data) + p , l, MSG_NOSIGNAL, (struct sockaddr*)&saddr, &slen);
925+
if( ret == SOCKET_ERROR ) {
926+
HANDLE_EINTR(recv_from_again);
927+
return block_error();
928+
}
929+
alloc_field(addr,f_host,alloc_int32(*(int*)&saddr.sin_addr));
930+
alloc_field(addr,f_port,alloc_int(ntohs(saddr.sin_port)));
931+
return alloc_int(ret);
932+
}
933+
852934
DEFINE_PRIM(socket_init,0);
853935
DEFINE_PRIM(socket_new,1);
854936
DEFINE_PRIM(socket_send,4);
@@ -870,6 +952,9 @@ DEFINE_PRIM(socket_shutdown,3);
870952
DEFINE_PRIM(socket_set_blocking,2);
871953
DEFINE_PRIM(socket_set_fast_send,2);
872954

955+
DEFINE_PRIM(socket_send_to,5);
956+
DEFINE_PRIM(socket_recv_from,5);
957+
873958
DEFINE_PRIM(socket_poll_alloc,1);
874959
DEFINE_PRIM(socket_poll,3);
875960
DEFINE_PRIM(socket_poll_prepare,3);

0 commit comments

Comments
 (0)