smalltalk
/
osmo-st-msc
Archived
1
0
Fork 0
This repository has been archived on 2022-02-17. You can view files and clone it, but cannot push or open issues or pull requests.
osmo-st-msc/src/MSC.st

324 lines
8.7 KiB
Smalltalk

"
(C) 2010-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/>.
"
PackageLoader
fileInPackage: 'OsmoMGCP';
fileInPackage: 'OsmoSIP'.
Object subclass: MSCConfig [
| ip port mgcp sip_ip sip_port |
<category: 'OsmoMSC-MSC'>
<comment: 'I contain a very simple MSC config for IP based BSCs'>
bscIP: aIP [
<category: 'config'>
ip := aIP
]
bscIP [
<category: 'accessing'>
^ ip
]
bscPort: aPort [
<category: 'config'>
port := aPort
]
bscPort [
<category: 'accessing'>
^ port
]
mgcpIP: aIP [
<category: 'config'>
mgcp := aIP
]
mgcpIP [
<category: 'accessing'>
^ mgcp ifNil: [ip]
]
sipIP: aIP [
<category: 'config'>
sip_ip := aIP
]
sipIP [
<category: 'accessing'>
^ sip_ip ifNil: [ip]
]
sipPort: aPort [
<category: 'config'>
sip_port := aPort
]
sipPort [
<category: 'accessing'>
^ sip_port ifNil: [5061]
]
]
Object subclass: MSCBSCConnectionHandler [
| msc connections |
<category: 'OsmoMSC-MSC'>
<comment: 'I take incoming connections, find a handler for them and
will register them. I will be passed to the BSCListener'>
MSCBSCConnectionHandler class >> initWith: aMSC [
^ self new
instVarNamed: #msc put: aMSC; yourself
]
connections [ ^ connections ifNil: [connections := OrderedCollection new]]
setupConnection: aConnection on: aConfig [
| bsc |
self logNotice: 'BSC-Socket: New Connection for lac', (aConfig lac asString)
area: #bsc.
"Create the BSC first and then assume it is present"
[
bsc := BSCIPAConnection createOn: aConnection withConfig: aConfig msc: msc.
] on: Exception do: [:ex |
ex logException: 'BSC: Creating a handler failed.' area: #bsc.
aConnection close.
^ false
].
[
Processor activeProcess name: 'MSCBSCConnectionHandler(%1)' % {aConfig lac}.
[[
aConfig connection: bsc.
self connections add: bsc.
bsc process.
] on: SystemExceptions.EndOfStream do: [:ex |
aConfig connection: nil.
self logNotice: 'BSC disconnected for lac: %1' % {aConfig lac}
area: #bsc.
] on: Exception do: [:ex |
self logError: 'Unexpected exception for lac: %1' % {aConfig lac}
area: #bsc.
thisContext backtraceOn: Transcript.
]] ensure: [
self logNotice: 'BSC being disconnected for lac: %1' % {aConfig lac}
area: #bsc.
bsc terminateAll.
self connections remove: bsc ifAbsent: [
self logError: 'BSC was never added on lac: %1?' % {aConfig lac}
area: #bsc].
aConfig connection: nil.
aConnection close.
].
] fork.
]
newConnection: aConnection [
| peer |
<category: 'handling'>
peer := aConnection remoteAddress.
msc bscConfig bscList do: [:each |
each peer = peer ifTrue: [
each connected ifTrue: [
self logError: 'BSC-Socket: Still connected for lac: %1' % {each lac}
area: #bsc.
aConnection close.
^ false
].
self setupConnection: aConnection on: each.
^ true
].
].
self logError: 'BSC-Socket: Unknown connection from %1' % {peer} area: #bsc.
aConnection close.
]
]
Object subclass: MSCApplication [
| hlr vlr config bscListener bscConfig bscConHandler mgcp sip paging |
<category: 'OsmoMSC-MSC'>
<comment: 'I am a MSC as I have the VLR/HLR and other instances'>
MSCApplication class >> new [
<category: 'creation'>
^ super new
initialize;
yourself
]
initialize [
<category: 'creation'>
ObjectMemory addDependent: self.
]
update: aSymbol [
<category: 'initialize'>
"We need to re-initialize the sockets and state"
aSymbol = #returnFromSnapshot ifTrue: [
self returnedFromSnapshot.
]
]
hlr [ ^ hlr ifNil: [HLRLocalCollection new]]
vlr [ ^ vlr ifNil: [VLRLocalCollection new]]
pagingManager [ ^ paging ifNil: [paging := PagingManager initWith: self]]
config [ ^ config ifNil: [config := MSCConfig new]]
bscConfig [ ^ bscConfig ifNil: [bscConfig := BSCConfig new]]
bscConHandler [ ^ bscConHandler ifNil: [bscConHandler := MSCBSCConnectionHandler initWith: self]]
returnedFromSnapshot [
<category: 'resume'>
mgcp isNil ifFalse: [
mgcp start
].
"Stop the UDP processing and create a new transport. We might need
to do this in an atomic operation."
sip isNil ifFalse: [|old transport|
old := sip transport.
old stop.
transport := self newSipTransport.
transport start.
sip transport: transport].
"Make sure MGCP is running"
self mgcpCallAgent.
"Make sure we handle SIP"
self sipGateway.
self logNotice: 'Serving BSCs now' area: #msc.
[
Processor activeProcess name: 'BSC Listener'.
self serveBSC. 'MSC has exited' printNl] fork.
]
mgcpCallAgent [
<category: 'MGCP-Audio'>
^ mgcp ifNil: [
mgcp := (Osmo.MGCPCallAgent startOn: config bscIP)
start;
yourself]
]
newSipTransport [
<category: 'private'>
^ Osmo.SIPUdpTransport
startOn: self config sipIP port: self config sipPort.
]
sipGateway [
<category: 'SIP-Audio'>
^ sip ifNil: [ | transport |
transport := self newSipTransport.
sip := Osmo.SIPUserAgent createOn: transport.
transport start.
sip]
]
selectAudioRouteForEmergency: aCon leg: aLeg [
^ (SIPMTCall
fromUser: 'sip:1000@sip.zecke.osmocom.org'
host: '127.0.0.1'
port: 5060
to: 'sip:911@127.0.0.1'
on: self sipGateway)
remoteLeg: aLeg;
msc: self;
yourself
]
selectRedirectFor: aSipCall to: aSipContact [
^ (SIPMTCall
fromUser: 'sip:1000@sip.zecke.osmocom.org'
host: '127.0.0.1'
port: 5060
to: aSipContact
on: self sipGateway)
remoteLeg: aSipCall remoteLeg;
msc: self;
yourself
]
selectAudioRoute: aCon plan: aPlan leg: aLeg [
| nr |
"TODO: Very simple and hardcoded rule"
nr := aPlan number.
"No number, let us return"
nr isEmpty ifTrue: [^nil].
"No special number"
nr first = $* ifFalse: [^nil].
^ (SIPMTCall
fromUser: 'sip:1000@sip.zecke.osmocom.org'
host: '127.0.0.1'
port: 5060
to: 'sip:1%1@127.0.0.1' % {nr allButFirst}
on: self sipGateway)
remoteLeg: aLeg;
msc: self;
yourself
]
serveBSC [
"I will start to listen for BSCs"
bscListener ifNotNil: [bscListener stop.].
bscListener := BSCListener
initWith: config bscIP
port: config bscPort
handler: self bscConHandler.
bscListener serve.
]
MSCApplication class >> startExample [
| msc |
msc := MSCApplication new.
msc config
bscIP: '0.0.0.0';
bscPort: 5000;
sipIP: '127.0.0.1'.
msc bscConfig
addBSC: '127.0.0.1' withName: 'test1' andLac: 8210 sendOsmoRSIP: true;
addBSC: '10.240.240.1' withName: 'test2' andLac: 4712 sendOsmoRSIP: true.
msc returnedFromSnapshot.
^ msc.
]
]