attempting to change the Socket class to invoke methods instead of relying on blocks

This commit is contained in:
hyunghwan.chung 2018-05-10 10:48:44 +00:00
parent ff5e5aa23f
commit 16b12e2dfc
3 changed files with 161 additions and 77 deletions

View File

@ -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
{
'CLIENT accepted ..............' dump.
clisck dump.
cliaddr dump.
## clisck close.
}
###self addEventListener: self. method acceptedSocketClass
{
^HttpSocket
} }
} }
@ -19,6 +37,7 @@ class HttpServer(Object)
method initialize method initialize
{ {
super initialize.
server_sockets := LinkedList new. server_sockets := LinkedList new.
} }

View File

@ -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.
]. ].
} }
@ -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
}
} }

View File

@ -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 } },