added SocketAddress>>family

added Socket>>readBytes:offset:length:
started writing Http.moo
This commit is contained in:
hyunghwan.chung
2018-05-09 10:37:07 +00:00
parent 82160e03dd
commit bc93856b35
4 changed files with 267 additions and 148 deletions

190
moo/kernel/Http.moo Normal file
View 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.
}
}

View File

@ -216,9 +216,9 @@ class(#byte(16)) IP6Address(IP4Address)
class(#byte) SocketAddress(Object) from 'sck.addr'
{
##method(#primitive) family.
method(#primitive) family.
method(#primitive) fromString: str.
method(#class) 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 internal representation used by various modules. (e.g. sck)
var(#get) handle := -1.
var(#get) closedEventAction := nil.
##method initialize
##{
@ -242,9 +243,25 @@ class AsyncHandle(Object)
{
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.
@ -264,7 +281,7 @@ class Socket(AsyncHandle) from 'sck'
var pending_bytes, pending_offset, pending_length.
var outreadysem, outdonesem, inreadysem.
method(#primitive) open(domain, type, proto).
method(#primitive) open(family, type, proto).
method(#primitive) _close.
method(#primitive) bind: addr.
method(#primitive) _listen: backlog.
@ -273,12 +290,13 @@ class Socket(AsyncHandle) from 'sck'
method(#primitive) _socketError.
method(#primitive) readBytes: bytes.
method(#primitive) readBytes: bytes offset: offset length: length.
method(#primitive) _writeBytes: bytes.
method(#primitive) _writeBytes: bytes offset: offset length: length.
}
(* TODO: generate these domain and type from the C header *)
pooldic Socket.Domain
(* TODO: generate these family and type from the C header *)
pooldic Socket.Family
{
INET := 2.
INET6 := 10.
@ -295,9 +313,9 @@ extend Socket
method(#class) new { 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
@ -351,8 +369,6 @@ extend Socket
method close
{
'Socket close' dump.
if (self.outdonesem notNil)
{
System unsignal: self.outdonesem.
@ -390,7 +406,7 @@ extend Socket
}
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.
}
}
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.
}
}