smalltalk
/
osmo-st-all
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-all/osmo-st-mgcp/callagent/MGCPCallAgent.st

165 lines
4.4 KiB
Smalltalk

"
(C) 2010-2012 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: 'Sockets';
fileInPackage: 'OsmoNetwork'.
Object subclass: MGCPCallAgentBase [
| net trunks sem addr port |
<category: 'OsmoMGCP-Callagent'>
<comment: 'I am responsible for the networking'>
MGCPCallAgentBase class >> startOn: anAddress [
<category: 'creation'>
^ (self new)
initialize: anAddress port: 2727;
yourself.
]
MGCPCallAgentBase class >> startOn: anAddress port: aPort [
<category: 'creation'>
^ self new
initialize: anAddress port: aPort;
yourself.
]
initialize: anAddress port: aPort [
<category: 'creation'>
sem := Semaphore forMutualExclusion.
trunks := OrderedCollection new.
addr := anAddress.
port := aPort.
net := Osmo.OsmoUDPSocket new
name: 'MGCPCallAgent';
onData: [:data | OsmoDispatcher dispatchBlock: [self handleData: data]];
yourself.
]
addTrunk: aTrunk [
<category: 'setup'>
sem critical: [
trunks add: aTrunk.
].
]
handleData: aData [
<category: 'handling'>
^ self subclassResponsibility
]
start [
| socket |
<category: 'handling'>
self stop.
socket := (Sockets.DatagramSocket local: addr port: port)
bufferSize: 2048;
yourself.
net start: socket.
]
stop [
<category: 'processing'>
net stop
]
queueData: aDatagram [
<category: 'sending'>
net queueData: aDatagram.
]
]
MGCPCallAgentBase subclass: MGCPCallAgent [
| transactions parser |
<category: 'OsmoMGCP-Callagent'>
<comment: 'I deal with transactions and timeouts'>
initialize: anAddress port: aPort [
<category: 'private'>
super initialize: anAddress port: aPort.
transactions := OrderedCollection new.
]
addTransaction: aTransaction [
<category: 'private'>
sem critical: [
aTransaction transactionId: self generateTransactionId.
transactions add: aTransaction.
]
]
removeTransactionInternal: aTransaction [
<category: 'private'>
sem critical: [transactions remove: aTransaction].
]
transactionIdIsUsed: anId [
<category: 'private'>
^ transactions anySatisfy: [:each | each transactionId = anId]
]
generateTransactionId [
| ran |
<category: 'private'>
"I need to generate a transaction identifier. I assume proper locking"
"Check if the below could ever succeed"
(transactions size - 500000) > (999999999 - 100000000) ifTrue: [
^ self error: 'No free transaction ID.'.
].
[
ran := Random between: 100000000 and: 999999999.
self transactionIdIsUsed: ran
] whileTrue.
^ ran.
]
parser [
<category: 'private'>
^ parser ifNil: [parser := MGCPParser new]
]
handleData: aData [
[
| res data id trans |
data := aData data copyFrom: 1 to: aData size.
res := self parser parse: data asString onError: [
^ self error: 'Parse error ', data asByteArray printString.
].
id := res transactionId asInteger.
trans := sem critical: [transactions copy].
trans do: [:each |
each transactionId = id ifTrue: [
each response: res.
]
]
] on: Error do: [:e |
e logException: 'Incoming data ', e tag area: #mgcp.
]
]
]