command: Be able to parse a MGCP Command
The Command and Response code could and should share parts. Start with slowly aligning the APIs and begin being able to parse a command from a string.
This commit is contained in:
parent
be46bf5b35
commit
f0549c2df8
|
@ -16,27 +16,45 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"
|
"
|
||||||
|
|
||||||
Object subclass: MGCPCommand [
|
Object subclass: MGCPCommandBase [
|
||||||
| transaction endp params sdp |
|
| transaction endp params sdp |
|
||||||
<comment: 'I am a command send to a MGCP gateway. I know my timeout
|
<comment: 'I am a command send to a MGCP gateway. I know my timeout
|
||||||
and such. Each MGCPGateWay can have a MGCPCommand subclass to specify
|
and such. Each MGCPGateWay can have a MGCPCommand subclass to specify
|
||||||
certain things. E.g. the endpoint numbering is different'>
|
certain things. E.g. the endpoint numbering is different'>
|
||||||
<category: 'OsmoMGCP-callagent'>
|
<category: 'OsmoMGCP-callagent'>
|
||||||
|
|
||||||
MGCPCommand class >> create: anEndpoint callId: aCallId [
|
MGCPCommandBase class >> fromDict: nodes [
|
||||||
^ (self new)
|
| verb |
|
||||||
endpoint: anEndpoint;
|
verb := nodes first.
|
||||||
parameterAdd: 'C: ', aCallId asString;
|
self allSubclassesDo: [:each |
|
||||||
|
each verb = verb
|
||||||
|
ifTrue: [^each parseFromDict: nodes]].
|
||||||
|
^self error: 'Unknown command verb "%1"' % {verb}.
|
||||||
|
]
|
||||||
|
|
||||||
|
MGCPCommandBase class >> parseFromDict: nodes [
|
||||||
|
^self new
|
||||||
|
transactionId: nodes third;
|
||||||
|
endpoint: (nodes at: 5);
|
||||||
|
addParametersInternal: (nodes at: 9);
|
||||||
|
sdp: (nodes at: 10);
|
||||||
yourself
|
yourself
|
||||||
]
|
]
|
||||||
|
|
||||||
MGCPCommand class >> create: anEndpoint [
|
MGCPCommandBase class >> create: anEndpoint callId: aCallId [
|
||||||
|
^ (self new)
|
||||||
|
endpoint: anEndpoint;
|
||||||
|
addParameter: 'C' with: aCallId asString;
|
||||||
|
yourself
|
||||||
|
]
|
||||||
|
|
||||||
|
MGCPCommandBase class >> create: anEndpoint [
|
||||||
^ (self new)
|
^ (self new)
|
||||||
endpoint: anEndpoint;
|
endpoint: anEndpoint;
|
||||||
yourself
|
yourself
|
||||||
]
|
]
|
||||||
|
|
||||||
MGCPCommand class >> verb [
|
MGCPCommandBase class >> verb [
|
||||||
<category: 'verb'>
|
<category: 'verb'>
|
||||||
^ self subclassResponsibility
|
^ self subclassResponsibility
|
||||||
]
|
]
|
||||||
|
@ -53,7 +71,29 @@ Object subclass: MGCPCommand [
|
||||||
|
|
||||||
parameterAdd: aParam [
|
parameterAdd: aParam [
|
||||||
<category: 'private'>
|
<category: 'private'>
|
||||||
self params add: aParam.
|
^self error: 'This is deprecated. Use >>#addParameter:with:'
|
||||||
|
]
|
||||||
|
|
||||||
|
addParameter: aKey with: aValue [
|
||||||
|
^self params add: aKey->aValue.
|
||||||
|
]
|
||||||
|
|
||||||
|
addParametersInternal: anArray [
|
||||||
|
<category: 'private'>
|
||||||
|
"TODO: Share code with MGCPResponse"
|
||||||
|
anArray do: [:each |
|
||||||
|
self addParameter: each first first asString with: each first fourth].
|
||||||
|
]
|
||||||
|
|
||||||
|
parameterAt: aKey [
|
||||||
|
^self parameterAt: aKey ifAbsent: [^self error: 'Parameter not found'].
|
||||||
|
]
|
||||||
|
|
||||||
|
parameterAt: aKey ifAbsent: aBlock [
|
||||||
|
self params do: [:each |
|
||||||
|
each key = aKey
|
||||||
|
ifTrue: [^each value]].
|
||||||
|
^aBlock value.
|
||||||
]
|
]
|
||||||
|
|
||||||
params [
|
params [
|
||||||
|
@ -85,7 +125,9 @@ Object subclass: MGCPCommand [
|
||||||
"write the parameters"
|
"write the parameters"
|
||||||
self params do: [:each |
|
self params do: [:each |
|
||||||
out
|
out
|
||||||
nextPutAll: each;
|
nextPutAll: each key;
|
||||||
|
nextPutAll: ': ';
|
||||||
|
nextPutAll: each value;
|
||||||
cr; nl.
|
cr; nl.
|
||||||
].
|
].
|
||||||
|
|
||||||
|
@ -100,7 +142,7 @@ Object subclass: MGCPCommand [
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
MGCPCommand subclass: MGCPCRCXCommand [
|
MGCPCommandBase subclass: MGCPCRCXCommand [
|
||||||
<comment: 'I represent a CRCX message'>
|
<comment: 'I represent a CRCX message'>
|
||||||
<category: 'OsmoMGCP-Callagent'>
|
<category: 'OsmoMGCP-Callagent'>
|
||||||
|
|
||||||
|
@ -118,7 +160,7 @@ MGCPCommand subclass: MGCPCRCXCommand [
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
MGCPCommand subclass: MGCPMDCXCommand [
|
MGCPCommandBase subclass: MGCPMDCXCommand [
|
||||||
<comment: 'I represent a MDCX message'>
|
<comment: 'I represent a MDCX message'>
|
||||||
<category: 'OsmoMGCP-Callagent'>
|
<category: 'OsmoMGCP-Callagent'>
|
||||||
|
|
||||||
|
@ -135,7 +177,7 @@ MGCPCommand subclass: MGCPMDCXCommand [
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
MGCPCommand subclass: MGCPDLCXCommand [
|
MGCPCommandBase subclass: MGCPDLCXCommand [
|
||||||
<comment: 'I represent a DLCX message'>
|
<comment: 'I represent a DLCX message'>
|
||||||
<category: 'OsmoMGCP-Callagent'>
|
<category: 'OsmoMGCP-Callagent'>
|
||||||
|
|
||||||
|
@ -150,7 +192,7 @@ MGCPCommand subclass: MGCPDLCXCommand [
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
MGCPCommand subclass: MGCPAUEPComamnd [
|
MGCPCommandBase subclass: MGCPAUEPComamnd [
|
||||||
<comment: 'I represent an AUEP message'>
|
<comment: 'I represent an AUEP message'>
|
||||||
<category: 'OsmoMGCP-Callagent'>
|
<category: 'OsmoMGCP-Callagent'>
|
||||||
|
|
||||||
|
@ -165,7 +207,7 @@ MGCPCommand subclass: MGCPAUEPComamnd [
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
MGCPCommand subclass: MGCPOsmoRSIPCommand [
|
MGCPCommandBase subclass: MGCPOsmoRSIPCommand [
|
||||||
<comment: 'I represent an Osmocom Extension to MGCP to reset remote
|
<comment: 'I represent an Osmocom Extension to MGCP to reset remote
|
||||||
mediagateways. The spec is working the other way around.'>
|
mediagateways. The spec is working the other way around.'>
|
||||||
<category: 'OsmoMGCP-Callagent'>
|
<category: 'OsmoMGCP-Callagent'>
|
||||||
|
|
|
@ -27,11 +27,15 @@ MGCPGrammar subclass: MGCPParser [
|
||||||
|
|
||||||
MGCPCommand [
|
MGCPCommand [
|
||||||
<category: 'extract'>
|
<category: 'extract'>
|
||||||
^ super MGCPCommand => [:nodes | nil]
|
^ super MGCPCommand => [:nodes | MGCPCommandBase fromDict: nodes]
|
||||||
]
|
]
|
||||||
|
|
||||||
MGCPResponse [
|
MGCPResponse [
|
||||||
<category: 'extract'>
|
<category: 'extract'>
|
||||||
^ super MGCPResponse => [:nodes | MGCPResponse fromDict: nodes]
|
^ super MGCPResponse => [:nodes | MGCPResponse fromDict: nodes]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
endpointName [
|
||||||
|
^super endpointName flatten
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
|
|
@ -78,8 +78,8 @@ TestCase subclass: MGCPCommandTest [
|
||||||
trans := MGCPTransaction on: self endpoint of: self callagent.
|
trans := MGCPTransaction on: self endpoint of: self callagent.
|
||||||
trans transactionId: '808080'.
|
trans transactionId: '808080'.
|
||||||
crcx := (MGCPCRCXCommand createCRCX: self endpoint callId: '4a84ad5d25f')
|
crcx := (MGCPCRCXCommand createCRCX: self endpoint callId: '4a84ad5d25f')
|
||||||
parameterAdd: 'L: p:20, a:GSM-EFR, nt:IN';
|
addParameter: 'L' with: 'p:20, a:GSM-EFR, nt:IN';
|
||||||
parameterAdd: 'M: recvonly';
|
addParameter: 'M' with: 'recvonly';
|
||||||
yourself.
|
yourself.
|
||||||
trans command: crcx.
|
trans command: crcx.
|
||||||
|
|
||||||
|
@ -130,8 +130,8 @@ TestCase subclass: MGCPCommandTest [
|
||||||
trans := MGCPTransaction on: self endpoint of: self callagent.
|
trans := MGCPTransaction on: self endpoint of: self callagent.
|
||||||
trans transactionId: '808080'.
|
trans transactionId: '808080'.
|
||||||
mdcx := (MGCPMDCXCommand createMDCX: self endpoint callId: '4a84ad5d25f')
|
mdcx := (MGCPMDCXCommand createMDCX: self endpoint callId: '4a84ad5d25f')
|
||||||
parameterAdd: 'L: p:20, a:GSM-EFR, nt:IN';
|
addParameter: 'L' with: 'p:20, a:GSM-EFR, nt:IN';
|
||||||
parameterAdd: 'M: recvonly';
|
addParameter: 'M' with: 'recvonly';
|
||||||
sdp: self exampleSDP;
|
sdp: self exampleSDP;
|
||||||
yourself.
|
yourself.
|
||||||
trans command: mdcx.
|
trans command: mdcx.
|
||||||
|
@ -224,8 +224,8 @@ TestCase subclass: MGCPTransactionTest [
|
||||||
|
|
||||||
trans := MGCPShortTransaction on: self endpoint of: self timeoutCallagent.
|
trans := MGCPShortTransaction on: self endpoint of: self timeoutCallagent.
|
||||||
crcx := (MGCPCRCXCommand createCRCX: self endpoint callId: '4a84ad5d25f')
|
crcx := (MGCPCRCXCommand createCRCX: self endpoint callId: '4a84ad5d25f')
|
||||||
parameterAdd: 'L: p:20, a:GSM-EFR, nt:IN';
|
addParameter: 'L' with: 'p:20, a:GSM-EFR, nt:IN';
|
||||||
parameterAdd: 'M: recvonly';
|
addParameter: 'M' with: 'recvonly';
|
||||||
yourself.
|
yourself.
|
||||||
trans command: crcx.
|
trans command: crcx.
|
||||||
|
|
||||||
|
@ -248,8 +248,8 @@ TestCase subclass: MGCPTransactionTest [
|
||||||
|
|
||||||
trans := MGCPShortTransaction on: self endpoint of: self dropAgent.
|
trans := MGCPShortTransaction on: self endpoint of: self dropAgent.
|
||||||
crcx := (MGCPCRCXCommand createCRCX: self endpoint callId: '4a84ad5d25f')
|
crcx := (MGCPCRCXCommand createCRCX: self endpoint callId: '4a84ad5d25f')
|
||||||
parameterAdd: 'L: p:20, a:GSM-EFR, nt:IN';
|
addParameter: 'L' with: 'p:20, a:GSM-EFR, nt:IN';
|
||||||
parameterAdd: 'M: recvonly';
|
addParameter: 'M' with: 'recvonly';
|
||||||
yourself.
|
yourself.
|
||||||
trans command: crcx.
|
trans command: crcx.
|
||||||
|
|
||||||
|
@ -352,10 +352,28 @@ TestCase subclass: MGCPEndpointAllocTest [
|
||||||
PP.PPCompositeParserTest subclass: MGCPParserTest [
|
PP.PPCompositeParserTest subclass: MGCPParserTest [
|
||||||
<category: 'OsmoMGCP-Callagent-Tests'>
|
<category: 'OsmoMGCP-Callagent-Tests'>
|
||||||
|
|
||||||
|
MGCPParserTest class >> crcxMessage [
|
||||||
|
^String streamContents: [:stream |
|
||||||
|
stream
|
||||||
|
nextPutAll: 'CRCX 1 14@mgw MGCP 1.0'; cr; nl;
|
||||||
|
nextPutAll: 'C: 4a84ad5d25f'; cr; nl;
|
||||||
|
nextPutAll: 'L: p:20, a:GSM-EFR, nt:IN'; cr; nl;
|
||||||
|
nextPutAll: 'M: recvonly'; cr; nl]
|
||||||
|
]
|
||||||
|
|
||||||
parserClass [
|
parserClass [
|
||||||
^MGCPParser
|
^MGCPParser
|
||||||
]
|
]
|
||||||
|
|
||||||
|
testParseCRCX [
|
||||||
|
| crcx |
|
||||||
|
crcx := self parse: self class crcxMessage.
|
||||||
|
|
||||||
|
self assert: crcx class verb equals: 'CRCX'.
|
||||||
|
self assert: (crcx parameterAt: 'M') equals: 'recvonly'.
|
||||||
|
self assert: crcx asDatagram equals: self class crcxMessage.
|
||||||
|
]
|
||||||
|
|
||||||
testRespParse [
|
testRespParse [
|
||||||
| nl res sdp |
|
| nl res sdp |
|
||||||
nl := Character cr asString, Character nl asString.
|
nl := Character cr asString, Character nl asString.
|
||||||
|
|
Reference in New Issue