added SocketAddress>>family
added Socket>>readBytes:offset:length: started writing Http.moo
This commit is contained in:
parent
82160e03dd
commit
bc93856b35
190
moo/kernel/Http.moo
Normal file
190
moo/kernel/Http.moo
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
###include 'Moo.moo'.
|
||||||
|
#include 'Socket.moo'.
|
||||||
|
|
||||||
|
|
||||||
|
class HttpServerSocket(ServerSocket)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
class HttpServer(Object)
|
||||||
|
{
|
||||||
|
var server_sockets.
|
||||||
|
|
||||||
|
method initialize
|
||||||
|
{
|
||||||
|
server_sockets := LinkedList new.
|
||||||
|
}
|
||||||
|
|
||||||
|
method start: laddr
|
||||||
|
{
|
||||||
|
| sck |
|
||||||
|
|
||||||
|
if (laddr class == Array)
|
||||||
|
{
|
||||||
|
laddr do: [:addr |
|
||||||
|
sck := ServerSocket family: (addr family) type: Socket.Type.STREAM.
|
||||||
|
self.server_sockets addLast: sck.
|
||||||
|
sck bind: addr.
|
||||||
|
].
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sck := ServerSocket family: (laddr family) type: Socket.Type.STREAM.
|
||||||
|
self.server_sockets addLast: sck.
|
||||||
|
sck bind: laddr.
|
||||||
|
}.
|
||||||
|
|
||||||
|
self.server_sockets do: [:ssck |
|
||||||
|
ssck listen: 128.
|
||||||
|
].
|
||||||
|
}
|
||||||
|
|
||||||
|
method close
|
||||||
|
{
|
||||||
|
self.server_sockets do: [:sck |
|
||||||
|
sck close.
|
||||||
|
].
|
||||||
|
|
||||||
|
while (self.server_sockets size > 0)
|
||||||
|
{
|
||||||
|
self.server_sockets removeLastLink.
|
||||||
|
}.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class MyObject(Object)
|
||||||
|
{
|
||||||
|
method(#class) start_server_socket
|
||||||
|
{
|
||||||
|
| s2 buf |
|
||||||
|
s2 := ServerSocket family: Socket.Family.INET type: Socket.Type.STREAM.
|
||||||
|
buf := ByteArray new: 128.
|
||||||
|
|
||||||
|
s2 onEvent: #accepted do: [ :sck :clisck :cliaddr |
|
||||||
|
'SERVER ACCEPTED new client' dump.
|
||||||
|
clisck onEvent: #data_in do: [ :csck |
|
||||||
|
| nbytes |
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
nbytes := csck readBytes: buf.
|
||||||
|
if (nbytes <= 0)
|
||||||
|
{
|
||||||
|
if (nbytes == 0) { csck close }.
|
||||||
|
('Got ' & (nbytes asString)) dump.
|
||||||
|
break.
|
||||||
|
}.
|
||||||
|
|
||||||
|
buf dump.
|
||||||
|
csck writeBytes: buf offset: 0 length: nbytes.
|
||||||
|
}.
|
||||||
|
].
|
||||||
|
clisck onEvent: #data_out do: [ :csck |
|
||||||
|
##csck writeBytes: #[ $a, $b, C'\n' ].
|
||||||
|
].
|
||||||
|
clisck onEvent: #closed do: [ :csck |
|
||||||
|
'Socket CLOSED....' dump.
|
||||||
|
].
|
||||||
|
].
|
||||||
|
|
||||||
|
s2 bind: (SocketAddress fromString: '0.0.0.0:7777').
|
||||||
|
s2 listen: 10.
|
||||||
|
^s2.
|
||||||
|
}
|
||||||
|
|
||||||
|
method(#class) start_client_socket
|
||||||
|
{
|
||||||
|
| s buf count |
|
||||||
|
s := ClientSocket family: Socket.Family.INET type: Socket.Type.STREAM.
|
||||||
|
buf := ByteArray new: 128.
|
||||||
|
|
||||||
|
count := 0.
|
||||||
|
|
||||||
|
s onEvent: #connected do: [ :sck :state |
|
||||||
|
if (state)
|
||||||
|
{
|
||||||
|
s writeBytes: #[ $a, $b, $c ].
|
||||||
|
s writeBytes: #[ $d, $e, $f ].
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
'FAILED TO CONNECT' dump.
|
||||||
|
}.
|
||||||
|
].
|
||||||
|
|
||||||
|
s onEvent: #data_in do: [ :sck |
|
||||||
|
| nbytes |
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
nbytes := sck readBytes: buf.
|
||||||
|
if (nbytes <= 0)
|
||||||
|
{
|
||||||
|
if (nbytes == 0) { sck close }.
|
||||||
|
break.
|
||||||
|
}.
|
||||||
|
('Got ' & (nbytes asString)) dump.
|
||||||
|
buf dump.
|
||||||
|
}.
|
||||||
|
].
|
||||||
|
s onEvent: #data_out do: [ :sck |
|
||||||
|
if (count < 10) { sck writeBytes: #[ $a, $b, C'\n' ]. count := count + 1. }.
|
||||||
|
].
|
||||||
|
|
||||||
|
s connect: (SocketAddress fromString: '127.0.0.1:9999').
|
||||||
|
}
|
||||||
|
|
||||||
|
method(#class) mainxx
|
||||||
|
{
|
||||||
|
[
|
||||||
|
| s s2 ss |
|
||||||
|
|
||||||
|
[
|
||||||
|
s := self start_client_socket.
|
||||||
|
s2 := self start_server_socket.
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
ss := System handleAsyncEvent.
|
||||||
|
if (ss isError) { break }.
|
||||||
|
###if (ss == st) { System removeAsyncSemaphore: st }.
|
||||||
|
}.
|
||||||
|
]
|
||||||
|
ensure:
|
||||||
|
[
|
||||||
|
if (s notNil) { s close }.
|
||||||
|
if (s2 notNil) { s2 close }.
|
||||||
|
]
|
||||||
|
|
||||||
|
] on: Exception do: [:ex | ('Exception - ' & ex messageText) dump ].
|
||||||
|
|
||||||
|
'----- END OF MAIN ------' dump.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
method(#class) main
|
||||||
|
{
|
||||||
|
| httpd |
|
||||||
|
|
||||||
|
[
|
||||||
|
httpd := HttpServer new.
|
||||||
|
[
|
||||||
|
| ss |
|
||||||
|
httpd start: %(
|
||||||
|
SocketAddress fromString: '[::]:7777',
|
||||||
|
SocketAddress fromString: '0.0.0.0:7776'
|
||||||
|
).
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
ss := System handleAsyncEvent.
|
||||||
|
if (ss isError) { break }.
|
||||||
|
}.
|
||||||
|
] ensure: [
|
||||||
|
if (httpd notNil) { httpd close }
|
||||||
|
]
|
||||||
|
|
||||||
|
] on: Exception do: [:ex | ('Exception - ' & ex messageText) dump].
|
||||||
|
|
||||||
|
'----- END OF MAIN ------' dump.
|
||||||
|
}
|
||||||
|
}
|
@ -216,9 +216,9 @@ class(#byte(16)) IP6Address(IP4Address)
|
|||||||
|
|
||||||
class(#byte) SocketAddress(Object) from 'sck.addr'
|
class(#byte) SocketAddress(Object) from 'sck.addr'
|
||||||
{
|
{
|
||||||
##method(#primitive) family.
|
method(#primitive) family.
|
||||||
method(#primitive) fromString: str.
|
method(#primitive) fromString: str.
|
||||||
|
|
||||||
method(#class) fromString: str
|
method(#class) fromString: str
|
||||||
{
|
{
|
||||||
^self new fromString: str
|
^self new fromString: str
|
||||||
@ -230,6 +230,7 @@ class AsyncHandle(Object)
|
|||||||
## the handle must be the first field in this object to match
|
## the handle must be the first field in this object to match
|
||||||
## the internal representation used by various modules. (e.g. sck)
|
## the internal representation used by various modules. (e.g. sck)
|
||||||
var(#get) handle := -1.
|
var(#get) handle := -1.
|
||||||
|
var(#get) closedEventAction := nil.
|
||||||
|
|
||||||
##method initialize
|
##method initialize
|
||||||
##{
|
##{
|
||||||
@ -242,9 +243,25 @@ class AsyncHandle(Object)
|
|||||||
{
|
{
|
||||||
self _close.
|
self _close.
|
||||||
self.handle := -1.
|
self.handle := -1.
|
||||||
|
|
||||||
|
if (self.closedEventAction notNil)
|
||||||
|
{
|
||||||
|
self.closedEventAction value: self.
|
||||||
|
}.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
method onEvent: event_type do: action_block
|
||||||
|
{
|
||||||
|
if (event_type == #closed)
|
||||||
|
{
|
||||||
|
self.closedEventAction := action_block.
|
||||||
|
^self.
|
||||||
|
}.
|
||||||
|
|
||||||
|
Exception signal: 'unknown event type ' & event_type asString.
|
||||||
|
}
|
||||||
|
|
||||||
method writeBytes: bytes offset: offset length: length
|
method writeBytes: bytes offset: offset length: length
|
||||||
{
|
{
|
||||||
^self writeBytes: bytes offset: offset length: length.
|
^self writeBytes: bytes offset: offset length: length.
|
||||||
@ -264,7 +281,7 @@ class Socket(AsyncHandle) from 'sck'
|
|||||||
var pending_bytes, pending_offset, pending_length.
|
var pending_bytes, pending_offset, pending_length.
|
||||||
var outreadysem, outdonesem, inreadysem.
|
var outreadysem, outdonesem, inreadysem.
|
||||||
|
|
||||||
method(#primitive) open(domain, type, proto).
|
method(#primitive) open(family, type, proto).
|
||||||
method(#primitive) _close.
|
method(#primitive) _close.
|
||||||
method(#primitive) bind: addr.
|
method(#primitive) bind: addr.
|
||||||
method(#primitive) _listen: backlog.
|
method(#primitive) _listen: backlog.
|
||||||
@ -273,12 +290,13 @@ class Socket(AsyncHandle) from 'sck'
|
|||||||
method(#primitive) _socketError.
|
method(#primitive) _socketError.
|
||||||
|
|
||||||
method(#primitive) readBytes: bytes.
|
method(#primitive) readBytes: bytes.
|
||||||
|
method(#primitive) readBytes: bytes offset: offset length: length.
|
||||||
method(#primitive) _writeBytes: bytes.
|
method(#primitive) _writeBytes: bytes.
|
||||||
method(#primitive) _writeBytes: bytes offset: offset length: length.
|
method(#primitive) _writeBytes: bytes offset: offset length: length.
|
||||||
}
|
}
|
||||||
|
|
||||||
(* TODO: generate these domain and type from the C header *)
|
(* TODO: generate these family and type from the C header *)
|
||||||
pooldic Socket.Domain
|
pooldic Socket.Family
|
||||||
{
|
{
|
||||||
INET := 2.
|
INET := 2.
|
||||||
INET6 := 10.
|
INET6 := 10.
|
||||||
@ -295,9 +313,9 @@ extend Socket
|
|||||||
method(#class) new { self messageProhibited: #new }
|
method(#class) new { self messageProhibited: #new }
|
||||||
method(#class) new: size { self messageProhibited: #new: }
|
method(#class) new: size { self messageProhibited: #new: }
|
||||||
|
|
||||||
method(#class) domain: domain type: type
|
method(#class) family: family type: type
|
||||||
{
|
{
|
||||||
^(super new) open(domain, type, 0)
|
^(super new) open(family, type, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
method initialize
|
method initialize
|
||||||
@ -351,8 +369,6 @@ extend Socket
|
|||||||
|
|
||||||
method close
|
method close
|
||||||
{
|
{
|
||||||
'Socket close' dump.
|
|
||||||
|
|
||||||
if (self.outdonesem notNil)
|
if (self.outdonesem notNil)
|
||||||
{
|
{
|
||||||
System unsignal: self.outdonesem.
|
System unsignal: self.outdonesem.
|
||||||
@ -390,7 +406,7 @@ extend Socket
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Exception signal: 'unknown event type ' & event_type asString.
|
^super onEvent: event_type do: action_block.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -569,109 +585,3 @@ class ServerSocket(Socket)
|
|||||||
^self _listen: backlog.
|
^self _listen: backlog.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyObject(Object)
|
|
||||||
{
|
|
||||||
method(#class) start_server_socket
|
|
||||||
{
|
|
||||||
| s2 buf |
|
|
||||||
s2 := ServerSocket domain: Socket.Domain.INET type: Socket.Type.STREAM.
|
|
||||||
buf := ByteArray new: 128.
|
|
||||||
|
|
||||||
s2 onEvent: #accepted do: [ :sck :clisck :cliaddr |
|
|
||||||
'SERVER ACCEPTED new client' dump.
|
|
||||||
clisck onEvent: #data_in do: [ :csck |
|
|
||||||
| nbytes |
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
nbytes := csck readBytes: buf.
|
|
||||||
if (nbytes <= 0)
|
|
||||||
{
|
|
||||||
if (nbytes == 0) { csck close }.
|
|
||||||
('Got ' & (nbytes asString)) dump.
|
|
||||||
break.
|
|
||||||
}.
|
|
||||||
|
|
||||||
buf dump.
|
|
||||||
csck writeBytes: buf offset: 0 length: nbytes.
|
|
||||||
}.
|
|
||||||
].
|
|
||||||
clisck onEvent: #data_out do: [ :csck |
|
|
||||||
##csck writeBytes: #[ $a, $b, C'\n' ].
|
|
||||||
].
|
|
||||||
].
|
|
||||||
|
|
||||||
s2 bind: (SocketAddress fromString: '0.0.0.0:7777').
|
|
||||||
s2 listen: 10.
|
|
||||||
^s2.
|
|
||||||
}
|
|
||||||
|
|
||||||
method(#class) start_client_socket
|
|
||||||
{
|
|
||||||
| s buf count |
|
|
||||||
s := ClientSocket domain: Socket.Domain.INET type: Socket.Type.STREAM.
|
|
||||||
buf := ByteArray new: 128.
|
|
||||||
|
|
||||||
count := 0.
|
|
||||||
|
|
||||||
s onEvent: #connected do: [ :sck :state |
|
|
||||||
if (state)
|
|
||||||
{
|
|
||||||
s writeBytes: #[ $a, $b, $c ].
|
|
||||||
s writeBytes: #[ $d, $e, $f ].
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
'FAILED TO CONNECT' dump.
|
|
||||||
}.
|
|
||||||
].
|
|
||||||
|
|
||||||
s onEvent: #data_in do: [ :sck |
|
|
||||||
| nbytes |
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
nbytes := sck readBytes: buf.
|
|
||||||
if (nbytes <= 0)
|
|
||||||
{
|
|
||||||
if (nbytes == 0) { sck close }.
|
|
||||||
break.
|
|
||||||
}.
|
|
||||||
('Got ' & (nbytes asString)) dump.
|
|
||||||
buf dump.
|
|
||||||
}.
|
|
||||||
].
|
|
||||||
s onEvent: #data_out do: [ :sck |
|
|
||||||
if (count < 10) { sck writeBytes: #[ $a, $b, C'\n' ]. count := count + 1. }.
|
|
||||||
].
|
|
||||||
|
|
||||||
s connect: (SocketAddress fromString: '127.0.0.1:9999').
|
|
||||||
}
|
|
||||||
|
|
||||||
method(#class) main
|
|
||||||
{
|
|
||||||
[
|
|
||||||
| s s2 ss |
|
|
||||||
|
|
||||||
[
|
|
||||||
s := self start_client_socket.
|
|
||||||
s2 := self start_server_socket.
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
ss := System handleAsyncEvent.
|
|
||||||
if (ss isError) { break }.
|
|
||||||
###if (ss == st) { System removeAsyncSemaphore: st }.
|
|
||||||
}.
|
|
||||||
]
|
|
||||||
ensure:
|
|
||||||
[
|
|
||||||
if (s notNil) { s close }.
|
|
||||||
if (s2 notNil) { s2 close }.
|
|
||||||
]
|
|
||||||
|
|
||||||
] on: Exception do: [:ex | ('Exception - ' & ex messageText) dump ].
|
|
||||||
|
|
||||||
'----- END OF MAIN ------' dump.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -55,36 +55,9 @@
|
|||||||
|
|
||||||
#define MA MOO_TYPE_MAX(moo_oow_t)
|
#define MA MOO_TYPE_MAX(moo_oow_t)
|
||||||
|
|
||||||
typedef struct sck_addr_trailer_t sck_addr_trailer_t;
|
|
||||||
|
|
||||||
struct sck_addr_trailer_t
|
|
||||||
{
|
|
||||||
int family;
|
|
||||||
union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
moo_uint16_t port;
|
|
||||||
moo_uint32_t addr;
|
|
||||||
} in4;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
moo_uint16_t port;
|
|
||||||
moo_uint8_t addr[16];
|
|
||||||
moo_uint32_t scope;
|
|
||||||
} in6;
|
|
||||||
|
|
||||||
/*
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
moo_ooch_t path[100];
|
|
||||||
} local; */
|
|
||||||
} u;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
union sockaddr_t
|
union sockaddr_t
|
||||||
{
|
{
|
||||||
|
struct sockaddr sa;
|
||||||
#if (MOO_SIZEOF_STRUCT_SOCKADDR_IN > 0)
|
#if (MOO_SIZEOF_STRUCT_SOCKADDR_IN > 0)
|
||||||
struct sockaddr_in in4;
|
struct sockaddr_in in4;
|
||||||
#endif
|
#endif
|
||||||
@ -104,7 +77,7 @@ static int str_to_ipv4 (const moo_ooch_t* str, moo_oow_t len, struct in_addr* in
|
|||||||
{
|
{
|
||||||
const moo_ooch_t* end;
|
const moo_ooch_t* end;
|
||||||
int dots = 0, digits = 0;
|
int dots = 0, digits = 0;
|
||||||
moo_uint32_t acc = 0, addr = 0;
|
moo_uint32_t acc = 0, addr = 0;
|
||||||
moo_ooch_t c;
|
moo_ooch_t c;
|
||||||
|
|
||||||
end = str + len;
|
end = str + len;
|
||||||
@ -482,6 +455,21 @@ no_rbrack:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static moo_pfrc_t pf_get_family (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||||
|
{
|
||||||
|
moo_oop_t rcv;
|
||||||
|
moo_oop_t v;
|
||||||
|
struct sockaddr* sa;
|
||||||
|
|
||||||
|
rcv = (moo_oop_t)MOO_STACK_GETRCV(moo, nargs);
|
||||||
|
MOO_PF_CHECK_RCV (moo, MOO_OBJ_IS_BYTE_POINTER(rcv) && MOO_OBJ_GET_SIZE(rcv) >= MOO_SIZEOF(sockaddr_t));
|
||||||
|
|
||||||
|
sa = (struct sockaddr*)MOO_OBJ_GET_BYTE_SLOT(rcv);
|
||||||
|
v = MOO_SMOOI_TO_OOP(sa->sa_family);
|
||||||
|
|
||||||
|
MOO_STACK_SETRET (moo, nargs, v);
|
||||||
|
return MOO_PF_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static moo_pfrc_t pf_from_string (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
static moo_pfrc_t pf_from_string (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||||
{
|
{
|
||||||
@ -506,7 +494,8 @@ static moo_pfrc_t pf_from_string (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
|||||||
|
|
||||||
static moo_pfinfo_t pfinfos[] =
|
static moo_pfinfo_t pfinfos[] =
|
||||||
{
|
{
|
||||||
{ I, { 'f','r','o','m','S','t','r','i','n','g',':','\0' }, 0, { pf_from_string, 1, 1 } },
|
{ I, { 'f','a','m','i','l','y' }, 0, { pf_get_family, 0, 0 } },
|
||||||
|
{ I, { 'f','r','o','m','S','t','r','i','n','g',':','\0' }, 0, { pf_from_string, 1, 1 } }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
@ -514,7 +503,6 @@ static moo_pfinfo_t pfinfos[] =
|
|||||||
static int import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)
|
static int import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)
|
||||||
{
|
{
|
||||||
moo_ooi_t spec;
|
moo_ooi_t spec;
|
||||||
/*if (moo_setclasstrsize (moo, _class, MOO_SIZEOF(sck_addr_trailer_t), MOO_NULL) <= -1) return -1;*/
|
|
||||||
|
|
||||||
spec = MOO_OOP_TO_SMOOI(_class->spec);
|
spec = MOO_OOP_TO_SMOOI(_class->spec);
|
||||||
if (!MOO_CLASS_SPEC_IS_INDEXED(spec) || MOO_CLASS_SPEC_INDEXED_TYPE(spec) != MOO_OBJ_TYPE_BYTE || MOO_CLASS_SPEC_NAMED_INSTVARS(spec) != 0)
|
if (!MOO_CLASS_SPEC_IS_INDEXED(spec) || MOO_CLASS_SPEC_INDEXED_TYPE(spec) != MOO_OBJ_TYPE_BYTE || MOO_CLASS_SPEC_NAMED_INSTVARS(spec) != 0)
|
||||||
|
@ -404,6 +404,7 @@ static moo_pfrc_t pf_read_socket (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
|||||||
{
|
{
|
||||||
oop_sck_t sck;
|
oop_sck_t sck;
|
||||||
moo_oop_byte_t buf;
|
moo_oop_byte_t buf;
|
||||||
|
moo_oow_t offset, length, maxlen;
|
||||||
int fd;
|
int fd;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
|
||||||
@ -428,7 +429,36 @@ static moo_pfrc_t pf_read_socket (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
|||||||
return MOO_PF_FAILURE;
|
return MOO_PF_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = recv(fd, MOO_OBJ_GET_BYTE_SLOT(buf), MOO_OBJ_GET_SIZE(buf), 0);
|
offset = 0;
|
||||||
|
maxlen = MOO_OBJ_GET_SIZE(buf);
|
||||||
|
length = maxlen;
|
||||||
|
|
||||||
|
if (nargs >= 2)
|
||||||
|
{
|
||||||
|
moo_oop_t tmp;
|
||||||
|
|
||||||
|
tmp = MOO_STACK_GETARG(moo, nargs, 1);
|
||||||
|
if (moo_inttooow (moo, tmp, &offset) <= 0)
|
||||||
|
{
|
||||||
|
moo_seterrbfmt (moo, MOO_EINVAL, "invalid offset - %O", tmp);
|
||||||
|
return MOO_PF_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nargs >= 3)
|
||||||
|
{
|
||||||
|
tmp = MOO_STACK_GETARG(moo, nargs, 2);
|
||||||
|
if (moo_inttooow(moo, tmp, &length) <= 0)
|
||||||
|
{
|
||||||
|
moo_seterrbfmt (moo, MOO_EINVAL, "invalid length - %O", tmp);
|
||||||
|
return MOO_PF_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset >= maxlen) offset = maxlen - 1;
|
||||||
|
if (length > maxlen - offset) length = maxlen - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = recv(fd, &MOO_OBJ_GET_BYTE_SLOT(buf)[offset], length, 0);
|
||||||
if (n <= -1 && errno != EWOULDBLOCK && errno != EAGAIN)
|
if (n <= -1 && errno != EWOULDBLOCK && errno != EAGAIN)
|
||||||
{
|
{
|
||||||
moo_seterrwithsyserr (moo, errno);
|
moo_seterrwithsyserr (moo, errno);
|
||||||
@ -540,6 +570,7 @@ static moo_pfinfo_t pfinfos[] =
|
|||||||
{ I, { 'l','i','s','t','e','n',':','\0' }, 0, { pf_listen_socket, 1, 1 } },
|
{ I, { 'l','i','s','t','e','n',':','\0' }, 0, { pf_listen_socket, 1, 1 } },
|
||||||
{ I, { 'o','p','e','n','\0' }, 0, { pf_open_socket, 3, 3 } },
|
{ I, { 'o','p','e','n','\0' }, 0, { pf_open_socket, 3, 3 } },
|
||||||
{ I, { 'r','e','a','d','B','y','t','e','s',':','\0' }, 0, { pf_read_socket, 1, 1 } },
|
{ I, { 'r','e','a','d','B','y','t','e','s',':','\0' }, 0, { pf_read_socket, 1, 1 } },
|
||||||
|
{ I, { 'r','e','a','d','B','y','t','e','s',':','o','f','f','s','e','t',':','l','e','n','g','t','h',':','\0' }, 0, { pf_read_socket, 3, 3 } },
|
||||||
{ I, { 's','o','c','k','e','t','E','r','r','o','r','\0' }, 0, { pf_get_socket_error, 0, 0 } },
|
{ I, { 's','o','c','k','e','t','E','r','r','o','r','\0' }, 0, { pf_get_socket_error, 0, 0 } },
|
||||||
{ I, { 'w','r','i','t','e','B','y','t','e','s',':','\0' }, 0, { pf_write_socket, 1, 1 } },
|
{ I, { 'w','r','i','t','e','B','y','t','e','s',':','\0' }, 0, { pf_write_socket, 1, 1 } },
|
||||||
{ I, { 'w','r','i','t','e','B','y','t','e','s',':','o','f','f','s','e','t',':','l','e','n','g','t','h',':','\0' }, 0, { pf_write_socket, 3, 3 } }
|
{ I, { 'w','r','i','t','e','B','y','t','e','s',':','o','f','f','s','e','t',':','l','e','n','g','t','h',':','\0' }, 0, { pf_write_socket, 3, 3 } }
|
||||||
|
Loading…
Reference in New Issue
Block a user