attempting to change the Socket class to invoke methods instead of relying on blocks
This commit is contained in:
parent
ff5e5aa23f
commit
16b12e2dfc
@ -1,15 +1,33 @@
|
|||||||
###include 'Moo.moo'.
|
###include 'Moo.moo'.
|
||||||
#include 'Socket.moo'.
|
#include 'Socket.moo'.
|
||||||
|
|
||||||
|
class HttpSocket(Socket)
|
||||||
|
{
|
||||||
|
method onSocketDataIn
|
||||||
|
{
|
||||||
|
'CLIENT got DATA' dump.
|
||||||
|
self close.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class HttpServerSocket(ServerSocket)
|
class HttpServerSocket(ServerSocket)
|
||||||
{
|
{
|
||||||
method(#class) initialize
|
method initialize
|
||||||
{
|
{
|
||||||
self onEvent: #accepted do: [
|
super initialize.
|
||||||
|
}
|
||||||
].
|
|
||||||
|
method onSocketAccepted: clisck from: cliaddr
|
||||||
###self addEventListener: self.
|
{
|
||||||
|
'CLIENT accepted ..............' dump.
|
||||||
|
clisck dump.
|
||||||
|
cliaddr dump.
|
||||||
|
## clisck close.
|
||||||
|
}
|
||||||
|
|
||||||
|
method acceptedSocketClass
|
||||||
|
{
|
||||||
|
^HttpSocket
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,6 +37,7 @@ class HttpServer(Object)
|
|||||||
|
|
||||||
method initialize
|
method initialize
|
||||||
{
|
{
|
||||||
|
super initialize.
|
||||||
server_sockets := LinkedList new.
|
server_sockets := LinkedList new.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,56 +225,14 @@ class(#byte) SocketAddress(Object) from 'sck.addr'
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AsyncHandle(Object)
|
|
||||||
|
class Socket(Object) from 'sck'
|
||||||
{
|
{
|
||||||
## 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
|
var(#get) closedEventAction.
|
||||||
##{
|
|
||||||
## ^super initialize
|
|
||||||
##}
|
|
||||||
|
|
||||||
method close
|
|
||||||
{
|
|
||||||
if (self.handle >= 0)
|
|
||||||
{
|
|
||||||
self _close.
|
|
||||||
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
|
|
||||||
{
|
|
||||||
^self writeBytes: bytes offset: offset length: length.
|
|
||||||
}
|
|
||||||
|
|
||||||
method writeBytes: bytes
|
|
||||||
{
|
|
||||||
^self writeBytes: bytes offset: 0 length: (bytes size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Socket(AsyncHandle) from 'sck'
|
|
||||||
{
|
|
||||||
var(#get) dataInEventAction.
|
var(#get) dataInEventAction.
|
||||||
var(#get) dataOutEventAction.
|
var(#get) dataOutEventAction.
|
||||||
|
|
||||||
@ -282,6 +240,10 @@ class Socket(AsyncHandle) from 'sck'
|
|||||||
var outreadysem, outdonesem, inreadysem.
|
var outreadysem, outdonesem, inreadysem.
|
||||||
|
|
||||||
method(#primitive) open(family, type, proto).
|
method(#primitive) open(family, type, proto).
|
||||||
|
## map the open primitive again with a different name for strict internal use only.
|
||||||
|
## this method is supposed to be used to handle an accepted socket in server sockets.
|
||||||
|
method(#primitive) __open(handle).
|
||||||
|
|
||||||
method(#primitive) _close.
|
method(#primitive) _close.
|
||||||
method(#primitive) bind: addr.
|
method(#primitive) bind: addr.
|
||||||
method(#primitive) _listen: backlog.
|
method(#primitive) _listen: backlog.
|
||||||
@ -313,11 +275,27 @@ 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) __with: handle
|
||||||
|
{
|
||||||
|
^(self _basicNew initialize) __open(handle)
|
||||||
|
}
|
||||||
|
|
||||||
method(#class) family: family type: type
|
method(#class) family: family type: type
|
||||||
{
|
{
|
||||||
^(super new) open(family, type, 0)
|
## new is prohibited. so use _basicNew with initialize.
|
||||||
|
##^(self new) open(family, type, 0)
|
||||||
|
^(self _basicNew initialize) open(family, type, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(* -------------------
|
||||||
|
socketClosing
|
||||||
|
socketClosed
|
||||||
|
socketDataIn
|
||||||
|
socketDataOut
|
||||||
|
socketAccepted:from:
|
||||||
|
socketConnected:
|
||||||
|
-------------------- *)
|
||||||
|
|
||||||
method initialize
|
method initialize
|
||||||
{
|
{
|
||||||
super initialize.
|
super initialize.
|
||||||
@ -327,8 +305,11 @@ extend Socket
|
|||||||
self.inreadysem := Semaphore new.
|
self.inreadysem := Semaphore new.
|
||||||
|
|
||||||
self.outdonesem signalAction: [ :sem |
|
self.outdonesem signalAction: [ :sem |
|
||||||
self.dataOutEventAction value: self.
|
##if (self.dataOutEventAction notNil)
|
||||||
##(self.eventActions at: Socket.EventType.DATA_OUT) value: self.
|
##{
|
||||||
|
## self.dataOutEventAction value: self.
|
||||||
|
##}.
|
||||||
|
self onSocketDataOut.
|
||||||
System unsignal: self.outreadysem.
|
System unsignal: self.outreadysem.
|
||||||
].
|
].
|
||||||
|
|
||||||
@ -356,8 +337,8 @@ extend Socket
|
|||||||
].
|
].
|
||||||
|
|
||||||
self.inreadysem signalAction: [ :sem |
|
self.inreadysem signalAction: [ :sem |
|
||||||
##(self.eventActions at: Socket.EventType.DATA_IN) value: self.
|
###self.dataInEventAction value: self.
|
||||||
self.dataInEventAction value: self.
|
self onSocketDataIn.
|
||||||
].
|
].
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,7 +347,7 @@ extend Socket
|
|||||||
'SOCKET FINALIZED...............' dump.
|
'SOCKET FINALIZED...............' dump.
|
||||||
self close.
|
self close.
|
||||||
}
|
}
|
||||||
|
|
||||||
method close
|
method close
|
||||||
{
|
{
|
||||||
if (self.outdonesem notNil)
|
if (self.outdonesem notNil)
|
||||||
@ -390,13 +371,26 @@ extend Socket
|
|||||||
self.inreadysem := nil.
|
self.inreadysem := nil.
|
||||||
}.
|
}.
|
||||||
|
|
||||||
^super close.
|
if (self.handle >= 0)
|
||||||
|
{
|
||||||
|
self _close.
|
||||||
|
self.handle := -1.
|
||||||
|
|
||||||
|
##if (self.closedEventAction notNil)
|
||||||
|
##{
|
||||||
|
## self.closedEventAction value: self.
|
||||||
|
##}.
|
||||||
|
self onSocketClosed.
|
||||||
|
}.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
method onEvent: event_type do: action_block
|
method onEvent: event_type do: action_block
|
||||||
{
|
{
|
||||||
if (event_type == #data_in)
|
if (event_type == #closed)
|
||||||
|
{
|
||||||
|
self.closedEventAction := action_block.
|
||||||
|
}
|
||||||
|
elsif (event_type == #data_in)
|
||||||
{
|
{
|
||||||
self.dataInEventAction := action_block.
|
self.dataInEventAction := action_block.
|
||||||
}
|
}
|
||||||
@ -406,10 +400,17 @@ extend Socket
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
^super onEvent: event_type do: action_block.
|
Exception signal: 'unknown event type ' & event_type asString.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
method beWatched
|
||||||
|
{
|
||||||
|
System addAsyncSemaphore: self.inreadysem.
|
||||||
|
System signal: self.inreadysem onInput: self.handle.
|
||||||
|
System addAsyncSemaphore: self.outdonesem.
|
||||||
|
}
|
||||||
|
|
||||||
method writeBytes: bytes offset: offset length: length
|
method writeBytes: bytes offset: offset length: length
|
||||||
{
|
{
|
||||||
| n pos rem |
|
| n pos rem |
|
||||||
@ -448,11 +449,22 @@ extend Socket
|
|||||||
System signal: self.outreadysem onOutput: self.handle.
|
System signal: self.outreadysem onOutput: self.handle.
|
||||||
}
|
}
|
||||||
|
|
||||||
method beWatched
|
method writeBytes: bytes
|
||||||
|
{
|
||||||
|
^self writeBytes: bytes offset: 0 length: (bytes size)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
method onSocketClosed
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
method onSocketDataIn
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
method onSocketDataOut
|
||||||
{
|
{
|
||||||
System addAsyncSemaphore: self.inreadysem.
|
|
||||||
System signal: self.inreadysem onInput: self.handle.
|
|
||||||
System addAsyncSemaphore: self.outdonesem.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,7 +488,8 @@ class ClientSocket(Socket)
|
|||||||
System unsignal: sem.
|
System unsignal: sem.
|
||||||
System removeAsyncSemaphore: sem.
|
System removeAsyncSemaphore: sem.
|
||||||
|
|
||||||
self.connectedEventAction value: self value: (soerr == 0).
|
##self.connectedEventAction value: self value: (soerr == 0).
|
||||||
|
self onSocketConnected: (soerr == 0).
|
||||||
if (soerr == 0) { self beWatched }.
|
if (soerr == 0) { self beWatched }.
|
||||||
}.
|
}.
|
||||||
(* HOW TO HANDLE TIMEOUT? *)
|
(* HOW TO HANDLE TIMEOUT? *)
|
||||||
@ -516,13 +529,18 @@ class ClientSocket(Socket)
|
|||||||
{
|
{
|
||||||
## connected immediately
|
## connected immediately
|
||||||
'IMMEDIATELY CONNECTED.....' dump.
|
'IMMEDIATELY CONNECTED.....' dump.
|
||||||
self.connectedEventAction value: self value: true.
|
###self.connectedEventAction value: self value: true.
|
||||||
|
self onSocketConnected: true.
|
||||||
|
|
||||||
System addAsyncSemaphore: self.inreadysem.
|
System addAsyncSemaphore: self.inreadysem.
|
||||||
System signal: self.inreadysem onInput: self.handle.
|
System signal: self.inreadysem onInput: self.handle.
|
||||||
System addAsyncSemaphore: self.outdonesem.
|
System addAsyncSemaphore: self.outdonesem.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
method onSocketConnected
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ServerSocket(Socket)
|
class ServerSocket(Socket)
|
||||||
@ -535,22 +553,36 @@ class ServerSocket(Socket)
|
|||||||
super initialize.
|
super initialize.
|
||||||
|
|
||||||
self.inreadysem signalAction: [ :sem |
|
self.inreadysem signalAction: [ :sem |
|
||||||
| cliaddr clisck cliact |
|
| cliaddr clisck cliact fd |
|
||||||
cliaddr := SocketAddress new.
|
cliaddr := SocketAddress new.
|
||||||
|
|
||||||
|
fd := self _accept: cliaddr.
|
||||||
|
if (fd >= 0)
|
||||||
|
{
|
||||||
|
clisck := (self acceptedSocketClass) __with: fd.
|
||||||
|
clisck beWatched.
|
||||||
|
self onSocketAccepted: clisck from: cliaddr.
|
||||||
|
}
|
||||||
|
|
||||||
|
(*--------------------------
|
||||||
clisck := self _accept: cliaddr.
|
clisck := self _accept: cliaddr.
|
||||||
if (clisck notNil)
|
if (clisck notNil) ## if nil, _accept: failed with EWOULDBLOCK/EAGAIN.
|
||||||
{
|
{
|
||||||
## the _accept method doesn't invoke the initialize method.
|
## the _accept method doesn't invoke the initialize method.
|
||||||
## i should invoke it manually here.
|
## i should invoke it manually here.
|
||||||
clisck initialize.
|
clisck initialize.
|
||||||
|
clisck beWatched.
|
||||||
|
self onSocketAccepted: clisck from: cliaddr.
|
||||||
|
|
||||||
if (self.acceptedEventAction notNil)
|
###if (self.acceptedEventAction notNil)
|
||||||
{
|
####{
|
||||||
self.acceptedEventAction value: self value: clisck value: cliaddr.
|
### clisck beWatched.
|
||||||
clisck beWatched.
|
### self.acceptedEventAction value: self value: clisck value: cliaddr.
|
||||||
}
|
### clisck beWatched.
|
||||||
else { clisck close }.
|
###}
|
||||||
|
###else { clisck close }.
|
||||||
}.
|
}.
|
||||||
|
---------------------------*)
|
||||||
].
|
].
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,4 +616,14 @@ class ServerSocket(Socket)
|
|||||||
System signal: self.inreadysem onInput: self.handle.
|
System signal: self.inreadysem onInput: self.handle.
|
||||||
^self _listen: backlog.
|
^self _listen: backlog.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
method onSocketAccepted: clisck from: cliaddr
|
||||||
|
{
|
||||||
|
clisck close.
|
||||||
|
}
|
||||||
|
|
||||||
|
method acceptedSocketClass
|
||||||
|
{
|
||||||
|
^Socket
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,9 +58,18 @@ static moo_pfrc_t pf_open_socket (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
|||||||
MOO_OBJ_BYTESOF(sck) >= (MOO_SIZEOF(*sck) - MOO_SIZEOF(moo_obj_t))
|
MOO_OBJ_BYTESOF(sck) >= (MOO_SIZEOF(*sck) - MOO_SIZEOF(moo_obj_t))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (nargs == 1)
|
||||||
|
{
|
||||||
|
/* special form of opening. the socket handle is given */
|
||||||
|
sck->handle = MOO_STACK_GETARG(moo, nargs, 0);
|
||||||
|
MOO_STACK_SETRETTORCV (moo, nargs);
|
||||||
|
return MOO_PF_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
dom = MOO_STACK_GETARG(moo, nargs, 0);
|
dom = MOO_STACK_GETARG(moo, nargs, 0);
|
||||||
type = MOO_STACK_GETARG(moo, nargs, 1);
|
type = MOO_STACK_GETARG(moo, nargs, 1);
|
||||||
proto = MOO_STACK_GETARG(moo, nargs, 2);
|
proto = (nargs < 3)? 0: MOO_STACK_GETARG(moo, nargs, 2);
|
||||||
|
|
||||||
|
|
||||||
MOO_PF_CHECK_ARGS (moo, nargs, MOO_OOP_IS_SMOOI(dom) && MOO_OOP_IS_SMOOI(type) && MOO_OOP_IS_SMOOI(proto));
|
MOO_PF_CHECK_ARGS (moo, nargs, MOO_OOP_IS_SMOOI(dom) && MOO_OOP_IS_SMOOI(type) && MOO_OOP_IS_SMOOI(proto));
|
||||||
|
|
||||||
@ -266,6 +275,7 @@ normal_accept:
|
|||||||
#endif
|
#endif
|
||||||
if (fcntl(newfd, F_SETFL, fl) == -1) goto fcntl_failure;
|
if (fcntl(newfd, F_SETFL, fl) == -1) goto fcntl_failure;
|
||||||
|
|
||||||
|
#if 0
|
||||||
accept_done:
|
accept_done:
|
||||||
/*newsck = (oop_sck_t)moo_instantiate(moo, MOO_OBJ_GET_CLASS(sck), MOO_NULL, 0);*/
|
/*newsck = (oop_sck_t)moo_instantiate(moo, MOO_OBJ_GET_CLASS(sck), MOO_NULL, 0);*/
|
||||||
newsck = (oop_sck_t)moo_instantiate(moo, ((sck_modctx_t*)mod->ctx)->sck_class, MOO_NULL, 0);
|
newsck = (oop_sck_t)moo_instantiate(moo, ((sck_modctx_t*)mod->ctx)->sck_class, MOO_NULL, 0);
|
||||||
@ -289,6 +299,19 @@ accept_done:
|
|||||||
* method should call application-level initializer. */
|
* method should call application-level initializer. */
|
||||||
MOO_STACK_SETRET (moo, nargs, (moo_oop_t)newsck);
|
MOO_STACK_SETRET (moo, nargs, (moo_oop_t)newsck);
|
||||||
return MOO_PF_SUCCESS;
|
return MOO_PF_SUCCESS;
|
||||||
|
#else
|
||||||
|
accept_done:
|
||||||
|
if (!MOO_IN_SMOOI_RANGE(newfd))
|
||||||
|
{
|
||||||
|
/* the file descriptor is too big to be represented as a small integer */
|
||||||
|
moo_seterrbfmt (moo, MOO_ERANGE, "socket handle %d not in the permitted range", newfd);
|
||||||
|
close (newfd);
|
||||||
|
return MOO_PF_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(newfd));
|
||||||
|
return MOO_PF_SUCCESS;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static moo_pfrc_t pf_listen_socket (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
static moo_pfrc_t pf_listen_socket (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||||
@ -568,7 +591,7 @@ static moo_pfinfo_t pfinfos[] =
|
|||||||
{ I, { 'c','l','o','s','e','\0' }, 0, { pf_close_socket, 0, 0 } },
|
{ I, { 'c','l','o','s','e','\0' }, 0, { pf_close_socket, 0, 0 } },
|
||||||
{ I, { 'c','o','n','n','e','c','t',':','\0' }, 0, { pf_connect_socket, 1, 1 } },
|
{ I, { 'c','o','n','n','e','c','t',':','\0' }, 0, { pf_connect_socket, 1, 1 } },
|
||||||
{ 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, 1, 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, { '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 } },
|
||||||
|
Loading…
Reference in New Issue
Block a user