2010-12-14 02:03:20 +00:00
|
|
|
"
|
2011-06-15 14:44:22 +00:00
|
|
|
(C) 2010-2011 by Holger Hans Peter Freyther
|
2010-12-14 02:03:20 +00:00
|
|
|
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/>.
|
|
|
|
"
|
|
|
|
|
2010-11-14 21:43:29 +00:00
|
|
|
PackageLoader fileInPackage: 'OsmoNetwork'.
|
|
|
|
|
2010-11-20 08:35:12 +00:00
|
|
|
Object subclass: SCCPConnection [
|
2010-11-29 15:53:00 +00:00
|
|
|
| src dst queue conManager confirmSem proc state |
|
|
|
|
|
|
|
|
SCCPConnection class >> stateInitial [ ^ 0 ]
|
|
|
|
SCCPConnection class >> stateConnected [ ^ 1 ]
|
|
|
|
SCCPConnection class >> stateReleased [ ^ 2 ]
|
2010-12-16 20:20:35 +00:00
|
|
|
SCCPConnection class >> stateReleaseComplete [ ^ 3 ]
|
2010-11-29 15:53:00 +00:00
|
|
|
SCCPConnection class >> stateTimeout [ ^ 3 ]
|
2010-11-28 20:14:25 +00:00
|
|
|
|
|
|
|
SCCPConnection class >> new [
|
|
|
|
^ super new
|
|
|
|
initialize; yourself
|
|
|
|
]
|
|
|
|
|
|
|
|
initialize [
|
2010-11-29 15:53:00 +00:00
|
|
|
state := SCCPConnection stateInitial.
|
2010-11-28 20:14:25 +00:00
|
|
|
confirmSem := Semaphore new.
|
2010-11-29 15:53:00 +00:00
|
|
|
queue := SharedQueue new.
|
2010-11-28 20:14:25 +00:00
|
|
|
]
|
|
|
|
|
2011-06-15 14:44:22 +00:00
|
|
|
conManager [
|
|
|
|
<category: 'accessing'>
|
|
|
|
^ conManager
|
|
|
|
]
|
|
|
|
|
2010-11-28 22:40:54 +00:00
|
|
|
conManager: aHandler [
|
2010-11-28 20:14:25 +00:00
|
|
|
<category: 'private'>
|
2010-11-28 22:40:54 +00:00
|
|
|
conManager := aHandler.
|
|
|
|
]
|
|
|
|
|
|
|
|
readQueue [
|
|
|
|
<category: 'private'>
|
2010-11-29 15:53:00 +00:00
|
|
|
^ queue
|
2010-11-28 20:14:25 +00:00
|
|
|
]
|
2010-11-20 08:35:12 +00:00
|
|
|
|
|
|
|
srcRef [
|
2010-11-28 20:14:25 +00:00
|
|
|
<category: 'access'>
|
2010-11-20 08:35:12 +00:00
|
|
|
^ src
|
|
|
|
]
|
|
|
|
srcRef: aRef [
|
2010-11-28 20:14:25 +00:00
|
|
|
<category: 'access'>
|
2010-11-20 08:35:12 +00:00
|
|
|
src := aRef
|
|
|
|
]
|
|
|
|
|
|
|
|
dstRef: aRef [
|
2010-11-28 20:14:25 +00:00
|
|
|
<category: 'access'>
|
2010-11-20 08:35:12 +00:00
|
|
|
dst := aRef
|
|
|
|
]
|
2010-11-22 16:16:44 +00:00
|
|
|
|
2010-11-28 09:14:15 +00:00
|
|
|
dstRef [
|
2010-11-28 20:14:25 +00:00
|
|
|
<category: 'access'>
|
2010-11-28 09:14:15 +00:00
|
|
|
^ dst
|
|
|
|
]
|
|
|
|
|
2010-11-29 15:53:00 +00:00
|
|
|
next [
|
|
|
|
"Read the next item. If the connection is terminated"
|
|
|
|
| msg |
|
2010-11-28 20:14:25 +00:00
|
|
|
|
2010-11-29 15:53:00 +00:00
|
|
|
"If we are not connected we need to wait"
|
|
|
|
state = SCCPConnection stateInitial
|
|
|
|
ifTrue: [
|
2010-11-28 20:14:25 +00:00
|
|
|
self waitForConfirmation.
|
2010-11-29 15:53:00 +00:00
|
|
|
].
|
2010-11-28 20:27:26 +00:00
|
|
|
|
2010-11-29 15:53:00 +00:00
|
|
|
"If we are not connected here. Send a EndOfStream signal"
|
2010-12-15 15:24:45 +00:00
|
|
|
(state > SCCPConnection stateConnected and: [self readQueue isEmpty])
|
|
|
|
ifTrue: [
|
2010-11-29 15:53:00 +00:00
|
|
|
^ SystemExceptions.EndOfStream signal
|
|
|
|
].
|
2010-11-28 20:14:25 +00:00
|
|
|
|
2010-11-29 15:53:00 +00:00
|
|
|
msg := self readQueue next.
|
2010-11-28 20:14:25 +00:00
|
|
|
|
2010-11-29 15:53:00 +00:00
|
|
|
"If this is a small integer our connection is gone"
|
|
|
|
(msg isKindOf: SmallInteger)
|
|
|
|
ifTrue: [
|
|
|
|
^ SystemExceptions.EndOfStream signal
|
|
|
|
].
|
|
|
|
|
|
|
|
"We do have a real message"
|
|
|
|
^ msg
|
2010-11-28 20:14:25 +00:00
|
|
|
]
|
|
|
|
|
2010-11-29 18:49:39 +00:00
|
|
|
nextPutData: aMsg [
|
|
|
|
| dt1 |
|
|
|
|
dt1 := Osmo.SCCPConnectionData initWith: self dstRef data: aMsg.
|
|
|
|
self nextPut: dt1 toMessage.
|
|
|
|
]
|
|
|
|
|
2010-11-29 15:53:00 +00:00
|
|
|
nextPut: aMsg [
|
|
|
|
conManager sendMsg: aMsg.
|
|
|
|
]
|
2010-11-28 20:14:25 +00:00
|
|
|
|
|
|
|
waitForConfirmation [
|
2010-11-28 20:27:26 +00:00
|
|
|
"Wait for the connection to be confirmed and then exit"
|
|
|
|
|
|
|
|
((Delay forSeconds: 10) timedWaitOn: confirmSem)
|
|
|
|
ifTrue: [
|
2010-11-29 15:53:00 +00:00
|
|
|
state := SCCPConnection stateTimeout.
|
2010-11-28 22:40:54 +00:00
|
|
|
conManager connectionTimeout: self.
|
2010-11-28 20:27:26 +00:00
|
|
|
^ false
|
|
|
|
].
|
|
|
|
|
|
|
|
^ true
|
2010-11-28 20:14:25 +00:00
|
|
|
]
|
|
|
|
|
2010-11-29 15:53:00 +00:00
|
|
|
|
|
|
|
"SCCP Connection state handling"
|
|
|
|
terminate [
|
|
|
|
self readQueue nextPut: 0.
|
|
|
|
]
|
|
|
|
|
2010-11-28 09:44:50 +00:00
|
|
|
confirm: aCC [
|
|
|
|
<category: 'connection-handling'>
|
2010-11-28 20:14:25 +00:00
|
|
|
self dstRef: aCC src.
|
2010-11-29 15:53:00 +00:00
|
|
|
state := SCCPConnection stateConnected.
|
2010-11-28 20:14:25 +00:00
|
|
|
confirmSem signal.
|
2010-11-28 09:44:50 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
data: aDT [
|
2010-11-28 20:14:25 +00:00
|
|
|
self readQueue nextPut: aDT data.
|
2010-11-28 09:44:50 +00:00
|
|
|
]
|
|
|
|
|
2010-12-16 20:10:20 +00:00
|
|
|
release [
|
|
|
|
| rlsd |
|
|
|
|
|
|
|
|
state := SCCPConnection stateReleased.
|
|
|
|
rlsd := Osmo.SCCPConnectionReleased initWithDst: self dstRef src: self srcRef cause: 0.
|
|
|
|
self nextPut: rlsd toMessage.
|
|
|
|
]
|
|
|
|
|
|
|
|
releaseComplete: aMSG [
|
|
|
|
"TODO: verify that we are in the right state"
|
2010-12-16 20:20:35 +00:00
|
|
|
state := SCCPConnection stateReleaseComplete.
|
2010-12-16 20:10:20 +00:00
|
|
|
self terminate.
|
|
|
|
]
|
|
|
|
|
2010-11-28 09:44:50 +00:00
|
|
|
released: aRLSD [
|
2010-11-28 20:14:25 +00:00
|
|
|
| rlc |
|
2010-11-28 09:44:50 +00:00
|
|
|
"Give up local resources here. We are done."
|
2010-11-28 20:14:25 +00:00
|
|
|
|
2010-12-16 20:20:35 +00:00
|
|
|
state := SCCPConnection stateReleaseComplete.
|
2010-11-28 20:14:25 +00:00
|
|
|
rlc := Osmo.SCCPConnectionReleaseComplete
|
|
|
|
initWithDst: aRLSD src src: aRLSD dst.
|
2010-11-29 15:53:00 +00:00
|
|
|
self nextPut: rlc toMessage.
|
2010-11-28 20:27:26 +00:00
|
|
|
self terminate.
|
|
|
|
]
|
2010-12-16 20:10:20 +00:00
|
|
|
|
|
|
|
state [ <category: 'accessing'> ^ state ]
|
2010-11-20 08:35:12 +00:00
|
|
|
]
|
|
|
|
|
2010-11-22 16:13:26 +00:00
|
|
|
Object subclass: MSGParser [
|
|
|
|
<comment: 'I take a SCCP message and recursively parse all the data'>
|
|
|
|
|
|
|
|
MSGParser class >> parse: aByteArray [
|
|
|
|
| sccp |
|
|
|
|
"Return a completely decoded subtree"
|
|
|
|
|
|
|
|
sccp := Osmo.SCCPMessage decode: aByteArray.
|
|
|
|
(sccp respondsTo: #data)
|
|
|
|
ifTrue: [
|
|
|
|
sccp data: (self decodeBSSAP: sccp data).
|
|
|
|
].
|
|
|
|
|
|
|
|
^ sccp
|
|
|
|
]
|
|
|
|
|
|
|
|
MSGParser class >> decodeBSSAP: aData [
|
|
|
|
| bssap |
|
|
|
|
bssap := BSSAPMessage decode: aData.
|
2010-11-24 14:17:10 +00:00
|
|
|
bssap class msgType = BSSAPDTAP msgType
|
2010-11-22 16:13:26 +00:00
|
|
|
ifTrue: [
|
2010-11-24 14:17:10 +00:00
|
|
|
bssap data: (GSM48MSG decode: bssap data)
|
|
|
|
]
|
|
|
|
ifFalse: [
|
2010-11-22 16:13:26 +00:00
|
|
|
bssap data: (self decodeBSSMAP: bssap data).
|
2010-11-24 14:17:10 +00:00
|
|
|
].
|
2010-11-22 16:13:26 +00:00
|
|
|
|
|
|
|
^ bssap
|
|
|
|
]
|
|
|
|
|
|
|
|
MSGParser class >> decodeBSSMAP: aData [
|
|
|
|
| bssmap |
|
|
|
|
bssmap := IEMessage decode: aData with: GSM0808IE.
|
2010-11-23 23:41:38 +00:00
|
|
|
bssmap findIE: (GSMLayer3Info elementId) ifPresent: [:each |
|
|
|
|
each data: (GSM48MSG decode: each data).
|
|
|
|
].
|
2010-11-22 16:13:26 +00:00
|
|
|
^ bssmap
|
|
|
|
]
|
|
|
|
|
|
|
|
]
|
|
|
|
|
2011-06-15 14:44:22 +00:00
|
|
|
|
|
|
|
Osmo.SCCPMessage extend [
|
|
|
|
sccpHandlerDispatchOn: aCon [
|
|
|
|
"Message is not handled here"
|
|
|
|
self logError: 'Unhandled SCCP packet %1' % {self class} area: #sccp.
|
|
|
|
^ false
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
Osmo.SCCPConnectionConfirm extend [
|
|
|
|
sccpHandlerDispatchOn: aCon [
|
|
|
|
aCon confirm: self.
|
|
|
|
^ true
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
Osmo.SCCPConnectionData extend [
|
|
|
|
sccpHandlerDispatchOn: aCon [
|
|
|
|
aCon data: self.
|
|
|
|
^ true
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
Osmo.SCCPConnectionReleased extend [
|
|
|
|
sccpHandlerDispatchOn: aCon [
|
|
|
|
aCon released: self.
|
|
|
|
aCon conManager removeConnection: aCon.
|
|
|
|
^ true
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
Osmo.SCCPConnectionReleaseComplete extend [
|
|
|
|
sccpHandlerDispatchOn: aCon [
|
|
|
|
aCon releaseComplete: self.
|
|
|
|
aCon conManager removeConnection: aCon.
|
|
|
|
^ true
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2010-11-24 09:58:30 +00:00
|
|
|
Object subclass: SCCPHandler [
|
2010-12-17 21:03:13 +00:00
|
|
|
| connections last_ref connection sem |
|
2010-11-14 21:43:29 +00:00
|
|
|
<comment: 'I handle SCCP messages'>
|
|
|
|
|
2010-12-17 21:03:13 +00:00
|
|
|
SCCPHandler class >> new [
|
|
|
|
^ super new initialize; yourself
|
|
|
|
]
|
|
|
|
|
|
|
|
initialize [
|
|
|
|
sem := Semaphore forMutualExclusion.
|
|
|
|
]
|
|
|
|
|
2010-12-16 20:24:22 +00:00
|
|
|
addConnection: aConnection [
|
2010-12-17 21:03:13 +00:00
|
|
|
sem critical: [
|
|
|
|
self connections add: aConnection.
|
|
|
|
aConnection srcRef: self assignSrcRef.
|
|
|
|
].
|
2010-12-16 20:24:22 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
removeConnection: aConnection [
|
|
|
|
self connections remove: aConnection.
|
2010-12-17 21:03:13 +00:00
|
|
|
|
2010-12-16 20:24:22 +00:00
|
|
|
]
|
|
|
|
|
2010-11-14 21:43:29 +00:00
|
|
|
registerOn: aDispatcher [
|
|
|
|
aDispatcher addHandler: Osmo.IPAConstants protocolSCCP
|
2010-11-15 15:26:00 +00:00
|
|
|
on: self with: #handleMsg:.
|
2010-11-14 21:43:29 +00:00
|
|
|
]
|
|
|
|
|
2010-11-28 20:27:26 +00:00
|
|
|
connectionTimeout: aConnection [
|
2010-12-17 21:07:45 +00:00
|
|
|
self logError: 'SCCP Connection %1 timedout' % {aConnection srcRef} area: #sccp.
|
2010-12-17 21:03:13 +00:00
|
|
|
sem critical: [
|
|
|
|
self removeConnection: aConnection.
|
|
|
|
]
|
2010-11-28 20:27:26 +00:00
|
|
|
]
|
|
|
|
|
2011-06-15 14:44:22 +00:00
|
|
|
forwardMessage: aMessage with: aConnection [
|
|
|
|
^ aMessage sccpHandlerDispatchOn: aConnection.
|
2010-11-28 09:44:50 +00:00
|
|
|
|
|
|
|
]
|
2010-11-28 09:14:15 +00:00
|
|
|
|
2010-11-28 09:44:50 +00:00
|
|
|
dispatchMessage: aMessage [
|
2010-12-17 21:03:13 +00:00
|
|
|
sem critical: [
|
|
|
|
self connections do: [:each |
|
|
|
|
each srcRef = aMessage dst
|
|
|
|
ifTrue: [
|
|
|
|
^ self forwardMessage: aMessage with: each.
|
|
|
|
].
|
|
|
|
]
|
2010-11-28 09:44:50 +00:00
|
|
|
].
|
|
|
|
|
2010-12-17 21:07:45 +00:00
|
|
|
self logError: 'No one handled connection %1' % {aMessage dst} area: #sccp.
|
2010-11-28 09:14:15 +00:00
|
|
|
]
|
|
|
|
|
2010-12-16 20:10:20 +00:00
|
|
|
dissectMSG: aMsg [
|
|
|
|
^ MSGParser parse: (aMsg asByteArray).
|
|
|
|
]
|
|
|
|
|
|
|
|
newConnection: aCon [
|
|
|
|
"Interesting for subclasses"
|
|
|
|
]
|
|
|
|
|
|
|
|
confirmConnection: aMsg [
|
|
|
|
| con res |
|
|
|
|
con := SCCPConnection new.
|
|
|
|
con conManager: self.
|
2010-12-16 20:24:22 +00:00
|
|
|
self addConnection: con.
|
2010-12-16 20:10:20 +00:00
|
|
|
|
|
|
|
"Confirm the messga now and send any data"
|
|
|
|
con confirm: aMsg.
|
|
|
|
aMsg data ifNotNil: [
|
|
|
|
con data: aMsg.
|
|
|
|
].
|
|
|
|
|
|
|
|
"Confirm it without sending any new data bad"
|
|
|
|
res := Osmo.SCCPConnectionConfirm initWithSrc: (con srcRef) dst: (con dstRef).
|
|
|
|
self sendMsg: res toMessage.
|
|
|
|
|
|
|
|
self newConnection: con.
|
|
|
|
^ con.
|
|
|
|
]
|
|
|
|
|
2010-11-15 15:26:00 +00:00
|
|
|
handleMsg: aMsg [
|
2010-11-24 09:58:30 +00:00
|
|
|
| sccp |
|
|
|
|
|
|
|
|
[
|
2010-12-16 20:10:20 +00:00
|
|
|
sccp := self dissectMSG: aMsg asByteArray.
|
2010-11-24 09:58:30 +00:00
|
|
|
] on: Exception do: [
|
|
|
|
self logError: 'Failed to parse message' area: #sccp.
|
2010-12-15 15:05:46 +00:00
|
|
|
aMsg toMessageOrByteArray printNl.
|
2010-11-28 09:14:15 +00:00
|
|
|
^ false
|
|
|
|
].
|
|
|
|
|
2010-12-16 20:10:20 +00:00
|
|
|
(sccp isKindOf: Osmo.SCCPConnectionRequest) ifTrue: [
|
|
|
|
self logNotice: 'New incoming connection' area: #sccp.
|
|
|
|
self confirmConnection: sccp.
|
|
|
|
^ true
|
|
|
|
].
|
|
|
|
|
2011-05-18 21:37:17 +00:00
|
|
|
(sccp isKindOf: Osmo.SCCPUDT) ifTrue: [
|
|
|
|
self handleUDT: sccp.
|
|
|
|
^ true
|
|
|
|
].
|
|
|
|
|
2010-11-28 09:44:50 +00:00
|
|
|
self dispatchMessage: sccp.
|
2010-11-14 21:43:29 +00:00
|
|
|
]
|
2010-11-20 08:35:12 +00:00
|
|
|
|
2011-05-18 21:37:17 +00:00
|
|
|
handleUDT: aSCCP [
|
|
|
|
self logNotice: 'Incomind UDT message' area: #sccp.
|
|
|
|
]
|
|
|
|
|
2010-11-28 20:14:25 +00:00
|
|
|
|
|
|
|
connection: aConnection [
|
|
|
|
connection := aConnection.
|
|
|
|
]
|
|
|
|
|
|
|
|
sendMsg: aMsg [
|
|
|
|
"Send a SCCP message."
|
|
|
|
connection send: aMsg with: Osmo.IPAConstants protocolSCCP.
|
|
|
|
]
|
|
|
|
|
2010-11-20 08:35:12 +00:00
|
|
|
createConnection: aData [
|
|
|
|
| con res|
|
|
|
|
|
|
|
|
con := SCCPConnection new.
|
2010-11-28 22:40:54 +00:00
|
|
|
con conManager: self.
|
2010-12-17 20:53:53 +00:00
|
|
|
self addConnection: con.
|
|
|
|
|
|
|
|
"Send the confirmation now"
|
2010-11-20 08:35:12 +00:00
|
|
|
res := Osmo.SCCPConnectionRequest
|
|
|
|
initWith: (con srcRef) dest: (Osmo.SCCPAddress createWith: 254) data: aData.
|
2010-11-29 15:53:00 +00:00
|
|
|
self sendMsg: res toMessage.
|
2010-11-20 08:35:12 +00:00
|
|
|
|
2010-11-29 15:53:00 +00:00
|
|
|
^ con
|
2010-11-20 08:35:12 +00:00
|
|
|
]
|
|
|
|
|
2010-11-28 22:55:52 +00:00
|
|
|
referenceIsFree: aRef [
|
|
|
|
<category: 'private'>
|
|
|
|
self connections do: [:each |
|
|
|
|
each srcRef = aRef
|
|
|
|
ifTrue: [
|
|
|
|
^ false
|
|
|
|
].
|
|
|
|
].
|
|
|
|
|
|
|
|
^ true
|
|
|
|
]
|
|
|
|
|
2010-11-20 08:35:12 +00:00
|
|
|
assignSrcRef [
|
2010-11-28 22:55:52 +00:00
|
|
|
"Find a free SCCP reference"
|
|
|
|
1 to: 16rFFFFFE do: [:dummy |
|
|
|
|
| ref |
|
|
|
|
ref := Random between: 1 and: 16rFFFFFE.
|
|
|
|
(self referenceIsFree: ref)
|
|
|
|
ifTrue: [
|
|
|
|
^ ref.
|
|
|
|
].
|
|
|
|
].
|
|
|
|
|
|
|
|
self error: 'No free SCCP Connection. Close some'.
|
2010-11-20 08:35:12 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
connections [
|
|
|
|
^ connections ifNil: [ connections := OrderedCollection new. ]
|
|
|
|
]
|
2010-11-14 21:43:29 +00:00
|
|
|
]
|
|
|
|
|