From 16b12e2dfc42e169be26da52daa87999cb30da6e Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Thu, 10 May 2018 10:48:44 +0000 Subject: [PATCH] attempting to change the Socket class to invoke methods instead of relying on blocks --- moo/kernel/Http.moo | 31 ++++++-- moo/kernel/Socket.moo | 180 ++++++++++++++++++++++++++---------------- moo/mod/sck.c | 27 ++++++- 3 files changed, 161 insertions(+), 77 deletions(-) diff --git a/moo/kernel/Http.moo b/moo/kernel/Http.moo index 9018973..5982594 100644 --- a/moo/kernel/Http.moo +++ b/moo/kernel/Http.moo @@ -1,15 +1,33 @@ ###include 'Moo.moo'. #include 'Socket.moo'. +class HttpSocket(Socket) +{ + method onSocketDataIn + { + 'CLIENT got DATA' dump. + self close. + } +} + class HttpServerSocket(ServerSocket) { - method(#class) initialize + method initialize { - self onEvent: #accepted do: [ - - ]. - - ###self addEventListener: self. + super initialize. + } + + method onSocketAccepted: clisck from: cliaddr + { + 'CLIENT accepted ..............' dump. +clisck dump. + cliaddr dump. + ## clisck close. + } + + method acceptedSocketClass + { + ^HttpSocket } } @@ -19,6 +37,7 @@ class HttpServer(Object) method initialize { + super initialize. server_sockets := LinkedList new. } diff --git a/moo/kernel/Socket.moo b/moo/kernel/Socket.moo index 6215588..4f8a122 100644 --- a/moo/kernel/Socket.moo +++ b/moo/kernel/Socket.moo @@ -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 internal representation used by various modules. (e.g. sck) var(#get) handle := -1. - var(#get) closedEventAction := nil. - ##method initialize - ##{ - ## ^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) closedEventAction. var(#get) dataInEventAction. var(#get) dataOutEventAction. @@ -282,6 +240,10 @@ class Socket(AsyncHandle) from 'sck' var outreadysem, outdonesem, inreadysem. 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) bind: addr. method(#primitive) _listen: backlog. @@ -313,11 +275,27 @@ extend Socket method(#class) new { 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 { - ^(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 { super initialize. @@ -327,8 +305,11 @@ extend Socket self.inreadysem := Semaphore new. self.outdonesem signalAction: [ :sem | - self.dataOutEventAction value: self. - ##(self.eventActions at: Socket.EventType.DATA_OUT) value: self. + ##if (self.dataOutEventAction notNil) + ##{ + ## self.dataOutEventAction value: self. + ##}. + self onSocketDataOut. System unsignal: self.outreadysem. ]. @@ -356,8 +337,8 @@ extend Socket ]. 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. self close. } - + method close { if (self.outdonesem notNil) @@ -390,13 +371,26 @@ extend Socket 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 { - if (event_type == #data_in) + if (event_type == #closed) + { + self.closedEventAction := action_block. + } + elsif (event_type == #data_in) { self.dataInEventAction := action_block. } @@ -406,10 +400,17 @@ extend Socket } 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 { | n pos rem | @@ -448,11 +449,22 @@ extend Socket 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 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 }. }. (* HOW TO HANDLE TIMEOUT? *) @@ -516,13 +529,18 @@ class ClientSocket(Socket) { ## connected immediately 'IMMEDIATELY CONNECTED.....' dump. - self.connectedEventAction value: self value: true. + ###self.connectedEventAction value: self value: true. + self onSocketConnected: true. System addAsyncSemaphore: self.inreadysem. System signal: self.inreadysem onInput: self.handle. System addAsyncSemaphore: self.outdonesem. } } + + method onSocketConnected + { + } } class ServerSocket(Socket) @@ -535,22 +553,36 @@ class ServerSocket(Socket) super initialize. self.inreadysem signalAction: [ :sem | - | cliaddr clisck cliact | + | cliaddr clisck cliact fd | 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. - if (clisck notNil) + if (clisck notNil) ## if nil, _accept: failed with EWOULDBLOCK/EAGAIN. { ## the _accept method doesn't invoke the initialize method. ## i should invoke it manually here. clisck initialize. + clisck beWatched. + self onSocketAccepted: clisck from: cliaddr. - if (self.acceptedEventAction notNil) - { - self.acceptedEventAction value: self value: clisck value: cliaddr. - clisck beWatched. - } - else { clisck close }. + ###if (self.acceptedEventAction notNil) + ####{ + ### clisck beWatched. + ### self.acceptedEventAction value: self value: clisck value: cliaddr. + ### clisck beWatched. + ###} + ###else { clisck close }. }. + ---------------------------*) ]. } @@ -584,4 +616,14 @@ class ServerSocket(Socket) System signal: self.inreadysem onInput: self.handle. ^self _listen: backlog. } + + method onSocketAccepted: clisck from: cliaddr + { + clisck close. + } + + method acceptedSocketClass + { + ^Socket + } } diff --git a/moo/mod/sck.c b/moo/mod/sck.c index d18af8f..b94d908 100644 --- a/moo/mod/sck.c +++ b/moo/mod/sck.c @@ -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)) ); + 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); 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)); @@ -266,6 +275,7 @@ normal_accept: #endif if (fcntl(newfd, F_SETFL, fl) == -1) goto fcntl_failure; +#if 0 accept_done: /*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); @@ -289,6 +299,19 @@ accept_done: * method should call application-level initializer. */ MOO_STACK_SETRET (moo, nargs, (moo_oop_t)newsck); 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) @@ -568,7 +591,7 @@ static moo_pfinfo_t pfinfos[] = { 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, { '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',':','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 } },