166 lines
4.9 KiB
Smalltalk
166 lines
4.9 KiB
Smalltalk
"
|
|
(C) 2011-2013 by Holger Hans Peter Freyther
|
|
All Rights Reserved
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as
|
|
published by the Free Software Foundation, either version 3 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
"
|
|
|
|
Object subclass: OsmoStreamSocketBase [
|
|
| socket hostname port tx_proc rx_proc started |
|
|
|
|
<category: 'OsmoNetwork-Socket'>
|
|
<comment: 'I am the base class for streaming related sockets. I help with
|
|
supervising the RX/TX process and re-starting.'>
|
|
|
|
OsmoStreamSocketBase class >> connectionException [
|
|
<category: 'pharo-porting'>
|
|
^ SystemExceptions.FileError
|
|
]
|
|
|
|
hostname: aHostname [
|
|
<category: 'creation'>
|
|
hostname := aHostname
|
|
]
|
|
|
|
port: aPort [
|
|
<category: 'creation'>
|
|
port := aPort
|
|
]
|
|
|
|
hostname [
|
|
<category: 'accessing'>
|
|
^hostname
|
|
]
|
|
|
|
port [
|
|
<category: 'accessing'>
|
|
^port
|
|
]
|
|
|
|
targetDescription [
|
|
<category: 'accessing'>
|
|
^(WriteStream on: String new)
|
|
nextPutAll: hostname;
|
|
nextPut: $:;
|
|
nextPutAll: port asString;
|
|
contents
|
|
]
|
|
|
|
connect [
|
|
<category: 'connect'>
|
|
socket ifNotNil: [socket close].
|
|
socket := self createConnection: hostname port: port
|
|
]
|
|
|
|
start [
|
|
<category: 'connect'>
|
|
started := true.
|
|
|
|
[
|
|
self logNotice: ('Attempting to connect to ',
|
|
self targetDescription) area: #osmo.
|
|
self connect
|
|
] on: self class connectionException do: [
|
|
self logError: ('Failed to connect to ',
|
|
self targetDescription) area: #osmo.
|
|
^Osmo.TimerScheduler instance scheduleInSeconds: 1 block: [self reconnect]].
|
|
|
|
rx_proc :=
|
|
[Processor activeProcess name: 'OsmoAppConnection-RX ', self targetDescription.
|
|
[self driveDispatch] repeat] fork.
|
|
tx_proc := [Processor activeProcess name: 'OsmoAppConnection-TX ', self targetDescription.
|
|
[self driveSend] repeat] fork
|
|
]
|
|
|
|
stop [
|
|
<category: 'connect'>
|
|
started := false.
|
|
self terminate
|
|
"A reconnect timer might be running right now"
|
|
]
|
|
|
|
terminate [
|
|
<category: 'connect'>
|
|
tx_proc ifNotNil: [tx_proc terminate].
|
|
rx_proc ifNotNil: [rx_proc terminate].
|
|
socket ifNotNil:
|
|
[[socket close.] ensure: [ socket := nil ]].
|
|
]
|
|
|
|
driveDispatch [
|
|
<category: 'private'>
|
|
|
|
[
|
|
self dispatchOne
|
|
] on: SystemExceptions.EndOfStream do: [:e |
|
|
self logError: ('OsmoApplication dispatch eof on ',
|
|
self targetDescription) area: #osmo.
|
|
self scheduleReconnect
|
|
] on: SystemExceptions.FileError do: [:e |
|
|
self logError: ('OsmoApplication dispatch file-error on ',
|
|
self targetDescription) area: #osmo.
|
|
self scheduleReconnect
|
|
] on: Error do: [:e |
|
|
e logException: ('OsmoApplication dispatch error on ',
|
|
self targetDescription) area: #osmo.
|
|
self scheduleReconnect
|
|
]
|
|
]
|
|
|
|
driveSend [
|
|
<category: 'private'>
|
|
[
|
|
self sendOne
|
|
] on: SystemExceptions.EndOfStream do: [:e |
|
|
self logError: ('OsmoApplication send eof on ',
|
|
self targetDescription) area: #osmo.
|
|
self scheduleReconnect
|
|
] on: Error do: [:e |
|
|
e logException: ('OsmoApplication send error on ',
|
|
self targetDescription) area: #osmo.
|
|
self scheduleReconnect
|
|
]
|
|
]
|
|
|
|
reconnect [
|
|
<category: 'private'>
|
|
self logNotice: ('Going to reconnect socket to ', self targetDescription) area: #osmo.
|
|
self terminate.
|
|
started ifTrue: [self start]
|
|
]
|
|
|
|
scheduleReconnect [
|
|
<category: 'private'>
|
|
socket ifNotNil: [socket close. socket := nil].
|
|
TimerScheduler instance scheduleInSeconds: 1 block: [self reconnect].
|
|
"We are done now"
|
|
Processor activeProcess terminate
|
|
]
|
|
|
|
createConnection: aHostname port: aPort [
|
|
<category: 'internal'>
|
|
self subclassResponsibility
|
|
]
|
|
|
|
dispatchOne [
|
|
<category: 'internal'>
|
|
self subclassResponsibility
|
|
]
|
|
|
|
sendOne [
|
|
<category: 'internal'>
|
|
self subclassResponsibility
|
|
]
|
|
]
|