more async socket code
This commit is contained in:
@ -279,9 +279,9 @@ class Socket(AsyncHandle) from 'sck'
|
||||
{
|
||||
var eventActions.
|
||||
var pending_bytes, pending_offset, pending_length.
|
||||
var outreadysem, outdonesem, inreadysem.
|
||||
var outreadysem, outdonesem, inreadysem, connsem.
|
||||
|
||||
method(#primitive) _open(domain, type, proto).
|
||||
method(#primitive) open(domain, type, proto).
|
||||
method(#primitive) _close.
|
||||
method(#primitive) bind: addr.
|
||||
method(#primitive) _listen: backlog.
|
||||
@ -332,13 +332,14 @@ extend Socket
|
||||
self.outdonesem := Semaphore new.
|
||||
self.outreadysem := Semaphore new.
|
||||
self.inreadysem := Semaphore new.
|
||||
self.connsem := nil.
|
||||
|
||||
self.outdonesem signalAction: [ :xsem |
|
||||
self.outdonesem signalAction: [ :sem |
|
||||
(self.eventActions at: Socket.EventType.DATA_OUT) value: self.
|
||||
System unsignal: self.outreadysem.
|
||||
].
|
||||
|
||||
self.outreadysem signalAction: [ :xsem |
|
||||
self.outreadysem signalAction: [ :sem |
|
||||
| nwritten |
|
||||
nwritten := self _writeBytes: self.pending_bytes offset: self.pending_offset length: self.pending_length.
|
||||
if (nwritten >= 0)
|
||||
@ -350,44 +351,59 @@ extend Socket
|
||||
}
|
||||
].
|
||||
|
||||
self.inreadysem signalAction: [ :ysem |
|
||||
self.inreadysem signalAction: [ :sem |
|
||||
(self.eventActions at: Socket.EventType.DATA_IN) value: self.
|
||||
].
|
||||
}
|
||||
|
||||
method open(domain, type, proto)
|
||||
method finalize
|
||||
{
|
||||
| sck |
|
||||
sck := self _open(domain, type, proto).
|
||||
|
||||
if (self.handle >= 0)
|
||||
{
|
||||
System addAsyncSemaphore: self.outdonesem.
|
||||
System addAsyncSemaphore: self.outreadysem.
|
||||
}.
|
||||
|
||||
^sck
|
||||
'SOCKET FINALIZED...............' dump.
|
||||
self close.
|
||||
}
|
||||
|
||||
|
||||
method close
|
||||
{
|
||||
'Socket close' dump.
|
||||
System removeAsyncSemaphore: self.outdonesem.
|
||||
System removeAsyncSemaphore: self.outreadysem.
|
||||
|
||||
if (self.outdonesem notNil)
|
||||
{
|
||||
System unsignal: self.outdonesem.
|
||||
if (self.outdonesem _group notNil) { System removeAsyncSemaphore: self.outdonesem }.
|
||||
self.outdonesem := nil.
|
||||
}.
|
||||
|
||||
if (self.outreadysem notNil)
|
||||
{
|
||||
System unsignal: self.outreadysem.
|
||||
if (self.outreadysem _group notNil) { System removeAsyncSemaphore: self.outreadysem }.
|
||||
self.outreadysem := nil.
|
||||
}.
|
||||
|
||||
if (self.connsem notNil)
|
||||
{
|
||||
System unsignal: self.connsem.
|
||||
if (self.connsem _group notNil) { System removeAsyncSemaphore: self.connsem }.
|
||||
self.connsem := nil.
|
||||
}.
|
||||
|
||||
if (self.inreadysem notNil)
|
||||
{
|
||||
System unsignal: self.inreadysem.
|
||||
if (self.inreadysem _group notNil) { System removeAsyncSemaphore: self.inreadysem }.
|
||||
self.inreadysem := nil.
|
||||
}.
|
||||
|
||||
^super close.
|
||||
}
|
||||
### method listen: backlog do: acceptBlock
|
||||
### {
|
||||
### self.inputAction := acceptBlock.
|
||||
### self watchInput.
|
||||
### ^self _listen: backlog.
|
||||
### }
|
||||
|
||||
method onEvent: event_type do: action_block
|
||||
{
|
||||
self.eventActions at: event_type put: action_block.
|
||||
}
|
||||
|
||||
|
||||
|
||||
method connect: target
|
||||
{
|
||||
| sem |
|
||||
@ -395,49 +411,40 @@ extend Socket
|
||||
{
|
||||
sem := Semaphore new.
|
||||
sem signalAction: [ :xsem |
|
||||
| soerr dra |
|
||||
| soerr |
|
||||
soerr := self _socketError.
|
||||
if (soerr >= 0)
|
||||
{
|
||||
## finalize connection if not in progress
|
||||
'CHECKING FOR CONNECTION.....' dump.
|
||||
System unsignal: xsem.
|
||||
System removeAsyncSemaphore: xsem.
|
||||
|
||||
'CHECKING FOR CONNECTION.....' dump.
|
||||
(self.eventActions at: Socket.EventType.CONNECTED) value: self value: (soerr == 0).
|
||||
|
||||
if (soerr == 0)
|
||||
{
|
||||
if ((self.eventActions at: Socket.EventType.DATA_IN) notNil)
|
||||
{
|
||||
xsem signalAction: [ :ysem |
|
||||
(self.eventActions at: Socket.EventType.DATA_IN) value: self.
|
||||
].
|
||||
System addAsyncSemaphore: xsem.
|
||||
System signal: xsem onInput: self.handle.
|
||||
}.
|
||||
System addAsyncSemaphore: self.inreadysem.
|
||||
System signal: self.inreadysem onInput: self.handle.
|
||||
System addAsyncSemaphore: self.outdonesem.
|
||||
}.
|
||||
}.
|
||||
(* HOW TO HANDLE TIMEOUT? *)
|
||||
].
|
||||
|
||||
System addAsyncSemaphore: sem.
|
||||
System signal: sem onOutput: self.handle.
|
||||
self.connsem := sem.
|
||||
System addAsyncSemaphore: self.connsem.
|
||||
System signal: self.connsem onOutput: self.handle.
|
||||
}
|
||||
else
|
||||
{
|
||||
## connected immediately
|
||||
'IMMEDIATELY CONNECTED.....' dump.
|
||||
(self.eventActions at: Socket.EventType.CONNECTED) value: self value: true.
|
||||
if ((self.eventActions at: Socket.EventType.DATA_IN) notNil)
|
||||
{
|
||||
sem := Semaphore new.
|
||||
sem signalAction: [ :xsem |
|
||||
(self.eventActions at: Socket.EventType.DATA_IN) value: self.
|
||||
].
|
||||
System addAsyncSemaphore: sem.
|
||||
System signal: sem onInput: self.handle.
|
||||
}.
|
||||
|
||||
System addAsyncSemaphore: self.inreadysem.
|
||||
System signal: self.inreadysem onInput: self.handle.
|
||||
System addAsyncSemaphore: self.outdonesem.
|
||||
}
|
||||
}
|
||||
|
||||
@ -445,6 +452,11 @@ extend Socket
|
||||
{
|
||||
| n |
|
||||
|
||||
if (self.outreadysem _group notNil)
|
||||
{
|
||||
Exception signal: 'Not allowed to write again'.
|
||||
}.
|
||||
|
||||
## n >= 0: written
|
||||
## n <= -1: tolerable error (e.g. EAGAIN)
|
||||
## exception: fatal error
|
||||
@ -452,7 +464,7 @@ extend Socket
|
||||
##{
|
||||
n := self _writeBytes: bytes offset: offset length: length.
|
||||
if (n >= 0)
|
||||
{
|
||||
{
|
||||
self.outdonesem signal.
|
||||
^n
|
||||
}.
|
||||
@ -463,11 +475,31 @@ extend Socket
|
||||
self.pending_offset := offset.
|
||||
self.pending_length := length.
|
||||
|
||||
System addAsyncSemaphore: self.outreadysem.
|
||||
System signal: self.outreadysem onOutput: self.handle.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ServerSocket(Socket)
|
||||
{
|
||||
method initialize
|
||||
{
|
||||
super initialize.
|
||||
self.inreadysem := [ :sem |
|
||||
| xxx |
|
||||
System accept: xxx.
|
||||
].
|
||||
}
|
||||
|
||||
method listen: backlog
|
||||
{
|
||||
System addAsyncSemaphore: self.inreadysem.
|
||||
System signal: self.inreadysem onInput: self.handle.
|
||||
^self _listen: backlog.
|
||||
}
|
||||
}
|
||||
|
||||
class MyObject(Object)
|
||||
{
|
||||
method(#class) main
|
||||
@ -479,12 +511,18 @@ class MyObject(Object)
|
||||
[
|
||||
buf := ByteArray new: 128.
|
||||
s := Socket domain: Socket.Domain.INET type: Socket.Type.STREAM.
|
||||
s2 := ServerSocket domain: Socket.Domain.INET type: Socket.Type.STREAM.
|
||||
|
||||
s2 onEvent: Socket.EventType.DATA_IN do: [:sck |
|
||||
### accept...
|
||||
].
|
||||
|
||||
s onEvent: Socket.EventType.CONNECTED do: [ :sck :state |
|
||||
if (state)
|
||||
{
|
||||
'AAAAAAAA' dump.
|
||||
s writeBytes: #[ $a, $b, $c ]
|
||||
s writeBytes: #[ $a, $b, $c ].
|
||||
s writeBytes: #[ $d, $e, $f ].
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -496,7 +534,8 @@ class MyObject(Object)
|
||||
nbytes := s readBytes: buf.
|
||||
if (nbytes == 0)
|
||||
{
|
||||
sck close
|
||||
sck close.
|
||||
s := nil.
|
||||
}.
|
||||
('Got ' & (nbytes asString)) dump.
|
||||
buf dump.
|
||||
@ -517,7 +556,6 @@ class MyObject(Object)
|
||||
ensure:
|
||||
[
|
||||
if (s notNil) { s close }.
|
||||
if (s2 notNil) { s2 close }.
|
||||
]
|
||||
|
||||
] on: Exception do: [:ex | ('Exception - ' & ex messageText) dump ].
|
||||
|
Reference in New Issue
Block a user