diff options
author | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
commit | 84adefa331c4159d432d22840663c38f155cd4c1 (patch) | |
tree | bff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/megaco/src/binary | |
download | otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2 otp-84adefa331c4159d432d22840663c38f155cd4c1.zip |
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/megaco/src/binary')
79 files changed, 32346 insertions, 0 deletions
diff --git a/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-prev3a.asn b/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-prev3a.asn new file mode 100644 index 0000000000..083f7e8271 --- /dev/null +++ b/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-prev3a.asn @@ -0,0 +1,1001 @@ +MEDIA-GATEWAY-CONTROL-prev3a +{itu-t(0) recommendation(0) h(8) h248(248) + modules(0) media-gateway-control(0) version3(3)} +DEFINITIONS AUTOMATIC TAGS ::= +BEGIN + + +MegacoMessage ::= SEQUENCE + { + authHeader AuthenticationHeader OPTIONAL, + mess Message + } + +AuthenticationHeader ::= SEQUENCE + { + secParmIndex SecurityParmIndex, + seqNum SequenceNum, + ad AuthData + } + +SecurityParmIndex ::= OCTET STRING(SIZE(4)) + +SequenceNum ::= OCTET STRING(SIZE(4)) + +AuthData ::= OCTET STRING (SIZE (12..32)) + +Message ::= SEQUENCE + { + version INTEGER(0..99), + -- The version of the protocol defined here is equal to 3. + mId MId, -- Name/address of message originator + messageBody CHOICE + { + messageError ErrorDescriptor, + transactions SEQUENCE OF Transaction + }, + ... + } + +MId ::= CHOICE + { + ip4Address IP4Address, + ip6Address IP6Address, + domainName DomainName, + deviceName PathName, + mtpAddress OCTET STRING(SIZE(2..4)), + -- Addressing structure of mtpAddress: + -- 25 - 15 0 + -- | PC | NI | + -- 24 - 14 bits 2 bits + -- Note: 14 bits are defined for international use. + -- Two national options exist where the point code is 16 or 24 + -- bits. + -- To octet align the mtpAddress, the MSBs shall be encoded as 0s. + ... + } + +DomainName ::= SEQUENCE + { + name IA5String, + -- The name starts with an alphanumeric digit followed by a + -- sequence of alphanumeric digits, hyphens and dots. No two + -- dots shall occur consecutively. + portNumber INTEGER(0..65535) OPTIONAL + } + +IP4Address ::= SEQUENCE + { + address OCTET STRING (SIZE(4)), + portNumber INTEGER(0..65535) OPTIONAL + } + +IP6Address ::= SEQUENCE + { + address OCTET STRING (SIZE(16)), + portNumber INTEGER(0..65535) OPTIONAL + } + +PathName ::= IA5String(SIZE (1..64)) +-- See A.3 + +Transaction ::= CHOICE + { + transactionRequest TransactionRequest, + transactionPending TransactionPending, + transactionReply TransactionReply, + transactionResponseAck TransactionResponseAck, + -- use of response acks is dependent on underlying transport + ... + } + +TransactionId ::= INTEGER(0..4294967295) -- 32-bit unsigned integer + +TransactionRequest ::= SEQUENCE + { + transactionId TransactionId, + actions SEQUENCE OF ActionRequest, + ... + } + +TransactionPending ::= SEQUENCE + { + transactionId TransactionId, + ... + } + +TransactionReply ::= SEQUENCE + { + transactionId TransactionId, + immAckRequired NULL OPTIONAL, + transactionResult CHOICE + { + transactionError ErrorDescriptor, + actionReplies SEQUENCE OF ActionReply + }, + ..., + -- Erlang Note: NOT REALLY PART OF THIS IMPLEMENTATION + -- Erlang Note: The only reason why we need to include + -- Erlang Note: these definitions in this version is + -- Erlang Note: that we cannot distinguish between v3 + -- Erlang Note: versions in the megaco_messenger module + segmentNumber SegmentNumber OPTIONAL, + segmentationComplete NULL OPTIONAL + } + +-- SegmentReply ::= SEQUENCE +-- { +-- transactionId TransactionId, +-- segmentNumber SegmentNumber, +-- segmentationComplete NULL OPTIONAL, +-- ... +-- } +-- +SegmentNumber ::= INTEGER(0..65535) + +TransactionResponseAck ::= SEQUENCE OF TransactionAck +TransactionAck ::= SEQUENCE + { + firstAck TransactionId, + lastAck TransactionId OPTIONAL + } + +ErrorDescriptor ::= SEQUENCE + { + errorCode ErrorCode, + errorText ErrorText OPTIONAL + } + +ErrorCode ::= INTEGER(0..65535) +-- See clause 14 for IANA considerations with respect to error codes +ErrorText ::= IA5String + +ContextID ::= INTEGER(0..4294967295) + +-- Context NULL Value: 0 +-- Context CHOOSE Value: 4294967294 (0xFFFFFFFE) +-- Context ALL Value: 4294967295 (0xFFFFFFFF) + + +ActionRequest ::= SEQUENCE + { + contextId ContextID, + contextRequest ContextRequest OPTIONAL, + contextAttrAuditReq ContextAttrAuditRequest OPTIONAL, + commandRequests SEQUENCE OF CommandRequest + } + +ActionReply ::= SEQUENCE + { + contextId ContextID, + errorDescriptor ErrorDescriptor OPTIONAL, + contextReply ContextRequest OPTIONAL, + commandReply SEQUENCE OF CommandReply + } + +ContextRequest ::= SEQUENCE + { + priority INTEGER(0..15) OPTIONAL, + emergency BOOLEAN OPTIONAL, + topologyReq SEQUENCE OF TopologyRequest OPTIONAL, + ..., + iepsCallind BOOLEAN OPTIONAL, -- Fixed + contextProp SEQUENCE OF PropertyParm OPTIONAL + } + +ContextAttrAuditRequest ::= SEQUENCE + { + topology NULL OPTIONAL, + emergency NULL OPTIONAL, + priority NULL OPTIONAL, + ..., + iepsCallind NULL OPTIONAL, -- Fixed + contextPropAud SEQUENCE OF IndAudPropertyParm OPTIONAL + } + +CommandRequest ::= SEQUENCE + { + command Command, + optional NULL OPTIONAL, + wildcardReturn NULL OPTIONAL, + ... + } + +Command ::= CHOICE + { + addReq AmmRequest, + moveReq AmmRequest, + modReq AmmRequest, + -- Add, Move, Modify requests have the same parameters + subtractReq SubtractRequest, + auditCapRequest AuditRequest, + auditValueRequest AuditRequest, + notifyReq NotifyRequest, + serviceChangeReq ServiceChangeRequest, + ... + } + +CommandReply ::= CHOICE + { + addReply AmmsReply, + moveReply AmmsReply, + modReply AmmsReply, + subtractReply AmmsReply, + -- Add, Move, Modify, Subtract replies have the same parameters + auditCapReply AuditReply, + auditValueReply AuditReply, + notifyReply NotifyReply, + serviceChangeReply ServiceChangeReply, + ... + } + +TopologyRequest ::= SEQUENCE + { + terminationFrom TerminationID, + terminationTo TerminationID, + topologyDirection ENUMERATED + { + bothway(0), + isolate(1), + oneway(2) + }, + ..., + streamID StreamID OPTIONAL + } + +AmmRequest ::= SEQUENCE + { + terminationID TerminationIDList, + descriptors SEQUENCE OF AmmDescriptor, + -- At most one descriptor of each type (see AmmDescriptor) + -- allowed in the sequence. + ... + } + +AmmDescriptor ::= CHOICE + { + mediaDescriptor MediaDescriptor, + modemDescriptor ModemDescriptor, + muxDescriptor MuxDescriptor, + eventsDescriptor EventsDescriptor, + eventBufferDescriptor EventBufferDescriptor, + signalsDescriptor SignalsDescriptor, + digitMapDescriptor DigitMapDescriptor, + auditDescriptor AuditDescriptor, + ..., + statisticsDescriptor StatisticsDescriptor + } + + +AmmsReply ::= SEQUENCE + { + terminationID TerminationIDList, + terminationAudit TerminationAudit OPTIONAL, + ... + } + +SubtractRequest ::= SEQUENCE + { + terminationID TerminationIDList, + auditDescriptor AuditDescriptor OPTIONAL, + ... + } + +AuditRequest ::= SEQUENCE + { + terminationID TerminationID, + auditDescriptor AuditDescriptor, + ... + } + +AuditReply ::= CHOICE + { + contextAuditResult TerminationIDList, + error ErrorDescriptor, + auditResult AuditResult, + ... + } + +AuditResult ::= SEQUENCE + { + + terminationID TerminationID, + terminationAuditResult TerminationAudit + } + + + +TerminationAudit ::= SEQUENCE OF AuditReturnParameter + +AuditReturnParameter ::= CHOICE + { + errorDescriptor ErrorDescriptor, + mediaDescriptor MediaDescriptor, + modemDescriptor ModemDescriptor, + muxDescriptor MuxDescriptor, + eventsDescriptor EventsDescriptor, + eventBufferDescriptor EventBufferDescriptor, + signalsDescriptor SignalsDescriptor, + digitMapDescriptor DigitMapDescriptor, + observedEventsDescriptor ObservedEventsDescriptor, + statisticsDescriptor StatisticsDescriptor, + packagesDescriptor PackagesDescriptor, + emptyDescriptors AuditDescriptor, + ... + } + +AuditDescriptor ::= SEQUENCE + { + auditToken BIT STRING + { + muxToken(0), modemToken(1), mediaToken(2), + eventsToken(3), signalsToken(4), + digitMapToken(5), statsToken(6), + observedEventsToken(7), + packagesToken(8), eventBufferToken(9) + } OPTIONAL, + ..., + auditPropertyToken SEQUENCE OF IndAuditParameter OPTIONAL + } + + +IndAuditParameter ::= CHOICE + { + -- Note that the lower/upper case letters of the tags have + -- been changed. The same changes has been made in text... + indAudMediaDescriptor IndAudMediaDescriptor, + indAudEventsDescriptor IndAudEventsDescriptor, + indAudEventBufferDescriptor IndAudEventBufferDescriptor, + indAudSignalsDescriptor IndAudSignalsDescriptor, + indAudDigitMapDescriptor IndAudDigitMapDescriptor, + indAudStatisticsDescriptor IndAudStatisticsDescriptor, + indAudPackagesDescriptor IndAudPackagesDescriptor, + ... + } + +IndAudMediaDescriptor ::= SEQUENCE + { + + termStateDescr IndAudTerminationStateDescriptor OPTIONAL, + streams CHOICE + { + oneStream IndAudStreamParms, + multiStream SEQUENCE OF IndAudStreamDescriptor + } OPTIONAL, + ... + } + +IndAudStreamDescriptor ::= SEQUENCE + { + streamID StreamID, + streamParms IndAudStreamParms + } + +IndAudStreamParms ::= SEQUENCE + { + localControlDescriptor IndAudLocalControlDescriptor OPTIONAL, + localDescriptor IndAudLocalRemoteDescriptor OPTIONAL, + remoteDescriptor IndAudLocalRemoteDescriptor OPTIONAL, + ..., + statisticsDescriptor IndAudStatisticsDescriptor OPTIONAL + } + +IndAudLocalControlDescriptor ::= SEQUENCE + { + streamMode NULL OPTIONAL, + reserveValue NULL OPTIONAL, + reserveGroup NULL OPTIONAL, + propertyParms SEQUENCE OF IndAudPropertyParm OPTIONAL, + ... + } + +IndAudPropertyParm ::= SEQUENCE + { + name PkgdName, + ... + } + +IndAudLocalRemoteDescriptor ::= SEQUENCE + { + propGroupID INTEGER(0..65535) OPTIONAL, + propGrps IndAudPropertyGroup, + ... + } + +IndAudPropertyGroup ::= SEQUENCE OF IndAudPropertyParm + +IndAudTerminationStateDescriptor ::= SEQUENCE + { + propertyParms SEQUENCE OF IndAudPropertyParm, + eventBufferControl NULL OPTIONAL, + serviceState NULL OPTIONAL, + ... + } + +IndAudEventsDescriptor ::= SEQUENCE + { + requestID RequestID OPTIONAL, + pkgdName PkgdName, + streamID StreamID OPTIONAL, + ... + } + +IndAudEventBufferDescriptor ::= SEQUENCE + { + eventName PkgdName, + streamID StreamID OPTIONAL, + ... + } + +IndAudSignalsDescriptor ::=CHOICE + { + signal IndAudSignal, + seqSigList IndAudSeqSigList, + ... + } + +IndAudSeqSigList ::= SEQUENCE + { + id INTEGER(0..65535), + signalList IndAudSignal OPTIONAL + } + +IndAudSignal ::= SEQUENCE + { + signalName PkgdName, + streamID StreamID OPTIONAL, + ... + } + +IndAudDigitMapDescriptor ::= SEQUENCE + { + digitMapName DigitMapName OPTIONAL + } + +IndAudStatisticsDescriptor ::= SEQUENCE + { + statName PkgdName + } + +IndAudPackagesDescriptor ::= SEQUENCE + { + packageName Name, + packageVersion INTEGER(0..99), + ... + } + +NotifyRequest ::= SEQUENCE + { + terminationID TerminationIDList, + observedEventsDescriptor ObservedEventsDescriptor, + errorDescriptor ErrorDescriptor OPTIONAL, + ... + } + +NotifyReply ::= SEQUENCE + { + terminationID TerminationIDList, + errorDescriptor ErrorDescriptor OPTIONAL, + ... + } + +ObservedEventsDescriptor ::= SEQUENCE + { + requestId RequestID, + observedEventLst SEQUENCE OF ObservedEvent + } + +ObservedEvent ::= SEQUENCE + { + eventName EventName, + streamID StreamID OPTIONAL, + eventParList SEQUENCE OF EventParameter, + timeNotation TimeNotation OPTIONAL, + ... + } + +EventName ::= PkgdName + +EventParameter ::= SEQUENCE + { + eventParameterName Name, + value Value, + -- For use of extraInfo see the comment related to PropertyParm + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... + + } + +ServiceChangeRequest ::= SEQUENCE + { + terminationID TerminationIDList, + serviceChangeParms ServiceChangeParm, + ... + } + +ServiceChangeReply ::= SEQUENCE + { + terminationID TerminationIDList, + serviceChangeResult ServiceChangeResult, + ... + } + +-- For ServiceChangeResult, no parameters are mandatory. Hence the +-- distinction between ServiceChangeParm and ServiceChangeResParm. + +ServiceChangeResult ::= CHOICE + { + errorDescriptor ErrorDescriptor, + serviceChangeResParms ServiceChangeResParm + } + +WildcardField ::= OCTET STRING(SIZE(1)) + +TerminationID ::= SEQUENCE + { + wildcard SEQUENCE OF WildcardField, + id OCTET STRING(SIZE(1..8)), + ... + } +-- See A.1 for explanation of wildcarding mechanism. +-- Termination ID 0xFFFFFFFFFFFFFFFF indicates the ROOT Termination. + +TerminationIDList ::= SEQUENCE OF TerminationID + +MediaDescriptor ::= SEQUENCE + { + termStateDescr TerminationStateDescriptor OPTIONAL, + streams CHOICE + { + oneStream StreamParms, + multiStream SEQUENCE OF StreamDescriptor + } OPTIONAL, + ... + } + +StreamDescriptor ::= SEQUENCE + { + streamID StreamID, + streamParms StreamParms + } + +StreamParms ::= SEQUENCE + { + localControlDescriptor LocalControlDescriptor OPTIONAL, + localDescriptor LocalRemoteDescriptor OPTIONAL, + remoteDescriptor LocalRemoteDescriptor OPTIONAL, + ..., + statisticsDescriptor StatisticsDescriptor OPTIONAL + } + +LocalControlDescriptor ::= SEQUENCE + { + streamMode StreamMode OPTIONAL, + reserveValue BOOLEAN OPTIONAL, + reserveGroup BOOLEAN OPTIONAL, + propertyParms SEQUENCE OF PropertyParm, + ... + } + +StreamMode ::= ENUMERATED + { + sendOnly(0), + recvOnly(1), + sendRecv(2), + inactive(3), + loopBack(4), + ... + } + +-- In PropertyParm, value is a SEQUENCE OF octet string. When sent +-- by an MGC the interpretation is as follows: +-- empty sequence means CHOOSE +-- one element sequence specifies value +-- If the sublist field is not selected, a longer sequence means +-- "choose one of the values" (i.e. value1 OR value2 OR ...) +-- If the sublist field is selected, +-- a sequence with more than one element encodes the value of a +-- list-valued property (i.e. value1 AND value2 AND ...). +-- The relation field may only be selected if the value sequence +-- has length 1. It indicates that the MG has to choose a value +-- for the property. E.g. x > 3 (using the greaterThan +-- value for relation) instructs the MG to choose any value larger +-- than 3 for property x. +-- The range field may only be selected if the value sequence +-- has length 2. It indicates that the MG has to choose a value +-- in the range between the first octet in the value sequence and +-- the trailing octet in the value sequence, including the +-- boundary values. +-- When sent by the MG, only responses to an AuditCapability request +-- may contain multiple values, a range, or a relation field. + +PropertyParm ::= SEQUENCE + { + name PkgdName, + value SEQUENCE OF OCTET STRING, + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... + } + +Name ::= OCTET STRING(SIZE(2)) + +PkgdName ::= OCTET STRING(SIZE(4)) +-- represents Package Name (2 octets) plus Property, Event, +-- Signal Names or Statistics ID. (2 octets) +-- To wildcard a package use 0xFFFF for first two octets, choose +-- is not allowed. To reference native property tag specified in +-- Annex C, use 0x0000 as first two octets. +-- To wildcard a Property, Event, Signal, or Statistics ID, use +-- 0xFFFF for last two octets, choose is not allowed. +-- Wildcarding of Package Name is permitted only if Property, +-- Event, Signal, or Statistics ID are +-- also wildcarded. + +Relation ::= ENUMERATED + { + greaterThan(0), + smallerThan(1), + unequalTo(2), + ... + } + +LocalRemoteDescriptor ::= SEQUENCE + { + propGrps SEQUENCE OF PropertyGroup, + ... + } + +PropertyGroup ::= SEQUENCE OF PropertyParm + +TerminationStateDescriptor ::= SEQUENCE + { + propertyParms SEQUENCE OF PropertyParm, + eventBufferControl EventBufferControl OPTIONAL, + serviceState ServiceState OPTIONAL, + ... + } + +EventBufferControl ::= ENUMERATED + { + off(0), + lockStep(1), + ... + } + +ServiceState ::= ENUMERATED + { + test(0), + outOfSvc(1), + inSvc(2), + ... + } + +MuxDescriptor ::= SEQUENCE + { + muxType MuxType, + termList SEQUENCE OF TerminationID, + nonStandardData NonStandardData OPTIONAL, + ... + } + +MuxType ::= ENUMERATED + { + h221(0), + h223(1), + h226(2), + v76(3), + ..., + nx64k(4) + } + +StreamID ::= INTEGER(0..65535) -- 16-bit unsigned integer + +EventsDescriptor ::= SEQUENCE + { + requestID RequestID OPTIONAL, + -- RequestID must be present if eventList + -- is non empty + eventList SEQUENCE OF RequestedEvent, + ... + } + +RequestedEvent ::= SEQUENCE + { + pkgdName PkgdName, + streamID StreamID OPTIONAL, + eventAction RequestedActions OPTIONAL, + evParList SEQUENCE OF EventParameter, + ... + } + +RequestedActions ::= SEQUENCE + { + keepActive BOOLEAN OPTIONAL, + eventDM EventDM OPTIONAL, + secondEvent SecondEventsDescriptor OPTIONAL, + signalsDescriptor SignalsDescriptor OPTIONAL, + ... + } + +EventDM ::= CHOICE + { + digitMapName DigitMapName, + digitMapValue DigitMapValue + } + +SecondEventsDescriptor ::= SEQUENCE + { + requestID RequestID OPTIONAL, + eventList SEQUENCE OF SecondRequestedEvent, + ... + } + +SecondRequestedEvent ::= SEQUENCE + { + pkgdName PkgdName, + streamID StreamID OPTIONAL, + eventAction SecondRequestedActions OPTIONAL, + evParList SEQUENCE OF EventParameter, + ... + } + +SecondRequestedActions ::= SEQUENCE + { + keepActive BOOLEAN OPTIONAL, + eventDM EventDM OPTIONAL, + signalsDescriptor SignalsDescriptor OPTIONAL, + ... + } + +EventBufferDescriptor ::= SEQUENCE OF EventSpec + +EventSpec ::= SEQUENCE + { + eventName EventName, + streamID StreamID OPTIONAL, + eventParList SEQUENCE OF EventParameter, + ... + } + + +SignalsDescriptor ::= SEQUENCE OF SignalRequest + +SignalRequest ::= CHOICE + { + signal Signal, + seqSigList SeqSigList, + ... + } + +SeqSigList ::= SEQUENCE + { + id INTEGER(0..65535), + signalList SEQUENCE OF Signal + } + +Signal ::= SEQUENCE + { + signalName SignalName, + streamID StreamID OPTIONAL, + sigType SignalType OPTIONAL, + duration INTEGER (0..65535) OPTIONAL, + notifyCompletion NotifyCompletion OPTIONAL, + keepActive BOOLEAN OPTIONAL, + sigParList SEQUENCE OF SigParameter, + ..., + direction SignalDirection OPTIONAL, + requestID RequestID OPTIONAL + } + +SignalType ::= ENUMERATED + { + brief(0), + onOff(1), + timeOut(2), + ... + } + +SignalDirection ::= ENUMERATED + { + internal(0), + external(1), + both(3), + ... + } + +SignalName ::= PkgdName + +NotifyCompletion ::= BIT STRING + { + onTimeOut(0), onInterruptByEvent(1), + onInterruptByNewSignalDescr(2), otherReason(3) + } + +SigParameter ::= SEQUENCE + { + sigParameterName Name, + value Value, + -- For use of extraInfo see the comment related to PropertyParm + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... + } + +-- For an AuditCapReply with all events, the RequestID SHALL be ALL. +-- ALL is represented by 0xffffffff. + +RequestID ::= INTEGER(0..4294967295) -- 32-bit unsigned integer + +ModemDescriptor ::= SEQUENCE + { + mtl SEQUENCE OF ModemType, + mpl SEQUENCE OF PropertyParm, + nonStandardData NonStandardData OPTIONAL + } + +ModemType ::= ENUMERATED + { + v18(0), + v22(1), + v22bis(2), + v32(3), + v32bis(4), + v34(5), + v90(6), + v91(7), + synchISDN(8), + ... + } + +DigitMapDescriptor ::= SEQUENCE + { + digitMapName DigitMapName OPTIONAL, + digitMapValue DigitMapValue OPTIONAL + } + +DigitMapName ::= Name + +DigitMapValue ::= SEQUENCE + { + startTimer INTEGER(0..99) OPTIONAL, + shortTimer INTEGER(0..99) OPTIONAL, + longTimer INTEGER(0..99) OPTIONAL, + digitMapBody IA5String, + -- Units are seconds for start, short and long timers, and + -- hundreds of milliseconds for duration timer. Thus start, + -- short, and long range from 1 to 99 seconds and duration + -- from 100 ms to 9.9 s + -- See A.3 for explanation of digit map syntax + ..., + durationTimer INTEGER (0..99) OPTIONAL + } + +ServiceChangeParm ::= SEQUENCE + { + serviceChangeMethod ServiceChangeMethod, + serviceChangeAddress ServiceChangeAddress OPTIONAL, + serviceChangeVersion INTEGER(0..99) OPTIONAL, + serviceChangeProfile ServiceChangeProfile OPTIONAL, + serviceChangeReason Value, + -- A serviceChangeReason consists of a numeric reason code + -- and an optional text description. + -- The serviceChangeReason SHALL be a string consisting of + -- a decimal reason code, optionally followed by a single + -- space character and a textual description string. + -- This string is first BER-encoded as an IA5String. + -- The result of this BER-encoding is then encoded as + -- an ASN.1 OCTET STRING type, "double wrapping" the + -- value + -- as was done for package elements. + serviceChangeDelay INTEGER(0..4294967295) OPTIONAL, + -- 32-bit unsigned integer + serviceChangeMgcId MId OPTIONAL, + timeStamp TimeNotation OPTIONAL, + nonStandardData NonStandardData OPTIONAL, + ..., + serviceChangeInfo AuditDescriptor OPTIONAL, + serviceChangeIncompleteFlag NULL OPTIONAL + } + +ServiceChangeAddress ::= CHOICE + { + portNumber INTEGER(0..65535), -- TCP/UDP port number + ip4Address IP4Address, + ip6Address IP6Address, + domainName DomainName, + deviceName PathName, + mtpAddress OCTET STRING(SIZE(2..4)), + ... + } + +ServiceChangeResParm ::= SEQUENCE + { + serviceChangeMgcId MId OPTIONAL, + serviceChangeAddress ServiceChangeAddress OPTIONAL, + serviceChangeVersion INTEGER(0..99) OPTIONAL, + serviceChangeProfile ServiceChangeProfile OPTIONAL, + timestamp TimeNotation OPTIONAL, + ... + } + +ServiceChangeMethod ::= ENUMERATED + { + failover(0), + forced(1), + graceful(2), + restart(3), + disconnected(4), + handOff(5), + ... + } + +ServiceChangeProfile ::= SEQUENCE + { + profileName IA5String(SIZE (1..67)) + + -- 64 characters for name, 1 for "/", 2 for version to match ABNF + } + +PackagesDescriptor ::= SEQUENCE OF PackagesItem +PackagesItem ::= SEQUENCE + { + packageName Name, + packageVersion INTEGER(0..99), + ... + } + +StatisticsDescriptor ::= SEQUENCE OF StatisticsParameter + +StatisticsParameter ::= SEQUENCE + { + statName PkgdName, + statValue Value OPTIONAL + } + +NonStandardData ::= SEQUENCE + { + nonStandardIdentifier NonStandardIdentifier, + data OCTET STRING + } + +NonStandardIdentifier ::= CHOICE + { + object OBJECT IDENTIFIER, + h221NonStandard H221NonStandard, + experimental IA5String(SIZE(8)), + -- first two characters SHOULD be "X-" or "X+" + ... + } + +H221NonStandard ::= SEQUENCE + { t35CountryCode1 INTEGER(0..255), + t35CountryCode2 INTEGER(0..255), -- country, as per T.35 + t35Extension INTEGER(0..255), -- assigned nationally + manufacturerCode INTEGER(0..65535), -- assigned nationally + ... + } + +TimeNotation ::= SEQUENCE + { + date IA5String(SIZE(8)), -- yyyymmdd format + time IA5String(SIZE(8)) -- hhmmssss format + -- per ISO 8601:1988 + } + +Value ::= SEQUENCE OF OCTET STRING + +END diff --git a/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-prev3b.asn b/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-prev3b.asn new file mode 100644 index 0000000000..1fb4d8fff2 --- /dev/null +++ b/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-prev3b.asn @@ -0,0 +1,1001 @@ +MEDIA-GATEWAY-CONTROL-prev3b +{itu-t(0) recommendation(0) h(8) h248(248) + modules(0) media-gateway-control(0) version3(3)} +DEFINITIONS AUTOMATIC TAGS ::= +BEGIN + + +MegacoMessage ::= SEQUENCE + { + authHeader AuthenticationHeader OPTIONAL, + mess Message + } + +AuthenticationHeader ::= SEQUENCE + { + secParmIndex SecurityParmIndex, + seqNum SequenceNum, + ad AuthData + } + +SecurityParmIndex ::= OCTET STRING(SIZE(4)) + +SequenceNum ::= OCTET STRING(SIZE(4)) + +AuthData ::= OCTET STRING (SIZE (12..32)) + +Message ::= SEQUENCE + { + version INTEGER(0..99), + -- The version of the protocol defined here is equal to 3. + mId MId, -- Name/address of message originator + messageBody CHOICE + { + messageError ErrorDescriptor, + transactions SEQUENCE OF Transaction + }, + ... + } + +MId ::= CHOICE + { + ip4Address IP4Address, + ip6Address IP6Address, + domainName DomainName, + deviceName PathName, + mtpAddress OCTET STRING(SIZE(2..4)), + -- Addressing structure of mtpAddress: + -- 25 - 15 0 + -- | PC | NI | + -- 24 - 14 bits 2 bits + -- Note: 14 bits are defined for international use. + -- Two national options exist where the point code is 16 or 24 + -- bits. + -- To octet align the mtpAddress, the MSBs shall be encoded as 0s. + ... + } + +DomainName ::= SEQUENCE + { + name IA5String, + -- The name starts with an alphanumeric digit followed by a + -- sequence of alphanumeric digits, hyphens and dots. No two + -- dots shall occur consecutively. + portNumber INTEGER(0..65535) OPTIONAL + } + +IP4Address ::= SEQUENCE + { + address OCTET STRING (SIZE(4)), + portNumber INTEGER(0..65535) OPTIONAL + } + +IP6Address ::= SEQUENCE + { + address OCTET STRING (SIZE(16)), + portNumber INTEGER(0..65535) OPTIONAL + } + +PathName ::= IA5String(SIZE (1..64)) +-- See A.3 + +Transaction ::= CHOICE + { + transactionRequest TransactionRequest, + transactionPending TransactionPending, + transactionReply TransactionReply, + transactionResponseAck TransactionResponseAck, + -- use of response acks is dependent on underlying transport + ... + } + +TransactionId ::= INTEGER(0..4294967295) -- 32-bit unsigned integer + +TransactionRequest ::= SEQUENCE + { + transactionId TransactionId, + actions SEQUENCE OF ActionRequest, + ... + } + +TransactionPending ::= SEQUENCE + { + transactionId TransactionId, + ... + } + +TransactionReply ::= SEQUENCE + { + transactionId TransactionId, + immAckRequired NULL OPTIONAL, + transactionResult CHOICE + { + transactionError ErrorDescriptor, + actionReplies SEQUENCE OF ActionReply + }, + ..., + -- Erlang Note: NOT REALLY PART OF THIS IMPLEMENTATION + -- Erlang Note: The only reason why we need to include + -- Erlang Note: these definitions in this version is + -- Erlang Note: that we cannot distinguish between v3 + -- Erlang Note: versions in the megaco_messenger module + segmentNumber SegmentNumber OPTIONAL, + segmentationComplete NULL OPTIONAL + } + +-- SegmentReply ::= SEQUENCE +-- { +-- transactionId TransactionId, +-- segmentNumber SegmentNumber, +-- segmentationComplete NULL OPTIONAL, +-- ... +-- } +-- +SegmentNumber ::= INTEGER(0..65535) + +TransactionResponseAck ::= SEQUENCE OF TransactionAck +TransactionAck ::= SEQUENCE + { + firstAck TransactionId, + lastAck TransactionId OPTIONAL + } + +ErrorDescriptor ::= SEQUENCE + { + errorCode ErrorCode, + errorText ErrorText OPTIONAL + } + +ErrorCode ::= INTEGER(0..65535) +-- See clause 14 for IANA considerations with respect to error codes +ErrorText ::= IA5String + +ContextID ::= INTEGER(0..4294967295) + +-- Context NULL Value: 0 +-- Context CHOOSE Value: 4294967294 (0xFFFFFFFE) +-- Context ALL Value: 4294967295 (0xFFFFFFFF) + + +ActionRequest ::= SEQUENCE + { + contextId ContextID, + contextRequest ContextRequest OPTIONAL, + contextAttrAuditReq ContextAttrAuditRequest OPTIONAL, + commandRequests SEQUENCE OF CommandRequest + } + +ActionReply ::= SEQUENCE + { + contextId ContextID, + errorDescriptor ErrorDescriptor OPTIONAL, + contextReply ContextRequest OPTIONAL, + commandReply SEQUENCE OF CommandReply + } + +ContextRequest ::= SEQUENCE + { + priority INTEGER(0..15) OPTIONAL, + emergency BOOLEAN OPTIONAL, + topologyReq SEQUENCE OF TopologyRequest OPTIONAL, + ..., + iepscallind BOOLEAN OPTIONAL, + contextProp SEQUENCE OF PropertyParm OPTIONAL + } + +ContextAttrAuditRequest ::= SEQUENCE + { + topology NULL OPTIONAL, + emergency NULL OPTIONAL, + priority NULL OPTIONAL, + ..., + iepscallind NULL OPTIONAL, + contextPropAud SEQUENCE OF IndAudPropertyParm OPTIONAL + } + +CommandRequest ::= SEQUENCE + { + command Command, + optional NULL OPTIONAL, + wildcardReturn NULL OPTIONAL, + ... + } + +Command ::= CHOICE + { + addReq AmmRequest, + moveReq AmmRequest, + modReq AmmRequest, + -- Add, Move, Modify requests have the same parameters + subtractReq SubtractRequest, + auditCapRequest AuditRequest, + auditValueRequest AuditRequest, + notifyReq NotifyRequest, + serviceChangeReq ServiceChangeRequest, + ... + } + +CommandReply ::= CHOICE + { + addReply AmmsReply, + moveReply AmmsReply, + modReply AmmsReply, + subtractReply AmmsReply, + -- Add, Move, Modify, Subtract replies have the same parameters + auditCapReply AuditReply, + auditValueReply AuditReply, + notifyReply NotifyReply, + serviceChangeReply ServiceChangeReply, + ... + } + +TopologyRequest ::= SEQUENCE + { + terminationFrom TerminationID, + terminationTo TerminationID, + topologyDirection ENUMERATED + { + bothway(0), + isolate(1), + oneway(2) + }, + ..., + streamID StreamID OPTIONAL + } + +AmmRequest ::= SEQUENCE + { + terminationID TerminationIDList, + descriptors SEQUENCE OF AmmDescriptor, + -- At most one descriptor of each type (see AmmDescriptor) + -- allowed in the sequence. + ... + } + +AmmDescriptor ::= CHOICE + { + mediaDescriptor MediaDescriptor, + modemDescriptor ModemDescriptor, + muxDescriptor MuxDescriptor, + eventsDescriptor EventsDescriptor, + eventBufferDescriptor EventBufferDescriptor, + signalsDescriptor SignalsDescriptor, + digitMapDescriptor DigitMapDescriptor, + auditDescriptor AuditDescriptor, + ..., + statisticsDescriptor StatisticsDescriptor + } + + +AmmsReply ::= SEQUENCE + { + terminationID TerminationIDList, + terminationAudit TerminationAudit OPTIONAL, + ... + } + +SubtractRequest ::= SEQUENCE + { + terminationID TerminationIDList, + auditDescriptor AuditDescriptor OPTIONAL, + ... + } + +AuditRequest ::= SEQUENCE + { + terminationID TerminationID, + auditDescriptor AuditDescriptor, + ... + } + +AuditReply ::= CHOICE + { + contextAuditResult TerminationIDList, + error ErrorDescriptor, + auditResult AuditResult, + ... + } + +AuditResult ::= SEQUENCE + { + + terminationID TerminationID, + terminationAuditResult TerminationAudit + } + + + +TerminationAudit ::= SEQUENCE OF AuditReturnParameter + +AuditReturnParameter ::= CHOICE + { + errorDescriptor ErrorDescriptor, + mediaDescriptor MediaDescriptor, + modemDescriptor ModemDescriptor, + muxDescriptor MuxDescriptor, + eventsDescriptor EventsDescriptor, + eventBufferDescriptor EventBufferDescriptor, + signalsDescriptor SignalsDescriptor, + digitMapDescriptor DigitMapDescriptor, + observedEventsDescriptor ObservedEventsDescriptor, + statisticsDescriptor StatisticsDescriptor, + packagesDescriptor PackagesDescriptor, + emptyDescriptors AuditDescriptor, + ... + } + +AuditDescriptor ::= SEQUENCE + { + auditToken BIT STRING + { + muxToken(0), modemToken(1), mediaToken(2), + eventsToken(3), signalsToken(4), + digitMapToken(5), statsToken(6), + observedEventsToken(7), + packagesToken(8), eventBufferToken(9) + } OPTIONAL, + ..., + auditPropertyToken SEQUENCE OF IndAuditParameter OPTIONAL + } + + +IndAuditParameter ::= CHOICE + { + -- Note that the lower/upper case letters of the tags have + -- been changed. The same changes has been made in text... + indAudMediaDescriptor IndAudMediaDescriptor, + indAudEventsDescriptor IndAudEventsDescriptor, + indAudEventBufferDescriptor IndAudEventBufferDescriptor, + indAudSignalsDescriptor IndAudSignalsDescriptor, + indAudDigitMapDescriptor IndAudDigitMapDescriptor, + indAudStatisticsDescriptor IndAudStatisticsDescriptor, + indAudPackagesDescriptor IndAudPackagesDescriptor, + ... + } + +IndAudMediaDescriptor ::= SEQUENCE + { + + termStateDescr IndAudTerminationStateDescriptor OPTIONAL, + streams CHOICE + { + oneStream IndAudStreamParms, + multiStream SEQUENCE OF IndAudStreamDescriptor + } OPTIONAL, + ... + } + +IndAudStreamDescriptor ::= SEQUENCE + { + streamID StreamID, + streamParms IndAudStreamParms + } + +IndAudStreamParms ::= SEQUENCE + { + localControlDescriptor IndAudLocalControlDescriptor OPTIONAL, + localDescriptor IndAudLocalRemoteDescriptor OPTIONAL, + remoteDescriptor IndAudLocalRemoteDescriptor OPTIONAL, + ..., + statisticsDescriptor IndAudStatisticsDescriptor OPTIONAL + } + +IndAudLocalControlDescriptor ::= SEQUENCE + { + streamMode NULL OPTIONAL, + reserveValue NULL OPTIONAL, + reserveGroup NULL OPTIONAL, + propertyParms SEQUENCE OF IndAudPropertyParm OPTIONAL, + ... + } + +IndAudPropertyParm ::= SEQUENCE + { + name PkgdName, + ... + } + +IndAudLocalRemoteDescriptor ::= SEQUENCE + { + propGroupID INTEGER(0..65535) OPTIONAL, + propGrps IndAudPropertyGroup, + ... + } + +IndAudPropertyGroup ::= SEQUENCE OF IndAudPropertyParm + +IndAudTerminationStateDescriptor ::= SEQUENCE + { + propertyParms SEQUENCE OF IndAudPropertyParm, + eventBufferControl NULL OPTIONAL, + serviceState NULL OPTIONAL, + ... + } + +IndAudEventsDescriptor ::= SEQUENCE + { + requestID RequestID OPTIONAL, + pkgdName PkgdName, + streamID StreamID OPTIONAL, + ... + } + +IndAudEventBufferDescriptor ::= SEQUENCE + { + eventName PkgdName, + streamID StreamID OPTIONAL, + ... + } + +IndAudSignalsDescriptor ::=CHOICE + { + signal IndAudSignal, + seqSigList IndAudSeqSigList, + ... + } + +IndAudSeqSigList ::= SEQUENCE + { + id INTEGER(0..65535), + signalList IndAudSignal OPTIONAL + } + +IndAudSignal ::= SEQUENCE + { + signalName PkgdName, + streamID StreamID OPTIONAL, + ... + } + +IndAudDigitMapDescriptor ::= SEQUENCE + { + digitMapName DigitMapName OPTIONAL + } + +IndAudStatisticsDescriptor ::= SEQUENCE + { + statName PkgdName + } + +IndAudPackagesDescriptor ::= SEQUENCE + { + packageName Name, + packageVersion INTEGER(0..99), + ... + } + +NotifyRequest ::= SEQUENCE + { + terminationID TerminationIDList, + observedEventsDescriptor ObservedEventsDescriptor, + errorDescriptor ErrorDescriptor OPTIONAL, + ... + } + +NotifyReply ::= SEQUENCE + { + terminationID TerminationIDList, + errorDescriptor ErrorDescriptor OPTIONAL, + ... + } + +ObservedEventsDescriptor ::= SEQUENCE + { + requestId RequestID, + observedEventLst SEQUENCE OF ObservedEvent + } + +ObservedEvent ::= SEQUENCE + { + eventName EventName, + streamID StreamID OPTIONAL, + eventParList SEQUENCE OF EventParameter, + timeNotation TimeNotation OPTIONAL, + ... + } + +EventName ::= PkgdName + +EventParameter ::= SEQUENCE + { + eventParameterName Name, + value Value, + -- For use of extraInfo see the comment related to PropertyParm + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... + + } + +ServiceChangeRequest ::= SEQUENCE + { + terminationID TerminationIDList, + serviceChangeParms ServiceChangeParm, + ... + } + +ServiceChangeReply ::= SEQUENCE + { + terminationID TerminationIDList, + serviceChangeResult ServiceChangeResult, + ... + } + +-- For ServiceChangeResult, no parameters are mandatory. Hence the +-- distinction between ServiceChangeParm and ServiceChangeResParm. + +ServiceChangeResult ::= CHOICE + { + errorDescriptor ErrorDescriptor, + serviceChangeResParms ServiceChangeResParm + } + +WildcardField ::= OCTET STRING(SIZE(1)) + +TerminationID ::= SEQUENCE + { + wildcard SEQUENCE OF WildcardField, + id OCTET STRING(SIZE(1..8)), + ... + } +-- See A.1 for explanation of wildcarding mechanism. +-- Termination ID 0xFFFFFFFFFFFFFFFF indicates the ROOT Termination. + +TerminationIDList ::= SEQUENCE OF TerminationID + +MediaDescriptor ::= SEQUENCE + { + termStateDescr TerminationStateDescriptor OPTIONAL, + streams CHOICE + { + oneStream StreamParms, + multiStream SEQUENCE OF StreamDescriptor + } OPTIONAL, + ... + } + +StreamDescriptor ::= SEQUENCE + { + streamID StreamID, + streamParms StreamParms + } + +StreamParms ::= SEQUENCE + { + localControlDescriptor LocalControlDescriptor OPTIONAL, + localDescriptor LocalRemoteDescriptor OPTIONAL, + remoteDescriptor LocalRemoteDescriptor OPTIONAL, + ..., + statisticsDescriptor StatisticsDescriptor OPTIONAL + } + +LocalControlDescriptor ::= SEQUENCE + { + streamMode StreamMode OPTIONAL, + reserveValue BOOLEAN OPTIONAL, + reserveGroup BOOLEAN OPTIONAL, + propertyParms SEQUENCE OF PropertyParm, + ... + } + +StreamMode ::= ENUMERATED + { + sendOnly(0), + recvOnly(1), + sendRecv(2), + inactive(3), + loopBack(4), + ... + } + +-- In PropertyParm, value is a SEQUENCE OF octet string. When sent +-- by an MGC the interpretation is as follows: +-- empty sequence means CHOOSE +-- one element sequence specifies value +-- If the sublist field is not selected, a longer sequence means +-- "choose one of the values" (i.e. value1 OR value2 OR ...) +-- If the sublist field is selected, +-- a sequence with more than one element encodes the value of a +-- list-valued property (i.e. value1 AND value2 AND ...). +-- The relation field may only be selected if the value sequence +-- has length 1. It indicates that the MG has to choose a value +-- for the property. E.g. x > 3 (using the greaterThan +-- value for relation) instructs the MG to choose any value larger +-- than 3 for property x. +-- The range field may only be selected if the value sequence +-- has length 2. It indicates that the MG has to choose a value +-- in the range between the first octet in the value sequence and +-- the trailing octet in the value sequence, including the +-- boundary values. +-- When sent by the MG, only responses to an AuditCapability request +-- may contain multiple values, a range, or a relation field. + +PropertyParm ::= SEQUENCE + { + name PkgdName, + value SEQUENCE OF OCTET STRING, + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... + } + +Name ::= OCTET STRING(SIZE(2)) + +PkgdName ::= OCTET STRING(SIZE(4)) +-- represents Package Name (2 octets) plus Property, Event, +-- Signal Names or Statistics ID. (2 octets) +-- To wildcard a package use 0xFFFF for first two octets, choose +-- is not allowed. To reference native property tag specified in +-- Annex C, use 0x0000 as first two octets. +-- To wildcard a Property, Event, Signal, or Statistics ID, use +-- 0xFFFF for last two octets, choose is not allowed. +-- Wildcarding of Package Name is permitted only if Property, +-- Event, Signal, or Statistics ID are +-- also wildcarded. + +Relation ::= ENUMERATED + { + greaterThan(0), + smallerThan(1), + unequalTo(2), + ... + } + +LocalRemoteDescriptor ::= SEQUENCE + { + propGrps SEQUENCE OF PropertyGroup, + ... + } + +PropertyGroup ::= SEQUENCE OF PropertyParm + +TerminationStateDescriptor ::= SEQUENCE + { + propertyParms SEQUENCE OF PropertyParm, + eventBufferControl EventBufferControl OPTIONAL, + serviceState ServiceState OPTIONAL, + ... + } + +EventBufferControl ::= ENUMERATED + { + off(0), + lockStep(1), + ... + } + +ServiceState ::= ENUMERATED + { + test(0), + outOfSvc(1), + inSvc(2), + ... + } + +MuxDescriptor ::= SEQUENCE + { + muxType MuxType, + termList SEQUENCE OF TerminationID, + nonStandardData NonStandardData OPTIONAL, + ... + } + +MuxType ::= ENUMERATED + { + h221(0), + h223(1), + h226(2), + v76(3), + ..., + nx64k(4) + } + +StreamID ::= INTEGER(0..65535) -- 16-bit unsigned integer + +EventsDescriptor ::= SEQUENCE + { + requestID RequestID OPTIONAL, + -- RequestID must be present if eventList + -- is non empty + eventList SEQUENCE OF RequestedEvent, + ... + } + +RequestedEvent ::= SEQUENCE + { + pkgdName PkgdName, + streamID StreamID OPTIONAL, + eventAction RequestedActions OPTIONAL, + evParList SEQUENCE OF EventParameter, + ... + } + +RequestedActions ::= SEQUENCE + { + keepActive BOOLEAN OPTIONAL, + eventDM EventDM OPTIONAL, + secondEvent SecondEventsDescriptor OPTIONAL, + signalsDescriptor SignalsDescriptor OPTIONAL, + ... + } + +EventDM ::= CHOICE + { + digitMapName DigitMapName, + digitMapValue DigitMapValue + } + +SecondEventsDescriptor ::= SEQUENCE + { + requestID RequestID OPTIONAL, + eventList SEQUENCE OF SecondRequestedEvent, + ... + } + +SecondRequestedEvent ::= SEQUENCE + { + pkgdName PkgdName, + streamID StreamID OPTIONAL, + eventAction SecondRequestedActions OPTIONAL, + evParList SEQUENCE OF EventParameter, + ... + } + +SecondRequestedActions ::= SEQUENCE + { + keepActive BOOLEAN OPTIONAL, + eventDM EventDM OPTIONAL, + signalsDescriptor SignalsDescriptor OPTIONAL, + ... + } + +EventBufferDescriptor ::= SEQUENCE OF EventSpec + +EventSpec ::= SEQUENCE + { + eventName EventName, + streamID StreamID OPTIONAL, + eventParList SEQUENCE OF EventParameter, + ... + } + + +SignalsDescriptor ::= SEQUENCE OF SignalRequest + +SignalRequest ::= CHOICE + { + signal Signal, + seqSigList SeqSigList, + ... + } + +SeqSigList ::= SEQUENCE + { + id INTEGER(0..65535), + signalList SEQUENCE OF Signal + } + +Signal ::= SEQUENCE + { + signalName SignalName, + streamID StreamID OPTIONAL, + sigType SignalType OPTIONAL, + duration INTEGER (0..65535) OPTIONAL, + notifyCompletion NotifyCompletion OPTIONAL, + keepActive BOOLEAN OPTIONAL, + sigParList SEQUENCE OF SigParameter, + ..., + direction SignalDirection OPTIONAL, + requestID RequestID OPTIONAL + } + +SignalType ::= ENUMERATED + { + brief(0), + onOff(1), + timeOut(2), + ... + } + +SignalDirection ::= ENUMERATED + { + internal(0), + external(1), + both(3), + ... + } + +SignalName ::= PkgdName + +NotifyCompletion ::= BIT STRING + { + onTimeOut(0), onInterruptByEvent(1), + onInterruptByNewSignalDescr(2), otherReason(3) + } + +SigParameter ::= SEQUENCE + { + sigParameterName Name, + value Value, + -- For use of extraInfo see the comment related to PropertyParm + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... + } + +-- For an AuditCapReply with all events, the RequestID SHALL be ALL. +-- ALL is represented by 0xffffffff. + +RequestID ::= INTEGER(0..4294967295) -- 32-bit unsigned integer + +ModemDescriptor ::= SEQUENCE + { + mtl SEQUENCE OF ModemType, + mpl SEQUENCE OF PropertyParm, + nonStandardData NonStandardData OPTIONAL + } + +ModemType ::= ENUMERATED + { + v18(0), + v22(1), + v22bis(2), + v32(3), + v32bis(4), + v34(5), + v90(6), + v91(7), + synchISDN(8), + ... + } + +DigitMapDescriptor ::= SEQUENCE + { + digitMapName DigitMapName OPTIONAL, + digitMapValue DigitMapValue OPTIONAL + } + +DigitMapName ::= Name + +DigitMapValue ::= SEQUENCE + { + startTimer INTEGER(0..99) OPTIONAL, + shortTimer INTEGER(0..99) OPTIONAL, + longTimer INTEGER(0..99) OPTIONAL, + digitMapBody IA5String, + -- Units are seconds for start, short and long timers, and + -- hundreds of milliseconds for duration timer. Thus start, + -- short, and long range from 1 to 99 seconds and duration + -- from 100 ms to 9.9 s + -- See A.3 for explanation of digit map syntax + ..., + durationTimer INTEGER (0..99) OPTIONAL + } + +ServiceChangeParm ::= SEQUENCE + { + serviceChangeMethod ServiceChangeMethod, + serviceChangeAddress ServiceChangeAddress OPTIONAL, + serviceChangeVersion INTEGER(0..99) OPTIONAL, + serviceChangeProfile ServiceChangeProfile OPTIONAL, + serviceChangeReason Value, + -- A serviceChangeReason consists of a numeric reason code + -- and an optional text description. + -- The serviceChangeReason SHALL be a string consisting of + -- a decimal reason code, optionally followed by a single + -- space character and a textual description string. + -- This string is first BER-encoded as an IA5String. + -- The result of this BER-encoding is then encoded as + -- an ASN.1 OCTET STRING type, "double wrapping" the + -- value + -- as was done for package elements. + serviceChangeDelay INTEGER(0..4294967295) OPTIONAL, + -- 32-bit unsigned integer + serviceChangeMgcId MId OPTIONAL, + timeStamp TimeNotation OPTIONAL, + nonStandardData NonStandardData OPTIONAL, + ..., + serviceChangeInfo AuditDescriptor OPTIONAL, + serviceChangeIncompleteFlag NULL OPTIONAL + } + +ServiceChangeAddress ::= CHOICE + { + portNumber INTEGER(0..65535), -- TCP/UDP port number + ip4Address IP4Address, + ip6Address IP6Address, + domainName DomainName, + deviceName PathName, + mtpAddress OCTET STRING(SIZE(2..4)), + ... + } + +ServiceChangeResParm ::= SEQUENCE + { + serviceChangeMgcId MId OPTIONAL, + serviceChangeAddress ServiceChangeAddress OPTIONAL, + serviceChangeVersion INTEGER(0..99) OPTIONAL, + serviceChangeProfile ServiceChangeProfile OPTIONAL, + timestamp TimeNotation OPTIONAL, + ... + } + +ServiceChangeMethod ::= ENUMERATED + { + failover(0), + forced(1), + graceful(2), + restart(3), + disconnected(4), + handOff(5), + ... + } + +ServiceChangeProfile ::= SEQUENCE + { + profileName IA5String(SIZE (1..67)) + + -- 64 characters for name, 1 for "/", 2 for version to match ABNF + } + +PackagesDescriptor ::= SEQUENCE OF PackagesItem +PackagesItem ::= SEQUENCE + { + packageName Name, + packageVersion INTEGER(0..99), + ... + } + +StatisticsDescriptor ::= SEQUENCE OF StatisticsParameter + +StatisticsParameter ::= SEQUENCE + { + statName PkgdName, + statValue Value OPTIONAL + } + +NonStandardData ::= SEQUENCE + { + nonStandardIdentifier NonStandardIdentifier, + data OCTET STRING + } + +NonStandardIdentifier ::= CHOICE + { + object OBJECT IDENTIFIER, + h221NonStandard H221NonStandard, + experimental IA5String(SIZE(8)), + -- first two characters SHOULD be "X-" or "X+" + ... + } + +H221NonStandard ::= SEQUENCE + { t35CountryCode1 INTEGER(0..255), + t35CountryCode2 INTEGER(0..255), -- country, as per T.35 + t35Extension INTEGER(0..255), -- assigned nationally + manufacturerCode INTEGER(0..65535), -- assigned nationally + ... + } + +TimeNotation ::= SEQUENCE + { + date IA5String(SIZE(8)), -- yyyymmdd format + time IA5String(SIZE(8)) -- hhmmssss format + -- per ISO 8601:1988 + } + +Value ::= SEQUENCE OF OCTET STRING + +END diff --git a/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-prev3c.asn b/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-prev3c.asn new file mode 100644 index 0000000000..cb6940e8b0 --- /dev/null +++ b/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-prev3c.asn @@ -0,0 +1,1073 @@ +MEDIA-GATEWAY-CONTROL-prev3c +{itu-t(0) recommendation(0) h(8) h248(248) + modules(0) media-gateway-control(0) version3(3)} +DEFINITIONS AUTOMATIC TAGS ::= +BEGIN + + +MegacoMessage ::= SEQUENCE + { + authHeader AuthenticationHeader OPTIONAL, + mess Message + } + +AuthenticationHeader ::= SEQUENCE + { + secParmIndex SecurityParmIndex, + seqNum SequenceNum, + ad AuthData + } + +SecurityParmIndex ::= OCTET STRING(SIZE(4)) + +SequenceNum ::= OCTET STRING(SIZE(4)) + +AuthData ::= OCTET STRING (SIZE (12..32)) + +Message ::= SEQUENCE + { + version INTEGER(0..99), + -- The version of the protocol defined here is equal to 3. + mId MId, -- Name/address of message originator + messageBody CHOICE + { + messageError ErrorDescriptor, + transactions SEQUENCE OF Transaction + }, + ... + } + +MId ::= CHOICE + { + ip4Address IP4Address, + ip6Address IP6Address, + domainName DomainName, + deviceName PathName, + mtpAddress OCTET STRING(SIZE(2..4)), + -- Addressing structure of mtpAddress: + -- 25 - 15 0 + -- | PC | NI | + -- 24 - 14 bits 2 bits + -- Note: 14 bits are defined for international use. + -- Two national options exist where the point code is 16 or 24 + -- bits. + -- To octet align the mtpAddress, the MSBs shall be encoded as 0s. + ... + } + +DomainName ::= SEQUENCE + { + name IA5String, + -- The name starts with an alphanumeric digit followed by a + -- sequence of alphanumeric digits, hyphens and dots. No two + -- dots shall occur consecutively. + portNumber INTEGER(0..65535) OPTIONAL + } + +IP4Address ::= SEQUENCE + { + address OCTET STRING (SIZE(4)), + portNumber INTEGER(0..65535) OPTIONAL + } + +IP6Address ::= SEQUENCE + { + address OCTET STRING (SIZE(16)), + portNumber INTEGER(0..65535) OPTIONAL + } + +PathName ::= IA5String(SIZE (1..64)) +-- See A.3 + +Transaction ::= CHOICE + { + transactionRequest TransactionRequest, + transactionPending TransactionPending, + transactionReply TransactionReply, + transactionResponseAck TransactionResponseAck, + -- use of response acks is dependent on underlying transport + ... + -- segmentReply SegmentReply + } + +TransactionId ::= INTEGER(0..4294967295) -- 32-bit unsigned integer + +TransactionRequest ::= SEQUENCE + { + transactionId TransactionId, + actions SEQUENCE OF ActionRequest, + ... + } + +TransactionPending ::= SEQUENCE + { + transactionId TransactionId, + ... + } + +TransactionReply ::= SEQUENCE + { + transactionId TransactionId, + immAckRequired NULL OPTIONAL, + transactionResult CHOICE + { + transactionError ErrorDescriptor, + actionReplies SEQUENCE OF ActionReply + }, + ..., + -- Erlang Note: NOT REALLY PART OF THIS IMPLEMENTATION + -- Erlang Note: The only reason why we need to include + -- Erlang Note: these definitions in this version is + -- Erlang Note: that we cannot distinguish between v3 + -- Erlang Note: versions in the megaco_messenger module + segmentNumber SegmentNumber OPTIONAL, + segmentationComplete NULL OPTIONAL + } + +-- SegmentReply ::= SEQUENCE +-- { +-- transactionId TransactionId, +-- segmentNumber SegmentNumber, +-- segmentationComplete NULL OPTIONAL, +-- ... +-- } +-- +SegmentNumber ::= INTEGER(0..65535) + +TransactionResponseAck ::= SEQUENCE OF TransactionAck +TransactionAck ::= SEQUENCE + { + firstAck TransactionId, + lastAck TransactionId OPTIONAL + } + +ErrorDescriptor ::= SEQUENCE + { + errorCode ErrorCode, + errorText ErrorText OPTIONAL + } + +ErrorCode ::= INTEGER(0..65535) +-- See clause 14 for IANA considerations with respect to error codes +ErrorText ::= IA5String + +ContextID ::= INTEGER(0..4294967295) +-- Context NULL Value: 0 +-- Context CHOOSE Value: 4294967294 (0xFFFFFFFE) +-- Context ALL Value: 4294967295 (0xFFFFFFFF) + + +ActionRequest ::= SEQUENCE + { + contextId ContextID, + contextRequest ContextRequest OPTIONAL, + contextAttrAuditReq ContextAttrAuditRequest OPTIONAL, + commandRequests SEQUENCE OF CommandRequest + } + +ActionReply ::= SEQUENCE + { + contextId ContextID, + errorDescriptor ErrorDescriptor OPTIONAL, + contextReply ContextRequest OPTIONAL, + commandReply SEQUENCE OF CommandReply + } + +ContextRequest ::= SEQUENCE + { + priority INTEGER(0..15) OPTIONAL, + emergency BOOLEAN OPTIONAL, + topologyReq SEQUENCE OF TopologyRequest OPTIONAL, + ..., + iepscallind BOOLEAN OPTIONAL, + contextProp SEQUENCE OF PropertyParm OPTIONAL, + contextList SEQUENCE OF ContextID OPTIONAL + } +-- When returning a contextList, the contextId in the ActionReply +-- construct will return the contextId from the associated ActionRequest. + +ContextAttrAuditRequest ::= SEQUENCE + { + topology NULL OPTIONAL, + emergency NULL OPTIONAL, + priority NULL OPTIONAL, + ..., + iepscallind NULL OPTIONAL, + contextPropAud SEQUENCE OF IndAudPropertyParm OPTIONAL, + + selectpriority INTEGER(0..15) OPTIONAL, + -- to select given priority + + selectemergency BOOLEAN OPTIONAL, + -- to select if emergency set/not set (T/F) + + selectiepscallind BOOLEAN OPTIONAL, + -- to select if IEPS set/not set (T/F) + + selectLogic SelectLogic OPTIONAL -- default is AND + } + +SelectLogic ::= CHOICE + { + andAUDITSelect NULL, -- all selection conditions satisfied + orAUDITSelect NULL, -- at least one selection condition satisfied + ... + } + + +CommandRequest ::= SEQUENCE + { + command Command, + optional NULL OPTIONAL, + wildcardReturn NULL OPTIONAL, + ... + } + +Command ::= CHOICE + { + addReq AmmRequest, + moveReq AmmRequest, + modReq AmmRequest, + -- Add, Move, Modify requests have the same parameters + subtractReq SubtractRequest, + auditCapRequest AuditRequest, + auditValueRequest AuditRequest, + notifyReq NotifyRequest, + serviceChangeReq ServiceChangeRequest, + ... + } + +CommandReply ::= CHOICE + { + addReply AmmsReply, + moveReply AmmsReply, + modReply AmmsReply, + subtractReply AmmsReply, + -- Add, Move, Modify, Subtract replies have the same parameters + auditCapReply AuditReply, + auditValueReply AuditReply, + notifyReply NotifyReply, + serviceChangeReply ServiceChangeReply, + ... + } + +TopologyRequest ::= SEQUENCE + { + terminationFrom TerminationID, + terminationTo TerminationID, + topologyDirection ENUMERATED + { + bothway(0), + isolate(1), + oneway(2) + }, + ..., + streamID StreamID OPTIONAL, + topologyDirectionExtension ENUMERATED + { + onewayexternal(0), + onewayboth(1), + ... + } OPTIONAL + -- This is not according to the standard, but without it + -- the TopologyRequest will be useless since topologyDirection + -- and topologyDirectionExtension are contradictory. + } + +AmmRequest ::= SEQUENCE + { + terminationID TerminationIDList, + descriptors SEQUENCE OF AmmDescriptor, + -- At most one descriptor of each type (see AmmDescriptor) + -- allowed in the sequence. + ... + } + +AmmDescriptor ::= CHOICE + { + mediaDescriptor MediaDescriptor, + modemDescriptor ModemDescriptor, + muxDescriptor MuxDescriptor, + eventsDescriptor EventsDescriptor, + eventBufferDescriptor EventBufferDescriptor, + signalsDescriptor SignalsDescriptor, + digitMapDescriptor DigitMapDescriptor, + auditDescriptor AuditDescriptor, + ..., + statisticsDescriptor StatisticsDescriptor + } + + +AmmsReply ::= SEQUENCE + { + terminationID TerminationIDList, + terminationAudit TerminationAudit OPTIONAL, + ... + } + +SubtractRequest ::= SEQUENCE + { + terminationID TerminationIDList, + auditDescriptor AuditDescriptor OPTIONAL, + ... + } + +AuditRequest ::= SEQUENCE + { + terminationID TerminationID, + auditDescriptor AuditDescriptor, + ..., + terminationIDList TerminationIDList OPTIONAL + } +-- terminationID shall contain the first termination in the +-- list when using the terminationIDList construct in AuditRequest + +AuditReply ::= CHOICE + { + contextAuditResult TerminationIDList, + error ErrorDescriptor, + auditResult AuditResult, + ..., + auditResultTermList TermListAuditResult + } + +AuditResult ::= SEQUENCE + { + + terminationID TerminationID, + terminationAuditResult TerminationAudit + } + +TermListAuditResult ::= SEQUENCE + { + terminationIDList TerminationIDList, + terminationAuditResult TerminationAudit, + ... + } + +TerminationAudit ::= SEQUENCE OF AuditReturnParameter + +AuditReturnParameter ::= CHOICE + { + errorDescriptor ErrorDescriptor, + mediaDescriptor MediaDescriptor, + modemDescriptor ModemDescriptor, + muxDescriptor MuxDescriptor, + eventsDescriptor EventsDescriptor, + eventBufferDescriptor EventBufferDescriptor, + signalsDescriptor SignalsDescriptor, + digitMapDescriptor DigitMapDescriptor, + observedEventsDescriptor ObservedEventsDescriptor, + statisticsDescriptor StatisticsDescriptor, + packagesDescriptor PackagesDescriptor, + emptyDescriptors AuditDescriptor, + ... + } + +AuditDescriptor ::= SEQUENCE + { + auditToken BIT STRING + { + muxToken(0), modemToken(1), mediaToken(2), + eventsToken(3), signalsToken(4), + digitMapToken(5), statsToken(6), + observedEventsToken(7), + packagesToken(8), eventBufferToken(9) + } OPTIONAL, + ..., + auditPropertyToken SEQUENCE OF IndAuditParameter OPTIONAL + } + + +IndAuditParameter ::= CHOICE + { + -- Note that the lower/upper case letters of the tags have + -- been changed. The same changes has been made in text... + indAudMediaDescriptor IndAudMediaDescriptor, + indAudEventsDescriptor IndAudEventsDescriptor, + indAudEventBufferDescriptor IndAudEventBufferDescriptor, + indAudSignalsDescriptor IndAudSignalsDescriptor, + indAudDigitMapDescriptor IndAudDigitMapDescriptor, + indAudStatisticsDescriptor IndAudStatisticsDescriptor, + indAudPackagesDescriptor IndAudPackagesDescriptor, + ... + } + +IndAudMediaDescriptor ::= SEQUENCE + { + + termStateDescr IndAudTerminationStateDescriptor OPTIONAL, + streams CHOICE + { + oneStream IndAudStreamParms, + multiStream SEQUENCE OF IndAudStreamDescriptor + } OPTIONAL, + ... + } + +IndAudStreamDescriptor ::= SEQUENCE + { + streamID StreamID, + streamParms IndAudStreamParms + } + +IndAudStreamParms ::= SEQUENCE + { + localControlDescriptor IndAudLocalControlDescriptor OPTIONAL, + localDescriptor IndAudLocalRemoteDescriptor OPTIONAL, + remoteDescriptor IndAudLocalRemoteDescriptor OPTIONAL, + ..., + statisticsDescriptor IndAudStatisticsDescriptor OPTIONAL + } + +IndAudLocalControlDescriptor ::= SEQUENCE + { + streamMode NULL OPTIONAL, + reserveValue NULL OPTIONAL, + reserveGroup NULL OPTIONAL, + propertyParms SEQUENCE OF IndAudPropertyParm OPTIONAL, + ..., + streamModeSel StreamMode OPTIONAL + -- must not have both streamMode and streamModeSel + -- if both are present only streamModeSel shall be honoured + } + +IndAudPropertyParm ::= SEQUENCE + { + name PkgdName, + ..., + propertyParms PropertyParm OPTIONAL + } +-- to select based on property values +-- AND/OR selection logic is specified at context level + +IndAudLocalRemoteDescriptor ::= SEQUENCE + { + propGroupID INTEGER(0..65535) OPTIONAL, + propGrps IndAudPropertyGroup, + ... + } + +IndAudPropertyGroup ::= SEQUENCE OF IndAudPropertyParm + +IndAudTerminationStateDescriptor ::= SEQUENCE + { + propertyParms SEQUENCE OF IndAudPropertyParm, + eventBufferControl NULL OPTIONAL, + serviceState NULL OPTIONAL, + ..., + serviceStateSel ServiceState OPTIONAL + -- must not have both serviceState and serviceStateSel + -- if both are present only serviceStateSel shall be honoured + } + +IndAudEventsDescriptor ::= SEQUENCE + { + requestID RequestID OPTIONAL, + pkgdName PkgdName, + streamID StreamID OPTIONAL, + ... + } + +IndAudEventBufferDescriptor ::= SEQUENCE + { + eventName PkgdName, + streamID StreamID OPTIONAL, + ... + } + +IndAudSignalsDescriptor ::=CHOICE + { + signal IndAudSignal, + seqSigList IndAudSeqSigList, + ... + } + +IndAudSeqSigList ::= SEQUENCE + { + id INTEGER(0..65535), + signalList IndAudSignal OPTIONAL + } + +IndAudSignal ::= SEQUENCE + { + signalName PkgdName, + streamID StreamID OPTIONAL, + ..., + signalRequestID RequestID OPTIONAL + } + +IndAudDigitMapDescriptor ::= SEQUENCE + { + digitMapName DigitMapName OPTIONAL + } + +IndAudStatisticsDescriptor ::= SEQUENCE + { + statName PkgdName + } + +IndAudPackagesDescriptor ::= SEQUENCE + { + packageName Name, + packageVersion INTEGER(0..99), + ... + } + +NotifyRequest ::= SEQUENCE + { + terminationID TerminationIDList, + observedEventsDescriptor ObservedEventsDescriptor, + errorDescriptor ErrorDescriptor OPTIONAL, + ... + } + +NotifyReply ::= SEQUENCE + { + terminationID TerminationIDList, + errorDescriptor ErrorDescriptor OPTIONAL, + ... + } + +ObservedEventsDescriptor ::= SEQUENCE + { + requestId RequestID, + observedEventLst SEQUENCE OF ObservedEvent + } + +ObservedEvent ::= SEQUENCE + { + eventName EventName, + streamID StreamID OPTIONAL, + eventParList SEQUENCE OF EventParameter, + timeNotation TimeNotation OPTIONAL, + ... + } + +EventName ::= PkgdName + +EventParameter ::= SEQUENCE + { + eventParameterName Name, + value Value, + -- For use of extraInfo see the comment related to PropertyParm + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... + + } + +ServiceChangeRequest ::= SEQUENCE + { + terminationID TerminationIDList, + serviceChangeParms ServiceChangeParm, + ... + } + +ServiceChangeReply ::= SEQUENCE + { + terminationID TerminationIDList, + serviceChangeResult ServiceChangeResult, + ... + } + +-- For ServiceChangeResult, no parameters are mandatory. Hence the +-- distinction between ServiceChangeParm and ServiceChangeResParm. +ServiceChangeResult ::= CHOICE + { + errorDescriptor ErrorDescriptor, + serviceChangeResParms ServiceChangeResParm + } + +WildcardField ::= OCTET STRING(SIZE(1)) + +TerminationID ::= SEQUENCE + { + wildcard SEQUENCE OF WildcardField, + id OCTET STRING(SIZE(1..8)), + ... + } +-- See A.1 for explanation of wildcarding mechanism. +-- Termination ID 0xFFFFFFFFFFFFFFFF indicates the ROOT Termination. + +TerminationIDList ::= SEQUENCE OF TerminationID + +MediaDescriptor ::= SEQUENCE + { + termStateDescr TerminationStateDescriptor OPTIONAL, + streams CHOICE + { + oneStream StreamParms, + multiStream SEQUENCE OF StreamDescriptor + } OPTIONAL, + ... + } + +StreamDescriptor ::= SEQUENCE + { + streamID StreamID, + streamParms StreamParms + } + +StreamParms ::= SEQUENCE + { + localControlDescriptor LocalControlDescriptor OPTIONAL, + localDescriptor LocalRemoteDescriptor OPTIONAL, + remoteDescriptor LocalRemoteDescriptor OPTIONAL, + ..., + statisticsDescriptor StatisticsDescriptor OPTIONAL + } + +LocalControlDescriptor ::= SEQUENCE + { + streamMode StreamMode OPTIONAL, + reserveValue BOOLEAN OPTIONAL, + reserveGroup BOOLEAN OPTIONAL, + propertyParms SEQUENCE OF PropertyParm, + ... + } + +StreamMode ::= ENUMERATED + { + sendOnly(0), + recvOnly(1), + sendRecv(2), + inactive(3), + loopBack(4), + ... + } + +-- In PropertyParm, value is a SEQUENCE OF octet string. When sent +-- by an MGC the interpretation is as follows: +-- empty sequence means CHOOSE +-- one element sequence specifies value +-- If the sublist field is not selected, a longer sequence means +-- "choose one of the values" (i.e. value1 OR value2 OR ...) +-- If the sublist field is selected, +-- a sequence with more than one element encodes the value of a +-- list-valued property (i.e. value1 AND value2 AND ...). +-- The relation field may only be selected if the value sequence +-- has length 1. It indicates that the MG has to choose a value +-- for the property. E.g. x > 3 (using the greaterThan +-- value for relation) instructs the MG to choose any value larger +-- than 3 for property x. +-- The range field may only be selected if the value sequence +-- has length 2. It indicates that the MG has to choose a value +-- in the range between the first octet in the value sequence and +-- the trailing octet in the value sequence, including the +-- boundary values. +-- When sent by the MG, only responses to an AuditCapability request +-- may contain multiple values, a range, or a relation field. + +PropertyParm ::= SEQUENCE + { + name PkgdName, + value SEQUENCE OF OCTET STRING, + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... + } + +Name ::= OCTET STRING(SIZE(2)) + +PkgdName ::= OCTET STRING(SIZE(4)) +-- represents Package Name (2 octets) plus Property, Event, +-- Signal Names or Statistics ID. (2 octets) +-- To wildcard a package use 0xFFFF for first two octets, choose +-- is not allowed. To reference native property tag specified in +-- Annex C, use 0x0000 as first two octets. +-- To wildcard a Property, Event, Signal, or Statistics ID, use +-- 0xFFFF for last two octets, choose is not allowed. +-- Wildcarding of Package Name is permitted only if Property, +-- Event, Signal, or Statistics ID are +-- also wildcarded. + +Relation ::= ENUMERATED + { + greaterThan(0), + smallerThan(1), + unequalTo(2), + ... + } + +LocalRemoteDescriptor ::= SEQUENCE + { + propGrps SEQUENCE OF PropertyGroup, + ... + } + +PropertyGroup ::= SEQUENCE OF PropertyParm + +TerminationStateDescriptor ::= SEQUENCE + { + propertyParms SEQUENCE OF PropertyParm, + eventBufferControl EventBufferControl OPTIONAL, + serviceState ServiceState OPTIONAL, + ... + } + +EventBufferControl ::= ENUMERATED + { + off(0), + lockStep(1), + ... + } + +ServiceState ::= ENUMERATED + { + test(0), + outOfSvc(1), + inSvc(2), + ... + } + +MuxDescriptor ::= SEQUENCE + { + muxType MuxType, + termList SEQUENCE OF TerminationID, + nonStandardData NonStandardData OPTIONAL, + ... + } + +MuxType ::= ENUMERATED + { + h221(0), + h223(1), + h226(2), + v76(3), + ..., + nx64k(4) + } + +StreamID ::= INTEGER(0..65535) -- 16-bit unsigned integer + +EventsDescriptor ::= SEQUENCE + { + requestID RequestID OPTIONAL, + -- RequestID must be present if eventList + -- is non empty + eventList SEQUENCE OF RequestedEvent, + ... + } + +RequestedEvent ::= SEQUENCE + { + pkgdName PkgdName, + streamID StreamID OPTIONAL, + eventAction RequestedActions OPTIONAL, + evParList SEQUENCE OF EventParameter, + ... + } + +RegulatedEmbeddedDescriptor ::= SEQUENCE + { + secondEvent SecondEventsDescriptor OPTIONAL, + signalsDescriptor SignalsDescriptor OPTIONAL, + ... + } + +NotifyBehaviour ::= CHOICE + { + notifyImmediate NULL, + notifyRegulated RegulatedEmbeddedDescriptor, + neverNotify NULL, + ... + } + +RequestedActions ::= SEQUENCE + { + keepActive BOOLEAN OPTIONAL, + eventDM EventDM OPTIONAL, + secondEvent SecondEventsDescriptor OPTIONAL, + signalsDescriptor SignalsDescriptor OPTIONAL, + ..., + notifyBehaviour NotifyBehaviour OPTIONAL, + resetEventsDescriptor NULL OPTIONAL + } + +EventDM ::= CHOICE + { + digitMapName DigitMapName, + digitMapValue DigitMapValue + } + +SecondEventsDescriptor ::= SEQUENCE + { + requestID RequestID OPTIONAL, + eventList SEQUENCE OF SecondRequestedEvent, + ... + } + +SecondRequestedEvent ::= SEQUENCE + { + pkgdName PkgdName, + streamID StreamID OPTIONAL, + eventAction SecondRequestedActions OPTIONAL, + evParList SEQUENCE OF EventParameter, + ... + } + +SecondRequestedActions ::= SEQUENCE + { + keepActive BOOLEAN OPTIONAL, + eventDM EventDM OPTIONAL, + signalsDescriptor SignalsDescriptor OPTIONAL, + ..., + notifyBehaviour NotifyBehaviour OPTIONAL, + resetEventsDescriptor NULL OPTIONAL + } + +EventBufferDescriptor ::= SEQUENCE OF EventSpec + +EventSpec ::= SEQUENCE + { + eventName EventName, + streamID StreamID OPTIONAL, + eventParList SEQUENCE OF EventParameter, + ... + } + + +SignalsDescriptor ::= SEQUENCE OF SignalRequest + +SignalRequest ::= CHOICE + { + signal Signal, + seqSigList SeqSigList, + ... + } + +SeqSigList ::= SEQUENCE + { + id INTEGER(0..65535), + signalList SEQUENCE OF Signal + } + +Signal ::= SEQUENCE + { + signalName SignalName, + streamID StreamID OPTIONAL, + sigType SignalType OPTIONAL, + duration INTEGER (0..65535) OPTIONAL, + notifyCompletion NotifyCompletion OPTIONAL, + keepActive BOOLEAN OPTIONAL, + sigParList SEQUENCE OF SigParameter, + ..., + direction SignalDirection OPTIONAL, + requestID RequestID OPTIONAL, + intersigDelay INTEGER (0..65535) OPTIONAL + } + +SignalType ::= ENUMERATED + { + brief(0), + onOff(1), + timeOut(2), + ... + } + +SignalDirection ::= ENUMERATED + { + internal(0), + external(1), + both(3), + ... + } + +SignalName ::= PkgdName + +NotifyCompletion ::= BIT STRING + { + onTimeOut(0), onInterruptByEvent(1), + onInterruptByNewSignalDescr(2), otherReason(3), onIteration(4) + } + +SigParameter ::= SEQUENCE + { + sigParameterName Name, + value Value, + -- For use of extraInfo see the comment related to PropertyParm + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... + } + +-- For an AuditCapReply with all events, the RequestID SHALL be ALL. +-- ALL is represented by 0xffffffff. +RequestID ::= INTEGER(0..4294967295) -- 32-bit unsigned integer + +ModemDescriptor ::= SEQUENCE + { + mtl SEQUENCE OF ModemType, + mpl SEQUENCE OF PropertyParm, + nonStandardData NonStandardData OPTIONAL + } + +ModemType ::= ENUMERATED + { + v18(0), + v22(1), + v22bis(2), + v32(3), + v32bis(4), + v34(5), + v90(6), + v91(7), + synchISDN(8), + ... + } + +DigitMapDescriptor ::= SEQUENCE + { + digitMapName DigitMapName OPTIONAL, + digitMapValue DigitMapValue OPTIONAL + } + +DigitMapName ::= Name + +DigitMapValue ::= SEQUENCE + { + startTimer INTEGER(0..99) OPTIONAL, + shortTimer INTEGER(0..99) OPTIONAL, + longTimer INTEGER(0..99) OPTIONAL, + digitMapBody IA5String, + -- Units are seconds for start, short and long timers, and + -- hundreds of milliseconds for duration timer. Thus start, + -- short, and long range from 1 to 99 seconds and duration + -- from 100 ms to 9.9 s + -- See A.3 for explanation of digit map syntax + ..., + durationTimer INTEGER (0..99) OPTIONAL + } + +ServiceChangeParm ::= SEQUENCE + { + serviceChangeMethod ServiceChangeMethod, + serviceChangeAddress ServiceChangeAddress OPTIONAL, + serviceChangeVersion INTEGER(0..99) OPTIONAL, + serviceChangeProfile ServiceChangeProfile OPTIONAL, + serviceChangeReason Value, + -- A serviceChangeReason consists of a numeric reason code + -- and an optional text description. + -- The serviceChangeReason SHALL be a string consisting of + -- a decimal reason code, optionally followed by a single + -- space character and a textual description string. + -- This string is first BER-encoded as an IA5String. + -- The result of this BER-encoding is then encoded as + -- an ASN.1 OCTET STRING type, "double wrapping" the + -- value + -- as was done for package elements. + serviceChangeDelay INTEGER(0..4294967295) OPTIONAL, + -- 32-bit unsigned integer + serviceChangeMgcId MId OPTIONAL, + timeStamp TimeNotation OPTIONAL, + nonStandardData NonStandardData OPTIONAL, + ..., + serviceChangeInfo AuditDescriptor OPTIONAL, + serviceChangeIncompleteFlag NULL OPTIONAL + } + +ServiceChangeAddress ::= CHOICE + { + portNumber INTEGER(0..65535), -- TCP/UDP port number + ip4Address IP4Address, + ip6Address IP6Address, + domainName DomainName, + deviceName PathName, + mtpAddress OCTET STRING(SIZE(2..4)), + ... + } + +ServiceChangeResParm ::= SEQUENCE + { + serviceChangeMgcId MId OPTIONAL, + serviceChangeAddress ServiceChangeAddress OPTIONAL, + serviceChangeVersion INTEGER(0..99) OPTIONAL, + serviceChangeProfile ServiceChangeProfile OPTIONAL, + timestamp TimeNotation OPTIONAL, + ... + } + +ServiceChangeMethod ::= ENUMERATED + { + failover(0), + forced(1), + graceful(2), + restart(3), + disconnected(4), + handOff(5), + ... + } + +ServiceChangeProfile ::= SEQUENCE + { + profileName IA5String(SIZE (1..67)) + + -- 64 characters for name, 1 for "/", 2 for version to match ABNF + } + +PackagesDescriptor ::= SEQUENCE OF PackagesItem + +PackagesItem ::= SEQUENCE + { + packageName Name, + packageVersion INTEGER(0..99), + ... + } + +StatisticsDescriptor ::= SEQUENCE OF StatisticsParameter + +StatisticsParameter ::= SEQUENCE + { + statName PkgdName, + statValue Value OPTIONAL + } + +-- If statistic consists of a sub-list there will be more than one +-- octetstring in statValue. + +NonStandardData ::= SEQUENCE + { + nonStandardIdentifier NonStandardIdentifier, + data OCTET STRING + } + +NonStandardIdentifier ::= CHOICE + { + object OBJECT IDENTIFIER, + h221NonStandard H221NonStandard, + experimental IA5String(SIZE(8)), + -- first two characters SHOULD be "X-" or "X+" + ... + } + +H221NonStandard ::= SEQUENCE + { t35CountryCode1 INTEGER(0..255), + t35CountryCode2 INTEGER(0..255), -- country, as per T.35 + t35Extension INTEGER(0..255), -- assigned nationally + manufacturerCode INTEGER(0..65535), -- assigned nationally + ... + } + +TimeNotation ::= SEQUENCE + { + date IA5String(SIZE(8)), -- yyyymmdd format + time IA5String(SIZE(8)) -- hhmmssss format + -- per ISO 8601:1988 + } + +Value ::= SEQUENCE OF OCTET STRING + +END diff --git a/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-v1.asn b/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-v1.asn new file mode 100644 index 0000000000..717517938f --- /dev/null +++ b/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-v1.asn @@ -0,0 +1,982 @@ +-- This ASN.1 spec has been extracted from the Megaco/H.248 spec +-- http://www.ietf.org/internet-drafts/draft-ietf-megaco-merged-01.txt +-- +-- o Removed stuff named nonStandard +-- o Major enhancements of the indentation has been performed. +-- +-- Hakan Mattsson <[email protected]> +-- +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +-- ANNEX A: BINARY ENCODING OF THE PROTOCOL (NORMATIVE) +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +-- +-- This Annex specifies the syntax of messages using the notation +-- defined in ASN.1 [ITU-T Recommendation X.680 (1997): Information +-- Technology - Abstract Syntax Notation One (ASN.1) - Specification of +-- basic notation.]. Messages shall be encoded for transmission by +-- applying the basic encoding rules specified in [ITU-T Recommendation +-- X.690(1994) Information Technology - ASN.1 Encoding Rules: +-- Specification of Basic Encoding Rules (BER)]. +-- +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +-- A.1 Coding of wildcards +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +-- +-- The use of wildcards ALL and CHOOSE is allowed in the protocol. +-- This allows a MGC to partially specify Termination IDs and let the +-- MG choose from the values that conform to the partial specification. +-- Termination IDs may encode a hierarchy of names. This hierarchy is +-- provisioned. For instance, a TerminationID may consist of a trunk +-- group, a trunk within the group and a circuit. Wildcarding must be +-- possible at all levels. The following paragraphs explain how this +-- is achieved. +-- +-- The ASN.1 description uses octet strings of up to 8 octets in length +-- for Termination IDs. This means that Termination IDs consist of at +-- most 64 bits. A fully specified Termination ID may be preceded by a +-- sequence of wildcarding fields. A wildcarding field is one octet in +-- length. Bit 7 (the most significant bit) of this octet specifies +-- what type of wildcarding is invoked: if the bit value equals 1, +-- then the ALL wildcard is used; if the bit value if 0, then the +-- CHOOSE wildcard is used. Bit 6 of the wildcarding field specifies +-- whether the wildcarding pertains to one level in the hierarchical +-- naming scheme (bit value 0) or to the level of the hierarchy +-- specified in the wildcarding field plus all lower levels (bit value +-- 1). Bits 0 through 5 of the wildcarding field specify the bit +-- position in the Termination ID at which the starts. +-- +-- We illustrate this scheme with some examples. In these examples, +-- the most significant bit in a string of bits appears on the left +-- hand side. +-- +-- Assume that Termination IDs are three octets long and that each +-- octet represents a level in a hierarchical naming scheme. A valid +-- Termination ID is +-- 00000001 00011110 01010101. +-- +-- Addressing ALL names with prefix 00000001 00011110 is done as +-- follows: +-- wildcarding field: 10000111 +-- Termination ID: 00000001 00011110 xxxxxxxx. +-- +-- The values of the bits labeled "x" is irrelevant and shall be +-- ignored by the receiver. +-- +-- Indicating to the receiver that is must choose a name with 00011110 +-- as the second octet is done as follows: +-- wildcarding fields: 00010111 followed by 00000111 +-- Termination ID: xxxxxxxx 00011110 xxxxxxxx. +-- +-- The first wildcard field indicates a CHOOSE wildcard for the level +-- in the naming hierarchy starting at bit 23, the highest level in our +-- assumed naming scheme. The second wildcard field indicates a CHOOSE +-- wildcard for the level in the naming hierarchy starting at bit 7, +-- the lowest level in our assumed naming scheme. +-- +-- Finally, a CHOOSE-wildcarded name with the highest level of the name +-- equal to 00000001 is specified as follows: +-- wildcard field: 01001111 +-- Termination ID: 0000001 xxxxxxxx xxxxxxxx . +-- +-- Bit value 1 at bit position 6 of the first octet of the wildcard +-- field indicates that the wildcarding pertains to the specified level +-- in the naming hierarchy and all lower levels. +-- +-- Context IDs may also be wildcarded. In the case of Context IDs, +-- however, specifying partial names is not allowed. Context ID 0x0 +-- SHALL be used to indicate the NULL Context, Context ID 0xFFFFFFFE +-- SHALL be used to indicate a CHOOSE wildcard, and Context ID +-- 0xFFFFFFFF SHALL be used to indicate an ALL wildcard. +-- +-- TerminationID 0xFFFFFFFFFFFFFFFF SHALL be used to indicate the ROOT +-- Termination. +-- +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +-- Digit maps and path names +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +-- +-- From a syntactic viewpoint, digit maps are strings with syntactic +-- restrictions imposed upon them. The syntax of valid digit maps is +-- specified in ABNF [RFC 2234]. The syntax for digit maps presented +-- in this section is for illustrative purposes only. The definition of +-- digitMap in Annex B takes precedence in the case of differences +-- between the two. +-- +-- digitMap = (digitString / LWSP "(" LWSP digitStringList LWSP ")" +-- LWSP) +-- digitStringList = digitString *( LWSP "/" LWSP digitString ) +-- digitString = 1*(digitStringElement) +-- digitStringElement = digitPosition [DOT] +-- digitPosition = digitMapLetter / digitMapRange +-- digitMapRange = ("x" / LWSP "[" LWSP digitLetter LWSP "]" LWSP) +-- digitLetter = *((DIGIT "-" DIGIT) /digitMapLetter) +-- digitMapLetter = DIGIT ;digits 0-9 +-- / %x41-4B / %x61-6B ;a-k and A-K +-- / "L" / "S" ;Inter-event timers +-- ;(long, short) +-- / "Z" ;Long duration event +-- DOT = %x2E ; "." +-- LWSP = *(WSP / COMMENT / EOL) +-- WSP = SP / HTAB +-- COMMENT = ";" *(SafeChar / RestChar / WSP) EOL +-- EOL = (CR [LF]) / LF +-- SP = %x20 +-- HTAB = %x09 +-- CR = %x0D +-- LF = %x0A +-- SafeChar = DIGIT / ALPHA / "+" / "-" / "&" / "!" / "_" / "/" / +-- "'" / "?" / "@" / "^" / "`" / "~" / "*" / "$" / "\" / +-- "(" / ")" / "%" / "." +-- RestChar = ";" / "[" / "]" / "{" / "}" / ":" / "," / "#" / +-- "<" / ">" / "=" / %x22 +-- DIGIT = %x30-39 ; digits 0 through 9 +-- ALPHA = %x41-5A / %x61-7A ; A-Z, a-z +-- A path name is also a string with syntactic restrictions imposed +-- upon it. The ABNF production defining it is copied from Annex B. +-- +-- PathName = NAME *(["/"] ["*"] ["@"] (ALPHA / DIGIT)) ["*"] +-- NAME = ALPHA *63(ALPHA / DIGIT / "_" ) +-- +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +-- A.2 ASN.1 syntax specification +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +-- +-- This section contains the ASN.1 specification of the H.248 protocol +-- syntax. +-- +-- NOTE - In case a transport mechanism is used that employs +-- application level framing, the definition of Transaction below +-- changes. Refer to the annex defining the transport mechanism for +-- the definition that applies in that case. +-- +-- NOTE - The ASN.1 specification below contains a clause defining +-- TerminationIDList as a sequence of TerminationIDs. The length of +-- this sequence SHALL be one, except possibly when used in +-- contextAuditResult. +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +MEDIA-GATEWAY-CONTROL-v1 +DEFINITIONS AUTOMATIC TAGS ::= +BEGIN + +MegacoMessage ::= SEQUENCE +{ + authHeader AuthenticationHeader OPTIONAL, + mess Message +} + +AuthenticationHeader ::= SEQUENCE +{ + secParmIndex SecurityParmIndex, + seqNum SequenceNum, + ad AuthData +} + +SecurityParmIndex ::= OCTET STRING(SIZE(4)) + +SequenceNum ::= OCTET STRING(SIZE(4)) + +AuthData ::= OCTET STRING (SIZE (12..32)) + +Message ::= SEQUENCE +{ + version INTEGER(0..99), + -- The version of the protocol defined here is equal to 1. + mId MId, -- Name/address of message originator + messageBody CHOICE + { + messageError ErrorDescriptor, + transactions SEQUENCE OF Transaction + }, + ... +} + +MId ::= CHOICE +{ + ip4Address IP4Address, + ip6Address IP6Address, + domainName DomainName, + deviceName PathName, + mtpAddress OCTET STRING(SIZE(2..4)), + -- Addressing structure of mtpAddress: + -- 15 0 + -- | PC | NI | + -- 14 bits 2 bits + ... +} + +DomainName ::= SEQUENCE +{ + name IA5String, + -- The name starts with an alphanumeric digit followed by a + -- sequence of alphanumeric digits, hyphens and dots. No two + -- dots shall occur consecutively. + portNumber INTEGER(0..65535) OPTIONAL +} + +IP4Address ::= SEQUENCE +{ + address OCTET STRING (SIZE(4)), + portNumber INTEGER(0..65535) OPTIONAL +} + +IP6Address ::= SEQUENCE +{ + address OCTET STRING (SIZE(16)), + portNumber INTEGER(0..65535) OPTIONAL +} + +PathName ::= IA5String(SIZE (1..64)) +-- See section A.3 + +Transaction ::= CHOICE +{ + transactionRequest TransactionRequest, + transactionPending TransactionPending, + transactionReply TransactionReply, + transactionResponseAck TransactionResponseAck, + -- use of response acks is dependent on underlying transport + ... +} + +TransactionId ::= INTEGER(0..4294967295) -- 32 bit unsigned integer + +TransactionRequest ::= SEQUENCE +{ + transactionId TransactionId, + actions SEQUENCE OF ActionRequest, + ... +} + +TransactionPending ::= SEQUENCE +{ + transactionId TransactionId, + ... +} + +TransactionReply ::= SEQUENCE +{ + transactionId TransactionId, + immAckRequired NULL OPTIONAL, + transactionResult CHOICE + { + transactionError ErrorDescriptor, + actionReplies SEQUENCE OF ActionReply + }, + ... +} + +TransactionResponseAck ::= SEQUENCE OF TransactionAck + +TransactionAck ::= SEQUENCE +{ + firstAck TransactionId, + lastAck TransactionId OPTIONAL +} + +ErrorDescriptor ::= SEQUENCE +{ + errorCode ErrorCode, + errorText ErrorText OPTIONAL +} + +ErrorCode ::= INTEGER(0..65535) +-- See section 13 for IANA considerations w.r.t. error codes + +ErrorText ::= IA5String + +ContextID ::= INTEGER(0..4294967295) + +-- Context NULL Value: 0 +-- Context CHOOSE Value: 4294967294 (0xFFFFFFFE) +-- Context ALL Value: 4294967295 (0xFFFFFFFF) + + +ActionRequest ::= SEQUENCE +{ + contextId ContextID, + contextRequest ContextRequest OPTIONAL, + contextAttrAuditReq ContextAttrAuditRequest OPTIONAL, + commandRequests SEQUENCE OF CommandRequest +} + +ActionReply ::= SEQUENCE +{ + contextId ContextID, + errorDescriptor ErrorDescriptor OPTIONAL, + contextReply ContextRequest OPTIONAL, + commandReply SEQUENCE OF CommandReply +} + +ContextRequest ::= SEQUENCE +{ + priority INTEGER(0..15) OPTIONAL, + emergency BOOLEAN OPTIONAL, + topologyReq SEQUENCE OF TopologyRequest OPTIONAL, + ... +} + +ContextAttrAuditRequest ::= SEQUENCE +{ + topology NULL OPTIONAL, + emergency NULL OPTIONAL, + priority NULL OPTIONAL, + ... +} + +CommandRequest ::= SEQUENCE +{ + command Command, + optional NULL OPTIONAL, + wildcardReturn NULL OPTIONAL, + ... +} + +Command ::= CHOICE +{ + addReq AmmRequest, + moveReq AmmRequest, + modReq AmmRequest, + -- Add, Move, Modify requests have the same parameters + subtractReq SubtractRequest, + auditCapRequest AuditRequest, + auditValueRequest AuditRequest, + notifyReq NotifyRequest, + serviceChangeReq ServiceChangeRequest, + ... +} + +CommandReply ::= CHOICE +{ + addReply AmmsReply, + moveReply AmmsReply, + modReply AmmsReply, + subtractReply AmmsReply, + -- Add, Move, Modify, Subtract replies have the same parameters + auditCapReply AuditReply, + auditValueReply AuditReply, + notifyReply NotifyReply, + serviceChangeReply ServiceChangeReply, + ... +} + +TopologyRequest ::= SEQUENCE +{ + terminationFrom TerminationID, + terminationTo TerminationID, + topologyDirection ENUMERATED + { + bothway(0), + isolate(1), + oneway(2) + } +} + +AmmRequest ::= SEQUENCE +{ + terminationID TerminationIDList, + descriptors SEQUENCE OF AmmDescriptor, + -- At most one descriptor of each type (see AmmDescriptor) + -- allowed in the sequence. + ... +} + +AmmDescriptor ::= CHOICE +{ + mediaDescriptor MediaDescriptor, + modemDescriptor ModemDescriptor, + muxDescriptor MuxDescriptor, + eventsDescriptor EventsDescriptor, + eventBufferDescriptor EventBufferDescriptor, + signalsDescriptor SignalsDescriptor, + digitMapDescriptor DigitMapDescriptor, + auditDescriptor AuditDescriptor, +... +} + +AmmsReply ::= SEQUENCE +{ + terminationID TerminationIDList, + terminationAudit TerminationAudit OPTIONAL, + ... +} + +SubtractRequest ::= SEQUENCE +{ + terminationID TerminationIDList, + auditDescriptor AuditDescriptor OPTIONAL, + ... +} + +AuditRequest ::= SEQUENCE +{ + terminationID TerminationID, + auditDescriptor AuditDescriptor, + ... +} + +AuditReply ::= CHOICE +{ + contextAuditResult TerminationIDList, + error ErrorDescriptor, + auditResult AuditResult, + ... +} + +AuditResult ::= SEQUENCE +{ + terminationID TerminationID, + terminationAuditResult TerminationAudit +} + +TerminationAudit ::= SEQUENCE OF AuditReturnParameter + +AuditReturnParameter ::= CHOICE +{ + errorDescriptor ErrorDescriptor, + mediaDescriptor MediaDescriptor, + modemDescriptor ModemDescriptor, + muxDescriptor MuxDescriptor, + eventsDescriptor EventsDescriptor, + eventBufferDescriptor EventBufferDescriptor, + signalsDescriptor SignalsDescriptor, + digitMapDescriptor DigitMapDescriptor, + observedEventsDescriptor ObservedEventsDescriptor, + statisticsDescriptor StatisticsDescriptor, + packagesDescriptor PackagesDescriptor, + emptyDescriptors AuditDescriptor, + ... +} + +AuditDescriptor ::= SEQUENCE +{ + auditToken BIT STRING + { + muxToken(0), + modemToken(1), + mediaToken(2), + eventsToken(3), + signalsToken(4), + digitMapToken(5), + statsToken(6), + observedEventsToken(7), + packagesToken(8), + eventBufferToken(9) + } OPTIONAL, + ... +} + +NotifyRequest ::= SEQUENCE +{ + terminationID TerminationIDList, + observedEventsDescriptor ObservedEventsDescriptor, + errorDescriptor ErrorDescriptor OPTIONAL, + ... +} + +NotifyReply ::= SEQUENCE +{ + terminationID TerminationIDList, + errorDescriptor ErrorDescriptor OPTIONAL, + ... +} + +ObservedEventsDescriptor ::= SEQUENCE +{ + requestId RequestID, + observedEventLst SEQUENCE OF ObservedEvent +} + +ObservedEvent ::= SEQUENCE +{ + eventName EventName, + streamID StreamID OPTIONAL, + eventParList SEQUENCE OF EventParameter, + timeNotation TimeNotation OPTIONAL, + ... +} + +EventName ::= PkgdName + +EventParameter ::= SEQUENCE +{ + eventParameterName Name, + value Value, + -- For use of extraInfo see the comment related to propertyParm + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... +} + +ServiceChangeRequest ::= SEQUENCE +{ + terminationID TerminationIDList, + serviceChangeParms ServiceChangeParm, + ... +} + +ServiceChangeReply ::= SEQUENCE +{ + terminationID TerminationIDList, + serviceChangeResult ServiceChangeResult, + ... +} + +-- For ServiceChangeResult, no parameters are mandatory. Hence the +-- distinction between ServiceChangeParm and ServiceChangeResParm. + +ServiceChangeResult ::= CHOICE +{ + errorDescriptor ErrorDescriptor, + serviceChangeResParms ServiceChangeResParm +} + +WildcardField ::= OCTET STRING(SIZE(1)) + +TerminationID ::= SEQUENCE +{ + wildcard SEQUENCE OF WildcardField, + id OCTET STRING(SIZE(1..8)), + ... +} +-- See Section A.1 for explanation of wildcarding mechanism. +-- Termination ID 0xFFFFFFFFFFFFFFFF indicates the ROOT Termination. + +TerminationIDList ::= SEQUENCE OF TerminationID + +MediaDescriptor ::= SEQUENCE +{ + + termStateDescr TerminationStateDescriptor OPTIONAL, + streams CHOICE + { + oneStream StreamParms, + multiStream SEQUENCE OF StreamDescriptor + } OPTIONAL, + ... +} + +StreamDescriptor ::= SEQUENCE +{ + streamID StreamID, + streamParms StreamParms +} + +StreamParms ::= SEQUENCE +{ + localControlDescriptor LocalControlDescriptor OPTIONAL, + localDescriptor LocalRemoteDescriptor OPTIONAL, + remoteDescriptor LocalRemoteDescriptor OPTIONAL, + ... +} + +LocalControlDescriptor ::= SEQUENCE +{ + streamMode StreamMode OPTIONAL, + reserveValue BOOLEAN OPTIONAL, + reserveGroup BOOLEAN OPTIONAL, + propertyParms SEQUENCE OF PropertyParm, + ... +} + +StreamMode ::= ENUMERATED +{ + sendOnly(0), + recvOnly(1), + sendRecv(2), + inactive(3), + loopBack(4), + ... +} + +-- In PropertyParm, value is a SEQUENCE OF octet string. When sent +-- by an MGC the interpretation is as follows: +-- empty sequence means CHOOSE +-- one element sequence specifies value +-- If the sublist field is not selected, a longer sequence means +-- "choose one of the values" (i.e. value1 OR value2 OR ...) +-- If the sublist field is selected, +-- a sequence with more than one element encodes the value of a +-- list-valued property (i.e. value1 AND value2 AND ...). +-- The relation field may only be selected if the value sequence +-- has length 1. It indicates that the MG has to choose a value +-- for the property. E.g., x > 3 (using the greaterThan +-- value for relation) instructs the MG to choose any value larger +-- than 3 for property x. +-- The range field may only be selected if the value sequence +-- has length 2. It indicates that the MG has to choose a value +-- in the range between the first octet in the value sequence and +-- the trailing octet in the value sequence, including the +-- boundary values. +-- When sent by the MG, only responses to an AuditCapability request +-- may contain multiple values, a range, or a relation field. + +PropertyParm ::= SEQUENCE +{ + name PkgdName, + value SEQUENCE OF OCTET STRING, + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... +} + +Name ::= OCTET STRING(SIZE(2)) + +PkgdName ::= OCTET STRING(SIZE(4)) +-- represents Package Name (2 octets) plus Property Name (2 octets) +-- To wildcard a package use 0xFFFF for first two octets, choose +-- is not allowed. To reference native property tag specified in +-- Annex C, use 0x0000 as first two octets. +-- Wildcarding of Package Name is permitted only if Property Name is +-- also wildcarded. + +Relation ::= ENUMERATED +{ + greaterThan(0), + smallerThan(1), + unequalTo(2), + ... +} + +LocalRemoteDescriptor ::= SEQUENCE +{ + propGrps SEQUENCE OF PropertyGroup, + ... +} + +PropertyGroup ::= SEQUENCE OF PropertyParm + +TerminationStateDescriptor ::= SEQUENCE +{ + propertyParms SEQUENCE OF PropertyParm, + eventBufferControl EventBufferControl OPTIONAL, + serviceState ServiceState OPTIONAL, + ... +} + +EventBufferControl ::= ENUMERATED +{ + off(0), + lockStep(1), + ... +} + +ServiceState ::= ENUMERATED +{ + test(0), + outOfSvc(1), + inSvc(2), + ... +} + +MuxDescriptor ::= SEQUENCE +{ + muxType MuxType, + termList SEQUENCE OF TerminationID, + nonStandardData NonStandardData OPTIONAL, + ... +} + +MuxType ::= ENUMERATED +{ + h221(0), + h223(1), + h226(2), + v76(3), + ... +} + +StreamID ::= INTEGER(0..65535) -- 16 bit unsigned integer + +EventsDescriptor ::= SEQUENCE +{ + requestID RequestID, + -- IG 6.82 was withdrawn + -- requestID RequestID OPTIONAL, + -- RequestID must be present if eventList is non empty + eventList SEQUENCE OF RequestedEvent, + ... +} + +RequestedEvent ::= SEQUENCE +{ + pkgdName PkgdName, + streamID StreamID OPTIONAL, + eventAction RequestedActions OPTIONAL, + evParList SEQUENCE OF EventParameter, + ... +} + +RequestedActions ::= SEQUENCE +{ + keepActive BOOLEAN OPTIONAL, + eventDM EventDM OPTIONAL, + secondEvent SecondEventsDescriptor OPTIONAL, + signalsDescriptor SignalsDescriptor OPTIONAL, + ... +} + + +EventDM ::= CHOICE +{ + digitMapName DigitMapName, + digitMapValue DigitMapValue +} + +SecondEventsDescriptor ::= SEQUENCE +{ + requestID RequestID, + -- IG 6.82 was withdrawn + -- requestID RequestID OPTIONAL, + -- RequestID must be present if eventList is non empty + eventList SEQUENCE OF SecondRequestedEvent, + ... +} + +SecondRequestedEvent ::= SEQUENCE +{ + pkgdName PkgdName, + streamID StreamID OPTIONAL, + eventAction SecondRequestedActions OPTIONAL, + evParList SEQUENCE OF EventParameter, + ... +} + +SecondRequestedActions ::= SEQUENCE +{ + keepActive BOOLEAN OPTIONAL, + eventDM EventDM OPTIONAL, + signalsDescriptor SignalsDescriptor OPTIONAL, + ... +} + +EventBufferDescriptor ::= SEQUENCE OF EventSpec + +EventSpec ::= SEQUENCE +{ + eventName EventName, + streamID StreamID OPTIONAL, + eventParList SEQUENCE OF EventParameter, + ... +} + +SignalsDescriptor ::= SEQUENCE OF SignalRequest + +SignalRequest ::= CHOICE +{ + signal Signal, + seqSigList SeqSigList, + ... +} + +SeqSigList ::= SEQUENCE +{ + id INTEGER(0..65535), + signalList SEQUENCE OF Signal +} + +Signal ::= SEQUENCE +{ + signalName SignalName, + streamID StreamID OPTIONAL, + sigType SignalType OPTIONAL, + duration INTEGER (0..65535) OPTIONAL, + notifyCompletion NotifyCompletion OPTIONAL, + keepActive BOOLEAN OPTIONAL, + sigParList SEQUENCE OF SigParameter, + ... +} + +SignalType ::= ENUMERATED +{ + brief(0), + onOff(1), + timeOut(2), + ... +} + +SignalName ::= PkgdName + +NotifyCompletion ::= BIT STRING +{ + onTimeOut(0), + onInterruptByEvent(1), + onInterruptByNewSignalDescr(2), + otherReason(3) +} + +SigParameter ::= SEQUENCE +{ + sigParameterName Name, + value Value, + -- For use of extraInfo see the comment related to propertyParm + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... +} + +RequestID ::= INTEGER(0..4294967295) -- 32 bit unsigned integer +-- Request ALL Value: 4294967295 (0xFFFFFFFF) + +ModemDescriptor ::= SEQUENCE +{ + mtl SEQUENCE OF ModemType, + mpl SEQUENCE OF PropertyParm, + nonStandardData NonStandardData OPTIONAL +} + +ModemType ::= ENUMERATED +{ + v18(0), + v22(1), + v22bis(2), + v32(3), + v32bis(4), + v34(5), + v90(6), + v91(7), + synchISDN(8), + ... +} + +DigitMapDescriptor ::= SEQUENCE +{ + digitMapName DigitMapName OPTIONAL, + digitMapValue DigitMapValue OPTIONAL +} + +DigitMapName ::= Name + +DigitMapValue ::= SEQUENCE +{ + startTimer INTEGER(0..99) OPTIONAL, + shortTimer INTEGER(0..99) OPTIONAL, + longTimer INTEGER(0..99) OPTIONAL, + digitMapBody IA5String, + -- See Section A.3 for explanation of digit map syntax + ... +} + +ServiceChangeParm ::= SEQUENCE +{ + serviceChangeMethod ServiceChangeMethod, + serviceChangeAddress ServiceChangeAddress OPTIONAL, + serviceChangeVersion INTEGER(0..99) OPTIONAL, + serviceChangeProfile ServiceChangeProfile OPTIONAL, + serviceChangeReason Value, + serviceChangeDelay INTEGER(0..4294967295) OPTIONAL, + -- 32 bit unsigned integer + serviceChangeMgcId MId OPTIONAL, + timeStamp TimeNotation OPTIONAL, + nonStandardData NonStandardData OPTIONAL, + ... +} + +ServiceChangeAddress ::= CHOICE +{ + portNumber INTEGER(0..65535), -- TCP/UDP port number + ip4Address IP4Address, + ip6Address IP6Address, + domainName DomainName, + deviceName PathName, + mtpAddress OCTET STRING(SIZE(2..4)), + ... +} + +ServiceChangeResParm ::= SEQUENCE +{ + serviceChangeMgcId MId OPTIONAL, + serviceChangeAddress ServiceChangeAddress OPTIONAL, + serviceChangeVersion INTEGER(0..99) OPTIONAL, + serviceChangeProfile ServiceChangeProfile OPTIONAL, + timeStamp TimeNotation OPTIONAL, + ... +} + +ServiceChangeMethod ::= ENUMERATED +{ + failover(0), + forced(1), + graceful(2), + restart(3), + disconnected(4), + handOff(5), + ... +} + +ServiceChangeProfile ::= SEQUENCE +{ + profileName IA5String(SIZE (1..67)) + -- 64 characters for name, 1 for "/", 2 for version to match ABNF +} + +-- ServiceChangeProfile ::= SEQUENCE +-- { +-- profileName Name, +-- version INTEGER(0..99) +-- } + +PackagesDescriptor ::= SEQUENCE OF PackagesItem + +PackagesItem ::= SEQUENCE +{ + packageName Name, + packageVersion INTEGER(0..99), + ... +} + +StatisticsDescriptor ::= SEQUENCE OF StatisticsParameter + +StatisticsParameter ::= SEQUENCE +{ + statName PkgdName, + statValue Value OPTIONAL +} + +NonStandardData ::= SEQUENCE +{ + nonStandardIdentifier NonStandardIdentifier, + data OCTET STRING +} + +NonStandardIdentifier ::= CHOICE +{ + object OBJECT IDENTIFIER, + h221NonStandard H221NonStandard, + experimental IA5String(SIZE(8)), + -- first two characters should be "X-" or "X+" + ... +} + +H221NonStandard ::= SEQUENCE +{ + t35CountryCode1 INTEGER(0..255), + t35CountryCode2 INTEGER(0..255), -- country, as per T.35 + t35Extension INTEGER(0..255), -- assigned nationally + manufacturerCode INTEGER(0..65535), -- assigned nationally + ... +} + +TimeNotation ::= SEQUENCE +{ + date IA5String(SIZE(8)), -- yyyymmdd format + time IA5String(SIZE(8)) -- hhmmssss format +} + +Value ::= SEQUENCE OF OCTET STRING + + +END + diff --git a/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-v2.asn b/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-v2.asn new file mode 100644 index 0000000000..b75925b30e --- /dev/null +++ b/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-v2.asn @@ -0,0 +1,966 @@ +MEDIA-GATEWAY-CONTROL-v2 +{itu-t(0) recommendation(0) h(8) h248(248) + modules(0) media-gateway-control(0) version2(2)} +DEFINITIONS AUTOMATIC TAGS ::= +BEGIN + + +MegacoMessage ::= SEQUENCE + { + authHeader AuthenticationHeader OPTIONAL, + mess Message + } + +AuthenticationHeader ::= SEQUENCE + { + secParmIndex SecurityParmIndex, + seqNum SequenceNum, + ad AuthData + } + +SecurityParmIndex ::= OCTET STRING(SIZE(4)) + +SequenceNum ::= OCTET STRING(SIZE(4)) + +AuthData ::= OCTET STRING (SIZE (12..32)) + +Message ::= SEQUENCE + { + version INTEGER(0..99), + -- The version of the protocol defined here is equal to 2. + mId MId, -- Name/address of message originator + messageBody CHOICE + { + messageError ErrorDescriptor, + transactions SEQUENCE OF Transaction + }, + ... + } + +MId ::= CHOICE + { + ip4Address IP4Address, + ip6Address IP6Address, + domainName DomainName, + deviceName PathName, + mtpAddress OCTET STRING(SIZE(2..4)), + -- Addressing structure of mtpAddress: + -- 25 - 15 0 + -- | PC | NI | + -- 24 - 14 bits 2 bits + -- Note: 14 bits are defined for international use. + -- Two national options exist where the point code is 16 or 24 + -- bits. + -- To octet align the mtpAddress, the MSBs shall be encoded as 0s. + ... + } + +DomainName ::= SEQUENCE + { + name IA5String, + -- The name starts with an alphanumeric digit followed by a + -- sequence of alphanumeric digits, hyphens and dots. No two + -- dots shall occur consecutively. + portNumber INTEGER(0..65535) OPTIONAL + } + +IP4Address ::= SEQUENCE + { + address OCTET STRING (SIZE(4)), + portNumber INTEGER(0..65535) OPTIONAL + } + +IP6Address ::= SEQUENCE + { + address OCTET STRING (SIZE(16)), + portNumber INTEGER(0..65535) OPTIONAL + } + +PathName ::= IA5String(SIZE (1..64)) +-- See A.3 + +Transaction ::= CHOICE + { + transactionRequest TransactionRequest, + transactionPending TransactionPending, + transactionReply TransactionReply, + transactionResponseAck TransactionResponseAck, + -- use of response acks is dependent on underlying transport + ... + } + +TransactionId ::= INTEGER(0..4294967295) -- 32-bit unsigned integer + +TransactionRequest ::= SEQUENCE + { + transactionId TransactionId, + actions SEQUENCE OF ActionRequest, + ... + } + +TransactionPending ::= SEQUENCE + { + transactionId TransactionId, + ... + } + +TransactionReply ::= SEQUENCE + { + transactionId TransactionId, + immAckRequired NULL OPTIONAL, + transactionResult CHOICE + { + transactionError ErrorDescriptor, + actionReplies SEQUENCE OF ActionReply + }, + ... + } + +TransactionResponseAck ::= SEQUENCE OF TransactionAck +TransactionAck ::= SEQUENCE + { + firstAck TransactionId, + lastAck TransactionId OPTIONAL + } + +ErrorDescriptor ::= SEQUENCE + { + errorCode ErrorCode, + errorText ErrorText OPTIONAL + } + +ErrorCode ::= INTEGER(0..65535) +-- See clause 14 for IANA considerations with respect to error codes +ErrorText ::= IA5String + +ContextID ::= INTEGER(0..4294967295) + +-- Context NULL Value: 0 +-- Context CHOOSE Value: 4294967294 (0xFFFFFFFE) +-- Context ALL Value: 4294967295 (0xFFFFFFFF) + + +ActionRequest ::= SEQUENCE + { + contextId ContextID, + contextRequest ContextRequest OPTIONAL, + contextAttrAuditReq ContextAttrAuditRequest OPTIONAL, + commandRequests SEQUENCE OF CommandRequest + } + +ActionReply ::= SEQUENCE + { + contextId ContextID, + errorDescriptor ErrorDescriptor OPTIONAL, + contextReply ContextRequest OPTIONAL, + commandReply SEQUENCE OF CommandReply + } + +ContextRequest ::= SEQUENCE + { + priority INTEGER(0..15) OPTIONAL, + emergency BOOLEAN OPTIONAL, + topologyReq SEQUENCE OF TopologyRequest OPTIONAL, + ... + } + +ContextAttrAuditRequest ::= SEQUENCE + { + topology NULL OPTIONAL, + emergency NULL OPTIONAL, + priority NULL OPTIONAL, + ... + } + +CommandRequest ::= SEQUENCE + { + command Command, + optional NULL OPTIONAL, + wildcardReturn NULL OPTIONAL, + ... + } + +Command ::= CHOICE + { + addReq AmmRequest, + moveReq AmmRequest, + modReq AmmRequest, + -- Add, Move, Modify requests have the same parameters + subtractReq SubtractRequest, + auditCapRequest AuditRequest, + auditValueRequest AuditRequest, + notifyReq NotifyRequest, + serviceChangeReq ServiceChangeRequest, + ... + } + +CommandReply ::= CHOICE + { + addReply AmmsReply, + moveReply AmmsReply, + modReply AmmsReply, + subtractReply AmmsReply, + -- Add, Move, Modify, Subtract replies have the same parameters + auditCapReply AuditReply, + auditValueReply AuditReply, + notifyReply NotifyReply, + serviceChangeReply ServiceChangeReply, + ... + } + +TopologyRequest ::= SEQUENCE + { + terminationFrom TerminationID, + terminationTo TerminationID, + topologyDirection ENUMERATED + { + bothway(0), + isolate(1), + oneway(2) + }, + ..., + streamID StreamID OPTIONAL + } + +AmmRequest ::= SEQUENCE + { + terminationID TerminationIDList, + descriptors SEQUENCE OF AmmDescriptor, + -- At most one descriptor of each type (see AmmDescriptor) + -- allowed in the sequence. + ... + } + +AmmDescriptor ::= CHOICE + { + mediaDescriptor MediaDescriptor, + modemDescriptor ModemDescriptor, + muxDescriptor MuxDescriptor, + eventsDescriptor EventsDescriptor, + eventBufferDescriptor EventBufferDescriptor, + signalsDescriptor SignalsDescriptor, + digitMapDescriptor DigitMapDescriptor, + auditDescriptor AuditDescriptor, + ... + } + + +AmmsReply ::= SEQUENCE + { + terminationID TerminationIDList, + terminationAudit TerminationAudit OPTIONAL, + ... + } + +SubtractRequest ::= SEQUENCE + { + terminationID TerminationIDList, + auditDescriptor AuditDescriptor OPTIONAL, + ... + } + +AuditRequest ::= SEQUENCE + { + terminationID TerminationID, + auditDescriptor AuditDescriptor, + ... + } + +AuditReply ::= CHOICE + { + contextAuditResult TerminationIDList, + error ErrorDescriptor, + auditResult AuditResult, + ... + } + +AuditResult ::= SEQUENCE + { + + terminationID TerminationID, + terminationAuditResult TerminationAudit + } + + + +TerminationAudit ::= SEQUENCE OF AuditReturnParameter + +AuditReturnParameter ::= CHOICE + { + errorDescriptor ErrorDescriptor, + mediaDescriptor MediaDescriptor, + modemDescriptor ModemDescriptor, + muxDescriptor MuxDescriptor, + eventsDescriptor EventsDescriptor, + eventBufferDescriptor EventBufferDescriptor, + signalsDescriptor SignalsDescriptor, + digitMapDescriptor DigitMapDescriptor, + observedEventsDescriptor ObservedEventsDescriptor, + statisticsDescriptor StatisticsDescriptor, + packagesDescriptor PackagesDescriptor, + emptyDescriptors AuditDescriptor, + ... + } + +AuditDescriptor ::= SEQUENCE + { + auditToken BIT STRING + { + muxToken(0), modemToken(1), mediaToken(2), + eventsToken(3), signalsToken(4), + digitMapToken(5), statsToken(6), + observedEventsToken(7), + packagesToken(8), eventBufferToken(9) + } OPTIONAL, + ..., + auditPropertyToken SEQUENCE OF IndAuditParameter OPTIONAL + } + + +IndAuditParameter ::= CHOICE + { + -- Note that the lower/upper case letters of the tags have + -- been changed. The same changes has been made in text... + indAudMediaDescriptor IndAudMediaDescriptor, + indAudEventsDescriptor IndAudEventsDescriptor, + indAudEventBufferDescriptor IndAudEventBufferDescriptor, + indAudSignalsDescriptor IndAudSignalsDescriptor, + indAudDigitMapDescriptor IndAudDigitMapDescriptor, + indAudStatisticsDescriptor IndAudStatisticsDescriptor, + indAudPackagesDescriptor IndAudPackagesDescriptor, + ... + } + +IndAudMediaDescriptor ::= SEQUENCE + { + + termStateDescr IndAudTerminationStateDescriptor OPTIONAL, + streams CHOICE + { + oneStream IndAudStreamParms, + multiStream SEQUENCE OF IndAudStreamDescriptor + } OPTIONAL, + ... + } + +IndAudStreamDescriptor ::= SEQUENCE + { + streamID StreamID, + streamParms IndAudStreamParms + } + +IndAudStreamParms ::= SEQUENCE + { + localControlDescriptor IndAudLocalControlDescriptor OPTIONAL, + localDescriptor IndAudLocalRemoteDescriptor OPTIONAL, + remoteDescriptor IndAudLocalRemoteDescriptor OPTIONAL, + ... + } + +IndAudLocalControlDescriptor ::= SEQUENCE + { + streamMode NULL OPTIONAL, + reserveValue NULL OPTIONAL, + reserveGroup NULL OPTIONAL, + propertyParms SEQUENCE OF IndAudPropertyParm OPTIONAL, + ... + } + +IndAudPropertyParm ::= SEQUENCE + { + name PkgdName, + ... + } + +IndAudLocalRemoteDescriptor ::= SEQUENCE + { + propGroupID INTEGER(0..65535) OPTIONAL, + propGrps IndAudPropertyGroup, + ... + } + +IndAudPropertyGroup ::= SEQUENCE OF IndAudPropertyParm + +IndAudTerminationStateDescriptor ::= SEQUENCE + { + propertyParms SEQUENCE OF IndAudPropertyParm, + eventBufferControl NULL OPTIONAL, + serviceState NULL OPTIONAL, + ... + } + +IndAudEventsDescriptor ::= SEQUENCE + { + requestID RequestID OPTIONAL, + pkgdName PkgdName, + streamID StreamID OPTIONAL, + ... + } + +IndAudEventBufferDescriptor ::= SEQUENCE + { + eventName PkgdName, + streamID StreamID OPTIONAL, + ... + } + +IndAudSignalsDescriptor ::=CHOICE + { + signal IndAudSignal, + seqSigList IndAudSeqSigList, + ... + } + +IndAudSeqSigList ::= SEQUENCE + { + id INTEGER(0..65535), + signalList IndAudSignal OPTIONAL + } + +IndAudSignal ::= SEQUENCE + { + signalName PkgdName, + streamID StreamID OPTIONAL, + ... + } + +IndAudDigitMapDescriptor ::= SEQUENCE + { + digitMapName DigitMapName OPTIONAL + } + +IndAudStatisticsDescriptor ::= SEQUENCE + { + statName PkgdName + } + +IndAudPackagesDescriptor ::= SEQUENCE + { + packageName Name, + packageVersion INTEGER(0..99), + ... + } + +NotifyRequest ::= SEQUENCE + { + terminationID TerminationIDList, + observedEventsDescriptor ObservedEventsDescriptor, + errorDescriptor ErrorDescriptor OPTIONAL, + ... + } + +NotifyReply ::= SEQUENCE + { + terminationID TerminationIDList, + errorDescriptor ErrorDescriptor OPTIONAL, + ... + } + +ObservedEventsDescriptor ::= SEQUENCE + { + requestId RequestID, + observedEventLst SEQUENCE OF ObservedEvent + } + +ObservedEvent ::= SEQUENCE + { + eventName EventName, + streamID StreamID OPTIONAL, + eventParList SEQUENCE OF EventParameter, + timeNotation TimeNotation OPTIONAL, + ... + } + +EventName ::= PkgdName + +EventParameter ::= SEQUENCE + { + eventParameterName Name, + value Value, + -- For use of extraInfo see the comment related to PropertyParm + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... + + } + +ServiceChangeRequest ::= SEQUENCE + { + terminationID TerminationIDList, + serviceChangeParms ServiceChangeParm, + ... + } + +ServiceChangeReply ::= SEQUENCE + { + terminationID TerminationIDList, + serviceChangeResult ServiceChangeResult, + ... + } + +-- For ServiceChangeResult, no parameters are mandatory. Hence the +-- distinction between ServiceChangeParm and ServiceChangeResParm. + +ServiceChangeResult ::= CHOICE + { + errorDescriptor ErrorDescriptor, + serviceChangeResParms ServiceChangeResParm + } + +WildcardField ::= OCTET STRING(SIZE(1)) + +TerminationID ::= SEQUENCE + { + wildcard SEQUENCE OF WildcardField, + id OCTET STRING(SIZE(1..8)), + ... + } +-- See A.1 for explanation of wildcarding mechanism. +-- Termination ID 0xFFFFFFFFFFFFFFFF indicates the ROOT Termination. + +TerminationIDList ::= SEQUENCE OF TerminationID + +MediaDescriptor ::= SEQUENCE + { + termStateDescr TerminationStateDescriptor OPTIONAL, + streams CHOICE + { + oneStream StreamParms, + multiStream SEQUENCE OF StreamDescriptor + } OPTIONAL, + ... + } + +StreamDescriptor ::= SEQUENCE + { + streamID StreamID, + streamParms StreamParms + } + +StreamParms ::= SEQUENCE + { + localControlDescriptor LocalControlDescriptor OPTIONAL, + localDescriptor LocalRemoteDescriptor OPTIONAL, + remoteDescriptor LocalRemoteDescriptor OPTIONAL, + ... + } + +LocalControlDescriptor ::= SEQUENCE + { + streamMode StreamMode OPTIONAL, + reserveValue BOOLEAN OPTIONAL, + reserveGroup BOOLEAN OPTIONAL, + propertyParms SEQUENCE OF PropertyParm, + ... + } + +StreamMode ::= ENUMERATED + { + sendOnly(0), + recvOnly(1), + sendRecv(2), + inactive(3), + loopBack(4), + ... + } + +-- In PropertyParm, value is a SEQUENCE OF octet string. When sent +-- by an MGC the interpretation is as follows: +-- empty sequence means CHOOSE +-- one element sequence specifies value +-- If the sublist field is not selected, a longer sequence means +-- "choose one of the values" (i.e. value1 OR value2 OR ...) +-- If the sublist field is selected, +-- a sequence with more than one element encodes the value of a +-- list-valued property (i.e. value1 AND value2 AND ...). +-- The relation field may only be selected if the value sequence +-- has length 1. It indicates that the MG has to choose a value +-- for the property. E.g. x > 3 (using the greaterThan +-- value for relation) instructs the MG to choose any value larger +-- than 3 for property x. +-- The range field may only be selected if the value sequence +-- has length 2. It indicates that the MG has to choose a value +-- in the range between the first octet in the value sequence and +-- the trailing octet in the value sequence, including the +-- boundary values. +-- When sent by the MG, only responses to an AuditCapability request +-- may contain multiple values, a range, or a relation field. + +PropertyParm ::= SEQUENCE + { + name PkgdName, + value SEQUENCE OF OCTET STRING, + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... + } + +Name ::= OCTET STRING(SIZE(2)) + +PkgdName ::= OCTET STRING(SIZE(4)) +-- represents Package Name (2 octets) plus Property, Event, +-- Signal Names or Statistics ID. (2 octets) +-- To wildcard a package use 0xFFFF for first two octets, choose +-- is not allowed. To reference native property tag specified in +-- Annex C, use 0x0000 as first two octets. +-- To wildcard a Property, Event, Signal, or Statistics ID, use +-- 0xFFFF for last two octets, choose is not allowed. +-- Wildcarding of Package Name is permitted only if Property, +-- Event, Signal, or Statistics ID are +-- also wildcarded. + +Relation ::= ENUMERATED + { + greaterThan(0), + smallerThan(1), + unequalTo(2), + ... + } + +LocalRemoteDescriptor ::= SEQUENCE + { + propGrps SEQUENCE OF PropertyGroup, + ... + } + +PropertyGroup ::= SEQUENCE OF PropertyParm + +TerminationStateDescriptor ::= SEQUENCE + { + propertyParms SEQUENCE OF PropertyParm, + eventBufferControl EventBufferControl OPTIONAL, + serviceState ServiceState OPTIONAL, + ... + } + +EventBufferControl ::= ENUMERATED + { + off(0), + lockStep(1), + ... + } + +ServiceState ::= ENUMERATED + { + test(0), + outOfSvc(1), + inSvc(2), + ... + } + +MuxDescriptor ::= SEQUENCE + { + muxType MuxType, + termList SEQUENCE OF TerminationID, + nonStandardData NonStandardData OPTIONAL, + ... + } + +MuxType ::= ENUMERATED + { + h221(0), + h223(1), + h226(2), + v76(3), + ..., + nx64k(4) + } + +StreamID ::= INTEGER(0..65535) -- 16-bit unsigned integer + +EventsDescriptor ::= SEQUENCE + { + requestID RequestID OPTIONAL, + -- RequestID must be present if eventList + -- is non empty + eventList SEQUENCE OF RequestedEvent, + ... + } + +RequestedEvent ::= SEQUENCE + { + pkgdName PkgdName, + streamID StreamID OPTIONAL, + eventAction RequestedActions OPTIONAL, + evParList SEQUENCE OF EventParameter, + ... + } + +RequestedActions ::= SEQUENCE + { + keepActive BOOLEAN OPTIONAL, + eventDM EventDM OPTIONAL, + secondEvent SecondEventsDescriptor OPTIONAL, + signalsDescriptor SignalsDescriptor OPTIONAL, + ... + } + +EventDM ::= CHOICE + { + digitMapName DigitMapName, + digitMapValue DigitMapValue + } + +SecondEventsDescriptor ::= SEQUENCE + { + requestID RequestID OPTIONAL, + eventList SEQUENCE OF SecondRequestedEvent, + ... + } + +SecondRequestedEvent ::= SEQUENCE + { + pkgdName PkgdName, + streamID StreamID OPTIONAL, + eventAction SecondRequestedActions OPTIONAL, + evParList SEQUENCE OF EventParameter, + ... + } + +SecondRequestedActions ::= SEQUENCE + { + keepActive BOOLEAN OPTIONAL, + eventDM EventDM OPTIONAL, + signalsDescriptor SignalsDescriptor OPTIONAL, + ... + } + +EventBufferDescriptor ::= SEQUENCE OF EventSpec + +EventSpec ::= SEQUENCE + { + eventName EventName, + streamID StreamID OPTIONAL, + eventParList SEQUENCE OF EventParameter, + ... + } + + +SignalsDescriptor ::= SEQUENCE OF SignalRequest + +SignalRequest ::= CHOICE + { + signal Signal, + seqSigList SeqSigList, + ... + } + +SeqSigList ::= SEQUENCE + { + id INTEGER(0..65535), + signalList SEQUENCE OF Signal + } + +Signal ::= SEQUENCE + { + signalName SignalName, + streamID StreamID OPTIONAL, + sigType SignalType OPTIONAL, + duration INTEGER (0..65535) OPTIONAL, + notifyCompletion NotifyCompletion OPTIONAL, + keepActive BOOLEAN OPTIONAL, + sigParList SEQUENCE OF SigParameter, + ... + } + +SignalType ::= ENUMERATED + { + brief(0), + onOff(1), + timeOut(2), + ... + } + +SignalName ::= PkgdName + +NotifyCompletion ::= BIT STRING + { + onTimeOut(0), onInterruptByEvent(1), + onInterruptByNewSignalDescr(2), otherReason(3) + } + +SigParameter ::= SEQUENCE + { + sigParameterName Name, + value Value, + -- For use of extraInfo see the comment related to PropertyParm + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... + } + +-- For an AuditCapReply with all events, the RequestID SHALL be ALL. +-- ALL is represented by 0xffffffff. + +RequestID ::= INTEGER(0..4294967295) -- 32-bit unsigned integer + +ModemDescriptor ::= SEQUENCE + { + mtl SEQUENCE OF ModemType, + mpl SEQUENCE OF PropertyParm, + nonStandardData NonStandardData OPTIONAL + } + +ModemType ::= ENUMERATED + { + v18(0), + v22(1), + v22bis(2), + v32(3), + v32bis(4), + v34(5), + v90(6), + v91(7), + synchISDN(8), + ... + } + +DigitMapDescriptor ::= SEQUENCE + { + digitMapName DigitMapName OPTIONAL, + digitMapValue DigitMapValue OPTIONAL + } + +DigitMapName ::= Name + +DigitMapValue ::= SEQUENCE + { + startTimer INTEGER(0..99) OPTIONAL, + shortTimer INTEGER(0..99) OPTIONAL, + longTimer INTEGER(0..99) OPTIONAL, + digitMapBody IA5String, + -- Units are seconds for start, short and long timers, and + -- hundreds of milliseconds for duration timer. Thus start, + -- short, and long range from 1 to 99 seconds and duration + -- from 100 ms to 9.9 s + -- See A.3 for explanation of digit map syntax + ..., + durationTimer INTEGER (0..99) OPTIONAL + } + +ServiceChangeParm ::= SEQUENCE + { + serviceChangeMethod ServiceChangeMethod, + serviceChangeAddress ServiceChangeAddress OPTIONAL, + serviceChangeVersion INTEGER(0..99) OPTIONAL, + serviceChangeProfile ServiceChangeProfile OPTIONAL, + serviceChangeReason Value, + -- A serviceChangeReason consists of a numeric reason code + -- and an optional text description. + -- The serviceChangeReason SHALL be a string consisting of + -- a decimal reason code, optionally followed by a single + -- space character and a textual description string. + -- This string is first BER-encoded as an IA5String. + -- The result of this BER-encoding is then encoded as + -- an ASN.1 OCTET STRING type, "double wrapping" the + -- value + -- as was done for package elements. + serviceChangeDelay INTEGER(0..4294967295) OPTIONAL, + -- 32-bit unsigned integer + serviceChangeMgcId MId OPTIONAL, + timeStamp TimeNotation OPTIONAL, + nonStandardData NonStandardData OPTIONAL, + ..., + serviceChangeInfo AuditDescriptor OPTIONAL + } + +ServiceChangeAddress ::= CHOICE + { + portNumber INTEGER(0..65535), -- TCP/UDP port number + ip4Address IP4Address, + ip6Address IP6Address, + domainName DomainName, + deviceName PathName, + mtpAddress OCTET STRING(SIZE(2..4)), + ... + } + +ServiceChangeResParm ::= SEQUENCE + { + serviceChangeMgcId MId OPTIONAL, + serviceChangeAddress ServiceChangeAddress OPTIONAL, + serviceChangeVersion INTEGER(0..99) OPTIONAL, + serviceChangeProfile ServiceChangeProfile OPTIONAL, + timestamp TimeNotation OPTIONAL, + ... + } + +ServiceChangeMethod ::= ENUMERATED + { + failover(0), + forced(1), + graceful(2), + restart(3), + disconnected(4), + handOff(5), + ... + } + +ServiceChangeProfile ::= SEQUENCE + { + profileName IA5String(SIZE (1..67)) + + -- 64 characters for name, 1 for "/", 2 for version to match ABNF + } + +PackagesDescriptor ::= SEQUENCE OF PackagesItem +PackagesItem ::= SEQUENCE + { + packageName Name, + packageVersion INTEGER(0..99), + ... + } + +StatisticsDescriptor ::= SEQUENCE OF StatisticsParameter + +StatisticsParameter ::= SEQUENCE + { + statName PkgdName, + statValue Value OPTIONAL + } + +NonStandardData ::= SEQUENCE + { + nonStandardIdentifier NonStandardIdentifier, + data OCTET STRING + } + +NonStandardIdentifier ::= CHOICE + { + object OBJECT IDENTIFIER, + h221NonStandard H221NonStandard, + experimental IA5String(SIZE(8)), + -- first two characters SHOULD be "X-" or "X+" + ... + } + +H221NonStandard ::= SEQUENCE + { t35CountryCode1 INTEGER(0..255), + t35CountryCode2 INTEGER(0..255), -- country, as per T.35 + t35Extension INTEGER(0..255), -- assigned nationally + manufacturerCode INTEGER(0..65535), -- assigned nationally + ... + } + +TimeNotation ::= SEQUENCE + { + date IA5String(SIZE(8)), -- yyyymmdd format + time IA5String(SIZE(8)) -- hhmmssss format + -- per ISO 8601:1988 + } + +Value ::= SEQUENCE OF OCTET STRING + +END diff --git a/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-v3.asn b/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-v3.asn new file mode 100644 index 0000000000..644a35ffee --- /dev/null +++ b/lib/megaco/src/binary/MEDIA-GATEWAY-CONTROL-v3.asn @@ -0,0 +1,1068 @@ +MEDIA-GATEWAY-CONTROL-v3 +{itu-t(0) recommendation(0) h(8) h248(248) + modules(0) media-gateway-control(0) version3(3)} +DEFINITIONS AUTOMATIC TAGS ::= +BEGIN + + +MegacoMessage ::= SEQUENCE + { + authHeader AuthenticationHeader OPTIONAL, + mess Message + } + +AuthenticationHeader ::= SEQUENCE + { + secParmIndex SecurityParmIndex, + seqNum SequenceNum, + ad AuthData + } + +SecurityParmIndex ::= OCTET STRING(SIZE(4)) + +SequenceNum ::= OCTET STRING(SIZE(4)) + +AuthData ::= OCTET STRING (SIZE (12..32)) + +Message ::= SEQUENCE + { + version INTEGER(0..99), + -- The version of the protocol defined here is equal to 3. + mId MId, -- Name/address of message originator + messageBody CHOICE + { + messageError ErrorDescriptor, + transactions SEQUENCE OF Transaction + }, + ... + } + +MId ::= CHOICE + { + ip4Address IP4Address, + ip6Address IP6Address, + domainName DomainName, + deviceName PathName, + mtpAddress OCTET STRING(SIZE(2..4)), + -- Addressing structure of mtpAddress: + -- 25 - 15 0 + -- | PC | NI | + -- 24 - 14 bits 2 bits + -- Note: 14 bits are defined for international use. + -- Two national options exist where the point code is 16 or 24 + -- bits. + -- To octet align the mtpAddress, the MSBs shall be encoded as 0s. + ... + } + +DomainName ::= SEQUENCE + { + name IA5String, + -- The name starts with an alphanumeric digit followed by a + -- sequence of alphanumeric digits, hyphens and dots. No two + -- dots shall occur consecutively. + portNumber INTEGER(0..65535) OPTIONAL + } + +IP4Address ::= SEQUENCE + { + address OCTET STRING (SIZE(4)), + portNumber INTEGER(0..65535) OPTIONAL + } + +IP6Address ::= SEQUENCE + { + address OCTET STRING (SIZE(16)), + portNumber INTEGER(0..65535) OPTIONAL + } + +PathName ::= IA5String(SIZE (1..64)) +-- See A.3 + +Transaction ::= CHOICE + { + transactionRequest TransactionRequest, + transactionPending TransactionPending, + transactionReply TransactionReply, + transactionResponseAck TransactionResponseAck, + -- use of response acks is dependent on underlying transport + ..., + segmentReply SegmentReply + } + +TransactionId ::= INTEGER(0..4294967295) -- 32-bit unsigned integer + +TransactionRequest ::= SEQUENCE + { + transactionId TransactionId, + actions SEQUENCE OF ActionRequest, + ... + } + +TransactionPending ::= SEQUENCE + { + transactionId TransactionId, + ... + } + +TransactionReply ::= SEQUENCE + { + transactionId TransactionId, + immAckRequired NULL OPTIONAL, + transactionResult CHOICE + { + transactionError ErrorDescriptor, + actionReplies SEQUENCE OF ActionReply + }, + ..., + segmentNumber SegmentNumber OPTIONAL, + segmentationComplete NULL OPTIONAL + } + +SegmentReply ::= SEQUENCE + { + transactionId TransactionId, + segmentNumber SegmentNumber, + segmentationComplete NULL OPTIONAL, + ... + } + +SegmentNumber ::= INTEGER(0..65535) + +TransactionResponseAck ::= SEQUENCE OF TransactionAck +TransactionAck ::= SEQUENCE + { + firstAck TransactionId, + lastAck TransactionId OPTIONAL + } + +ErrorDescriptor ::= SEQUENCE + { + errorCode ErrorCode, + errorText ErrorText OPTIONAL + } + +ErrorCode ::= INTEGER(0..65535) +-- See clause 14 for IANA considerations with respect to error codes +ErrorText ::= IA5String + +ContextID ::= INTEGER(0..4294967295) +-- Context NULL Value: 0 +-- Context CHOOSE Value: 4294967294 (0xFFFFFFFE) +-- Context ALL Value: 4294967295 (0xFFFFFFFF) + + +ActionRequest ::= SEQUENCE + { + contextId ContextID, + contextRequest ContextRequest OPTIONAL, + contextAttrAuditReq ContextAttrAuditRequest OPTIONAL, + commandRequests SEQUENCE OF CommandRequest + } + +ActionReply ::= SEQUENCE + { + contextId ContextID, + errorDescriptor ErrorDescriptor OPTIONAL, + contextReply ContextRequest OPTIONAL, + commandReply SEQUENCE OF CommandReply + } + +ContextRequest ::= SEQUENCE + { + priority INTEGER(0..15) OPTIONAL, + emergency BOOLEAN OPTIONAL, + topologyReq SEQUENCE OF TopologyRequest OPTIONAL, + ..., + iepscallind BOOLEAN OPTIONAL, + contextProp SEQUENCE OF PropertyParm OPTIONAL, + contextList SEQUENCE OF ContextID OPTIONAL + } +-- When returning a contextList, the contextId in the ActionReply +-- construct will return the contextId from the associated ActionRequest. + +ContextAttrAuditRequest ::= SEQUENCE + { + topology NULL OPTIONAL, + emergency NULL OPTIONAL, + priority NULL OPTIONAL, + ..., + iepscallind NULL OPTIONAL, + contextPropAud SEQUENCE OF IndAudPropertyParm OPTIONAL, + + selectpriority INTEGER(0..15) OPTIONAL, + -- to select given priority + + selectemergency BOOLEAN OPTIONAL, + -- to select if emergency set/not set (T/F) + + selectiepscallind BOOLEAN OPTIONAL, + -- to select if IEPS set/not set (T/F) + + selectLogic SelectLogic OPTIONAL -- default is AND + } + +SelectLogic ::= CHOICE + { + andAUDITSelect NULL, -- all selection conditions satisfied + orAUDITSelect NULL, -- at least one selection condition satisfied + ... + } + + +CommandRequest ::= SEQUENCE + { + command Command, + optional NULL OPTIONAL, + wildcardReturn NULL OPTIONAL, + ... + } + +Command ::= CHOICE + { + addReq AmmRequest, + moveReq AmmRequest, + modReq AmmRequest, + -- Add, Move, Modify requests have the same parameters + subtractReq SubtractRequest, + auditCapRequest AuditRequest, + auditValueRequest AuditRequest, + notifyReq NotifyRequest, + serviceChangeReq ServiceChangeRequest, + ... + } + +CommandReply ::= CHOICE + { + addReply AmmsReply, + moveReply AmmsReply, + modReply AmmsReply, + subtractReply AmmsReply, + -- Add, Move, Modify, Subtract replies have the same parameters + auditCapReply AuditReply, + auditValueReply AuditReply, + notifyReply NotifyReply, + serviceChangeReply ServiceChangeReply, + ... + } + +TopologyRequest ::= SEQUENCE + { + terminationFrom TerminationID, + terminationTo TerminationID, + topologyDirection ENUMERATED + { + bothway(0), + isolate(1), + oneway(2) + }, + ..., + streamID StreamID OPTIONAL, + topologyDirectionExtension ENUMERATED + { + onewayexternal(0), + onewayboth(1), + ... + } OPTIONAL + -- This is not according to the standard, but without it + -- the TopologyRequest will be useless since topologyDirection + -- and topologyDirectionExtension are contradictory. + } + +AmmRequest ::= SEQUENCE + { + terminationID TerminationIDList, + descriptors SEQUENCE OF AmmDescriptor, + -- At most one descriptor of each type (see AmmDescriptor) + -- allowed in the sequence. + ... + } + +AmmDescriptor ::= CHOICE + { + mediaDescriptor MediaDescriptor, + modemDescriptor ModemDescriptor, + muxDescriptor MuxDescriptor, + eventsDescriptor EventsDescriptor, + eventBufferDescriptor EventBufferDescriptor, + signalsDescriptor SignalsDescriptor, + digitMapDescriptor DigitMapDescriptor, + auditDescriptor AuditDescriptor, + ..., + statisticsDescriptor StatisticsDescriptor + } + + +AmmsReply ::= SEQUENCE + { + terminationID TerminationIDList, + terminationAudit TerminationAudit OPTIONAL, + ... + } + +SubtractRequest ::= SEQUENCE + { + terminationID TerminationIDList, + auditDescriptor AuditDescriptor OPTIONAL, + ... + } + +AuditRequest ::= SEQUENCE + { + terminationID TerminationID, + auditDescriptor AuditDescriptor, + ..., + terminationIDList TerminationIDList OPTIONAL + } +-- terminationID shall contain the first termination in the +-- list when using the terminationIDList construct in AuditRequest + +AuditReply ::= CHOICE + { + contextAuditResult TerminationIDList, + error ErrorDescriptor, + auditResult AuditResult, + ..., + auditResultTermList TermListAuditResult + } + +AuditResult ::= SEQUENCE + { + + terminationID TerminationID, + terminationAuditResult TerminationAudit + } + +TermListAuditResult ::= SEQUENCE + { + terminationIDList TerminationIDList, + terminationAuditResult TerminationAudit, + ... + } + +TerminationAudit ::= SEQUENCE OF AuditReturnParameter + +AuditReturnParameter ::= CHOICE + { + errorDescriptor ErrorDescriptor, + mediaDescriptor MediaDescriptor, + modemDescriptor ModemDescriptor, + muxDescriptor MuxDescriptor, + eventsDescriptor EventsDescriptor, + eventBufferDescriptor EventBufferDescriptor, + signalsDescriptor SignalsDescriptor, + digitMapDescriptor DigitMapDescriptor, + observedEventsDescriptor ObservedEventsDescriptor, + statisticsDescriptor StatisticsDescriptor, + packagesDescriptor PackagesDescriptor, + emptyDescriptors AuditDescriptor, + ... + } + +AuditDescriptor ::= SEQUENCE + { + auditToken BIT STRING + { + muxToken(0), modemToken(1), mediaToken(2), + eventsToken(3), signalsToken(4), + digitMapToken(5), statsToken(6), + observedEventsToken(7), + packagesToken(8), eventBufferToken(9) + } OPTIONAL, + ..., + auditPropertyToken SEQUENCE OF IndAuditParameter OPTIONAL + } + + +IndAuditParameter ::= CHOICE + { + -- Note that the lower/upper case letters of the tags have + -- been changed. The same changes has been made in text... + indAudMediaDescriptor IndAudMediaDescriptor, + indAudEventsDescriptor IndAudEventsDescriptor, + indAudEventBufferDescriptor IndAudEventBufferDescriptor, + indAudSignalsDescriptor IndAudSignalsDescriptor, + indAudDigitMapDescriptor IndAudDigitMapDescriptor, + indAudStatisticsDescriptor IndAudStatisticsDescriptor, + indAudPackagesDescriptor IndAudPackagesDescriptor, + ... + } + +IndAudMediaDescriptor ::= SEQUENCE + { + + termStateDescr IndAudTerminationStateDescriptor OPTIONAL, + streams CHOICE + { + oneStream IndAudStreamParms, + multiStream SEQUENCE OF IndAudStreamDescriptor + } OPTIONAL, + ... + } + +IndAudStreamDescriptor ::= SEQUENCE + { + streamID StreamID, + streamParms IndAudStreamParms + } + +IndAudStreamParms ::= SEQUENCE + { + localControlDescriptor IndAudLocalControlDescriptor OPTIONAL, + localDescriptor IndAudLocalRemoteDescriptor OPTIONAL, + remoteDescriptor IndAudLocalRemoteDescriptor OPTIONAL, + ..., + statisticsDescriptor IndAudStatisticsDescriptor OPTIONAL + } + +IndAudLocalControlDescriptor ::= SEQUENCE + { + streamMode NULL OPTIONAL, + reserveValue NULL OPTIONAL, + reserveGroup NULL OPTIONAL, + propertyParms SEQUENCE OF IndAudPropertyParm OPTIONAL, + ..., + streamModeSel StreamMode OPTIONAL + -- must not have both streamMode and streamModeSel + -- if both are present only streamModeSel shall be honoured + } + +IndAudPropertyParm ::= SEQUENCE + { + name PkgdName, + ..., + propertyParms PropertyParm OPTIONAL + } +-- to select based on property values +-- AND/OR selection logic is specified at context level + +IndAudLocalRemoteDescriptor ::= SEQUENCE + { + propGroupID INTEGER(0..65535) OPTIONAL, + propGrps IndAudPropertyGroup, + ... + } + +IndAudPropertyGroup ::= SEQUENCE OF IndAudPropertyParm + +IndAudTerminationStateDescriptor ::= SEQUENCE + { + propertyParms SEQUENCE OF IndAudPropertyParm, + eventBufferControl NULL OPTIONAL, + serviceState NULL OPTIONAL, + ..., + serviceStateSel ServiceState OPTIONAL + -- must not have both serviceState and serviceStateSel + -- if both are present only serviceStateSel shall be honoured + } + +IndAudEventsDescriptor ::= SEQUENCE + { + requestID RequestID OPTIONAL, + pkgdName PkgdName, + streamID StreamID OPTIONAL, + ... + } + +IndAudEventBufferDescriptor ::= SEQUENCE + { + eventName PkgdName, + streamID StreamID OPTIONAL, + ... + } + +IndAudSignalsDescriptor ::=CHOICE + { + signal IndAudSignal, + seqSigList IndAudSeqSigList, + ... + } + +IndAudSeqSigList ::= SEQUENCE + { + id INTEGER(0..65535), + signalList IndAudSignal OPTIONAL + } + +IndAudSignal ::= SEQUENCE + { + signalName PkgdName, + streamID StreamID OPTIONAL, + ..., + signalRequestID RequestID OPTIONAL + } + +IndAudDigitMapDescriptor ::= SEQUENCE + { + digitMapName DigitMapName OPTIONAL + } + +IndAudStatisticsDescriptor ::= SEQUENCE + { + statName PkgdName + } + +IndAudPackagesDescriptor ::= SEQUENCE + { + packageName Name, + packageVersion INTEGER(0..99), + ... + } + +NotifyRequest ::= SEQUENCE + { + terminationID TerminationIDList, + observedEventsDescriptor ObservedEventsDescriptor, + errorDescriptor ErrorDescriptor OPTIONAL, + ... + } + +NotifyReply ::= SEQUENCE + { + terminationID TerminationIDList, + errorDescriptor ErrorDescriptor OPTIONAL, + ... + } + +ObservedEventsDescriptor ::= SEQUENCE + { + requestId RequestID, + observedEventLst SEQUENCE OF ObservedEvent + } + +ObservedEvent ::= SEQUENCE + { + eventName EventName, + streamID StreamID OPTIONAL, + eventParList SEQUENCE OF EventParameter, + timeNotation TimeNotation OPTIONAL, + ... + } + +EventName ::= PkgdName + +EventParameter ::= SEQUENCE + { + eventParameterName Name, + value Value, + -- For use of extraInfo see the comment related to PropertyParm + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... + + } + +ServiceChangeRequest ::= SEQUENCE + { + terminationID TerminationIDList, + serviceChangeParms ServiceChangeParm, + ... + } + +ServiceChangeReply ::= SEQUENCE + { + terminationID TerminationIDList, + serviceChangeResult ServiceChangeResult, + ... + } + +-- For ServiceChangeResult, no parameters are mandatory. Hence the +-- distinction between ServiceChangeParm and ServiceChangeResParm. +ServiceChangeResult ::= CHOICE + { + errorDescriptor ErrorDescriptor, + serviceChangeResParms ServiceChangeResParm + } + +WildcardField ::= OCTET STRING(SIZE(1)) + +TerminationID ::= SEQUENCE + { + wildcard SEQUENCE OF WildcardField, + id OCTET STRING(SIZE(1..8)), + ... + } +-- See A.1 for explanation of wildcarding mechanism. +-- Termination ID 0xFFFFFFFFFFFFFFFF indicates the ROOT Termination. + +TerminationIDList ::= SEQUENCE OF TerminationID + +MediaDescriptor ::= SEQUENCE + { + termStateDescr TerminationStateDescriptor OPTIONAL, + streams CHOICE + { + oneStream StreamParms, + multiStream SEQUENCE OF StreamDescriptor + } OPTIONAL, + ... + } + +StreamDescriptor ::= SEQUENCE + { + streamID StreamID, + streamParms StreamParms + } + +StreamParms ::= SEQUENCE + { + localControlDescriptor LocalControlDescriptor OPTIONAL, + localDescriptor LocalRemoteDescriptor OPTIONAL, + remoteDescriptor LocalRemoteDescriptor OPTIONAL, + ..., + statisticsDescriptor StatisticsDescriptor OPTIONAL + } + +LocalControlDescriptor ::= SEQUENCE + { + streamMode StreamMode OPTIONAL, + reserveValue BOOLEAN OPTIONAL, + reserveGroup BOOLEAN OPTIONAL, + propertyParms SEQUENCE OF PropertyParm, + ... + } + +StreamMode ::= ENUMERATED + { + sendOnly(0), + recvOnly(1), + sendRecv(2), + inactive(3), + loopBack(4), + ... + } + +-- In PropertyParm, value is a SEQUENCE OF octet string. When sent +-- by an MGC the interpretation is as follows: +-- empty sequence means CHOOSE +-- one element sequence specifies value +-- If the sublist field is not selected, a longer sequence means +-- "choose one of the values" (i.e. value1 OR value2 OR ...) +-- If the sublist field is selected, +-- a sequence with more than one element encodes the value of a +-- list-valued property (i.e. value1 AND value2 AND ...). +-- The relation field may only be selected if the value sequence +-- has length 1. It indicates that the MG has to choose a value +-- for the property. E.g. x > 3 (using the greaterThan +-- value for relation) instructs the MG to choose any value larger +-- than 3 for property x. +-- The range field may only be selected if the value sequence +-- has length 2. It indicates that the MG has to choose a value +-- in the range between the first octet in the value sequence and +-- the trailing octet in the value sequence, including the +-- boundary values. +-- When sent by the MG, only responses to an AuditCapability request +-- may contain multiple values, a range, or a relation field. + +PropertyParm ::= SEQUENCE + { + name PkgdName, + value SEQUENCE OF OCTET STRING, + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... + } + +Name ::= OCTET STRING(SIZE(2)) + +PkgdName ::= OCTET STRING(SIZE(4)) +-- represents Package Name (2 octets) plus Property, Event, +-- Signal Names or Statistics ID. (2 octets) +-- To wildcard a package use 0xFFFF for first two octets, choose +-- is not allowed. To reference native property tag specified in +-- Annex C, use 0x0000 as first two octets. +-- To wildcard a Property, Event, Signal, or Statistics ID, use +-- 0xFFFF for last two octets, choose is not allowed. +-- Wildcarding of Package Name is permitted only if Property, +-- Event, Signal, or Statistics ID are +-- also wildcarded. + +Relation ::= ENUMERATED + { + greaterThan(0), + smallerThan(1), + unequalTo(2), + ... + } + +LocalRemoteDescriptor ::= SEQUENCE + { + propGrps SEQUENCE OF PropertyGroup, + ... + } + +PropertyGroup ::= SEQUENCE OF PropertyParm + +TerminationStateDescriptor ::= SEQUENCE + { + propertyParms SEQUENCE OF PropertyParm, + eventBufferControl EventBufferControl OPTIONAL, + serviceState ServiceState OPTIONAL, + ... + } + +EventBufferControl ::= ENUMERATED + { + off(0), + lockStep(1), + ... + } + +ServiceState ::= ENUMERATED + { + test(0), + outOfSvc(1), + inSvc(2), + ... + } + +MuxDescriptor ::= SEQUENCE + { + muxType MuxType, + termList SEQUENCE OF TerminationID, + nonStandardData NonStandardData OPTIONAL, + ... + } + +MuxType ::= ENUMERATED + { + h221(0), + h223(1), + h226(2), + v76(3), + ..., + nx64k(4) + } + +StreamID ::= INTEGER(0..65535) -- 16-bit unsigned integer + +EventsDescriptor ::= SEQUENCE + { + requestID RequestID OPTIONAL, + -- RequestID must be present if eventList + -- is non empty + eventList SEQUENCE OF RequestedEvent, + ... + } + +RequestedEvent ::= SEQUENCE + { + pkgdName PkgdName, + streamID StreamID OPTIONAL, + eventAction RequestedActions OPTIONAL, + evParList SEQUENCE OF EventParameter, + ... + } + +RegulatedEmbeddedDescriptor ::= SEQUENCE + { + secondEvent SecondEventsDescriptor OPTIONAL, + signalsDescriptor SignalsDescriptor OPTIONAL, + ... + } + +NotifyBehaviour ::= CHOICE + { + notifyImmediate NULL, + notifyRegulated RegulatedEmbeddedDescriptor, + neverNotify NULL, + ... + } + +RequestedActions ::= SEQUENCE + { + keepActive BOOLEAN OPTIONAL, + eventDM EventDM OPTIONAL, + secondEvent SecondEventsDescriptor OPTIONAL, + signalsDescriptor SignalsDescriptor OPTIONAL, + ..., + notifyBehaviour NotifyBehaviour OPTIONAL, + resetEventsDescriptor NULL OPTIONAL + } + +EventDM ::= CHOICE + { + digitMapName DigitMapName, + digitMapValue DigitMapValue + } + +SecondEventsDescriptor ::= SEQUENCE + { + requestID RequestID OPTIONAL, + eventList SEQUENCE OF SecondRequestedEvent, + ... + } + +SecondRequestedEvent ::= SEQUENCE + { + pkgdName PkgdName, + streamID StreamID OPTIONAL, + eventAction SecondRequestedActions OPTIONAL, + evParList SEQUENCE OF EventParameter, + ... + } + +SecondRequestedActions ::= SEQUENCE + { + keepActive BOOLEAN OPTIONAL, + eventDM EventDM OPTIONAL, + signalsDescriptor SignalsDescriptor OPTIONAL, + ..., + notifyBehaviour NotifyBehaviour OPTIONAL, + resetEventsDescriptor NULL OPTIONAL + } + +EventBufferDescriptor ::= SEQUENCE OF EventSpec + +EventSpec ::= SEQUENCE + { + eventName EventName, + streamID StreamID OPTIONAL, + eventParList SEQUENCE OF EventParameter, + ... + } + + +SignalsDescriptor ::= SEQUENCE OF SignalRequest + +SignalRequest ::= CHOICE + { + signal Signal, + seqSigList SeqSigList, + ... + } + +SeqSigList ::= SEQUENCE + { + id INTEGER(0..65535), + signalList SEQUENCE OF Signal + } + +Signal ::= SEQUENCE + { + signalName SignalName, + streamID StreamID OPTIONAL, + sigType SignalType OPTIONAL, + duration INTEGER (0..65535) OPTIONAL, + notifyCompletion NotifyCompletion OPTIONAL, + keepActive BOOLEAN OPTIONAL, + sigParList SEQUENCE OF SigParameter, + ..., + direction SignalDirection OPTIONAL, + requestID RequestID OPTIONAL, + intersigDelay INTEGER (0..65535) OPTIONAL + } + +SignalType ::= ENUMERATED + { + brief(0), + onOff(1), + timeOut(2), + ... + } + +SignalDirection ::= ENUMERATED + { + internal(0), + external(1), + both(3), + ... + } + +SignalName ::= PkgdName + +NotifyCompletion ::= BIT STRING + { + onTimeOut(0), onInterruptByEvent(1), + onInterruptByNewSignalDescr(2), otherReason(3), onIteration(4) + } + +SigParameter ::= SEQUENCE + { + sigParameterName Name, + value Value, + -- For use of extraInfo see the comment related to PropertyParm + extraInfo CHOICE + { + relation Relation, + range BOOLEAN, + sublist BOOLEAN + } OPTIONAL, + ... + } + +-- For an AuditCapReply with all events, the RequestID SHALL be ALL. +-- ALL is represented by 0xffffffff. +RequestID ::= INTEGER(0..4294967295) -- 32-bit unsigned integer + +ModemDescriptor ::= SEQUENCE + { + mtl SEQUENCE OF ModemType, + mpl SEQUENCE OF PropertyParm, + nonStandardData NonStandardData OPTIONAL + } + +ModemType ::= ENUMERATED + { + v18(0), + v22(1), + v22bis(2), + v32(3), + v32bis(4), + v34(5), + v90(6), + v91(7), + synchISDN(8), + ... + } + +DigitMapDescriptor ::= SEQUENCE + { + digitMapName DigitMapName OPTIONAL, + digitMapValue DigitMapValue OPTIONAL + } + +DigitMapName ::= Name + +DigitMapValue ::= SEQUENCE + { + startTimer INTEGER(0..99) OPTIONAL, + shortTimer INTEGER(0..99) OPTIONAL, + longTimer INTEGER(0..99) OPTIONAL, + digitMapBody IA5String, + -- Units are seconds for start, short and long timers, and + -- hundreds of milliseconds for duration timer. Thus start, + -- short, and long range from 1 to 99 seconds and duration + -- from 100 ms to 9.9 s + -- See A.3 for explanation of digit map syntax + ..., + durationTimer INTEGER (0..99) OPTIONAL + } + +ServiceChangeParm ::= SEQUENCE + { + serviceChangeMethod ServiceChangeMethod, + serviceChangeAddress ServiceChangeAddress OPTIONAL, + serviceChangeVersion INTEGER(0..99) OPTIONAL, + serviceChangeProfile ServiceChangeProfile OPTIONAL, + serviceChangeReason Value, + -- A serviceChangeReason consists of a numeric reason code + -- and an optional text description. + -- The serviceChangeReason SHALL be a string consisting of + -- a decimal reason code, optionally followed by a single + -- space character and a textual description string. + -- This string is first BER-encoded as an IA5String. + -- The result of this BER-encoding is then encoded as + -- an ASN.1 OCTET STRING type, "double wrapping" the + -- value + -- as was done for package elements. + serviceChangeDelay INTEGER(0..4294967295) OPTIONAL, + -- 32-bit unsigned integer + serviceChangeMgcId MId OPTIONAL, + timeStamp TimeNotation OPTIONAL, + nonStandardData NonStandardData OPTIONAL, + ..., + serviceChangeInfo AuditDescriptor OPTIONAL, + serviceChangeIncompleteFlag NULL OPTIONAL + } + +ServiceChangeAddress ::= CHOICE + { + portNumber INTEGER(0..65535), -- TCP/UDP port number + ip4Address IP4Address, + ip6Address IP6Address, + domainName DomainName, + deviceName PathName, + mtpAddress OCTET STRING(SIZE(2..4)), + ... + } + +ServiceChangeResParm ::= SEQUENCE + { + serviceChangeMgcId MId OPTIONAL, + serviceChangeAddress ServiceChangeAddress OPTIONAL, + serviceChangeVersion INTEGER(0..99) OPTIONAL, + serviceChangeProfile ServiceChangeProfile OPTIONAL, + timestamp TimeNotation OPTIONAL, + ... + } + +ServiceChangeMethod ::= ENUMERATED + { + failover(0), + forced(1), + graceful(2), + restart(3), + disconnected(4), + handOff(5), + ... + } + +ServiceChangeProfile ::= SEQUENCE + { + profileName IA5String(SIZE (1..67)) + + -- 64 characters for name, 1 for "/", 2 for version to match ABNF + } + +PackagesDescriptor ::= SEQUENCE OF PackagesItem + +PackagesItem ::= SEQUENCE + { + packageName Name, + packageVersion INTEGER(0..99), + ... + } + +StatisticsDescriptor ::= SEQUENCE OF StatisticsParameter + +StatisticsParameter ::= SEQUENCE + { + statName PkgdName, + statValue Value OPTIONAL + } + +-- If statistic consists of a sub-list there will be more than one +-- octetstring in statValue. + +NonStandardData ::= SEQUENCE + { + nonStandardIdentifier NonStandardIdentifier, + data OCTET STRING + } + +NonStandardIdentifier ::= CHOICE + { + object OBJECT IDENTIFIER, + h221NonStandard H221NonStandard, + experimental IA5String(SIZE(8)), + -- first two characters SHOULD be "X-" or "X+" + ... + } + +H221NonStandard ::= SEQUENCE + { t35CountryCode1 INTEGER(0..255), + t35CountryCode2 INTEGER(0..255), -- country, as per T.35 + t35Extension INTEGER(0..255), -- assigned nationally + manufacturerCode INTEGER(0..65535), -- assigned nationally + ... + } + +TimeNotation ::= SEQUENCE + { + date IA5String(SIZE(8)), -- yyyymmdd format + time IA5String(SIZE(8)) -- hhmmssss format + -- per ISO 8601:1988 + } + +Value ::= SEQUENCE OF OCTET STRING + +END diff --git a/lib/megaco/src/binary/Makefile b/lib/megaco/src/binary/Makefile new file mode 100644 index 0000000000..d594f34f43 --- /dev/null +++ b/lib/megaco/src/binary/Makefile @@ -0,0 +1,212 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2000-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% + +include $(ERL_TOP)/make/target.mk + +EBIN = ../../ebin +MEGACO_INCLUDEDIR = ../../include +MEGACO_ENGINEDIR = ../engine + +include $(ERL_TOP)/make/$(TARGET)/otp.mk + + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../../vsn.mk +VSN=$(MEGACO_VSN) + + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/lib/megaco-$(VSN) + + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +include modules.mk + +ASN1_SPECS = $(ASN1_V1_SPEC) \ + $(ASN1_V2_SPEC) \ + $(ASN1_PREV3A_SPEC) +ASN1_FILES = $(ASN1_SPECS:%=%.asn) + +V1_SPECS = $(BER_ASN1_V1_SPEC) \ + $(BER_BIN_ASN1_V1_SPEC) \ + $(BER_BIN_DRV_ASN1_V1_SPEC) \ + $(PER_ASN1_V1_SPEC) \ + $(PER_BIN_ASN1_V1_SPEC) \ + $(PER_BIN_DRV_ASN1_V1_SPEC) + +V2_SPECS = $(BER_ASN1_V2_SPEC) \ + $(BER_BIN_ASN1_V2_SPEC) \ + $(BER_BIN_DRV_ASN1_V2_SPEC) \ + $(PER_ASN1_V2_SPEC) \ + $(PER_BIN_ASN1_V2_SPEC) \ + $(PER_BIN_DRV_ASN1_V2_SPEC) + +PREV3A_SPECS = $(BER_ASN1_PREV3A_SPEC) \ + $(BER_BIN_ASN1_PREV3A_SPEC) \ + $(BER_BIN_DRV_ASN1_PREV3A_SPEC) \ + $(PER_ASN1_PREV3A_SPEC) \ + $(PER_BIN_ASN1_PREV3A_SPEC) \ + $(PER_BIN_DRV_ASN1_PREV3A_SPEC) + +PREV3B_SPECS = $(BER_ASN1_PREV3B_SPEC) \ + $(BER_BIN_ASN1_PREV3B_SPEC) \ + $(BER_BIN_DRV_ASN1_PREV3B_SPEC) \ + $(PER_ASN1_PREV3B_SPEC) \ + $(PER_BIN_ASN1_PREV3B_SPEC) \ + $(PER_BIN_DRV_ASN1_PREV3B_SPEC) + +PREV3C_SPECS = $(BER_ASN1_PREV3C_SPEC) \ + $(BER_BIN_ASN1_PREV3C_SPEC) \ + $(BER_BIN_DRV_ASN1_PREV3C_SPEC) \ + $(PER_ASN1_PREV3C_SPEC) \ + $(PER_BIN_ASN1_PREV3C_SPEC) \ + $(PER_BIN_DRV_ASN1_PREV3C_SPEC) + +V3_SPECS = $(BER_ASN1_V3_SPEC) \ + $(BER_BIN_ASN1_V3_SPEC) \ + $(BER_BIN_DRV_ASN1_V3_SPEC) \ + $(PER_ASN1_V3_SPEC) \ + $(PER_BIN_ASN1_V3_SPEC) \ + $(PER_BIN_DRV_ASN1_V3_SPEC) \ + $(PREV3A_SPECS) $(PREV3B_SPECS) $(PREV3C_SPECS) + +SPECS = $(V1_SPECS) $(V2_SPECS) $(V3_SPECS) + +V1_SPEC_ASN1DB = $(V1_SPECS:%=%.asn1db) +V2_SPEC_ASN1DB = $(V2_SPECS:%=%.asn1db) +PREV3A_SPEC_ASN1DB = $(PREV3A_SPECS:%=%.asn1db) +PREV3B_SPEC_ASN1DB = $(PREV3B_SPECS:%=%.asn1db) +PREV3C_SPEC_ASN1DB = $(PREV3C_SPECS:%=%.asn1db) +V3_SPEC_ASN1DB = $(V3_SPECS:%=%.asn1db) \ + $(PREV3A_SPEC_ASN1DB) \ + $(PREV3B_SPEC_ASN1DB) \ + $(PREV3C_SPEC_ASN1DB) +SPEC_ASN1DB = $(V1_SPEC_ASN1DB) \ + $(V2_SPEC_ASN1DB)\ + $(V3_SPEC_ASN1DB) + +V1_SPEC_BINS = $(V1_SPECS:%=%.erl) $(V1_SPECS:%=%.hrl) +V2_SPEC_BINS = $(V2_SPECS:%=%.erl) $(V2_SPECS:%=%.hrl) +PREV3A_SPEC_BINS = $(PREV3A_SPECS:%=%.erl) $(PREV3A_SPECS:%=%.hrl) +PREV3B_SPEC_BINS = $(PREV3B_SPECS:%=%.erl) $(PREV3B_SPECS:%=%.hrl) +PREV3C_SPEC_BINS = $(PREV3C_SPECS:%=%.erl) $(PREV3C_SPECS:%=%.hrl) +V3_SPEC_BINS = $(V3_SPECS:%=%.erl) $(V3_SPECS:%=%.hrl) \ + $(PREV3A_SPEC_BINS) \ + $(PREV3B_SPEC_BINS) \ + $(PREV3C_SPEC_BINS) +SPEC_BINS = $(V1_SPEC_BINS) $(V2_SPEC_BINS) $(V3_SPEC_BINS) + +ERL_FILES = $(MODULES:%=%.erl) +HRL_FILES = $(INTERNAL_HRL_FILES) \ + $(V1_SPECS:%=%.hrl) \ + $(V2_SPECS:%=%.hrl) \ + $(V3_SPECS:%=%.hrl) + +TARGET_FILES = \ + $(MODULES:%=$(EBIN)/%.$(EMULATOR)) + + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- +ifeq ($(TYPE),debug) +ERL_COMPILE_FLAGS += -Ddebug +endif + +include ../app/megaco.mk + +ERL_COMPILE_FLAGS += \ + $(MEGACO_ERL_COMPILE_FLAGS) \ + -I../../include + + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- +debug: + @${MAKE} TYPE=debug opt + +opt: prebuild $(TARGET_FILES) + +prebuild: prebuild.skip + +prebuild.skip: + @echo "Building prebuild.skip\c" + @touch prebuild.skip + @for a in $(SPEC_ASN1DB); do \ + echo $$a >> prebuild.skip; \ + done + @echo "" + +v1: $(V2_SPEC_BINS) + +v2: $(V2_SPEC_BINS) + +v3: $(V3_SPEC_BINS) + +specs: v1 v2 v3 + +clean: + rm -f $(TARGET_FILES) + rm -f $(SPEC_BINS) + rm -f $(SPEC_ASN1DB) + rm -f prebuild.skip + rm -f core *~ + +docs: + +info: + @echo "MODULES: $(MODULES)" + @echo "ERL_FILES: $(ERL_FILES)" + @echo "HRL_FILES: $(HRL_FILES)" + @echo "TARGET_FILES: $(TARGET_FILES)" + @echo "ASN1_SPECS: $(ASN1_SPECS)" + @echo "SPECS: $(SPECS)" + @echo "SPEC_BINS: $(SPEC_BINS)" + + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + + +release_spec: opt + $(INSTALL_DIR) $(RELSYSDIR)/ebin + $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin + $(INSTALL_DIR) $(RELSYSDIR)/src + $(INSTALL_DIR) $(RELSYSDIR)/src/binary + $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(ASN1_FILES) $(RELSYSDIR)/src/binary + + +release_docs_spec: + + +# ---------------------------------------------------- +# Include dependencies +# ---------------------------------------------------- + +include depend.mk + diff --git a/lib/megaco/src/binary/depend.mk b/lib/megaco/src/binary/depend.mk new file mode 100644 index 0000000000..5ec4977175 --- /dev/null +++ b/lib/megaco/src/binary/depend.mk @@ -0,0 +1,557 @@ +#-*-makefile-*- ; force emacs to enter makefile-mode + +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% + +# Flag description: +# +# +optimize +# For ber_bin this means "optimize" (whatever that is), +# but for per_bin it means that a stage in the encode +# is done in the asn1 driver. +# +# +driver +# For ber_bin this means that part of the decode is done +# in the asn1 driver. +# +# +asn1config +# This is only used by the ber_bin, and means that +# some partial decode functions will be created +# (as described by the asn1config file). +# +# +inline +# This means that the ASN.1 runtime library will be inlined. +# + +ASN1_CT_OPTS += +noobj +ifeq ($(MEGACO_INLINE_ASN1_RT),true) +# We need atleast version 1.4.6 of the ANS.1 application +ASN1_CT_OPTS += +inline +endif + +BER_V1_FLAGS = $(ASN1_CT_OPTS) +BER_BIN_V1_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +BER_BIN_DRV_V1_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver +BER_V2_FLAGS = $(ASN1_CT_OPTS) +BER_BIN_V2_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +BER_BIN_DRV_V2_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver +BER_PREV3A_FLAGS = $(ASN1_CT_OPTS) +BER_BIN_PREV3A_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +BER_BIN_DRV_PREV3A_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver +BER_PREV3B_FLAGS = $(ASN1_CT_OPTS) +BER_BIN_PREV3B_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +BER_BIN_DRV_PREV3B_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver +BER_PREV3C_FLAGS = $(ASN1_CT_OPTS) +BER_BIN_PREV3C_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +BER_BIN_DRV_PREV3C_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver +BER_V3_FLAGS = $(ASN1_CT_OPTS) +BER_BIN_V3_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +BER_BIN_DRV_V3_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver +PER_V1_FLAGS = $(ASN1_CT_OPTS) +PER_BIN_V1_FLAGS = $(ASN1_CT_OPTS) +PER_BIN_DRV_V1_FLAGS = $(ASN1_CT_OPTS) +optimize +PER_V2_FLAGS = $(ASN1_CT_OPTS) +PER_BIN_V2_FLAGS = $(ASN1_CT_OPTS) +PER_BIN_DRV_V2_FLAGS = $(ASN1_CT_OPTS) +optimize +PER_PREV3A_FLAGS = $(ASN1_CT_OPTS) +PER_BIN_PREV3A_FLAGS = $(ASN1_CT_OPTS) +PER_BIN_DRV_PREV3A_FLAGS = $(ASN1_CT_OPTS) +optimize +PER_PREV3B_FLAGS = $(ASN1_CT_OPTS) +PER_BIN_PREV3B_FLAGS = $(ASN1_CT_OPTS) +PER_BIN_DRV_PREV3B_FLAGS = $(ASN1_CT_OPTS) +optimize +PER_PREV3C_FLAGS = $(ASN1_CT_OPTS) +PER_BIN_PREV3C_FLAGS = $(ASN1_CT_OPTS) +PER_BIN_DRV_PREV3C_FLAGS = $(ASN1_CT_OPTS) +optimize +PER_V3_FLAGS = $(ASN1_CT_OPTS) +PER_BIN_V3_FLAGS = $(ASN1_CT_OPTS) +PER_BIN_DRV_V3_FLAGS = $(ASN1_CT_OPTS) +optimize + + +# --- Version 1 --- + +$(BER_ASN1_V1_SPEC).erl $(BER_ASN1_V1_SPEC).hrl: \ + $(BER_ASN1_V1_SPEC).set.asn \ + $(ASN1_V1_SPEC).asn + @echo "$(BER_ASN1_V1_SPEC):" + $(ERLC) -bber $(BER_V1_FLAGS) $(BER_ASN1_V1_SPEC).set.asn + +$(EBIN)/$(BER_ASN1_V1_SPEC).$(EMULATOR): \ + $(BER_ASN1_V1_SPEC).erl \ + $(BER_ASN1_V1_SPEC).hrl + +$(BER_BIN_ASN1_V1_SPEC).erl $(BER_BIN_ASN1_V1_SPEC).hrl: \ + $(BER_BIN_ASN1_V1_SPEC).set.asn \ + $(BER_BIN_ASN1_V1_SPEC).asn1config \ + $(ASN1_V1_SPEC).asn + @echo "$(BER_BIN_ASN1_V1_SPEC):" + $(ERLC) -bber_bin $(BER_BIN_V1_FLAGS) $(BER_BIN_ASN1_V1_SPEC).set.asn + +$(EBIN)/$(BER_BIN_ASN1_V1_SPEC).$(EMULATOR): \ + $(BER_BIN_ASN1_V1_SPEC).erl \ + $(BER_BIN_ASN1_V1_SPEC).hrl + +$(BER_BIN_DRV_ASN1_V1_SPEC).erl $(BER_BIN_DRV_ASN1_V1_SPEC).hrl: \ + $(BER_BIN_DRV_ASN1_V1_SPEC).set.asn \ + $(BER_BIN_DRV_ASN1_V1_SPEC).asn1config \ + $(ASN1_V1_SPEC).asn + @echo "$(BER_BIN_DRV_ASN1_V1_SPEC):" + $(ERLC) -bber_bin $(BER_BIN_DRV_V1_FLAGS) $(BER_BIN_DRV_ASN1_V1_SPEC).set.asn + +$(EBIN)/$(BER_BIN_DRV_ASN1_V1_SPEC).$(EMULATOR): \ + $(BER_BIN_DRV_ASN1_V1_SPEC).erl \ + $(BER_BIN_DRV_ASN1_V1_SPEC).hrl + +$(PER_ASN1_V1_SPEC).erl $(PER_ASN1_V1_SPEC).hrl: \ + $(PER_ASN1_V1_SPEC).set.asn \ + $(ASN1_V1_SPEC).asn + @echo "$(PER_ASN1_V1_SPEC):" + $(ERLC) -bper $(PER_V1_FLAGS) $(PER_ASN1_V1_SPEC).set.asn + +$(EBIN)/$(PER_ASN1_V1_SPEC).$(EMULATOR): \ + $(PER_ASN1_V1_SPEC).erl \ + $(PER_ASN1_V1_SPEC).hrl + +$(PER_BIN_ASN1_V1_SPEC).erl $(PER_BIN_ASN1_V1_SPEC).hrl: \ + $(PER_BIN_ASN1_V1_SPEC).set.asn \ + $(ASN1_V1_SPEC).asn + @echo "$(PER_BIN_ASN1_V1_SPEC):" + $(ERLC) -bper_bin $(PER_BIN_V1_FLAGS) $(PER_BIN_ASN1_V1_SPEC).set.asn + +$(EBIN)/$(PER_BIN_ASN1_V1_SPEC).$(EMULATOR): \ + $(PER_BIN_ASN1_V1_SPEC).erl \ + $(PER_BIN_ASN1_V1_SPEC).hrl + +$(PER_BIN_DRV_ASN1_V1_SPEC).erl $(PER_BIN_DRV_ASN1_V1_SPEC).hrl: \ + $(PER_BIN_DRV_ASN1_V1_SPEC).set.asn \ + $(ASN1_V1_SPEC).asn + @echo "$(PER_BIN_DRV_ASN1_V1_SPEC):" + $(ERLC) -bper_bin $(PER_BIN_DRV_V1_FLAGS) $(PER_BIN_DRV_ASN1_V1_SPEC).set.asn + +$(EBIN)/$(PER_BIN_DRV_ASN1_V1_SPEC).$(EMULATOR): \ + $(PER_BIN_DRV_ASN1_V1_SPEC).erl \ + $(PER_BIN_DRV_ASN1_V1_SPEC).hrl + + +# --- Version 2 --- + +$(BER_ASN1_V2_SPEC).erl $(BER_ASN1_V2_SPEC).hrl: \ + $(BER_ASN1_V2_SPEC).set.asn \ + $(ASN1_V2_SPEC).asn + @echo "$(BER_ASN1_V2_SPEC):" + $(ERLC) -bber $(BER_V2_FLAGS) $(BER_ASN1_V2_SPEC).set.asn + +$(EBIN)/$(BER_ASN1_V2_SPEC).$(EMULATOR): \ + $(BER_ASN1_V2_SPEC).erl \ + $(BER_ASN1_V2_SPEC).hrl + +$(BER_BIN_ASN1_V2_SPEC).erl $(BER_BIN_ASN1_V2_SPEC).hrl: \ + $(BER_BIN_ASN1_V2_SPEC).set.asn \ + $(BER_BIN_ASN1_V2_SPEC).asn1config \ + $(ASN1_V2_SPEC).asn + @echo "$(BER_BIN_ASN1_V2_SPEC):" + $(ERLC) -bber_bin $(BER_BIN_V2_FLAGS) $(BER_BIN_ASN1_V2_SPEC).set.asn + +$(EBIN)/$(BER_BIN_ASN1_V2_SPEC).$(EMULATOR): \ + $(BER_BIN_ASN1_V2_SPEC).erl \ + $(BER_BIN_ASN1_V2_SPEC).hrl + +$(BER_BIN_DRV_ASN1_V2_SPEC).erl $(BER_BIN_DRV_ASN1_V2_SPEC).hrl: \ + $(BER_BIN_DRV_ASN1_V2_SPEC).set.asn \ + $(BER_BIN_DRV_ASN1_V2_SPEC).asn1config \ + $(ASN1_V2_SPEC).asn + @echo "$(BER_BIN_DRV_ASN1_V2_SPEC):" + $(ERLC) -bber_bin $(BER_BIN_DRV_V2_FLAGS) $(BER_BIN_DRV_ASN1_V2_SPEC).set.asn + +$(EBIN)/$(BER_BIN_DRV_ASN1_V2_SPEC).$(EMULATOR): \ + $(BER_BIN_DRV_ASN1_V2_SPEC).erl \ + $(BER_BIN_DRV_ASN1_V2_SPEC).hrl + +$(PER_ASN1_V2_SPEC).erl $(PER_ASN1_V2_SPEC).hrl: \ + $(PER_ASN1_V2_SPEC).set.asn \ + $(ASN1_V2_SPEC).asn + @echo "$(PER_ASN1_V2_SPEC):" + $(ERLC) -bper $(PER_V2_FLAGS) $(PER_ASN1_V2_SPEC).set.asn + +$(EBIN)/$(PER_ASN1_V2_SPEC).$(EMULATOR): \ + $(PER_ASN1_V2_SPEC).erl \ + $(PER_ASN1_V2_SPEC).hrl + +$(PER_BIN_ASN1_V2_SPEC).erl $(PER_BIN_ASN1_V2_SPEC).hrl: \ + $(PER_BIN_ASN1_V2_SPEC).set.asn \ + $(ASN1_V2_SPEC).asn + @echo "$(PER_BIN_ASN1_V2_SPEC):" + $(ERLC) -bper_bin $(PER_BIN_V2_FLAGS) $(PER_BIN_ASN1_V2_SPEC).set.asn + +$(EBIN)/$(PER_BIN_ASN1_V2_SPEC).$(EMULATOR): \ + $(PER_BIN_ASN1_V2_SPEC).erl \ + $(PER_BIN_ASN1_V2_SPEC).hrl + +$(PER_BIN_DRV_ASN1_V2_SPEC).erl $(PER_BIN_DRV_ASN1_V2_SPEC).hrl: \ + $(PER_BIN_DRV_ASN1_V2_SPEC).set.asn \ + $(ASN1_V2_SPEC).asn + @echo "$(PER_BIN_DRV_ASN1_V2_SPEC):" + $(ERLC) -bper_bin $(PER_BIN_DRV_V2_FLAGS) $(PER_BIN_DRV_ASN1_V2_SPEC).set.asn + +$(EBIN)/$(PER_BIN_DRV_ASN1_V2_SPEC).$(EMULATOR): \ + $(PER_BIN_DRV_ASN1_V2_SPEC).erl \ + $(PER_BIN_DRV_ASN1_V2_SPEC).hrl + + +# --- Version 3 --- + +# -- (prev3a) -- + +$(BER_ASN1_PREV3A_SPEC).erl $(BER_ASN1_PREV3A_SPEC).hrl: \ + $(BER_ASN1_PREV3A_SPEC).set.asn \ + $(ASN1_PREV3A_SPEC).asn + @echo "$(BER_ASN1_PREV3A_SPEC):" + $(ERLC) -bber $(BER_PREV3A_FLAGS) $(BER_ASN1_PREV3A_SPEC).set.asn + +$(EBIN)/$(BER_ASN1_PREV3A_SPEC).$(EMULATOR): \ + $(BER_ASN1_PREV3A_SPEC).erl \ + $(BER_ASN1_PREV3A_SPEC).hrl + +$(BER_BIN_ASN1_PREV3A_SPEC).erl $(BER_BIN_ASN1_PREV3A_SPEC).hrl: \ + $(BER_BIN_ASN1_PREV3A_SPEC).set.asn \ + $(BER_BIN_ASN1_PREV3A_SPEC).asn1config \ + $(ASN1_PREV3A_SPEC).asn + @echo "$(BER_BIN_ASN1_PREV3A_SPEC):" + $(ERLC) -bber_bin $(BER_BIN_PREV3A_FLAGS) $(BER_BIN_ASN1_PREV3A_SPEC).set.asn + +$(EBIN)/$(BER_BIN_ASN1_PREV3A_SPEC).$(EMULATOR): \ + $(BER_BIN_ASN1_PREV3A_SPEC).erl \ + $(BER_BIN_ASN1_PREV3A_SPEC).hrl + +$(BER_BIN_DRV_ASN1_PREV3A_SPEC).erl $(BER_BIN_DRV_ASN1_PREV3A_SPEC).hrl: \ + $(BER_BIN_DRV_ASN1_PREV3A_SPEC).set.asn \ + $(BER_BIN_DRV_ASN1_PREV3A_SPEC).asn1config \ + $(ASN1_PREV3A_SPEC).asn + @echo "$(BER_BIN_DRV_ASN1_PREV3A_SPEC):" + $(ERLC) -bber_bin $(BER_BIN_DRV_PREV3A_FLAGS) $(BER_BIN_DRV_ASN1_PREV3A_SPEC).set.asn + +$(EBIN)/$(BER_BIN_DRV_ASN1_PREV3A_SPEC).$(EMULATOR): \ + $(BER_BIN_DRV_ASN1_PREV3A_SPEC).erl \ + $(BER_BIN_DRV_ASN1_PREV3A_SPEC).hrl + +$(PER_ASN1_PREV3A_SPEC).erl $(PER_ASN1_PREV3A_SPEC).hrl: \ + $(PER_ASN1_PREV3A_SPEC).set.asn \ + $(ASN1_PREV3A_SPEC).asn + @echo "$(PER_ASN1_PREV3A_SPEC):" + $(ERLC) -bper $(PER_PREV3A_FLAGS) $(PER_ASN1_PREV3A_SPEC).set.asn + +$(EBIN)/$(PER_ASN1_PREV3A_SPEC).$(EMULATOR): \ + $(PER_ASN1_PREV3A_SPEC).erl \ + $(PER_ASN1_PREV3A_SPEC).hrl + +$(PER_BIN_ASN1_PREV3A_SPEC).erl $(PER_BIN_ASN1_PREV3A_SPEC).hrl: \ + $(PER_BIN_ASN1_PREV3A_SPEC).set.asn \ + $(ASN1_PREV3A_SPEC).asn + @echo "$(PER_BIN_ASN1_PREV3A_SPEC):" + $(ERLC) -bper_bin $(PER_BIN_PREV3A_FLAGS) $(PER_BIN_ASN1_PREV3A_SPEC).set.asn + +$(EBIN)/$(PER_BIN_ASN1_PREV3A_SPEC).$(EMULATOR): \ + $(PER_BIN_ASN1_PREV3A_SPEC).erl \ + $(PER_BIN_ASN1_PREV3A_SPEC).hrl + +$(PER_BIN_DRV_ASN1_PREV3A_SPEC).erl $(PER_BIN_DRV_ASN1_PREV3A_SPEC).hrl: \ + $(PER_BIN_DRV_ASN1_PREV3A_SPEC).set.asn \ + $(ASN1_PREV3A_SPEC).asn + @echo "$(PER_BIN_DRV_ASN1_PREV3A_SPEC):" + $(ERLC) -bper_bin $(PER_BIN_DRV_PREV3A_FLAGS) $(PER_BIN_DRV_ASN1_PREV3A_SPEC).set.asn + +$(EBIN)/$(PER_BIN_DRV_ASN1_PREV3A_SPEC).$(EMULATOR): \ + $(PER_BIN_DRV_ASN1_PREV3A_SPEC).erl \ + $(PER_BIN_DRV_ASN1_PREV3A_SPEC).hrl + +# -- (prev3b) -- + +$(BER_ASN1_PREV3B_SPEC).erl $(BER_ASN1_PREV3B_SPEC).hrl: \ + $(BER_ASN1_PREV3B_SPEC).set.asn \ + $(ASN1_PREV3B_SPEC).asn + @echo "$(BER_ASN1_PREV3B_SPEC):" + $(ERLC) -bber $(BER_PREV3B_FLAGS) $(BER_ASN1_PREV3B_SPEC).set.asn + +$(EBIN)/$(BER_ASN1_PREV3B_SPEC).$(EMULATOR): \ + $(BER_ASN1_PREV3B_SPEC).erl \ + $(BER_ASN1_PREV3B_SPEC).hrl + +$(BER_BIN_ASN1_PREV3B_SPEC).erl $(BER_BIN_ASN1_PREV3B_SPEC).hrl: \ + $(BER_BIN_ASN1_PREV3B_SPEC).set.asn \ + $(BER_BIN_ASN1_PREV3B_SPEC).asn1config \ + $(ASN1_PREV3B_SPEC).asn + @echo "$(BER_BIN_ASN1_PREV3B_SPEC):" + $(ERLC) -bber_bin $(BER_BIN_PREV3B_FLAGS) $(BER_BIN_ASN1_PREV3B_SPEC).set.asn + +$(EBIN)/$(BER_BIN_ASN1_PREV3B_SPEC).$(EMULATOR): \ + $(BER_BIN_ASN1_PREV3B_SPEC).erl \ + $(BER_BIN_ASN1_PREV3B_SPEC).hrl + +$(BER_BIN_DRV_ASN1_PREV3B_SPEC).erl $(BER_BIN_DRV_ASN1_PREV3B_SPEC).hrl: \ + $(BER_BIN_DRV_ASN1_PREV3B_SPEC).set.asn \ + $(BER_BIN_DRV_ASN1_PREV3B_SPEC).asn1config \ + $(ASN1_PREV3B_SPEC).asn + @echo "$(BER_BIN_DRV_ASN1_PREV3B_SPEC):" + $(ERLC) -bber_bin $(BER_BIN_DRV_PREV3B_FLAGS) $(BER_BIN_DRV_ASN1_PREV3B_SPEC).set.asn + +$(EBIN)/$(BER_BIN_DRV_ASN1_PREV3B_SPEC).$(EMULATOR): \ + $(BER_BIN_DRV_ASN1_PREV3B_SPEC).erl \ + $(BER_BIN_DRV_ASN1_PREV3B_SPEC).hrl + +$(PER_ASN1_PREV3B_SPEC).erl $(PER_ASN1_PREV3B_SPEC).hrl: \ + $(PER_ASN1_PREV3B_SPEC).set.asn \ + $(ASN1_PREV3B_SPEC).asn + @echo "$(PER_ASN1_PREV3B_SPEC):" + $(ERLC) -bper $(PER_PREV3B_FLAGS) $(PER_ASN1_PREV3B_SPEC).set.asn + +$(EBIN)/$(PER_ASN1_PREV3B_SPEC).$(EMULATOR): \ + $(PER_ASN1_PREV3B_SPEC).erl \ + $(PER_ASN1_PREV3B_SPEC).hrl + +$(PER_BIN_ASN1_PREV3B_SPEC).erl $(PER_BIN_ASN1_PREV3B_SPEC).hrl: \ + $(PER_BIN_ASN1_PREV3B_SPEC).set.asn \ + $(ASN1_PREV3B_SPEC).asn + @echo "$(PER_BIN_ASN1_PREV3B_SPEC):" + $(ERLC) -bper_bin $(PER_BIN_PREV3B_FLAGS) $(PER_BIN_ASN1_PREV3B_SPEC).set.asn + +$(EBIN)/$(PER_BIN_ASN1_PREV3B_SPEC).$(EMULATOR): \ + $(PER_BIN_ASN1_PREV3B_SPEC).erl \ + $(PER_BIN_ASN1_PREV3B_SPEC).hrl + +$(PER_BIN_DRV_ASN1_PREV3B_SPEC).erl $(PER_BIN_DRV_ASN1_PREV3B_SPEC).hrl: \ + $(PER_BIN_DRV_ASN1_PREV3B_SPEC).set.asn \ + $(ASN1_PREV3B_SPEC).asn + @echo "$(PER_BIN_DRV_ASN1_PREV3B_SPEC):" + $(ERLC) -bper_bin $(PER_BIN_DRV_PREV3B_FLAGS) $(PER_BIN_DRV_ASN1_PREV3B_SPEC).set.asn + +$(EBIN)/$(PER_BIN_DRV_ASN1_PREV3B_SPEC).$(EMULATOR): \ + $(PER_BIN_DRV_ASN1_PREV3B_SPEC).erl \ + $(PER_BIN_DRV_ASN1_PREV3B_SPEC).hrl + + +# -- (prev3c) -- + +$(BER_ASN1_PREV3C_SPEC).erl $(BER_ASN1_PREV3C_SPEC).hrl: \ + $(BER_ASN1_PREV3C_SPEC).set.asn \ + $(ASN1_PREV3C_SPEC).asn + @echo "$(BER_ASN1_PREV3C_SPEC):" + $(ERLC) -bber $(BER_PREV3C_FLAGS) $(BER_ASN1_PREV3C_SPEC).set.asn + +$(EBIN)/$(BER_ASN1_PREV3C_SPEC).$(EMULATOR): \ + $(BER_ASN1_PREV3C_SPEC).erl \ + $(BER_ASN1_PREV3C_SPEC).hrl + +$(BER_BIN_ASN1_PREV3C_SPEC).erl $(BER_BIN_ASN1_PREV3C_SPEC).hrl: \ + $(BER_BIN_ASN1_PREV3C_SPEC).set.asn \ + $(BER_BIN_ASN1_PREV3C_SPEC).asn1config \ + $(ASN1_PREV3C_SPEC).asn + @echo "$(BER_BIN_ASN1_PREV3C_SPEC):" + $(ERLC) -bber_bin $(BER_BIN_PREV3C_FLAGS) $(BER_BIN_ASN1_PREV3C_SPEC).set.asn + +$(EBIN)/$(BER_BIN_ASN1_PREV3C_SPEC).$(EMULATOR): \ + $(BER_BIN_ASN1_PREV3C_SPEC).erl \ + $(BER_BIN_ASN1_PREV3C_SPEC).hrl + +$(BER_BIN_DRV_ASN1_PREV3C_SPEC).erl $(BER_BIN_DRV_ASN1_PREV3C_SPEC).hrl: \ + $(BER_BIN_DRV_ASN1_PREV3C_SPEC).set.asn \ + $(BER_BIN_DRV_ASN1_PREV3C_SPEC).asn1config \ + $(ASN1_PREV3C_SPEC).asn + @echo "$(BER_BIN_DRV_ASN1_PREV3C_SPEC):" + $(ERLC) -bber_bin $(BER_BIN_DRV_PREV3C_FLAGS) $(BER_BIN_DRV_ASN1_PREV3C_SPEC).set.asn + +$(EBIN)/$(BER_BIN_DRV_ASN1_PREV3C_SPEC).$(EMULATOR): \ + $(BER_BIN_DRV_ASN1_PREV3C_SPEC).erl \ + $(BER_BIN_DRV_ASN1_PREV3C_SPEC).hrl + +$(PER_ASN1_PREV3C_SPEC).erl $(PER_ASN1_PREV3C_SPEC).hrl: \ + $(PER_ASN1_PREV3C_SPEC).set.asn \ + $(ASN1_PREV3C_SPEC).asn + @echo "$(PER_ASN1_PREV3C_SPEC):" + $(ERLC) -bper $(PER_PREV3C_FLAGS) $(PER_ASN1_PREV3C_SPEC).set.asn + +$(EBIN)/$(PER_ASN1_PREV3C_SPEC).$(EMULATOR): \ + $(PER_ASN1_PREV3C_SPEC).erl \ + $(PER_ASN1_PREV3C_SPEC).hrl + +$(PER_BIN_ASN1_PREV3C_SPEC).erl $(PER_BIN_ASN1_PREV3C_SPEC).hrl: \ + $(PER_BIN_ASN1_PREV3C_SPEC).set.asn \ + $(ASN1_PREV3C_SPEC).asn + @echo "$(PER_BIN_ASN1_PREV3C_SPEC):" + $(ERLC) -bper_bin $(PER_BIN_PREV3C_FLAGS) $(PER_BIN_ASN1_PREV3C_SPEC).set.asn + +$(EBIN)/$(PER_BIN_ASN1_PREV3C_SPEC).$(EMULATOR): \ + $(PER_BIN_ASN1_PREV3C_SPEC).erl \ + $(PER_BIN_ASN1_PREV3C_SPEC).hrl + +$(PER_BIN_DRV_ASN1_PREV3C_SPEC).erl $(PER_BIN_DRV_ASN1_PREV3C_SPEC).hrl: \ + $(PER_BIN_DRV_ASN1_PREV3C_SPEC).set.asn \ + $(ASN1_PREV3C_SPEC).asn + @echo "$(PER_BIN_DRV_ASN1_PREV3C_SPEC):" + $(ERLC) -bper_bin $(PER_BIN_DRV_PREV3C_FLAGS) $(PER_BIN_DRV_ASN1_PREV3C_SPEC).set.asn + +$(EBIN)/$(PER_BIN_DRV_ASN1_PREV3C_SPEC).$(EMULATOR): \ + $(PER_BIN_DRV_ASN1_PREV3C_SPEC).erl \ + $(PER_BIN_DRV_ASN1_PREV3C_SPEC).hrl + + +# -- (v3) -- + +$(BER_ASN1_V3_SPEC).erl $(BER_ASN1_V3_SPEC).hrl: \ + $(BER_ASN1_V3_SPEC).set.asn \ + $(ASN1_V3_SPEC).asn + @echo "$(BER_ASN1_V3_SPEC):" + $(ERLC) -bber $(BER_V3_FLAGS) $(BER_ASN1_V3_SPEC).set.asn + +$(EBIN)/$(BER_ASN1_V3_SPEC).$(EMULATOR): \ + $(BER_ASN1_V3_SPEC).erl \ + $(BER_ASN1_V3_SPEC).hrl + +$(BER_BIN_ASN1_V3_SPEC).erl $(BER_BIN_ASN1_V3_SPEC).hrl: \ + $(BER_BIN_ASN1_V3_SPEC).set.asn \ + $(BER_BIN_ASN1_V3_SPEC).asn1config \ + $(ASN1_V3_SPEC).asn + @echo "$(BER_BIN_ASN1_V3_SPEC):" + $(ERLC) -bber_bin $(BER_BIN_V3_FLAGS) $(BER_BIN_ASN1_V3_SPEC).set.asn + +$(EBIN)/$(BER_BIN_ASN1_V3_SPEC).$(EMULATOR): \ + $(BER_BIN_ASN1_V3_SPEC).erl \ + $(BER_BIN_ASN1_V3_SPEC).hrl + +$(BER_BIN_DRV_ASN1_V3_SPEC).erl $(BER_BIN_DRV_ASN1_V3_SPEC).hrl: \ + $(BER_BIN_DRV_ASN1_V3_SPEC).set.asn \ + $(BER_BIN_DRV_ASN1_V3_SPEC).asn1config \ + $(ASN1_V3_SPEC).asn + @echo "$(BER_BIN_DRV_ASN1_V3_SPEC):" + $(ERLC) -bber_bin $(BER_BIN_DRV_V3_FLAGS) $(BER_BIN_DRV_ASN1_V3_SPEC).set.asn + +$(EBIN)/$(BER_BIN_DRV_ASN1_V3_SPEC).$(EMULATOR): \ + $(BER_BIN_DRV_ASN1_V3_SPEC).erl \ + $(BER_BIN_DRV_ASN1_V3_SPEC).hrl + +$(PER_ASN1_V3_SPEC).erl $(PER_ASN1_V3_SPEC).hrl: \ + $(PER_ASN1_V3_SPEC).set.asn \ + $(ASN1_V3_SPEC).asn + @echo "$(PER_ASN1_V3_SPEC):" + $(ERLC) -bper $(PER_V3_FLAGS) $(PER_ASN1_V3_SPEC).set.asn + +$(EBIN)/$(PER_ASN1_V3_SPEC).$(EMULATOR): \ + $(PER_ASN1_V3_SPEC).erl \ + $(PER_ASN1_V3_SPEC).hrl + +$(PER_BIN_ASN1_V3_SPEC).erl $(PER_BIN_ASN1_V3_SPEC).hrl: \ + $(PER_BIN_ASN1_V3_SPEC).set.asn \ + $(ASN1_V3_SPEC).asn + @echo "$(PER_BIN_ASN1_V3_SPEC):" + $(ERLC) -bper_bin $(PER_BIN_V3_FLAGS) $(PER_BIN_ASN1_V3_SPEC).set.asn + +$(EBIN)/$(PER_BIN_ASN1_V3_SPEC).$(EMULATOR): \ + $(PER_BIN_ASN1_V3_SPEC).erl \ + $(PER_BIN_ASN1_V3_SPEC).hrl + +$(PER_BIN_DRV_ASN1_V3_SPEC).erl $(PER_BIN_DRV_ASN1_V3_SPEC).hrl: \ + $(PER_BIN_DRV_ASN1_V3_SPEC).set.asn \ + $(ASN1_V3_SPEC).asn + @echo "$(PER_BIN_DRV_ASN1_V3_SPEC):" + $(ERLC) -bper_bin $(PER_BIN_DRV_V3_FLAGS) $(PER_BIN_DRV_ASN1_V3_SPEC).set.asn + +$(EBIN)/$(PER_BIN_DRV_ASN1_V3_SPEC).$(EMULATOR): \ + $(PER_BIN_DRV_ASN1_V3_SPEC).erl \ + $(PER_BIN_DRV_ASN1_V3_SPEC).hrl + + +# ------------- + +$(EBIN)/megaco_ber_encoder.$(EMULATOR): megaco_ber_encoder.erl \ + $(MEGACO_ENGINEDIR)/megaco_message_internal.hrl + +$(EBIN)/megaco_ber_bin_encoder.$(EMULATOR): megaco_ber_bin_encoder.erl \ + $(MEGACO_ENGINEDIR)/megaco_message_internal.hrl + +$(EBIN)/megaco_per_encoder.$(EMULATOR): megaco_per_encoder.erl \ + $(MEGACO_ENGINEDIR)/megaco_message_internal.hrl + +$(EBIN)/megaco_per_bin_encoder.$(EMULATOR): megaco_per_bin_encoder.erl \ + $(MEGACO_ENGINEDIR)/megaco_message_internal.hrl + +$(EBIN)/megaco_binary_encoder_lib.$(EMULATOR): megaco_binary_encoder_lib.erl \ + $(MEGACO_ENGINEDIR)/megaco_message_internal.hrl + +$(EBIN)/megaco_binary_encoder.$(EMULATOR): megaco_binary_encoder.erl \ + $(MEGACO_ENGINEDIR)/megaco_message_internal.hrl + +$(EBIN)/megaco_binary_name_resolver_v1.$(EMULATOR): \ + megaco_binary_name_resolver_v1.erl \ + ../app/megaco_internal.hrl + +$(EBIN)/megaco_binary_name_resolver_v2.$(EMULATOR): \ + megaco_binary_name_resolver_v2.erl \ + ../app/megaco_internal.hrl + +$(EBIN)/megaco_binary_name_resolver_prev3a.$(EMULATOR): \ + megaco_binary_name_resolver_prev3a.erl \ + ../app/megaco_internal.hrl + +$(EBIN)/megaco_binary_name_resolver_prev3b.$(EMULATOR): \ + megaco_binary_name_resolver_prev3b.erl \ + ../app/megaco_internal.hrl + +$(EBIN)/megaco_binary_name_resolver_prev3c.$(EMULATOR): \ + megaco_binary_name_resolver_prev3c.erl \ + ../app/megaco_internal.hrl + +$(EBIN)/megaco_binary_name_resolver_v3.$(EMULATOR): \ + megaco_binary_name_resolver_v3.erl + +$(EBIN)/megaco_binary_term_id.$(EMULATOR): megaco_binary_term_id.erl + +$(EBIN)/megaco_binary_term_id_gen.$(EMULATOR): megaco_binary_term_id_gen.erl + +$(EBIN)/megaco_binary_transformer_v1.$(EMULATOR): \ + megaco_binary_transformer_v1.erl \ + ../app/megaco_internal.hrl \ + $(MEGACO_INCLUDEDIR)/megaco.hrl \ + $(MEGACO_INCLUDEDIR)/megaco_message_v1.hrl + +$(EBIN)/megaco_binary_transformer_v2.$(EMULATOR): \ + megaco_binary_transformer_v2.erl \ + ../app/megaco_internal.hrl \ + $(MEGACO_INCLUDEDIR)/megaco.hrl \ + $(MEGACO_INCLUDEDIR)/megaco_message_v2.hrl + +$(EBIN)/megaco_binary_transformer_prev3a.$(EMULATOR): \ + megaco_binary_transformer_prev3a.erl \ + ../app/megaco_internal.hrl \ + $(MEGACO_INCLUDEDIR)/megaco.hrl \ + $(MEGACO_INCLUDEDIR)/megaco_message_prev3a.hrl + +$(EBIN)/megaco_binary_transformer_prev3b.$(EMULATOR): \ + megaco_binary_transformer_prev3b.erl \ + ../app/megaco_internal.hrl \ + $(MEGACO_INCLUDEDIR)/megaco.hrl \ + $(MEGACO_INCLUDEDIR)/megaco_message_prev3b.hrl + +$(EBIN)/megaco_binary_transformer_prev3c.$(EMULATOR): \ + megaco_binary_transformer_prev3c.erl \ + ../app/megaco_internal.hrl \ + $(MEGACO_INCLUDEDIR)/megaco.hrl \ + $(MEGACO_INCLUDEDIR)/megaco_message_prev3c.hrl + +$(EBIN)/megaco_binary_transformer_v3.$(EMULATOR): \ + megaco_binary_transformer_v3.erl \ + ../app/megaco_internal.hrl \ + $(MEGACO_INCLUDEDIR)/megaco.hrl \ + $(MEGACO_INCLUDEDIR)/megaco_message_v3.hrl + diff --git a/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3a.asn1config b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3a.asn1config new file mode 100644 index 0000000000..179473717d --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3a.asn1config @@ -0,0 +1,43 @@ +{exclusive_decode, + {'megaco_ber_bin_drv_media_gateway_control_prev3a', + [ + {decode_message_trans_partial, + [ + 'MegacoMessage',[{mess,[{messageBody,[{transactions,parts}]}]}] + ] + }, + {decode_message_acts_partial, + ['Transaction', + [ + {transactionRequest, + [ + {actions,parts} + ] + }, + {transactionReply, + [ + {transactionResult, [{actionReplies,parts}]} + ] + } + ] + ] + }, + {decode_message_version, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{mId,undecoded},{messageBody,undecoded}]} + ] + ] + }, + {decode_message_mId, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{messageBody,undecoded}]} + ] + ] + } + ] + } +}. diff --git a/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3a.set.asn b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3a.set.asn new file mode 100644 index 0000000000..b9ba7ffdb4 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3a.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3a.asn diff --git a/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3b.asn1config b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3b.asn1config new file mode 100644 index 0000000000..ceda97fbd1 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3b.asn1config @@ -0,0 +1,43 @@ +{exclusive_decode, + {'megaco_ber_bin_drv_media_gateway_control_prev3b', + [ + {decode_message_trans_partial, + [ + 'MegacoMessage',[{mess,[{messageBody,[{transactions,parts}]}]}] + ] + }, + {decode_message_acts_partial, + ['Transaction', + [ + {transactionRequest, + [ + {actions,parts} + ] + }, + {transactionReply, + [ + {transactionResult, [{actionReplies,parts}]} + ] + } + ] + ] + }, + {decode_message_version, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{mId,undecoded},{messageBody,undecoded}]} + ] + ] + }, + {decode_message_mId, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{messageBody,undecoded}]} + ] + ] + } + ] + } +}. diff --git a/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3b.set.asn b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3b.set.asn new file mode 100644 index 0000000000..0437bde310 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3b.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3b.asn diff --git a/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3c.asn1config b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3c.asn1config new file mode 100644 index 0000000000..d181ef44bd --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3c.asn1config @@ -0,0 +1,43 @@ +{exclusive_decode, + {'megaco_ber_bin_drv_media_gateway_control_prev3c', + [ + {decode_message_trans_partial, + [ + 'MegacoMessage',[{mess,[{messageBody,[{transactions,parts}]}]}] + ] + }, + {decode_message_acts_partial, + ['Transaction', + [ + {transactionRequest, + [ + {actions,parts} + ] + }, + {transactionReply, + [ + {transactionResult, [{actionReplies,parts}]} + ] + } + ] + ] + }, + {decode_message_version, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{mId,undecoded},{messageBody,undecoded}]} + ] + ] + }, + {decode_message_mId, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{messageBody,undecoded}]} + ] + ] + } + ] + } +}. diff --git a/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3c.set.asn b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3c.set.asn new file mode 100644 index 0000000000..e78055fbad --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3c.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3c.asn diff --git a/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v1.asn1config b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v1.asn1config new file mode 100644 index 0000000000..ea10a7d527 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v1.asn1config @@ -0,0 +1,44 @@ +{exclusive_decode, + {'megaco_ber_bin_drv_media_gateway_control_v1', + [ + {decode_message_trans_partial, + [ + 'MegacoMessage',[{mess,[{messageBody,[{transactions,parts}]}]}] + ] + }, + {decode_message_acts_partial, + ['Transaction', + [ + {transactionRequest, + [ + {actions,parts} + ] + }, + {transactionReply, + [ + {transactionResult, [{actionReplies,parts}]} + ] + } + ] + ] + }, + {decode_message_version, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{mId,undecoded},{messageBody,undecoded}]} + ] + ] + }, + {decode_message_mId, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{messageBody,undecoded}]} + ] + ] + } + ] + } +}. + diff --git a/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v1.set.asn b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v1.set.asn new file mode 100644 index 0000000000..0f5a92dba1 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v1.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v1.asn diff --git a/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v2.asn1config b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v2.asn1config new file mode 100644 index 0000000000..3d0cb9a019 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v2.asn1config @@ -0,0 +1,43 @@ +{exclusive_decode, + {'megaco_ber_bin_drv_media_gateway_control_v2', + [ + {decode_message_trans_partial, + [ + 'MegacoMessage',[{mess,[{messageBody,[{transactions,parts}]}]}] + ] + }, + {decode_message_acts_partial, + ['Transaction', + [ + {transactionRequest, + [ + {actions,parts} + ] + }, + {transactionReply, + [ + {transactionResult, [{actionReplies,parts}]} + ] + } + ] + ] + }, + {decode_message_version, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{mId,undecoded},{messageBody,undecoded}]} + ] + ] + }, + {decode_message_mId, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{messageBody,undecoded}]} + ] + ] + } + ] + } +}. diff --git a/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v2.set.asn b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v2.set.asn new file mode 100644 index 0000000000..7fc82b127f --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v2.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v2.asn diff --git a/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v3.asn1config b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v3.asn1config new file mode 100644 index 0000000000..cc662c0145 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v3.asn1config @@ -0,0 +1,43 @@ +{exclusive_decode, + {'megaco_ber_bin_drv_media_gateway_control_v3', + [ + {decode_message_trans_partial, + [ + 'MegacoMessage',[{mess,[{messageBody,[{transactions,parts}]}]}] + ] + }, + {decode_message_acts_partial, + ['Transaction', + [ + {transactionRequest, + [ + {actions,parts} + ] + }, + {transactionReply, + [ + {transactionResult, [{actionReplies,parts}]} + ] + } + ] + ] + }, + {decode_message_version, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{mId,undecoded},{messageBody,undecoded}]} + ] + ] + }, + {decode_message_mId, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{messageBody,undecoded}]} + ] + ] + } + ] + } +}. diff --git a/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v3.set.asn b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v3.set.asn new file mode 100644 index 0000000000..1d7950a283 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v3.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v3.asn diff --git a/lib/megaco/src/binary/megaco_ber_bin_encoder.erl b/lib/megaco/src/binary/megaco_ber_bin_encoder.erl new file mode 100644 index 0000000000..bf9926c7e5 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_encoder.erl @@ -0,0 +1,716 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose : Handle ASN.1 BER encoding of Megaco/H.248 +%%---------------------------------------------------------------------- + +-module(megaco_ber_bin_encoder). + +-behaviour(megaco_encoder). + +-export([encode_message/3, decode_message/3, + decode_mini_message/3, + + encode_transaction/3, + encode_action_requests/3, + encode_action_request/3, + encode_action_reply/3, + + version_of/2]). + +%% Backward compatible functions: +-export([encode_message/2, decode_message/2]). + +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). + +-define(V1_ASN1_MOD, megaco_ber_bin_media_gateway_control_v1). +-define(V2_ASN1_MOD, megaco_ber_bin_media_gateway_control_v2). +-define(V3_ASN1_MOD, megaco_ber_bin_media_gateway_control_v3). +-define(PREV3A_ASN1_MOD, megaco_ber_bin_media_gateway_control_prev3a). +-define(PREV3B_ASN1_MOD, megaco_ber_bin_media_gateway_control_prev3b). +-define(PREV3C_ASN1_MOD, megaco_ber_bin_media_gateway_control_prev3c). +-define(V1_ASN1_MOD_DRV, megaco_ber_bin_drv_media_gateway_control_v1). +-define(V2_ASN1_MOD_DRV, megaco_ber_bin_drv_media_gateway_control_v2). +-define(V3_ASN1_MOD_DRV, megaco_ber_bin_drv_media_gateway_control_v3). +-define(PREV3A_ASN1_MOD_DRV, megaco_ber_bin_drv_media_gateway_control_prev3a). +-define(PREV3B_ASN1_MOD_DRV, megaco_ber_bin_drv_media_gateway_control_prev3b). +-define(PREV3C_ASN1_MOD_DRV, megaco_ber_bin_drv_media_gateway_control_prev3c). + +-define(V1_TRANS_MOD, megaco_binary_transformer_v1). +-define(V2_TRANS_MOD, megaco_binary_transformer_v2). +-define(V3_TRANS_MOD, megaco_binary_transformer_v3). +-define(PREV3A_TRANS_MOD, megaco_binary_transformer_prev3a). +-define(PREV3B_TRANS_MOD, megaco_binary_transformer_prev3b). +-define(PREV3C_TRANS_MOD, megaco_binary_transformer_prev3c). + +-define(BIN_LIB, megaco_binary_encoder_lib). + + +%%---------------------------------------------------------------------- +%% Detect (check/get) message version +%% Return {ok, Version} | {error, Reason} +%%---------------------------------------------------------------------- + +version_of([{version3,v3},driver|EC], Binary) -> + Decoders = [?V1_ASN1_MOD_DRV, ?V2_ASN1_MOD_DRV, ?V3_ASN1_MOD_DRV], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,prev3c},driver|EC], Binary) -> + Decoders = [?V1_ASN1_MOD_DRV, ?V2_ASN1_MOD_DRV, ?PREV3C_ASN1_MOD_DRV], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,prev3b},driver|EC], Binary) -> + Decoders = [?V1_ASN1_MOD_DRV, ?V2_ASN1_MOD_DRV, ?PREV3B_ASN1_MOD_DRV], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,prev3a},driver|EC], Binary) -> + Decoders = [?V1_ASN1_MOD_DRV, ?V2_ASN1_MOD_DRV, ?PREV3A_ASN1_MOD_DRV], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,v3}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?V3_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,prev3c}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3C_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,prev3b}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3B_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,prev3a}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3A_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([driver|EC], Binary) -> + Decoders = [?V1_ASN1_MOD_DRV, ?V2_ASN1_MOD_DRV, ?V3_ASN1_MOD_DRV], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); + +%% All values we need to take (special) care of has been delt with, +%% so just pass the rest on +version_of(EC, Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?V3_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders). + + +%%---------------------------------------------------------------------- +%% Convert a 'MegacoMessage' record into a binary +%% Return {ok, Binary} | {error, Reason} +%%---------------------------------------------------------------------- + + +encode_message(EC, + #'MegacoMessage'{mess = #'Message'{version = V}} = MegaMsg) -> + encode_message(EC, V, MegaMsg). + + +%% -- Version 1 -- + +encode_message([{version3, _},driver|EC], 1, MegaMsg) -> + AsnMod = ?V1_ASN1_MOD_DRV, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([driver|EC], 1, MegaMsg) -> + AsnMod = ?V1_ASN1_MOD_DRV, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,_}|EC], 1, MegaMsg) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); + +%% All values we need to take (special) care of has been delt with, +%% so just pass the rest on +encode_message(EC, 1, MegaMsg) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); + + +%% -- Version 2 -- + +encode_message([{version3,_},driver|EC], 2, MegaMsg) -> + AsnMod = ?V2_ASN1_MOD_DRV, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([driver|EC], 2, MegaMsg) -> + AsnMod = ?V2_ASN1_MOD_DRV, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,_}|EC], 2, MegaMsg) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); + +%% All values we need to take (special) care of has been delt with, +%% so just pass the rest on +encode_message(EC, 2, MegaMsg) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); + + +%% -- Version 3 -- + +encode_message([{version3,v3},driver|EC], 3, MegaMsg) -> + AsnMod = ?V3_ASN1_MOD_DRV, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3c},driver|EC], 3, MegaMsg) -> + AsnMod = ?PREV3C_ASN1_MOD_DRV, + TransMod = ?PREV3C_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3b},driver|EC], 3, MegaMsg) -> + AsnMod = ?PREV3B_ASN1_MOD_DRV, + TransMod = ?PREV3B_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3a},driver|EC], 3, MegaMsg) -> + AsnMod = ?PREV3A_ASN1_MOD_DRV, + TransMod = ?PREV3A_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,v3}|EC], 3, MegaMsg) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3c}|EC], 3, MegaMsg) -> + AsnMod = ?PREV3C_ASN1_MOD, + TransMod = ?PREV3C_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3b}|EC], 3, MegaMsg) -> + AsnMod = ?PREV3B_ASN1_MOD, + TransMod = ?PREV3B_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3a}|EC], 3, MegaMsg) -> + AsnMod = ?PREV3A_ASN1_MOD, + TransMod = ?PREV3A_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([driver|EC], 3, MegaMsg) -> + AsnMod = ?V3_ASN1_MOD_DRV, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); + +%% All values we need to take (special) care of has been delt with, +%% so just pass the rest on +encode_message(EC, 3, MegaMsg) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list). + + +%%---------------------------------------------------------------------- +%% Convert a transaction (or transactions in the case of ack) record(s) +%% into a binary +%% Return {ok, Binary} | {error, Reason} +%%---------------------------------------------------------------------- + +%% encode_transaction([] = EC, 1, Trans) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +%% encode_transaction([native] = EC, 1, Trans) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +%% encode_transaction([driver|EC], 1, Trans) -> +%% AsnMod = ?V1_ASN1_MOD_DRV, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +%% encode_transaction(_EC, 1, _Trans) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +%% encode_transaction([] = EC, 2, Trans) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +%% encode_transaction([native] = EC, 2, Trans) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +%% encode_transaction([driver|EC], 2, Trans) -> +%% AsnMod = ?V2_ASN1_MOD_DRV, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +%%encode_transaction(_EC, 2, _Trans) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list). +%% encode_transaction([] = EC, 3, Trans) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +%% encode_transaction([native] = EC, 3, Trans) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +%% encode_transaction([driver|EC], 3, Trans) -> +%% AsnMod = ?V3_ASN1_MOD_DRV, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +%%encode_transaction(_EC, 3, _Trans) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list). +encode_transaction(_EC, _V, _Trans) -> + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a list of ActionRequest record's into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +%% encode_action_requests([] = EC, 1, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_requests([native] = EC, 1, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_requests([driver|EC], 1, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V1_ASN1_MOD_DRV, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_requests(_EC, 1, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_requests([] = EC, 2, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_requests([native] = EC, 2, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_requests([driver|EC], 2, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V2_ASN1_MOD_DRV, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_requests(_EC, 2, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_requests([] = EC, 3, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_requests([native] = EC, 3, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_requests([driver|EC], 3, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V3_ASN1_MOD_DRV, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); +%%encode_action_requests(_EC, 3, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_requests(_EC, V, _ActReqs) -> +%% {error, {bad_version, V}}. +encode_action_requests(_EC, _V, _ActReqs) -> + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a ActionRequest record into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +%% encode_action_request([] = EC, 1, ActReq) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_request([native] = EC, 1, ActReq) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_request([driver|EC], 1, ActReq) -> +%% AsnMod = ?V1_ASN1_MOD_DRV, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_request(_EC, 1, ActReq) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_request([] = EC, 2, ActReq) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_request([native] = EC, 2, ActReq) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_request([driver|EC], 2, ActReq) -> +%% AsnMod = ?V2_ASN1_MOD_DRV, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_request(_EC, 2, ActReq) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_request([] = EC, 3, ActReq) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_request([native] = EC, 3, ActReq) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_request([driver|EC], 3, ActReq) -> +%% AsnMod = ?V3_ASN1_MOD_DRV, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); +%% encode_action_request(_EC, 3, ActReq) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); +encode_action_request(_EC, _V, _ActReq) -> + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a action reply into a deep io list +%% Not yest supported by this binary codec! +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_action_reply(_EC, _V, _AcionReply) -> + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a binary into a 'MegacoMessage' record +%% Return {ok, MegacoMessageRecord} | {error, Reason} +%%---------------------------------------------------------------------- + +%% Old decode function +decode_message(EC, Binary) -> + decode_message(EC, 1, Binary). + +%% -- Dynamic version detection -- + +%% Select from message +decode_message([{version3,v3},driver|EC], dynamic, Binary) -> + Mods = [{?V1_ASN1_MOD_DRV, ?V1_TRANS_MOD}, + {?V2_ASN1_MOD_DRV, ?V2_TRANS_MOD}, + {?V3_ASN1_MOD_DRV, ?V3_TRANS_MOD}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Mods, binary); +decode_message([{version3,prev3c},driver|EC], dynamic, Binary) -> + Mods = [{?V1_ASN1_MOD_DRV, ?V1_TRANS_MOD}, + {?V2_ASN1_MOD_DRV, ?V2_TRANS_MOD}, + {?PREV3C_ASN1_MOD_DRV, ?PREV3C_TRANS_MOD}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Mods, binary); +decode_message([{version3,prev3b},driver|EC], dynamic, Binary) -> + Mods = [{?V1_ASN1_MOD_DRV, ?V1_TRANS_MOD}, + {?V2_ASN1_MOD_DRV, ?V2_TRANS_MOD}, + {?PREV3B_ASN1_MOD_DRV, ?PREV3B_TRANS_MOD}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Mods, binary); +decode_message([{version3,prev3a},driver|EC], dynamic, Binary) -> + Mods = [{?V1_ASN1_MOD_DRV, ?V1_TRANS_MOD}, + {?V2_ASN1_MOD_DRV, ?V2_TRANS_MOD}, + {?PREV3A_ASN1_MOD_DRV, ?PREV3A_TRANS_MOD}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Mods, binary); +decode_message([{version3,v3}|EC], dynamic, Binary) -> + Mods = [{?V1_ASN1_MOD, ?V1_TRANS_MOD}, + {?V2_ASN1_MOD, ?V2_TRANS_MOD}, + {?V3_ASN1_MOD, ?V3_TRANS_MOD}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Mods, binary); +decode_message([{version3,prev3c}|EC], dynamic, Binary) -> + Mods = [{?V1_ASN1_MOD, ?V1_TRANS_MOD}, + {?V2_ASN1_MOD, ?V2_TRANS_MOD}, + {?PREV3C_ASN1_MOD, ?PREV3C_TRANS_MOD}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Mods, binary); +decode_message([{version3,prev3b}|EC], dynamic, Binary) -> + Mods = [{?V1_ASN1_MOD, ?V1_TRANS_MOD}, + {?V2_ASN1_MOD, ?V2_TRANS_MOD}, + {?PREV3B_ASN1_MOD, ?PREV3B_TRANS_MOD}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Mods, binary); +decode_message([{version3,prev3a}|EC], dynamic, Binary) -> + Mods = [{?V1_ASN1_MOD, ?V1_TRANS_MOD}, + {?V2_ASN1_MOD, ?V2_TRANS_MOD}, + {?PREV3A_ASN1_MOD, ?PREV3A_TRANS_MOD}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Mods, binary); +decode_message([driver|EC], dynamic, Binary) -> + Mods = [{?V1_ASN1_MOD_DRV, ?V1_TRANS_MOD}, + {?V2_ASN1_MOD_DRV, ?V2_TRANS_MOD}, + {?V3_ASN1_MOD_DRV, ?V3_TRANS_MOD}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Mods, binary); + +%% All values we need to take (special) care of has been delt with, +%% so just pass the rest on +decode_message(EC, dynamic, Binary) -> + Mods = [{?V1_ASN1_MOD, ?V1_TRANS_MOD}, + {?V2_ASN1_MOD, ?V2_TRANS_MOD}, + {?V3_ASN1_MOD, ?V3_TRANS_MOD}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Mods, binary); + + +%% -- Version 1 -- + +decode_message([{version3,_},driver|EC], 1, Binary) -> + AsnMod = ?V1_ASN1_MOD_DRV, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([driver|EC], 1, Binary) -> + AsnMod = ?V1_ASN1_MOD_DRV, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,_}|EC], 1, Binary) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +%% All values we need to take (special) care of has been delt with, +%% so just pass the rest on +decode_message(EC, 1, Binary) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + + +%% -- Version 2 -- + +decode_message([{version3,_},driver|EC], 2, Binary) -> + AsnMod = ?V2_ASN1_MOD_DRV, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([driver|EC], 2, Binary) -> + AsnMod = ?V2_ASN1_MOD_DRV, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,_}|EC], 2, Binary) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +%% All values we need to take (special) care of has been delt with, +%% so just pass the rest on +decode_message(EC, 2, Binary) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + + +%% -- Version 3 -- + +decode_message([{version3,v3},driver|EC], 3, Binary) -> + AsnMod = ?V3_ASN1_MOD_DRV, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3c},driver|EC], 3, Binary) -> + AsnMod = ?PREV3C_ASN1_MOD_DRV, + TransMod = ?PREV3C_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3b},driver|EC], 3, Binary) -> + AsnMod = ?PREV3B_ASN1_MOD_DRV, + TransMod = ?PREV3B_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3a},driver|EC], 3, Binary) -> + AsnMod = ?PREV3A_ASN1_MOD_DRV, + TransMod = ?PREV3A_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,v3}|EC], 3, Binary) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3c}|EC], 3, Binary) -> + AsnMod = ?PREV3C_ASN1_MOD, + TransMod = ?PREV3C_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3b}|EC], 3, Binary) -> + AsnMod = ?PREV3B_ASN1_MOD, + TransMod = ?PREV3B_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3a}|EC], 3, Binary) -> + AsnMod = ?PREV3A_ASN1_MOD, + TransMod = ?PREV3A_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([driver|EC], 3, Binary) -> + AsnMod = ?V3_ASN1_MOD_DRV, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +%% All values we need to take (special) care of has been delt with, +%% so just pass the rest on +decode_message(EC, 3, Binary) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary). + + +decode_mini_message([{version3,v3},driver|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD_DRV, + ?V2_ASN1_MOD_DRV, + ?V3_ASN1_MOD_DRV], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3c},driver|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD_DRV, + ?V2_ASN1_MOD_DRV, + ?PREV3C_ASN1_MOD_DRV], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3b},driver|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD_DRV, + ?V2_ASN1_MOD_DRV, + ?PREV3B_ASN1_MOD_DRV], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3a},driver|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD_DRV, + ?V2_ASN1_MOD_DRV, + ?PREV3A_ASN1_MOD_DRV], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,v3}|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD, + ?V2_ASN1_MOD, + ?V3_ASN1_MOD], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3c}|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD, + ?V2_ASN1_MOD, + ?PREV3C_ASN1_MOD], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3b}|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD, + ?V2_ASN1_MOD, + ?PREV3B_ASN1_MOD], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3a}|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD, + ?V2_ASN1_MOD, + ?PREV3A_ASN1_MOD], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([driver|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD_DRV, + ?V2_ASN1_MOD_DRV, + ?V3_ASN1_MOD_DRV], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message(EC, dynamic, Bin) -> + Mods = [?V1_ASN1_MOD, + ?V2_ASN1_MOD, + ?V3_ASN1_MOD], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,_},driver|EC], 1, Bin) -> + AsnMod = ?V1_ASN1_MOD_DRV, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,_}|EC], 1, Bin) -> + AsnMod = ?V1_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([driver|EC], 1, Bin) -> + AsnMod = ?V1_ASN1_MOD_DRV, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message(EC, 1, Bin) -> + AsnMod = ?V1_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,_},driver|EC], 2, Bin) -> + AsnMod = ?V2_ASN1_MOD_DRV, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,_}|EC], 2, Bin) -> + AsnMod = ?V2_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([driver|EC], 2, Bin) -> + AsnMod = ?V2_ASN1_MOD_DRV, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message(EC, 2, Bin) -> + AsnMod = ?V2_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,v3},driver|EC], 3, Bin) -> + AsnMod = ?V3_ASN1_MOD_DRV, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3c},driver|EC], 3, Bin) -> + AsnMod = ?PREV3C_ASN1_MOD_DRV, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3b},driver|EC], 3, Bin) -> + AsnMod = ?PREV3B_ASN1_MOD_DRV, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3a},driver|EC], 3, Bin) -> + AsnMod = ?PREV3A_ASN1_MOD_DRV, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,v3}|EC], 3, Bin) -> + AsnMod = ?V3_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3c}|EC], 3, Bin) -> + AsnMod = ?PREV3C_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3b}|EC], 3, Bin) -> + AsnMod = ?PREV3B_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3a}|EC], 3, Bin) -> + AsnMod = ?PREV3A_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([driver|EC], 3, Bin) -> + AsnMod = ?V3_ASN1_MOD_DRV, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message(EC, 3, Bin) -> + AsnMod = ?V3_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary). diff --git a/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3a.asn1config b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3a.asn1config new file mode 100644 index 0000000000..456ce750ad --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3a.asn1config @@ -0,0 +1,43 @@ +{exclusive_decode, + {'megaco_ber_bin_media_gateway_control_prev3a', + [ + {decode_message_trans_partial, + [ + 'MegacoMessage',[{mess,[{messageBody,[{transactions,parts}]}]}] + ] + }, + {decode_message_acts_partial, + ['Transaction', + [ + {transactionRequest, + [ + {actions,parts} + ] + }, + {transactionReply, + [ + {transactionResult, [{actionReplies,parts}]} + ] + } + ] + ] + }, + {decode_message_version, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{mId,undecoded},{messageBody,undecoded}]} + ] + ] + }, + {decode_message_mId, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{messageBody,undecoded}]} + ] + ] + } + ] + } +}. diff --git a/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3a.set.asn b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3a.set.asn new file mode 100644 index 0000000000..b9ba7ffdb4 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3a.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3a.asn diff --git a/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3b.asn1config b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3b.asn1config new file mode 100644 index 0000000000..fa5cd80baf --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3b.asn1config @@ -0,0 +1,43 @@ +{exclusive_decode, + {'megaco_ber_bin_media_gateway_control_prev3b', + [ + {decode_message_trans_partial, + [ + 'MegacoMessage',[{mess,[{messageBody,[{transactions,parts}]}]}] + ] + }, + {decode_message_acts_partial, + ['Transaction', + [ + {transactionRequest, + [ + {actions,parts} + ] + }, + {transactionReply, + [ + {transactionResult, [{actionReplies,parts}]} + ] + } + ] + ] + }, + {decode_message_version, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{mId,undecoded},{messageBody,undecoded}]} + ] + ] + }, + {decode_message_mId, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{messageBody,undecoded}]} + ] + ] + } + ] + } +}. diff --git a/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3b.set.asn b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3b.set.asn new file mode 100644 index 0000000000..0437bde310 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3b.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3b.asn diff --git a/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3c.asn1config b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3c.asn1config new file mode 100644 index 0000000000..c74422b9a2 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3c.asn1config @@ -0,0 +1,43 @@ +{exclusive_decode, + {'megaco_ber_bin_media_gateway_control_prev3c', + [ + {decode_message_trans_partial, + [ + 'MegacoMessage',[{mess,[{messageBody,[{transactions,parts}]}]}] + ] + }, + {decode_message_acts_partial, + ['Transaction', + [ + {transactionRequest, + [ + {actions,parts} + ] + }, + {transactionReply, + [ + {transactionResult, [{actionReplies,parts}]} + ] + } + ] + ] + }, + {decode_message_version, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{mId,undecoded},{messageBody,undecoded}]} + ] + ] + }, + {decode_message_mId, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{messageBody,undecoded}]} + ] + ] + } + ] + } +}. diff --git a/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3c.set.asn b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3c.set.asn new file mode 100644 index 0000000000..e78055fbad --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3c.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3c.asn diff --git a/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v1.asn1config b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v1.asn1config new file mode 100644 index 0000000000..e815e90948 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v1.asn1config @@ -0,0 +1,44 @@ +{exclusive_decode, + {'megaco_ber_bin_media_gateway_control_v1', + [ + {decode_message_trans_partial, + [ + 'MegacoMessage',[{mess,[{messageBody,[{transactions,parts}]}]}] + ] + }, + {decode_message_acts_partial, + ['Transaction', + [ + {transactionRequest, + [ + {actions,parts} + ] + }, + {transactionReply, + [ + {transactionResult, [{actionReplies,parts}]} + ] + } + ] + ] + }, + {decode_message_version, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{mId,undecoded},{messageBody,undecoded}]} + ] + ] + }, + {decode_message_mId, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{messageBody,undecoded}]} + ] + ] + } + + ] + } +}. diff --git a/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v1.set.asn b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v1.set.asn new file mode 100644 index 0000000000..0f5a92dba1 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v1.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v1.asn diff --git a/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v2.asn1config b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v2.asn1config new file mode 100644 index 0000000000..cc072b30ee --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v2.asn1config @@ -0,0 +1,43 @@ +{exclusive_decode, + {'megaco_ber_bin_media_gateway_control_v2', + [ + {decode_message_trans_partial, + [ + 'MegacoMessage',[{mess,[{messageBody,[{transactions,parts}]}]}] + ] + }, + {decode_message_acts_partial, + ['Transaction', + [ + {transactionRequest, + [ + {actions,parts} + ] + }, + {transactionReply, + [ + {transactionResult, [{actionReplies,parts}]} + ] + } + ] + ] + }, + {decode_message_version, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{mId,undecoded},{messageBody,undecoded}]} + ] + ] + }, + {decode_message_mId, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{messageBody,undecoded}]} + ] + ] + } + ] + } +}. diff --git a/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v2.set.asn b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v2.set.asn new file mode 100644 index 0000000000..7fc82b127f --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v2.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v2.asn diff --git a/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v3.asn1config b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v3.asn1config new file mode 100644 index 0000000000..deeb2b2da9 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v3.asn1config @@ -0,0 +1,43 @@ +{exclusive_decode, + {'megaco_ber_bin_media_gateway_control_v3', + [ + {decode_message_trans_partial, + [ + 'MegacoMessage',[{mess,[{messageBody,[{transactions,parts}]}]}] + ] + }, + {decode_message_acts_partial, + ['Transaction', + [ + {transactionRequest, + [ + {actions,parts} + ] + }, + {transactionReply, + [ + {transactionResult, [{actionReplies,parts}]} + ] + } + ] + ] + }, + {decode_message_version, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{mId,undecoded},{messageBody,undecoded}]} + ] + ] + }, + {decode_message_mId, + ['MegacoMessage', + [ + {authHeader,undecoded}, + {mess,[{messageBody,undecoded}]} + ] + ] + } + ] + } +}. diff --git a/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v3.set.asn b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v3.set.asn new file mode 100644 index 0000000000..1d7950a283 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_bin_media_gateway_control_v3.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v3.asn diff --git a/lib/megaco/src/binary/megaco_ber_encoder.erl b/lib/megaco/src/binary/megaco_ber_encoder.erl new file mode 100644 index 0000000000..ff65b5bf81 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_encoder.erl @@ -0,0 +1,346 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose : Handle ASN.1 BER encoding of Megaco/H.248 +%%---------------------------------------------------------------------- + +-module(megaco_ber_encoder). + +-behaviour(megaco_encoder). + +-export([encode_message/3, decode_message/3, + decode_mini_message/3, + + encode_transaction/3, + encode_action_requests/3, + encode_action_request/3, + encode_action_reply/3, + + version_of/2]). + +%% Backward compatible functions: +-export([encode_message/2, decode_message/2]). + +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). + +-define(V1_ASN1_MOD, megaco_ber_media_gateway_control_v1). +-define(V2_ASN1_MOD, megaco_ber_media_gateway_control_v2). +-define(V3_ASN1_MOD, megaco_ber_media_gateway_control_v3). +-define(PREV3A_ASN1_MOD, megaco_ber_media_gateway_control_prev3a). +-define(PREV3B_ASN1_MOD, megaco_ber_media_gateway_control_prev3b). +-define(PREV3C_ASN1_MOD, megaco_ber_media_gateway_control_prev3c). + +-define(V1_TRANS_MOD, megaco_binary_transformer_v1). +-define(V2_TRANS_MOD, megaco_binary_transformer_v2). +-define(V3_TRANS_MOD, megaco_binary_transformer_v3). +-define(PREV3A_TRANS_MOD, megaco_binary_transformer_prev3a). +-define(PREV3B_TRANS_MOD, megaco_binary_transformer_prev3b). +-define(PREV3C_TRANS_MOD, megaco_binary_transformer_prev3c). + +-define(BIN_LIB, megaco_binary_encoder_lib). + + +%%---------------------------------------------------------------------- +%% Detect (check/get) message version +%% Return {ok, Version} | {error, Reason} +%%---------------------------------------------------------------------- + +version_of([{version3,v3}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?V3_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([{version3,prev3c}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3C_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([{version3,prev3b}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3B_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([{version3,prev3a}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3A_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of(EC, Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?V3_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders). + + +%%---------------------------------------------------------------------- +%% Convert a 'MegacoMessage' record into a binary +%% Return {ok, Binary} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_message(EC, + #'MegacoMessage'{mess = #'Message'{version = V}} = MegaMsg) -> + encode_message(EC, V, MegaMsg). + + +%% -- Version 1 -- + +encode_message([{version3,_}|EC], 1, MegaMsg) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message(EC, 1, MegaMsg) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); + + +%% -- Version 2 -- + +encode_message([{version3,_}|EC], 2, MegaMsg) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message(EC, 2, MegaMsg) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); + + +%% -- Version 3 -- + +encode_message([{version3,v3}|EC], 3, MegaMsg) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3c}|EC], 3, MegaMsg) -> + AsnMod = ?PREV3C_ASN1_MOD, + TransMod = ?PREV3C_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3b}|EC], 3, MegaMsg) -> + AsnMod = ?PREV3B_ASN1_MOD, + TransMod = ?PREV3B_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3a}|EC], 3, MegaMsg) -> + AsnMod = ?PREV3A_ASN1_MOD, + TransMod = ?PREV3A_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message(EC, 3, MegaMsg) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list). + + +%%---------------------------------------------------------------------- +%% Convert a transaction (or transactions in the case of ack) record(s) +%% into a binary +%% Return {ok, Binary} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_transaction(_EC, 1, _Trans) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); + {error, not_implemented}; +encode_transaction(_EC, 2, _Trans) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); + {error, not_implemented}; +encode_transaction(_EC, 3, _Trans) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a list of ActionRequest record's into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +encode_action_requests(_EC, 1, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); + {error, not_implemented}; +encode_action_requests(_EC, 2, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); + {error, not_implemented}; +encode_action_requests(_EC, 3, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a ActionRequest record into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +encode_action_request(_EC, 1, _ActReq) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); + {error, not_implemented}; +encode_action_request(_EC, 2, _ActReq) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); + {error, not_implemented}; +encode_action_request(_EC, 3, _ActReq) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a action reply into a deep io list +%% Not yest supported by this binary codec! +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_action_reply(_EC, _V, _AcionReply) -> + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a binary into a 'MegacoMessage' record +%% Return {ok, MegacoMessageRecord} | {error, Reason} +%%---------------------------------------------------------------------- + +decode_message(EC, Binary) -> + decode_message(EC, 1, Binary). + +%% Not supported for this codec, revert to version 1 +decode_message(EC, dynamic, Binary) -> + decode_message(EC, 1, Binary); + + +%% -- Version 1 -- + +decode_message([{version3,_}|EC], 1, Binary) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message(EC, 1, Binary) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + + +%% -- Version 2 -- + +decode_message([{version3,_}|EC], 2, Binary) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message(EC, 2, Binary) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + + +%% -- Version 3 -- + +decode_message([{version3,v3}|EC], 3, Binary) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3c}|EC], 3, Binary) -> + AsnMod = ?PREV3C_ASN1_MOD, + TransMod = ?PREV3C_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3b}|EC], 3, Binary) -> + AsnMod = ?PREV3B_ASN1_MOD, + TransMod = ?PREV3B_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3a}|EC], 3, Binary) -> + AsnMod = ?PREV3A_ASN1_MOD, + TransMod = ?PREV3A_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message(EC, 3, Binary) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary). + + +decode_mini_message([{version3,v3}|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD, + ?V2_ASN1_MOD, + ?V3_ASN1_MOD], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3c}|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD, + ?V2_ASN1_MOD, + ?PREV3C_ASN1_MOD], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3b}|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD, + ?V2_ASN1_MOD, + ?PREV3B_ASN1_MOD], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3a}|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD, + ?V2_ASN1_MOD, + ?PREV3A_ASN1_MOD], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message(EC, dynamic, Bin) -> + Mods = [?V1_ASN1_MOD, + ?V2_ASN1_MOD, + ?V3_ASN1_MOD], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); + +decode_mini_message([{version3,_}|EC], 1, Bin) -> + AsnMod = ?V1_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message(EC, 1, Bin) -> + AsnMod = ?V1_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,_}|EC], 2, Bin) -> + AsnMod = ?V2_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message(EC, 2, Bin) -> + AsnMod = ?V2_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,v3}|EC], 3, Bin) -> + AsnMod = ?V3_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3c}|EC], 3, Bin) -> + AsnMod = ?PREV3C_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3b}|EC], 3, Bin) -> + AsnMod = ?PREV3B_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3a}|EC], 3, Bin) -> + AsnMod = ?PREV3A_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message(EC, 3, Bin) -> + AsnMod = ?V3_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary). + + diff --git a/lib/megaco/src/binary/megaco_ber_media_gateway_control_prev3a.set.asn b/lib/megaco/src/binary/megaco_ber_media_gateway_control_prev3a.set.asn new file mode 100644 index 0000000000..b9ba7ffdb4 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_media_gateway_control_prev3a.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3a.asn diff --git a/lib/megaco/src/binary/megaco_ber_media_gateway_control_prev3b.set.asn b/lib/megaco/src/binary/megaco_ber_media_gateway_control_prev3b.set.asn new file mode 100644 index 0000000000..0437bde310 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_media_gateway_control_prev3b.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3b.asn diff --git a/lib/megaco/src/binary/megaco_ber_media_gateway_control_prev3c.set.asn b/lib/megaco/src/binary/megaco_ber_media_gateway_control_prev3c.set.asn new file mode 100644 index 0000000000..e78055fbad --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_media_gateway_control_prev3c.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3c.asn diff --git a/lib/megaco/src/binary/megaco_ber_media_gateway_control_v1.set.asn b/lib/megaco/src/binary/megaco_ber_media_gateway_control_v1.set.asn new file mode 100644 index 0000000000..0f5a92dba1 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_media_gateway_control_v1.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v1.asn diff --git a/lib/megaco/src/binary/megaco_ber_media_gateway_control_v2.set.asn b/lib/megaco/src/binary/megaco_ber_media_gateway_control_v2.set.asn new file mode 100644 index 0000000000..7fc82b127f --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_media_gateway_control_v2.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v2.asn diff --git a/lib/megaco/src/binary/megaco_ber_media_gateway_control_v3.set.asn b/lib/megaco/src/binary/megaco_ber_media_gateway_control_v3.set.asn new file mode 100644 index 0000000000..1d7950a283 --- /dev/null +++ b/lib/megaco/src/binary/megaco_ber_media_gateway_control_v3.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v3.asn diff --git a/lib/megaco/src/binary/megaco_binary_encoder.erl b/lib/megaco/src/binary/megaco_binary_encoder.erl new file mode 100644 index 0000000000..f825f91a45 --- /dev/null +++ b/lib/megaco/src/binary/megaco_binary_encoder.erl @@ -0,0 +1,588 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose : Handle ASN.1 BER encoding of Megaco/H.248 +%%---------------------------------------------------------------------- + +-module(megaco_binary_encoder). + +-behaviour(megaco_encoder). + +%% API +-export([encode_message/3, decode_message/3, + decode_mini_message/3, + + encode_transaction/3, + encode_action_requests/3, + encode_action_request/3, + encode_action_reply/3, + + version_of/2]). + +%% Backward compatible functions: +-export([encode_message/2, decode_message/2]). + +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). + +-define(BIN_LIB, megaco_binary_encoder_lib). + + +%%---------------------------------------------------------------------- +%% Convert a 'MegacoMessage' record into a binary +%% Return {ok, Binary} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_message(EC, + #'MegacoMessage'{mess = #'Message'{version = V}} = MegaMsg) -> + encode_message(EC, V, MegaMsg). + +encode_message([{version3,_}|EC], 1, MegaMsg) -> + AsnMod = megaco_ber_media_gateway_control_v1, + TransMod = megaco_binary_transformer_v1, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message(EC, 1, MegaMsg) -> + AsnMod = megaco_ber_media_gateway_control_v1, + TransMod = megaco_binary_transformer_v1, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,_}|EC], 2, MegaMsg) -> + AsnMod = megaco_ber_media_gateway_control_v2, + TransMod = megaco_binary_transformer_v2, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message(EC, 2, MegaMsg) -> + AsnMod = megaco_ber_media_gateway_control_v2, + TransMod = megaco_binary_transformer_v2, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,v3}|EC], 3, MegaMsg) -> + AsnMod = megaco_ber_media_gateway_control_v3, + TransMod = megaco_binary_transformer_v3, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3c}|EC], 3, MegaMsg) -> + AsnMod = megaco_ber_media_gateway_control_prev3c, + TransMod = megaco_binary_transformer_prev3c, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3b}|EC], 3, MegaMsg) -> + AsnMod = megaco_ber_media_gateway_control_prev3b, + TransMod = megaco_binary_transformer_prev3b, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3a}|EC], 3, MegaMsg) -> + AsnMod = megaco_ber_media_gateway_control_prev3a, + TransMod = megaco_binary_transformer_prev3a, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message(EC, 3, MegaMsg) -> + AsnMod = megaco_ber_media_gateway_control_v3, + TransMod = megaco_binary_transformer_v3, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list). + + +%%---------------------------------------------------------------------- +%% Convert a transaction (or transactions in the case of ack) record(s) +%% into a binary +%% Return {ok, Binary} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_transaction([{version3,_}|EC], 1, Trans) -> + AsnMod = megaco_ber_media_gateway_control_v1, + TransMod = megaco_binary_transformer_v1, + ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, io_list); +encode_transaction(EC, 1, Trans) -> + AsnMod = megaco_ber_media_gateway_control_v1, + TransMod = megaco_binary_transformer_v1, + ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, io_list); +encode_transaction([{version3,_}|EC], 2, Trans) -> + AsnMod = megaco_ber_media_gateway_control_v2, + TransMod = megaco_binary_transformer_v2, + ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, io_list); +encode_transaction(EC, 2, Trans) -> + AsnMod = megaco_ber_media_gateway_control_v2, + TransMod = megaco_binary_transformer_v2, + ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, io_list); +encode_transaction([{version3,v3}|EC], 3, Trans) -> + AsnMod = megaco_ber_media_gateway_control_v3, + TransMod = megaco_binary_transformer_v3, + ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, io_list); +encode_transaction([{version3,prev3c}|EC], 3, Trans) -> + AsnMod = megaco_ber_media_gateway_control_prev3c, + TransMod = megaco_binary_transformer_prev3c, + ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, io_list); +encode_transaction([{version3,prev3b}|EC], 3, Trans) -> + AsnMod = megaco_ber_media_gateway_control_prev3b, + TransMod = megaco_binary_transformer_prev3b, + ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, io_list); +encode_transaction([{version3,prev3a}|EC], 3, Trans) -> + AsnMod = megaco_ber_media_gateway_control_prev3a, + TransMod = megaco_binary_transformer_prev3a, + ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, io_list); +encode_transaction(EC, 3, Trans) -> + AsnMod = megaco_ber_media_gateway_control_v3, + TransMod = megaco_binary_transformer_v3, + ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, io_list). + + +%%---------------------------------------------------------------------- +%% Convert a list of ActionRequest record's into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +encode_action_requests([{version3,_}|EC], 1, ActReqs) + when is_list(ActReqs) -> + AsnMod = megaco_ber_media_gateway_control_v1, + TransMod = megaco_binary_transformer_v1, + ?BIN_LIB:encode_action_requests(EC, ActReqs, AsnMod, TransMod, io_list); +encode_action_requests(EC, 1, ActReqs) when is_list(ActReqs) -> + AsnMod = megaco_ber_media_gateway_control_v1, + TransMod = megaco_binary_transformer_v1, + ?BIN_LIB:encode_action_requests(EC, ActReqs, AsnMod, TransMod, io_list); +encode_action_requests([{version3,_}|EC], 2, ActReqs) + when is_list(ActReqs) -> + AsnMod = megaco_ber_media_gateway_control_v2, + TransMod = megaco_binary_transformer_v2, + ?BIN_LIB:encode_action_requests(EC, ActReqs, AsnMod, TransMod, io_list); +encode_action_requests(EC, 2, ActReqs) when is_list(ActReqs) -> + AsnMod = megaco_ber_media_gateway_control_v2, + TransMod = megaco_binary_transformer_v2, + ?BIN_LIB:encode_action_requests(EC, ActReqs, AsnMod, TransMod, io_list); +encode_action_requests([{version3,v3}|EC], 3, ActReqs) + when is_list(ActReqs) -> + AsnMod = megaco_ber_media_gateway_control_v3, + TransMod = megaco_binary_transformer_v3, + ?BIN_LIB:encode_action_requests(EC, ActReqs, AsnMod, TransMod, io_list); +encode_action_requests([{version3,prev3c}|EC], 3, ActReqs) + when is_list(ActReqs) -> + AsnMod = megaco_ber_media_gateway_control_prev3c, + TransMod = megaco_binary_transformer_prev3c, + ?BIN_LIB:encode_action_requests(EC, ActReqs, AsnMod, TransMod, io_list); +encode_action_requests([{version3,prev3b}|EC], 3, ActReqs) + when is_list(ActReqs) -> + AsnMod = megaco_ber_media_gateway_control_prev3b, + TransMod = megaco_binary_transformer_prev3b, + ?BIN_LIB:encode_action_requests(EC, ActReqs, AsnMod, TransMod, io_list); +encode_action_requests([{version3,prev3a}|EC], 3, ActReqs) + when is_list(ActReqs) -> + AsnMod = megaco_ber_media_gateway_control_prev3a, + TransMod = megaco_binary_transformer_prev3a, + ?BIN_LIB:encode_action_requests(EC, ActReqs, AsnMod, TransMod, io_list); +encode_action_requests(EC, 3, ActReqs) when is_list(ActReqs) -> + AsnMod = megaco_ber_media_gateway_control_v3, + TransMod = megaco_binary_transformer_v3, + ?BIN_LIB:encode_action_requests(EC, ActReqs, AsnMod, TransMod, io_list). + + +%%---------------------------------------------------------------------- +%% Convert a ActionRequest record into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +encode_action_request([{version3,_}|EC], 1, ActReq) -> + AsnMod = megaco_ber_media_gateway_control_v1, + TransMod = megaco_binary_transformer_v1, + ?BIN_LIB:encode_action_request(EC, ActReq, AsnMod, TransMod, io_list); +encode_action_request(EC, 1, ActReq) -> + AsnMod = megaco_ber_media_gateway_control_v1, + TransMod = megaco_binary_transformer_v1, + ?BIN_LIB:encode_action_request(EC, ActReq, AsnMod, TransMod, io_list); +encode_action_request([{version3,_}|EC], 2, ActReq) -> + AsnMod = megaco_ber_media_gateway_control_v2, + TransMod = megaco_binary_transformer_v2, + ?BIN_LIB:encode_action_request(EC, ActReq, AsnMod, TransMod, io_list); +encode_action_request(EC, 2, ActReq) -> + AsnMod = megaco_ber_media_gateway_control_v2, + TransMod = megaco_binary_transformer_v2, + ?BIN_LIB:encode_action_request(EC, ActReq, AsnMod, TransMod, io_list); +encode_action_request([{version3,v3}|EC], 3, ActReq) -> + AsnMod = megaco_ber_media_gateway_control_v3, + TransMod = megaco_binary_transformer_v3, + ?BIN_LIB:encode_action_request(EC, ActReq, AsnMod, TransMod, io_list); +encode_action_request([{version3,prev3c}|EC], 3, ActReq) -> + AsnMod = megaco_ber_media_gateway_control_prev3c, + TransMod = megaco_binary_transformer_prev3c, + ?BIN_LIB:encode_action_request(EC, ActReq, AsnMod, TransMod, io_list); +encode_action_request([{version3,prev3b}|EC], 3, ActReq) -> + AsnMod = megaco_ber_media_gateway_control_prev3b, + TransMod = megaco_binary_transformer_prev3b, + ?BIN_LIB:encode_action_request(EC, ActReq, AsnMod, TransMod, io_list); +encode_action_request([{version3,prev3a}|EC], 3, ActReq) -> + AsnMod = megaco_ber_media_gateway_control_prev3a, + TransMod = megaco_binary_transformer_prev3a, + ?BIN_LIB:encode_action_request(EC, ActReq, AsnMod, TransMod, io_list); +encode_action_request(EC, 3, ActReq) -> + AsnMod = megaco_ber_media_gateway_control_v3, + TransMod = megaco_binary_transformer_v3, + ?BIN_LIB:encode_action_request(EC, ActReq, AsnMod, TransMod, io_list). + + +%%---------------------------------------------------------------------- +%% Convert a action reply into a deep io list +%% Not yest supported by this binary codec! +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_action_reply(_EC, _V, _AcionReply) -> + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Detect (check) which version a message is +%% Return {ok, Version} | {error, Reason} +%%---------------------------------------------------------------------- + +version_of([{version3,v3},driver|EC], Binary) -> + Decoders = [megaco_ber_bin_drv_media_gateway_control_v1, + megaco_ber_bin_drv_media_gateway_control_v2, + megaco_ber_bin_drv_media_gateway_control_v3], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,prev3c},driver|EC], Binary) -> + Decoders = [megaco_ber_bin_drv_media_gateway_control_v1, + megaco_ber_bin_drv_media_gateway_control_v2, + megaco_ber_bin_drv_media_gateway_control_prev3c], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,prev3b},driver|EC], Binary) -> + Decoders = [megaco_ber_bin_drv_media_gateway_control_v1, + megaco_ber_bin_drv_media_gateway_control_v2, + megaco_ber_bin_drv_media_gateway_control_prev3b], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,prev3a},driver|EC], Binary) -> + Decoders = [megaco_ber_bin_drv_media_gateway_control_v1, + megaco_ber_bin_drv_media_gateway_control_v2, + megaco_ber_bin_drv_media_gateway_control_prev3a], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([driver|EC], Binary) -> + Decoders = [megaco_ber_bin_drv_media_gateway_control_v1, + megaco_ber_bin_drv_media_gateway_control_v2, + megaco_ber_bin_drv_media_gateway_control_v3], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,v3}|EC], Binary) -> + Decoders = [megaco_ber_bin_media_gateway_control_v1, + megaco_ber_bin_media_gateway_control_v2, + megaco_ber_bin_media_gateway_control_v3], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,prev3c}|EC], Binary) -> + Decoders = [megaco_ber_bin_media_gateway_control_v1, + megaco_ber_bin_media_gateway_control_v2, + megaco_ber_bin_media_gateway_control_prev3c], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,prev3b}|EC], Binary) -> + Decoders = [megaco_ber_bin_media_gateway_control_v1, + megaco_ber_bin_media_gateway_control_v2, + megaco_ber_bin_media_gateway_control_prev3b], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,prev3a}|EC], Binary) -> + Decoders = [megaco_ber_bin_media_gateway_control_v1, + megaco_ber_bin_media_gateway_control_v2, + megaco_ber_bin_media_gateway_control_prev3a], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of(EC, Binary) -> + Decoders = [megaco_ber_bin_media_gateway_control_v1, + megaco_ber_bin_media_gateway_control_v2, + megaco_ber_bin_media_gateway_control_v3], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders). + + +%%---------------------------------------------------------------------- +%% Convert a binary into a 'MegacoMessage' record +%% Return {ok, MegacoMessageRecord} | {error, Reason} +%%---------------------------------------------------------------------- + +decode_message(EC, Binary) -> + decode_message(EC, 1, Binary). + +decode_message([{version3,v3},driver|EC], dynamic, Binary) -> + Decoders = [{megaco_ber_bin_drv_media_gateway_control_v1, + megaco_binary_transformer_v1}, + {megaco_ber_bin_drv_media_gateway_control_v2, + megaco_binary_transformer_v2}, + {megaco_ber_bin_drv_media_gateway_control_v3, + megaco_binary_transformer_v3}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Decoders, binary); +decode_message([{version3,prev3c},driver|EC], dynamic, Binary) -> + Decoders = [{megaco_ber_bin_drv_media_gateway_control_v1, + megaco_binary_transformer_v1}, + {megaco_ber_bin_drv_media_gateway_control_v2, + megaco_binary_transformer_v2}, + {megaco_ber_bin_drv_media_gateway_control_prev3c, + megaco_binary_transformer_prev3c}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Decoders, binary); +decode_message([{version3,prev3b},driver|EC], dynamic, Binary) -> + Decoders = [{megaco_ber_bin_drv_media_gateway_control_v1, + megaco_binary_transformer_v1}, + {megaco_ber_bin_drv_media_gateway_control_v2, + megaco_binary_transformer_v2}, + {megaco_ber_bin_drv_media_gateway_control_prev3b, + megaco_binary_transformer_prev3b}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Decoders, binary); +decode_message([{version3,prev3a},driver|EC], dynamic, Binary) -> + Decoders = [{megaco_ber_bin_drv_media_gateway_control_v1, + megaco_binary_transformer_v1}, + {megaco_ber_bin_drv_media_gateway_control_v2, + megaco_binary_transformer_v2}, + {megaco_ber_bin_drv_media_gateway_control_prev3a, + megaco_binary_transformer_prev3a}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Decoders, binary); +decode_message([driver|EC], dynamic, Binary) -> + Decoders = [{megaco_ber_bin_drv_media_gateway_control_v1, + megaco_binary_transformer_v1}, + {megaco_ber_bin_drv_media_gateway_control_v2, + megaco_binary_transformer_v2}, + {megaco_ber_bin_drv_media_gateway_control_v3, + megaco_binary_transformer_v3}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Decoders, binary); +decode_message([{version3,v3}|EC], dynamic, Binary) -> + Decoders = [{megaco_ber_bin_media_gateway_control_v1, + megaco_binary_transformer_v1}, + {megaco_ber_bin_media_gateway_control_v2, + megaco_binary_transformer_v2}, + {megaco_ber_bin_media_gateway_control_v3, + megaco_binary_transformer_v3}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Decoders, binary); +decode_message([{version3,prev3c}|EC], dynamic, Binary) -> + Decoders = [{megaco_ber_bin_media_gateway_control_v1, + megaco_binary_transformer_v1}, + {megaco_ber_bin_media_gateway_control_v2, + megaco_binary_transformer_v2}, + {megaco_ber_bin_media_gateway_control_prev3c, + megaco_binary_transformer_prev3c}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Decoders, binary); +decode_message([{version3,prev3b}|EC], dynamic, Binary) -> + Decoders = [{megaco_ber_bin_media_gateway_control_v1, + megaco_binary_transformer_v1}, + {megaco_ber_bin_media_gateway_control_v2, + megaco_binary_transformer_v2}, + {megaco_ber_bin_media_gateway_control_prev3b, + megaco_binary_transformer_prev3b}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Decoders, binary); +decode_message([{version3,prev3a}|EC], dynamic, Binary) -> + Decoders = [{megaco_ber_bin_media_gateway_control_v1, + megaco_binary_transformer_v1}, + {megaco_ber_bin_media_gateway_control_v2, + megaco_binary_transformer_v2}, + {megaco_ber_bin_media_gateway_control_prev3a, + megaco_binary_transformer_prev3a}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Decoders, binary); +decode_message(EC, dynamic, Binary) -> + Decoders = [{megaco_ber_bin_media_gateway_control_v1, + megaco_binary_transformer_v1}, + {megaco_ber_bin_media_gateway_control_v2, + megaco_binary_transformer_v2}, + {megaco_ber_bin_media_gateway_control_v3, + megaco_binary_transformer_v3}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Decoders, binary); + + +%% -- Version 1 -- + +decode_message([{version3,_},driver|EC], 1, Binary) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_v1, + TransMod = megaco_binary_transformer_v1, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +decode_message([driver|EC], 1, Binary) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_v1, + TransMod = megaco_binary_transformer_v1, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +decode_message([{version3,_}|EC], 1, Binary) -> + AsnMod = megaco_ber_bin_media_gateway_control_v1, + TransMod = megaco_binary_transformer_v1, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +decode_message(EC, 1, Binary) -> + AsnMod = megaco_ber_bin_media_gateway_control_v1, + TransMod = megaco_binary_transformer_v1, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + + +%% -- Version 2 -- + +decode_message([{version3,_},driver|EC], 2, Binary) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_v2, + TransMod = megaco_binary_transformer_v2, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +decode_message([driver|EC], 2, Binary) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_v2, + TransMod = megaco_binary_transformer_v2, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +decode_message([{version3,_}|EC], 2, Binary) -> + AsnMod = megaco_ber_bin_media_gateway_control_v2, + TransMod = megaco_binary_transformer_v2, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +decode_message(EC, 2, Binary) -> + AsnMod = megaco_ber_bin_media_gateway_control_v2, + TransMod = megaco_binary_transformer_v2, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + + +%% -- Version 3 -- + +decode_message([{version3,v3},driver|EC], 3, Binary) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_v3, + TransMod = megaco_binary_transformer_v3, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3c},driver|EC], 3, Binary) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_prev3c, + TransMod = megaco_binary_transformer_prev3c, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3b},driver|EC], 3, Binary) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_prev3b, + TransMod = megaco_binary_transformer_prev3b, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3a},driver|EC], 3, Binary) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_prev3a, + TransMod = megaco_binary_transformer_prev3a, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +decode_message([driver|EC], 3, Binary) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_v3, + TransMod = megaco_binary_transformer_v3, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +decode_message([{version3,v3}|EC], 3, Binary) -> + AsnMod = megaco_ber_bin_media_gateway_control_v3, + TransMod = megaco_binary_transformer_v3, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3c}|EC], 3, Binary) -> + AsnMod = megaco_ber_bin_media_gateway_control_prev3c, + TransMod = megaco_binary_transformer_prev3c, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3b}|EC], 3, Binary) -> + AsnMod = megaco_ber_bin_media_gateway_control_prev3b, + TransMod = megaco_binary_transformer_prev3b, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3a}|EC], 3, Binary) -> + AsnMod = megaco_ber_bin_media_gateway_control_prev3a, + TransMod = megaco_binary_transformer_prev3a, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +decode_message(EC, 3, Binary) -> + AsnMod = megaco_ber_bin_media_gateway_control_v3, + TransMod = megaco_binary_transformer_v3, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary). + + +decode_mini_message([{version3,v3},driver|EC], dynamic, Bin) -> + Mods = [megaco_ber_bin_drv_media_gateway_control_v1, + megaco_ber_bin_drv_media_gateway_control_v2, + megaco_ber_bin_drv_media_gateway_control_v3], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3c},driver|EC], dynamic, Bin) -> + Mods = [megaco_ber_bin_drv_media_gateway_control_v1, + megaco_ber_bin_drv_media_gateway_control_v2, + megaco_ber_bin_drv_media_gateway_control_prev3c], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3b},driver|EC], dynamic, Bin) -> + Mods = [megaco_ber_bin_drv_media_gateway_control_v1, + megaco_ber_bin_drv_media_gateway_control_v2, + megaco_ber_bin_drv_media_gateway_control_prev3b], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3a},driver|EC], dynamic, Bin) -> + Mods = [megaco_ber_bin_drv_media_gateway_control_v1, + megaco_ber_bin_drv_media_gateway_control_v2, + megaco_ber_bin_drv_media_gateway_control_prev3a], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([driver|EC], dynamic, Bin) -> + Mods = [megaco_ber_bin_drv_media_gateway_control_v1, + megaco_ber_bin_drv_media_gateway_control_v2, + megaco_ber_bin_drv_media_gateway_control_v3], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,v3}|EC], dynamic, Bin) -> + Mods = [megaco_ber_bin_media_gateway_control_v1, + megaco_ber_bin_media_gateway_control_v2, + megaco_ber_bin_media_gateway_control_v3], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3c}|EC], dynamic, Bin) -> + Mods = [megaco_ber_bin_media_gateway_control_v1, + megaco_ber_bin_media_gateway_control_v2, + megaco_ber_bin_media_gateway_control_prev3c], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3b}|EC], dynamic, Bin) -> + Mods = [megaco_ber_bin_media_gateway_control_v1, + megaco_ber_bin_media_gateway_control_v2, + megaco_ber_bin_media_gateway_control_prev3b], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3a}|EC], dynamic, Bin) -> + Mods = [megaco_ber_bin_media_gateway_control_v1, + megaco_ber_bin_media_gateway_control_v2, + megaco_ber_bin_media_gateway_control_prev3a], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message(EC, dynamic, Bin) -> + Mods = [megaco_ber_bin_media_gateway_control_v1, + megaco_ber_bin_media_gateway_control_v2, + megaco_ber_bin_media_gateway_control_v3], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); + +decode_mini_message([{version3,_},driver|EC], 1, Bin) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_v1, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([driver|EC], 1, Bin) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_v1, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,_}|EC], 1, Bin) -> + AsnMod = megaco_ber_bin_media_gateway_control_v1, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message(EC, 1, Bin) -> + AsnMod = megaco_ber_bin_media_gateway_control_v1, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); + +decode_mini_message([{version3,_},driver|EC], 2, Bin) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_v2, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([driver|EC], 2, Bin) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_v2, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,_}|EC], 2, Bin) -> + AsnMod = megaco_ber_bin_media_gateway_control_v2, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message(EC, 2, Bin) -> + AsnMod = megaco_ber_bin_media_gateway_control_v2, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); + +decode_mini_message([{version3,v3},driver|EC], 3, Bin) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_v3, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3c},driver|EC], 3, Bin) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_prev3c, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3b},driver|EC], 3, Bin) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_prev3b, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3a},driver|EC], 3, Bin) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_prev3a, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([driver|EC], 3, Bin) -> + AsnMod = megaco_ber_bin_drv_media_gateway_control_v3, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,v3}|EC], 3, Bin) -> + AsnMod = megaco_ber_bin_media_gateway_control_v3, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3c}|EC], 3, Bin) -> + AsnMod = megaco_ber_bin_media_gateway_control_prev3c, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3b}|EC], 3, Bin) -> + AsnMod = megaco_ber_bin_media_gateway_control_prev3b, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3a}|EC], 3, Bin) -> + AsnMod = megaco_ber_bin_media_gateway_control_prev3a, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message(EC, 3, Bin) -> + AsnMod = megaco_ber_bin_media_gateway_control_v3, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary). + + + diff --git a/lib/megaco/src/binary/megaco_binary_encoder_lib.erl b/lib/megaco/src/binary/megaco_binary_encoder_lib.erl new file mode 100644 index 0000000000..842d6b70d1 --- /dev/null +++ b/lib/megaco/src/binary/megaco_binary_encoder_lib.erl @@ -0,0 +1,317 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose : Handle ASN.1 BER encoding of Megaco/H.248 +%%---------------------------------------------------------------------- + +-module(megaco_binary_encoder_lib). + +%% API +-export([ + version_of/4, + decode_message/5, decode_message_dynamic/4, + decode_mini_message/4, decode_mini_message_dynamic/4, + encode_message/5, + encode_transaction/5, + encode_action_requests/5, + encode_action_request/5, + encode_action_reply/5 + ]). + +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). + + +%%---------------------------------------------------------------------- +%% Detect (check) which version a message is +%% Return {ok, Version} | {error, Reason} +%%---------------------------------------------------------------------- + +version_of(_EC, Binary, dynamic, [AsnModV1|_AsnMods]) + when is_binary(Binary) andalso is_atom(AsnModV1) -> + case (catch AsnModV1:decode_message_version(Binary)) of + {ok, PartialMsg} -> + V = (PartialMsg#'MegacoMessage'.mess)#'Message'.version, + {ok, V}; + Error -> + Error + end; +version_of(_EC, Binary, 1, AsnMods) + when is_binary(Binary) andalso is_list(AsnMods) -> + version_of(AsnMods, Binary, []); +version_of(_EC, Binary, 2, [AsnModV1, AsnModV2, AsnModV3]) + when is_binary(Binary) -> + version_of([AsnModV2, AsnModV1, AsnModV3], Binary, []); +version_of(_EC, Binary, 3, [AsnModV1, AsnModV2, AsnModV3]) + when is_binary(Binary) -> + version_of([AsnModV3, AsnModV1, AsnModV2], Binary, []). + +version_of([], _Binary, Err) -> + {error, {decode_failed, lists:reverse(Err)}}; +version_of([AsnMod|AsnMods], Binary, Errs) when is_atom(AsnMod) -> + case (catch asn1rt:decode(AsnMod, 'MegacoMessage', Binary)) of + {ok, M} -> + V = (M#'MegacoMessage'.mess)#'Message'.version, + {ok, V}; + Err -> + version_of(AsnMods, Binary, [Err|Errs]) + end. + + +%%---------------------------------------------------------------------- +%% Convert a 'MegacoMessage' record into a binary +%% Return {ok, Binary} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_message([native], MegaMsg, AsnMod, _TransMod, binary) + when is_record(MegaMsg, 'MegacoMessage') -> + asn1rt:encode(AsnMod, 'MegacoMessage', MegaMsg); +encode_message(EC, MegaMsg, AsnMod, TransMod, binary) + when is_list(EC) andalso is_record(MegaMsg, 'MegacoMessage') -> + case (catch TransMod:tr_message(MegaMsg, encode, EC)) of + {'EXIT', Reason} -> + {error, Reason}; + MegaMsg2 -> + asn1rt:encode(AsnMod, 'MegacoMessage', MegaMsg2) + end; +encode_message(EC, MegaMsg, AsnMod, TransMod, io_list) -> + case encode_message(EC, MegaMsg, AsnMod, TransMod, binary) of + {ok, Bin} when is_binary(Bin) -> + {ok, Bin}; + {ok, DeepIoList} -> + Bin = erlang:list_to_binary(DeepIoList), + {ok, Bin}; + {error, Reason} -> + {error, Reason} + end; +encode_message(EC, MegaMsg, _AsnMod, _TransMod, _Type) + when is_record(MegaMsg, 'MegacoMessage') -> + {error, {bad_encoding_config, EC}}; +encode_message(_EC, MegaMsg, _AsnMod, _TransMod, _Type) -> + {error, {no_megaco_message, MegaMsg}}. + + +%%---------------------------------------------------------------------- +%% Convert a transaction (or transactions in the case of ack) record(s) +%% into a binary +%% Return {ok, Binary} | {error, Reason} +%%---------------------------------------------------------------------- + +%% Should handle encoding of all types of transactions: +%% TransactionAck, TransactionPending, TransactionRequest +%% and TransactionReply +encode_transaction(EC, {Tag, _} = Trans, AsnMod, TransMod, Type) + when (Tag == transactionResponseAck) -> + do_encode_transaction(EC, Trans, AsnMod, TransMod, Type); +encode_transaction(EC, {Tag, _} = Trans, AsnMod, TransMod, Type) + when (Tag == transactionPending) -> + do_encode_transaction(EC, Trans, AsnMod, TransMod, Type); +encode_transaction(EC, {Tag, _} = Trans, AsnMod, TransMod, Type) + when (Tag == transactionRequest) -> + do_encode_transaction(EC, Trans, AsnMod, TransMod, Type); +%% TransactionReply has been changed as of v3 so we cannot use +%% the record definition in this common module. +encode_transaction(EC, {Tag, _} = Trans, AsnMod, TransMod, Type) + when (Tag == transactionReply) -> + do_encode_transaction(EC, Trans, AsnMod, TransMod, Type); +encode_transaction(_EC, T, _AsnMod, _TransMod, _Type) -> + {error, {no_megaco_transaction, T}}. + +do_encode_transaction([native], _Trans, _AsnMod, _TransMod, binary) -> + %% asn1rt:encode(AsnMod, element(1, T), T); + {error, not_implemented}; +do_encode_transaction(EC, _Trans, _AsnMod, _TransMod, binary) + when is_list(EC) -> + %% T2 = TransMod:tr_transaction(Trans, encode, EC), + %% asn1rt:encode(AsnMod, element(1, T), T2); + {error, not_implemented}; +do_encode_transaction(EC, Trans, AsnMod, TransMod, io_list) -> + case do_encode_transaction(EC, Trans, AsnMod, TransMod, binary) of + {ok, Bin} when is_binary(Bin) -> + {ok, Bin}; + {ok, DeepIoList} -> + Bin = erlang:list_to_binary(DeepIoList), + {ok, Bin}; + {error, Reason} -> + {error, Reason} + end; +do_encode_transaction(EC, _Trans, _AsnMod, _TransMod, _Type) -> + {error, {bad_encoding_config, EC}}. + + +%%---------------------------------------------------------------------- +%% Convert a list of ActionRequest record's into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +encode_action_requests([native], _ARs, _AsnMod, _TransMod, binary) -> + %% asn1rt:encode(AsnMod, element(1, T), T); + {error, not_implemented}; +encode_action_requests(_EC, _ARs0, _AsnMod, _TransMod, binary) -> + {error, not_implemented}; +encode_action_requests(EC, ARs, AsnMod, TransMod, io_list) -> + case encode_action_requests(EC, ARs, AsnMod, TransMod, binary) of + {ok, Bin} when is_binary(Bin) -> + {ok, Bin}; + {ok, DeepIoList} -> + Bin = erlang:list_to_binary(DeepIoList), + {ok, Bin}; + {error, Reason} -> + {error, Reason} + end; +encode_action_requests(EC, _ARs, _AsnMod, _TransMod, _Type) -> + {error, {bad_encoding_config, EC}}. + + +%%---------------------------------------------------------------------- +%% Convert a ActionRequest record into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +encode_action_request([native], _ARs, _AsnMod, _TransMod, binary) -> + %% asn1rt:encode(AsnMod, element(1, T), T); + {error, not_implemented}; +encode_action_request(_EC, _ARs0, _AsnMod, _TransMod, binary) -> + {error, not_implemented}; +encode_action_request(EC, ARs, AsnMod, TransMod, io_list) -> + case encode_action_request(EC, ARs, AsnMod, TransMod, binary) of + {ok, Bin} when is_binary(Bin) -> + {ok, Bin}; + {ok, DeepIoList} -> + Bin = erlang:list_to_binary(DeepIoList), + {ok, Bin}; + {error, Reason} -> + {error, Reason} + end; +encode_action_request(EC, _ARs, _AsnMod, _TransMod, _Type) -> + {error, {bad_encoding_config, EC}}. + + +%%---------------------------------------------------------------------- +%% Convert a ActionReply record into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +encode_action_reply([native], _ARs, _AsnMod, _TransMod, binary) -> + %% asn1rt:encode(AsnMod, element(1, T), T); + {error, not_implemented}; +encode_action_reply(_EC, _ARs0, _AsnMod, _TransMod, binary) -> + {error, not_implemented}; +encode_action_reply(EC, ARs, AsnMod, TransMod, io_list) -> + case encode_action_reply(EC, ARs, AsnMod, TransMod, binary) of + {ok, Bin} when is_binary(Bin) -> + {ok, Bin}; + {ok, DeepIoList} -> + Bin = erlang:list_to_binary(DeepIoList), + {ok, Bin}; + {error, Reason} -> + {error, Reason} + end; +encode_action_reply(EC, _ARs, _AsnMod, _TransMod, _Type) -> + {error, {bad_encoding_config, EC}}. + + +%%---------------------------------------------------------------------- +%% Convert a binary into a 'MegacoMessage' record +%% Return {ok, MegacoMessageRecord} | {error, Reason} +%%---------------------------------------------------------------------- + +decode_message_dynamic(EC, Bin, + [{AsnModV1, TransModV1}, + {AsnModV2, TransModV2}, + {AsnModV3, TransModV3}], Form) + when is_list(EC) andalso is_binary(Bin) -> + case AsnModV1:decode_message_version(Bin) of + {ok, PartialMsg} -> + V = (PartialMsg#'MegacoMessage'.mess)#'Message'.version, + case V of + 1 -> + decode_message(EC, Bin, AsnModV1, TransModV1, Form); + 2 -> + decode_message(EC, Bin, AsnModV2, TransModV2, Form); + 3 -> + decode_message(EC, Bin, AsnModV3, TransModV3, Form) + end; + {error, Reason} -> + {error, Reason} + end; +decode_message_dynamic(EC, Bin, _Mods, _Type) + when is_binary(Bin) -> + {error, {bad_encoding_config, EC}}; +decode_message_dynamic(_EC, _BadBin, _Mods, _Type) -> + {error, no_binary}. + + +decode_message(EC, Bin, AsnMod, TransMod, binary) -> + case asn1rt:decode(AsnMod, 'MegacoMessage', Bin) of + {ok, MegaMsg} -> + case EC of + [native] -> + {ok, MegaMsg}; + _ -> + {ok, TransMod:tr_message(MegaMsg, decode, EC)} + end; + {error, Reason} -> + {error, Reason} + end; +decode_message(EC, Bin, AsnMod, TransMod, io_list) -> + ShallowIoList = erlang:binary_to_list(Bin), + case asn1rt:decode(AsnMod, 'MegacoMessage', ShallowIoList) of + {ok, MegaMsg} -> + case EC of + [native] -> + {ok, MegaMsg}; + _ -> + {ok, TransMod:tr_message(MegaMsg, decode, EC)} + end; + {error, Reason} -> + {error, Reason} + end. + + +%%---------------------------------------------------------------------- +%% Convert a binary into a partial 'MegacoMessage' record +%% I.e. only version and Mid is fully decoded. +%% Return {ok, MegacoMessageRecord} | {error, Reason} +%%---------------------------------------------------------------------- + +decode_mini_message(_, Bin, Mod, _) -> + case (catch Mod:decode_message_mId(Bin)) of + {ok, #'MegacoMessage'{mess = Mess} = MegaMsg} -> + Mess2 = Mess#'Message'{messageBody = undefined}, + {ok, MegaMsg#'MegacoMessage'{mess = Mess2}}; + Error -> + Error + end. + + +decode_mini_message_dynamic(EC, Bin, [Mod1, Mod2, Mod3], Form) -> + case Mod1:decode_message_version(Bin) of + {ok, PartialMsg} -> + V = (PartialMsg#'MegacoMessage'.mess)#'Message'.version, + case V of + 1 -> + decode_mini_message(EC, Bin, Mod1, Form); + 2 -> + decode_mini_message(EC, Bin, Mod2, Form); + 3 -> + decode_mini_message(EC, Bin, Mod3, Form) + end; + Error -> + Error + end. + diff --git a/lib/megaco/src/binary/megaco_binary_name_resolver_prev3a.erl b/lib/megaco/src/binary/megaco_binary_name_resolver_prev3a.erl new file mode 100644 index 0000000000..72b3112053 --- /dev/null +++ b/lib/megaco/src/binary/megaco_binary_name_resolver_prev3a.erl @@ -0,0 +1,2003 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Handle meta data about packages +%%---------------------------------------------------------------------- + +-module(megaco_binary_name_resolver_prev3a). + +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). +-include_lib("megaco/src/app/megaco_internal.hrl"). + + +-define(LOWER(Char), + if + Char >= $A, Char =< $Z -> + Char - ($A - $a); + true -> + Char + end). + +-export([packages/0, + capabilities/0, + capabilities/1, + decode_name/3, + encode_name/3 + ]). + +encode_name(Config, term_id, TermId) -> + case megaco:encode_binary_term_id(Config, TermId) of + {ok, TermId2} -> + TermId2; + {error, _Reason} -> + exit({bad_term_id, TermId}) + end; +encode_name(_Config, Scope, Item) -> + ?d("encode_name(~p) -> entry with" + "~n Item: ~p", [Scope, Item]), + encode(Scope, Item). + +decode_name(Config, term_id, TermId) -> + case megaco:decode_binary_term_id(Config, TermId) of + {ok, TermId2} -> + TermId2; + {error, _Reason} -> + exit({bad_term_id, TermId}) + end; +decode_name(_Config, Scope, Item) -> + ?d("decode_name(~p) -> entry with" + "~n Item: ~p", [Scope, Item]), + decode(Scope, Item). + + + +%%---------------------------------------------------------------------- +%% 12.1.1 Package +%% +%% Overall description of the package, specifying: +%% +%% Package Name: only descriptive +%% +%% PackageID: is an identifier +%% +%% Description: is a description of the package +%% +%% Version: +%% +%% A new version of a package can only add additional Properties, +%% Events, Signals, Statistics and new possible values for an +%% existing parameter described in the original package. No +%% deletions or modifications shall be allowed. A version is an +%% integer in the range from 1 to 99. +%% +%% Designed to be extended only (Optional): Yes +%% +%% This indicates that the package has been expressly designed to +%% be extended by others, not to be directly referenced. For +%% example, the package may not have any function on its own or be +%% nonsensical on its own. The MG SHOULD NOT publish this PackageID +%% when reporting packages. +%% +%% Extends: existing package Descriptor +%% +%% A package may extend an existing package. The version of the +%% original package must be specified. When a package extends +%% another package it shall only add additional Properties, Events, +%% Signals, Statistics and new possible values for an existing +%% parameter described in the original package. An extended package +%% shall not redefine or overload an identifier defined in the +%% original package and packages it may have extended (multiple +%% levels of extension). Hence, if package B version 1 extends +%% package A version 1, version 2 of B will not be able to extend +%% the A version 2 if A version 2 defines a name already in B +%% version 1. If the package does not extend another package, it +%% shall specify "none". +%% +%% +%% 12.1.2 Properties +%% +%% Properties defined by the package, specifying: +%% +%% Property Name: only descriptive +%% +%% PropertyID: is an identifier +%% +%% Description: is a description of the function of the property +%% +%% Type: One of: +%% +%% Boolean +%% +%% String: UTF-8 string +%% +%% Octet String: A number of octets. See Annex A and B.3 for +%% encoding +%% +%% Integer: 4 byte signed integer +%% +%% Double: 8 byte signed integer +%% +%% Character: unicode UTF-8 encoding of a single letter. +%% Could be more than one octet. +%% +%% Enumeration: one of a list of possible unique values (see 12.3) +%% +%% Sub-list: a list of several values from a list. +%% The type of sub-list SHALL also be specified. +%% The type shall be chosen from the types specified in +%% this section (with the exception of sub-list). For +%% example, Type: sub-list of enumeration. The encoding +%% of sub-lists is specified in Annexes A and B.3. +%% +%% Possible values: +%% +%% A package MUST specify either a specific set of values or a +%% description of how values are determined. A package MUST also +%% specify a default value or the default behaviour when the value +%% is omitted from its descriptor. For example, a package may +%% specify that procedures related to the property are suspended +%% when its value is omitted. +%% +%% Default: +%% +%% A default value (but not procedures) may be specified as +%% provisionable. +%% +%% Defined in: +%% +%% Which H.248.1 descriptor the property is defined in. +%% LocalControl is for stream-dependent properties. +%% TerminationState is for stream-independent properties. +%% ContextAttribute is for properties that affect the context as +%% a whole, i.e., mixing properties. These are expected to be the +%% most common cases, but it is possible for properties to be +%% defined in other descriptors. Context properties MUST be defined +%% in the ContextAttribute descriptor. +%% +%% Characteristics: Read/Write or both, and (optionally), global: +%% +%% Indicates whether a property is read-only, or read-write, and +%% if it is global. If Global is omitted, the property is not +%% global. If a property is declared as global, the value of the +%% property is shared by all Terminations realizing the package. +%% If a context property is declared as global, the property is +%% shared by all contexts realizing the package. +%% +%% +%% 12.1.3 Events +%% +%% Events defined by the package, specifying: +%% +%% Event name: only descriptive +%% +%% EventID: is an identifier +%% +%% Description: a description of the function of the event +%% +%% EventsDescriptor Parameters: +%% +%% Parameters used by the MGC to configure the event, and found in +%% the EventsDescriptor. See 12.2. If there are no parameters for +%% the Events Descriptor, then "none" shall be specified. +%% +%% ObservedEventsDescriptor Parameters: +%% +%% Parameters returned to the MGC in Notify requests and in replies +%% to command requests from the MGC that audit +%% ObservedEventsDescriptor, and found in the +%% ObservedEventsDescriptor. See 12.2. If there are no parameters +%% for the ObservedEvents Descriptor, then �none� shall be specified. +%% +%% +%% 12.1.4 Signals +%% +%% Signals defined by the package, specifying: +%% +%% Signal Name: only descriptive +%% +%% SignalID: is an identifier. SignalID is used in a SignalsDescriptor +%% +%% Description: a description of the function of the signal +%% +%% SignalType: one of: +%% +%% OO (On/Off) +%% +%% TO (TimeOut) +%% +%% BR (Brief) +%% +%% NOTE -�SignalType may be defined such that it is dependent on +%% the value of one or more parameters. The package MUST specify a +%% default signal type. If the default type is TO, the package MUST +%% specify a default duration which may be provisioned. A default +%% duration is meaningless for BR. +%% +%% Duration: in hundredths of seconds +%% +%% Additional Parameters: see 12.2 +%% +%% +%% 12.1.5 Statistics +%% +%% Statistics defined by the package, specifying: +%% +%% Statistic name: only descriptive +%% +%% StatisticID: is an identifier +%% +%% StatisticID is used in a StatisticsDescriptor +%% +%% Description: a description of the statistic +%% +%% Type: One of: +%% +%% Boolean +%% +%% String: UTF-8 string +%% +%% Octet String: A number of octets. +%% See Annex A and Annex B.3 for encoding +%% +%% Integer: 4 byte signed integer +%% +%% Double: 8 byte signed integer +%% +%% Character: Unicode UTF-8 encoding of a single letter. +%% Could be more than one octet. +%% +%% Enumeration: One of a list of possible unique values (See 12.3) +%% +%% Sub-list: A list of several values from a list. +%% The type of sub-list SHALL also be specified. +%% The type shall be chosen from the types specified in +%% this section (with the exception of sub-list). +%% For example, Type: sub-list of enumeration. +%% The encoding of sub-lists is specified in Annexes A +%% and B.3. +%% +%% Possible Values: +%% +%% A package must indicate the unit of measure, e.g. milliseconds, +%% packets, either here or along with the type above, as well as +%% indicating any restriction on the range. +%% +%% Level: Specify if the statistic can be kept at the Termination +%% level, Stream level or Either. +%% +%% +%% 12.1.6 Error Codes +%% +%% If the package does not define any error codes, this section may be omitted. +%% Otherwise, it describes error codes defined by the package, specifying: +%% +%% Error Code #: The error code number. +%% +%% Name: Name of the error +%% +%% Definition: A description of the error code. +%% +%% Error Text in the Error Descriptor: +%% +%% A description of what text to return in the Error Descriptor. +%% +%% Comment: Any further comments on the use of the error code. +%% +%% +%% 12.1.7 Procedures +%% +%% Additional guidance on the use of the package. +%% +%% +%% 12.2 Guidelines to defining parameters to events and signals +%% +%% Parameter Name: only descriptive +%% +%% ParameterID: is an identifier. The textual ParameterID of +%% parameters to Events and Signals shall not start with "EPA" and +%% "SPA", respectively. The textual ParameterID shall also not be +%% "ST", "Stream", "SY", "SignalType", "DR", "Duration", "NC", +%% "NotifyCompletion", "KA", "KeepActive", "EB", "Embed", "DM", +%% "DigitMap", "DI", "Direction", "RQ" or "RequestID". +%% +%% Description: a description of the function of the parameter. +%% +%% Type: One of: +%% +%% Boolean +%% +%% String: UTF-8 octet string +%% +%% Octet String: A number of octets. See Annex A and B.3 for +%% encoding +%% +%% Integer: 4-octet signed integer +%% +%% Double: 8-octet signed integer +%% +%% Character: Unicode UTF-8 encoding of a single letter. Could be +%% more than one octet. +%% +%% Enumeration: one of a list of possible unique values (see 12.3) +%% +%% Sub-list: a list of several values from a list (not supported +%% for statistics). The type of sub-list SHALL also be +%% specified The type shall be chosen from the types +%% specified in this section (with the exception of +%% sub-list). For example, Type: sub-list of enumeration. +%% The encoding of sub-lists is specified in Annex A +%% and B.3. +%% +%% Optional: Yes/No +%% +%% Describes if the parameter may be omitted from the signal or +%% event. +%% +%% Possible values: +%% +%% A package MUST specify either a specific set of values or a +%% description of how values are determined. A package MUST +%% also specify a default value or the default behavior when the +%% value is omitted from its descriptor. For example, a package +%% may specify that procedures related to the parameter are +%% suspended when its value is omitted. +%% +%% Default: +%% +%% A default value (but not procedures) may be specified as +%% provisionable. +%% +%% +%% 12.3 Lists +%% +%% Possible values for parameters include enumerations. Enumerations may be +%% defined in a list. It is recommended that the list be IANA registered so +%% that packages that extend the list can be defined without concern for +%% conflicting names. +%% +%% +%% 12.4 Identifiers +%% +%% Identifiers in text encoding shall be strings of up to 64 characters, +%% containing no spaces, starting with an alphabetic character and consisting +%% of alphanumeric characters and/or digits, and possibly including the +%% special character underscore ("_"). +%% +%% Identifiers in binary encoding are 2 octets long. +%% +%% Both text and binary values shall be specified for each identifier, +%% including identifiers used as values in enumerated types. +%% +%% +%% 12.5 Package registration +%% +%% A package can be registered with IANA for interoperability reasons. See +%% clause 14 for IANA considerations. +%% +%%---------------------------------------------------------------------- + +capabilities() -> + [{P, capabilities(P)} || P <- packages()]. + +%% -record(property, {name, type, values, defined_in, characteristics}). + +%%---------------------------------------------------------------------- +%% List all known packages +%% 'native' and 'all' are not real packages +%%---------------------------------------------------------------------- + +packages() -> + [ + "g", % Generic + "root", % Base Root Package + "tonegen", % Tone Generator Package + "tonedet", % Tone Detection Package + "dg", % Basic DTMF Generator Package + "dd", % DTMF detection Package + "cg", % Call Progress Tones Generator Package + "cd", % Call Progress Tones Detection Package + "al", % Analog Line Supervision Package + "ct", % Basic Continuity Package + "nt", % Network Package + "rtp", % RTP Package + "swb", % SwitchBoard Package + "tdmc", % TDM Circuit Package + "" % Native pseudo package + ]. + +%%---------------------------------------------------------------------- +%% List all matching capabilities +%%---------------------------------------------------------------------- + +capabilities(Package) -> + case Package of + "g" -> capabilities_g(); + "root" -> capabilities_root(); + "tonegen" -> capabilities_tonegen(); + "tonedet" -> capabilities_tonedet(); + "dg" -> capabilities_dg(); + "dd" -> capabilities_dd(); + "cg" -> capabilities_cg(); + "cd" -> capabilities_cd(); + "al" -> capabilities_al(); + "ct" -> capabilities_ct(); + "nt" -> capabilities_nt(); + "rtp" -> capabilities_rtp(); + "swb" -> capabilities_swb(); + "tdmc" -> capabilities_tdmc(); + "" -> capabilities_native() + end. + +%%---------------------------------------------------------------------- +%% Decode package name to internal form +%% Scope ::= property | event | signal | statistics +%%---------------------------------------------------------------------- + +decode(mid, Package) -> + decode_mid(Package); +decode(package, Package) -> + decode_package(Package); +decode(profile, Package) -> + decode_profile(Package); +decode(dialplan, Dialplan) -> + decode_dialplan(Dialplan); +decode(Scope, [A, B | Item]) when is_atom(Scope) -> + ?d("decode(~p) -> entry with" + "~n A: ~p" + "~n B: ~p" + "~n Item: ~p", [Scope, A, B, Item]), + case decode_package([A, B]) of + "" -> + ?d("decode -> \"no\" package",[]), + decode_item(Scope, [A, B], Item); + Package -> + ?d("decode -> Package: ~p", [Package]), + Package ++ "/" ++ decode_item(Scope, [A, B], Item) + end; +decode({Scope, [A, B | Item]}, SubItem) when is_atom(Scope) -> + ?d("decode(~p) -> entry with" + "~n A: ~p" + "~n B: ~p" + "~n Item: ~p" + "~n SubItem: ~p", [Scope, A, B, Item, SubItem]), + decode_item({Scope, Item}, [A, B], SubItem). + +decode_item(Scope, [A, B], Item) -> + ?d("decode_item -> entry",[]), + case A of + 16#00 -> + case B of + 16#01 -> decode_g(Scope, Item); + 16#02 -> decode_root(Scope, Item); + 16#03 -> decode_tonegen(Scope, Item); + 16#04 -> decode_tonedet(Scope, Item); + 16#05 -> decode_dg(Scope, Item); + 16#06 -> decode_dd(Scope, Item); + 16#07 -> decode_cg(Scope, Item); + 16#08 -> decode_cd(Scope, Item); + 16#09 -> decode_al(Scope, Item); + 16#0a -> decode_ct(Scope, Item); + 16#0b -> decode_nt(Scope, Item); + 16#0c -> decode_rtp(Scope, Item); + 16#0d -> decode_tdmc(Scope, Item); + 16#00 -> decode_native(Scope, Item) + end; + 16#fe -> + case B of + %% Proprietary extension + 16#fe -> decode_swb(Scope, Item) + end; + 16#ff -> + case B of + 16#ff when Item =:= [16#ff, 16#ff] -> "*" + end + end. + +decode_package(Package) -> + ?d("decode_package -> entry with" + "~n Package: ~p", [Package]), + [A, B] = Package, + case A of + 16#00 -> + case B of + 16#01 -> "g"; + 16#02 -> "root"; + 16#03 -> "tonegen"; + 16#04 -> "tonedet"; + 16#05 -> "dg"; + 16#06 -> "dd"; + 16#07 -> "cg"; + 16#08 -> "cd"; + 16#09 -> "al"; + 16#0a -> "ct"; + 16#0b -> "nt"; + 16#0c -> "rtp"; + 16#0d -> "tdmc"; + 16#00 -> "" + end; + 16#fe -> + case B of + 16#fe -> "swb" + end; + 16#ff -> + case B of + 16#ff -> "*" + end + end. + +decode_profile([A, B]) -> + case A of + 16#00 -> + case B of + 16#fe -> "resgw"; + _ -> "profile" ++ [A + $0, B + $0] + end; + _ -> + "profile" ++ [A + $0, B + $0] + end. + +decode_dialplan([A, B]) -> + "dialplan" ++ [A + $0, B + $0]. + +decode_mid(Mid) -> + case Mid of + {domainName, DN} -> + Lower = to_lower(DN#'DomainName'.name), + {domainName, DN#'DomainName'{name = Lower}}; + {deviceName, PathName} -> + Lower = to_lower(PathName), + {deviceName, Lower}; + Other -> + Other + end. + +to_lower(Chars) -> + [?LOWER(Char) || Char <- Chars]. + +%%---------------------------------------------------------------------- +%% Encode package name from internal form +%% Scope ::= property | event | signal | statistics +%%---------------------------------------------------------------------- + +encode(mid, Package) -> + encode_mid(Package); +encode(package, Package) -> + encode_package(Package); +encode(profile, Profile) -> + encode_profile(Profile); +encode(dialplan, Dialplan) -> + encode_dialplan(Dialplan); +encode(Scope, PackageItem) when is_atom(Scope) -> + ?d("encode(~p) -> entry with" + "~n PackageItem: ~p", [Scope, PackageItem]), + case string:tokens(PackageItem, [$/]) of + [Package, Item] -> + ?d("encode -> " + "~n Package: ~p" + "~n Item: ~p", [Package, Item]), + encode_package(Package) ++ encode_item(Scope, Package, Item); + [Item] -> + ?d("encode -> Item: ~p", [Item]), + [16#00, 16#00 | encode_native(Scope, Item)] + end; +encode({Scope, PackageItem}, SubItem) when is_atom(Scope) -> + ?d("encode(~p) -> entry with" + "~n PackageItem: ~p" + "~n SubItem: ~p", [Scope, PackageItem, SubItem]), + case string:tokens(PackageItem, [$/]) of + [Package, Item] -> + ?d("encode -> " + "~n Package: ~p" + "~n Item: ~p", [Package, Item]), + encode_item({Scope, Item}, Package, SubItem); + [_Item] -> + ?d("encode -> _Item: ~p", [_Item]), + encode_native(Scope, SubItem) + end. + +encode_item(_Scope, _Package, "*") -> + [16#ff, 16#ff]; +encode_item(Scope, Package, Item) -> + ?d("encode_item(~s) -> entry", [Package]), + case Package of + "g" -> encode_g(Scope, Item); + "root" -> encode_root(Scope, Item); + "tonegen" -> encode_tonegen(Scope, Item); + "tonedet" -> encode_tonedet(Scope, Item); + "dg" -> encode_dg(Scope, Item); + "dd" -> encode_dd(Scope, Item); + "cg" -> encode_cg(Scope, Item); + "cd" -> encode_cd(Scope, Item); + "al" -> encode_al(Scope, Item); + "ct" -> encode_ct(Scope, Item); + "nt" -> encode_nt(Scope, Item); + "rtp" -> encode_rtp(Scope, Item); + "tdmc" -> encode_tdmc(Scope, Item); + "swb" -> encode_swb(Scope, Item) + end. + +encode_package(Package) -> + case Package of + "g" -> [16#00, 16#01]; + "root" -> [16#00, 16#02]; + "tonegen" -> [16#00, 16#03]; + "tonedet" -> [16#00, 16#04]; + "dg" -> [16#00, 16#05]; + "dd" -> [16#00, 16#06]; + "cg" -> [16#00, 16#07]; + "cd" -> [16#00, 16#08]; + "al" -> [16#00, 16#09]; + "ct" -> [16#00, 16#0a]; + "nt" -> [16#00, 16#0b]; + "rtp" -> [16#00, 16#0c]; + "tdmc" -> [16#00, 16#0d]; + "" -> [16#00, 16#00]; + "*" -> [16#ff, 16#ff]; + "swb" -> [16#fe, 16#fe] + end. + +encode_profile(Profile) -> + case Profile of + "resgw" -> + [16#00, 16#fe]; + [$p, $r, $o, $f, $i, $l, $e | Name] -> + case Name of + [A, B] -> [A - $0, B - $0]; + [B] -> [0, B - $0]; + [] -> [0, 0] + end + end. + +encode_dialplan(Dialplan) -> + case Dialplan of + [$d, $i, $a, $l, $p, $l, $a, $n | Name] -> + case Name of + [A, B] -> [A - $0, B - $0]; + [B] -> [0, B - $0]; + [] -> [0, 0] + end + end. + +encode_mid(Mid) -> + Mid. + + +%%---------------------------------------------------------------------- +%% Name: g - Generic +%% Version: 1 +%% Extends: None +%% Purpose: Generic package for commonly encountered items +%%---------------------------------------------------------------------- + +capabilities_g() -> + [ + {event, "cause"}, + {event, "sc"} + ]. + +encode_g(event, Item) -> + case Item of + "cause" -> [16#00, 16#01]; + "sc" -> [16#00, 16#02] + end; + +encode_g({event_parameter, Item}, SubItem) -> + case Item of + "cause" -> + case SubItem of + "Generalcause" -> [16#00, 16#01]; + "Failurecause" -> [16#00, 16#02] + end; + "sc" -> + case SubItem of + "SigID" -> [16#00, 16#01]; + "Meth" -> [16#00, 16#02]; + "SLID" -> [16#00, 16#03]; + "RID" -> [16#00, 16#04] + end + end. + +decode_g(event, Item) -> + case Item of + [16#00, 16#01] -> "cause"; + [16#00, 16#02] -> "sc" + end; + +decode_g({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event: cause + case SubItem of + [16#00, 16#01] -> "Generalcause"; + [16#00, 16#02] -> "Failurecause" + end; + + [16#00, 16#02] -> % Event: sc + case SubItem of + [16#00, 16#01] -> "SigID"; + [16#00, 16#02] -> "Meth"; + [16#00, 16#03] -> "SLID"; + [16#00, 16#04] -> "RID" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: root - Base Root Package +%% Version: 2 +%% Extends: None +%% Purpose: This package defines Gateway wide properties. +%%---------------------------------------------------------------------- + +capabilities_root() -> + [ + {property, "maxNumberOfContexts"}, + {property, "maxTerminationsPerContext"}, + {property, "normalMGExecutionTime"}, + {property, "normalMGCExecutionTime"}, + {property, "MGProvisionalResponseTimerValue"}, + {property, "MGCProvisionalResponseTimerValue"}, + {property, "MGCOriginatedPendingLimit"}, + {property, "MGOriginatedPendingLimit"} + ]. + +encode_root(Scope, Item) -> + case Scope of + property -> + case Item of + "maxNumberOfContexts" -> [16#00, 16#01]; + "maxTerminationsPerContext" -> [16#00, 16#02]; + "normalMGExecutionTime" -> [16#00, 16#03]; + "normalMGCExecutionTime" -> [16#00, 16#04]; + "MGProvisionalResponseTimerValue" -> [16#00, 16#05]; + "MGCProvisionalResponseTimerValue" -> [16#00, 16#06]; + "MGCOriginatedPendingLimit" -> [16#00, 16#07]; + "MGOriginatedPendingLimit" -> [16#00, 16#08] + end + end. + +decode_root(Scope, Item) -> + case Scope of + property -> + case Item of + [16#00, 16#01] -> "maxNumberOfContexts"; + [16#00, 16#02] -> "maxTerminationsPerContext"; + [16#00, 16#03] -> "normalMGExecutionTime"; + [16#00, 16#04] -> "normalMGCExecutionTime"; + [16#00, 16#05] -> "MGProvisionalResponseTimerValue"; + [16#00, 16#06] -> "MGCProvisionalResponseTimerValue"; + [16#00, 16#07] -> "MGCOriginatedPendingLimit"; + [16#00, 16#08] -> "MGOriginatedPendingLimit" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: tonegen - Tone Generator Package +%% Version: 2 +%% Extends: None +%% Purpose: This package defines signals to generate audio tones. +%% This package does not specify parameter values. It is +%% intended to be extendable. Generally, tones are defined +%% as an individual signal with a parameter, ind, +%% representing "interdigit" time delay, and a tone id to +%% be used with playtones. A tone id should be kept +%% consistent with any tone generation for the same tone. +%% MGs are expected to be provisioned with the characteristics +%% of appropriate tones for the country in which the MG is located. +%%---------------------------------------------------------------------- + +capabilities_tonegen() -> + [ + {signal, "pt"} + ]. + +encode_tonegen(signal, Item) -> + case Item of + "pt" -> [16#00, 16#01] + end; + +encode_tonegen({signal_parameter, Item}, SubItem) -> + case Item of + "pt" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "ind" -> [16#00, 16#02]; + "btd" -> [16#00, 16#03] + end + end. + +decode_tonegen(signal, Item) -> + case Item of + [16#00, 16#01] -> "pt" + end; + +decode_tonegen({signal_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event: pt + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#02] -> "ind"; + [16#00, 16#03] -> "btd" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: tonedet - Tone Detection Package +%% Version: 1 +%% Extends: None +%% Purpose: This Package defines events for audio tone detection. +%% Tones are selected by name (tone id). MGs are expected +%% to be provisioned with the characteristics of appropriate +%% tones for the country in which the MG is located. +%% +%% This package does not specify parameter values. +%% It is intended to be extendable. +%%---------------------------------------------------------------------- + +capabilities_tonedet() -> + [ + {event, "std"}, + {event, "etd"}, + {event, "ltd"} + ]. + +encode_tonedet(event, Item) -> + case Item of + "std" -> [16#00, 16#01]; + "etd" -> [16#00, 16#02]; + "ltd" -> [16#00, 16#03] + end; + +encode_tonedet({event_parameter, Item}, SubItem) -> + case Item of + "std" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "tid" -> [16#00, 16#03] + end; + "etd" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "tid" -> [16#00, 16#03]; + "dur" -> [16#00, 16#02] + end; + "ltd" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "dur" -> [16#00, 16#02]; + "tid" -> [16#00, 16#03] + end + end. + +decode_tonedet(event, Item) -> + case Item of + [16#00, 16#01] -> "std"; + [16#00, 16#02] -> "etd"; + [16#00, 16#03] -> "ltd" + end; + +decode_tonedet({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event std + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#03] -> "tid" + end; + [16#00, 16#02] -> % Event etd + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#03] -> "tid"; + [16#00, 16#02] -> "dur" + end; + [16#00, 16#03] -> % Event ltd + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#02] -> "dur"; + [16#00, 16#03] -> "tid" + end + end. + +%%---------------------------------------------------------------------- +%% Name: dg - Basic DTMF Generator Package +%% Version: 1 +%% Extends: tonegen version 1 +%% Purpose: This package defines the basic DTMF tones as signals and +%% extends the allowed values of parameter tl of playtone +%% in tonegen. +%%---------------------------------------------------------------------- + +capabilities_dg() -> + [ + {signal, "d0"}, + {signal, "d1"}, + {signal, "d2"}, + {signal, "d3"}, + {signal, "d4"}, + {signal, "d5"}, + {signal, "d6"}, + {signal, "d7"}, + {signal, "d8"}, + {signal, "d9"}, + {signal, "ds"}, + {signal, "do"}, + {signal, "da"}, + {signal, "db"}, + {signal, "dc"}, + {signal, "dd"} + ]. + +encode_dg(signal, Item) -> + case Item of + "d0" -> [16#00, 16#10]; + "d1" -> [16#00, 16#11]; + "d2" -> [16#00, 16#12]; + "d3" -> [16#00, 16#13]; + "d4" -> [16#00, 16#14]; + "d5" -> [16#00, 16#15]; + "d6" -> [16#00, 16#16]; + "d7" -> [16#00, 16#17]; + "d8" -> [16#00, 16#18]; + "d9" -> [16#00, 16#19]; + "ds" -> [16#00, 16#20]; + "do" -> [16#00, 16#21]; + "da" -> [16#00, 16#1a]; + "db" -> [16#00, 16#1b]; + "dc" -> [16#00, 16#1c]; + "dd" -> [16#00, 16#1d] + end; + +encode_dg({signal_parameter, Item}, SubItem) -> + case Item of + "d0" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d1" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d2" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d3" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d4" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d5" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d6" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d7" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d8" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d9" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "ds" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "do" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "da" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "db" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "dc" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "dd" -> + case SubItem of + "btd" -> [16#00, 16#01] + end + end. + +decode_dg(signal, Item) -> + case Item of + [16#00, 16#10] -> "d0"; + [16#00, 16#11] -> "d1"; + [16#00, 16#12] -> "d2"; + [16#00, 16#13] -> "d3"; + [16#00, 16#14] -> "d4"; + [16#00, 16#15] -> "d5"; + [16#00, 16#16] -> "d6"; + [16#00, 16#17] -> "d7"; + [16#00, 16#18] -> "d8"; + [16#00, 16#19] -> "d9"; + [16#00, 16#20] -> "ds"; + [16#00, 16#21] -> "do"; + [16#00, 16#1a] -> "da"; + [16#00, 16#1b] -> "db"; + [16#00, 16#1c] -> "dc"; + [16#00, 16#1d] -> "dd" + end; + +decode_dg({signal_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#10] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#11] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#12] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#13] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#14] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#15] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#16] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#17] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#18] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#19] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#20] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#21] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1a] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1b] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1c] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1d] -> + case SubItem of + [16#00, 16#01] -> "btd" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: dd - DTMF detection Package +%% Version: 1 +%% Extends: tonedet version 1 +%% Purpose: This package defines the basic DTMF tones detection. +%% Tones are selected by name (tone id). MGs are expected +%% to be provisioned with the characteristics of appropriate +%% tones for the country in which the MG is located. +%% +%% This package does not specify parameter values. +%% It is intended to be extendable. +%% +%% Additional tone id values are all tone ids described in package dg +%% (basic DTMF generator package). +%% +%% The following table maps DTMF events to digit map symbols as described +%% in section 7.1.14. +%% +%% _________________________________ +%% | DTMF Event | Symbol | +%% | d0 | "0" | +%% | d1 | "1" | +%% | d2 | "2" | +%% | d3 | "3" | +%% | d4 | "4" | +%% | d5 | "5" | +%% | d6 | "6" | +%% | d7 | "7" | +%% | d8 | "8" | +%% | d9 | "9" | +%% | da | "A" or "a"| +%% | db | "B" or "b"| +%% | dc | "C" or "c"| +%% | dd | "D" or "d"| +%% | ds | "E" or "e"| +%% | do | "F" or "f"| +%% |___________________|____________| +%% +%%---------------------------------------------------------------------- + +capabilities_dd() -> + [ + {event, "ce"}, + {event, "d0"}, + {event, "d1"}, + {event, "d2"}, + {event, "d3"}, + {event, "d4"}, + {event, "d5"}, + {event, "d6"}, + {event, "d7"}, + {event, "d8"}, + {event, "d9"}, + {event, "ds"}, + {event, "do"}, + {event, "da"}, + {event, "db"}, + {event, "dc"}, + {event, "dd"} + ]. + +encode_dd(event, Item) -> + case Item of + "ce" -> [16#00, 16#04]; + "d0" -> [16#00, 16#10]; + "d1" -> [16#00, 16#11]; + "d2" -> [16#00, 16#12]; + "d3" -> [16#00, 16#13]; + "d4" -> [16#00, 16#14]; + "d5" -> [16#00, 16#15]; + "d6" -> [16#00, 16#16]; + "d7" -> [16#00, 16#17]; + "d8" -> [16#00, 16#18]; + "d9" -> [16#00, 16#19]; + "ds" -> [16#00, 16#20]; + "do" -> [16#00, 16#21]; + "da" -> [16#00, 16#1a]; + "db" -> [16#00, 16#1b]; + "dc" -> [16#00, 16#1c]; + "dd" -> [16#00, 16#1d] + end; + +encode_dd({event_parameter, Item}, SubItem) -> + case Item of + "ce" -> + case SubItem of + "ds" -> [16#00, 16#01]; + "Meth" -> [16#00, 16#03] + end; + "d0" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d1" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d2" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d3" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d4" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d5" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d6" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d7" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d8" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d9" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "ds" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "do" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "da" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "db" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "dc" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "dd" -> + case SubItem of + "btd" -> [16#00, 16#01] + end + end. + +decode_dd(event, Item) -> + case Item of + [16#00, 16#04] -> "ce"; + [16#00, 16#10] -> "d0"; + [16#00, 16#11] -> "d1"; + [16#00, 16#12] -> "d2"; + [16#00, 16#13] -> "d3"; + [16#00, 16#14] -> "d4"; + [16#00, 16#15] -> "d5"; + [16#00, 16#16] -> "d6"; + [16#00, 16#17] -> "d7"; + [16#00, 16#18] -> "d8"; + [16#00, 16#19] -> "d9"; + [16#00, 16#20] -> "ds"; + [16#00, 16#21] -> "do"; + [16#00, 16#1a] -> "da"; + [16#00, 16#1b] -> "db"; + [16#00, 16#1c] -> "dc"; + [16#00, 16#1d] -> "dd" + end; + +decode_dd({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#04] -> % Event ce + case SubItem of + [16#00, 16#01] -> "ds"; + [16#00, 16#03] -> "Meth" + end; + [16#00, 16#10] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#11] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#12] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#13] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#14] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#15] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#16] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#17] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#18] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#19] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#20] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#21] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1a] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1b] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1c] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1d] -> + case SubItem of + [16#00, 16#01] -> "btd" + end + end. + +%%---------------------------------------------------------------------- +%% Name: cg - Call Progress Tones Generator Package +%% Version: 1 +%% Extends: tonegen version 1 +%% Purpose: This package defines the basic call progress tones as signals +%% and extends the allowed values of the tl parameter of +%% playtone in tonegen. +%%---------------------------------------------------------------------- + +capabilities_cg() -> + [ + {signal, "dt"}, + {signal, "rt"}, + {signal, "bt"}, + {signal, "ct"}, + {signal, "sit"}, + {signal, "wt"}, + {signal, "prt"}, + {signal, "cw"}, + {signal, "cr"} + ]. + + +encode_cg(Scope, Item) -> + case Scope of + signal -> + case Item of + "dt" -> [16#00, 16#30]; + "rt" -> [16#00, 16#31]; + "bt" -> [16#00, 16#32]; + "ct" -> [16#00, 16#33]; + "sit" -> [16#00, 16#34]; + "wt" -> [16#00, 16#35]; + "prt" -> [16#00, 16#36]; + "cw" -> [16#00, 16#37]; + "cr" -> [16#00, 16#38] + end + end. + +decode_cg(Scope, Item) -> + case Scope of + signal -> + case Item of + [16#00, 16#30] -> "dt"; + [16#00, 16#31] -> "rt"; + [16#00, 16#32] -> "bt"; + [16#00, 16#33] -> "ct"; + [16#00, 16#34] -> "sit"; + [16#00, 16#35] -> "wt"; + [16#00, 16#36] -> "prt"; + [16#00, 16#37] -> "cw"; + [16#00, 16#38] -> "cr" + end + end. + +%%---------------------------------------------------------------------- +%% Name: cd - Call Progress Tones Detection Package +%% Version: 1 +%% Extends: tonedet version 1 +%% Purpose: This package defines the basic call progress detection tones. +%% This Package extends the possible values of tone id +%% in the "start tone detected", "end tone detected" and +%% "long tone detected" events. +%% Additional values +%% tone id values are defined for start tone detected, +%% end tone detected and long tone detected with +%% the same values as those in package cg (call +%% progress tones generation package). +%% +%% The required set of tone ids corresponds to Recommendation E.180/Q.35 +%% [ITU-T Recommendation E.180/Q.35 (1998)]. See Recommendation E.180/Q.35 +%% for definition of the meanings of these tones. +%%---------------------------------------------------------------------- + +capabilities_cd() -> + [ + {event, "dt"}, + {event, "rt"}, + {event, "bt"}, + {event, "ct"}, + {event, "sit"}, + {event, "wt"}, + {event, "prt"}, + {event, "cw"}, + {event, "cr"} + ]. + + +encode_cd(Scope, Item) -> + case Scope of + event -> + case Item of + "dt" -> [16#00, 16#30]; + "rt" -> [16#00, 16#31]; + "bt" -> [16#00, 16#32]; + "ct" -> [16#00, 16#33]; + "sit"-> [16#00, 16#34]; + "wt" -> [16#00, 16#35]; + "prt"-> [16#00, 16#36]; + "cw" -> [16#00, 16#37]; + "cr" -> [16#00, 16#38] + end + end. + +decode_cd(Scope, Item) -> + case Scope of + event -> + case Item of + [16#00, 16#30] -> "dt"; + [16#00, 16#31] -> "rt"; + [16#00, 16#32] -> "bt"; + [16#00, 16#33] -> "ct"; + [16#00, 16#34] -> "sit"; + [16#00, 16#35] -> "wt"; + [16#00, 16#36] -> "prt"; + [16#00, 16#37] -> "cw"; + [16#00, 16#38] -> "cr" + end + end. + +%%---------------------------------------------------------------------- +%% Name: al - Analog Line Supervision Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines events and signals for an analog line. +%%---------------------------------------------------------------------- + +capabilities_al() -> + [ + {event, "on"}, + {event, "of"}, + {event, "fl"}, + {signal, "ri"} + ]. + +encode_al(event, Item) -> + ?d("encode_al(event) -> entry with" + "~n Item: ~p", [Item]), + case Item of + "on" -> [16#00, 16#04]; + "of" -> [16#00, 16#05]; + "fl" -> [16#00, 16#06] + end; + +encode_al({event_parameter, Item}, SubItem) -> + ?d("encode_al({event_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + "on" -> + case SubItem of + "strict" -> [16#00, 16#01]; + "init" -> [16#00, 16#02] + end; + "of" -> + case SubItem of + "strict" -> [16#00, 16#01]; + "init" -> [16#00, 16#02] + end; + "fl" -> + case SubItem of + "mindur" -> [16#00, 16#04]; + "maxdur" -> [16#00, 16#05] + end + end; + +encode_al(signal, Item) -> + ?d("encode_al(signal) -> entry with" + "~n Item: ~p", [Item]), + case Item of + "ri" -> [16#00, 16#02] + end; + +encode_al({signal_parameter, Item}, SubItem) -> + ?d("encode_al({signal_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + "ri" -> + case SubItem of + "cad" -> [16#00, 16#06]; + "freq" -> [16#00, 16#07] + end + end. + +decode_al(event, SubItem) -> + ?d("decode_al(event) -> entry with" + "~n SubItem: ~p", [SubItem]), + case SubItem of + [16#00, 16#04] -> "on"; + [16#00, 16#05] -> "of"; + [16#00, 16#06] -> "fl" + end; + +decode_al({event_parameter, Item}, SubItem) -> + ?d("decode_al({event_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + [16#00,16#04] -> %% Event: on + case SubItem of + [16#00, 16#01] -> "strict"; + [16#00, 16#02] -> "init" + end; + [16#00,16#05] -> %% Event: of + case SubItem of + [16#00, 16#01] -> "strict"; + [16#00, 16#02] -> "init" + end; + [16#00,16#06] -> %% Event: fl + case SubItem of + [16#00, 16#04] -> "mindur"; + [16#00, 16#05] -> "maxdur" + end + end; + +decode_al(signal, SubItem) -> + ?d("decode_al(signal) -> entry with" + "~n SubItem: ~p", [SubItem]), + case SubItem of + [16#00, 16#02] -> "ri" + end; + +decode_al({signal_parameter, Item}, SubItem) -> + ?d("decode_al({signal_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + [16#00,16#02] -> %% Event: ri + case SubItem of + [16#00, 16#06] -> "cad"; + [16#00, 16#07] -> "freq" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: ct - Basic Continuity Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines events and signals for continuity test. +%% The continuity test includes provision of either a loopback +%% or transceiver functionality. +%%---------------------------------------------------------------------- + +capabilities_ct() -> + [ + {event, "cmp"}, + {signal, "ct"}, + {signal, "rsp"} + ]. + +encode_ct(event, Item) -> + case Item of + "cmp" -> [16#00, 16#05] + end; +encode_ct({event_parameter, Item}, SubItem) -> + case Item of + "cmp" -> + case SubItem of + "res" -> [16#00, 16#08] + end + end; +encode_ct(signal, Item) -> + case Item of + "ct" -> [16#00, 16#03]; + "rsp" -> [16#00, 16#04] + end. + +decode_ct(event, Item) -> + case Item of + [16#00, 16#05] -> "cmp" + end; +decode_ct({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#05] -> % Event cmp + case SubItem of + [16#00, 16#08] -> "res" + end + end; +decode_ct(signal, Item) -> + case Item of + [16#00, 16#03] -> "ct"; + [16#00, 16#04] -> "rsp" + end. + +%%---------------------------------------------------------------------- +%% Name: nt - Network Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines properties of network terminations +%% independent of network type. +%%---------------------------------------------------------------------- + +capabilities_nt() -> + [ + {property, "jit"}, + {event, "netfail"}, + {event, "qualert"}, + {statistics, "dur"}, + {statistics, "os"}, + {statistics, "or"} + ]. + +encode_nt(property, Item) -> + case Item of + "jit" -> [16#00, 16#07] + end; +encode_nt(event, Item) -> + case Item of + "netfail" -> [16#00, 16#05]; + "qualert" -> [16#00, 16#06] + end; +encode_nt({event_parameter, Item}, SubItem) -> + case Item of + "netfail" -> + case SubItem of + "cs" -> [16#00, 16#01] + end; + "qualert" -> + case SubItem of + "th" -> [16#00, 16#01] + end + end; +encode_nt(statistics, Item) -> + case Item of + "dur" -> [16#00, 16#01]; + "os" -> [16#00, 16#02]; + "or" -> [16#00, 16#03] + end. + +decode_nt(property, Item) -> + case Item of + [16#00, 16#07] -> "jit" + end; +decode_nt(event, Item) -> + case Item of + [16#00, 16#05] -> "netfail"; + [16#00, 16#06] -> "qualert" + end; +decode_nt({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#05] -> % Event netfail + case SubItem of + [16#00, 16#01] -> "cs" + end; + [16#00, 16#06] -> % Event qualert + case Item of + [16#00, 16#01] -> "th" + end + end; +decode_nt(statistics, Item) -> + case Item of + [16#00, 16#01] -> "dur"; + [16#00, 16#02] -> "os"; + [16#00, 16#03] -> "or" + end. + +%%---------------------------------------------------------------------- +%% Name: rtp - RTP Package +%% Version: 1 +%% Extends: nt version 1 +%% Purpose: This package is used to support packet based multimedia +%% data transfer by means of the Real-time Transport Protocol +%% (RTP) [RFC 1889]. +%%---------------------------------------------------------------------- + +capabilities_rtp() -> + [ + {event, "pltrans"}, + {statistics, "ps"}, + {statistics, "pr"}, + {statistics, "pl"}, + {statistics, "jit"}, + {statistics, "delay"} + ]. + +encode_rtp(event, Item) -> + case Item of + "pltrans" -> [16#00, 16#01] + end; +encode_rtp({event_parameter, Item}, SubItem) -> + case Item of + "pltrans" -> + case SubItem of + "rtppltype" -> [16#00, 16#01] + end + end; +encode_rtp(statistics, Item) -> + case Item of + "ps" -> [16#00, 16#04]; + "pr" -> [16#00, 16#05]; + "pl" -> [16#00, 16#06]; + "jit" -> [16#00, 16#07]; + "delay" -> [16#00, 16#08] + end. + +decode_rtp(event, Item) -> + case Item of + [16#00, 16#01] -> "pltrans" + end; +decode_rtp({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event pltrans + case SubItem of + [16#00, 16#01] -> "rtppltype" + end + end; +decode_rtp(statistics, Item) -> + case Item of + [16#00, 16#04] -> "ps"; + [16#00, 16#05] -> "pr"; + [16#00, 16#06] -> "pl"; + [16#00, 16#07] -> "jit"; + [16#00, 16#08] -> "delay" + end. + + +%%---------------------------------------------------------------------- +%% Name: tdmc - TDM Circuit Package +%% Version: 1 +%% Extends: nt version 1 +%% Purpose: This package is used to support TDM circuit terminations. +%%---------------------------------------------------------------------- + +capabilities_tdmc() -> + [ + {property, "ec"}, + {property, "gain"} + ]. + +encode_tdmc(Scope, Item) -> + case Scope of + property -> + case Item of + "ec" -> [16#00, 16#08]; + "gain" -> [16#00, 16#0a] + end + end. + +decode_tdmc(Scope, Item) -> + case Scope of + property -> + case Item of + [16#00, 16#08] -> "ec"; + [16#00, 16#0a] -> "gain" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: swb - SwitchBoard Package +%% Version: 1 +%% Extends: none +%% Purpose: This package is used to support SwitchBoard specials +%%---------------------------------------------------------------------- + +capabilities_swb() -> + [ + {statistics, "fs"}, % Free slots + {statistics, "as"} % Allocated slots + ]. + +encode_swb(Scope, Item) -> + case Scope of + statistics -> + case Item of + "fs" -> [16#00, 16#00]; + "as" -> [16#00, 16#01] + end + end. + +decode_swb(Scope, Item) -> + case Scope of + statistics -> + case Item of + [16#00, 16#00] -> "fs"; + [16#00, 16#01] -> "as" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: native - Pseudo package +%% Version: 1 +%% Extends: None +%% Purpose: Native tags for media stream properties +%% +%% Parameters for Local descriptors and Remote descriptors are +%% specified as tag-value pairs if binary encoding is used for the +%% protocol. This annex contains the property names (PropertyID), the +%% tags (Property Tag), type of the property (Type) and the values +%% (Value).Values presented in the Value field when the field contains +%% references shall be regarded as "information". The reference +%% contains the normative values. If a value field does not contain a +%% reference then the values in that field can be considered as +%% "normative". +%% +%% Tags are given as hexadecimal numbers in this annex. When setting +%% the value of a property, a MGC may underspecify the value according +%% to one of the mechanisms specified in section 7.1.1. +%% +%% For type "enumeration" the value is represented by the value in brack- +%% ets, e.g., Send(0), Receive(1). +%%---------------------------------------------------------------------- +%% +%% C.6. IP +%% +%% ________________________________________________________________ +%% | PropertyID| Tag | Type | Value | +%% | IPv4 | 6001 | 32 BITS | Ipv4Address | +%% | IPv6 | 6002 | 128 BITS | IPv6 Address | +%% | Port | 6003 | Unsigned Int| Port | +%% | Porttype | 6004 | Enumerated | TCP(0),UDP(1),SCTP(2)| +%% |___________|____________|______________|_______________________| +%% +%% +%% C.11. SDP Equivalents +%% +%% ______________________________________________________________ +%% | PropertyID| Tag | Type | Value | +%% | SDP_V | B001| STRING| Protocol Version | +%% | SDP_O | B002| STRING| Owner-creator and session ID | +%% | SDP_S | B003| STRING| Sesson name | +%% | SDP_I | B004| STRING| Session identifier | +%% | SDP_U | B005| STRING| URI of descriptor | +%% | SDC_E | B006| STRING| email address | +%% | SDP_P | B007| STRING| phone number | +%% | SDP_C | B008| STRING| Connection information | +%% | SDP_B | B009| STRING| Bandwidth Information | +%% | SDP_Z | B00A| STRING| time zone adjustment | +%% | SDP_K | B00B| STRING| Encryption Key | +%% | SDP_A | B00C| STRING| Zero or more session attributes| +%% | SDP_T | B00D| STRING| Active Session Time | +%% | SDP_R | B00E| STRING| Zero or more repeat times | +%% | SDP_M | B00F| STRING| Media name and transport addr | +%% | | | | Reference: IETF RFC 2327 | +%% |___________|______|________|_________________________________| +%% +%%---------------------------------------------------------------------- + +capabilities_native() -> + [ + %% C.6. IP + {property, "IPv4"}, + {property, "IPv6"}, + {property, "Port"}, + {property, "Porttype"}, + + %% C.11. SDP Equivalents + {property, "v"}, + {property, "o"}, + {property, "s"}, + {property, "i"}, + {property, "u"}, + {property, "e"}, + {property, "p"}, + {property, "c"}, + {property, "b"}, + {property, "z"}, + {property, "k"}, + {property, "a"}, + {property, "t"}, + {property, "r"}, + {property, "m"} + ]. + +encode_native(Scope, Item) -> + case Scope of + property -> + case Item of + %% IP + "IPv4" -> [16#60, 16#01]; + "IPv6" -> [16#60, 16#02]; + "Port" -> [16#60, 16#03]; + "Porttype" -> [16#60, 16#04]; + + %% SDP + "v" -> [16#b0, 16#01]; + "o" -> [16#b0, 16#02]; + "s" -> [16#b0, 16#03]; + "i" -> [16#b0, 16#04]; + "u" -> [16#b0, 16#05]; + "e" -> [16#b0, 16#06]; + "p" -> [16#b0, 16#07]; + "c" -> [16#b0, 16#08]; + "b" -> [16#b0, 16#09]; + "z" -> [16#b0, 16#0a]; + "k" -> [16#b0, 16#0b]; + "a" -> [16#b0, 16#0c]; + "t" -> [16#b0, 16#0d]; + "r" -> [16#b0, 16#0e]; + "m" -> [16#b0, 16#0f] + end + end. + +decode_native(Scope, [Type, Item]) -> + case Scope of + property -> + case Type of + 16#60 -> + case Item of + 16#01 -> "IPv4"; + 16#02 -> "IPv6"; + 16#03 -> "Port"; + 16#04 -> "Porttype" + end; + + 16#b0 -> + case Item of + 16#01 -> "v"; + 16#02 -> "o"; + 16#03 -> "s"; + 16#04 -> "i"; + 16#05 -> "u"; + 16#06 -> "e"; + 16#07 -> "p"; + 16#08 -> "c"; + 16#09 -> "b"; + 16#0a -> "z"; + 16#0b -> "k"; + 16#0c -> "a"; + 16#0d -> "t"; + 16#0e -> "r"; + 16#0f -> "m" + end + end + end. + +%% ------------------------------------------------------------------- + +% error(Reason) -> +% erlang:error(Reason). + diff --git a/lib/megaco/src/binary/megaco_binary_name_resolver_prev3b.erl b/lib/megaco/src/binary/megaco_binary_name_resolver_prev3b.erl new file mode 100644 index 0000000000..12e673ac81 --- /dev/null +++ b/lib/megaco/src/binary/megaco_binary_name_resolver_prev3b.erl @@ -0,0 +1,2003 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Handle meta data about packages +%%---------------------------------------------------------------------- + +-module(megaco_binary_name_resolver_prev3b). + +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). +-include_lib("megaco/src/app/megaco_internal.hrl"). + + +-define(LOWER(Char), + if + Char >= $A, Char =< $Z -> + Char - ($A - $a); + true -> + Char + end). + +-export([packages/0, + capabilities/0, + capabilities/1, + decode_name/3, + encode_name/3 + ]). + +encode_name(Config, term_id, TermId) -> + case megaco:encode_binary_term_id(Config, TermId) of + {ok, TermId2} -> + TermId2; + {error, _Reason} -> + exit({bad_term_id, TermId}) + end; +encode_name(_Config, Scope, Item) -> + ?d("encode_name(~p) -> entry with" + "~n Item: ~p", [Scope, Item]), + encode(Scope, Item). + +decode_name(Config, term_id, TermId) -> + case megaco:decode_binary_term_id(Config, TermId) of + {ok, TermId2} -> + TermId2; + {error, _Reason} -> + exit({bad_term_id, TermId}) + end; +decode_name(_Config, Scope, Item) -> + ?d("decode_name(~p) -> entry with" + "~n Item: ~p", [Scope, Item]), + decode(Scope, Item). + + + +%%---------------------------------------------------------------------- +%% 12.1.1 Package +%% +%% Overall description of the package, specifying: +%% +%% Package Name: only descriptive +%% +%% PackageID: is an identifier +%% +%% Description: is a description of the package +%% +%% Version: +%% +%% A new version of a package can only add additional Properties, +%% Events, Signals, Statistics and new possible values for an +%% existing parameter described in the original package. No +%% deletions or modifications shall be allowed. A version is an +%% integer in the range from 1 to 99. +%% +%% Designed to be extended only (Optional): Yes +%% +%% This indicates that the package has been expressly designed to +%% be extended by others, not to be directly referenced. For +%% example, the package may not have any function on its own or be +%% nonsensical on its own. The MG SHOULD NOT publish this PackageID +%% when reporting packages. +%% +%% Extends: existing package Descriptor +%% +%% A package may extend an existing package. The version of the +%% original package must be specified. When a package extends +%% another package it shall only add additional Properties, Events, +%% Signals, Statistics and new possible values for an existing +%% parameter described in the original package. An extended package +%% shall not redefine or overload an identifier defined in the +%% original package and packages it may have extended (multiple +%% levels of extension). Hence, if package B version 1 extends +%% package A version 1, version 2 of B will not be able to extend +%% the A version 2 if A version 2 defines a name already in B +%% version 1. If the package does not extend another package, it +%% shall specify "none". +%% +%% +%% 12.1.2 Properties +%% +%% Properties defined by the package, specifying: +%% +%% Property Name: only descriptive +%% +%% PropertyID: is an identifier +%% +%% Description: is a description of the function of the property +%% +%% Type: One of: +%% +%% Boolean +%% +%% String: UTF-8 string +%% +%% Octet String: A number of octets. See Annex A and B.3 for +%% encoding +%% +%% Integer: 4 byte signed integer +%% +%% Double: 8 byte signed integer +%% +%% Character: unicode UTF-8 encoding of a single letter. +%% Could be more than one octet. +%% +%% Enumeration: one of a list of possible unique values (see 12.3) +%% +%% Sub-list: a list of several values from a list. +%% The type of sub-list SHALL also be specified. +%% The type shall be chosen from the types specified in +%% this section (with the exception of sub-list). For +%% example, Type: sub-list of enumeration. The encoding +%% of sub-lists is specified in Annexes A and B.3. +%% +%% Possible values: +%% +%% A package MUST specify either a specific set of values or a +%% description of how values are determined. A package MUST also +%% specify a default value or the default behaviour when the value +%% is omitted from its descriptor. For example, a package may +%% specify that procedures related to the property are suspended +%% when its value is omitted. +%% +%% Default: +%% +%% A default value (but not procedures) may be specified as +%% provisionable. +%% +%% Defined in: +%% +%% Which H.248.1 descriptor the property is defined in. +%% LocalControl is for stream-dependent properties. +%% TerminationState is for stream-independent properties. +%% ContextAttribute is for properties that affect the context as +%% a whole, i.e., mixing properties. These are expected to be the +%% most common cases, but it is possible for properties to be +%% defined in other descriptors. Context properties MUST be defined +%% in the ContextAttribute descriptor. +%% +%% Characteristics: Read/Write or both, and (optionally), global: +%% +%% Indicates whether a property is read-only, or read-write, and +%% if it is global. If Global is omitted, the property is not +%% global. If a property is declared as global, the value of the +%% property is shared by all Terminations realizing the package. +%% If a context property is declared as global, the property is +%% shared by all contexts realizing the package. +%% +%% +%% 12.1.3 Events +%% +%% Events defined by the package, specifying: +%% +%% Event name: only descriptive +%% +%% EventID: is an identifier +%% +%% Description: a description of the function of the event +%% +%% EventsDescriptor Parameters: +%% +%% Parameters used by the MGC to configure the event, and found in +%% the EventsDescriptor. See 12.2. If there are no parameters for +%% the Events Descriptor, then "none" shall be specified. +%% +%% ObservedEventsDescriptor Parameters: +%% +%% Parameters returned to the MGC in Notify requests and in replies +%% to command requests from the MGC that audit +%% ObservedEventsDescriptor, and found in the +%% ObservedEventsDescriptor. See 12.2. If there are no parameters +%% for the ObservedEvents Descriptor, then �none� shall be specified. +%% +%% +%% 12.1.4 Signals +%% +%% Signals defined by the package, specifying: +%% +%% Signal Name: only descriptive +%% +%% SignalID: is an identifier. SignalID is used in a SignalsDescriptor +%% +%% Description: a description of the function of the signal +%% +%% SignalType: one of: +%% +%% OO (On/Off) +%% +%% TO (TimeOut) +%% +%% BR (Brief) +%% +%% NOTE -�SignalType may be defined such that it is dependent on +%% the value of one or more parameters. The package MUST specify a +%% default signal type. If the default type is TO, the package MUST +%% specify a default duration which may be provisioned. A default +%% duration is meaningless for BR. +%% +%% Duration: in hundredths of seconds +%% +%% Additional Parameters: see 12.2 +%% +%% +%% 12.1.5 Statistics +%% +%% Statistics defined by the package, specifying: +%% +%% Statistic name: only descriptive +%% +%% StatisticID: is an identifier +%% +%% StatisticID is used in a StatisticsDescriptor +%% +%% Description: a description of the statistic +%% +%% Type: One of: +%% +%% Boolean +%% +%% String: UTF-8 string +%% +%% Octet String: A number of octets. +%% See Annex A and Annex B.3 for encoding +%% +%% Integer: 4 byte signed integer +%% +%% Double: 8 byte signed integer +%% +%% Character: Unicode UTF-8 encoding of a single letter. +%% Could be more than one octet. +%% +%% Enumeration: One of a list of possible unique values (See 12.3) +%% +%% Sub-list: A list of several values from a list. +%% The type of sub-list SHALL also be specified. +%% The type shall be chosen from the types specified in +%% this section (with the exception of sub-list). +%% For example, Type: sub-list of enumeration. +%% The encoding of sub-lists is specified in Annexes A +%% and B.3. +%% +%% Possible Values: +%% +%% A package must indicate the unit of measure, e.g. milliseconds, +%% packets, either here or along with the type above, as well as +%% indicating any restriction on the range. +%% +%% Level: Specify if the statistic can be kept at the Termination +%% level, Stream level or Either. +%% +%% +%% 12.1.6 Error Codes +%% +%% If the package does not define any error codes, this section may be omitted. +%% Otherwise, it describes error codes defined by the package, specifying: +%% +%% Error Code #: The error code number. +%% +%% Name: Name of the error +%% +%% Definition: A description of the error code. +%% +%% Error Text in the Error Descriptor: +%% +%% A description of what text to return in the Error Descriptor. +%% +%% Comment: Any further comments on the use of the error code. +%% +%% +%% 12.1.7 Procedures +%% +%% Additional guidance on the use of the package. +%% +%% +%% 12.2 Guidelines to defining parameters to events and signals +%% +%% Parameter Name: only descriptive +%% +%% ParameterID: is an identifier. The textual ParameterID of +%% parameters to Events and Signals shall not start with "EPA" and +%% "SPA", respectively. The textual ParameterID shall also not be +%% "ST", "Stream", "SY", "SignalType", "DR", "Duration", "NC", +%% "NotifyCompletion", "KA", "KeepActive", "EB", "Embed", "DM", +%% "DigitMap", "DI", "Direction", "RQ" or "RequestID". +%% +%% Description: a description of the function of the parameter. +%% +%% Type: One of: +%% +%% Boolean +%% +%% String: UTF-8 octet string +%% +%% Octet String: A number of octets. See Annex A and B.3 for +%% encoding +%% +%% Integer: 4-octet signed integer +%% +%% Double: 8-octet signed integer +%% +%% Character: Unicode UTF-8 encoding of a single letter. Could be +%% more than one octet. +%% +%% Enumeration: one of a list of possible unique values (see 12.3) +%% +%% Sub-list: a list of several values from a list (not supported +%% for statistics). The type of sub-list SHALL also be +%% specified The type shall be chosen from the types +%% specified in this section (with the exception of +%% sub-list). For example, Type: sub-list of enumeration. +%% The encoding of sub-lists is specified in Annex A +%% and B.3. +%% +%% Optional: Yes/No +%% +%% Describes if the parameter may be omitted from the signal or +%% event. +%% +%% Possible values: +%% +%% A package MUST specify either a specific set of values or a +%% description of how values are determined. A package MUST +%% also specify a default value or the default behavior when the +%% value is omitted from its descriptor. For example, a package +%% may specify that procedures related to the parameter are +%% suspended when its value is omitted. +%% +%% Default: +%% +%% A default value (but not procedures) may be specified as +%% provisionable. +%% +%% +%% 12.3 Lists +%% +%% Possible values for parameters include enumerations. Enumerations may be +%% defined in a list. It is recommended that the list be IANA registered so +%% that packages that extend the list can be defined without concern for +%% conflicting names. +%% +%% +%% 12.4 Identifiers +%% +%% Identifiers in text encoding shall be strings of up to 64 characters, +%% containing no spaces, starting with an alphabetic character and consisting +%% of alphanumeric characters and/or digits, and possibly including the +%% special character underscore ("_"). +%% +%% Identifiers in binary encoding are 2 octets long. +%% +%% Both text and binary values shall be specified for each identifier, +%% including identifiers used as values in enumerated types. +%% +%% +%% 12.5 Package registration +%% +%% A package can be registered with IANA for interoperability reasons. See +%% clause 14 for IANA considerations. +%% +%%---------------------------------------------------------------------- + +capabilities() -> + [{P, capabilities(P)} || P <- packages()]. + +%% -record(property, {name, type, values, defined_in, characteristics}). + +%%---------------------------------------------------------------------- +%% List all known packages +%% 'native' and 'all' are not real packages +%%---------------------------------------------------------------------- + +packages() -> + [ + "g", % Generic + "root", % Base Root Package + "tonegen", % Tone Generator Package + "tonedet", % Tone Detection Package + "dg", % Basic DTMF Generator Package + "dd", % DTMF detection Package + "cg", % Call Progress Tones Generator Package + "cd", % Call Progress Tones Detection Package + "al", % Analog Line Supervision Package + "ct", % Basic Continuity Package + "nt", % Network Package + "rtp", % RTP Package + "swb", % SwitchBoard Package + "tdmc", % TDM Circuit Package + "" % Native pseudo package + ]. + +%%---------------------------------------------------------------------- +%% List all matching capabilities +%%---------------------------------------------------------------------- + +capabilities(Package) -> + case Package of + "g" -> capabilities_g(); + "root" -> capabilities_root(); + "tonegen" -> capabilities_tonegen(); + "tonedet" -> capabilities_tonedet(); + "dg" -> capabilities_dg(); + "dd" -> capabilities_dd(); + "cg" -> capabilities_cg(); + "cd" -> capabilities_cd(); + "al" -> capabilities_al(); + "ct" -> capabilities_ct(); + "nt" -> capabilities_nt(); + "rtp" -> capabilities_rtp(); + "swb" -> capabilities_swb(); + "tdmc" -> capabilities_tdmc(); + "" -> capabilities_native() + end. + +%%---------------------------------------------------------------------- +%% Decode package name to internal form +%% Scope ::= property | event | signal | statistics +%%---------------------------------------------------------------------- + +decode(mid, Package) -> + decode_mid(Package); +decode(package, Package) -> + decode_package(Package); +decode(profile, Package) -> + decode_profile(Package); +decode(dialplan, Dialplan) -> + decode_dialplan(Dialplan); +decode(Scope, [A, B | Item]) when is_atom(Scope) -> + ?d("decode(~p) -> entry with" + "~n A: ~p" + "~n B: ~p" + "~n Item: ~p", [Scope, A, B, Item]), + case decode_package([A, B]) of + "" -> + ?d("decode -> \"no\" package",[]), + decode_item(Scope, [A, B], Item); + Package -> + ?d("decode -> Package: ~p", [Package]), + Package ++ "/" ++ decode_item(Scope, [A, B], Item) + end; +decode({Scope, [A, B | Item]}, SubItem) when is_atom(Scope) -> + ?d("decode(~p) -> entry with" + "~n A: ~p" + "~n B: ~p" + "~n Item: ~p" + "~n SubItem: ~p", [Scope, A, B, Item, SubItem]), + decode_item({Scope, Item}, [A, B], SubItem). + +decode_item(Scope, [A, B], Item) -> + ?d("decode_item -> entry",[]), + case A of + 16#00 -> + case B of + 16#01 -> decode_g(Scope, Item); + 16#02 -> decode_root(Scope, Item); + 16#03 -> decode_tonegen(Scope, Item); + 16#04 -> decode_tonedet(Scope, Item); + 16#05 -> decode_dg(Scope, Item); + 16#06 -> decode_dd(Scope, Item); + 16#07 -> decode_cg(Scope, Item); + 16#08 -> decode_cd(Scope, Item); + 16#09 -> decode_al(Scope, Item); + 16#0a -> decode_ct(Scope, Item); + 16#0b -> decode_nt(Scope, Item); + 16#0c -> decode_rtp(Scope, Item); + 16#0d -> decode_tdmc(Scope, Item); + 16#00 -> decode_native(Scope, Item) + end; + 16#fe -> + case B of + %% Proprietary extension + 16#fe -> decode_swb(Scope, Item) + end; + 16#ff -> + case B of + 16#ff when Item =:= [16#ff, 16#ff] -> "*" + end + end. + +decode_package(Package) -> + ?d("decode_package -> entry with" + "~n Package: ~p", [Package]), + [A, B] = Package, + case A of + 16#00 -> + case B of + 16#01 -> "g"; + 16#02 -> "root"; + 16#03 -> "tonegen"; + 16#04 -> "tonedet"; + 16#05 -> "dg"; + 16#06 -> "dd"; + 16#07 -> "cg"; + 16#08 -> "cd"; + 16#09 -> "al"; + 16#0a -> "ct"; + 16#0b -> "nt"; + 16#0c -> "rtp"; + 16#0d -> "tdmc"; + 16#00 -> "" + end; + 16#fe -> + case B of + 16#fe -> "swb" + end; + 16#ff -> + case B of + 16#ff -> "*" + end + end. + +decode_profile([A, B]) -> + case A of + 16#00 -> + case B of + 16#fe -> "resgw"; + _ -> "profile" ++ [A + $0, B + $0] + end; + _ -> + "profile" ++ [A + $0, B + $0] + end. + +decode_dialplan([A, B]) -> + "dialplan" ++ [A + $0, B + $0]. + +decode_mid(Mid) -> + case Mid of + {domainName, DN} -> + Lower = to_lower(DN#'DomainName'.name), + {domainName, DN#'DomainName'{name = Lower}}; + {deviceName, PathName} -> + Lower = to_lower(PathName), + {deviceName, Lower}; + Other -> + Other + end. + +to_lower(Chars) -> + [?LOWER(Char) || Char <- Chars]. + +%%---------------------------------------------------------------------- +%% Encode package name from internal form +%% Scope ::= property | event | signal | statistics +%%---------------------------------------------------------------------- + +encode(mid, Package) -> + encode_mid(Package); +encode(package, Package) -> + encode_package(Package); +encode(profile, Profile) -> + encode_profile(Profile); +encode(dialplan, Dialplan) -> + encode_dialplan(Dialplan); +encode(Scope, PackageItem) when is_atom(Scope) -> + ?d("encode(~p) -> entry with" + "~n PackageItem: ~p", [Scope, PackageItem]), + case string:tokens(PackageItem, [$/]) of + [Package, Item] -> + ?d("encode -> " + "~n Package: ~p" + "~n Item: ~p", [Package, Item]), + encode_package(Package) ++ encode_item(Scope, Package, Item); + [Item] -> + ?d("encode -> Item: ~p", [Item]), + [16#00, 16#00 | encode_native(Scope, Item)] + end; +encode({Scope, PackageItem}, SubItem) when is_atom(Scope) -> + ?d("encode(~p) -> entry with" + "~n PackageItem: ~p" + "~n SubItem: ~p", [Scope, PackageItem, SubItem]), + case string:tokens(PackageItem, [$/]) of + [Package, Item] -> + ?d("encode -> " + "~n Package: ~p" + "~n Item: ~p", [Package, Item]), + encode_item({Scope, Item}, Package, SubItem); + [_Item] -> + ?d("encode -> _Item: ~p", [_Item]), + encode_native(Scope, SubItem) + end. + +encode_item(_Scope, _Package, "*") -> + [16#ff, 16#ff]; +encode_item(Scope, Package, Item) -> + ?d("encode_item(~s) -> entry", [Package]), + case Package of + "g" -> encode_g(Scope, Item); + "root" -> encode_root(Scope, Item); + "tonegen" -> encode_tonegen(Scope, Item); + "tonedet" -> encode_tonedet(Scope, Item); + "dg" -> encode_dg(Scope, Item); + "dd" -> encode_dd(Scope, Item); + "cg" -> encode_cg(Scope, Item); + "cd" -> encode_cd(Scope, Item); + "al" -> encode_al(Scope, Item); + "ct" -> encode_ct(Scope, Item); + "nt" -> encode_nt(Scope, Item); + "rtp" -> encode_rtp(Scope, Item); + "tdmc" -> encode_tdmc(Scope, Item); + "swb" -> encode_swb(Scope, Item) + end. + +encode_package(Package) -> + case Package of + "g" -> [16#00, 16#01]; + "root" -> [16#00, 16#02]; + "tonegen" -> [16#00, 16#03]; + "tonedet" -> [16#00, 16#04]; + "dg" -> [16#00, 16#05]; + "dd" -> [16#00, 16#06]; + "cg" -> [16#00, 16#07]; + "cd" -> [16#00, 16#08]; + "al" -> [16#00, 16#09]; + "ct" -> [16#00, 16#0a]; + "nt" -> [16#00, 16#0b]; + "rtp" -> [16#00, 16#0c]; + "tdmc" -> [16#00, 16#0d]; + "" -> [16#00, 16#00]; + "*" -> [16#ff, 16#ff]; + "swb" -> [16#fe, 16#fe] + end. + +encode_profile(Profile) -> + case Profile of + "resgw" -> + [16#00, 16#fe]; + [$p, $r, $o, $f, $i, $l, $e | Name] -> + case Name of + [A, B] -> [A - $0, B - $0]; + [B] -> [0, B - $0]; + [] -> [0, 0] + end + end. + +encode_dialplan(Dialplan) -> + case Dialplan of + [$d, $i, $a, $l, $p, $l, $a, $n | Name] -> + case Name of + [A, B] -> [A - $0, B - $0]; + [B] -> [0, B - $0]; + [] -> [0, 0] + end + end. + +encode_mid(Mid) -> + Mid. + + +%%---------------------------------------------------------------------- +%% Name: g - Generic +%% Version: 1 +%% Extends: None +%% Purpose: Generic package for commonly encountered items +%%---------------------------------------------------------------------- + +capabilities_g() -> + [ + {event, "cause"}, + {event, "sc"} + ]. + +encode_g(event, Item) -> + case Item of + "cause" -> [16#00, 16#01]; + "sc" -> [16#00, 16#02] + end; + +encode_g({event_parameter, Item}, SubItem) -> + case Item of + "cause" -> + case SubItem of + "Generalcause" -> [16#00, 16#01]; + "Failurecause" -> [16#00, 16#02] + end; + "sc" -> + case SubItem of + "SigID" -> [16#00, 16#01]; + "Meth" -> [16#00, 16#02]; + "SLID" -> [16#00, 16#03]; + "RID" -> [16#00, 16#04] + end + end. + +decode_g(event, Item) -> + case Item of + [16#00, 16#01] -> "cause"; + [16#00, 16#02] -> "sc" + end; + +decode_g({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event: cause + case SubItem of + [16#00, 16#01] -> "Generalcause"; + [16#00, 16#02] -> "Failurecause" + end; + + [16#00, 16#02] -> % Event: sc + case SubItem of + [16#00, 16#01] -> "SigID"; + [16#00, 16#02] -> "Meth"; + [16#00, 16#03] -> "SLID"; + [16#00, 16#04] -> "RID" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: root - Base Root Package +%% Version: 2 +%% Extends: None +%% Purpose: This package defines Gateway wide properties. +%%---------------------------------------------------------------------- + +capabilities_root() -> + [ + {property, "maxNumberOfContexts"}, + {property, "maxTerminationsPerContext"}, + {property, "normalMGExecutionTime"}, + {property, "normalMGCExecutionTime"}, + {property, "MGProvisionalResponseTimerValue"}, + {property, "MGCProvisionalResponseTimerValue"}, + {property, "MGCOriginatedPendingLimit"}, + {property, "MGOriginatedPendingLimit"} + ]. + +encode_root(Scope, Item) -> + case Scope of + property -> + case Item of + "maxNumberOfContexts" -> [16#00, 16#01]; + "maxTerminationsPerContext" -> [16#00, 16#02]; + "normalMGExecutionTime" -> [16#00, 16#03]; + "normalMGCExecutionTime" -> [16#00, 16#04]; + "MGProvisionalResponseTimerValue" -> [16#00, 16#05]; + "MGCProvisionalResponseTimerValue" -> [16#00, 16#06]; + "MGCOriginatedPendingLimit" -> [16#00, 16#07]; + "MGOriginatedPendingLimit" -> [16#00, 16#08] + end + end. + +decode_root(Scope, Item) -> + case Scope of + property -> + case Item of + [16#00, 16#01] -> "maxNumberOfContexts"; + [16#00, 16#02] -> "maxTerminationsPerContext"; + [16#00, 16#03] -> "normalMGExecutionTime"; + [16#00, 16#04] -> "normalMGCExecutionTime"; + [16#00, 16#05] -> "MGProvisionalResponseTimerValue"; + [16#00, 16#06] -> "MGCProvisionalResponseTimerValue"; + [16#00, 16#07] -> "MGCOriginatedPendingLimit"; + [16#00, 16#08] -> "MGOriginatedPendingLimit" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: tonegen - Tone Generator Package +%% Version: 2 +%% Extends: None +%% Purpose: This package defines signals to generate audio tones. +%% This package does not specify parameter values. It is +%% intended to be extendable. Generally, tones are defined +%% as an individual signal with a parameter, ind, +%% representing "interdigit" time delay, and a tone id to +%% be used with playtones. A tone id should be kept +%% consistent with any tone generation for the same tone. +%% MGs are expected to be provisioned with the characteristics +%% of appropriate tones for the country in which the MG is located. +%%---------------------------------------------------------------------- + +capabilities_tonegen() -> + [ + {signal, "pt"} + ]. + +encode_tonegen(signal, Item) -> + case Item of + "pt" -> [16#00, 16#01] + end; + +encode_tonegen({signal_parameter, Item}, SubItem) -> + case Item of + "pt" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "ind" -> [16#00, 16#02]; + "btd" -> [16#00, 16#03] + end + end. + +decode_tonegen(signal, Item) -> + case Item of + [16#00, 16#01] -> "pt" + end; + +decode_tonegen({signal_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event: pt + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#02] -> "ind"; + [16#00, 16#03] -> "btd" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: tonedet - Tone Detection Package +%% Version: 1 +%% Extends: None +%% Purpose: This Package defines events for audio tone detection. +%% Tones are selected by name (tone id). MGs are expected +%% to be provisioned with the characteristics of appropriate +%% tones for the country in which the MG is located. +%% +%% This package does not specify parameter values. +%% It is intended to be extendable. +%%---------------------------------------------------------------------- + +capabilities_tonedet() -> + [ + {event, "std"}, + {event, "etd"}, + {event, "ltd"} + ]. + +encode_tonedet(event, Item) -> + case Item of + "std" -> [16#00, 16#01]; + "etd" -> [16#00, 16#02]; + "ltd" -> [16#00, 16#03] + end; + +encode_tonedet({event_parameter, Item}, SubItem) -> + case Item of + "std" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "tid" -> [16#00, 16#03] + end; + "etd" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "tid" -> [16#00, 16#03]; + "dur" -> [16#00, 16#02] + end; + "ltd" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "dur" -> [16#00, 16#02]; + "tid" -> [16#00, 16#03] + end + end. + +decode_tonedet(event, Item) -> + case Item of + [16#00, 16#01] -> "std"; + [16#00, 16#02] -> "etd"; + [16#00, 16#03] -> "ltd" + end; + +decode_tonedet({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event std + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#03] -> "tid" + end; + [16#00, 16#02] -> % Event etd + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#03] -> "tid"; + [16#00, 16#02] -> "dur" + end; + [16#00, 16#03] -> % Event ltd + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#02] -> "dur"; + [16#00, 16#03] -> "tid" + end + end. + +%%---------------------------------------------------------------------- +%% Name: dg - Basic DTMF Generator Package +%% Version: 1 +%% Extends: tonegen version 1 +%% Purpose: This package defines the basic DTMF tones as signals and +%% extends the allowed values of parameter tl of playtone +%% in tonegen. +%%---------------------------------------------------------------------- + +capabilities_dg() -> + [ + {signal, "d0"}, + {signal, "d1"}, + {signal, "d2"}, + {signal, "d3"}, + {signal, "d4"}, + {signal, "d5"}, + {signal, "d6"}, + {signal, "d7"}, + {signal, "d8"}, + {signal, "d9"}, + {signal, "ds"}, + {signal, "do"}, + {signal, "da"}, + {signal, "db"}, + {signal, "dc"}, + {signal, "dd"} + ]. + +encode_dg(signal, Item) -> + case Item of + "d0" -> [16#00, 16#10]; + "d1" -> [16#00, 16#11]; + "d2" -> [16#00, 16#12]; + "d3" -> [16#00, 16#13]; + "d4" -> [16#00, 16#14]; + "d5" -> [16#00, 16#15]; + "d6" -> [16#00, 16#16]; + "d7" -> [16#00, 16#17]; + "d8" -> [16#00, 16#18]; + "d9" -> [16#00, 16#19]; + "ds" -> [16#00, 16#20]; + "do" -> [16#00, 16#21]; + "da" -> [16#00, 16#1a]; + "db" -> [16#00, 16#1b]; + "dc" -> [16#00, 16#1c]; + "dd" -> [16#00, 16#1d] + end; + +encode_dg({signal_parameter, Item}, SubItem) -> + case Item of + "d0" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d1" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d2" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d3" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d4" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d5" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d6" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d7" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d8" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d9" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "ds" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "do" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "da" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "db" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "dc" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "dd" -> + case SubItem of + "btd" -> [16#00, 16#01] + end + end. + +decode_dg(signal, Item) -> + case Item of + [16#00, 16#10] -> "d0"; + [16#00, 16#11] -> "d1"; + [16#00, 16#12] -> "d2"; + [16#00, 16#13] -> "d3"; + [16#00, 16#14] -> "d4"; + [16#00, 16#15] -> "d5"; + [16#00, 16#16] -> "d6"; + [16#00, 16#17] -> "d7"; + [16#00, 16#18] -> "d8"; + [16#00, 16#19] -> "d9"; + [16#00, 16#20] -> "ds"; + [16#00, 16#21] -> "do"; + [16#00, 16#1a] -> "da"; + [16#00, 16#1b] -> "db"; + [16#00, 16#1c] -> "dc"; + [16#00, 16#1d] -> "dd" + end; + +decode_dg({signal_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#10] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#11] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#12] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#13] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#14] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#15] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#16] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#17] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#18] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#19] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#20] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#21] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1a] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1b] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1c] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1d] -> + case SubItem of + [16#00, 16#01] -> "btd" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: dd - DTMF detection Package +%% Version: 1 +%% Extends: tonedet version 1 +%% Purpose: This package defines the basic DTMF tones detection. +%% Tones are selected by name (tone id). MGs are expected +%% to be provisioned with the characteristics of appropriate +%% tones for the country in which the MG is located. +%% +%% This package does not specify parameter values. +%% It is intended to be extendable. +%% +%% Additional tone id values are all tone ids described in package dg +%% (basic DTMF generator package). +%% +%% The following table maps DTMF events to digit map symbols as described +%% in section 7.1.14. +%% +%% _________________________________ +%% | DTMF Event | Symbol | +%% | d0 | "0" | +%% | d1 | "1" | +%% | d2 | "2" | +%% | d3 | "3" | +%% | d4 | "4" | +%% | d5 | "5" | +%% | d6 | "6" | +%% | d7 | "7" | +%% | d8 | "8" | +%% | d9 | "9" | +%% | da | "A" or "a"| +%% | db | "B" or "b"| +%% | dc | "C" or "c"| +%% | dd | "D" or "d"| +%% | ds | "E" or "e"| +%% | do | "F" or "f"| +%% |___________________|____________| +%% +%%---------------------------------------------------------------------- + +capabilities_dd() -> + [ + {event, "ce"}, + {event, "d0"}, + {event, "d1"}, + {event, "d2"}, + {event, "d3"}, + {event, "d4"}, + {event, "d5"}, + {event, "d6"}, + {event, "d7"}, + {event, "d8"}, + {event, "d9"}, + {event, "ds"}, + {event, "do"}, + {event, "da"}, + {event, "db"}, + {event, "dc"}, + {event, "dd"} + ]. + +encode_dd(event, Item) -> + case Item of + "ce" -> [16#00, 16#04]; + "d0" -> [16#00, 16#10]; + "d1" -> [16#00, 16#11]; + "d2" -> [16#00, 16#12]; + "d3" -> [16#00, 16#13]; + "d4" -> [16#00, 16#14]; + "d5" -> [16#00, 16#15]; + "d6" -> [16#00, 16#16]; + "d7" -> [16#00, 16#17]; + "d8" -> [16#00, 16#18]; + "d9" -> [16#00, 16#19]; + "ds" -> [16#00, 16#20]; + "do" -> [16#00, 16#21]; + "da" -> [16#00, 16#1a]; + "db" -> [16#00, 16#1b]; + "dc" -> [16#00, 16#1c]; + "dd" -> [16#00, 16#1d] + end; + +encode_dd({event_parameter, Item}, SubItem) -> + case Item of + "ce" -> + case SubItem of + "ds" -> [16#00, 16#01]; + "Meth" -> [16#00, 16#03] + end; + "d0" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d1" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d2" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d3" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d4" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d5" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d6" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d7" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d8" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d9" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "ds" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "do" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "da" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "db" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "dc" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "dd" -> + case SubItem of + "btd" -> [16#00, 16#01] + end + end. + +decode_dd(event, Item) -> + case Item of + [16#00, 16#04] -> "ce"; + [16#00, 16#10] -> "d0"; + [16#00, 16#11] -> "d1"; + [16#00, 16#12] -> "d2"; + [16#00, 16#13] -> "d3"; + [16#00, 16#14] -> "d4"; + [16#00, 16#15] -> "d5"; + [16#00, 16#16] -> "d6"; + [16#00, 16#17] -> "d7"; + [16#00, 16#18] -> "d8"; + [16#00, 16#19] -> "d9"; + [16#00, 16#20] -> "ds"; + [16#00, 16#21] -> "do"; + [16#00, 16#1a] -> "da"; + [16#00, 16#1b] -> "db"; + [16#00, 16#1c] -> "dc"; + [16#00, 16#1d] -> "dd" + end; + +decode_dd({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#04] -> % Event ce + case SubItem of + [16#00, 16#01] -> "ds"; + [16#00, 16#03] -> "Meth" + end; + [16#00, 16#10] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#11] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#12] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#13] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#14] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#15] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#16] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#17] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#18] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#19] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#20] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#21] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1a] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1b] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1c] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1d] -> + case SubItem of + [16#00, 16#01] -> "btd" + end + end. + +%%---------------------------------------------------------------------- +%% Name: cg - Call Progress Tones Generator Package +%% Version: 1 +%% Extends: tonegen version 1 +%% Purpose: This package defines the basic call progress tones as signals +%% and extends the allowed values of the tl parameter of +%% playtone in tonegen. +%%---------------------------------------------------------------------- + +capabilities_cg() -> + [ + {signal, "dt"}, + {signal, "rt"}, + {signal, "bt"}, + {signal, "ct"}, + {signal, "sit"}, + {signal, "wt"}, + {signal, "prt"}, + {signal, "cw"}, + {signal, "cr"} + ]. + + +encode_cg(Scope, Item) -> + case Scope of + signal -> + case Item of + "dt" -> [16#00, 16#30]; + "rt" -> [16#00, 16#31]; + "bt" -> [16#00, 16#32]; + "ct" -> [16#00, 16#33]; + "sit" -> [16#00, 16#34]; + "wt" -> [16#00, 16#35]; + "prt" -> [16#00, 16#36]; + "cw" -> [16#00, 16#37]; + "cr" -> [16#00, 16#38] + end + end. + +decode_cg(Scope, Item) -> + case Scope of + signal -> + case Item of + [16#00, 16#30] -> "dt"; + [16#00, 16#31] -> "rt"; + [16#00, 16#32] -> "bt"; + [16#00, 16#33] -> "ct"; + [16#00, 16#34] -> "sit"; + [16#00, 16#35] -> "wt"; + [16#00, 16#36] -> "prt"; + [16#00, 16#37] -> "cw"; + [16#00, 16#38] -> "cr" + end + end. + +%%---------------------------------------------------------------------- +%% Name: cd - Call Progress Tones Detection Package +%% Version: 1 +%% Extends: tonedet version 1 +%% Purpose: This package defines the basic call progress detection tones. +%% This Package extends the possible values of tone id +%% in the "start tone detected", "end tone detected" and +%% "long tone detected" events. +%% Additional values +%% tone id values are defined for start tone detected, +%% end tone detected and long tone detected with +%% the same values as those in package cg (call +%% progress tones generation package). +%% +%% The required set of tone ids corresponds to Recommendation E.180/Q.35 +%% [ITU-T Recommendation E.180/Q.35 (1998)]. See Recommendation E.180/Q.35 +%% for definition of the meanings of these tones. +%%---------------------------------------------------------------------- + +capabilities_cd() -> + [ + {event, "dt"}, + {event, "rt"}, + {event, "bt"}, + {event, "ct"}, + {event, "sit"}, + {event, "wt"}, + {event, "prt"}, + {event, "cw"}, + {event, "cr"} + ]. + + +encode_cd(Scope, Item) -> + case Scope of + event -> + case Item of + "dt" -> [16#00, 16#30]; + "rt" -> [16#00, 16#31]; + "bt" -> [16#00, 16#32]; + "ct" -> [16#00, 16#33]; + "sit"-> [16#00, 16#34]; + "wt" -> [16#00, 16#35]; + "prt"-> [16#00, 16#36]; + "cw" -> [16#00, 16#37]; + "cr" -> [16#00, 16#38] + end + end. + +decode_cd(Scope, Item) -> + case Scope of + event -> + case Item of + [16#00, 16#30] -> "dt"; + [16#00, 16#31] -> "rt"; + [16#00, 16#32] -> "bt"; + [16#00, 16#33] -> "ct"; + [16#00, 16#34] -> "sit"; + [16#00, 16#35] -> "wt"; + [16#00, 16#36] -> "prt"; + [16#00, 16#37] -> "cw"; + [16#00, 16#38] -> "cr" + end + end. + +%%---------------------------------------------------------------------- +%% Name: al - Analog Line Supervision Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines events and signals for an analog line. +%%---------------------------------------------------------------------- + +capabilities_al() -> + [ + {event, "on"}, + {event, "of"}, + {event, "fl"}, + {signal, "ri"} + ]. + +encode_al(event, Item) -> + ?d("encode_al(event) -> entry with" + "~n Item: ~p", [Item]), + case Item of + "on" -> [16#00, 16#04]; + "of" -> [16#00, 16#05]; + "fl" -> [16#00, 16#06] + end; + +encode_al({event_parameter, Item}, SubItem) -> + ?d("encode_al({event_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + "on" -> + case SubItem of + "strict" -> [16#00, 16#01]; + "init" -> [16#00, 16#02] + end; + "of" -> + case SubItem of + "strict" -> [16#00, 16#01]; + "init" -> [16#00, 16#02] + end; + "fl" -> + case SubItem of + "mindur" -> [16#00, 16#04]; + "maxdur" -> [16#00, 16#05] + end + end; + +encode_al(signal, Item) -> + ?d("encode_al(signal) -> entry with" + "~n Item: ~p", [Item]), + case Item of + "ri" -> [16#00, 16#02] + end; + +encode_al({signal_parameter, Item}, SubItem) -> + ?d("encode_al({signal_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + "ri" -> + case SubItem of + "cad" -> [16#00, 16#06]; + "freq" -> [16#00, 16#07] + end + end. + +decode_al(event, SubItem) -> + ?d("decode_al(event) -> entry with" + "~n SubItem: ~p", [SubItem]), + case SubItem of + [16#00, 16#04] -> "on"; + [16#00, 16#05] -> "of"; + [16#00, 16#06] -> "fl" + end; + +decode_al({event_parameter, Item}, SubItem) -> + ?d("decode_al({event_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + [16#00,16#04] -> %% Event: on + case SubItem of + [16#00, 16#01] -> "strict"; + [16#00, 16#02] -> "init" + end; + [16#00,16#05] -> %% Event: of + case SubItem of + [16#00, 16#01] -> "strict"; + [16#00, 16#02] -> "init" + end; + [16#00,16#06] -> %% Event: fl + case SubItem of + [16#00, 16#04] -> "mindur"; + [16#00, 16#05] -> "maxdur" + end + end; + +decode_al(signal, SubItem) -> + ?d("decode_al(signal) -> entry with" + "~n SubItem: ~p", [SubItem]), + case SubItem of + [16#00, 16#02] -> "ri" + end; + +decode_al({signal_parameter, Item}, SubItem) -> + ?d("decode_al({signal_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + [16#00,16#02] -> %% Event: ri + case SubItem of + [16#00, 16#06] -> "cad"; + [16#00, 16#07] -> "freq" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: ct - Basic Continuity Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines events and signals for continuity test. +%% The continuity test includes provision of either a loopback +%% or transceiver functionality. +%%---------------------------------------------------------------------- + +capabilities_ct() -> + [ + {event, "cmp"}, + {signal, "ct"}, + {signal, "rsp"} + ]. + +encode_ct(event, Item) -> + case Item of + "cmp" -> [16#00, 16#05] + end; +encode_ct({event_parameter, Item}, SubItem) -> + case Item of + "cmp" -> + case SubItem of + "res" -> [16#00, 16#08] + end + end; +encode_ct(signal, Item) -> + case Item of + "ct" -> [16#00, 16#03]; + "rsp" -> [16#00, 16#04] + end. + +decode_ct(event, Item) -> + case Item of + [16#00, 16#05] -> "cmp" + end; +decode_ct({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#05] -> % Event cmp + case SubItem of + [16#00, 16#08] -> "res" + end + end; +decode_ct(signal, Item) -> + case Item of + [16#00, 16#03] -> "ct"; + [16#00, 16#04] -> "rsp" + end. + +%%---------------------------------------------------------------------- +%% Name: nt - Network Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines properties of network terminations +%% independent of network type. +%%---------------------------------------------------------------------- + +capabilities_nt() -> + [ + {property, "jit"}, + {event, "netfail"}, + {event, "qualert"}, + {statistics, "dur"}, + {statistics, "os"}, + {statistics, "or"} + ]. + +encode_nt(property, Item) -> + case Item of + "jit" -> [16#00, 16#07] + end; +encode_nt(event, Item) -> + case Item of + "netfail" -> [16#00, 16#05]; + "qualert" -> [16#00, 16#06] + end; +encode_nt({event_parameter, Item}, SubItem) -> + case Item of + "netfail" -> + case SubItem of + "cs" -> [16#00, 16#01] + end; + "qualert" -> + case SubItem of + "th" -> [16#00, 16#01] + end + end; +encode_nt(statistics, Item) -> + case Item of + "dur" -> [16#00, 16#01]; + "os" -> [16#00, 16#02]; + "or" -> [16#00, 16#03] + end. + +decode_nt(property, Item) -> + case Item of + [16#00, 16#07] -> "jit" + end; +decode_nt(event, Item) -> + case Item of + [16#00, 16#05] -> "netfail"; + [16#00, 16#06] -> "qualert" + end; +decode_nt({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#05] -> % Event netfail + case SubItem of + [16#00, 16#01] -> "cs" + end; + [16#00, 16#06] -> % Event qualert + case Item of + [16#00, 16#01] -> "th" + end + end; +decode_nt(statistics, Item) -> + case Item of + [16#00, 16#01] -> "dur"; + [16#00, 16#02] -> "os"; + [16#00, 16#03] -> "or" + end. + +%%---------------------------------------------------------------------- +%% Name: rtp - RTP Package +%% Version: 1 +%% Extends: nt version 1 +%% Purpose: This package is used to support packet based multimedia +%% data transfer by means of the Real-time Transport Protocol +%% (RTP) [RFC 1889]. +%%---------------------------------------------------------------------- + +capabilities_rtp() -> + [ + {event, "pltrans"}, + {statistics, "ps"}, + {statistics, "pr"}, + {statistics, "pl"}, + {statistics, "jit"}, + {statistics, "delay"} + ]. + +encode_rtp(event, Item) -> + case Item of + "pltrans" -> [16#00, 16#01] + end; +encode_rtp({event_parameter, Item}, SubItem) -> + case Item of + "pltrans" -> + case SubItem of + "rtppltype" -> [16#00, 16#01] + end + end; +encode_rtp(statistics, Item) -> + case Item of + "ps" -> [16#00, 16#04]; + "pr" -> [16#00, 16#05]; + "pl" -> [16#00, 16#06]; + "jit" -> [16#00, 16#07]; + "delay" -> [16#00, 16#08] + end. + +decode_rtp(event, Item) -> + case Item of + [16#00, 16#01] -> "pltrans" + end; +decode_rtp({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event pltrans + case SubItem of + [16#00, 16#01] -> "rtppltype" + end + end; +decode_rtp(statistics, Item) -> + case Item of + [16#00, 16#04] -> "ps"; + [16#00, 16#05] -> "pr"; + [16#00, 16#06] -> "pl"; + [16#00, 16#07] -> "jit"; + [16#00, 16#08] -> "delay" + end. + + +%%---------------------------------------------------------------------- +%% Name: tdmc - TDM Circuit Package +%% Version: 1 +%% Extends: nt version 1 +%% Purpose: This package is used to support TDM circuit terminations. +%%---------------------------------------------------------------------- + +capabilities_tdmc() -> + [ + {property, "ec"}, + {property, "gain"} + ]. + +encode_tdmc(Scope, Item) -> + case Scope of + property -> + case Item of + "ec" -> [16#00, 16#08]; + "gain" -> [16#00, 16#0a] + end + end. + +decode_tdmc(Scope, Item) -> + case Scope of + property -> + case Item of + [16#00, 16#08] -> "ec"; + [16#00, 16#0a] -> "gain" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: swb - SwitchBoard Package +%% Version: 1 +%% Extends: none +%% Purpose: This package is used to support SwitchBoard specials +%%---------------------------------------------------------------------- + +capabilities_swb() -> + [ + {statistics, "fs"}, % Free slots + {statistics, "as"} % Allocated slots + ]. + +encode_swb(Scope, Item) -> + case Scope of + statistics -> + case Item of + "fs" -> [16#00, 16#00]; + "as" -> [16#00, 16#01] + end + end. + +decode_swb(Scope, Item) -> + case Scope of + statistics -> + case Item of + [16#00, 16#00] -> "fs"; + [16#00, 16#01] -> "as" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: native - Pseudo package +%% Version: 1 +%% Extends: None +%% Purpose: Native tags for media stream properties +%% +%% Parameters for Local descriptors and Remote descriptors are +%% specified as tag-value pairs if binary encoding is used for the +%% protocol. This annex contains the property names (PropertyID), the +%% tags (Property Tag), type of the property (Type) and the values +%% (Value).Values presented in the Value field when the field contains +%% references shall be regarded as "information". The reference +%% contains the normative values. If a value field does not contain a +%% reference then the values in that field can be considered as +%% "normative". +%% +%% Tags are given as hexadecimal numbers in this annex. When setting +%% the value of a property, a MGC may underspecify the value according +%% to one of the mechanisms specified in section 7.1.1. +%% +%% For type "enumeration" the value is represented by the value in brack- +%% ets, e.g., Send(0), Receive(1). +%%---------------------------------------------------------------------- +%% +%% C.6. IP +%% +%% ________________________________________________________________ +%% | PropertyID| Tag | Type | Value | +%% | IPv4 | 6001 | 32 BITS | Ipv4Address | +%% | IPv6 | 6002 | 128 BITS | IPv6 Address | +%% | Port | 6003 | Unsigned Int| Port | +%% | Porttype | 6004 | Enumerated | TCP(0),UDP(1),SCTP(2)| +%% |___________|____________|______________|_______________________| +%% +%% +%% C.11. SDP Equivalents +%% +%% ______________________________________________________________ +%% | PropertyID| Tag | Type | Value | +%% | SDP_V | B001| STRING| Protocol Version | +%% | SDP_O | B002| STRING| Owner-creator and session ID | +%% | SDP_S | B003| STRING| Sesson name | +%% | SDP_I | B004| STRING| Session identifier | +%% | SDP_U | B005| STRING| URI of descriptor | +%% | SDC_E | B006| STRING| email address | +%% | SDP_P | B007| STRING| phone number | +%% | SDP_C | B008| STRING| Connection information | +%% | SDP_B | B009| STRING| Bandwidth Information | +%% | SDP_Z | B00A| STRING| time zone adjustment | +%% | SDP_K | B00B| STRING| Encryption Key | +%% | SDP_A | B00C| STRING| Zero or more session attributes| +%% | SDP_T | B00D| STRING| Active Session Time | +%% | SDP_R | B00E| STRING| Zero or more repeat times | +%% | SDP_M | B00F| STRING| Media name and transport addr | +%% | | | | Reference: IETF RFC 2327 | +%% |___________|______|________|_________________________________| +%% +%%---------------------------------------------------------------------- + +capabilities_native() -> + [ + %% C.6. IP + {property, "IPv4"}, + {property, "IPv6"}, + {property, "Port"}, + {property, "Porttype"}, + + %% C.11. SDP Equivalents + {property, "v"}, + {property, "o"}, + {property, "s"}, + {property, "i"}, + {property, "u"}, + {property, "e"}, + {property, "p"}, + {property, "c"}, + {property, "b"}, + {property, "z"}, + {property, "k"}, + {property, "a"}, + {property, "t"}, + {property, "r"}, + {property, "m"} + ]. + +encode_native(Scope, Item) -> + case Scope of + property -> + case Item of + %% IP + "IPv4" -> [16#60, 16#01]; + "IPv6" -> [16#60, 16#02]; + "Port" -> [16#60, 16#03]; + "Porttype" -> [16#60, 16#04]; + + %% SDP + "v" -> [16#b0, 16#01]; + "o" -> [16#b0, 16#02]; + "s" -> [16#b0, 16#03]; + "i" -> [16#b0, 16#04]; + "u" -> [16#b0, 16#05]; + "e" -> [16#b0, 16#06]; + "p" -> [16#b0, 16#07]; + "c" -> [16#b0, 16#08]; + "b" -> [16#b0, 16#09]; + "z" -> [16#b0, 16#0a]; + "k" -> [16#b0, 16#0b]; + "a" -> [16#b0, 16#0c]; + "t" -> [16#b0, 16#0d]; + "r" -> [16#b0, 16#0e]; + "m" -> [16#b0, 16#0f] + end + end. + +decode_native(Scope, [Type, Item]) -> + case Scope of + property -> + case Type of + 16#60 -> + case Item of + 16#01 -> "IPv4"; + 16#02 -> "IPv6"; + 16#03 -> "Port"; + 16#04 -> "Porttype" + end; + + 16#b0 -> + case Item of + 16#01 -> "v"; + 16#02 -> "o"; + 16#03 -> "s"; + 16#04 -> "i"; + 16#05 -> "u"; + 16#06 -> "e"; + 16#07 -> "p"; + 16#08 -> "c"; + 16#09 -> "b"; + 16#0a -> "z"; + 16#0b -> "k"; + 16#0c -> "a"; + 16#0d -> "t"; + 16#0e -> "r"; + 16#0f -> "m" + end + end + end. + +%% ------------------------------------------------------------------- + +% error(Reason) -> +% erlang:error(Reason). + diff --git a/lib/megaco/src/binary/megaco_binary_name_resolver_prev3c.erl b/lib/megaco/src/binary/megaco_binary_name_resolver_prev3c.erl new file mode 100644 index 0000000000..d08231caac --- /dev/null +++ b/lib/megaco/src/binary/megaco_binary_name_resolver_prev3c.erl @@ -0,0 +1,2004 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Handle meta data about packages +%%---------------------------------------------------------------------- + +-module(megaco_binary_name_resolver_prev3c). + +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). +-include_lib("megaco/src/app/megaco_internal.hrl"). + + +-define(LOWER(Char), + if + Char >= $A, Char =< $Z -> + Char - ($A - $a); + true -> + Char + end). + +-export([packages/0, + capabilities/0, + capabilities/1, + decode_name/3, + encode_name/3 + ]). + +encode_name(Config, term_id, TermId) -> + case megaco:encode_binary_term_id(Config, TermId) of + {ok, TermId2} -> + TermId2; + {error, Reason} -> + exit({bad_term_id, TermId, Reason}) + end; +encode_name(_Config, Scope, Item) -> + ?d("encode_name(~p) -> entry with" + "~n Item: ~p", [Scope, Item]), + encode(Scope, Item). + +decode_name(Config, term_id, TermId) -> + case megaco:decode_binary_term_id(Config, TermId) of + {ok, TermId2} -> + TermId2; + {error, Reason} -> + exit({bad_term_id, TermId, Reason}) + end; +decode_name(_Config, Scope, Item) -> + ?d("decode_name(~p) -> entry with" + "~n Item: ~p", [Scope, Item]), + decode(Scope, Item). + + + +%%---------------------------------------------------------------------- +%% 12.1.1 Package +%% +%% Overall description of the package, specifying: +%% +%% Package Name: only descriptive +%% +%% PackageID: is an identifier +%% +%% Description: is a description of the package +%% +%% Version: +%% +%% A new version of a package can only add additional Properties, +%% Events, Signals, Statistics and new possible values for an +%% existing parameter described in the original package. No +%% deletions or modifications shall be allowed. A version is an +%% integer in the range from 1 to 99. +%% +%% Designed to be extended only (Optional): Yes +%% +%% This indicates that the package has been expressly designed to +%% be extended by others, not to be directly referenced. For +%% example, the package may not have any function on its own or be +%% nonsensical on its own. The MG SHOULD NOT publish this PackageID +%% when reporting packages. +%% +%% Extends: existing package Descriptor +%% +%% A package may extend an existing package. The version of the +%% original package must be specified. When a package extends +%% another package it shall only add additional Properties, Events, +%% Signals, Statistics and new possible values for an existing +%% parameter described in the original package. An extended package +%% shall not redefine or overload an identifier defined in the +%% original package and packages it may have extended (multiple +%% levels of extension). Hence, if package B version 1 extends +%% package A version 1, version 2 of B will not be able to extend +%% the A version 2 if A version 2 defines a name already in B +%% version 1. If the package does not extend another package, it +%% shall specify "none". +%% +%% +%% 12.1.2 Properties +%% +%% Properties defined by the package, specifying: +%% +%% Property Name: only descriptive +%% +%% PropertyID: is an identifier +%% +%% Description: is a description of the function of the property +%% +%% Type: One of: +%% +%% Boolean +%% +%% String: UTF-8 string +%% +%% Octet String: A number of octets. See Annex A and B.3 for +%% encoding +%% +%% Integer: 4 byte signed integer +%% +%% Double: 8 byte signed integer +%% +%% Character: unicode UTF-8 encoding of a single letter. +%% Could be more than one octet. +%% +%% Enumeration: one of a list of possible unique values (see 12.3) +%% +%% Sub-list: a list of several values from a list. +%% The type of sub-list SHALL also be specified. +%% The type shall be chosen from the types specified in +%% this section (with the exception of sub-list). For +%% example, Type: sub-list of enumeration. The encoding +%% of sub-lists is specified in Annexes A and B.3. +%% +%% Possible values: +%% +%% A package MUST specify either a specific set of values or a +%% description of how values are determined. A package MUST also +%% specify a default value or the default behaviour when the value +%% is omitted from its descriptor. For example, a package may +%% specify that procedures related to the property are suspended +%% when its value is omitted. +%% +%% Default: +%% +%% A default value (but not procedures) may be specified as +%% provisionable. +%% +%% Defined in: +%% +%% Which H.248.1 descriptor the property is defined in. +%% LocalControl is for stream-dependent properties. +%% TerminationState is for stream-independent properties. +%% ContextAttribute is for properties that affect the context as +%% a whole, i.e., mixing properties. These are expected to be the +%% most common cases, but it is possible for properties to be +%% defined in other descriptors. Context properties MUST be defined +%% in the ContextAttribute descriptor. +%% +%% Characteristics: Read/Write or both, and (optionally), global: +%% +%% Indicates whether a property is read-only, or read-write, and +%% if it is global. If Global is omitted, the property is not +%% global. If a property is declared as global, the value of the +%% property is shared by all Terminations realizing the package. +%% If a context property is declared as global, the property is +%% shared by all contexts realizing the package. +%% +%% +%% 12.1.3 Events +%% +%% Events defined by the package, specifying: +%% +%% Event name: only descriptive +%% +%% EventID: is an identifier +%% +%% Description: a description of the function of the event +%% +%% EventsDescriptor Parameters: +%% +%% Parameters used by the MGC to configure the event, and found in +%% the EventsDescriptor. See 12.2. If there are no parameters for +%% the Events Descriptor, then "none" shall be specified. +%% +%% ObservedEventsDescriptor Parameters: +%% +%% Parameters returned to the MGC in Notify requests and in replies +%% to command requests from the MGC that audit +%% ObservedEventsDescriptor, and found in the +%% ObservedEventsDescriptor. See 12.2. If there are no parameters +%% for the ObservedEvents Descriptor, then �none� shall be specified. +%% +%% +%% 12.1.4 Signals +%% +%% Signals defined by the package, specifying: +%% +%% Signal Name: only descriptive +%% +%% SignalID: is an identifier. SignalID is used in a SignalsDescriptor +%% +%% Description: a description of the function of the signal +%% +%% SignalType: one of: +%% +%% OO (On/Off) +%% +%% TO (TimeOut) +%% +%% BR (Brief) +%% +%% NOTE -�SignalType may be defined such that it is dependent on +%% the value of one or more parameters. The package MUST specify a +%% default signal type. If the default type is TO, the package MUST +%% specify a default duration which may be provisioned. A default +%% duration is meaningless for BR. +%% +%% Duration: in hundredths of seconds +%% +%% Additional Parameters: see 12.2 +%% +%% +%% 12.1.5 Statistics +%% +%% Statistics defined by the package, specifying: +%% +%% Statistic name: only descriptive +%% +%% StatisticID: is an identifier +%% +%% StatisticID is used in a StatisticsDescriptor +%% +%% Description: a description of the statistic +%% +%% Type: One of: +%% +%% Boolean +%% +%% String: UTF-8 string +%% +%% Octet String: A number of octets. +%% See Annex A and Annex B.3 for encoding +%% +%% Integer: 4 byte signed integer +%% +%% Double: 8 byte signed integer +%% +%% Character: Unicode UTF-8 encoding of a single letter. +%% Could be more than one octet. +%% +%% Enumeration: One of a list of possible unique values (See 12.3) +%% +%% Sub-list: A list of several values from a list. +%% The type of sub-list SHALL also be specified. +%% The type shall be chosen from the types specified in +%% this section (with the exception of sub-list). +%% For example, Type: sub-list of enumeration. +%% The encoding of sub-lists is specified in Annexes A +%% and B.3. +%% +%% Possible Values: +%% +%% A package must indicate the unit of measure, e.g. milliseconds, +%% packets, either here or along with the type above, as well as +%% indicating any restriction on the range. +%% +%% Level: Specify if the statistic can be kept at the Termination +%% level, Stream level or Either. +%% +%% +%% 12.1.6 Error Codes +%% +%% If the package does not define any error codes, this section may be omitted. +%% Otherwise, it describes error codes defined by the package, specifying: +%% +%% Error Code #: The error code number. +%% +%% Name: Name of the error +%% +%% Definition: A description of the error code. +%% +%% Error Text in the Error Descriptor: +%% +%% A description of what text to return in the Error Descriptor. +%% +%% Comment: Any further comments on the use of the error code. +%% +%% +%% 12.1.7 Procedures +%% +%% Additional guidance on the use of the package. +%% +%% +%% 12.2 Guidelines to defining parameters to events and signals +%% +%% Parameter Name: only descriptive +%% +%% ParameterID: is an identifier. The textual ParameterID of +%% parameters to Events and Signals shall not start with "EPA" and +%% "SPA", respectively. The textual ParameterID shall also not be +%% "ST", "Stream", "SY", "SignalType", "DR", "Duration", "NC", +%% "NotifyCompletion", "KA", "KeepActive", "EB", "Embed", "DM", +%% "DigitMap", "DI", "Direction", "RQ" or "RequestID". +%% +%% Description: a description of the function of the parameter. +%% +%% Type: One of: +%% +%% Boolean +%% +%% String: UTF-8 octet string +%% +%% Octet String: A number of octets. See Annex A and B.3 for +%% encoding +%% +%% Integer: 4-octet signed integer +%% +%% Double: 8-octet signed integer +%% +%% Character: Unicode UTF-8 encoding of a single letter. Could be +%% more than one octet. +%% +%% Enumeration: one of a list of possible unique values (see 12.3) +%% +%% Sub-list: a list of several values from a list (not supported +%% for statistics). The type of sub-list SHALL also be +%% specified The type shall be chosen from the types +%% specified in this section (with the exception of +%% sub-list). For example, Type: sub-list of enumeration. +%% The encoding of sub-lists is specified in Annex A +%% and B.3. +%% +%% Optional: Yes/No +%% +%% Describes if the parameter may be omitted from the signal or +%% event. +%% +%% Possible values: +%% +%% A package MUST specify either a specific set of values or a +%% description of how values are determined. A package MUST +%% also specify a default value or the default behavior when the +%% value is omitted from its descriptor. For example, a package +%% may specify that procedures related to the parameter are +%% suspended when its value is omitted. +%% +%% Default: +%% +%% A default value (but not procedures) may be specified as +%% provisionable. +%% +%% +%% 12.3 Lists +%% +%% Possible values for parameters include enumerations. Enumerations may be +%% defined in a list. It is recommended that the list be IANA registered so +%% that packages that extend the list can be defined without concern for +%% conflicting names. +%% +%% +%% 12.4 Identifiers +%% +%% Identifiers in text encoding shall be strings of up to 64 characters, +%% containing no spaces, starting with an alphabetic character and consisting +%% of alphanumeric characters and/or digits, and possibly including the +%% special character underscore ("_"). +%% +%% Identifiers in binary encoding are 2 octets long. +%% +%% Both text and binary values shall be specified for each identifier, +%% including identifiers used as values in enumerated types. +%% +%% +%% 12.5 Package registration +%% +%% A package can be registered with IANA for interoperability reasons. See +%% clause 14 for IANA considerations. +%% +%%---------------------------------------------------------------------- + +capabilities() -> + [{P, capabilities(P)} || P <- packages()]. + +%% -record(property, {name, type, values, defined_in, characteristics}). + +%%---------------------------------------------------------------------- +%% List all known packages +%% 'native' and 'all' are not real packages +%%---------------------------------------------------------------------- + +packages() -> + [ + "g", % Generic + "root", % Base Root Package + "tonegen", % Tone Generator Package + "tonedet", % Tone Detection Package + "dg", % Basic DTMF Generator Package + "dd", % DTMF detection Package + "cg", % Call Progress Tones Generator Package + "cd", % Call Progress Tones Detection Package + "al", % Analog Line Supervision Package + "ct", % Basic Continuity Package + "nt", % Network Package + "rtp", % RTP Package + "swb", % SwitchBoard Package + "tdmc", % TDM Circuit Package + "" % Native pseudo package + ]. + +%%---------------------------------------------------------------------- +%% List all matching capabilities +%%---------------------------------------------------------------------- + +capabilities(Package) -> + case Package of + "g" -> capabilities_g(); + "root" -> capabilities_root(); + "tonegen" -> capabilities_tonegen(); + "tonedet" -> capabilities_tonedet(); + "dg" -> capabilities_dg(); + "dd" -> capabilities_dd(); + "cg" -> capabilities_cg(); + "cd" -> capabilities_cd(); + "al" -> capabilities_al(); + "ct" -> capabilities_ct(); + "nt" -> capabilities_nt(); + "rtp" -> capabilities_rtp(); + "swb" -> capabilities_swb(); + "tdmc" -> capabilities_tdmc(); + "" -> capabilities_native() + end. + +%%---------------------------------------------------------------------- +%% Decode package name to internal form +%% Scope ::= property | event | signal | statistics +%%---------------------------------------------------------------------- + +decode(mid, Package) -> + decode_mid(Package); +decode(package, Package) -> + decode_package(Package); +decode(profile, Package) -> + decode_profile(Package); +decode(dialplan, Dialplan) -> + decode_dialplan(Dialplan); +decode(Scope, [A, B | Item]) when is_atom(Scope) -> + ?d("decode(~p) -> entry with" + "~n A: ~p" + "~n B: ~p" + "~n Item: ~p", [Scope, A, B, Item]), + case decode_package([A, B]) of + "" -> + ?d("decode -> \"no\" package",[]), + decode_item(Scope, [A, B], Item); + Package -> + ?d("decode -> Package: ~p", [Package]), + Package ++ "/" ++ decode_item(Scope, [A, B], Item) + end; +decode({Scope, [A, B | Item]}, SubItem) when is_atom(Scope) -> + ?d("decode(~p) -> entry with" + "~n A: ~p" + "~n B: ~p" + "~n Item: ~p" + "~n SubItem: ~p", [Scope, A, B, Item, SubItem]), + decode_item({Scope, Item}, [A, B], SubItem). + +decode_item(Scope, [A, B], Item) -> + ?d("decode_item -> entry",[]), + case A of + 16#00 -> + case B of + 16#01 -> decode_g(Scope, Item); + 16#02 -> decode_root(Scope, Item); + 16#03 -> decode_tonegen(Scope, Item); + 16#04 -> decode_tonedet(Scope, Item); + 16#05 -> decode_dg(Scope, Item); + 16#06 -> decode_dd(Scope, Item); + 16#07 -> decode_cg(Scope, Item); + 16#08 -> decode_cd(Scope, Item); + 16#09 -> decode_al(Scope, Item); + 16#0a -> decode_ct(Scope, Item); + 16#0b -> decode_nt(Scope, Item); + 16#0c -> decode_rtp(Scope, Item); + 16#0d -> decode_tdmc(Scope, Item); + 16#00 -> decode_native(Scope, Item) + end; + 16#fe -> + case B of + %% Proprietary extension + 16#fe -> decode_swb(Scope, Item) + end; + 16#ff -> + case B of + 16#ff when Item =:= [16#ff, 16#ff] -> "*" + end + end. + +decode_package(Package) -> + ?d("decode_package -> entry with" + "~n Package: ~p", [Package]), + [A, B] = Package, + case A of + 16#00 -> + case B of + 16#01 -> "g"; + 16#02 -> "root"; + 16#03 -> "tonegen"; + 16#04 -> "tonedet"; + 16#05 -> "dg"; + 16#06 -> "dd"; + 16#07 -> "cg"; + 16#08 -> "cd"; + 16#09 -> "al"; + 16#0a -> "ct"; + 16#0b -> "nt"; + 16#0c -> "rtp"; + 16#0d -> "tdmc"; + 16#00 -> "" + end; + 16#fe -> + case B of + 16#fe -> "swb" + end; + 16#ff -> + case B of + 16#ff -> "*" + end + end. + +decode_profile([A, B]) -> + case A of + 16#00 -> + case B of + 16#fe -> "resgw"; + _ -> "profile" ++ [A + $0, B + $0] + end; + _ -> + "profile" ++ [A + $0, B + $0] + end. + +decode_dialplan([A, B]) -> + "dialplan" ++ [A + $0, B + $0]. + +decode_mid(Mid) -> + case Mid of + {domainName, DN} -> + Lower = to_lower(DN#'DomainName'.name), + {domainName, DN#'DomainName'{name = Lower}}; + {deviceName, PathName} -> + Lower = to_lower(PathName), + {deviceName, Lower}; + Other -> + Other + end. + +to_lower(Chars) -> + [?LOWER(Char) || Char <- Chars]. + +%%---------------------------------------------------------------------- +%% Encode package name from internal form +%% Scope ::= property | event | signal | statistics +%%---------------------------------------------------------------------- + +encode(mid, Package) -> + encode_mid(Package); +encode(package, Package) -> + encode_package(Package); +encode(profile, Profile) -> + encode_profile(Profile); +encode(dialplan, Dialplan) -> + encode_dialplan(Dialplan); +encode(Scope, PackageItem) when is_atom(Scope) -> + ?d("encode(~p) -> entry with" + "~n PackageItem: ~p", [Scope, PackageItem]), + case string:tokens(PackageItem, [$/]) of + [Package, Item] -> + ?d("encode -> " + "~n Package: ~p" + "~n Item: ~p", [Package, Item]), + encode_package(Package) ++ encode_item(Scope, Package, Item); + [Item] -> + ?d("encode -> Item: ~p", [Item]), + [16#00, 16#00 | encode_native(Scope, Item)] + end; +encode({Scope, PackageItem}, SubItem) when is_atom(Scope) -> + ?d("encode(~p) -> entry with" + "~n PackageItem: ~p" + "~n SubItem: ~p", [Scope, PackageItem, SubItem]), + case string:tokens(PackageItem, [$/]) of + [Package, Item] -> + ?d("encode -> " + "~n Package: ~p" + "~n Item: ~p", [Package, Item]), + encode_item({Scope, Item}, Package, SubItem); + [_Item] -> + ?d("encode -> _Item: ~p", [_Item]), + encode_native(Scope, SubItem) + end. + +encode_item(_Scope, _Package, "*") -> + [16#ff, 16#ff]; +encode_item(Scope, Package, Item) -> + ?d("encode_item(~s) -> entry", [Package]), + case Package of + "g" -> encode_g(Scope, Item); + "root" -> encode_root(Scope, Item); + "tonegen" -> encode_tonegen(Scope, Item); + "tonedet" -> encode_tonedet(Scope, Item); + "dg" -> encode_dg(Scope, Item); + "dd" -> encode_dd(Scope, Item); + "cg" -> encode_cg(Scope, Item); + "cd" -> encode_cd(Scope, Item); + "al" -> encode_al(Scope, Item); + "ct" -> encode_ct(Scope, Item); + "nt" -> encode_nt(Scope, Item); + "rtp" -> encode_rtp(Scope, Item); + "tdmc" -> encode_tdmc(Scope, Item); + "swb" -> encode_swb(Scope, Item) + end. + +encode_package(Package) -> + case Package of + "g" -> [16#00, 16#01]; + "root" -> [16#00, 16#02]; + "tonegen" -> [16#00, 16#03]; + "tonedet" -> [16#00, 16#04]; + "dg" -> [16#00, 16#05]; + "dd" -> [16#00, 16#06]; + "cg" -> [16#00, 16#07]; + "cd" -> [16#00, 16#08]; + "al" -> [16#00, 16#09]; + "ct" -> [16#00, 16#0a]; + "nt" -> [16#00, 16#0b]; + "rtp" -> [16#00, 16#0c]; + "tdmc" -> [16#00, 16#0d]; + "" -> [16#00, 16#00]; + "*" -> [16#ff, 16#ff]; + "swb" -> [16#fe, 16#fe] + end. + +encode_profile(Profile) -> + case Profile of + "resgw" -> + [16#00, 16#fe]; + [$p, $r, $o, $f, $i, $l, $e | Name] -> + case Name of + [A, B] -> [A - $0, B - $0]; + [B] -> [0, B - $0]; + [] -> [0, 0] + end + end. + +encode_dialplan(Dialplan) -> + case Dialplan of + [$d, $i, $a, $l, $p, $l, $a, $n | Name] -> + case Name of + [A, B] -> [A - $0, B - $0]; + [B] -> [0, B - $0]; + [] -> [0, 0] + end + end. + +encode_mid(Mid) -> + Mid. + + +%%---------------------------------------------------------------------- +%% Name: g - Generic +%% Version: 1 +%% Extends: None +%% Purpose: Generic package for commonly encountered items +%%---------------------------------------------------------------------- + +capabilities_g() -> + [ + {event, "cause"}, + {event, "sc"} + ]. + +encode_g(event, Item) -> + case Item of + "cause" -> [16#00, 16#01]; + "sc" -> [16#00, 16#02] + end; + +encode_g({event_parameter, Item}, SubItem) -> + case Item of + "cause" -> + case SubItem of + "Generalcause" -> [16#00, 16#01]; + "Failurecause" -> [16#00, 16#02] + end; + "sc" -> + case SubItem of + "SigID" -> [16#00, 16#01]; + "Meth" -> [16#00, 16#02]; + "SLID" -> [16#00, 16#03]; + "RID" -> [16#00, 16#04] + end + end. + +decode_g(event, Item) -> + case Item of + [16#00, 16#01] -> "cause"; + [16#00, 16#02] -> "sc" + end; + +decode_g({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event: cause + case SubItem of + [16#00, 16#01] -> "Generalcause"; + [16#00, 16#02] -> "Failurecause" + end; + + [16#00, 16#02] -> % Event: sc + case SubItem of + [16#00, 16#01] -> "SigID"; + [16#00, 16#02] -> "Meth"; + [16#00, 16#03] -> "SLID"; + [16#00, 16#04] -> "RID" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: root - Base Root Package +%% Version: 2 +%% Extends: None +%% Purpose: This package defines Gateway wide properties. +%%---------------------------------------------------------------------- + +capabilities_root() -> + [ + {property, "maxNumberOfContexts"}, + {property, "maxTerminationsPerContext"}, + {property, "normalMGExecutionTime"}, + {property, "normalMGCExecutionTime"}, + {property, "MGProvisionalResponseTimerValue"}, + {property, "MGCProvisionalResponseTimerValue"}, + {property, "MGCOriginatedPendingLimit"}, + {property, "MGOriginatedPendingLimit"} + ]. + +encode_root(Scope, Item) -> + case Scope of + property -> + case Item of + "maxNumberOfContexts" -> [16#00, 16#01]; + "maxTerminationsPerContext" -> [16#00, 16#02]; + "normalMGExecutionTime" -> [16#00, 16#03]; + "normalMGCExecutionTime" -> [16#00, 16#04]; + "MGProvisionalResponseTimerValue" -> [16#00, 16#05]; + "MGCProvisionalResponseTimerValue" -> [16#00, 16#06]; + "MGCOriginatedPendingLimit" -> [16#00, 16#07]; + "MGOriginatedPendingLimit" -> [16#00, 16#08] + end + end. + +decode_root(Scope, Item) -> + case Scope of + property -> + case Item of + [16#00, 16#01] -> "maxNumberOfContexts"; + [16#00, 16#02] -> "maxTerminationsPerContext"; + [16#00, 16#03] -> "normalMGExecutionTime"; + [16#00, 16#04] -> "normalMGCExecutionTime"; + [16#00, 16#05] -> "MGProvisionalResponseTimerValue"; + [16#00, 16#06] -> "MGCProvisionalResponseTimerValue"; + [16#00, 16#07] -> "MGCOriginatedPendingLimit"; + [16#00, 16#08] -> "MGOriginatedPendingLimit" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: tonegen - Tone Generator Package +%% Version: 2 +%% Extends: None +%% Purpose: This package defines signals to generate audio tones. +%% This package does not specify parameter values. It is +%% intended to be extendable. Generally, tones are defined +%% as an individual signal with a parameter, ind, +%% representing "interdigit" time delay, and a tone id to +%% be used with playtones. A tone id should be kept +%% consistent with any tone generation for the same tone. +%% MGs are expected to be provisioned with the characteristics +%% of appropriate tones for the country in which the MG is located. +%%---------------------------------------------------------------------- + +capabilities_tonegen() -> + [ + {signal, "pt"} + ]. + +encode_tonegen(signal, Item) -> + case Item of + "pt" -> [16#00, 16#01] + end; + +encode_tonegen({signal_parameter, Item}, SubItem) -> + case Item of + "pt" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "ind" -> [16#00, 16#02]; + "btd" -> [16#00, 16#03] + end + end. + +decode_tonegen(signal, Item) -> + case Item of + [16#00, 16#01] -> "pt" + end; + +decode_tonegen({signal_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event: pt + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#02] -> "ind"; + [16#00, 16#03] -> "btd" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: tonedet - Tone Detection Package +%% Version: 1 +%% Extends: None +%% Purpose: This Package defines events for audio tone detection. +%% Tones are selected by name (tone id). MGs are expected +%% to be provisioned with the characteristics of appropriate +%% tones for the country in which the MG is located. +%% +%% This package does not specify parameter values. +%% It is intended to be extendable. +%%---------------------------------------------------------------------- + +capabilities_tonedet() -> + [ + {event, "std"}, + {event, "etd"}, + {event, "ltd"} + ]. + +encode_tonedet(event, Item) -> + case Item of + "std" -> [16#00, 16#01]; + "etd" -> [16#00, 16#02]; + "ltd" -> [16#00, 16#03] + end; + +encode_tonedet({event_parameter, Item}, SubItem) -> + case Item of + "std" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "tid" -> [16#00, 16#03] + end; + "etd" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "tid" -> [16#00, 16#03]; + "dur" -> [16#00, 16#02] + end; + "ltd" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "dur" -> [16#00, 16#02]; + "tid" -> [16#00, 16#03] + end + end. + +decode_tonedet(event, Item) -> + case Item of + [16#00, 16#01] -> "std"; + [16#00, 16#02] -> "etd"; + [16#00, 16#03] -> "ltd" + end; + +decode_tonedet({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event std + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#03] -> "tid" + end; + [16#00, 16#02] -> % Event etd + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#03] -> "tid"; + [16#00, 16#02] -> "dur" + end; + [16#00, 16#03] -> % Event ltd + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#02] -> "dur"; + [16#00, 16#03] -> "tid" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: dg - Basic DTMF Generator Package +%% Version: 1 +%% Extends: tonegen version 1 +%% Purpose: This package defines the basic DTMF tones as signals and +%% extends the allowed values of parameter tl of playtone +%% in tonegen. +%%---------------------------------------------------------------------- + +capabilities_dg() -> + [ + {signal, "d0"}, + {signal, "d1"}, + {signal, "d2"}, + {signal, "d3"}, + {signal, "d4"}, + {signal, "d5"}, + {signal, "d6"}, + {signal, "d7"}, + {signal, "d8"}, + {signal, "d9"}, + {signal, "ds"}, + {signal, "do"}, + {signal, "da"}, + {signal, "db"}, + {signal, "dc"}, + {signal, "dd"} + ]. + +encode_dg(signal, Item) -> + case Item of + "d0" -> [16#00, 16#10]; + "d1" -> [16#00, 16#11]; + "d2" -> [16#00, 16#12]; + "d3" -> [16#00, 16#13]; + "d4" -> [16#00, 16#14]; + "d5" -> [16#00, 16#15]; + "d6" -> [16#00, 16#16]; + "d7" -> [16#00, 16#17]; + "d8" -> [16#00, 16#18]; + "d9" -> [16#00, 16#19]; + "ds" -> [16#00, 16#20]; + "do" -> [16#00, 16#21]; + "da" -> [16#00, 16#1a]; + "db" -> [16#00, 16#1b]; + "dc" -> [16#00, 16#1c]; + "dd" -> [16#00, 16#1d] + end; + +encode_dg({signal_parameter, Item}, SubItem) -> + case Item of + "d0" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d1" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d2" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d3" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d4" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d5" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d6" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d7" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d8" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d9" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "ds" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "do" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "da" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "db" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "dc" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "dd" -> + case SubItem of + "btd" -> [16#00, 16#01] + end + end. + +decode_dg(signal, Item) -> + case Item of + [16#00, 16#10] -> "d0"; + [16#00, 16#11] -> "d1"; + [16#00, 16#12] -> "d2"; + [16#00, 16#13] -> "d3"; + [16#00, 16#14] -> "d4"; + [16#00, 16#15] -> "d5"; + [16#00, 16#16] -> "d6"; + [16#00, 16#17] -> "d7"; + [16#00, 16#18] -> "d8"; + [16#00, 16#19] -> "d9"; + [16#00, 16#20] -> "ds"; + [16#00, 16#21] -> "do"; + [16#00, 16#1a] -> "da"; + [16#00, 16#1b] -> "db"; + [16#00, 16#1c] -> "dc"; + [16#00, 16#1d] -> "dd" + end; + +decode_dg({signal_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#10] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#11] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#12] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#13] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#14] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#15] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#16] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#17] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#18] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#19] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#20] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#21] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1a] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1b] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1c] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1d] -> + case SubItem of + [16#00, 16#01] -> "btd" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: dd - DTMF detection Package +%% Version: 1 +%% Extends: tonedet version 1 +%% Purpose: This package defines the basic DTMF tones detection. +%% Tones are selected by name (tone id). MGs are expected +%% to be provisioned with the characteristics of appropriate +%% tones for the country in which the MG is located. +%% +%% This package does not specify parameter values. +%% It is intended to be extendable. +%% +%% Additional tone id values are all tone ids described in package dg +%% (basic DTMF generator package). +%% +%% The following table maps DTMF events to digit map symbols as described +%% in section 7.1.14. +%% +%% _________________________________ +%% | DTMF Event | Symbol | +%% | d0 | "0" | +%% | d1 | "1" | +%% | d2 | "2" | +%% | d3 | "3" | +%% | d4 | "4" | +%% | d5 | "5" | +%% | d6 | "6" | +%% | d7 | "7" | +%% | d8 | "8" | +%% | d9 | "9" | +%% | da | "A" or "a"| +%% | db | "B" or "b"| +%% | dc | "C" or "c"| +%% | dd | "D" or "d"| +%% | ds | "E" or "e"| +%% | do | "F" or "f"| +%% |___________________|____________| +%% +%%---------------------------------------------------------------------- + +capabilities_dd() -> + [ + {event, "ce"}, + {event, "d0"}, + {event, "d1"}, + {event, "d2"}, + {event, "d3"}, + {event, "d4"}, + {event, "d5"}, + {event, "d6"}, + {event, "d7"}, + {event, "d8"}, + {event, "d9"}, + {event, "ds"}, + {event, "do"}, + {event, "da"}, + {event, "db"}, + {event, "dc"}, + {event, "dd"} + ]. + +encode_dd(event, Item) -> + case Item of + "ce" -> [16#00, 16#04]; + "d0" -> [16#00, 16#10]; + "d1" -> [16#00, 16#11]; + "d2" -> [16#00, 16#12]; + "d3" -> [16#00, 16#13]; + "d4" -> [16#00, 16#14]; + "d5" -> [16#00, 16#15]; + "d6" -> [16#00, 16#16]; + "d7" -> [16#00, 16#17]; + "d8" -> [16#00, 16#18]; + "d9" -> [16#00, 16#19]; + "ds" -> [16#00, 16#20]; + "do" -> [16#00, 16#21]; + "da" -> [16#00, 16#1a]; + "db" -> [16#00, 16#1b]; + "dc" -> [16#00, 16#1c]; + "dd" -> [16#00, 16#1d] + end; + +encode_dd({event_parameter, Item}, SubItem) -> + case Item of + "ce" -> + case SubItem of + "ds" -> [16#00, 16#01]; + "Meth" -> [16#00, 16#03] + end; + "d0" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d1" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d2" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d3" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d4" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d5" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d6" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d7" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d8" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d9" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "ds" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "do" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "da" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "db" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "dc" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "dd" -> + case SubItem of + "btd" -> [16#00, 16#01] + end + end. + +decode_dd(event, Item) -> + case Item of + [16#00, 16#04] -> "ce"; + [16#00, 16#10] -> "d0"; + [16#00, 16#11] -> "d1"; + [16#00, 16#12] -> "d2"; + [16#00, 16#13] -> "d3"; + [16#00, 16#14] -> "d4"; + [16#00, 16#15] -> "d5"; + [16#00, 16#16] -> "d6"; + [16#00, 16#17] -> "d7"; + [16#00, 16#18] -> "d8"; + [16#00, 16#19] -> "d9"; + [16#00, 16#20] -> "ds"; + [16#00, 16#21] -> "do"; + [16#00, 16#1a] -> "da"; + [16#00, 16#1b] -> "db"; + [16#00, 16#1c] -> "dc"; + [16#00, 16#1d] -> "dd" + end; + +decode_dd({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#04] -> % Event ce + case SubItem of + [16#00, 16#01] -> "ds"; + [16#00, 16#03] -> "Meth" + end; + [16#00, 16#10] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#11] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#12] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#13] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#14] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#15] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#16] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#17] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#18] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#19] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#20] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#21] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1a] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1b] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1c] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1d] -> + case SubItem of + [16#00, 16#01] -> "btd" + end + end. + +%%---------------------------------------------------------------------- +%% Name: cg - Call Progress Tones Generator Package +%% Version: 1 +%% Extends: tonegen version 1 +%% Purpose: This package defines the basic call progress tones as signals +%% and extends the allowed values of the tl parameter of +%% playtone in tonegen. +%%---------------------------------------------------------------------- + +capabilities_cg() -> + [ + {signal, "dt"}, + {signal, "rt"}, + {signal, "bt"}, + {signal, "ct"}, + {signal, "sit"}, + {signal, "wt"}, + {signal, "prt"}, + {signal, "cw"}, + {signal, "cr"} + ]. + + +encode_cg(Scope, Item) -> + case Scope of + signal -> + case Item of + "dt" -> [16#00, 16#30]; + "rt" -> [16#00, 16#31]; + "bt" -> [16#00, 16#32]; + "ct" -> [16#00, 16#33]; + "sit" -> [16#00, 16#34]; + "wt" -> [16#00, 16#35]; + "prt" -> [16#00, 16#36]; + "cw" -> [16#00, 16#37]; + "cr" -> [16#00, 16#38] + end + end. + +decode_cg(Scope, Item) -> + case Scope of + signal -> + case Item of + [16#00, 16#30] -> "dt"; + [16#00, 16#31] -> "rt"; + [16#00, 16#32] -> "bt"; + [16#00, 16#33] -> "ct"; + [16#00, 16#34] -> "sit"; + [16#00, 16#35] -> "wt"; + [16#00, 16#36] -> "prt"; + [16#00, 16#37] -> "cw"; + [16#00, 16#38] -> "cr" + end + end. + +%%---------------------------------------------------------------------- +%% Name: cd - Call Progress Tones Detection Package +%% Version: 1 +%% Extends: tonedet version 1 +%% Purpose: This package defines the basic call progress detection tones. +%% This Package extends the possible values of tone id +%% in the "start tone detected", "end tone detected" and +%% "long tone detected" events. +%% Additional values +%% tone id values are defined for start tone detected, +%% end tone detected and long tone detected with +%% the same values as those in package cg (call +%% progress tones generation package). +%% +%% The required set of tone ids corresponds to Recommendation E.180/Q.35 +%% [ITU-T Recommendation E.180/Q.35 (1998)]. See Recommendation E.180/Q.35 +%% for definition of the meanings of these tones. +%%---------------------------------------------------------------------- + +capabilities_cd() -> + [ + {event, "dt"}, + {event, "rt"}, + {event, "bt"}, + {event, "ct"}, + {event, "sit"}, + {event, "wt"}, + {event, "prt"}, + {event, "cw"}, + {event, "cr"} + ]. + + +encode_cd(Scope, Item) -> + case Scope of + event -> + case Item of + "dt" -> [16#00, 16#30]; + "rt" -> [16#00, 16#31]; + "bt" -> [16#00, 16#32]; + "ct" -> [16#00, 16#33]; + "sit"-> [16#00, 16#34]; + "wt" -> [16#00, 16#35]; + "prt"-> [16#00, 16#36]; + "cw" -> [16#00, 16#37]; + "cr" -> [16#00, 16#38] + end + end. + +decode_cd(Scope, Item) -> + case Scope of + event -> + case Item of + [16#00, 16#30] -> "dt"; + [16#00, 16#31] -> "rt"; + [16#00, 16#32] -> "bt"; + [16#00, 16#33] -> "ct"; + [16#00, 16#34] -> "sit"; + [16#00, 16#35] -> "wt"; + [16#00, 16#36] -> "prt"; + [16#00, 16#37] -> "cw"; + [16#00, 16#38] -> "cr" + end + end. + +%%---------------------------------------------------------------------- +%% Name: al - Analog Line Supervision Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines events and signals for an analog line. +%%---------------------------------------------------------------------- + +capabilities_al() -> + [ + {event, "on"}, + {event, "of"}, + {event, "fl"}, + {signal, "ri"} + ]. + +encode_al(event, Item) -> + ?d("encode_al(event) -> entry with" + "~n Item: ~p", [Item]), + case Item of + "on" -> [16#00, 16#04]; + "of" -> [16#00, 16#05]; + "fl" -> [16#00, 16#06] + end; + +encode_al({event_parameter, Item}, SubItem) -> + ?d("encode_al({event_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + "on" -> + case SubItem of + "strict" -> [16#00, 16#01]; + "init" -> [16#00, 16#02] + end; + "of" -> + case SubItem of + "strict" -> [16#00, 16#01]; + "init" -> [16#00, 16#02] + end; + "fl" -> + case SubItem of + "mindur" -> [16#00, 16#04]; + "maxdur" -> [16#00, 16#05] + end + end; + +encode_al(signal, Item) -> + ?d("encode_al(signal) -> entry with" + "~n Item: ~p", [Item]), + case Item of + "ri" -> [16#00, 16#02] + end; + +encode_al({signal_parameter, Item}, SubItem) -> + ?d("encode_al({signal_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + "ri" -> + case SubItem of + "cad" -> [16#00, 16#06]; + "freq" -> [16#00, 16#07] + end + end. + +decode_al(event, SubItem) -> + ?d("decode_al(event) -> entry with" + "~n SubItem: ~p", [SubItem]), + case SubItem of + [16#00, 16#04] -> "on"; + [16#00, 16#05] -> "of"; + [16#00, 16#06] -> "fl" + end; + +decode_al({event_parameter, Item}, SubItem) -> + ?d("decode_al({event_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + [16#00,16#04] -> %% Event: on + case SubItem of + [16#00, 16#01] -> "strict"; + [16#00, 16#02] -> "init" + end; + [16#00,16#05] -> %% Event: of + case SubItem of + [16#00, 16#01] -> "strict"; + [16#00, 16#02] -> "init" + end; + [16#00,16#06] -> %% Event: fl + case SubItem of + [16#00, 16#04] -> "mindur"; + [16#00, 16#05] -> "maxdur" + end + end; + +decode_al(signal, SubItem) -> + ?d("decode_al(signal) -> entry with" + "~n SubItem: ~p", [SubItem]), + case SubItem of + [16#00, 16#02] -> "ri" + end; + +decode_al({signal_parameter, Item}, SubItem) -> + ?d("decode_al({signal_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + [16#00,16#02] -> %% Event: ri + case SubItem of + [16#00, 16#06] -> "cad"; + [16#00, 16#07] -> "freq" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: ct - Basic Continuity Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines events and signals for continuity test. +%% The continuity test includes provision of either a loopback +%% or transceiver functionality. +%%---------------------------------------------------------------------- + +capabilities_ct() -> + [ + {event, "cmp"}, + {signal, "ct"}, + {signal, "rsp"} + ]. + +encode_ct(event, Item) -> + case Item of + "cmp" -> [16#00, 16#05] + end; +encode_ct({event_parameter, Item}, SubItem) -> + case Item of + "cmp" -> + case SubItem of + "res" -> [16#00, 16#08] + end + end; +encode_ct(signal, Item) -> + case Item of + "ct" -> [16#00, 16#03]; + "rsp" -> [16#00, 16#04] + end. + +decode_ct(event, Item) -> + case Item of + [16#00, 16#05] -> "cmp" + end; +decode_ct({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#05] -> % Event cmp + case SubItem of + [16#00, 16#08] -> "res" + end + end; +decode_ct(signal, Item) -> + case Item of + [16#00, 16#03] -> "ct"; + [16#00, 16#04] -> "rsp" + end. + +%%---------------------------------------------------------------------- +%% Name: nt - Network Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines properties of network terminations +%% independent of network type. +%%---------------------------------------------------------------------- + +capabilities_nt() -> + [ + {property, "jit"}, + {event, "netfail"}, + {event, "qualert"}, + {statistics, "dur"}, + {statistics, "os"}, + {statistics, "or"} + ]. + +encode_nt(property, Item) -> + case Item of + "jit" -> [16#00, 16#07] + end; +encode_nt(event, Item) -> + case Item of + "netfail" -> [16#00, 16#05]; + "qualert" -> [16#00, 16#06] + end; +encode_nt({event_parameter, Item}, SubItem) -> + case Item of + "netfail" -> + case SubItem of + "cs" -> [16#00, 16#01] + end; + "qualert" -> + case SubItem of + "th" -> [16#00, 16#01] + end + end; +encode_nt(statistics, Item) -> + case Item of + "dur" -> [16#00, 16#01]; + "os" -> [16#00, 16#02]; + "or" -> [16#00, 16#03] + end. + +decode_nt(property, Item) -> + case Item of + [16#00, 16#07] -> "jit" + end; +decode_nt(event, Item) -> + case Item of + [16#00, 16#05] -> "netfail"; + [16#00, 16#06] -> "qualert" + end; +decode_nt({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#05] -> % Event netfail + case SubItem of + [16#00, 16#01] -> "cs" + end; + [16#00, 16#06] -> % Event qualert + case Item of + [16#00, 16#01] -> "th" + end + end; +decode_nt(statistics, Item) -> + case Item of + [16#00, 16#01] -> "dur"; + [16#00, 16#02] -> "os"; + [16#00, 16#03] -> "or" + end. + +%%---------------------------------------------------------------------- +%% Name: rtp - RTP Package +%% Version: 1 +%% Extends: nt version 1 +%% Purpose: This package is used to support packet based multimedia +%% data transfer by means of the Real-time Transport Protocol +%% (RTP) [RFC 1889]. +%%---------------------------------------------------------------------- + +capabilities_rtp() -> + [ + {event, "pltrans"}, + {statistics, "ps"}, + {statistics, "pr"}, + {statistics, "pl"}, + {statistics, "jit"}, + {statistics, "delay"} + ]. + +encode_rtp(event, Item) -> + case Item of + "pltrans" -> [16#00, 16#01] + end; +encode_rtp({event_parameter, Item}, SubItem) -> + case Item of + "pltrans" -> + case SubItem of + "rtppltype" -> [16#00, 16#01] + end + end; +encode_rtp(statistics, Item) -> + case Item of + "ps" -> [16#00, 16#04]; + "pr" -> [16#00, 16#05]; + "pl" -> [16#00, 16#06]; + "jit" -> [16#00, 16#07]; + "delay" -> [16#00, 16#08] + end. + +decode_rtp(event, Item) -> + case Item of + [16#00, 16#01] -> "pltrans" + end; +decode_rtp({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event pltrans + case SubItem of + [16#00, 16#01] -> "rtppltype" + end + end; +decode_rtp(statistics, Item) -> + case Item of + [16#00, 16#04] -> "ps"; + [16#00, 16#05] -> "pr"; + [16#00, 16#06] -> "pl"; + [16#00, 16#07] -> "jit"; + [16#00, 16#08] -> "delay" + end. + + +%%---------------------------------------------------------------------- +%% Name: tdmc - TDM Circuit Package +%% Version: 1 +%% Extends: nt version 1 +%% Purpose: This package is used to support TDM circuit terminations. +%%---------------------------------------------------------------------- + +capabilities_tdmc() -> + [ + {property, "ec"}, + {property, "gain"} + ]. + +encode_tdmc(Scope, Item) -> + case Scope of + property -> + case Item of + "ec" -> [16#00, 16#08]; + "gain" -> [16#00, 16#0a] + end + end. + +decode_tdmc(Scope, Item) -> + case Scope of + property -> + case Item of + [16#00, 16#08] -> "ec"; + [16#00, 16#0a] -> "gain" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: swb - SwitchBoard Package +%% Version: 1 +%% Extends: none +%% Purpose: This package is used to support SwitchBoard specials +%%---------------------------------------------------------------------- + +capabilities_swb() -> + [ + {statistics, "fs"}, % Free slots + {statistics, "as"} % Allocated slots + ]. + +encode_swb(Scope, Item) -> + case Scope of + statistics -> + case Item of + "fs" -> [16#00, 16#00]; + "as" -> [16#00, 16#01] + end + end. + +decode_swb(Scope, Item) -> + case Scope of + statistics -> + case Item of + [16#00, 16#00] -> "fs"; + [16#00, 16#01] -> "as" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: native - Pseudo package +%% Version: 1 +%% Extends: None +%% Purpose: Native tags for media stream properties +%% +%% Parameters for Local descriptors and Remote descriptors are +%% specified as tag-value pairs if binary encoding is used for the +%% protocol. This annex contains the property names (PropertyID), the +%% tags (Property Tag), type of the property (Type) and the values +%% (Value).Values presented in the Value field when the field contains +%% references shall be regarded as "information". The reference +%% contains the normative values. If a value field does not contain a +%% reference then the values in that field can be considered as +%% "normative". +%% +%% Tags are given as hexadecimal numbers in this annex. When setting +%% the value of a property, a MGC may underspecify the value according +%% to one of the mechanisms specified in section 7.1.1. +%% +%% For type "enumeration" the value is represented by the value in brack- +%% ets, e.g., Send(0), Receive(1). +%%---------------------------------------------------------------------- +%% +%% C.6. IP +%% +%% ________________________________________________________________ +%% | PropertyID| Tag | Type | Value | +%% | IPv4 | 6001 | 32 BITS | Ipv4Address | +%% | IPv6 | 6002 | 128 BITS | IPv6 Address | +%% | Port | 6003 | Unsigned Int| Port | +%% | Porttype | 6004 | Enumerated | TCP(0),UDP(1),SCTP(2)| +%% |___________|____________|______________|_______________________| +%% +%% +%% C.11. SDP Equivalents +%% +%% ______________________________________________________________ +%% | PropertyID| Tag | Type | Value | +%% | SDP_V | B001| STRING| Protocol Version | +%% | SDP_O | B002| STRING| Owner-creator and session ID | +%% | SDP_S | B003| STRING| Sesson name | +%% | SDP_I | B004| STRING| Session identifier | +%% | SDP_U | B005| STRING| URI of descriptor | +%% | SDC_E | B006| STRING| email address | +%% | SDP_P | B007| STRING| phone number | +%% | SDP_C | B008| STRING| Connection information | +%% | SDP_B | B009| STRING| Bandwidth Information | +%% | SDP_Z | B00A| STRING| time zone adjustment | +%% | SDP_K | B00B| STRING| Encryption Key | +%% | SDP_A | B00C| STRING| Zero or more session attributes| +%% | SDP_T | B00D| STRING| Active Session Time | +%% | SDP_R | B00E| STRING| Zero or more repeat times | +%% | SDP_M | B00F| STRING| Media name and transport addr | +%% | | | | Reference: IETF RFC 2327 | +%% |___________|______|________|_________________________________| +%% +%%---------------------------------------------------------------------- + +capabilities_native() -> + [ + %% C.6. IP + {property, "IPv4"}, + {property, "IPv6"}, + {property, "Port"}, + {property, "Porttype"}, + + %% C.11. SDP Equivalents + {property, "v"}, + {property, "o"}, + {property, "s"}, + {property, "i"}, + {property, "u"}, + {property, "e"}, + {property, "p"}, + {property, "c"}, + {property, "b"}, + {property, "z"}, + {property, "k"}, + {property, "a"}, + {property, "t"}, + {property, "r"}, + {property, "m"} + ]. + +encode_native(Scope, Item) -> + case Scope of + property -> + case Item of + %% IP + "IPv4" -> [16#60, 16#01]; + "IPv6" -> [16#60, 16#02]; + "Port" -> [16#60, 16#03]; + "Porttype" -> [16#60, 16#04]; + + %% SDP + "v" -> [16#b0, 16#01]; + "o" -> [16#b0, 16#02]; + "s" -> [16#b0, 16#03]; + "i" -> [16#b0, 16#04]; + "u" -> [16#b0, 16#05]; + "e" -> [16#b0, 16#06]; + "p" -> [16#b0, 16#07]; + "c" -> [16#b0, 16#08]; + "b" -> [16#b0, 16#09]; + "z" -> [16#b0, 16#0a]; + "k" -> [16#b0, 16#0b]; + "a" -> [16#b0, 16#0c]; + "t" -> [16#b0, 16#0d]; + "r" -> [16#b0, 16#0e]; + "m" -> [16#b0, 16#0f] + end + end. + +decode_native(Scope, [Type, Item]) -> + case Scope of + property -> + case Type of + 16#60 -> + case Item of + 16#01 -> "IPv4"; + 16#02 -> "IPv6"; + 16#03 -> "Port"; + 16#04 -> "Porttype" + end; + + 16#b0 -> + case Item of + 16#01 -> "v"; + 16#02 -> "o"; + 16#03 -> "s"; + 16#04 -> "i"; + 16#05 -> "u"; + 16#06 -> "e"; + 16#07 -> "p"; + 16#08 -> "c"; + 16#09 -> "b"; + 16#0a -> "z"; + 16#0b -> "k"; + 16#0c -> "a"; + 16#0d -> "t"; + 16#0e -> "r"; + 16#0f -> "m" + end + end + end. + +%% ------------------------------------------------------------------- + +% error(Reason) -> +% erlang:error(Reason). + diff --git a/lib/megaco/src/binary/megaco_binary_name_resolver_v1.erl b/lib/megaco/src/binary/megaco_binary_name_resolver_v1.erl new file mode 100644 index 0000000000..a748a1d0cc --- /dev/null +++ b/lib/megaco/src/binary/megaco_binary_name_resolver_v1.erl @@ -0,0 +1,1613 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Handle meta data about packages +%%---------------------------------------------------------------------- + +-module(megaco_binary_name_resolver_v1). + +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). +-include_lib("megaco/src/app/megaco_internal.hrl"). + +-define(LOWER(Char), + if + Char >= $A, Char =< $Z -> + Char - ($A - $a); + true -> + Char + end). + +-export([packages/0, + capabilities/0, + capabilities/1, + decode_name/3, + encode_name/3 + ]). + +encode_name(Config, term_id, TermId) -> + case megaco:encode_binary_term_id(Config, TermId) of + {ok, TermId2} -> + TermId2; + {error, _Reason} -> + exit({bad_term_id, TermId}) + end; +encode_name(_Config, Scope, Item) -> + ?d("encode_name(~p) -> entry with" + "~n Item: ~p", [Scope, Item]), + encode(Scope, Item). + +decode_name(Config, term_id, TermId) -> + case megaco:decode_binary_term_id(Config, TermId) of + {ok, TermId2} -> + TermId2; + {error, _Reason} -> + exit({bad_term_id, TermId}) + end; +decode_name(_Config, Scope, Item) -> + ?d("decode_name(~p) -> entry with" + "~n Item: ~p", [Scope, Item]), + decode(Scope, Item). + + + + +%%---------------------------------------------------------------------- +%% 12.1.1 Package +%% +%% Overall description of the package, specifying: +%% +%% Package Name: only descriptive +%% +%% PackageID: is an identifier +%% +%% Description: +%% +%% Version: +%% +%% A new version of a package can only add additional Properties, +%% Events, Signals, Statistics and new possible values for an +%% existing parameter described in the original package. No +%% deletions or modifications shall be allowed. A version is an +%% integer in the range from 1 to 99. +%% +%% Designed to be extended only (Optional): +%% +%% This indicates that the package has been expressly designed to +%% be extended by others, not to be directly referenced. For +%% example, the package may not have any function on its own or be +%% nonsensical on its own. The MG SHOULD NOT publish this +%% PackageID when reporting packages. +%% +%% Extends (Optional): existing package Descriptor +%% +%% A package may extend an existing package. The version of the +%% original package must be specified. When a package extends +%% another package it shall only add additional Properties, +%% Events, Signals, Statistics and new possible values for an +%% existing parameter described in the original package. An +%% extended package shall not redefine or overload an identifier +%% defined in the original package and packages it may have +%% extended (multiple levels of extension). Hence, if package B +%% version 1 extends package A version 1, version 2 of B will not +%% be able to extend the A version 2 if A version 2 defines a name +%% already in B version 1. +%% +%% +%% 12.1.2 Properties +%% +%% Properties defined by the package, specifying: +%% +%% Property Name: only descriptive +%% +%% PropertyID: is an identifier +%% +%% Description: +%% +%% Type: One of: +%% +%% Boolean +%% +%% String: UTF-8 string +%% +%% Octet String: A number of octets. See Annex A and Annex B.3 +%% for encoding +%% +%% Integer: 4 byte signed integer +%% +%% Double: 8 byte signed integer +%% +%% Character: unicode UTF-8 encoding of a single letter. Could be +%% more than one octet. +%% +%% Enumeration: one of a list of possible unique values (see 12.3) +%% +%% Sub-list: a list of several values from a list. The type of +%% sub-list SHALL also be specified. The type shall be chosen +%% from the types specified in this section (with the exception of +%% sub-list). For example, Type: sub-list of enumeration. The +%% encoding of sub-lists is specified in Annexes A and B.3. +%% +%% Possible values: +%% +%% A package MUST specify either a specific set of values or a +%% description of how values are determined. A package MUST also +%% specify a default value or the default behaviour when the value +%% is omitted from its descriptor. For example, a package may +%% specify that procedures related to the property are suspended +%% when its value is omitted. A default value (but not +%% procedures) may be specified as provisionable. +%% +%% Defined in: +%% +%% Which H.248.1 descriptor the property is defined in. +%% LocalControl is for stream dependent properties. +%% TerminationState is for stream independent properties. These +%% are expected to be the most common cases, but it is possible +%% for properties to be defined in other descriptors. +%% +%% Characteristics: Read/Write or both, and (optionally), global: +%% +%% Indicates whether a property is read-only, or read-write, and +%% if it is global. If Global is omitted, the property is not +%% global. If a property is declared as global, the value of the +%% property is shared by all Terminations realizing the package. +%% +%% +%% 12.1.3 Events +%% +%% Events defined by the package, specifying: +%% +%% Event name: only descriptive +%% +%% EventID: is an identifier +%% +%% Description: +%% +%% EventsDescriptor Parameters: +%% +%% Parameters used by the MGC to configure the event, and found in +%% the EventsDescriptor. See 12.2. +%% +%% ObservedEventsDescriptor Parameters: +%% +%% Parameters returned to the MGC in Notify requests and in +%% replies to command requests from the MGC that audit +%% ObservedEventsDescriptor, and found in the +%% ObservedEventsDescriptor. See 12.2. +%% +%% +%% 12.1.4 Signals +%% +%% Signals defined by the package, specifying: +%% +%% Signal Name: only descriptive +%% +%% SignalID: is an identifier. SignalID is used in a +%% SignalsDescriptor +%% +%% Description +%% +%% SignalType: one of: +%% +%% OO (On/Off) +%% +%% TO (TimeOut) +%% +%% BR (Brief) +%% +%% NOTE - SignalType may be defined such that it is dependent on the +%% value of one or more parameters. The package MUST specify a +%% default signal type. If the default type is TO, the package MUST +%% specify a default duration which may be provisioned. A default +%% duration is meaningless for BR. +%% +%% Duration: in hundredths of seconds +%% +%% Additional Parameters: see 12.2 +%% +%% +%% 12.1.5 Statistics +%% +%% Statistics defined by the package, specifying: +%% +%% Statistic name: only descriptive +%% +%% StatisticID: is an identifier +%% +%% StatisticID is used in a StatisticsDescriptor +%% +%% Description: +%% +%% Units: unit of measure, e.g., milliseconds, packets +%% +%% +%% 12.1.6 Procedures +%% +%% Additional guidance on the use of the package. +%% +%% +%% 12.2 Guidelines to defining Parameters to Events and Signals +%% +%% Parameter Name: only descriptive +%% +%% ParameterID: is an identifier. The textual ParameterID of parameters +%% to Events and Signals shall not start with "EPA" and "SPA", +%% respectively. The textual ParameterID shall also not be "ST", +%% "Stream", "SY", "SignalType", "DR", "Duration", "NC", +%% "NotifyCompletion", "KA", "Keepactive", "EB", "Embed", "DM" or +%% "DigitMap". +%% +%% Type: One of: +%% +%% Boolean +%% +%% String: UTF-8 octet string +%% Octet String: A number of octets. See Annex A and Annex B.3 for +%% encoding +%% +%% Integer: 4-octet signed integer +%% +%% Double: 8-octet signed integer +%% +%% Character: unicode UTF-8 encoding of a single letter. Could be +%% more than one octet. +%% +%% Enumeration: one of a list of possible unique values (see 12.3) +%% +%% Sub-list: a list of several values from a list (not supported for +%% statistics). The type of sub-list SHALL also be specified. The +%% type shall be chosen from the types specified in this section +%% (with the exception of sub-list). For example, Type: sub-list of +%% enumeration. The encoding of sub-lists is specified in Annexes A +%% and B.3. +%% +%% Possible values: +%% +%% A package MUST specify either a specific set of values or a +%% description of how values are determined. A package MUST also +%% specify a default value or the default behavior when the value is +%% omitted from its descriptor. For example, a package may specify +%% that procedures related to the parameter are suspended when it +%% value is omitted. A default value (but not procedures) may be +%% specified as provisionable. +%% +%% Description: +%% +%% +%% 12.3 Lists +%% +%% Possible values for parameters include enumerations. Enumerations +%% may be defined in a list. It is recommended that the list be IANA +%% registered so that packages that extend the list can be defined +%% without concern for conflicting names. +%% +%% +%% 12.4 Identifiers +%% +%% Identifiers in text encoding shall be strings of up to 64 characters, +%% containing no spaces, starting with an alphabetic character and +%% consisting of alphanumeric characters and/or digits, and possibly +%% including the special character underscore ("_"). +%% +%% Identifiers in binary encoding are 2 octets long. +%% +%% Both text and binary values shall be specified for each identifier, +%% including identifiers used as values in enumerated types. +%% +%% +%% 12.5 Package registration +%% +%% A package can be registered with IANA for interoperability reasons. +%% See clause 13 for IANA Considerations. +%% +%%---------------------------------------------------------------------- + +capabilities() -> + [{P, capabilities(P)} || P <- packages()]. + +%% -record(property, {name, type, values, defined_in, characteristics}). + +%%---------------------------------------------------------------------- +%% List all known packages +%% 'native' and 'all' are not real packages +%%---------------------------------------------------------------------- + +packages() -> + [ + "g", % Generic + "root", % Base Root Package + "tonegen", % Tone Generator Package + "tonedet", % Tone Detection Package + "dg", % Basic DTMF Generator Package + "dd", % DTMF detection Package + "cg", % Call Progress Tones Generator Package + "cd", % Call Progress Tones Detection Package + "al", % Analog Line Supervision Package + "ct", % Basic Continuity Package + "nt", % Network Package + "rtp", % RTP Package + "swb", % SwitchBoard Package + "tdmc", % TDM Circuit Package + "" % Native pseudo package + ]. + +%%---------------------------------------------------------------------- +%% List all matching capabilities +%%---------------------------------------------------------------------- + +capabilities(Package) -> + case Package of + "g" -> capabilities_g(); + "root" -> capabilities_root(); + "tonegen" -> capabilities_tonegen(); + "tonedet" -> capabilities_tonedet(); + "dg" -> capabilities_dg(); + "dd" -> capabilities_dd(); + "cg" -> capabilities_cg(); + "cd" -> capabilities_cd(); + "al" -> capabilities_al(); + "ct" -> capabilities_ct(); + "nt" -> capabilities_nt(); + "rtp" -> capabilities_rtp(); + "swb" -> capabilities_swb(); + "tdmc" -> capabilities_tdmc(); + "" -> capabilities_native() + end. + +%%---------------------------------------------------------------------- +%% Decode package name to internal form +%% Scope ::= property | event | signal | statistics +%%---------------------------------------------------------------------- + +decode(mid, Package) -> + decode_mid(Package); +decode(package, Package) -> + decode_package(Package); +decode(profile, Package) -> + decode_profile(Package); +decode(dialplan, Dialplan) -> + decode_dialplan(Dialplan); +decode(Scope, [A, B | Item]) when is_atom(Scope) -> + ?d("decode(~p) -> entry with" + "~n A: ~p" + "~n B: ~p" + "~n Item: ~p", [Scope, A, B, Item]), + case decode_package([A, B]) of + "" -> + ?d("decode -> \"no\" package",[]), + decode_item(Scope, [A, B], Item); + Package -> + ?d("decode -> Package: ~p", [Package]), + Package ++ "/" ++ decode_item(Scope, [A, B], Item) + end; +decode({Scope, [A, B | Item]}, SubItem) when is_atom(Scope) -> + ?d("decode(~p) -> entry with" + "~n A: ~p" + "~n B: ~p" + "~n Item: ~p" + "~n SubItem: ~p", [Scope, A, B, Item, SubItem]), + decode_item({Scope, Item}, [A, B], SubItem). + +decode_item(Scope, [A, B], Item) -> + ?d("decode_item -> entry",[]), + case A of + 16#00 -> + case B of + 16#01 -> decode_g(Scope, Item); + 16#02 -> decode_root(Scope, Item); + 16#03 -> decode_tonegen(Scope, Item); + 16#04 -> decode_tonedet(Scope, Item); + 16#05 -> decode_dg(Scope, Item); + 16#06 -> decode_dd(Scope, Item); + 16#07 -> decode_cg(Scope, Item); + 16#08 -> decode_cd(Scope, Item); + 16#09 -> decode_al(Scope, Item); + 16#0a -> decode_ct(Scope, Item); + 16#0b -> decode_nt(Scope, Item); + 16#0c -> decode_rtp(Scope, Item); + 16#0d -> decode_tdmc(Scope, Item); + 16#00 -> decode_native(Scope, Item) + end; + 16#fe -> + case B of + %% Proprietary extension + 16#fe -> decode_swb(Scope, Item) + end; + 16#ff -> + case B of + 16#ff when Item =:= [16#ff, 16#ff] -> "*" + end + end. + +decode_package(Package) -> + ?d("decode_package -> entry with" + "~n Package: ~p", [Package]), + [A, B] = Package, + case A of + 16#00 -> + case B of + 16#01 -> "g"; + 16#02 -> "root"; + 16#03 -> "tonegen"; + 16#04 -> "tonedet"; + 16#05 -> "dg"; + 16#06 -> "dd"; + 16#07 -> "cg"; + 16#08 -> "cd"; + 16#09 -> "al"; + 16#0a -> "ct"; + 16#0b -> "nt"; + 16#0c -> "rtp"; + 16#0d -> "tdmc"; + 16#00 -> "" + end; + 16#fe -> + case B of + 16#fe -> "swb" + end; + 16#ff -> + case B of + 16#ff -> "*" + end + end. + +decode_profile([A, B]) -> + case A of + 16#00 -> + case B of + 16#fe -> "resgw"; + _ -> "profile" ++ [A + $0, B + $0] + end; + _ -> + "profile" ++ [A + $0, B + $0] + end. + +decode_dialplan([A, B]) -> + "dialplan" ++ [A + $0, B + $0]. + +decode_mid(Mid) -> + case Mid of + {domainName, DN} -> + Lower = to_lower(DN#'DomainName'.name), + {domainName, DN#'DomainName'{name = Lower}}; + {deviceName, PathName} -> + Lower = to_lower(PathName), + {deviceName, Lower}; + Other -> + Other + end. + +to_lower(Chars) -> + [?LOWER(Char) || Char <- Chars]. + +%%---------------------------------------------------------------------- +%% Encode package name from internal form +%% Scope ::= property | event | signal | statistics +%%---------------------------------------------------------------------- + +encode(mid, Package) -> + encode_mid(Package); +encode(package, Package) -> + encode_package(Package); +encode(profile, Profile) -> + encode_profile(Profile); +encode(dialplan, Dialplan) -> + encode_dialplan(Dialplan); +encode(Scope, PackageItem) when is_atom(Scope) -> + ?d("encode(~p) -> entry with" + "~n PackageItem: ~p", [Scope, PackageItem]), + case string:tokens(PackageItem, [$/]) of + [Package, Item] -> + ?d("encode -> " + "~n Package: ~p" + "~n Item: ~p", [Package, Item]), + encode_package(Package) ++ encode_item(Scope, Package, Item); + [Item] -> + ?d("encode -> Item: ~p", [Item]), + [16#00, 16#00 | encode_native(Scope, Item)] + end; +encode({Scope, PackageItem}, SubItem) when is_atom(Scope) -> + ?d("encode(~p) -> entry with" + "~n PackageItem: ~p" + "~n SubItem: ~p", [Scope, PackageItem, SubItem]), + case string:tokens(PackageItem, [$/]) of + [Package, Item] -> + ?d("encode -> " + "~n Package: ~p" + "~n Item: ~p", [Package, Item]), + encode_item({Scope, Item}, Package, SubItem); + [_Item] -> + ?d("encode -> _Item: ~p", [_Item]), + encode_native(Scope, SubItem) + end. + +encode_item(_Scope, _Package, "*") -> + [16#ff, 16#ff]; +encode_item(Scope, Package, Item) -> + ?d("encode_item(~s) -> entry", [Package]), + case Package of + "g" -> encode_g(Scope, Item); + "root" -> encode_root(Scope, Item); + "tonegen" -> encode_tonegen(Scope, Item); + "tonedet" -> encode_tonedet(Scope, Item); + "dg" -> encode_dg(Scope, Item); + "dd" -> encode_dd(Scope, Item); + "cg" -> encode_cg(Scope, Item); + "cd" -> encode_cd(Scope, Item); + "al" -> encode_al(Scope, Item); + "ct" -> encode_ct(Scope, Item); + "nt" -> encode_nt(Scope, Item); + "rtp" -> encode_rtp(Scope, Item); + "tdmc" -> encode_tdmc(Scope, Item); + "swb" -> encode_swb(Scope, Item) + end. + +encode_package(Package) -> + case Package of + "g" -> [16#00, 16#01]; + "root" -> [16#00, 16#02]; + "tonegen" -> [16#00, 16#03]; + "tonedet" -> [16#00, 16#04]; + "dg" -> [16#00, 16#05]; + "dd" -> [16#00, 16#06]; + "cg" -> [16#00, 16#07]; + "cd" -> [16#00, 16#08]; + "al" -> [16#00, 16#09]; + "ct" -> [16#00, 16#0a]; + "nt" -> [16#00, 16#0b]; + "rtp" -> [16#00, 16#0c]; + "tdmc" -> [16#00, 16#0d]; + "" -> [16#00, 16#00]; + "*" -> [16#ff, 16#ff]; + "swb" -> [16#fe, 16#fe] + end. + +encode_profile(Profile) -> + case Profile of + "resgw" -> + [16#00, 16#fe]; + [$p, $r, $o, $f, $i, $l, $e | Name] -> + case Name of + [A, B] -> [A - $0, B - $0]; + [B] -> [0, B - $0]; + [] -> [0, 0] + end + end. + +encode_dialplan(Dialplan) -> + case Dialplan of + [$d, $i, $a, $l, $p, $l, $a, $n | Name] -> + case Name of + [A, B] -> [A - $0, B - $0]; + [B] -> [0, B - $0]; + [] -> [0, 0] + end + end. + +encode_mid(Mid) -> + Mid. + + +%%---------------------------------------------------------------------- +%% Name: g - Generic +%% Version: 1 +%% Extends: None +%% Purpose: Generic package for commonly encountered items +%%---------------------------------------------------------------------- + +capabilities_g() -> + [ + {event, "cause"}, + {event, "sc"} + ]. + +encode_g(event, Item) -> + case Item of + "cause" -> [16#00, 16#01]; + "sc" -> [16#00, 16#02] + end; + +encode_g({event_parameter, Item}, SubItem) -> + case Item of + "cause" -> + case SubItem of + "Generalcause" -> [16#00, 16#01]; + "Failurecause" -> [16#00, 16#02] + end; + "sc" -> + case SubItem of + "SigID" -> [16#00, 16#01]; + "Meth" -> [16#00, 16#02]; + "SLID" -> [16#00, 16#03] + end + end. + +decode_g(event, Item) -> + case Item of + [16#00, 16#01] -> "cause"; + [16#00, 16#02] -> "sc" + end; + +decode_g({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event: cause + case SubItem of + [16#00, 16#01] -> "Generalcause"; + [16#00, 16#02] -> "Failurecause" + end; + + [16#00, 16#02] -> % Event: sc + case SubItem of + [16#00, 16#01] -> "SigID"; + [16#00, 16#02] -> "Meth"; + [16#00, 16#03] -> "SLID" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: root - Base Root Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines Gateway wide properties. +%%---------------------------------------------------------------------- + +capabilities_root() -> + [ + {property, "maxNumberOfContexts"}, + {property, "maxTerminationsPerContext"}, + {property, "normalMGExecutionTime"}, + {property, "normalMGCExecutionTime"}, + {property, "MGProvisionalResponseTimerValue"}, + {property, "MGCProvisionalResponseTimerValue"} + ]. + +encode_root(Scope, Item) -> + case Scope of + property -> + case Item of + "maxNumberOfContexts" -> [16#00, 16#01]; + "maxTerminationsPerContext" -> [16#00, 16#02]; + "normalMGExecutionTime" -> [16#00, 16#03]; + "normalMGCExecutionTime" -> [16#00, 16#04]; + "MGProvisionalResponseTimerValue" -> [16#00, 16#05]; + "MGCProvisionalResponseTimerValue" -> [16#00, 16#06] + end + end. + +decode_root(Scope, Item) -> + case Scope of + property -> + case Item of + [16#00, 16#01] -> "maxNumberOfContexts"; + [16#00, 16#02] -> "maxTerminationsPerContext"; + [16#00, 16#03] -> "normalMGExecutionTime"; + [16#00, 16#04] -> "normalMGCExecutionTime"; + [16#00, 16#05] -> "MGProvisionalResponseTimerValue"; + [16#00, 16#06] -> "MGCProvisionalResponseTimerValue" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: tonegen - Tone Generator Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines signals to generate audio tones. +%% This package does not specify parameter values. It is +%% intended to be extendable. Generally, tones are defined +%% as an individual signal with a parameter, ind, +%% representing "interdigit" time delay, and a tone id to +%% be used with playtones. A tone id should be kept +%% consistent with any tone generation for the same tone. +%% MGs are expected to be provisioned with the characteristics +%% of appropriate tones for the country in which the MG is located. +%%---------------------------------------------------------------------- + +capabilities_tonegen() -> + [ + {signal, "pt"} + ]. + +encode_tonegen(signal, Item) -> + case Item of + "pt" -> [16#00, 16#01] + end; + +encode_tonegen({signal_parameter, Item}, SubItem) -> + case Item of + "pt" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "ind" -> [16#00, 16#02] + end + end. + +decode_tonegen(signal, Item) -> + case Item of + [16#00, 16#01] -> "pt" + end; + +decode_tonegen({signal_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event: pt + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#02] -> "ind" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: tonedet - Tone Detection Package +%% Version: 1 +%% Extends: None +%% Purpose: This Package defines events for audio tone detection. +%% Tones are selected by name (tone id). MGs are expected +%% to be provisioned with the characteristics of appropriate +%% tones for the country in which the MG is located. +%% +%% This package does not specify parameter values. +%% It is intended to be extendable. +%%---------------------------------------------------------------------- + +capabilities_tonedet() -> + [ + {event, "std"}, + {event, "etd"}, + {event, "ltd"} + ]. + +encode_tonedet(event, Item) -> + case Item of + "std" -> [16#00, 16#01]; + "etd" -> [16#00, 16#02]; + "ltd" -> [16#00, 16#03] + end; + +encode_tonedet({event_parameter, Item}, SubItem) -> + case Item of + "std" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "tid" -> [16#00, 16#03] + end; + "etd" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "tid" -> [16#00, 16#03]; + "dur" -> [16#00, 16#02] + end; + "ltd" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "dur" -> [16#00, 16#02]; + "tid" -> [16#00, 16#03] + end + end. + +decode_tonedet(event, Item) -> + case Item of + [16#00, 16#01] -> "std"; + [16#00, 16#02] -> "etd"; + [16#00, 16#03] -> "ltd" + end; + +decode_tonedet({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event std + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#03] -> "tid" + end; + [16#00, 16#02] -> % Event etd + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#03] -> "tid"; + [16#00, 16#02] -> "dur" + end; + [16#00, 16#03] -> % Event ltd + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#02] -> "dur"; + [16#00, 16#03] -> "tid" + end + end. + +%%---------------------------------------------------------------------- +%% Name: dg - Basic DTMF Generator Package +%% Version: 1 +%% Extends: tonegen version 1 +%% Purpose: This package defines the basic DTMF tones as signals and +%% extends the allowed values of parameter tl of playtone +%% in tonegen. +%%---------------------------------------------------------------------- + +capabilities_dg() -> + [ + {signal, "d0"}, + {signal, "d1"}, + {signal, "d2"}, + {signal, "d3"}, + {signal, "d4"}, + {signal, "d5"}, + {signal, "d6"}, + {signal, "d7"}, + {signal, "d8"}, + {signal, "d9"}, + {signal, "ds"}, + {signal, "do"}, + {signal, "da"}, + {signal, "db"}, + {signal, "dc"}, + {signal, "dd"} + ]. + +encode_dg(Scope, Item) -> + case Scope of + signal -> + case Item of + "d0" -> [16#00, 16#10]; + "d1" -> [16#00, 16#11]; + "d2" -> [16#00, 16#12]; + "d3" -> [16#00, 16#13]; + "d4" -> [16#00, 16#14]; + "d5" -> [16#00, 16#15]; + "d6" -> [16#00, 16#16]; + "d7" -> [16#00, 16#17]; + "d8" -> [16#00, 16#18]; + "d9" -> [16#00, 16#19]; + "ds" -> [16#00, 16#20]; + "do" -> [16#00, 16#21]; + "da" -> [16#00, 16#1a]; + "db" -> [16#00, 16#1b]; + "dc" -> [16#00, 16#1c]; + "dd" -> [16#00, 16#1d] + end + end. + +decode_dg(Scope, Item) -> + case Scope of + signal -> + case Item of + [16#00, 16#10] -> "d0"; + [16#00, 16#11] -> "d1"; + [16#00, 16#12] -> "d2"; + [16#00, 16#13] -> "d3"; + [16#00, 16#14] -> "d4"; + [16#00, 16#15] -> "d5"; + [16#00, 16#16] -> "d6"; + [16#00, 16#17] -> "d7"; + [16#00, 16#18] -> "d8"; + [16#00, 16#19] -> "d9"; + [16#00, 16#20] -> "ds"; + [16#00, 16#21] -> "do"; + [16#00, 16#1a] -> "da"; + [16#00, 16#1b] -> "db"; + [16#00, 16#1c] -> "dc"; + [16#00, 16#1d] -> "dd" + end + end. + +%%---------------------------------------------------------------------- +%% Name: dd - DTMF detection Package +%% Version: 1 +%% Extends: tonedet version 1 +%% Purpose: This package defines the basic DTMF tones detection. +%% Tones are selected by name (tone id). MGs are expected +%% to be provisioned with the characteristics of appropriate +%% tones for the country in which the MG is located. +%% +%% This package does not specify parameter values. +%% It is intended to be extendable. +%% +%% Additional tone id values are all tone ids described in package dg +%% (basic DTMF generator package). +%% +%% The following table maps DTMF events to digit map symbols as described +%% in section 7.1.14. +%% +%% _________________________________ +%% | DTMF Event | Symbol | +%% | d0 | "0" | +%% | d1 | "1" | +%% | d2 | "2" | +%% | d3 | "3" | +%% | d4 | "4" | +%% | d5 | "5" | +%% | d6 | "6" | +%% | d7 | "7" | +%% | d8 | "8" | +%% | d9 | "9" | +%% | da | "A" or "a"| +%% | db | "B" or "b"| +%% | dc | "C" or "c"| +%% | dd | "D" or "d"| +%% | ds | "E" or "e"| +%% | do | "F" or "f"| +%% |___________________|____________| +%% +%%---------------------------------------------------------------------- + +capabilities_dd() -> + [ + {event, "ce"} + ]. + +encode_dd(event, Item) -> + case Item of + "ce" -> [16#00, 16#04] + end; + +encode_dd({event_parameter, Item}, SubItem) -> + case Item of + "ce" -> + case SubItem of + "ds" -> [16#00, 16#01]; + "Meth" -> [16#00, 16#03] + end + end. + +decode_dd(event, Item) -> + case Item of + [16#00, 16#04] -> "ce" + end; + +decode_dd({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#04] -> % Event ce + case SubItem of + [16#00, 16#01] -> "ds"; + [16#00, 16#03] -> "Meth" + end + end. + +%%---------------------------------------------------------------------- +%% Name: cg - Call Progress Tones Generator Package +%% Version: 1 +%% Extends: tonegen version 1 +%% Purpose: This package defines the basic call progress tones as signals +%% and extends the allowed values of the tl parameter of +%% playtone in tonegen. +%%---------------------------------------------------------------------- + +capabilities_cg() -> + [ + {signal, "dt"}, + {signal, "rt"}, + {signal, "bt"}, + {signal, "ct"}, + {signal, "sit"}, + {signal, "wt"}, + {signal, "prt"}, + {signal, "cw"}, + {signal, "cr"} + ]. + + +encode_cg(Scope, Item) -> + case Scope of + signal -> + case Item of + "dt" -> [16#00, 16#30]; + "rt" -> [16#00, 16#31]; + "bt" -> [16#00, 16#32]; + "ct" -> [16#00, 16#33]; + "sit" -> [16#00, 16#34]; + "wt" -> [16#00, 16#35]; + "prt" -> [16#00, 16#36]; + "cw" -> [16#00, 16#37]; + "cr" -> [16#00, 16#38] + end + end. + +decode_cg(Scope, Item) -> + case Scope of + signal -> + case Item of + [16#00, 16#30] -> "dt"; + [16#00, 16#31] -> "rt"; + [16#00, 16#32] -> "bt"; + [16#00, 16#33] -> "ct"; + [16#00, 16#34] -> "sit"; + [16#00, 16#35] -> "wt"; + [16#00, 16#36] -> "prt"; + [16#00, 16#37] -> "cw"; + [16#00, 16#38] -> "cr" + end + end. + +%%---------------------------------------------------------------------- +%% Name: cd - Call Progress Tones Detection Package +%% Version: 1 +%% Extends: tonedet version 1 +%% Purpose: This package defines the basic call progress detection tones. +%% This Package extends the possible values of tone id +%% in the "start tone detected", "end tone detected" and +%% "long tone detected" events. +%% Additional values +%% tone id values are defined for start tone detected, +%% end tone detected and long tone detected with +%% the same values as those in package cg (call +%% progress tones generation package). +%% +%% The required set of tone ids corresponds to Recommendation E.180/Q.35 +%% [ITU-T Recommendation E.180/Q.35 (1998)]. See Recommendation E.180/Q.35 +%% for definition of the meanings of these tones. +%%---------------------------------------------------------------------- + +capabilities_cd() -> + [ + {event, "dt"}, + {event, "rt"}, + {event, "bt"}, + {event, "ct"}, + {event, "sit"}, + {event, "wt"}, + {event, "prt"}, + {event, "cw"}, + {event, "cr"} + ]. + + +encode_cd(Scope, Item) -> + case Scope of + event -> + case Item of + "dt" -> [16#00, 16#30]; + "rt" -> [16#00, 16#31]; + "bt" -> [16#00, 16#32]; + "ct" -> [16#00, 16#33]; + "sit"-> [16#00, 16#34]; + "wt" -> [16#00, 16#35]; + "prt"-> [16#00, 16#36]; + "cw" -> [16#00, 16#37]; + "cr" -> [16#00, 16#38] + end + end. + +decode_cd(Scope, Item) -> + case Scope of + event -> + case Item of + [16#00, 16#30] -> "dt"; + [16#00, 16#31] -> "rt"; + [16#00, 16#32] -> "bt"; + [16#00, 16#33] -> "ct"; + [16#00, 16#34] -> "sit"; + [16#00, 16#35] -> "wt"; + [16#00, 16#36] -> "prt"; + [16#00, 16#37] -> "cw"; + [16#00, 16#38] -> "cr" + end + end. + +%%---------------------------------------------------------------------- +%% Name: al - Analog Line Supervision Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines events and signals for an analog line. +%%---------------------------------------------------------------------- + +capabilities_al() -> + [ + {event, "on"}, + {event, "of"}, + {event, "fl"}, + {signal, "ri"} + ]. + +encode_al(event, Item) -> + ?d("encode_al(event) -> entry with" + "~n Item: ~p", [Item]), + case Item of + "on" -> [16#00, 16#04]; + "of" -> [16#00, 16#05]; + "fl" -> [16#00, 16#06] + end; + +encode_al({event_parameter, Item}, SubItem) -> + ?d("encode_al({event_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + "on" -> + case SubItem of + "strict" -> [16#00, 16#01]; + "init" -> [16#00, 16#02] + end; + "of" -> + case SubItem of + "strict" -> [16#00, 16#01]; + "init" -> [16#00, 16#02] + end; + "fl" -> + case SubItem of + "mindur" -> [16#00, 16#04]; + "maxdur" -> [16#00, 16#05] + end + end; + +encode_al(signal, Item) -> + ?d("encode_al(signal) -> entry with" + "~n Item: ~p", [Item]), + case Item of + "ri" -> [16#00, 16#02] + end; + +encode_al({signal_parameter, Item}, SubItem) -> + ?d("encode_al({signal_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + "ri" -> + case SubItem of + "cad" -> [16#00, 16#06]; + "freq" -> [16#00, 16#07] + end + end. + +decode_al(event, SubItem) -> + ?d("decode_al(event) -> entry with" + "~n SubItem: ~p", [SubItem]), + case SubItem of + [16#00, 16#04] -> "on"; + [16#00, 16#05] -> "of"; + [16#00, 16#06] -> "fl" + end; + +decode_al({event_parameter, Item}, SubItem) -> + ?d("decode_al({event_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + [16#00,16#04] -> %% Event: on + case SubItem of + [16#00, 16#01] -> "strict"; + [16#00, 16#02] -> "init" + end; + [16#00,16#05] -> %% Event: of + case SubItem of + [16#00, 16#01] -> "strict"; + [16#00, 16#02] -> "init" + end; + [16#00,16#06] -> %% Event: fl + case SubItem of + [16#00, 16#04] -> "mindur"; + [16#00, 16#05] -> "maxdur" + end + end; + +decode_al(signal, SubItem) -> + ?d("decode_al(signal) -> entry with" + "~n SubItem: ~p", [SubItem]), + case SubItem of + [16#00, 16#02] -> "ri" + end; + +decode_al({signal_parameter, Item}, SubItem) -> + ?d("decode_al({signal_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + [16#00,16#02] -> %% Event: ri + case SubItem of + [16#00, 16#06] -> "cad"; + [16#00, 16#07] -> "freq" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: ct - Basic Continuity Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines events and signals for continuity test. +%% The continuity test includes provision of either a loopback +%% or transceiver functionality. +%%---------------------------------------------------------------------- + +capabilities_ct() -> + [ + {event, "cmp"}, + {signal, "ct"}, + {signal, "rsp"} + ]. + +encode_ct(event, Item) -> + case Item of + "cmp" -> [16#00, 16#05] + end; +encode_ct({event_parameter, Item}, SubItem) -> + case Item of + "cmp" -> + case SubItem of + "res" -> [16#00, 16#08] + end + end; +encode_ct(signal, Item) -> + case Item of + "ct" -> [16#00, 16#03]; + "rsp" -> [16#00, 16#04] + end. + +decode_ct(event, Item) -> + case Item of + [16#00, 16#05] -> "cmp" + end; +decode_ct({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#05] -> % Event cmp + case SubItem of + [16#00, 16#08] -> "res" + end + end; +decode_ct(signal, Item) -> + case Item of + [16#00, 16#03] -> "ct"; + [16#00, 16#04] -> "rsp" + end. + + +%%---------------------------------------------------------------------- +%% Name: nt - Network Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines properties of network terminations +%% independent of network type. +%%---------------------------------------------------------------------- + +capabilities_nt() -> + [ + {property, "jit"}, + {event, "netfail"}, + {event, "qualert"}, + {statistics, "dur"}, + {statistics, "os"}, + {statistics, "or"} + ]. + +encode_nt(property, Item) -> + case Item of + "jit" -> [16#00, 16#07] + end; +encode_nt(event, Item) -> + case Item of + "netfail" -> [16#00, 16#05]; + "qualert" -> [16#00, 16#06] + end; +encode_nt({event_parameter, Item}, SubItem) -> + case Item of + "netfail" -> + case SubItem of + "cs" -> [16#00, 16#01] + end; + "qualert" -> + case SubItem of + "th" -> [16#00, 16#01] + end + end; +encode_nt(statistics, Item) -> + case Item of + "dur" -> [16#00, 16#01]; + "os" -> [16#00, 16#02]; + "or" -> [16#00, 16#03] + end. + +decode_nt(property, Item) -> + case Item of + [16#00, 16#07] -> "jit" + end; +decode_nt(event, Item) -> + case Item of + [16#00, 16#05] -> "netfail"; + [16#00, 16#06] -> "qualert" + end; +decode_nt({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#05] -> % Event netfail + case SubItem of + [16#00, 16#01] -> "cs" + end; + [16#00, 16#06] -> % Event qualert + case Item of + [16#00, 16#01] -> "th" + end + end; +decode_nt(statistics, Item) -> + case Item of + [16#00, 16#01] -> "dur"; + [16#00, 16#02] -> "os"; + [16#00, 16#03] -> "or" + end. + +%%---------------------------------------------------------------------- +%% Name: rtp - RTP Package +%% Version: 1 +%% Extends: nt version 1 +%% Purpose: This package is used to support packet based multimedia +%% data transfer by means of the Real-time Transport Protocol +%% (RTP) [RFC 1889]. +%%---------------------------------------------------------------------- + +capabilities_rtp() -> + [ + {event, "pltrans"}, + {statistics, "ps"}, + {statistics, "pr"}, + {statistics, "pl"}, + {statistics, "jit"}, + {statistics, "delay"} + ]. + +encode_rtp(event, Item) -> + case Item of + "pltrans" -> [16#00, 16#01] + end; +encode_rtp({event_parameter, Item}, SubItem) -> + case Item of + "pltrans" -> + case SubItem of + "rtppltype" -> [16#00, 16#01] + end + end; +encode_rtp(statistics, Item) -> + case Item of + "ps" -> [16#00, 16#04]; + "pr" -> [16#00, 16#05]; + "pl" -> [16#00, 16#06]; + "jit" -> [16#00, 16#07]; + "delay" -> [16#00, 16#08] + end. + +decode_rtp(event, Item) -> + case Item of + [16#00, 16#01] -> "pltrans" + end; +decode_rtp({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event pltrans + case SubItem of + [16#00, 16#01] -> "rtppltype" + end + end; +decode_rtp(statistics, Item) -> + case Item of + [16#00, 16#04] -> "ps"; + [16#00, 16#05] -> "pr"; + [16#00, 16#06] -> "pl"; + [16#00, 16#07] -> "jit"; + [16#00, 16#08] -> "delay" + end. + + +%%---------------------------------------------------------------------- +%% Name: tdmc - TDM Circuit Package +%% Version: 1 +%% Extends: nt version 1 +%% Purpose: This package is used to support TDM circuit terminations. +%%---------------------------------------------------------------------- + +capabilities_tdmc() -> + [ + {property, "ec"}, + {property, "gain"} + ]. + +encode_tdmc(Scope, Item) -> + case Scope of + property -> + case Item of + "ec" -> [16#00, 16#08]; + "gain" -> [16#00, 16#0a] + end + end. + +decode_tdmc(Scope, Item) -> + case Scope of + property -> + case Item of + [16#00, 16#08] -> "ec"; + [16#00, 16#0a] -> "gain" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: swb - SwitchBoard Package +%% Version: 1 +%% Extends: none +%% Purpose: This package is used to support SwitchBoard specials +%%---------------------------------------------------------------------- + +capabilities_swb() -> + [ + {statistics, "fs"}, % Free slots + {statistics, "as"} % Allocated slots + ]. + +encode_swb(Scope, Item) -> + case Scope of + statistics -> + case Item of + "fs" -> [16#00, 16#00]; + "as" -> [16#00, 16#01] + end + end. + +decode_swb(Scope, Item) -> + case Scope of + statistics -> + case Item of + [16#00, 16#00] -> "fs"; + [16#00, 16#01] -> "as" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: native - Pseudo package +%% Version: 1 +%% Extends: None +%% Purpose: Native tags for media stream properties +%% +%% Parameters for Local descriptors and Remote descriptors are +%% specified as tag-value pairs if binary encoding is used for the +%% protocol. This annex contains the property names (PropertyID), the +%% tags (Property Tag), type of the property (Type) and the values +%% (Value).Values presented in the Value field when the field contains +%% references shall be regarded as "information". The reference +%% contains the normative values. If a value field does not contain a +%% reference then the values in that field can be considered as +%% "normative". +%% +%% Tags are given as hexadecimal numbers in this annex. When setting +%% the value of a property, a MGC may underspecify the value according +%% to one of the mechanisms specified in section 7.1.1. +%% +%% For type "enumeration" the value is represented by the value in brack- +%% ets, e.g., Send(0), Receive(1). +%%---------------------------------------------------------------------- +%% +%% C.6. IP +%% +%% ________________________________________________________________ +%% | PropertyID| Tag | Type | Value | +%% | IPv4 | 6001 | 32 BITS | Ipv4Address | +%% | IPv6 | 6002 | 128 BITS | IPv6 Address | +%% | Port | 6003 | Unsigned Int| Port | +%% | Porttype | 6004 | Enumerated | TCP(0),UDP(1),SCTP(2)| +%% |___________|____________|______________|_______________________| +%% +%% +%% C.11. SDP Equivalents +%% +%% ______________________________________________________________ +%% | PropertyID| Tag | Type | Value | +%% | SDP_V | B001| STRING| Protocol Version | +%% | SDP_O | B002| STRING| Owner-creator and session ID | +%% | SDP_S | B003| STRING| Sesson name | +%% | SDP_I | B004| STRING| Session identifier | +%% | SDP_U | B005| STRING| URI of descriptor | +%% | SDC_E | B006| STRING| email address | +%% | SDP_P | B007| STRING| phone number | +%% | SDP_C | B008| STRING| Connection information | +%% | SDP_B | B009| STRING| Bandwidth Information | +%% | SDP_Z | B00A| STRING| time zone adjustment | +%% | SDP_K | B00B| STRING| Encryption Key | +%% | SDP_A | B00C| STRING| Zero or more session attributes| +%% | SDP_T | B00D| STRING| Active Session Time | +%% | SDP_R | B00E| STRING| Zero or more repeat times | +%% | SDP_M | B00F| STRING| Media name and transport addr | +%% | | | | Reference: IETF RFC 2327 | +%% |___________|______|________|_________________________________| +%% +%%---------------------------------------------------------------------- + +capabilities_native() -> + [ + %% C.6. IP + {property, "IPv4"}, + {property, "IPv6"}, + {property, "Port"}, + {property, "Porttype"}, + + %% C.11. SDP Equivalents + {property, "v"}, + {property, "o"}, + {property, "s"}, + {property, "i"}, + {property, "u"}, + {property, "e"}, + {property, "p"}, + {property, "c"}, + {property, "b"}, + {property, "z"}, + {property, "k"}, + {property, "a"}, + {property, "t"}, + {property, "r"}, + {property, "m"} + ]. + +encode_native(Scope, Item) -> + case Scope of + property -> + case Item of + %% IP + "IPv4" -> [16#60, 16#01]; + "IPv6" -> [16#60, 16#02]; + "Port" -> [16#60, 16#03]; + "Porttype" -> [16#60, 16#04]; + + %% SDP + "v" -> [16#b0, 16#01]; + "o" -> [16#b0, 16#02]; + "s" -> [16#b0, 16#03]; + "i" -> [16#b0, 16#04]; + "u" -> [16#b0, 16#05]; + "e" -> [16#b0, 16#06]; + "p" -> [16#b0, 16#07]; + "c" -> [16#b0, 16#08]; + "b" -> [16#b0, 16#09]; + "z" -> [16#b0, 16#0a]; + "k" -> [16#b0, 16#0b]; + "a" -> [16#b0, 16#0c]; + "t" -> [16#b0, 16#0d]; + "r" -> [16#b0, 16#0e]; + "m" -> [16#b0, 16#0f] + end + end. + +decode_native(Scope, [Type, Item]) -> + case Scope of + property -> + case Type of + 16#60 -> + case Item of + 16#01 -> "IPv4"; + 16#02 -> "IPv6"; + 16#03 -> "Port"; + 16#04 -> "Porttype" + end; + + 16#b0 -> + case Item of + 16#01 -> "v"; + 16#02 -> "o"; + 16#03 -> "s"; + 16#04 -> "i"; + 16#05 -> "u"; + 16#06 -> "e"; + 16#07 -> "p"; + 16#08 -> "c"; + 16#09 -> "b"; + 16#0a -> "z"; + 16#0b -> "k"; + 16#0c -> "a"; + 16#0d -> "t"; + 16#0e -> "r"; + 16#0f -> "m" + end + end + end. + +%% ------------------------------------------------------------------- + +% error(Reason) -> +% erlang:error(Reason). + diff --git a/lib/megaco/src/binary/megaco_binary_name_resolver_v2.erl b/lib/megaco/src/binary/megaco_binary_name_resolver_v2.erl new file mode 100644 index 0000000000..53891a26f2 --- /dev/null +++ b/lib/megaco/src/binary/megaco_binary_name_resolver_v2.erl @@ -0,0 +1,1681 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Handle meta data about packages +%%---------------------------------------------------------------------- + +-module(megaco_binary_name_resolver_v2). + +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). +-include_lib("megaco/src/app/megaco_internal.hrl"). + +-define(LOWER(Char), + if + Char >= $A, Char =< $Z -> + Char - ($A - $a); + true -> + Char + end). + +-export([packages/0, + capabilities/0, + capabilities/1, + decode_name/3, + encode_name/3 + ]). + +encode_name(Config, term_id, TermId) -> + case megaco:encode_binary_term_id(Config, TermId) of + {ok, TermId2} -> + TermId2; + {error, _Reason} -> + exit({bad_term_id, TermId}) + end; +encode_name(_Config, Scope, Item) -> + ?d("encode_name(~p) -> entry with" + "~n Item: ~p", [Scope, Item]), + encode(Scope, Item). + +decode_name(Config, term_id, TermId) -> + case megaco:decode_binary_term_id(Config, TermId) of + {ok, TermId2} -> + TermId2; + {error, _Reason} -> + exit({bad_term_id, TermId}) + end; +decode_name(_Config, Scope, Item) -> + ?d("decode_name(~p) -> entry with" + "~n Item: ~p", [Scope, Item]), + decode(Scope, Item). + +%%---------------------------------------------------------------------- +%% 12.1.1 Package +%% +%% Overall description of the package, specifying: +%% +%% Package Name: only descriptive +%% +%% PackageID: is an identifier +%% +%% Description: +%% +%% Version: +%% +%% A new version of a package can only add additional Properties, +%% Events, Signals, Statistics and new possible values for an existing +%% parameter described in the original package. No deletions or +%% modifications shall be allowed. A version is an integer in the range +%% from 1 to 99. +%% +%% Designed to be extended only (Optional): Yes +%% +%% This indicates that the package has been expressly designed to be +%% extended by others, not to be directly referenced. For example, the +%% package may not have any function on its own or be nonsensical on its +%% own. The MG SHOULD NOT publish this PackageID when reporting +%% packages. +%% +%% Extends (Optional): existing package Descriptor +%% +%% A package may extend an existing package. The version of the original +%% package must be specified. When a package extends another package it +%% shall only add additional Properties, Events, Signals, Statistics and +%% new possible values for an existing parameter described in the +%% original package. An extended package shall not redefine or overload +%% an identifier defined in the original package and packages it may +%% have extended (multiple levels of extension). Hence, if package B +%% version 1 extends package A version 1, version 2 of B will not be +%% able to extend the A version 2 if A version 2 defines a name already +%% in B version 1. +%% +%% +%% 12.1.2 Properties +%% +%% Properties defined by the package, specifying: +%% +%% Property Name: only descriptive +%% +%% PropertyID: is an identifier +%% +%% Description: +%% +%% Type: One of: +%% +%% Boolean +%% +%% String: UTF-8 string +%% +%% Octet String: A number of octets. See Annex A and Annex B.3 +%% for encoding +%% +%% Integer: 4 byte signed integer +%% +%% Double: 8 byte signed integer +%% +%% Character: unicode UTF-8 encoding of a single letter. Could be +%% more than one octet. +%% +%% Enumeration: one of a list of possible unique values (see 12.3) +%% +%% Sub-list: a list of several values from a list. The type of +%% sub-list SHALL also be specified. The type shall be chosen +%% from the types specified in this section (with the exception of +%% sub-list). For example, Type: sub-list of enumeration. The +%% encoding of sub-lists is specified in Annexes A and B.3. +%% +%% Possible values: +%% +%% A package MUST specify either a specific set of values or a +%% description of how values are determined. A package MUST also +%% specify a default value or the default behaviour when the value is +%% omitted from its descriptor. For example, a package may specify that +%% procedures related to the property are suspended when it value is +%% omitted. A default value (but not procedures) may be specified as +%% provisionable. +%% +%% Defined in: +%% +%% Which H.248.1 descriptor the property is defined in. LocalControl is +%% for stream dependent properties. TerminationState is for stream +%% independent properties. These are expected to be the most common +%% cases, but it is possible for properties to be defined in other +%% descriptors. +%% +%% Characteristics: Read/Write or both, and (optionally), global: +%% +%% Indicates whether a property is read-only, or read-write, and if it +%% is global. If Global is omitted, the property is not global. If a +%% property is declared as global, the value of the property is shared +%% by all Terminations realizing the package. +%% +%% +%% 12.1.3 Events +%% +%% Events defined by the package, specifying: +%% +%% Event name: only descriptive +%% +%% EventID: is an identifier +%% +%% Description: +%% +%% EventsDescriptor Parameters: +%% +%% Parameters used by the MGC to configure the event, and found in the +%% EventsDescriptor. See 12.2. +%% +%% ObservedEventsDescriptor Parameters: +%% +%% Parameters returned to the MGC in Notify requests and in replies to +%% command requests from the MGC that audit ObservedEventsDescriptor, +%% and found in the ObservedEventsDescriptor. See 12.2. +%% +%% +%% 12.1.4 Signals +%% +%% Signals defined by the package, specifying: +%% +%% Signal Name: only descriptive +%% +%% SignalID: is an identifier. SignalID is used in a +%% SignalsDescriptor +%% +%% Description +%% +%% SignalType: one of: +%% +%% OO (On/Off) +%% +%% TO (TimeOut) +%% +%% BR (Brief) +%% +%% NOTE - SignalType may be defined such that it is dependent on the +%% value of one or more parameters. The package MUST specify a default +%% signal type. If the default type is TO, the package MUST specify a +%% default duration which may be provisioned. A default duration is +%% meaningless for BR. +%% +%% Duration: in hundredths of seconds +%% +%% Additional Parameters: see 12.2 +%% +%% +%% 12.1.5 Statistics +%% +%% Statistics defined by the package, specifying: +%% +%% Statistic name: only descriptive +%% +%% StatisticID: is an identifier +%% +%% StatisticID is used in a StatisticsDescriptor +%% +%% Description: +%% +%% Type: One of: +%% Boolean +%% String: UTF-8 string +%% Octet String: A number of octets. See Annex A and B.3 for encoding +%% Integer: 4 byte signed integer +%% Double: 8 byte signed integer +%% Character: Unicode UTF-8 encoding of a single letter. +%% Could be more than one octet. +%% Enumeration: One of a list of possible unique values (see 12.3) +%% Sub-list: A list of several values from a list. +%% The type of sub-list SHALL also be specified. +%% The type shall be chosen from the types specified +%% in this clause (with the exception of sub-list). +%% For example, Type: sub-list of enumeration. +%% The encoding of sub-lists is specified in +%% Annex A and B.3. +%% Possible Values: +%% A package must indicate the unit of measure, e.g., +%% milliseconds, packets, either here or along with the type +%% above, as well as indicating any restriction on the range. +%% +%% +%% 12.1.6 Procedures +%% +%% Additional guidance on the use of the package. +%% +%% +%% 12.2 Guidelines to defining Parameters to Events and Signals +%% +%% Parameter Name: only descriptive +%% +%% ParameterID: is an identifier. The textual ParameterID of +%% parameters to Events and Signals shall not start with "EPA" and +%% "SPA", respectively. The textual ParameterID shall also not be +%% "ST", "Stream", "SY", "SignalType", "DR", "Duration", "NC", +%% "NotifyCompletion", "KA", "Keepactive", "EB", "Embed", "DM" or +%% "DigitMap". +%% +%% Type: One of: +%% +%% Boolean +%% +%% String: UTF-8 octet string +%% +%% Octet String: A number of octets. See Annex A and Annex B.3 +%% for encoding +%% +%% Integer: 4-octet signed integer +%% +%% Double: 8-octet signed integer +%% +%% Character: unicode UTF-8 encoding of a single letter. Could be +%% more than one octet. +%% +%% Enumeration: one of a list of possible unique values (see 12.3) +%% +%% Sub-list: a list of several values from a list (not supported +%% for statistics). The type of sub-list SHALL also be specified. +%% The type shall be chosen from the types specified in this +%% section (with the exception of sub-list). For example, Type: +%% sub-list of enumeration. The encoding of sub-lists is +%% specified in Annexes A and B.3. +%% +%% Possible values: +%% +%% A package MUST specify either a specific set of values or a +%% description of how values are determined. A package MUST also +%% specify a default value or the default behavior when the value is +%% omitted from its descriptor. For example, a package may specify that +%% procedures related to the parameter are suspended when it value is +%% omitted. A default value (but not procedures) may be specified as +%% provisionable. +%% +%% Description: +%% +%% +%% 12.3 Lists +%% +%% Possible values for parameters include enumerations. Enumerations may +%% be defined in a list. It is recommended that the list be IANA +%% registered so that packages that extend the list can be defined +%% without concern for conflicting names. +%% +%% +%% 12.4 Identifiers +%% +%% Identifiers in text encoding shall be strings of up to 64 characters, +%% containing no spaces, starting with an alphabetic character and +%% consisting of alphanumeric characters and/or digits, and possibly +%% including the special character underscore ("_"). +%% +%% Identifiers in binary encoding are 2 octets long. +%% +%% Both text and binary values shall be specified for each identifier, +%% including identifiers used as values in enumerated types. +%% +%% +%% 12.5 Package registration +%% +%% A package can be registered with IANA for interoperability reasons. +%% See clause 14 for IANA considerations. +%% +%%---------------------------------------------------------------------- + +capabilities() -> + [{P, capabilities(P)} || P <- packages()]. + +%% -record(property, {name, type, values, defined_in, characteristics}). + +%%---------------------------------------------------------------------- +%% List all known packages +%% 'native' and 'all' are not real packages +%%---------------------------------------------------------------------- + +packages() -> + [ + "g", % Generic + "root", % Base Root Package + "tonegen", % Tone Generator Package + "tonedet", % Tone Detection Package + "dg", % Basic DTMF Generator Package + "dd", % DTMF detection Package + "cg", % Call Progress Tones Generator Package + "cd", % Call Progress Tones Detection Package + "al", % Analog Line Supervision Package + "ct", % Basic Continuity Package + "nt", % Network Package + "rtp", % RTP Package + "swb", % SwitchBoard Package + "tdmc", % TDM Circuit Package + "" % Native pseudo package + ]. + +%%---------------------------------------------------------------------- +%% List all matching capabilities +%%---------------------------------------------------------------------- + +capabilities(Package) -> + case Package of + "g" -> capabilities_g(); + "root" -> capabilities_root(); + "tonegen" -> capabilities_tonegen(); + "tonedet" -> capabilities_tonedet(); + "dg" -> capabilities_dg(); + "dd" -> capabilities_dd(); + "cg" -> capabilities_cg(); + "cd" -> capabilities_cd(); + "al" -> capabilities_al(); + "ct" -> capabilities_ct(); + "nt" -> capabilities_nt(); + "rtp" -> capabilities_rtp(); + "swb" -> capabilities_swb(); + "tdmc" -> capabilities_tdmc(); + "" -> capabilities_native() + end. + +%%---------------------------------------------------------------------- +%% Decode package name to internal form +%% Scope ::= property | event | signal | statistics +%%---------------------------------------------------------------------- + +decode(mid, Package) -> + decode_mid(Package); +decode(package, Package) -> + decode_package(Package); +decode(profile, Package) -> + decode_profile(Package); +decode(dialplan, Dialplan) -> + decode_dialplan(Dialplan); +decode(Scope, [A, B | Item]) when is_atom(Scope) -> + ?d("decode(~p) -> entry with" + "~n A: ~p" + "~n B: ~p" + "~n Item: ~p", [Scope, A, B, Item]), + case decode_package([A, B]) of + "" -> + ?d("decode -> \"no\" package",[]), + decode_item(Scope, [A, B], Item); + Package -> + ?d("decode -> Package: ~p", [Package]), + Package ++ "/" ++ decode_item(Scope, [A, B], Item) + end; +decode({Scope, [A, B | Item]}, SubItem) when is_atom(Scope) -> + ?d("decode(~p) -> entry with" + "~n A: ~p" + "~n B: ~p" + "~n Item: ~p" + "~n SubItem: ~p", [Scope, A, B, Item, SubItem]), + decode_item({Scope, Item}, [A, B], SubItem). + +decode_item(Scope, [A, B], Item) -> + ?d("decode_item -> entry",[]), + case A of + 16#00 -> + case B of + 16#01 -> decode_g(Scope, Item); + 16#02 -> decode_root(Scope, Item); + 16#03 -> decode_tonegen(Scope, Item); + 16#04 -> decode_tonedet(Scope, Item); + 16#05 -> decode_dg(Scope, Item); + 16#06 -> decode_dd(Scope, Item); + 16#07 -> decode_cg(Scope, Item); + 16#08 -> decode_cd(Scope, Item); + 16#09 -> decode_al(Scope, Item); + 16#0a -> decode_ct(Scope, Item); + 16#0b -> decode_nt(Scope, Item); + 16#0c -> decode_rtp(Scope, Item); + 16#0d -> decode_tdmc(Scope, Item); + 16#00 -> decode_native(Scope, Item) + end; + 16#fe -> + case B of + %% Proprietary extension + 16#fe -> decode_swb(Scope, Item) + end; + 16#ff -> + case B of + 16#ff when Item =:= [16#ff, 16#ff] -> "*" + end + end. + +decode_package(Package) -> + ?d("decode_package -> entry with" + "~n Package: ~p", [Package]), + [A, B] = Package, + case A of + 16#00 -> + case B of + 16#01 -> "g"; + 16#02 -> "root"; + 16#03 -> "tonegen"; + 16#04 -> "tonedet"; + 16#05 -> "dg"; + 16#06 -> "dd"; + 16#07 -> "cg"; + 16#08 -> "cd"; + 16#09 -> "al"; + 16#0a -> "ct"; + 16#0b -> "nt"; + 16#0c -> "rtp"; + 16#0d -> "tdmc"; + 16#00 -> "" + end; + 16#fe -> + case B of + 16#fe -> "swb" + end; + 16#ff -> + case B of + 16#ff -> "*" + end + end. + +decode_profile([A, B]) -> + case A of + 16#00 -> + case B of + 16#fe -> "resgw"; + _ -> "profile" ++ [A + $0, B + $0] + end; + _ -> + "profile" ++ [A + $0, B + $0] + end. + +decode_dialplan([A, B]) -> + "dialplan" ++ [A + $0, B + $0]. + +decode_mid(Mid) -> + case Mid of + {domainName, DN} -> + Lower = to_lower(DN#'DomainName'.name), + {domainName, DN#'DomainName'{name = Lower}}; + {deviceName, PathName} -> + Lower = to_lower(PathName), + {deviceName, Lower}; + Other -> + Other + end. + +to_lower(Chars) -> + [?LOWER(Char) || Char <- Chars]. + +%%---------------------------------------------------------------------- +%% Encode package name from internal form +%% Scope ::= property | event | signal | statistics +%%---------------------------------------------------------------------- + +encode(mid, Package) -> + encode_mid(Package); +encode(package, Package) -> + encode_package(Package); +encode(profile, Profile) -> + encode_profile(Profile); +encode(dialplan, Dialplan) -> + encode_dialplan(Dialplan); +encode(Scope, PackageItem) when is_atom(Scope) -> + ?d("encode(~p) -> entry with" + "~n PackageItem: ~p", [Scope, PackageItem]), + case string:tokens(PackageItem, [$/]) of + [Package, Item] -> + ?d("encode -> " + "~n Package: ~p" + "~n Item: ~p", [Package, Item]), + encode_package(Package) ++ encode_item(Scope, Package, Item); + [Item] -> + ?d("encode -> Item: ~p", [Item]), + [16#00, 16#00 | encode_native(Scope, Item)] + end; +encode({Scope, PackageItem}, SubItem) when is_atom(Scope) -> + ?d("encode(~p) -> entry with" + "~n PackageItem: ~p" + "~n SubItem: ~p", [Scope, PackageItem, SubItem]), + case string:tokens(PackageItem, [$/]) of + [Package, Item] -> + ?d("encode -> " + "~n Package: ~p" + "~n Item: ~p", [Package, Item]), + encode_item({Scope, Item}, Package, SubItem); + [_Item] -> + ?d("encode -> _Item: ~p", [_Item]), + encode_native(Scope, SubItem) + end. + +encode_item(_Scope, _Package, "*") -> + [16#ff, 16#ff]; +encode_item(Scope, Package, Item) -> + ?d("encode_item(~s) -> entry", [Package]), + case Package of + "g" -> encode_g(Scope, Item); + "root" -> encode_root(Scope, Item); + "tonegen" -> encode_tonegen(Scope, Item); + "tonedet" -> encode_tonedet(Scope, Item); + "dg" -> encode_dg(Scope, Item); + "dd" -> encode_dd(Scope, Item); + "cg" -> encode_cg(Scope, Item); + "cd" -> encode_cd(Scope, Item); + "al" -> encode_al(Scope, Item); + "ct" -> encode_ct(Scope, Item); + "nt" -> encode_nt(Scope, Item); + "rtp" -> encode_rtp(Scope, Item); + "tdmc" -> encode_tdmc(Scope, Item); + "swb" -> encode_swb(Scope, Item) + end. + +encode_package(Package) -> + case Package of + "g" -> [16#00, 16#01]; + "root" -> [16#00, 16#02]; + "tonegen" -> [16#00, 16#03]; + "tonedet" -> [16#00, 16#04]; + "dg" -> [16#00, 16#05]; + "dd" -> [16#00, 16#06]; + "cg" -> [16#00, 16#07]; + "cd" -> [16#00, 16#08]; + "al" -> [16#00, 16#09]; + "ct" -> [16#00, 16#0a]; + "nt" -> [16#00, 16#0b]; + "rtp" -> [16#00, 16#0c]; + "tdmc" -> [16#00, 16#0d]; + "" -> [16#00, 16#00]; + "*" -> [16#ff, 16#ff]; + "swb" -> [16#fe, 16#fe] + end. + +encode_profile(Profile) -> + case Profile of + "resgw" -> + [16#00, 16#fe]; + [$p, $r, $o, $f, $i, $l, $e | Name] -> + case Name of + [A, B] -> [A - $0, B - $0]; + [B] -> [0, B - $0]; + [] -> [0, 0] + end + end. + +encode_dialplan(Dialplan) -> + case Dialplan of + [$d, $i, $a, $l, $p, $l, $a, $n | Name] -> + case Name of + [A, B] -> [A - $0, B - $0]; + [B] -> [0, B - $0]; + [] -> [0, 0] + end + end. + +encode_mid(Mid) -> + Mid. + + +%%---------------------------------------------------------------------- +%% Name: g - Generic +%% Version: 1 +%% Extends: None +%% Purpose: Generic package for commonly encountered items +%%---------------------------------------------------------------------- + +capabilities_g() -> + [ + {event, "cause"}, + {event, "sc"} + ]. + +encode_g(event, Item) -> + case Item of + "cause" -> [16#00, 16#01]; + "sc" -> [16#00, 16#02] + end; + +encode_g({event_parameter, Item}, SubItem) -> + case Item of + "cause" -> + case SubItem of + "Generalcause" -> [16#00, 16#01]; + "Failurecause" -> [16#00, 16#02] + end; + "sc" -> + case SubItem of + "SigID" -> [16#00, 16#01]; + "Meth" -> [16#00, 16#02]; + "SLID" -> [16#00, 16#03] + end + end. + +decode_g(event, Item) -> + case Item of + [16#00, 16#01] -> "cause"; + [16#00, 16#02] -> "sc" + end; + +decode_g({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event: cause + case SubItem of + [16#00, 16#01] -> "Generalcause"; + [16#00, 16#02] -> "Failurecause" + end; + + [16#00, 16#02] -> % Event: sc + case SubItem of + [16#00, 16#01] -> "SigID"; + [16#00, 16#02] -> "Meth"; + [16#00, 16#03] -> "SLID" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: root - Base Root Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines Gateway wide properties. +%%---------------------------------------------------------------------- + +capabilities_root() -> + [ + {property, "maxNumberOfContexts"}, + {property, "maxTerminationsPerContext"}, + {property, "normalMGExecutionTime"}, + {property, "normalMGCExecutionTime"}, + {property, "MGProvisionalResponseTimerValue"}, + {property, "MGCProvisionalResponseTimerValue"}, + {property, "MGCOriginatedPendingLimit"}, + {property, "MGOriginatedPendingLimit"} + ]. + +encode_root(Scope, Item) -> + case Scope of + property -> + case Item of + "maxNumberOfContexts" -> [16#00, 16#01]; + "maxTerminationsPerContext" -> [16#00, 16#02]; + "normalMGExecutionTime" -> [16#00, 16#03]; + "normalMGCExecutionTime" -> [16#00, 16#04]; + "MGProvisionalResponseTimerValue" -> [16#00, 16#05]; + "MGCProvisionalResponseTimerValue" -> [16#00, 16#06]; + "MGCOriginatedPendingLimit" -> [16#00, 16#07]; + "MGOriginatedPendingLimit" -> [16#00, 16#08] + end + end. + +decode_root(Scope, Item) -> + case Scope of + property -> + case Item of + [16#00, 16#01] -> "maxNumberOfContexts"; + [16#00, 16#02] -> "maxTerminationsPerContext"; + [16#00, 16#03] -> "normalMGExecutionTime"; + [16#00, 16#04] -> "normalMGCExecutionTime"; + [16#00, 16#05] -> "MGProvisionalResponseTimerValue"; + [16#00, 16#06] -> "MGCProvisionalResponseTimerValue"; + [16#00, 16#07] -> "MGCOriginatedPendingLimit"; + [16#00, 16#08] -> "MGOriginatedPendingLimit" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: tonegen - Tone Generator Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines signals to generate audio tones. +%% This package does not specify parameter values. It is +%% intended to be extendable. Generally, tones are defined +%% as an individual signal with a parameter, ind, +%% representing "interdigit" time delay, and a tone id to +%% be used with playtones. A tone id should be kept +%% consistent with any tone generation for the same tone. +%% MGs are expected to be provisioned with the characteristics +%% of appropriate tones for the country in which the MG is located. +%%---------------------------------------------------------------------- + +capabilities_tonegen() -> + [ + {signal, "pt"} + ]. + +encode_tonegen(signal, Item) -> + case Item of + "pt" -> [16#00, 16#01] + end; + +encode_tonegen({signal_parameter, Item}, SubItem) -> + case Item of + "pt" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "ind" -> [16#00, 16#02] + end + end. + +decode_tonegen(signal, Item) -> + case Item of + [16#00, 16#01] -> "pt" + end; + +decode_tonegen({signal_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event: pt + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#02] -> "ind" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: tonedet - Tone Detection Package +%% Version: 1 +%% Extends: None +%% Purpose: This Package defines events for audio tone detection. +%% Tones are selected by name (tone id). MGs are expected +%% to be provisioned with the characteristics of appropriate +%% tones for the country in which the MG is located. +%% +%% This package does not specify parameter values. +%% It is intended to be extendable. +%%---------------------------------------------------------------------- + +capabilities_tonedet() -> + [ + {event, "std"}, + {event, "etd"}, + {event, "ltd"} + ]. + +encode_tonedet(event, Item) -> + case Item of + "std" -> [16#00, 16#01]; + "etd" -> [16#00, 16#02]; + "ltd" -> [16#00, 16#03] + end; + +encode_tonedet({event_parameter, Item}, SubItem) -> + case Item of + "std" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "tid" -> [16#00, 16#03] + end; + "etd" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "tid" -> [16#00, 16#03]; + "dur" -> [16#00, 16#02] + end; + "ltd" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "dur" -> [16#00, 16#02]; + "tid" -> [16#00, 16#03] + end + end. + +decode_tonedet(event, Item) -> + case Item of + [16#00, 16#01] -> "std"; + [16#00, 16#02] -> "etd"; + [16#00, 16#03] -> "ltd" + end; + +decode_tonedet({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event std + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#03] -> "tid" + end; + [16#00, 16#02] -> % Event etd + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#03] -> "tid"; + [16#00, 16#02] -> "dur" + end; + [16#00, 16#03] -> % Event ltd + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#02] -> "dur"; + [16#00, 16#03] -> "tid" + end + end. + +%%---------------------------------------------------------------------- +%% Name: dg - Basic DTMF Generator Package +%% Version: 1 +%% Extends: tonegen version 1 +%% Purpose: This package defines the basic DTMF tones as signals and +%% extends the allowed values of parameter tl of playtone +%% in tonegen. +%%---------------------------------------------------------------------- + +capabilities_dg() -> + [ + {signal, "d0"}, + {signal, "d1"}, + {signal, "d2"}, + {signal, "d3"}, + {signal, "d4"}, + {signal, "d5"}, + {signal, "d6"}, + {signal, "d7"}, + {signal, "d8"}, + {signal, "d9"}, + {signal, "ds"}, + {signal, "do"}, + {signal, "da"}, + {signal, "db"}, + {signal, "dc"}, + {signal, "dd"} + ]. + +encode_dg(Scope, Item) -> + case Scope of + signal -> + case Item of + "d0" -> [16#00, 16#10]; + "d1" -> [16#00, 16#11]; + "d2" -> [16#00, 16#12]; + "d3" -> [16#00, 16#13]; + "d4" -> [16#00, 16#14]; + "d5" -> [16#00, 16#15]; + "d6" -> [16#00, 16#16]; + "d7" -> [16#00, 16#17]; + "d8" -> [16#00, 16#18]; + "d9" -> [16#00, 16#19]; + "ds" -> [16#00, 16#20]; + "do" -> [16#00, 16#21]; + "da" -> [16#00, 16#1a]; + "db" -> [16#00, 16#1b]; + "dc" -> [16#00, 16#1c]; + "dd" -> [16#00, 16#1d] + end + end. + +decode_dg(Scope, Item) -> + case Scope of + signal -> + case Item of + [16#00, 16#10] -> "d0"; + [16#00, 16#11] -> "d1"; + [16#00, 16#12] -> "d2"; + [16#00, 16#13] -> "d3"; + [16#00, 16#14] -> "d4"; + [16#00, 16#15] -> "d5"; + [16#00, 16#16] -> "d6"; + [16#00, 16#17] -> "d7"; + [16#00, 16#18] -> "d8"; + [16#00, 16#19] -> "d9"; + [16#00, 16#20] -> "ds"; + [16#00, 16#21] -> "do"; + [16#00, 16#1a] -> "da"; + [16#00, 16#1b] -> "db"; + [16#00, 16#1c] -> "dc"; + [16#00, 16#1d] -> "dd" + end + end. + +%%---------------------------------------------------------------------- +%% Name: dd - DTMF detection Package +%% Version: 1 +%% Extends: tonedet version 1 +%% Purpose: This package defines the basic DTMF tones detection. +%% Tones are selected by name (tone id). MGs are expected +%% to be provisioned with the characteristics of appropriate +%% tones for the country in which the MG is located. +%% +%% This package does not specify parameter values. +%% It is intended to be extendable. +%% +%% Additional tone id values are all tone ids described in package dg +%% (basic DTMF generator package). +%% +%% The following table maps DTMF events to digit map symbols as described +%% in section 7.1.14. +%% +%% _________________________________ +%% | DTMF Event | Symbol | +%% | d0 | "0" | +%% | d1 | "1" | +%% | d2 | "2" | +%% | d3 | "3" | +%% | d4 | "4" | +%% | d5 | "5" | +%% | d6 | "6" | +%% | d7 | "7" | +%% | d8 | "8" | +%% | d9 | "9" | +%% | da | "A" or "a"| +%% | db | "B" or "b"| +%% | dc | "C" or "c"| +%% | dd | "D" or "d"| +%% | ds | "E" or "e"| +%% | do | "F" or "f"| +%% |___________________|____________| +%% +%%---------------------------------------------------------------------- + +capabilities_dd() -> + [ + {event, "ce"}, + {event, "d0"}, + {event, "d1"}, + {event, "d2"}, + {event, "d3"}, + {event, "d4"}, + {event, "d5"}, + {event, "d6"}, + {event, "d7"}, + {event, "d8"}, + {event, "d9"}, + {event, "ds"}, + {event, "do"}, + {event, "da"}, + {event, "db"}, + {event, "dc"}, + {event, "dd"} + ]. + +encode_dd(event, Item) -> + case Item of + "ce" -> [16#00, 16#04]; + "d0" -> [16#00, 16#10]; + "d1" -> [16#00, 16#11]; + "d2" -> [16#00, 16#12]; + "d3" -> [16#00, 16#13]; + "d4" -> [16#00, 16#14]; + "d5" -> [16#00, 16#15]; + "d6" -> [16#00, 16#16]; + "d7" -> [16#00, 16#17]; + "d8" -> [16#00, 16#18]; + "d9" -> [16#00, 16#19]; + "ds" -> [16#00, 16#20]; + "do" -> [16#00, 16#21]; + "da" -> [16#00, 16#1a]; + "db" -> [16#00, 16#1b]; + "dc" -> [16#00, 16#1c]; + "dd" -> [16#00, 16#1d] + end; + +encode_dd({event_parameter, Item}, SubItem) -> + case Item of + "ce" -> + case SubItem of + "ds" -> [16#00, 16#01]; + "Meth" -> [16#00, 16#03] + end + end. + +decode_dd(event, Item) -> + case Item of + [16#00, 16#04] -> "ce"; + [16#00, 16#10] -> "d0"; + [16#00, 16#11] -> "d1"; + [16#00, 16#12] -> "d2"; + [16#00, 16#13] -> "d3"; + [16#00, 16#14] -> "d4"; + [16#00, 16#15] -> "d5"; + [16#00, 16#16] -> "d6"; + [16#00, 16#17] -> "d7"; + [16#00, 16#18] -> "d8"; + [16#00, 16#19] -> "d9"; + [16#00, 16#20] -> "ds"; + [16#00, 16#21] -> "do"; + [16#00, 16#1a] -> "da"; + [16#00, 16#1b] -> "db"; + [16#00, 16#1c] -> "dc"; + [16#00, 16#1d] -> "dd" + end; + +decode_dd({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#04] -> % Event ce + case SubItem of + [16#00, 16#01] -> "ds"; + [16#00, 16#03] -> "Meth" + end + end. + +%%---------------------------------------------------------------------- +%% Name: cg - Call Progress Tones Generator Package +%% Version: 1 +%% Extends: tonegen version 1 +%% Purpose: This package defines the basic call progress tones as signals +%% and extends the allowed values of the tl parameter of +%% playtone in tonegen. +%%---------------------------------------------------------------------- + +capabilities_cg() -> + [ + {signal, "dt"}, + {signal, "rt"}, + {signal, "bt"}, + {signal, "ct"}, + {signal, "sit"}, + {signal, "wt"}, + {signal, "prt"}, + {signal, "cw"}, + {signal, "cr"} + ]. + + +encode_cg(Scope, Item) -> + case Scope of + signal -> + case Item of + "dt" -> [16#00, 16#30]; + "rt" -> [16#00, 16#31]; + "bt" -> [16#00, 16#32]; + "ct" -> [16#00, 16#33]; + "sit" -> [16#00, 16#34]; + "wt" -> [16#00, 16#35]; + "prt" -> [16#00, 16#36]; + "cw" -> [16#00, 16#37]; + "cr" -> [16#00, 16#38] + end + end. + +decode_cg(Scope, Item) -> + case Scope of + signal -> + case Item of + [16#00, 16#30] -> "dt"; + [16#00, 16#31] -> "rt"; + [16#00, 16#32] -> "bt"; + [16#00, 16#33] -> "ct"; + [16#00, 16#34] -> "sit"; + [16#00, 16#35] -> "wt"; + [16#00, 16#36] -> "prt"; + [16#00, 16#37] -> "cw"; + [16#00, 16#38] -> "cr" + end + end. + +%%---------------------------------------------------------------------- +%% Name: cd - Call Progress Tones Detection Package +%% Version: 1 +%% Extends: tonedet version 1 +%% Purpose: This package defines the basic call progress detection tones. +%% This Package extends the possible values of tone id +%% in the "start tone detected", "end tone detected" and +%% "long tone detected" events. +%% Additional values +%% tone id values are defined for start tone detected, +%% end tone detected and long tone detected with +%% the same values as those in package cg (call +%% progress tones generation package). +%% +%% The required set of tone ids corresponds to Recommendation E.180/Q.35 +%% [ITU-T Recommendation E.180/Q.35 (1998)]. See Recommendation E.180/Q.35 +%% for definition of the meanings of these tones. +%%---------------------------------------------------------------------- + +capabilities_cd() -> + [ + {event, "dt"}, + {event, "rt"}, + {event, "bt"}, + {event, "ct"}, + {event, "sit"}, + {event, "wt"}, + {event, "prt"}, + {event, "cw"}, + {event, "cr"} + ]. + + +encode_cd(Scope, Item) -> + case Scope of + event -> + case Item of + "dt" -> [16#00, 16#30]; + "rt" -> [16#00, 16#31]; + "bt" -> [16#00, 16#32]; + "ct" -> [16#00, 16#33]; + "sit"-> [16#00, 16#34]; + "wt" -> [16#00, 16#35]; + "prt"-> [16#00, 16#36]; + "cw" -> [16#00, 16#37]; + "cr" -> [16#00, 16#38] + end + end. + +decode_cd(Scope, Item) -> + case Scope of + event -> + case Item of + [16#00, 16#30] -> "dt"; + [16#00, 16#31] -> "rt"; + [16#00, 16#32] -> "bt"; + [16#00, 16#33] -> "ct"; + [16#00, 16#34] -> "sit"; + [16#00, 16#35] -> "wt"; + [16#00, 16#36] -> "prt"; + [16#00, 16#37] -> "cw"; + [16#00, 16#38] -> "cr" + end + end. + +%%---------------------------------------------------------------------- +%% Name: al - Analog Line Supervision Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines events and signals for an analog line. +%%---------------------------------------------------------------------- + +capabilities_al() -> + [ + {event, "on"}, + {event, "of"}, + {event, "fl"}, + {signal, "ri"} + ]. + +encode_al(event, Item) -> + ?d("encode_al(event) -> entry with" + "~n Item: ~p", [Item]), + case Item of + "on" -> [16#00, 16#04]; + "of" -> [16#00, 16#05]; + "fl" -> [16#00, 16#06] + end; + +encode_al({event_parameter, Item}, SubItem) -> + ?d("encode_al({event_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + "on" -> + case SubItem of + "strict" -> [16#00, 16#01]; + "init" -> [16#00, 16#02] + end; + "of" -> + case SubItem of + "strict" -> [16#00, 16#01]; + "init" -> [16#00, 16#02] + end; + "fl" -> + case SubItem of + "mindur" -> [16#00, 16#04]; + "maxdur" -> [16#00, 16#05] + end + end; + +encode_al(signal, Item) -> + ?d("encode_al(signal) -> entry with" + "~n Item: ~p", [Item]), + case Item of + "ri" -> [16#00, 16#02] + end; + +encode_al({signal_parameter, Item}, SubItem) -> + ?d("encode_al({signal_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + "ri" -> + case SubItem of + "cad" -> [16#00, 16#06]; + "freq" -> [16#00, 16#07] + end + end. + +decode_al(event, SubItem) -> + ?d("decode_al(event) -> entry with" + "~n SubItem: ~p", [SubItem]), + case SubItem of + [16#00, 16#04] -> "on"; + [16#00, 16#05] -> "of"; + [16#00, 16#06] -> "fl" + end; + +decode_al({event_parameter, Item}, SubItem) -> + ?d("decode_al({event_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + [16#00,16#04] -> %% Event: on + case SubItem of + [16#00, 16#01] -> "strict"; + [16#00, 16#02] -> "init" + end; + [16#00,16#05] -> %% Event: of + case SubItem of + [16#00, 16#01] -> "strict"; + [16#00, 16#02] -> "init" + end; + [16#00,16#06] -> %% Event: fl + case SubItem of + [16#00, 16#04] -> "mindur"; + [16#00, 16#05] -> "maxdur" + end + end; + +decode_al(signal, SubItem) -> + ?d("decode_al(signal) -> entry with" + "~n SubItem: ~p", [SubItem]), + case SubItem of + [16#00, 16#02] -> "ri" + end; + +decode_al({signal_parameter, Item}, SubItem) -> + ?d("decode_al({signal_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + [16#00,16#02] -> %% Event: ri + case SubItem of + [16#00, 16#06] -> "cad"; + [16#00, 16#07] -> "freq" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: ct - Basic Continuity Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines events and signals for continuity test. +%% The continuity test includes provision of either a loopback +%% or transceiver functionality. +%%---------------------------------------------------------------------- + +capabilities_ct() -> + [ + {event, "cmp"}, + {signal, "ct"}, + {signal, "rsp"} + ]. + +encode_ct(event, Item) -> + case Item of + "cmp" -> [16#00, 16#05] + end; +encode_ct({event_parameter, Item}, SubItem) -> + case Item of + "cmp" -> + case SubItem of + "res" -> [16#00, 16#08] + end + end; +encode_ct(signal, Item) -> + case Item of + "ct" -> [16#00, 16#03]; + "rsp" -> [16#00, 16#04] + end. + +decode_ct(event, Item) -> + case Item of + [16#00, 16#05] -> "cmp" + end; +decode_ct({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#05] -> % Event cmp + case SubItem of + [16#00, 16#08] -> "res" + end + end; +decode_ct(signal, Item) -> + case Item of + [16#00, 16#03] -> "ct"; + [16#00, 16#04] -> "rsp" + end. + +%%---------------------------------------------------------------------- +%% Name: nt - Network Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines properties of network terminations +%% independent of network type. +%%---------------------------------------------------------------------- + +capabilities_nt() -> + [ + {property, "jit"}, + {event, "netfail"}, + {event, "qualert"}, + {statistics, "dur"}, + {statistics, "os"}, + {statistics, "or"} + ]. + +encode_nt(property, Item) -> + case Item of + "jit" -> [16#00, 16#07] + end; +encode_nt(event, Item) -> + case Item of + "netfail" -> [16#00, 16#05]; + "qualert" -> [16#00, 16#06] + end; +encode_nt({event_parameter, Item}, SubItem) -> + case Item of + "netfail" -> + case SubItem of + "cs" -> [16#00, 16#01] + end; + "qualert" -> + case SubItem of + "th" -> [16#00, 16#01] + end + end; +encode_nt(statistics, Item) -> + case Item of + "dur" -> [16#00, 16#01]; + "os" -> [16#00, 16#02]; + "or" -> [16#00, 16#03] + end. + +decode_nt(property, Item) -> + case Item of + [16#00, 16#07] -> "jit" + end; +decode_nt(event, Item) -> + case Item of + [16#00, 16#05] -> "netfail"; + [16#00, 16#06] -> "qualert" + end; +decode_nt({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#05] -> % Event netfail + case SubItem of + [16#00, 16#01] -> "cs" + end; + [16#00, 16#06] -> % Event qualert + case Item of + [16#00, 16#01] -> "th" + end + end; +decode_nt(statistics, Item) -> + case Item of + [16#00, 16#01] -> "dur"; + [16#00, 16#02] -> "os"; + [16#00, 16#03] -> "or" + end. + +%%---------------------------------------------------------------------- +%% Name: rtp - RTP Package +%% Version: 1 +%% Extends: nt version 1 +%% Purpose: This package is used to support packet based multimedia +%% data transfer by means of the Real-time Transport Protocol +%% (RTP) [RFC 1889]. +%%---------------------------------------------------------------------- + +capabilities_rtp() -> + [ + {event, "pltrans"}, + {statistics, "ps"}, + {statistics, "pr"}, + {statistics, "pl"}, + {statistics, "jit"}, + {statistics, "delay"} + ]. + +encode_rtp(event, Item) -> + case Item of + "pltrans" -> [16#00, 16#01] + end; +encode_rtp({event_parameter, Item}, SubItem) -> + case Item of + "pltrans" -> + case SubItem of + "rtppltype" -> [16#00, 16#01] + end + end; +encode_rtp(statistics, Item) -> + case Item of + "ps" -> [16#00, 16#04]; + "pr" -> [16#00, 16#05]; + "pl" -> [16#00, 16#06]; + "jit" -> [16#00, 16#07]; + "delay" -> [16#00, 16#08] + end. + +decode_rtp(event, Item) -> + case Item of + [16#00, 16#01] -> "pltrans" + end; +decode_rtp({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event pltrans + case SubItem of + [16#00, 16#01] -> "rtppltype" + end + end; +decode_rtp(statistics, Item) -> + case Item of + [16#00, 16#04] -> "ps"; + [16#00, 16#05] -> "pr"; + [16#00, 16#06] -> "pl"; + [16#00, 16#07] -> "jit"; + [16#00, 16#08] -> "delay" + end. + + +%%---------------------------------------------------------------------- +%% Name: tdmc - TDM Circuit Package +%% Version: 1 +%% Extends: nt version 1 +%% Purpose: This package is used to support TDM circuit terminations. +%%---------------------------------------------------------------------- + +capabilities_tdmc() -> + [ + {property, "ec"}, + {property, "gain"} + ]. + +encode_tdmc(Scope, Item) -> + case Scope of + property -> + case Item of + "ec" -> [16#00, 16#08]; + "gain" -> [16#00, 16#0a] + end + end. + +decode_tdmc(Scope, Item) -> + case Scope of + property -> + case Item of + [16#00, 16#08] -> "ec"; + [16#00, 16#0a] -> "gain" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: swb - SwitchBoard Package +%% Version: 1 +%% Extends: none +%% Purpose: This package is used to support SwitchBoard specials +%%---------------------------------------------------------------------- + +capabilities_swb() -> + [ + {statistics, "fs"}, % Free slots + {statistics, "as"} % Allocated slots + ]. + +encode_swb(Scope, Item) -> + case Scope of + statistics -> + case Item of + "fs" -> [16#00, 16#00]; + "as" -> [16#00, 16#01] + end + end. + +decode_swb(Scope, Item) -> + case Scope of + statistics -> + case Item of + [16#00, 16#00] -> "fs"; + [16#00, 16#01] -> "as" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: native - Pseudo package +%% Version: 1 +%% Extends: None +%% Purpose: Native tags for media stream properties +%% +%% Parameters for Local descriptors and Remote descriptors are +%% specified as tag-value pairs if binary encoding is used for the +%% protocol. This annex contains the property names (PropertyID), the +%% tags (Property Tag), type of the property (Type) and the values +%% (Value).Values presented in the Value field when the field contains +%% references shall be regarded as "information". The reference +%% contains the normative values. If a value field does not contain a +%% reference then the values in that field can be considered as +%% "normative". +%% +%% Tags are given as hexadecimal numbers in this annex. When setting +%% the value of a property, a MGC may underspecify the value according +%% to one of the mechanisms specified in section 7.1.1. +%% +%% For type "enumeration" the value is represented by the value in brack- +%% ets, e.g., Send(0), Receive(1). +%%---------------------------------------------------------------------- +%% +%% C.6. IP +%% +%% ________________________________________________________________ +%% | PropertyID| Tag | Type | Value | +%% | IPv4 | 6001 | 32 BITS | Ipv4Address | +%% | IPv6 | 6002 | 128 BITS | IPv6 Address | +%% | Port | 6003 | Unsigned Int| Port | +%% | Porttype | 6004 | Enumerated | TCP(0),UDP(1),SCTP(2)| +%% |___________|____________|______________|_______________________| +%% +%% +%% C.11. SDP Equivalents +%% +%% ______________________________________________________________ +%% | PropertyID| Tag | Type | Value | +%% | SDP_V | B001| STRING| Protocol Version | +%% | SDP_O | B002| STRING| Owner-creator and session ID | +%% | SDP_S | B003| STRING| Sesson name | +%% | SDP_I | B004| STRING| Session identifier | +%% | SDP_U | B005| STRING| URI of descriptor | +%% | SDC_E | B006| STRING| email address | +%% | SDP_P | B007| STRING| phone number | +%% | SDP_C | B008| STRING| Connection information | +%% | SDP_B | B009| STRING| Bandwidth Information | +%% | SDP_Z | B00A| STRING| time zone adjustment | +%% | SDP_K | B00B| STRING| Encryption Key | +%% | SDP_A | B00C| STRING| Zero or more session attributes| +%% | SDP_T | B00D| STRING| Active Session Time | +%% | SDP_R | B00E| STRING| Zero or more repeat times | +%% | SDP_M | B00F| STRING| Media name and transport addr | +%% | | | | Reference: IETF RFC 2327 | +%% |___________|______|________|_________________________________| +%% +%%---------------------------------------------------------------------- + +capabilities_native() -> + [ + %% C.6. IP + {property, "IPv4"}, + {property, "IPv6"}, + {property, "Port"}, + {property, "Porttype"}, + + %% C.11. SDP Equivalents + {property, "v"}, + {property, "o"}, + {property, "s"}, + {property, "i"}, + {property, "u"}, + {property, "e"}, + {property, "p"}, + {property, "c"}, + {property, "b"}, + {property, "z"}, + {property, "k"}, + {property, "a"}, + {property, "t"}, + {property, "r"}, + {property, "m"} + ]. + +encode_native(Scope, Item) -> + case Scope of + property -> + case Item of + %% IP + "IPv4" -> [16#60, 16#01]; + "IPv6" -> [16#60, 16#02]; + "Port" -> [16#60, 16#03]; + "Porttype" -> [16#60, 16#04]; + + %% SDP + "v" -> [16#b0, 16#01]; + "o" -> [16#b0, 16#02]; + "s" -> [16#b0, 16#03]; + "i" -> [16#b0, 16#04]; + "u" -> [16#b0, 16#05]; + "e" -> [16#b0, 16#06]; + "p" -> [16#b0, 16#07]; + "c" -> [16#b0, 16#08]; + "b" -> [16#b0, 16#09]; + "z" -> [16#b0, 16#0a]; + "k" -> [16#b0, 16#0b]; + "a" -> [16#b0, 16#0c]; + "t" -> [16#b0, 16#0d]; + "r" -> [16#b0, 16#0e]; + "m" -> [16#b0, 16#0f] + end + end. + +decode_native(Scope, [Type, Item]) -> + case Scope of + property -> + case Type of + 16#60 -> + case Item of + 16#01 -> "IPv4"; + 16#02 -> "IPv6"; + 16#03 -> "Port"; + 16#04 -> "Porttype" + end; + + 16#b0 -> + case Item of + 16#01 -> "v"; + 16#02 -> "o"; + 16#03 -> "s"; + 16#04 -> "i"; + 16#05 -> "u"; + 16#06 -> "e"; + 16#07 -> "p"; + 16#08 -> "c"; + 16#09 -> "b"; + 16#0a -> "z"; + 16#0b -> "k"; + 16#0c -> "a"; + 16#0d -> "t"; + 16#0e -> "r"; + 16#0f -> "m" + end + end + end. + +%% ------------------------------------------------------------------- + +% error(Reason) -> +% erlang:error(Reason). + diff --git a/lib/megaco/src/binary/megaco_binary_name_resolver_v3.erl b/lib/megaco/src/binary/megaco_binary_name_resolver_v3.erl new file mode 100644 index 0000000000..c101aa15bc --- /dev/null +++ b/lib/megaco/src/binary/megaco_binary_name_resolver_v3.erl @@ -0,0 +1,2016 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Handle meta data about packages +%%---------------------------------------------------------------------- + +-module(megaco_binary_name_resolver_v3). + +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). +-include_lib("megaco/src/app/megaco_internal.hrl"). + + +-define(LOWER(Char), + if + Char >= $A, Char =< $Z -> + Char - ($A - $a); + true -> + Char + end). + +-export([packages/0, + capabilities/0, + capabilities/1, + decode_name/3, + encode_name/3 + ]). + +encode_name(Config, term_id, TermId) -> + case megaco:encode_binary_term_id(Config, TermId) of + {ok, TermId2} -> + TermId2; + {error, Reason} -> + exit({bad_term_id, TermId, Reason}) + end; +encode_name(_Config, Scope, Item) -> + ?d("encode_name(~p) -> entry with" + "~n Item: ~p", [Scope, Item]), + encode(Scope, Item). + +decode_name(Config, term_id, TermId) -> + case megaco:decode_binary_term_id(Config, TermId) of + {ok, TermId2} -> + TermId2; + {error, Reason} -> + exit({bad_term_id, TermId, Reason}) + end; +decode_name(_Config, Scope, Item) -> + ?d("decode_name(~p) -> entry with" + "~n Item: ~p", [Scope, Item]), + decode(Scope, Item). + + + +%%---------------------------------------------------------------------- +%% 12.1.1 Package +%% +%% Overall description of the package, specifying: +%% +%% Package Name: only descriptive +%% +%% PackageID: is an identifier +%% +%% Description: is a description of the package +%% +%% Version: +%% +%% A new version of a package can only add additional Properties, +%% Events, Signals, Statistics and new possible values for an +%% existing parameter described in the original package. No +%% deletions or modifications shall be allowed. A version is an +%% integer in the range from 1 to 99. +%% +%% Designed to be extended only (Optional): Yes +%% +%% This indicates that the package has been expressly designed to +%% be extended by others, not to be directly referenced. For +%% example, the package may not have any function on its own or be +%% nonsensical on its own. The MG SHOULD NOT publish this PackageID +%% when reporting packages. +%% +%% Extends: existing package Descriptor +%% +%% A package may extend an existing package. The version of the +%% original package must be specified. When a package extends +%% another package it shall only add additional Properties, Events, +%% Signals, Statistics and new possible values for an existing +%% parameter described in the original package. An extended package +%% shall not redefine or overload an identifier defined in the +%% original package and packages it may have extended (multiple +%% levels of extension). Hence, if package B version 1 extends +%% package A version 1, version 2 of B will not be able to extend +%% the A version 2 if A version 2 defines a name already in B +%% version 1. If the package does not extend another package, it +%% shall specify "none". +%% +%% +%% 12.1.2 Properties +%% +%% Properties defined by the package, specifying: +%% +%% Property Name: only descriptive +%% +%% PropertyID: is an identifier +%% +%% Description: is a description of the function of the property +%% +%% Type: One of: +%% +%% Boolean +%% +%% String: UTF-8 string +%% +%% Octet String: A number of octets. See Annex A and B.3 for +%% encoding +%% +%% Integer: 4 byte signed integer +%% +%% Double: 8 byte signed integer +%% +%% Character: unicode UTF-8 encoding of a single letter. +%% Could be more than one octet. +%% +%% Enumeration: one of a list of possible unique values (see 12.3) +%% +%% Sub-list: a list of several values from a list. +%% The type of sub-list SHALL also be specified. +%% The type shall be chosen from the types specified in +%% this section (with the exception of sub-list). For +%% example, Type: sub-list of enumeration. The encoding +%% of sub-lists is specified in Annexes A and B.3. +%% +%% Possible values: +%% +%% A package MUST specify either a specific set of values or a +%% description of how values are determined. A package MUST also +%% specify a default value or the default behaviour when the value +%% is omitted from its descriptor. For example, a package may +%% specify that procedures related to the property are suspended +%% when its value is omitted. +%% +%% Default: +%% +%% A default value (but not procedures) may be specified as +%% provisionable. +%% +%% Defined in: +%% +%% Which H.248.1 descriptor the property is defined in. +%% LocalControl is for stream-dependent properties. +%% TerminationState is for stream-independent properties. +%% ContextAttribute is for properties that affect the context as +%% a whole, i.e., mixing properties. These are expected to be the +%% most common cases, but it is possible for properties to be +%% defined in other descriptors. Context properties MUST be defined +%% in the ContextAttribute descriptor. +%% +%% Characteristics: Read/Write or both, and (optionally), global: +%% +%% Indicates whether a property is read-only, or read-write, and +%% if it is global. If Global is omitted, the property is not +%% global. If a property is declared as global, the value of the +%% property is shared by all Terminations realizing the package. +%% If a context property is declared as global, the property is +%% shared by all contexts realizing the package. +%% +%% +%% 12.1.3 Events +%% +%% Events defined by the package, specifying: +%% +%% Event name: only descriptive +%% +%% EventID: is an identifier +%% +%% Description: a description of the function of the event +%% +%% EventsDescriptor Parameters: +%% +%% Parameters used by the MGC to configure the event, and found in +%% the EventsDescriptor. See 12.2. If there are no parameters for +%% the Events Descriptor, then "none" shall be specified. +%% +%% ObservedEventsDescriptor Parameters: +%% +%% Parameters returned to the MGC in Notify requests and in replies +%% to command requests from the MGC that audit +%% ObservedEventsDescriptor, and found in the +%% ObservedEventsDescriptor. See 12.2. If there are no parameters +%% for the ObservedEvents Descriptor, then �none� shall be specified. +%% +%% +%% 12.1.4 Signals +%% +%% Signals defined by the package, specifying: +%% +%% Signal Name: only descriptive +%% +%% SignalID: is an identifier. SignalID is used in a SignalsDescriptor +%% +%% Description: a description of the function of the signal +%% +%% SignalType: one of: +%% +%% OO (On/Off) +%% +%% TO (TimeOut) +%% +%% BR (Brief) +%% +%% NOTE -�SignalType may be defined such that it is dependent on +%% the value of one or more parameters. The package MUST specify a +%% default signal type. If the default type is TO, the package MUST +%% specify a default duration which may be provisioned. A default +%% duration is meaningless for BR. +%% +%% Duration: in hundredths of seconds +%% +%% Additional Parameters: see 12.2 +%% +%% +%% 12.1.5 Statistics +%% +%% Statistics defined by the package, specifying: +%% +%% Statistic name: only descriptive +%% +%% StatisticID: is an identifier +%% +%% StatisticID is used in a StatisticsDescriptor +%% +%% Description: a description of the statistic +%% +%% Type: One of: +%% +%% Boolean +%% +%% String: UTF-8 string +%% +%% Octet String: A number of octets. +%% See Annex A and Annex B.3 for encoding +%% +%% Integer: 4 byte signed integer +%% +%% Double: 8 byte signed integer +%% +%% Character: Unicode UTF-8 encoding of a single letter. +%% Could be more than one octet. +%% +%% Enumeration: One of a list of possible unique values (See 12.3) +%% +%% Sub-list: A list of several values from a list. +%% The type of sub-list SHALL also be specified. +%% The type shall be chosen from the types specified in +%% this section (with the exception of sub-list). +%% For example, Type: sub-list of enumeration. +%% The encoding of sub-lists is specified in Annexes A +%% and B.3. +%% +%% Possible Values: +%% +%% A package must indicate the unit of measure, e.g. milliseconds, +%% packets, either here or along with the type above, as well as +%% indicating any restriction on the range. +%% +%% Level: Specify if the statistic can be kept at the Termination +%% level, Stream level or Either. +%% +%% +%% 12.1.6 Error Codes +%% +%% If the package does not define any error codes, this section may be omitted. +%% Otherwise, it describes error codes defined by the package, specifying: +%% +%% Error Code #: The error code number. +%% +%% Name: Name of the error +%% +%% Definition: A description of the error code. +%% +%% Error Text in the Error Descriptor: +%% +%% A description of what text to return in the Error Descriptor. +%% +%% Comment: Any further comments on the use of the error code. +%% +%% +%% 12.1.7 Procedures +%% +%% Additional guidance on the use of the package. +%% +%% +%% 12.2 Guidelines to defining parameters to events and signals +%% +%% Parameter Name: only descriptive +%% +%% ParameterID: is an identifier. The textual ParameterID of +%% parameters to Events and Signals shall not start with "EPA" and +%% "SPA", respectively. The textual ParameterID shall also not be +%% "ST", "Stream", "SY", "SignalType", "DR", "Duration", "NC", +%% "NotifyCompletion", "KA", "KeepActive", "EB", "Embed", "DM", +%% "DigitMap", "DI", "Direction", "RQ" or "RequestID". +%% +%% Description: a description of the function of the parameter. +%% +%% Type: One of: +%% +%% Boolean +%% +%% String: UTF-8 octet string +%% +%% Octet String: A number of octets. See Annex A and B.3 for +%% encoding +%% +%% Integer: 4-octet signed integer +%% +%% Double: 8-octet signed integer +%% +%% Character: Unicode UTF-8 encoding of a single letter. Could be +%% more than one octet. +%% +%% Enumeration: one of a list of possible unique values (see 12.3) +%% +%% Sub-list: a list of several values from a list (not supported +%% for statistics). The type of sub-list SHALL also be +%% specified The type shall be chosen from the types +%% specified in this section (with the exception of +%% sub-list). For example, Type: sub-list of enumeration. +%% The encoding of sub-lists is specified in Annex A +%% and B.3. +%% +%% Optional: Yes/No +%% +%% Describes if the parameter may be omitted from the signal or +%% event. +%% +%% Possible values: +%% +%% A package MUST specify either a specific set of values or a +%% description of how values are determined. A package MUST +%% also specify a default value or the default behavior when the +%% value is omitted from its descriptor. For example, a package +%% may specify that procedures related to the parameter are +%% suspended when its value is omitted. +%% +%% Default: +%% +%% A default value (but not procedures) may be specified as +%% provisionable. +%% +%% +%% 12.3 Lists +%% +%% Possible values for parameters include enumerations. Enumerations may be +%% defined in a list. It is recommended that the list be IANA registered so +%% that packages that extend the list can be defined without concern for +%% conflicting names. +%% +%% +%% 12.4 Identifiers +%% +%% Identifiers in text encoding shall be strings of up to 64 characters, +%% containing no spaces, starting with an alphabetic character and consisting +%% of alphanumeric characters and/or digits, and possibly including the +%% special character underscore ("_"). +%% +%% Identifiers in binary encoding are 2 octets long. +%% +%% Both text and binary values shall be specified for each identifier, +%% including identifiers used as values in enumerated types. +%% +%% +%% 12.5 Package registration +%% +%% A package can be registered with IANA for interoperability reasons. See +%% clause 14 for IANA considerations. +%% +%%---------------------------------------------------------------------- + +capabilities() -> + [{P, capabilities(P)} || P <- packages()]. + +%% -record(property, {name, type, values, defined_in, characteristics}). + +%%---------------------------------------------------------------------- +%% List all known packages +%% 'native' and 'all' are not real packages +%%---------------------------------------------------------------------- + +packages() -> + [ + "g", % Generic + "root", % Base Root Package + "tonegen", % Tone Generator Package + "tonedet", % Tone Detection Package + "dg", % Basic DTMF Generator Package + "dd", % DTMF detection Package + "cg", % Call Progress Tones Generator Package + "cd", % Call Progress Tones Detection Package + "al", % Analog Line Supervision Package + "ct", % Basic Continuity Package + "nt", % Network Package + "rtp", % RTP Package + "swb", % SwitchBoard Package + "tdmc", % TDM Circuit Package + "" % Native pseudo package + ]. + +%%---------------------------------------------------------------------- +%% List all matching capabilities +%%---------------------------------------------------------------------- + +capabilities(Package) -> + case Package of + "g" -> capabilities_g(); + "root" -> capabilities_root(); + "tonegen" -> capabilities_tonegen(); + "tonedet" -> capabilities_tonedet(); + "dg" -> capabilities_dg(); + "dd" -> capabilities_dd(); + "cg" -> capabilities_cg(); + "cd" -> capabilities_cd(); + "al" -> capabilities_al(); + "ct" -> capabilities_ct(); + "nt" -> capabilities_nt(); + "rtp" -> capabilities_rtp(); + "swb" -> capabilities_swb(); + "tdmc" -> capabilities_tdmc(); + "" -> capabilities_native() + end. + +%%---------------------------------------------------------------------- +%% Decode package name to internal form +%% Scope ::= property | event | signal | statistics +%%---------------------------------------------------------------------- + +decode(mid, Package) -> + decode_mid(Package); +decode(package, Package) -> + decode_package(Package); +decode(profile, Package) -> + decode_profile(Package); +decode(dialplan, Dialplan) -> + decode_dialplan(Dialplan); +decode(Scope, [A, B | Item]) when is_atom(Scope) -> + ?d("decode(~p) -> entry with" + "~n A: ~p" + "~n B: ~p" + "~n Item: ~p", [Scope, A, B, Item]), + case decode_package([A, B]) of + "" -> + ?d("decode -> \"no\" package",[]), + decode_item(Scope, [A, B], Item); + Package -> + ?d("decode -> Package: ~p", [Package]), + Package ++ "/" ++ decode_item(Scope, [A, B], Item) + end; +decode({Scope, [A, B | Item]}, SubItem) when is_atom(Scope) -> + ?d("decode(~p) -> entry with" + "~n A: ~p" + "~n B: ~p" + "~n Item: ~p" + "~n SubItem: ~p", [Scope, A, B, Item, SubItem]), + decode_item({Scope, Item}, [A, B], SubItem). + +decode_item(Scope, [A, B], Item) -> + ?d("decode_item -> entry",[]), + case A of + 16#00 -> + case B of + 16#01 -> decode_g(Scope, Item); + 16#02 -> decode_root(Scope, Item); + 16#03 -> decode_tonegen(Scope, Item); + 16#04 -> decode_tonedet(Scope, Item); + 16#05 -> decode_dg(Scope, Item); + 16#06 -> decode_dd(Scope, Item); + 16#07 -> decode_cg(Scope, Item); + 16#08 -> decode_cd(Scope, Item); + 16#09 -> decode_al(Scope, Item); + 16#0a -> decode_ct(Scope, Item); + 16#0b -> decode_nt(Scope, Item); + 16#0c -> decode_rtp(Scope, Item); + 16#0d -> decode_tdmc(Scope, Item); + 16#00 -> decode_native(Scope, Item) + end; + 16#fe -> + case B of + %% Proprietary extension + 16#fe -> decode_swb(Scope, Item) + end; + 16#ff -> + case B of + 16#ff when Item =:= [16#ff, 16#ff] -> "*" + end + end. + +decode_package(Package) -> + ?d("decode_package -> entry with" + "~n Package: ~p", [Package]), + [A, B] = Package, + case A of + 16#00 -> + case B of + 16#01 -> "g"; + 16#02 -> "root"; + 16#03 -> "tonegen"; + 16#04 -> "tonedet"; + 16#05 -> "dg"; + 16#06 -> "dd"; + 16#07 -> "cg"; + 16#08 -> "cd"; + 16#09 -> "al"; + 16#0a -> "ct"; + 16#0b -> "nt"; + 16#0c -> "rtp"; + 16#0d -> "tdmc"; + 16#00 -> "" + end; + 16#fe -> + case B of + 16#fe -> "swb" + end; + 16#ff -> + case B of + 16#ff -> "*" + end + end. + +decode_profile([A, B]) -> + case A of + 16#00 -> + case B of + 16#fe -> "resgw"; + _ -> "profile" ++ [A + $0, B + $0] + end; + _ -> + "profile" ++ [A + $0, B + $0] + end. + +decode_dialplan([A, B]) -> + "dialplan" ++ [A + $0, B + $0]. + +decode_mid(Mid) -> + case Mid of + {domainName, DN} -> + Lower = to_lower(DN#'DomainName'.name), + {domainName, DN#'DomainName'{name = Lower}}; + {deviceName, PathName} -> + Lower = to_lower(PathName), + {deviceName, Lower}; + Other -> + Other + end. + +to_lower(Chars) -> + [?LOWER(Char) || Char <- Chars]. + +%%---------------------------------------------------------------------- +%% Encode package name from internal form +%% Scope ::= property | event | signal | statistics +%%---------------------------------------------------------------------- + +encode(mid, Package) -> + encode_mid(Package); +encode(package, Package) -> + encode_package(Package); +encode(profile, Profile) -> + encode_profile(Profile); +encode(dialplan, Dialplan) -> + encode_dialplan(Dialplan); +encode(Scope, PackageItem) when is_atom(Scope) -> + ?d("encode(~p) -> entry with" + "~n PackageItem: ~p", [Scope, PackageItem]), + case string:tokens(PackageItem, [$/]) of + [Package, Item] -> + ?d("encode -> " + "~n Package: ~p" + "~n Item: ~p", [Package, Item]), + encode_package(Package) ++ encode_item(Scope, Package, Item); + [Item] -> + ?d("encode -> Item: ~p", [Item]), + [16#00, 16#00 | encode_native(Scope, Item)] + end; +encode({Scope, PackageItem}, SubItem) when is_atom(Scope) -> + ?d("encode(~p) -> entry with" + "~n PackageItem: ~p" + "~n SubItem: ~p", [Scope, PackageItem, SubItem]), + case string:tokens(PackageItem, [$/]) of + [Package, Item] -> + ?d("encode -> " + "~n Package: ~p" + "~n Item: ~p", [Package, Item]), + encode_item({Scope, Item}, Package, SubItem); + [_Item] -> + ?d("encode -> _Item: ~p", [_Item]), + encode_native(Scope, SubItem) + end. + +encode_item(_Scope, _Package, "*") -> + [16#ff, 16#ff]; +encode_item(Scope, Package, Item) -> + ?d("encode_item(~s) -> entry", [Package]), + case Package of + "g" -> encode_g(Scope, Item); + "root" -> encode_root(Scope, Item); + "tonegen" -> encode_tonegen(Scope, Item); + "tonedet" -> encode_tonedet(Scope, Item); + "dg" -> encode_dg(Scope, Item); + "dd" -> encode_dd(Scope, Item); + "cg" -> encode_cg(Scope, Item); + "cd" -> encode_cd(Scope, Item); + "al" -> encode_al(Scope, Item); + "ct" -> encode_ct(Scope, Item); + "nt" -> encode_nt(Scope, Item); + "rtp" -> encode_rtp(Scope, Item); + "tdmc" -> encode_tdmc(Scope, Item); + "swb" -> encode_swb(Scope, Item) + end. + +encode_package(Package) -> + case Package of + "g" -> [16#00, 16#01]; + "root" -> [16#00, 16#02]; + "tonegen" -> [16#00, 16#03]; + "tonedet" -> [16#00, 16#04]; + "dg" -> [16#00, 16#05]; + "dd" -> [16#00, 16#06]; + "cg" -> [16#00, 16#07]; + "cd" -> [16#00, 16#08]; + "al" -> [16#00, 16#09]; + "ct" -> [16#00, 16#0a]; + "nt" -> [16#00, 16#0b]; + "rtp" -> [16#00, 16#0c]; + "tdmc" -> [16#00, 16#0d]; + "" -> [16#00, 16#00]; + "*" -> [16#ff, 16#ff]; + "swb" -> [16#fe, 16#fe] + end. + +encode_profile(Profile) -> + case Profile of + "resgw" -> + [16#00, 16#fe]; + [$p, $r, $o, $f, $i, $l, $e | Name] -> + case Name of + [A, B] -> [A - $0, B - $0]; + [B] -> [0, B - $0]; + [] -> [0, 0] + end + end. + +encode_dialplan(Dialplan) -> + case Dialplan of + [$d, $i, $a, $l, $p, $l, $a, $n | Name] -> + case Name of + [A, B] -> [A - $0, B - $0]; + [B] -> [0, B - $0]; + [] -> [0, 0] + end + end. + +encode_mid(Mid) -> + Mid. + + +%%---------------------------------------------------------------------- +%% Name: g - Generic +%% Version: 1 +%% Extends: None +%% Purpose: Generic package for commonly encountered items +%%---------------------------------------------------------------------- + +capabilities_g() -> + [ + {event, "cause"}, + {event, "sc"} + ]. + +encode_g(event, Item) -> + case Item of + "cause" -> [16#00, 16#01]; + "sc" -> [16#00, 16#02] + end; + +encode_g({event_parameter, Item}, SubItem) -> + case Item of + "cause" -> + case SubItem of + "Generalcause" -> [16#00, 16#01]; + "Failurecause" -> [16#00, 16#02] + end; + "sc" -> + case SubItem of + "SigID" -> [16#00, 16#01]; + "Meth" -> [16#00, 16#02]; + "SLID" -> [16#00, 16#03]; + "RID" -> [16#00, 16#04] + end + end. + +decode_g(event, Item) -> + case Item of + [16#00, 16#01] -> "cause"; + [16#00, 16#02] -> "sc" + end; + +decode_g({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event: cause + case SubItem of + [16#00, 16#01] -> "Generalcause"; + [16#00, 16#02] -> "Failurecause" + end; + + [16#00, 16#02] -> % Event: sc + case SubItem of + [16#00, 16#01] -> "SigID"; + [16#00, 16#02] -> "Meth"; + [16#00, 16#03] -> "SLID"; + [16#00, 16#04] -> "RID" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: root - Base Root Package +%% Version: 2 +%% Extends: None +%% Purpose: This package defines Gateway wide properties. +%%---------------------------------------------------------------------- + +capabilities_root() -> + [ + {property, "maxNumberOfContexts"}, + {property, "maxTerminationsPerContext"}, + {property, "normalMGExecutionTime"}, + {property, "normalMGCExecutionTime"}, + {property, "MGProvisionalResponseTimerValue"}, + {property, "MGCProvisionalResponseTimerValue"}, + {property, "MGCOriginatedPendingLimit"}, + {property, "MGOriginatedPendingLimit"}, + {property, "MGSegmentationTimerValue"}, + {property, "MGCSegmentationTimerValue"}, + {property, "MGMaxPDUSize"}, + {property, "MGCMaxPDUSize"} + ]. + +encode_root(Scope, Item) -> + case Scope of + property -> + case Item of + "maxNumberOfContexts" -> [16#00, 16#01]; + "maxTerminationsPerContext" -> [16#00, 16#02]; + "normalMGExecutionTime" -> [16#00, 16#03]; + "normalMGCExecutionTime" -> [16#00, 16#04]; + "MGProvisionalResponseTimerValue" -> [16#00, 16#05]; + "MGCProvisionalResponseTimerValue" -> [16#00, 16#06]; + "MGCOriginatedPendingLimit" -> [16#00, 16#07]; + "MGOriginatedPendingLimit" -> [16#00, 16#08]; + "MGSegmentationTimerValue" -> [16#00, 16#09]; + "MGCSegmentationTimerValue" -> [16#00, 16#0a]; + "MGMaxPDUSize" -> [16#00, 16#0b]; + "MGCMaxPDUSize" -> [16#00, 16#0c] + end + end. + +decode_root(Scope, Item) -> + case Scope of + property -> + case Item of + [16#00, 16#01] -> "maxNumberOfContexts"; + [16#00, 16#02] -> "maxTerminationsPerContext"; + [16#00, 16#03] -> "normalMGExecutionTime"; + [16#00, 16#04] -> "normalMGCExecutionTime"; + [16#00, 16#05] -> "MGProvisionalResponseTimerValue"; + [16#00, 16#06] -> "MGCProvisionalResponseTimerValue"; + [16#00, 16#07] -> "MGCOriginatedPendingLimit"; + [16#00, 16#08] -> "MGOriginatedPendingLimit"; + [16#00, 16#09] -> "MGSegmentationTimerValue"; + [16#00, 16#0a] -> "MGCSegmentationTimerValue"; + [16#00, 16#0b] -> "MGMaxPDUSize"; + [16#00, 16#0c] -> "MGCMaxPDUSize" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: tonegen - Tone Generator Package +%% Version: 2 +%% Extends: None +%% Purpose: This package defines signals to generate audio tones. +%% This package does not specify parameter values. It is +%% intended to be extendable. Generally, tones are defined +%% as an individual signal with a parameter, ind, +%% representing "interdigit" time delay, and a tone id to +%% be used with playtones. A tone id should be kept +%% consistent with any tone generation for the same tone. +%% MGs are expected to be provisioned with the characteristics +%% of appropriate tones for the country in which the MG is located. +%%---------------------------------------------------------------------- + +capabilities_tonegen() -> + [ + {signal, "pt"} + ]. + +encode_tonegen(signal, Item) -> + case Item of + "pt" -> [16#00, 16#01] + end; + +encode_tonegen({signal_parameter, Item}, SubItem) -> + case Item of + "pt" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "ind" -> [16#00, 16#02]; + "btd" -> [16#00, 16#03] + end + end. + +decode_tonegen(signal, Item) -> + case Item of + [16#00, 16#01] -> "pt" + end; + +decode_tonegen({signal_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event: pt + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#02] -> "ind"; + [16#00, 16#03] -> "btd" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: tonedet - Tone Detection Package +%% Version: 1 +%% Extends: None +%% Purpose: This Package defines events for audio tone detection. +%% Tones are selected by name (tone id). MGs are expected +%% to be provisioned with the characteristics of appropriate +%% tones for the country in which the MG is located. +%% +%% This package does not specify parameter values. +%% It is intended to be extendable. +%%---------------------------------------------------------------------- + +capabilities_tonedet() -> + [ + {event, "std"}, + {event, "etd"}, + {event, "ltd"} + ]. + +encode_tonedet(event, Item) -> + case Item of + "std" -> [16#00, 16#01]; + "etd" -> [16#00, 16#02]; + "ltd" -> [16#00, 16#03] + end; + +encode_tonedet({event_parameter, Item}, SubItem) -> + case Item of + "std" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "tid" -> [16#00, 16#03] + end; + "etd" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "tid" -> [16#00, 16#03]; + "dur" -> [16#00, 16#02] + end; + "ltd" -> + case SubItem of + "tl" -> [16#00, 16#01]; + "dur" -> [16#00, 16#02]; + "tid" -> [16#00, 16#03] + end + end. + +decode_tonedet(event, Item) -> + case Item of + [16#00, 16#01] -> "std"; + [16#00, 16#02] -> "etd"; + [16#00, 16#03] -> "ltd" + end; + +decode_tonedet({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event std + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#03] -> "tid" + end; + [16#00, 16#02] -> % Event etd + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#03] -> "tid"; + [16#00, 16#02] -> "dur" + end; + [16#00, 16#03] -> % Event ltd + case SubItem of + [16#00, 16#01] -> "tl"; + [16#00, 16#02] -> "dur"; + [16#00, 16#03] -> "tid" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: dg - Basic DTMF Generator Package +%% Version: 1 +%% Extends: tonegen version 1 +%% Purpose: This package defines the basic DTMF tones as signals and +%% extends the allowed values of parameter tl of playtone +%% in tonegen. +%%---------------------------------------------------------------------- + +capabilities_dg() -> + [ + {signal, "d0"}, + {signal, "d1"}, + {signal, "d2"}, + {signal, "d3"}, + {signal, "d4"}, + {signal, "d5"}, + {signal, "d6"}, + {signal, "d7"}, + {signal, "d8"}, + {signal, "d9"}, + {signal, "ds"}, + {signal, "do"}, + {signal, "da"}, + {signal, "db"}, + {signal, "dc"}, + {signal, "dd"} + ]. + +encode_dg(signal, Item) -> + case Item of + "d0" -> [16#00, 16#10]; + "d1" -> [16#00, 16#11]; + "d2" -> [16#00, 16#12]; + "d3" -> [16#00, 16#13]; + "d4" -> [16#00, 16#14]; + "d5" -> [16#00, 16#15]; + "d6" -> [16#00, 16#16]; + "d7" -> [16#00, 16#17]; + "d8" -> [16#00, 16#18]; + "d9" -> [16#00, 16#19]; + "ds" -> [16#00, 16#20]; + "do" -> [16#00, 16#21]; + "da" -> [16#00, 16#1a]; + "db" -> [16#00, 16#1b]; + "dc" -> [16#00, 16#1c]; + "dd" -> [16#00, 16#1d] + end; + +encode_dg({signal_parameter, Item}, SubItem) -> + case Item of + "d0" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d1" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d2" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d3" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d4" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d5" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d6" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d7" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d8" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d9" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "ds" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "do" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "da" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "db" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "dc" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "dd" -> + case SubItem of + "btd" -> [16#00, 16#01] + end + end. + +decode_dg(signal, Item) -> + case Item of + [16#00, 16#10] -> "d0"; + [16#00, 16#11] -> "d1"; + [16#00, 16#12] -> "d2"; + [16#00, 16#13] -> "d3"; + [16#00, 16#14] -> "d4"; + [16#00, 16#15] -> "d5"; + [16#00, 16#16] -> "d6"; + [16#00, 16#17] -> "d7"; + [16#00, 16#18] -> "d8"; + [16#00, 16#19] -> "d9"; + [16#00, 16#20] -> "ds"; + [16#00, 16#21] -> "do"; + [16#00, 16#1a] -> "da"; + [16#00, 16#1b] -> "db"; + [16#00, 16#1c] -> "dc"; + [16#00, 16#1d] -> "dd" + end; + +decode_dg({signal_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#10] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#11] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#12] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#13] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#14] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#15] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#16] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#17] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#18] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#19] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#20] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#21] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1a] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1b] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1c] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1d] -> + case SubItem of + [16#00, 16#01] -> "btd" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: dd - DTMF detection Package +%% Version: 1 +%% Extends: tonedet version 1 +%% Purpose: This package defines the basic DTMF tones detection. +%% Tones are selected by name (tone id). MGs are expected +%% to be provisioned with the characteristics of appropriate +%% tones for the country in which the MG is located. +%% +%% This package does not specify parameter values. +%% It is intended to be extendable. +%% +%% Additional tone id values are all tone ids described in package dg +%% (basic DTMF generator package). +%% +%% The following table maps DTMF events to digit map symbols as described +%% in section 7.1.14. +%% +%% _________________________________ +%% | DTMF Event | Symbol | +%% | d0 | "0" | +%% | d1 | "1" | +%% | d2 | "2" | +%% | d3 | "3" | +%% | d4 | "4" | +%% | d5 | "5" | +%% | d6 | "6" | +%% | d7 | "7" | +%% | d8 | "8" | +%% | d9 | "9" | +%% | da | "A" or "a"| +%% | db | "B" or "b"| +%% | dc | "C" or "c"| +%% | dd | "D" or "d"| +%% | ds | "E" or "e"| +%% | do | "F" or "f"| +%% |___________________|____________| +%% +%%---------------------------------------------------------------------- + +capabilities_dd() -> + [ + {event, "ce"}, + {event, "d0"}, + {event, "d1"}, + {event, "d2"}, + {event, "d3"}, + {event, "d4"}, + {event, "d5"}, + {event, "d6"}, + {event, "d7"}, + {event, "d8"}, + {event, "d9"}, + {event, "ds"}, + {event, "do"}, + {event, "da"}, + {event, "db"}, + {event, "dc"}, + {event, "dd"} + ]. + +encode_dd(event, Item) -> + case Item of + "ce" -> [16#00, 16#04]; + "d0" -> [16#00, 16#10]; + "d1" -> [16#00, 16#11]; + "d2" -> [16#00, 16#12]; + "d3" -> [16#00, 16#13]; + "d4" -> [16#00, 16#14]; + "d5" -> [16#00, 16#15]; + "d6" -> [16#00, 16#16]; + "d7" -> [16#00, 16#17]; + "d8" -> [16#00, 16#18]; + "d9" -> [16#00, 16#19]; + "ds" -> [16#00, 16#20]; + "do" -> [16#00, 16#21]; + "da" -> [16#00, 16#1a]; + "db" -> [16#00, 16#1b]; + "dc" -> [16#00, 16#1c]; + "dd" -> [16#00, 16#1d] + end; + +encode_dd({event_parameter, Item}, SubItem) -> + case Item of + "ce" -> + case SubItem of + "ds" -> [16#00, 16#01]; + "Meth" -> [16#00, 16#03] + end; + "d0" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d1" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d2" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d3" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d4" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d5" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d6" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d7" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d8" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "d9" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "ds" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "do" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "da" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "db" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "dc" -> + case SubItem of + "btd" -> [16#00, 16#01] + end; + "dd" -> + case SubItem of + "btd" -> [16#00, 16#01] + end + end. + +decode_dd(event, Item) -> + case Item of + [16#00, 16#04] -> "ce"; + [16#00, 16#10] -> "d0"; + [16#00, 16#11] -> "d1"; + [16#00, 16#12] -> "d2"; + [16#00, 16#13] -> "d3"; + [16#00, 16#14] -> "d4"; + [16#00, 16#15] -> "d5"; + [16#00, 16#16] -> "d6"; + [16#00, 16#17] -> "d7"; + [16#00, 16#18] -> "d8"; + [16#00, 16#19] -> "d9"; + [16#00, 16#20] -> "ds"; + [16#00, 16#21] -> "do"; + [16#00, 16#1a] -> "da"; + [16#00, 16#1b] -> "db"; + [16#00, 16#1c] -> "dc"; + [16#00, 16#1d] -> "dd" + end; + +decode_dd({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#04] -> % Event ce + case SubItem of + [16#00, 16#01] -> "ds"; + [16#00, 16#03] -> "Meth" + end; + [16#00, 16#10] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#11] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#12] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#13] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#14] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#15] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#16] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#17] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#18] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#19] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#20] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#21] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1a] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1b] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1c] -> + case SubItem of + [16#00, 16#01] -> "btd" + end; + [16#00, 16#1d] -> + case SubItem of + [16#00, 16#01] -> "btd" + end + end. + +%%---------------------------------------------------------------------- +%% Name: cg - Call Progress Tones Generator Package +%% Version: 1 +%% Extends: tonegen version 1 +%% Purpose: This package defines the basic call progress tones as signals +%% and extends the allowed values of the tl parameter of +%% playtone in tonegen. +%%---------------------------------------------------------------------- + +capabilities_cg() -> + [ + {signal, "dt"}, + {signal, "rt"}, + {signal, "bt"}, + {signal, "ct"}, + {signal, "sit"}, + {signal, "wt"}, + {signal, "prt"}, + {signal, "cw"}, + {signal, "cr"} + ]. + + +encode_cg(Scope, Item) -> + case Scope of + signal -> + case Item of + "dt" -> [16#00, 16#30]; + "rt" -> [16#00, 16#31]; + "bt" -> [16#00, 16#32]; + "ct" -> [16#00, 16#33]; + "sit" -> [16#00, 16#34]; + "wt" -> [16#00, 16#35]; + "prt" -> [16#00, 16#36]; + "cw" -> [16#00, 16#37]; + "cr" -> [16#00, 16#38] + end + end. + +decode_cg(Scope, Item) -> + case Scope of + signal -> + case Item of + [16#00, 16#30] -> "dt"; + [16#00, 16#31] -> "rt"; + [16#00, 16#32] -> "bt"; + [16#00, 16#33] -> "ct"; + [16#00, 16#34] -> "sit"; + [16#00, 16#35] -> "wt"; + [16#00, 16#36] -> "prt"; + [16#00, 16#37] -> "cw"; + [16#00, 16#38] -> "cr" + end + end. + +%%---------------------------------------------------------------------- +%% Name: cd - Call Progress Tones Detection Package +%% Version: 1 +%% Extends: tonedet version 1 +%% Purpose: This package defines the basic call progress detection tones. +%% This Package extends the possible values of tone id +%% in the "start tone detected", "end tone detected" and +%% "long tone detected" events. +%% Additional values +%% tone id values are defined for start tone detected, +%% end tone detected and long tone detected with +%% the same values as those in package cg (call +%% progress tones generation package). +%% +%% The required set of tone ids corresponds to Recommendation E.180/Q.35 +%% [ITU-T Recommendation E.180/Q.35 (1998)]. See Recommendation E.180/Q.35 +%% for definition of the meanings of these tones. +%%---------------------------------------------------------------------- + +capabilities_cd() -> + [ + {event, "dt"}, + {event, "rt"}, + {event, "bt"}, + {event, "ct"}, + {event, "sit"}, + {event, "wt"}, + {event, "prt"}, + {event, "cw"}, + {event, "cr"} + ]. + + +encode_cd(Scope, Item) -> + case Scope of + event -> + case Item of + "dt" -> [16#00, 16#30]; + "rt" -> [16#00, 16#31]; + "bt" -> [16#00, 16#32]; + "ct" -> [16#00, 16#33]; + "sit"-> [16#00, 16#34]; + "wt" -> [16#00, 16#35]; + "prt"-> [16#00, 16#36]; + "cw" -> [16#00, 16#37]; + "cr" -> [16#00, 16#38] + end + end. + +decode_cd(Scope, Item) -> + case Scope of + event -> + case Item of + [16#00, 16#30] -> "dt"; + [16#00, 16#31] -> "rt"; + [16#00, 16#32] -> "bt"; + [16#00, 16#33] -> "ct"; + [16#00, 16#34] -> "sit"; + [16#00, 16#35] -> "wt"; + [16#00, 16#36] -> "prt"; + [16#00, 16#37] -> "cw"; + [16#00, 16#38] -> "cr" + end + end. + +%%---------------------------------------------------------------------- +%% Name: al - Analog Line Supervision Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines events and signals for an analog line. +%%---------------------------------------------------------------------- + +capabilities_al() -> + [ + {event, "on"}, + {event, "of"}, + {event, "fl"}, + {signal, "ri"} + ]. + +encode_al(event, Item) -> + ?d("encode_al(event) -> entry with" + "~n Item: ~p", [Item]), + case Item of + "on" -> [16#00, 16#04]; + "of" -> [16#00, 16#05]; + "fl" -> [16#00, 16#06] + end; + +encode_al({event_parameter, Item}, SubItem) -> + ?d("encode_al({event_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + "on" -> + case SubItem of + "strict" -> [16#00, 16#01]; + "init" -> [16#00, 16#02] + end; + "of" -> + case SubItem of + "strict" -> [16#00, 16#01]; + "init" -> [16#00, 16#02] + end; + "fl" -> + case SubItem of + "mindur" -> [16#00, 16#04]; + "maxdur" -> [16#00, 16#05] + end + end; + +encode_al(signal, Item) -> + ?d("encode_al(signal) -> entry with" + "~n Item: ~p", [Item]), + case Item of + "ri" -> [16#00, 16#02] + end; + +encode_al({signal_parameter, Item}, SubItem) -> + ?d("encode_al({signal_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + "ri" -> + case SubItem of + "cad" -> [16#00, 16#06]; + "freq" -> [16#00, 16#07] + end + end. + +decode_al(event, SubItem) -> + ?d("decode_al(event) -> entry with" + "~n SubItem: ~p", [SubItem]), + case SubItem of + [16#00, 16#04] -> "on"; + [16#00, 16#05] -> "of"; + [16#00, 16#06] -> "fl" + end; + +decode_al({event_parameter, Item}, SubItem) -> + ?d("decode_al({event_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + [16#00,16#04] -> %% Event: on + case SubItem of + [16#00, 16#01] -> "strict"; + [16#00, 16#02] -> "init" + end; + [16#00,16#05] -> %% Event: of + case SubItem of + [16#00, 16#01] -> "strict"; + [16#00, 16#02] -> "init" + end; + [16#00,16#06] -> %% Event: fl + case SubItem of + [16#00, 16#04] -> "mindur"; + [16#00, 16#05] -> "maxdur" + end + end; + +decode_al(signal, SubItem) -> + ?d("decode_al(signal) -> entry with" + "~n SubItem: ~p", [SubItem]), + case SubItem of + [16#00, 16#02] -> "ri" + end; + +decode_al({signal_parameter, Item}, SubItem) -> + ?d("decode_al({signal_parameter,~p}) -> entry with" + "~n SubItem: ~p", [Item, SubItem]), + case Item of + [16#00,16#02] -> %% Event: ri + case SubItem of + [16#00, 16#06] -> "cad"; + [16#00, 16#07] -> "freq" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: ct - Basic Continuity Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines events and signals for continuity test. +%% The continuity test includes provision of either a loopback +%% or transceiver functionality. +%%---------------------------------------------------------------------- + +capabilities_ct() -> + [ + {event, "cmp"}, + {signal, "ct"}, + {signal, "rsp"} + ]. + +encode_ct(event, Item) -> + case Item of + "cmp" -> [16#00, 16#05] + end; +encode_ct({event_parameter, Item}, SubItem) -> + case Item of + "cmp" -> + case SubItem of + "res" -> [16#00, 16#08] + end + end; +encode_ct(signal, Item) -> + case Item of + "ct" -> [16#00, 16#03]; + "rsp" -> [16#00, 16#04] + end. + +decode_ct(event, Item) -> + case Item of + [16#00, 16#05] -> "cmp" + end; +decode_ct({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#05] -> % Event cmp + case SubItem of + [16#00, 16#08] -> "res" + end + end; +decode_ct(signal, Item) -> + case Item of + [16#00, 16#03] -> "ct"; + [16#00, 16#04] -> "rsp" + end. + +%%---------------------------------------------------------------------- +%% Name: nt - Network Package +%% Version: 1 +%% Extends: None +%% Purpose: This package defines properties of network terminations +%% independent of network type. +%%---------------------------------------------------------------------- + +capabilities_nt() -> + [ + {property, "jit"}, + {event, "netfail"}, + {event, "qualert"}, + {statistics, "dur"}, + {statistics, "os"}, + {statistics, "or"} + ]. + +encode_nt(property, Item) -> + case Item of + "jit" -> [16#00, 16#07] + end; +encode_nt(event, Item) -> + case Item of + "netfail" -> [16#00, 16#05]; + "qualert" -> [16#00, 16#06] + end; +encode_nt({event_parameter, Item}, SubItem) -> + case Item of + "netfail" -> + case SubItem of + "cs" -> [16#00, 16#01] + end; + "qualert" -> + case SubItem of + "th" -> [16#00, 16#01] + end + end; +encode_nt(statistics, Item) -> + case Item of + "dur" -> [16#00, 16#01]; + "os" -> [16#00, 16#02]; + "or" -> [16#00, 16#03] + end. + +decode_nt(property, Item) -> + case Item of + [16#00, 16#07] -> "jit" + end; +decode_nt(event, Item) -> + case Item of + [16#00, 16#05] -> "netfail"; + [16#00, 16#06] -> "qualert" + end; +decode_nt({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#05] -> % Event netfail + case SubItem of + [16#00, 16#01] -> "cs" + end; + [16#00, 16#06] -> % Event qualert + case Item of + [16#00, 16#01] -> "th" + end + end; +decode_nt(statistics, Item) -> + case Item of + [16#00, 16#01] -> "dur"; + [16#00, 16#02] -> "os"; + [16#00, 16#03] -> "or" + end. + +%%---------------------------------------------------------------------- +%% Name: rtp - RTP Package +%% Version: 1 +%% Extends: nt version 1 +%% Purpose: This package is used to support packet based multimedia +%% data transfer by means of the Real-time Transport Protocol +%% (RTP) [RFC 1889]. +%%---------------------------------------------------------------------- + +capabilities_rtp() -> + [ + {event, "pltrans"}, + {statistics, "ps"}, + {statistics, "pr"}, + {statistics, "pl"}, + {statistics, "jit"}, + {statistics, "delay"} + ]. + +encode_rtp(event, Item) -> + case Item of + "pltrans" -> [16#00, 16#01] + end; +encode_rtp({event_parameter, Item}, SubItem) -> + case Item of + "pltrans" -> + case SubItem of + "rtppltype" -> [16#00, 16#01] + end + end; +encode_rtp(statistics, Item) -> + case Item of + "ps" -> [16#00, 16#04]; + "pr" -> [16#00, 16#05]; + "pl" -> [16#00, 16#06]; + "jit" -> [16#00, 16#07]; + "delay" -> [16#00, 16#08] + end. + +decode_rtp(event, Item) -> + case Item of + [16#00, 16#01] -> "pltrans" + end; +decode_rtp({event_parameter, Item}, SubItem) -> + case Item of + [16#00, 16#01] -> % Event pltrans + case SubItem of + [16#00, 16#01] -> "rtppltype" + end + end; +decode_rtp(statistics, Item) -> + case Item of + [16#00, 16#04] -> "ps"; + [16#00, 16#05] -> "pr"; + [16#00, 16#06] -> "pl"; + [16#00, 16#07] -> "jit"; + [16#00, 16#08] -> "delay" + end. + + +%%---------------------------------------------------------------------- +%% Name: tdmc - TDM Circuit Package +%% Version: 1 +%% Extends: nt version 1 +%% Purpose: This package is used to support TDM circuit terminations. +%%---------------------------------------------------------------------- + +capabilities_tdmc() -> + [ + {property, "ec"}, + {property, "gain"} + ]. + +encode_tdmc(Scope, Item) -> + case Scope of + property -> + case Item of + "ec" -> [16#00, 16#08]; + "gain" -> [16#00, 16#0a] + end + end. + +decode_tdmc(Scope, Item) -> + case Scope of + property -> + case Item of + [16#00, 16#08] -> "ec"; + [16#00, 16#0a] -> "gain" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: swb - SwitchBoard Package +%% Version: 1 +%% Extends: none +%% Purpose: This package is used to support SwitchBoard specials +%%---------------------------------------------------------------------- + +capabilities_swb() -> + [ + {statistics, "fs"}, % Free slots + {statistics, "as"} % Allocated slots + ]. + +encode_swb(Scope, Item) -> + case Scope of + statistics -> + case Item of + "fs" -> [16#00, 16#00]; + "as" -> [16#00, 16#01] + end + end. + +decode_swb(Scope, Item) -> + case Scope of + statistics -> + case Item of + [16#00, 16#00] -> "fs"; + [16#00, 16#01] -> "as" + end + end. + + +%%---------------------------------------------------------------------- +%% Name: native - Pseudo package +%% Version: 1 +%% Extends: None +%% Purpose: Native tags for media stream properties +%% +%% Parameters for Local descriptors and Remote descriptors are +%% specified as tag-value pairs if binary encoding is used for the +%% protocol. This annex contains the property names (PropertyID), the +%% tags (Property Tag), type of the property (Type) and the values +%% (Value).Values presented in the Value field when the field contains +%% references shall be regarded as "information". The reference +%% contains the normative values. If a value field does not contain a +%% reference then the values in that field can be considered as +%% "normative". +%% +%% Tags are given as hexadecimal numbers in this annex. When setting +%% the value of a property, a MGC may underspecify the value according +%% to one of the mechanisms specified in section 7.1.1. +%% +%% For type "enumeration" the value is represented by the value in brack- +%% ets, e.g., Send(0), Receive(1). +%%---------------------------------------------------------------------- +%% +%% C.6. IP +%% +%% ________________________________________________________________ +%% | PropertyID| Tag | Type | Value | +%% | IPv4 | 6001 | 32 BITS | Ipv4Address | +%% | IPv6 | 6002 | 128 BITS | IPv6 Address | +%% | Port | 6003 | Unsigned Int| Port | +%% | Porttype | 6004 | Enumerated | TCP(0),UDP(1),SCTP(2)| +%% |___________|____________|______________|_______________________| +%% +%% +%% C.11. SDP Equivalents +%% +%% ______________________________________________________________ +%% | PropertyID| Tag | Type | Value | +%% | SDP_V | B001| STRING| Protocol Version | +%% | SDP_O | B002| STRING| Owner-creator and session ID | +%% | SDP_S | B003| STRING| Sesson name | +%% | SDP_I | B004| STRING| Session identifier | +%% | SDP_U | B005| STRING| URI of descriptor | +%% | SDC_E | B006| STRING| email address | +%% | SDP_P | B007| STRING| phone number | +%% | SDP_C | B008| STRING| Connection information | +%% | SDP_B | B009| STRING| Bandwidth Information | +%% | SDP_Z | B00A| STRING| time zone adjustment | +%% | SDP_K | B00B| STRING| Encryption Key | +%% | SDP_A | B00C| STRING| Zero or more session attributes| +%% | SDP_T | B00D| STRING| Active Session Time | +%% | SDP_R | B00E| STRING| Zero or more repeat times | +%% | SDP_M | B00F| STRING| Media name and transport addr | +%% | | | | Reference: IETF RFC 2327 | +%% |___________|______|________|_________________________________| +%% +%%---------------------------------------------------------------------- + +capabilities_native() -> + [ + %% C.6. IP + {property, "IPv4"}, + {property, "IPv6"}, + {property, "Port"}, + {property, "Porttype"}, + + %% C.11. SDP Equivalents + {property, "v"}, + {property, "o"}, + {property, "s"}, + {property, "i"}, + {property, "u"}, + {property, "e"}, + {property, "p"}, + {property, "c"}, + {property, "b"}, + {property, "z"}, + {property, "k"}, + {property, "a"}, + {property, "t"}, + {property, "r"}, + {property, "m"} + ]. + +encode_native(Scope, Item) -> + case Scope of + property -> + case Item of + %% IP + "IPv4" -> [16#60, 16#01]; + "IPv6" -> [16#60, 16#02]; + "Port" -> [16#60, 16#03]; + "Porttype" -> [16#60, 16#04]; + + %% SDP + "v" -> [16#b0, 16#01]; + "o" -> [16#b0, 16#02]; + "s" -> [16#b0, 16#03]; + "i" -> [16#b0, 16#04]; + "u" -> [16#b0, 16#05]; + "e" -> [16#b0, 16#06]; + "p" -> [16#b0, 16#07]; + "c" -> [16#b0, 16#08]; + "b" -> [16#b0, 16#09]; + "z" -> [16#b0, 16#0a]; + "k" -> [16#b0, 16#0b]; + "a" -> [16#b0, 16#0c]; + "t" -> [16#b0, 16#0d]; + "r" -> [16#b0, 16#0e]; + "m" -> [16#b0, 16#0f] + end + end. + +decode_native(Scope, [Type, Item]) -> + case Scope of + property -> + case Type of + 16#60 -> + case Item of + 16#01 -> "IPv4"; + 16#02 -> "IPv6"; + 16#03 -> "Port"; + 16#04 -> "Porttype" + end; + + 16#b0 -> + case Item of + 16#01 -> "v"; + 16#02 -> "o"; + 16#03 -> "s"; + 16#04 -> "i"; + 16#05 -> "u"; + 16#06 -> "e"; + 16#07 -> "p"; + 16#08 -> "c"; + 16#09 -> "b"; + 16#0a -> "z"; + 16#0b -> "k"; + 16#0c -> "a"; + 16#0d -> "t"; + 16#0e -> "r"; + 16#0f -> "m" + end + end + end. + +%% ------------------------------------------------------------------- + +% error(Reason) -> +% erlang:error(Reason). + diff --git a/lib/megaco/src/binary/megaco_binary_term_id.erl b/lib/megaco/src/binary/megaco_binary_term_id.erl new file mode 100644 index 0000000000..f975c1ab53 --- /dev/null +++ b/lib/megaco/src/binary/megaco_binary_term_id.erl @@ -0,0 +1,187 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose : Handle ASN.1 BER encoding of Megaco/H.248 +%%---------------------------------------------------------------------- + +-module(megaco_binary_term_id). + + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- + +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- + +-export([encode/2, decode/2]). + + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- + + +%%---------------------------------------------------------------------- +%% Macros +%%---------------------------------------------------------------------- + +-define(default_config, [8,8,8]). + +-define(asn_root_termination_id, + #'TerminationID'{wildcard = [], + id = [16#FF, 16#FF, 16#FF, 16#FF, + 16#FF, 16#FF, 16#FF, 16#FF]}). + +-define(megaco_all_wildcard_termination_id, + #megaco_term_id{contains_wildcards = true, + id = [[?megaco_all]]}). +-define(megaco_choose_wildcard_termination_id, + #megaco_term_id{contains_wildcards = true, + id = [[?megaco_choose]]}). + + +%%---------------------------------------------------------------------- +%% Convert a 'TerminationId' record into a ASN.1 termination id +%% Return {ok, TermId} | {error, Reason} +%%---------------------------------------------------------------------- + +encode(_Config, TermId) when TermId =:= ?megaco_root_termination_id -> + {ok, ?asn_root_termination_id}; +encode(Config, TermId) when (TermId =:= ?megaco_all_wildcard_termination_id) andalso + (Config =:= ?default_config) -> + {ok, asn_all_tid()}; +encode(Config, TermId) when (TermId =:= ?megaco_choose_wildcard_termination_id) andalso + (Config =:= ?default_config) -> + {ok, asn_choose_tid()}; +encode(Config, #megaco_term_id{contains_wildcards = false, id = IDs}) -> + case (catch encode1(IDs,Config)) of + {'EXIT',Reason} -> + {error,Reason}; + EncodedTid -> + {ok, EncodedTid} + end; +encode(Config, #megaco_term_id{contains_wildcards = true, id = IDs}) -> + case (catch encode2(IDs,Config)) of + {'EXIT',Reason} -> + {error,Reason}; + EncodedTid -> + {ok, EncodedTid} + end; +encode(_Config, TermId) -> + {error, {bad_type, TermId}}. + + +first_bit() -> + lists:sum(?default_config) - 1. +asn_all_tid() -> + #'TerminationID'{wildcard = [[(2#11000000 + first_bit())]], + id = [0, 0, 0]}. +asn_choose_tid() -> + #'TerminationID'{wildcard = [[(2#01000000 + first_bit())]], + id = [0, 0, 0]}. + + +%%---------------------------------------------------------------------- +%% Encode without wildcards +%%---------------------------------------------------------------------- +encode1(IDs,LevelConfig) when is_list(LevelConfig) -> + megaco_binary_term_id_gen:encode_without_wildcards(IDs, LevelConfig); + + +%% This is only temporary. Eventually a proper encoder for this case +%% should be implemented +encode1(IDs,LevelConfig) when is_integer(LevelConfig) -> + %% megaco_binary_term_id_8lev:encode_without_wildcards(IDs, LevelConfig). + encode1(IDs,lists:duplicate(LevelConfig,8)). + + +%%---------------------------------------------------------------------- +%% Encode with wildcards +%%---------------------------------------------------------------------- +encode2(IDs,LevelConfig) when is_list(LevelConfig) -> + megaco_binary_term_id_gen:encode_with_wildcards(IDs, LevelConfig); + + +%% This is only temporary. Eventually a proper encoder for this case +%% should be implemented +encode2(IDs,LevelConfig) when is_integer(LevelConfig) -> + %% megaco_binary_term_id_8lev:encode_with_wildcards(IDs, LevelConfig). + encode2(IDs,lists:duplicate(LevelConfig,8)). + + +%%---------------------------------------------------------------------- +%% Convert a ASN.1 termination id into a 'TerminationId' record +%% Return {ok, TerminationId} | {error, Reason} +%%---------------------------------------------------------------------- + +decode(_Config, TermId) when (TermId =:= ?asn_root_termination_id) -> + {ok, ?megaco_root_termination_id}; +decode(Config, #'TerminationID'{wildcard = [], id = IDs}) -> + case (catch decode1(IDs,Config)) of + {'EXIT',Reason} -> + {error,Reason}; + MegacoTid -> + {ok,MegacoTid} + end; +decode(Config, #'TerminationID'{wildcard = Wildcards, id = IDs}) -> + case (catch decode2(Wildcards,IDs,Config)) of + {'EXIT',Reason} -> + {error,Reason}; + MegacoTid -> + {ok,MegacoTid} + end; +decode(_Config, TermId) -> + {error, {bad_type, TermId}}. + + +%%---------------------------------------------------------------------- +%% Decode without wildcards +%%---------------------------------------------------------------------- +decode1(IDs, Lc) when is_list(Lc) -> + megaco_binary_term_id_gen:decode_without_wildcards(IDs, Lc); + +%% This is only temporary. Eventually a proper encoder for this case +%% should be implemented +decode1(IDs, Lc) when is_integer(Lc) -> + %% megaco_binary_term_id_8lev:decode_without_wildcards(IDs, Lc). + decode1(IDs,lists:duplicate(Lc,8)). + + +%%---------------------------------------------------------------------- +%% Decode with wildcards +%%---------------------------------------------------------------------- +decode2(Wildcards, IDs, Lc) when is_list(Lc) -> + megaco_binary_term_id_gen:decode_with_wildcards(Wildcards, IDs, Lc); + +%% This is only temporary. Eventually a proper encoder for this case +%% should be implemented +decode2(Wildcards, IDs, Lc) when is_integer(Lc) -> + %% megaco_binary_term_id_8lev:decode_with_wildcards(Wildcards, IDs, Lc); + decode2(Wildcards, IDs, lists:duplicate(Lc,8)). + + + diff --git a/lib/megaco/src/binary/megaco_binary_term_id_gen.erl b/lib/megaco/src/binary/megaco_binary_term_id_gen.erl new file mode 100644 index 0000000000..c8192c79b6 --- /dev/null +++ b/lib/megaco/src/binary/megaco_binary_term_id_gen.erl @@ -0,0 +1,436 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose : Handle ASN.1 BER encoding of Megaco/H.248 +%%---------------------------------------------------------------------- + +-module(megaco_binary_term_id_gen). + + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- + +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- + +-export([encode_without_wildcards/2, encode_with_wildcards/2, + decode_without_wildcards/2, decode_with_wildcards/3]). + + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- + + +%%---------------------------------------------------------------------- +%% Macros +%%---------------------------------------------------------------------- + +-define(asn_choose, ?megaco_choose). +-define(asn_all, ?megaco_all). + + +%%---------------------------------------------------------------------- +%% Encode without wildcards +%%---------------------------------------------------------------------- +encode_without_wildcards(IDs,LevelConfig) when is_list(LevelConfig) -> + EncodedIDs = encode_ids(false,IDs,LevelConfig), + #'TerminationID'{wildcard = [], id = EncodedIDs}. + +%%---------------------------------------------------------------------- +%% Encode with wildcards +%%---------------------------------------------------------------------- +encode_with_wildcards(IDs,LevelConfig) when is_list(LevelConfig) -> + Wildcards = encode_wildcards(IDs,LevelConfig), + EncodedIDs = encode_ids(true,IDs,LevelConfig), + #'TerminationID'{wildcard = Wildcards, id = EncodedIDs}. + + +%%---------------------------------------------------------------------- +%% Decode without wildcards +%%---------------------------------------------------------------------- +decode_without_wildcards(IDs,Lc) -> + DecodedIDs = decode_ids(IDs,Lc), + #megaco_term_id{contains_wildcards = false, + id = DecodedIDs}. + + +%%---------------------------------------------------------------------- +%% Decode with wildcards +%%---------------------------------------------------------------------- +decode_with_wildcards(Wildcards,IDs,Lc) -> + DecodedIDs = decode_ids(Wildcards,IDs,Lc), + #megaco_term_id{contains_wildcards = true, + id = DecodedIDs}. + + +%%---------------------------------------------------------------------- +%% Convert an internal TermId to an external +%%---------------------------------------------------------------------- + +encode_wildcards(IDs,LevelConfig) -> + case (catch encode_wildcards1(IDs,LevelConfig)) of + {'EXIT',id_config_mismatch} -> + exit({id_config_mismatch,IDs,LevelConfig}); + {'EXIT',Reason} -> + exit(Reason); + Wildcards -> + encode_wildcards2(Wildcards) + end. + +encode_wildcards1(IDs,LevelConfig) -> + encode_wildcards3(IDs,LevelConfig). + +encode_wildcards2(Ws) -> + F = fun(no_wildcard) -> false; (_) -> true end, + lists:filter(F,Ws). + + + +encode_wildcards3(IDs,LevelConfig) -> + encode_wildcards3(IDs,LevelConfig,1,lists:sum(LevelConfig)). + +encode_wildcards3([],[],_,_) -> + []; +encode_wildcards3([Level|Levels],[BitsInLevel|BitsRest],LevelNo,TotSize) -> + case (catch encode_wildcard(Level,BitsInLevel,TotSize-BitsInLevel, + length(Levels))) of + {'EXIT',{Reason,Info}} -> + exit({Reason,{LevelNo,Info}}); + + no_wildcard -> + encode_wildcards3(Levels,BitsRest,LevelNo+1,TotSize-BitsInLevel); + + {level,Wl} -> + [Wl| + encode_wildcards3(Levels,BitsRest,LevelNo+1,TotSize-BitsInLevel)]; + + {recursive,Wr} -> + [Wr]; + + Else -> + exit({wildcard_decode_error,Else}) + end; +encode_wildcards3(Levels,[],LevelNo,TotSize) -> + exit({id_config_mismatch,{Levels,LevelNo,TotSize}}); +encode_wildcards3(L,B,N,S) -> + exit({wildcard_encode_error,{L,B,N,S}}). + + +encode_wildcard([],0,_TotBits,_RemainingIdLevels) -> + no_wildcard; +encode_wildcard([],More,_TotBits,_RemainingIdLevels) -> + exit({to_few_bits_in_level,More}); +encode_wildcard(More,0,_TotBits,_RemainingIdLevels) -> + exit({to_many_bits_in_level,More}); +encode_wildcard([$0|R],Pos,TotBits,RemainingIdLevels) -> + encode_wildcard(R,Pos-1,TotBits,RemainingIdLevels); +encode_wildcard([$1|R],Pos,TotBits,RemainingIdLevels) -> + encode_wildcard(R,Pos-1,TotBits,RemainingIdLevels); +encode_wildcard([?asn_choose],Pos,TotBits,RemainingIdLevels) -> + encode_choose(Pos-1,TotBits,RemainingIdLevels); +encode_wildcard([?asn_all],Pos,TotBits,RemainingIdLevels) -> + encode_all(Pos-1,TotBits,RemainingIdLevels); +encode_wildcard([Val|_Rest],Pos,_TotBits,_RemainingIdLevels) -> + exit({invalid_level_content,{Pos-1,Val}}). + +%% This is the last level specified in the id list. +%% Therefor it is a 'recursive' wildcard, i.e. the 'choose' +%% apply to this level and all remaining levels. +encode_choose(BitPosInLevel,BitsInRemainingConfigLevels,0) + when BitsInRemainingConfigLevels > 0 -> + {recursive,[16#40 + BitPosInLevel + BitsInRemainingConfigLevels]}; + +%% The fact that there is no more bits in the level config +%% means that this is actually the last level. +%% It should not be a 'recursive' case but a 'level' case. +%% Although it is (propably) correct with both. +encode_choose(BitPosInLevel,0,0) -> + {recursive,[16#00 + BitPosInLevel]}; + +%% There are more levels specified in the id list. +%% Therefor it is a 'level' wildcard, i.e. the 'choose' +%% apply to this level only. +encode_choose(BitPosInLevel,BitsInRemainingConfigLevels,RemainingIdLevels) + when RemainingIdLevels > 0 -> + {level,[16#00 + BitPosInLevel + BitsInRemainingConfigLevels]}. + +%% This is the last level specified in the id list. +%% Therefor it is a 'recursive' wildcard, i.e. the 'all' +%% apply to this level and all remaining levels. +encode_all(BitPosInLevel,BitsInRemainingConfigLevels,0) + when BitsInRemainingConfigLevels > 0 -> + {recursive,[16#c0 + BitPosInLevel + BitsInRemainingConfigLevels]}; + +%% The fact that there is no more bits in the level config +%% means that this is actually the last level. +%% It should not be a 'recursive' case but a 'level' case. +%% Although it is (propably) correct with both. +encode_all(BitPosInLevel,0,0) -> + {recursive,[16#80 + BitPosInLevel]}; + +%% There are more levels specified in the id list. +%% Therefor it is a 'level' wildcard, i.e. the 'all' +%% apply to this level only. +encode_all(BitPosInLevel,BitsInRemainingConfigLevels,RemainingIdLevels) + when RemainingIdLevels > 0 -> + {level,[16#80 + BitPosInLevel + BitsInRemainingConfigLevels]}. + + +encode_ids(W,IDs,Config) -> + encode_ids(W,IDs,Config,8,[0],false). + +encode_ids(_,[],[],8,[0|EncodedIDs],_) -> + lists:reverse(EncodedIDs); +encode_ids(W,IDs,Config,0,EncodedIDs,Wf) -> + encode_ids(W,IDs,Config,8,[0|EncodedIDs],Wf); +encode_ids(W,[L|Ls],[C|Cs],R,E,_) -> + case (catch encode_id_level(W,L,C,R,E)) of + {'EXIT',Reason} -> + exit(Reason); + {true,R1,E1} when (length(Ls) =:= 0) -> + encode_ids2(Cs,encode_ids1(R1,E1)); + {WildcardFound1,R1,E1} -> + encode_ids(W,Ls,Cs,R1,E1,WildcardFound1); + {true,E2} when (length(Ls) =:= 0) -> + encode_ids2(Cs,E2); + {WildcardFound2,E2} -> + encode_ids(W,Ls,Cs,8,[0|E2],WildcardFound2) + end; +encode_ids(W,[[]],C,R,E,Wf) when length(C) > 0 -> + exit({empty_last_level,{W,C,R,E,Wf}}); +encode_ids(W,[],C,R,E,false) when length(C) > 0 -> + exit({unexpected_eof_data,{W,C,R,E}}). + +encode_ids1(_R,[0|Es]) -> + [0|Es]; +encode_ids1(R,[E|Es]) -> + [(E bsl R)|Es]. + +encode_ids2([],Es) -> + lists:reverse(Es); +encode_ids2(Cs,Es) -> + Fill = lists:duplicate(lists:sum(Cs) div 8,0), + lists:reverse(Fill ++ Es). + + +encode_id_level(W,L,C,R,[E|Es]) -> + case encode_id_level1(W,L,C,R,E) of + %% End Of Byte (more bits in level) + {eob,_WildcardFound,L1,C1,E1} -> + encode_id_level(W,L1,C1,8,[0,E1|Es]); + + %% End Of Level (more room in byte) + {eol,WildcardFound,R1,E1} -> + {WildcardFound,R1,[E1|Es]}; + + %% Done; Level used up all of the byte + {done,WildcardFound,E1} -> + {WildcardFound,[E1|Es]} + end. + + +encode_id_level1(_W,[],0,0,E) -> + {done,false,E}; +encode_id_level1(_W,[],0,R,E) -> + {eol,false,R,E}; +encode_id_level1(_W,L,C,0,E) -> + {eob,false,L,C,E}; +encode_id_level1(W,[$0|L],C,R,E) -> + encode_id_level1(W,L,C-1,R-1,E bsl 1); +encode_id_level1(W,[$1|L],C,R,E) -> + encode_id_level1(W,L,C-1,R-1,(E bsl 1) + 1); +encode_id_level1(true,[$$],C,R,E) -> + encode_id_level2(C,R,E,$$); +encode_id_level1(true,[$*],C,R,E) -> + encode_id_level2(C,R,E,$*); +encode_id_level1(false,[$$],C,R,_E) -> + exit({wildcard_error,{$$,C,R}}); +encode_id_level1(false,[$*],C,R,_E) -> + exit({wildcard_error,{$*,C,R}}); +encode_id_level1(_W,[L|_Ls],C,R,_E) -> + exit({invalid_level_content,{C,R,L}}). + +encode_id_level2(C,C,E,_W) -> + {done,true,E bsl C}; +encode_id_level2(C,R,E,W) when C > R -> + {eob,true,[W],C-R,E bsl R}; +encode_id_level2(C,R,E,_W) -> + {eol,true,R-C,E bsl C}. + + +%%---------------------------------------------------------------------- +%% Convert an external TermId to an internal +%%---------------------------------------------------------------------- + +%% Decode ID with wildcards +decode_ids(Ws,IDs,Config) when is_list(Config) -> + IDs1 = decode_ids(IDs,Config), + Ws1 = decode_wildcards(Ws,(length(IDs)*8) - 1), + decode_ids1(Ws1,IDs1); + +%% This is only temporary. Eventually a proper encoder for this case +%% should be implemented. +%% This is the case when each level is 8 bits = 1 byte and the config +%% simply indicates the number of (1 byte) levels +decode_ids(Ws,IDs,Config) when is_integer(Config) -> + decode_ids(Ws,IDs,lists:duplicate(Config,8)). + + +%% Decode ID without wildcards +decode_ids(E,Config) when is_list(Config) -> + decode_ids(0,E,Config,[]); + +%% This is only temporary. Eventually a proper encoder for this case +%% should be implemented. +%% This is the case when each level is 8 bits = 1 byte and the config +%% simply indicates the number of (1 byte) levels +decode_ids(E,Config) when is_integer(Config) -> + decode_ids(E,lists:duplicate(Config,8)). + + +%% The [0] is the result of all the bits of the byte has been shifted out. +decode_ids(_B,[0],[],Acc) -> + lists:reverse(Acc); +decode_ids(_B,[E],[],Acc) -> + exit({id_config_mismatch,{two_much_data,E,Acc}}); +decode_ids(_B,E,[],Acc) -> + exit({id_config_mismatch,{two_much_data,E,Acc}}); +decode_ids(B,E,[L|Ls],Acc) -> + case (catch decode_id_level(B,E,L,[])) of + {Level,E1,B1} -> + decode_ids(B1,E1,Ls,[Level|Acc]); + {'EXIT',{id_config_mismatch,{Bx,Ex,Lx,Accx}}} -> + exit({id_level_mismatch,{B,Bx,E,Ex,L,Ls,Lx,Acc,Accx}}) + end. + + +decode_wildcards(Ws,NofBits) -> + lists:keysort(3,[decode_wildcard(W,NofBits) || W <- Ws]). + + +%% ---------------------------------------------------------------------- +%% A decoded wildcard is a three tuple: +%% {wildcard_type(), wildcard_level(), wildcard_offset()} +%% wildcard_type() -> $ | * +%% wildcard_level() -> level | recursive +%% wildcard_offset() -> integer() +%% +%% The "raw" wildcard offset is measured from the end of the id bytes: +%% +%% 0 1 2 3 4 5 6 7 +%% ----------------- +%% | | | | | | | | | +%% ----------------- +%% +%% |<--------| +%% 5 +%% +%% The decoded wildcard offset in contrast is measured from the start +%% of the id field: +%% +%% 0 1 2 3 4 5 6 7 +%% ----------------- +%% | | | | | | | | | +%% ----------------- +%% +%% |---->| +%% 3 +%% + +decode_wildcard([W],NofBits) -> + {decode_wildcard_t(W band 16#80), + decode_wildcard_l(W band 16#40), + NofBits - (W band 16#3F)}. + +decode_wildcard_t(16#80) -> ?asn_all; +decode_wildcard_t(16#00) -> ?asn_choose. + +decode_wildcard_l(16#00) -> level; +decode_wildcard_l(16#40) -> recursive. + + +decode_ids1(W,IDs) -> + lists:reverse(decode_ids1(W,IDs,0,[])). + +decode_ids1([],IDs,_,Acc) -> + lists:reverse(IDs) ++ Acc; +decode_ids1([{Type,recursive,Offset}],IDs,Bp,Acc) -> + decode_ids2(Type,Offset,IDs,Bp,Acc); +decode_ids1([{Type,level,Offset}|Ws],IDs,Bp,Acc) -> + {IDs1,IDs2,Bp1} = decode_ids3(Type,Offset,IDs,Bp,[]), + decode_ids1(Ws,IDs2,Bp1,IDs1++Acc); +decode_ids1(Ws,_,_,_) -> + exit({invalid_wildcards,Ws}). + + +%% Called when recursive wildcard found +decode_ids2(Type,Offset,[ID|IDs],Bp,Acc) -> + LevelSz = length(ID), + Bp1 = Offset-Bp, + case Bp1 >= LevelSz of + true -> + decode_ids2(Type,Offset,IDs,Bp+LevelSz,[ID|Acc]); + false -> + [decode_ids4(Type,Bp1,ID)|Acc] + end. + + +decode_ids3(Type,Offset,[ID|IDs],Bp,Acc) -> + LevelSz = length(ID), + Bp1 = Offset-Bp, + case Bp1 > LevelSz of + true -> + decode_ids3(Type,Offset,IDs,Bp+LevelSz,[ID|Acc]); + false -> + A1 = decode_ids4(Type,Bp1,ID), + {[A1|Acc],IDs,Bp+LevelSz} + end. + + +decode_ids4(Type,0,_ID) -> + [Type]; +decode_ids4(Type,O,[H|T]) -> + [H|decode_ids4(Type,O-1,T)]. + + +%% E: Encoded bits -> [byte()] +%% L: Number of nits in level +decode_id_level(B,E,0,Acc) -> + {lists:reverse(Acc),E,B}; +decode_id_level(8,[_H|T],L,Acc) -> + decode_id_level(0,T,L,Acc); +decode_id_level(B,[H|T],L,Acc) -> + Acc1 = [decode_id_level1(H band 16#80) | Acc], + decode_id_level(B+1,[((H bsl 1) band 16#FF) |T],L-1,Acc1); +decode_id_level(B,E,L,Acc) -> + exit({id_config_mismatch,{B,E,L,Acc}}). + +decode_id_level1(16#80) -> $1; +decode_id_level1(16#00) -> $0. + + diff --git a/lib/megaco/src/binary/megaco_binary_transformer_prev3a.erl b/lib/megaco/src/binary/megaco_binary_transformer_prev3a.erl new file mode 100644 index 0000000000..609947c933 --- /dev/null +++ b/lib/megaco/src/binary/megaco_binary_transformer_prev3a.erl @@ -0,0 +1,1629 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Transform internal form of Megaco/H.248 messages +%%---------------------------------------------------------------------- + +-module(megaco_binary_transformer_prev3a). + +-include_lib("megaco/include/megaco.hrl"). +%% -include_lib("megaco/include/megaco_message.hrl"). +-include_lib("megaco/include/megaco_message_prev3a.hrl"). +-include_lib("megaco/src/app/megaco_internal.hrl"). + +-export([tr_message/3, tr_transaction/3]). + +-define(DEFAULT_NAME_RESOLVER, megaco_binary_name_resolver_prev3a). + +-record(state, {mode, % verify | encode | decode + resolver_module, % + resolver_options}). + +resolve(Type, Item, State, Constraint) -> + case State#state.mode of + verify -> + Item; + encode -> + ?d("resolve(encode) -> encode: ~p",[Item]), + Mod = State#state.resolver_module, + Opt = State#state.resolver_options, + EncodedItem = Mod:encode_name(Opt, Type, Item), + ?d("resolve -> verify contraint for ~p",[EncodedItem]), + verify_constraint(EncodedItem, Constraint); + decode -> + ?d("resolve(decode) -> verify contraint for ~p",[Item]), + DecodedItem = verify_constraint(Item, Constraint), + Mod = State#state.resolver_module, + Opt = State#state.resolver_options, + ?d("resolve(decode) -> decode: ~p",[DecodedItem]), + Mod:decode_name(Opt, Type, DecodedItem) + end. + +verify_constraint(Item, valid) -> + Item; +verify_constraint(Item, Constraint) when is_function(Constraint) -> + Constraint(Item). + +tr_message(MegaMsg, Mode, Config) -> + case Config of + [native] -> + MegaMsg; + [verify] -> + State = #state{mode = verify}, + tr_MegacoMessage(MegaMsg, State); + [] -> + State = #state{mode = Mode, + resolver_module = ?DEFAULT_NAME_RESOLVER, + resolver_options = [8, 8, 8]}, + tr_MegacoMessage(MegaMsg, State); + [{binary_name_resolver, {Module, Options}}] when is_atom(Module) -> + State = #state{mode = Mode, + resolver_module = Module, + resolver_options = Options}, + tr_MegacoMessage(MegaMsg, State) + end. + +tr_transaction(Trans, Mode, Config) -> + case Config of + [native] -> + Trans; + [verify] -> + State = #state{mode = verify}, + tr_Transaction(Trans, State); + [] -> + State = #state{mode = Mode, + resolver_module = ?DEFAULT_NAME_RESOLVER, + resolver_options = [8, 8, 8]}, + tr_Transaction(Trans, State); + [{binary_name_resolver, {Module, Options}}] when is_atom(Module) -> + State = #state{mode = Mode, + resolver_module = Module, + resolver_options = Options}, + tr_Transaction(Trans, State) + end. + +tr_MegacoMessage(#'MegacoMessage'{authHeader = Auth, + mess = Mess}, + State) -> + ?d("tr_MegacoMessage -> entry with" + "~n Auth: ~p" + "~n Mess: ~p" + "~n State: ~p", [Auth, Mess, State]), + #'MegacoMessage'{authHeader = tr_opt_AuthenticationHeader(Auth, State), + mess = tr_Message(Mess, State)}. + +tr_opt_AuthenticationHeader(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_AuthenticationHeader(#'AuthenticationHeader'{secParmIndex = SPI, + seqNum = SN, + ad = AuthData}, + State) -> + #'AuthenticationHeader'{secParmIndex = tr_SecurityParmIndex(SPI, State), + seqNum = tr_SequenceNum(SN, State), + ad = tr_AuthData(AuthData, State)}. + +tr_SecurityParmIndex(SPI, State) -> + tr_HEXDIG(SPI, State, 4, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_SequenceNum(SN, State) -> + tr_HEXDIG(SN, State, 4, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_AuthData(AuthData, State) -> + tr_HEXDIG(AuthData, State, 12, 32). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_Message(#'Message'{version = Version, + mId = MID, + messageBody = Body}, + State) -> + #'Message'{version = tr_version(Version, State), + mId = tr_MId(MID, State), + messageBody = tr_Message_messageBody(Body, State)}. + +tr_version(Version, State) -> + tr_DIGIT(Version, State, 0, 99). + +tr_Message_messageBody({Tag, Val}, State) -> + Val2 = + case Tag of + messageError -> tr_ErrorDescriptor(Val, State); + transactions when is_list(Val) -> [tr_Transaction(T, State) || T <- Val] + end, + {Tag, Val2}. + +tr_MId({Tag, Val}, State) -> + Val2 = + case Tag of + ip4Address -> tr_IP4Address(Val, State); + ip6Address -> tr_IP6Address(Val, State); + domainName -> tr_DomainName(Val, State); + deviceName -> tr_PathName(Val, State); + mtpAddress -> tr_mtpAddress(Val, State) + end, + {Tag, Val2}. + +tr_mtpAddress(MtpAddr, State) -> + tr_OCTET_STRING(MtpAddr, State, 2, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_DomainName(#'DomainName'{name = Name, + portNumber = Port}, + State) -> + Domain = #'DomainName'{name = tr_STRING(Name, State), % BUGBUG: Mismatch between ASN.1 and ABNF + portNumber = tr_opt_portNumber(Port, State)}, + {domainName, Domain2} = resolve(mid, {domainName, Domain}, State, valid), + Domain2. + +tr_IP4Address(#'IP4Address'{address = [A1, A2, A3, A4], + portNumber = Port}, + State) -> + #'IP4Address'{address = [tr_V4hex(A1, State), + tr_V4hex(A2, State), + tr_V4hex(A3, State), + tr_V4hex(A4, State)], + portNumber = tr_opt_portNumber(Port, State)}. + +tr_V4hex(Val, State) -> + tr_DIGIT(Val, State, 0, 255). + +tr_IP6Address(_Val, _State) -> + error(ipv6_not_supported). %% BUGBUG: nyi + +tr_PathName(Path, State) -> + %% BUGBUG: ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" ) + %% BUGBUG: ["@" pathDomainName ] + Constraint = fun({deviceName, Item}) -> tr_STRING(Item, State, 1, 64) end, + resolve(mid, {deviceName, Path}, State, Constraint). + +tr_Transaction({Tag, Val}, State) -> + Val2 = + case Tag of + transactionRequest -> tr_TransactionRequest(Val, State); + transactionPending -> tr_TransactionPending(Val, State); + transactionReply -> tr_TransactionReply(Val, State); + transactionResponseAck -> [tr_TransactionAck(T, State) || T <- Val] + end, + {Tag, Val2}. + +tr_TransactionAck(#'TransactionAck'{firstAck = First, + lastAck = Last}, + State) -> + #'TransactionAck'{firstAck = tr_TransactionId(First, State), + lastAck = tr_opt_TransactionId(Last, State)}. + +tr_opt_TransactionId(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TransactionId(Id, State) -> + tr_TransactionId(Id, State). + +tr_TransactionId(Id, State) -> + tr_UINT32(Id, State). + +tr_TransactionRequest(#'TransactionRequest'{transactionId = Id, + actions = Actions}, + State) when is_list(Actions) -> + + #'TransactionRequest'{transactionId = tr_TransactionId(Id, State), + actions = [tr_ActionRequest(ActReq, State) || ActReq <- Actions]}. + +tr_TransactionPending(#'TransactionPending'{transactionId = Id}, + State) -> + #'TransactionPending'{transactionId = tr_TransactionId(Id, State)}. + +tr_TransactionReply(#'TransactionReply'{transactionId = Id, + immAckRequired = ImmAck, + transactionResult = TransRes, + %% These fields are actually not + %% supported in this implementation, + %% but because the messanger module + %% cannot see any diff between the + %% various v3 implementations... + segmentNumber = asn1_NOVALUE, + segmentationComplete = asn1_NOVALUE}, + State) -> + #'TransactionReply'{transactionId = tr_TransactionId(Id, State), + immAckRequired = tr_opt_null(ImmAck, State), + transactionResult = tr_TransactionReply_transactionResult(TransRes, State), + segmentNumber = asn1_NOVALUE, + segmentationComplete = asn1_NOVALUE}; +tr_TransactionReply(TR, _State) -> + error({unsupported_TransactionReply, TR}). + +tr_opt_null(asn1_NOVALUE, _State) -> asn1_NOVALUE; +tr_opt_null('NULL', _State) -> 'NULL'. + +tr_TransactionReply_transactionResult({Tag, Val}, State) -> + Val2 = + case Tag of + transactionError -> + tr_ErrorDescriptor(Val, State); + actionReplies when is_list(Val) andalso (Val =/= []) -> + [tr_ActionReply(ActRep, State) || ActRep <- Val] + end, + {Tag, Val2}. + +tr_opt_ErrorDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ErrorDescriptor(ErrDesc, State) -> + tr_ErrorDescriptor(ErrDesc, State). + +tr_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code, + errorText = Text}, + State) -> + #'ErrorDescriptor'{errorCode = tr_ErrorCode(Code, State), + errorText = tr_opt_ErrorText(Text, State)}. + +tr_ErrorCode(Code, State) -> + tr_DIGIT(Code, State, 0, 999). + +tr_opt_ErrorText(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ErrorText(Text, State) -> + tr_QUOTED_STRING(Text, State). + +tr_ContextID(CtxId, State) -> + case CtxId of + ?megaco_all_context_id -> ?megaco_all_context_id; + ?megaco_null_context_id -> ?megaco_null_context_id; + ?megaco_choose_context_id -> ?megaco_choose_context_id; + Int when is_integer(Int) -> tr_UINT32(Int, State) + end. + +tr_ActionRequest(#'ActionRequest'{contextId = CtxId, + contextRequest = CtxReq, + contextAttrAuditReq = CtxAuditReq, + commandRequests = CmdReqList}, + State) -> + #'ActionRequest'{contextId = tr_ContextID(CtxId, State), + contextRequest = tr_opt_ContextRequest(CtxReq, State), + contextAttrAuditReq = tr_opt_ContextAttrAuditRequest(CtxAuditReq, State), + commandRequests = [tr_CommandRequest(CmdReq, State) || CmdReq <- CmdReqList]}. + +tr_ActionReply(#'ActionReply'{contextId = CtxId, + errorDescriptor = ErrDesc, + contextReply = CtxRep, + commandReply = CmdRepList}, + State) -> + CmdRepList2 = [tr_CommandReply(CmdRep, State) || CmdRep <- CmdRepList], + #'ActionReply'{contextId = tr_ContextID(CtxId, State), + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State), + contextReply = tr_opt_ContextRequest(CtxRep, State), + commandReply = CmdRepList2}. + +tr_opt_ContextRequest(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ContextRequest(CR, State) -> + tr_ContextRequest(CR, State). + +tr_ContextRequest(#'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = TopReqList, + iepsCallind = Ind, + contextProp = Props}, + State) -> + Prio2 = + case Prio of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_integer(Prio, State, 0, 15) + end, + Em2 = + case Em of + asn1_NOVALUE -> asn1_NOVALUE; + false -> false; + true -> true + end, + TopReqList2 = + case TopReqList of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_TopologyRequest(TopReq, State) || + TopReq <- TopReqList] + end, + Ind2 = + case Ind of + asn1_NOVALUE -> asn1_NOVALUE; + false -> false; + true -> true + end, + Props2 = + case Props of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_PropertyParm(Prop, State) || Prop <- Props] + end, + #'ContextRequest'{priority = Prio2, + emergency = Em2, + topologyReq = TopReqList2, + iepsCallind = Ind2, + contextProp = Props2}. + +tr_opt_ContextAttrAuditRequest(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ContextAttrAuditRequest(CAAR, State) -> + tr_ContextAttrAuditRequest(CAAR, State). + +tr_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepsCallind = Ind, + contextPropAud = Props}, + State) -> + Top2 = tr_opt_null(Top, State), + Em2 = tr_opt_null(Em, State), + Prio2 = tr_opt_null(Prio, State), + Ind2 = tr_opt_null(Ind, State), + Props2 = + case Props of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + [tr_indAudPropertyParm(Prop, State) || Prop <- Props] + end, + #'ContextAttrAuditRequest'{topology = Top2, + emergency = Em2, + priority = Prio2, + iepsCallind = Ind2, + contextPropAud = Props2}. + +tr_CommandRequest(#'CommandRequest'{command = Cmd, + optional = Opt, + wildcardReturn = Wild}, + State) -> + #'CommandRequest'{optional = tr_opt_null(Opt, State), + wildcardReturn = tr_opt_null(Wild, State), + command = tr_Command(Cmd, State)}. + +tr_Command({Tag, Val}, State) -> + Val2 = + case Tag of + addReq -> tr_AmmRequest(Val, State); + moveReq -> tr_AmmRequest(Val, State); + modReq -> tr_AmmRequest(Val, State); + subtractReq -> tr_SubtractRequest(Val, State); + auditCapRequest -> tr_AuditRequest(Val, State); + auditValueRequest -> tr_AuditRequest(Val, State); + notifyReq -> tr_NotifyRequest(Val, State); + serviceChangeReq -> tr_ServiceChangeRequest(Val, State) + end, + {Tag, Val2}. + +tr_CommandReply({Tag, Val}, State) -> + Val2 = + case Tag of + addReply -> tr_AmmsReply(Val, State); + moveReply -> tr_AmmsReply(Val, State); + modReply -> tr_AmmsReply(Val, State); + subtractReply -> tr_AmmsReply(Val, State); + auditCapReply -> tr_AuditReply(Val, State); + auditValueReply -> tr_AuditReply(Val, State); + notifyReply -> tr_NotifyReply(Val, State); + serviceChangeReply -> tr_ServiceChangeReply(Val, State) + end, + {Tag, Val2}. + +tr_TopologyRequest(#'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = Dir}, + State) -> + Dir2 = + case Dir of + bothway -> bothway; + isolate -> isolate; + oneway -> oneway + end, + #'TopologyRequest'{terminationFrom = tr_TerminationID(From, State), + terminationTo = tr_TerminationID(To, State), + topologyDirection = Dir2}. + +tr_AmmRequest(#'AmmRequest'{terminationID = IdList, + descriptors = DescList}, + State) -> + #'AmmRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + descriptors = tr_ammDescriptors(DescList, [], State)}. + +tr_ammDescriptors([], Acc, _State) -> + lists:reverse(Acc); +tr_ammDescriptors([Desc|Descs], Acc, State) -> + case tr_ammDescriptor(Desc, State) of + {_, deprecated} when State#state.mode =:= encode -> + error({deprecated, Desc}); + {_, deprecated} when State#state.mode =:= decode -> + %% SKIP + tr_ammDescriptors(Descs, Acc, State); + {_, deprecated} -> + %% SKIP + tr_ammDescriptors(Descs, Acc, State); + NewDesc -> + tr_ammDescriptors(Descs, [NewDesc|Acc], State) + end. + +tr_ammDescriptor({Tag, Desc}, State) -> + Desc2 = + case Tag of + mediaDescriptor -> tr_MediaDescriptor(Desc, State); + modemDescriptor -> tr_ModemDescriptor(Desc, State); + muxDescriptor -> tr_MuxDescriptor(Desc, State); + eventsDescriptor -> tr_EventsDescriptor(Desc, State); + eventBufferDescriptor -> tr_EventBufferDescriptor(Desc, State); + signalsDescriptor -> tr_SignalsDescriptor(Desc, State); + digitMapDescriptor -> tr_DigitMapDescriptor(Desc, State); + auditDescriptor -> tr_AuditDescriptor(Desc, State); + statisticsDescriptor -> tr_StatisticsDescriptor(Desc, State) + end, + {Tag, Desc2}. + +tr_AmmsReply(#'AmmsReply'{terminationID = IdList, + terminationAudit = TermAudit}, + State) -> + TermAudit2 = + case TermAudit of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_TerminationAudit(TermAudit, State) + end, + #'AmmsReply'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + terminationAudit = TermAudit2}. + +tr_SubtractRequest(#'SubtractRequest'{terminationID = IdList, + auditDescriptor = Desc}, + State) -> + #'SubtractRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + auditDescriptor = tr_opt_AuditDescriptor(Desc, State)}. + +tr_AuditRequest(#'AuditRequest'{terminationID = Id, + auditDescriptor = Desc}, + State) -> + #'AuditRequest'{terminationID = tr_TerminationID(Id, State), + auditDescriptor = tr_AuditDescriptor(Desc, State)}. + +%% auditReply = (AuditValueToken / AuditCapToken ) +%% ( contextTerminationAudit / auditOther) +%% auditOther = EQUAL TerminationID LBRKT +%% terminationAudit RBRKT +%% terminationAudit = auditReturnParameter *(COMMA auditReturnParameter) +%% +%% contextTerminationAudit = EQUAL CtxToken ( terminationIDList / +%% LBRKT errorDescriptor RBRKT ) + +tr_AuditReply({Tag, Val}, State) -> + Val2 = + case Tag of + contextAuditResult -> + [tr_TerminationID(Id, State) || Id <- Val]; + error -> + tr_ErrorDescriptor(Val, State); + auditResult -> + tr_AuditResult(Val, State) + end, + {Tag, Val2}. + +tr_AuditResult(#'AuditResult'{terminationID = Id, + terminationAuditResult = AuditRes}, + State) -> + #'AuditResult'{terminationID = tr_TerminationID(Id, State), + terminationAuditResult = tr_TerminationAudit(AuditRes, State)}. + +tr_opt_AuditDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_AuditDescriptor(Desc, State) -> + tr_AuditDescriptor(Desc, State). + +%% BUGBUG BUGBUG BUGBUG +%% With this construction it is possible to have both auditToken +%% and auditPropertyToken, but it is actually valid? +tr_AuditDescriptor(#'AuditDescriptor'{auditToken = Tokens, + auditPropertyToken = APTs}, + State) -> + Tokens2 = + case Tokens of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_auditItem(Token, State) || Token <- Tokens] + end, + %% v2 + APTs2 = + case APTs of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + [tr_indAuditParameter(APT, State) || APT <- APTs] + end, + #'AuditDescriptor'{auditToken = Tokens2, + auditPropertyToken = APTs2}. + +tr_auditItem(Token, _State) -> + case Token of + muxToken -> muxToken; + modemToken -> modemToken; + mediaToken -> mediaToken; + eventsToken -> eventsToken; + signalsToken -> signalsToken; + digitMapToken -> digitMapToken; + statsToken -> statsToken; + observedEventsToken -> observedEventsToken; + packagesToken -> packagesToken; + eventBufferToken -> eventBufferToken + end. + +%% --- v2 begin --- + +tr_indAuditParameter({Tag, Val}, State) -> + Val2 = + case Tag of + indAudMediaDescriptor -> + tr_indAudMediaDescriptor(Val, State); + indAudEventsDescriptor -> + tr_indAudEventsDescriptor(Val, State); + indAudSignalsDescriptor -> + tr_indAudSignalsDescriptor(Val, State); + indAudDigitMapDescriptor -> + tr_indAudDigitMapDescriptor(Val, State); + indAudEventBufferDescriptor -> + tr_indAudEventBufferDescriptor(Val, State); + indAudStatisticsDescriptor -> + tr_indAudStatisticsDescriptor(Val, State); + indAudPackagesDescriptor -> + tr_indAudPackagesDescriptor(Val, State) + end, + {Tag, Val2}. + + +%% - + +tr_indAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = S}, + State) -> + TSD2 = + case TSD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudTerminationStateDescriptor(TSD, State) + end, + S2 = + case S of + asn1_NOVALUE -> + asn1_NOVALUE; + {oneStream, OS} -> + {oneStream, tr_indAudStreamParms(OS, State)}; + {multiStream, MS} -> + MS2 = [tr_indAudStreamDescriptor(MS1, State) || MS1 <- MS], + {multiStream, MS2} + end, + #'IndAudMediaDescriptor'{termStateDescr = TSD2, + streams = S2}. + +tr_indAudTerminationStateDescriptor(Val, State) + when is_record(Val, 'IndAudTerminationStateDescriptor') -> + #'IndAudTerminationStateDescriptor'{propertyParms = Parms, + eventBufferControl = EBC, + serviceState = SS} = Val, + Parms2 = [tr_indAudPropertyParm(Parm, State) || Parm <- Parms], + EBC2 = tr_opt_null(EBC, State), + SS2 = tr_opt_null(SS, State), + #'IndAudTerminationStateDescriptor'{propertyParms = Parms2, + eventBufferControl = EBC2, + serviceState = SS2}. + + +tr_indAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD, + statisticsDescriptor = SD}, + State) -> + LCD2 = + case LCD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudLocalControlDescriptor(LCD, State) + end, + LD2 = + case LD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudLocalRemoteDescriptor(LD, State) + end, + RD2 = + case RD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudLocalRemoteDescriptor(RD, State) + end, + SD2 = + case SD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudStatisticsDescriptor(SD, State) + end, + #'IndAudStreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2, + statisticsDescriptor = SD2}. + +tr_indAudLocalControlDescriptor(Val, State) + when is_record(Val, 'IndAudLocalControlDescriptor') -> + #'IndAudLocalControlDescriptor'{streamMode = M, + reserveValue = V, + reserveGroup = G, + propertyParms = P} = Val, + M2 = tr_opt_null(M, State), + V2 = tr_opt_null(V, State), + G2 = tr_opt_null(G, State), + P2 = tr_indAudLocalControlDescriptor_propertyParms(P, State), + #'IndAudLocalControlDescriptor'{streamMode = M2, + reserveValue = V2, + reserveGroup = G2, + propertyParms = P2}. + +tr_indAudLocalControlDescriptor_propertyParms(Parms, State) + when is_list(Parms) andalso (length(Parms) > 0) -> + [tr_indAudPropertyParm(Parm, State) || Parm <- Parms]; +tr_indAudLocalControlDescriptor_propertyParms(asn1_NOVALUE, _State) -> + asn1_NOVALUE. + +tr_indAudLocalRemoteDescriptor(#'IndAudLocalRemoteDescriptor'{propGroupID = ID, + propGrps = Grps}, + State) -> + #'IndAudLocalRemoteDescriptor'{propGroupID = tr_opt_UINT16(ID, State), + propGrps = tr_indAudPropertyGroup(Grps, + State)}. + +tr_indAudPropertyGroup(Grps, State) when is_list(Grps) -> + [tr_indAudPropertyParm(Parm, State) || Parm <- Grps]. + +tr_indAudPropertyParm(#'IndAudPropertyParm'{name = Name0}, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(property, Name0, State, Constraint), + #'IndAudPropertyParm'{name = Name}. + + +tr_indAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = ID, + streamParms = Parms}, + State) -> + #'IndAudStreamDescriptor'{streamID = tr_StreamID(ID, State), + streamParms = tr_indAudStreamParms(Parms, + State)}. + + +%% - + +tr_indAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID, + pkgdName = Name0, + streamID = SID}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(event, Name0, State, Constraint), + #'IndAudEventsDescriptor'{requestID = tr_opt_RequestID(RID, State), + pkgdName = Name, + streamID = tr_opt_StreamID(SID, State)}. + + +%% - + +tr_indAudSignalsDescriptor({Tag, Val}, State) -> + case Tag of + signal -> + {signal, tr_indAudSignal(Val, State)}; + seqSigList -> + {seqSigList, tr_indAudSeqSigList(Val, State)} + end. + +tr_opt_indAudSignal(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_indAudSignal(Val, State) -> + tr_indAudSignal(Val, State). + +tr_indAudSignal(#'IndAudSignal'{signalName = Name0, + streamID = SID}, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(signal, Name0, State, Constraint), + #'IndAudSignal'{signalName = Name, + streamID = tr_opt_StreamID(SID, State)}. + +tr_indAudSeqSigList(#'IndAudSeqSigList'{id = ID, + signalList = SigList}, State) -> + #'IndAudSeqSigList'{id = tr_integer(ID, State, 0, 65535), + signalList = tr_opt_indAudSignal(SigList, State)}. + +%% - + +tr_indAudDigitMapDescriptor(#'IndAudDigitMapDescriptor'{digitMapName = Name}, + State) -> + #'IndAudDigitMapDescriptor'{digitMapName = + tr_opt_DigitMapName(Name, State)}. + + +%% - + +tr_indAudEventBufferDescriptor(#'IndAudEventBufferDescriptor'{eventName = N, + streamID = SID}, + State) -> + ?d("tr_indAudEventBufferDescriptor -> entry with" + "~n N: ~p" + "~n SID: ~p", [N, SID]), + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(event, N, State, Constraint), + ?d("tr_indAudEventBufferDescriptor -> entry with" + "~n Name: ~p", [Name]), + #'IndAudEventBufferDescriptor'{eventName = Name, + streamID = tr_opt_StreamID(SID, State)}. + +%% - + +tr_indAudStatisticsDescriptor(#'IndAudStatisticsDescriptor'{statName = N}, + State) -> + ?d("tr_indAudEventBufferDescriptor -> entry with" + "~n N: ~p", [N]), + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(statistics, N, State, Constraint), + #'IndAudStatisticsDescriptor'{statName = Name}. + + +%% - + +tr_indAudPackagesDescriptor(#'IndAudPackagesDescriptor'{packageName = N, + packageVersion = V}, + State) -> + ?d("tr_indAudPackagesDescriptor -> entry with" + "~n N: ~p" + "~n V: ~p", [N, V]), + Constraint = fun(Item) -> tr_Name(Item, State) end, + Name = resolve(package, N, State, Constraint), + ?d("tr_indAudPackagesDescriptor -> entry with" + "~n Name: ~p", [Name]), + #'IndAudPackagesDescriptor'{packageName = Name, + packageVersion = tr_integer(V, State, 0, 99)}. + +%% -- v2 end -- + + +tr_TerminationAudit(ParmList, State) when is_list(ParmList) -> + do_tr_TerminationAudit(ParmList, [], State). + +do_tr_TerminationAudit([], Acc, _State) -> + lists:reverse(Acc); +do_tr_TerminationAudit([Parm|ParmList], Acc, State) -> + case tr_AuditReturnParameter(Parm, State) of + {_, deprecated} when State#state.mode =:= encode -> + error({deprecated, Parm}); + {_, deprecated} when State#state.mode =:= decode -> + %% SKIP + do_tr_TerminationAudit(ParmList, Acc, State); + {_, deprecated} -> + %% SKIP + do_tr_TerminationAudit(ParmList, Acc, State); + NewParm -> + do_tr_TerminationAudit(ParmList, [NewParm|Acc], State) + end. + +tr_AuditReturnParameter({Tag, Val}, State) -> + Val2 = + case Tag of + errorDescriptor -> + tr_ErrorDescriptor(Val, State); + mediaDescriptor -> + tr_MediaDescriptor(Val, State); + modemDescriptor -> + tr_ModemDescriptor(Val, State); + muxDescriptor -> + tr_MuxDescriptor(Val, State); + eventsDescriptor -> + tr_EventsDescriptor(Val, State); + eventBufferDescriptor -> + tr_EventBufferDescriptor(Val, State); + signalsDescriptor -> + tr_SignalsDescriptor(Val, State); + digitMapDescriptor -> + tr_DigitMapDescriptor(Val, State); + observedEventsDescriptor -> + tr_ObservedEventsDescriptor(Val, State); + statisticsDescriptor -> + tr_StatisticsDescriptor(Val, State); + packagesDescriptor -> + tr_PackagesDescriptor(Val, State); + emptyDescriptors -> + tr_EmptyDescriptors(Val, State) + end, + {Tag, Val2}. + +tr_EmptyDescriptors(#'AuditDescriptor'{auditToken = Tokens}, + State) -> + case Tokens of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_auditItem(Token, State) || Token <- Tokens] + end. + +tr_NotifyRequest(#'NotifyRequest'{terminationID = IdList, + observedEventsDescriptor = ObsDesc, + errorDescriptor = ErrDesc}, + State) -> + %% BUGBUG: Mismatch between ASN.1 and ABNF + %% BUGBUG: The following ought to be a 'choice' + #'NotifyRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + observedEventsDescriptor = tr_ObservedEventsDescriptor(ObsDesc, State), + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State)}. + +tr_NotifyReply(#'NotifyReply'{terminationID = IdList, + errorDescriptor = ErrDesc}, + State) -> + #'NotifyReply'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State)}. + +tr_ObservedEventsDescriptor(#'ObservedEventsDescriptor'{requestId = Id, + observedEventLst = Events}, + State) when is_list(Events) -> + #'ObservedEventsDescriptor'{requestId = tr_RequestID(Id, State), + observedEventLst = [tr_ObservedEvent(E, State) || E <- Events]}. + +%% ;time per event, because it might be buffered +%% observedEvent = [ TimeStamp LWSP COLON] LWSP +%% pkgdName [ LBRKT observedEventParameter +%% *(COMMA observedEventParameter) RBRKT ] +%% +%% ;at-most-once eventStream, every eventParameterName at most once +%% observedEventParameter = eventStream / eventOther + +tr_ObservedEvent(#'ObservedEvent'{eventName = Name, + streamID = Id, + eventParList = Parms, + timeNotation = Time}, + State) -> + #'ObservedEvent'{eventName = tr_EventName(Name, State), + streamID = tr_opt_StreamID(Id, State), + eventParList = [tr_EventParameter(P, Name, State) || P <- Parms], + timeNotation = tr_opt_TimeNotation(Time, State)}. + +tr_EventName(Name, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + resolve(event, Name, State, Constraint). + +tr_EventParameter(#'EventParameter'{eventParameterName = ParName, + value = Value, + extraInfo = Extra}, + EventName, + State) -> + %% BUGBUG: event parameter name + Constraint = fun(Item) -> tr_Name(Item, State) end, + N = resolve({event_parameter, EventName}, ParName, State, Constraint), + #'EventParameter'{eventParameterName = N, + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_ServiceChangeRequest(#'ServiceChangeRequest'{terminationID = IdList, + serviceChangeParms = Parms}, + State) -> + #'ServiceChangeRequest'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + serviceChangeParms = tr_ServiceChangeParm(Parms, State)}. + +%% serviceChangeReply = ServiceChangeToken EQUAL TerminationID +%% [LBRKT (errorDescriptor / +%% serviceChangeReplyDescriptor) RBRKT] +%% serviceChangeReplyDescriptor = ServicesToken LBRKT +%% servChgReplyParm *(COMMA servChgReplyParm) RBRKT +%% +%% ;at-most-once. Version is REQUIRED on first ServiceChange response +%% servChgReplyParm = (serviceChangeAddress / serviceChangeMgcId / +%% serviceChangeProfile / serviceChangeVersion ) +tr_ServiceChangeReply(#'ServiceChangeReply'{terminationID = IdList, + serviceChangeResult = Res}, + State) -> + #'ServiceChangeReply'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + serviceChangeResult = tr_ServiceChangeResult(Res, State)}. + +tr_ServiceChangeResult({Tag, Val}, State) -> + Val2 = + case Tag of + errorDescriptor -> tr_ErrorDescriptor(Val, State); + serviceChangeResParms -> tr_ServiceChangeResParm(Val, State) + end, + {Tag, Val2}. + +%% TerminationID = "ROOT" / pathNAME / "$" / "*" +%% ; Total length of pathNAME must not exceed 64 chars. +%% pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" ) +%% ["@" pathDomainName ] + +tr_TerminationID(TermId, State) when State#state.mode =/= verify -> + resolve(term_id, TermId, State, valid); +tr_TerminationID(#'TerminationID'{wildcard = Wild, + id = Id}, + _State) -> + #'TerminationID'{wildcard = Wild, + id = Id}; +tr_TerminationID(#megaco_term_id{contains_wildcards = IsWild, + id = Id}, + State) -> + #megaco_term_id{contains_wildcards = tr_bool(IsWild, State), + id = [tr_term_id_component(Sub, State) || Sub <- Id]}. + +tr_opt_bool(asn1_NOVALUE, _State) -> asn1_NOVALUE; +tr_opt_bool(Bool, State) -> tr_bool(Bool, State). + +tr_bool(true, _State) -> true; +tr_bool(false, _State) -> false. + +tr_term_id_component(Sub, _State) -> + case Sub of + all -> all; + choose -> choose; + Char when is_integer(Char) -> Char + end. + +%% mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT +%% ; at-most-once per item +%% ; and either streamParm or streamDescriptor but not both +%% mediaParm = (streamParm / streamDescriptor / +%% terminationStateDescriptor) +%% ; at-most-once +%% streamParm = ( localDescriptor / remoteDescriptor / +%% localControlDescriptor ) +%% streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm +%% *(COMMA streamParm) RBRKT +tr_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TermState, + streams = Streams}, + State) -> + #'MediaDescriptor'{termStateDescr = tr_opt_TerminationStateDescriptor(TermState, State), + streams = tr_opt_streams(Streams, State)}. + +tr_opt_streams(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_streams({Tag, Val}, State) -> + Val2 = + case Tag of + oneStream -> tr_StreamParms(Val, State); + multiStream -> [tr_StreamDescriptor(SD, State) || SD <- Val] + end, + {Tag, Val2}. + +tr_StreamParms(#'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD, + statisticsDescriptor = SD}, + State) -> + LCD2 = tr_opt_LocalControlDescriptor(LCD, State), + LD2 = tr_opt_LocalRemoteDescriptor(LD, State), + RD2 = tr_opt_LocalRemoteDescriptor(RD, State), + SD2 = tr_opt_StatisticsDescriptor(SD, State), + #'StreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2, + statisticsDescriptor = SD2}. + +tr_StreamDescriptor(#'StreamDescriptor'{streamID = Id, + streamParms = Parms}, + State) -> + #'StreamDescriptor'{streamID = tr_StreamID(Id, State), + streamParms = tr_StreamParms(Parms, State)}. + +%% localControlDescriptor = LocalControlToken LBRKT localParm +%% *(COMMA localParm) RBRKT +%% +%% ; at-most-once per item +%% localParm = ( streamMode / propertyParm / +%% reservedValueMode / reservedGroupMode ) +%% reservedValueMode = ReservedValueToken EQUAL ( "ON" / "OFF" ) +%% reservedGroupMode = ReservedGroupToken EQUAL ( "ON" / "OFF" ) +%% +%% reservedMode = ReservedToken EQUAL ( "ON" / "OFF" ) +%% +%% streamMode = ModeToken EQUAL streamModes +tr_opt_LocalControlDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = Mode, + reserveGroup = Group, + reserveValue = Value, + propertyParms = Props}, + State) -> + #'LocalControlDescriptor'{streamMode = tr_opt_StreamMode(Mode, State), + reserveGroup = tr_opt_bool(Group, State), + reserveValue = tr_opt_bool(Value, State), + propertyParms = [tr_PropertyParm(P, State) || P <- Props]}. + +tr_opt_StreamMode(Mode, _State) -> + case Mode of + asn1_NOVALUE -> asn1_NOVALUE; + sendOnly -> sendOnly; + recvOnly -> recvOnly; + sendRecv -> sendRecv; + inactive -> inactive; + loopBack -> loopBack + end. + +tr_Name(Name, State) -> + %% BUGBUG: transform + %% BUGBUG: NAME = ALPHA *63(ALPHA / DIGIT / "_" ) + tr_STRING(Name, State, 2, 2). + +tr_PkgdName(Name, State) -> + %% BUGBUG: transform + %% BUGBUG: pkgdName = (NAME / "*") SLASH (ItemID / "*" ) + tr_OCTET_STRING(Name, State, 4, 4). + +%% When text encoding the protocol, the descriptors consist of session +%% descriptions as defined in SDP (RFC2327), except that the "s=", "t=" +%% and "o=" lines are optional. When multiple session descriptions are +%% provided in one descriptor, the "v=" lines are required as delimiters; +%% otherwise they are optional. Implementations shall accept session +%% descriptions that are fully conformant to RFC2327. When binary +%% encoding the protocol the descriptor consists of groups of properties +%% (tag-value pairs) as specified in Annex C. Each such group may +%% contain the parameters of a session description. +tr_opt_LocalRemoteDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = Groups}, + State) -> + #'LocalRemoteDescriptor'{propGrps = [tr_PropertyGroup(G, State) || G <- Groups]}. + +tr_PropertyGroup(Props, State) -> + [tr_PropertyGroupParm(P, State) || P <- Props]. + +tr_PropertyGroupParm(#'PropertyParm'{name = Name, + value = Value}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'PropertyParm'{name = resolve(property, Name, State, Constraint), + value = tr_OCTET_STRING(Value, State, 0, infinity)}. + +tr_PropertyParm(#'PropertyParm'{name = Name, + value = Value, + extraInfo = Extra}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'PropertyParm'{name = resolve(property, Name, State, Constraint), + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_opt_extraInfo(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_extraInfo({relation, Rel}, _State) -> + Rel2 = + case Rel of + greaterThan -> greaterThan; + smallerThan -> smallerThan; + unequalTo -> unequalTo + end, + {relation, Rel2}; +tr_opt_extraInfo({range, Range}, State) -> + Range2 = tr_bool(Range, State), + {range, Range2}; +tr_opt_extraInfo({sublist, Sub}, State) -> + Sub2 = tr_bool(Sub, State), + {sublist, Sub2}. + +tr_opt_TerminationStateDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TerminationStateDescriptor(#'TerminationStateDescriptor'{propertyParms = Props, + eventBufferControl = Control, + serviceState = Service}, + State) -> + #'TerminationStateDescriptor'{propertyParms = [tr_PropertyParm(P, State) || P <- Props], + eventBufferControl = tr_opt_EventBufferControl(Control, State), + serviceState = tr_opt_ServiceState(Service, State)}. + +tr_opt_EventBufferControl(Control, _State) -> + case Control of + asn1_NOVALUE -> asn1_NOVALUE; + off -> off; + lockStep -> lockStep + end. + +tr_opt_ServiceState(Service, _State) -> + case Service of + asn1_NOVALUE -> asn1_NOVALUE; + test -> test; + outOfSvc -> outOfSvc; + inSvc -> inSvc + end. + +tr_MuxDescriptor(#'MuxDescriptor'{muxType = Type, + termList = IdList}, + State) -> + #'MuxDescriptor'{muxType = tr_MuxType(Type, State), + termList = [tr_TerminationID(Id, State) || Id <- IdList]}. + +tr_MuxType(Type, _State) -> + case Type of + h221 -> h221; + h223 -> h223; + h226 -> h226; + v76 -> v76 + end. + +tr_opt_StreamID(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_StreamID(Id, State) -> + tr_StreamID(Id, State). + +tr_StreamID(Id, State) -> + tr_UINT16(Id, State). + +tr_EventsDescriptor(#'EventsDescriptor'{requestID = Id, + eventList = Events}, + State) -> + #'EventsDescriptor'{requestID = tr_opt_RequestID(Id, State), + eventList = [tr_RequestedEvent(E, State) || E <- Events]}. + +tr_RequestedEvent(#'RequestedEvent'{pkgdName = Name, + streamID = Id, + evParList = Parms, + eventAction = Actions}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'RequestedEvent'{pkgdName = resolve(event, Name, State, Constraint), + streamID = tr_opt_StreamID(Id, State), + eventAction = tr_opt_RequestedActions(Actions, State), + evParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + +tr_opt_RequestedActions(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_RequestedActions(#'RequestedActions'{keepActive = Keep, + eventDM = DM, + secondEvent = Event, + signalsDescriptor = SigDesc}, + State) -> + #'RequestedActions'{keepActive = tr_opt_keepActive(Keep, State), + eventDM = tr_opt_EventDM(DM, State), + secondEvent = tr_opt_SecondEventsDescriptor(Event, State), + signalsDescriptor = tr_opt_SignalsDescriptor(SigDesc, State)}. + +tr_opt_keepActive(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_keepActive(Keep, State) -> + tr_bool(Keep, State). + +tr_opt_EventDM(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_EventDM({Tag, Val}, State) -> + Val2 = + case Tag of + digitMapName -> tr_DigitMapName(Val, State); + digitMapValue -> tr_DigitMapValue(Val, State) + end, + {Tag, Val2}. + +tr_opt_SecondEventsDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = Id, + eventList = Events}, + State) -> + #'SecondEventsDescriptor'{requestID = tr_RequestID(Id, State), %% IG v6 6.8 withdrawn + eventList = [tr_SecondRequestedEvent(E, State) || E <- Events]}. + +tr_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = Name, + streamID = Id, + evParList = Parms, + eventAction = Actions}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'SecondRequestedEvent'{pkgdName = resolve(event, Name, State, Constraint), + streamID = tr_opt_StreamID(Id, State), + eventAction = tr_opt_SecondRequestedActions(Actions, State), + evParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + + +tr_opt_SecondRequestedActions(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SecondRequestedActions(#'SecondRequestedActions'{keepActive = Keep, + eventDM = DM, + signalsDescriptor = SigDesc}, + State) -> + #'SecondRequestedActions'{keepActive = tr_opt_keepActive(Keep, State), + eventDM = tr_opt_EventDM(DM, State), + signalsDescriptor = tr_opt_SignalsDescriptor(SigDesc, State)}. + +tr_EventBufferDescriptor(EventSpecs, State) -> + [tr_EventSpec(ES, State) || ES <- EventSpecs]. + +tr_EventSpec(#'EventSpec'{eventName = Name, + streamID = Id, + eventParList = Parms}, + State) -> + #'EventSpec'{eventName = tr_EventName(Name, State), + streamID = tr_opt_StreamID(Id, State), + eventParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + +tr_opt_SignalsDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SignalsDescriptor(SigDesc, State) -> + tr_SignalsDescriptor(SigDesc, State). + +tr_SignalsDescriptor(SigDesc, State) when is_list(SigDesc) -> + [tr_SignalRequest(SigReq, State) || SigReq <- SigDesc]. + +tr_SignalRequest({Tag, Val}, State) -> + Val2 = + case Tag of + signal -> tr_Signal(Val, State); + seqSigList -> tr_SeqSigList(Val, State) + end, + {Tag, Val2}. + + +tr_SeqSigList(#'SeqSigList'{id = Id, + signalList = SigList}, + State) when is_list(SigList) -> + #'SeqSigList'{id = tr_UINT16(Id, State), + signalList = [tr_Signal(Sig, State) || Sig <- SigList]}. + +tr_Signal(#'Signal'{signalName = Name, + streamID = SID, + sigType = Type, + duration = Dur, + notifyCompletion = Compl, + keepActive = Keep, + sigParList = Parms, + direction = Dir, + requestID = RID}, + State) -> + Name2 = tr_SignalName(Name, State), + SID2 = tr_opt_StreamID(SID, State), + Type2 = tr_opt_SignalType(Type, State), + Dur2 = tr_opt_duration(Dur, State), + Compl2 = tr_opt_NotifyCompletion(Compl, State), + Keep2 = tr_opt_keepActive(Keep, State), + Parms2 = [tr_SigParameter(P, Name, State) || P <- Parms], + Dir2 = tr_opt_SignalDirection(Dir, State), + RID2 = tr_opt_RequestID(RID, State), + #'Signal'{signalName = Name2, + streamID = SID2, + sigType = Type2, + duration = Dur2, + notifyCompletion = Compl2, + keepActive = Keep2, + sigParList = Parms2, + direction = Dir2, + requestID = RID2}. + +tr_opt_duration(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_duration(Dur, State) -> + tr_UINT16(Dur, State). + +tr_opt_NotifyCompletion(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_NotifyCompletion(Items, State) when is_list(Items) -> + [tr_notifyCompletionItem(I, State) || I <- Items]. + +tr_notifyCompletionItem(Item, _State) -> + case Item of + onTimeOut -> onTimeOut; + onInterruptByEvent -> onInterruptByEvent; + onInterruptByNewSignalDescr -> onInterruptByNewSignalDescr; + otherReason -> otherReason + end. + +tr_opt_SignalType(asn1_NOVALUE = Type, _State) -> + Type; +tr_opt_SignalType(Type, _State) -> + case Type of + brief -> brief; + onOff -> onOff; + timeOut -> timeOut + end. + +tr_opt_SignalDirection(asn1_NOVALUE = SD, _State) -> + SD; +tr_opt_SignalDirection(SD, _State) -> + case SD of + internal -> internal; + external -> external; + both -> both + end. + +tr_SignalName(Name, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + resolve(signal, Name, State, Constraint). + +tr_SigParameter(#'SigParameter'{sigParameterName = ParName, + value = Value, + extraInfo = Extra}, + SigName, + State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + N = resolve({signal_parameter, SigName}, ParName, State, Constraint), + #'SigParameter'{sigParameterName = N, + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_opt_RequestID(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_RequestID(Id, State) -> + tr_RequestID(Id, State). + +tr_RequestID(Id, _State) when Id =:= ?megaco_all_request_id -> + ?megaco_all_request_id; +tr_RequestID(Id, State) -> + tr_UINT32(Id, State). + +tr_ModemDescriptor(_MD, _State) -> + deprecated. + +tr_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value}, + State) -> + #'DigitMapDescriptor'{digitMapName = tr_opt_DigitMapName(Name, State), + digitMapValue = tr_opt_DigitMapValue(Value, State)}. + +tr_opt_DigitMapName(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_DigitMapName(Name, State) -> + tr_DigitMapName(Name, State). + +tr_DigitMapName(Name, State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + resolve(dialplan, Name, State, Constraint). + +tr_opt_DigitMapValue(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_DigitMapValue(Value, State) -> + tr_DigitMapValue(Value, State). + +tr_DigitMapValue(#'DigitMapValue'{digitMapBody = Body, + startTimer = Start, + shortTimer = Short, + longTimer = Long}, + State) -> + #'DigitMapValue'{startTimer = tr_opt_timer(Start, State), + shortTimer = tr_opt_timer(Short, State), + longTimer = tr_opt_timer(Long, State), + digitMapBody = tr_STRING(Body, State)}. %% BUGBUG: digitMapBody not handled at all + +tr_opt_timer(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_timer(Timer, State) -> + tr_DIGIT(Timer, State, 0, 99). + +tr_ServiceChangeParm( + #'ServiceChangeParm'{serviceChangeMethod = Method, + serviceChangeAddress = Addr, + serviceChangeVersion = Version, + serviceChangeProfile = Profile, + serviceChangeReason = Reason, + serviceChangeDelay = Delay, + serviceChangeMgcId = MgcId, + timeStamp = Time, + serviceChangeInfo = Info, + serviceChangeIncompleteFlag = Incomplete}, + State) -> + Method2 = tr_ServiceChangeMethod(Method, State), + Addr2 = tr_opt_ServiceChangeAddress(Addr, State), + Version2 = tr_opt_serviceChangeVersion(Version, State), + Profile2 = tr_opt_ServiceChangeProfile(Profile, State), + Reason2 = tr_serviceChangeReason(Reason, State), + Delay2 = tr_opt_serviceChangeDelay(Delay, State), + MgcId2 = tr_opt_serviceChangeMgcId(MgcId, State), + Time2 = tr_opt_TimeNotation(Time, State), + Info2 = tr_opt_AuditDescriptor(Info, State), + Incomplete2 = tr_opt_null(Incomplete, State), + #'ServiceChangeParm'{serviceChangeMethod = Method2, + serviceChangeAddress = Addr2, + serviceChangeVersion = Version2, + serviceChangeProfile = Profile2, + serviceChangeReason = Reason2, + serviceChangeDelay = Delay2, + serviceChangeMgcId = MgcId2, + timeStamp = Time2, + serviceChangeInfo = Info2, + serviceChangeIncompleteFlag = Incomplete2}. + +tr_ServiceChangeMethod(Method, _State) -> + case Method of + failover -> failover; + forced -> forced; + graceful -> graceful; + restart -> restart; + disconnected -> disconnected; + handOff -> handOff + end. %% BUGBUG: extension + +tr_opt_ServiceChangeAddress(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ServiceChangeAddress({Tag, Val}, State) -> + Val2 = + case Tag of + portNumber -> tr_portNumber(Val, State); + ip4Address -> tr_IP4Address(Val, State); + ip6Address -> tr_IP6Address(Val, State); + domainName -> tr_DomainName(Val, State); + deviceName -> tr_PathName(Val, State); + mtpAddress -> tr_mtpAddress(Val, State) + end, + {Tag, Val2}. + +tr_opt_serviceChangeVersion(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeVersion(Version, State) -> + tr_version(Version, State). + +tr_opt_ServiceChangeProfile(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +%% Decode +tr_opt_ServiceChangeProfile({'ServiceChangeProfile', ProfileName}, State) -> + case string:tokens(ProfileName, "/") of + [Name0, Version0] -> + Name = tr_STRING(Name0, State, 1, 64), + Version = tr_version(list_to_integer(Version0), State), + #'ServiceChangeProfile'{profileName = Name, + version = Version} + end; +%% Encode +tr_opt_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = Name0, + version = Version0}, + State) -> + Name = tr_STRING(Name0, State, 1, 64), + Version = tr_version(Version0, State), + ProfileName = lists:flatten(io_lib:format("~s/~w", [Name, Version])), + {'ServiceChangeProfile', ProfileName}. + +tr_serviceChangeReason([_] = Reason, State) -> + tr_Value(Reason, State). + +tr_opt_serviceChangeDelay(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeDelay(Delay, State) -> + tr_UINT32(Delay, State). + +tr_opt_serviceChangeMgcId(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeMgcId(MgcId, State) -> + tr_MId(MgcId, State). + +tr_opt_portNumber(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_portNumber(Port, State) -> + tr_portNumber(Port, State). + +tr_portNumber(Port, State) when is_integer(Port) andalso (Port >= 0) -> + tr_UINT16(Port, State). + +tr_ServiceChangeResParm(#'ServiceChangeResParm'{serviceChangeMgcId = MgcId, + serviceChangeAddress = Addr, + serviceChangeVersion = Version, + serviceChangeProfile = Profile, + timeStamp = Time}, + State) -> + #'ServiceChangeResParm'{serviceChangeMgcId = tr_opt_serviceChangeMgcId(MgcId, State), + serviceChangeAddress = tr_opt_ServiceChangeAddress(Addr, State), + serviceChangeVersion = tr_opt_serviceChangeVersion(Version, State), + serviceChangeProfile = tr_opt_ServiceChangeProfile(Profile, State), + timeStamp = tr_opt_TimeNotation(Time, State)}. + +tr_PackagesDescriptor(Items, State) when is_list(Items) -> + [tr_PackagesItem(I, State) || I <- Items]. + +tr_PackagesItem(#'PackagesItem'{packageName = Name, + packageVersion = Version}, + State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + #'PackagesItem'{packageName = resolve(package, Name, State, Constraint), + packageVersion = tr_UINT16(Version, State)}. + +tr_opt_StatisticsDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_StatisticsDescriptor(Parms, State) -> + tr_StatisticsDescriptor(Parms, State). + +tr_StatisticsDescriptor(Parms, State) when is_list(Parms) -> + [tr_StatisticsParameter(P, State) || P <- Parms]. + +tr_StatisticsParameter(#'StatisticsParameter'{statName = Name, + statValue = Value}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'StatisticsParameter'{statName = resolve(statistics, Name, State, Constraint), + statValue = tr_opt_Value(Value, State)}. + +tr_opt_TimeNotation(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TimeNotation(#'TimeNotation'{date = Date, + time = Time}, + State) -> + #'TimeNotation'{date = tr_STRING(Date, State, 8, 8), % "yyyymmdd" + time = tr_STRING(Time, State, 8, 8)}.% "hhmmssss" + +%% BUGBUG: Does not verify that string must contain at least one char +%% BUGBUG: This violation of the is required in order to comply with +%% BUGBUG: the dd/ce ds parameter that may possibly be empty. + +tr_opt_Value(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_Value(Value, State) -> + tr_Value(Value, State). + +tr_Value(Strings, _State) when is_list(Strings) -> + [[Char || Char <- String] || String <- Strings]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Encode an octet string, escape } by \ if necessary +tr_OCTET_STRING(String, _State, Min, Max) when is_list(String) -> + verify_count(length(String), Min, Max), + String. + +tr_QUOTED_STRING(String, _State) when is_list(String) -> + verify_count(length(String), 1, infinity), + String. + +%% The internal format of hex digits is a list of octets +%% Min and Max means #hexDigits +%% Leading zeros are prepended in order to fulfill Min +tr_HEXDIG(Octets, _State, Min, Max) when is_list(Octets) -> + verify_count(length(Octets), Min, Max), + Octets. + +tr_DIGIT(Val, State, Min, Max) -> + tr_integer(Val, State, Min, Max). + +tr_STRING(String, _State) when is_list(String) -> + String. + +tr_STRING(String, _State, Min, Max) when is_list(String) -> + verify_count(length(String), Min, Max), + String. + +tr_opt_UINT16(Val, State) -> + tr_opt_integer(Val, State, 0, 65535). + +tr_UINT16(Val, State) -> + tr_integer(Val, State, 0, 65535). + +tr_UINT32(Val, State) -> + tr_integer(Val, State, 0, 4294967295). + +tr_opt_integer(asn1_NOVALUE, _State, _Min, _Max) -> + asn1_NOVALUE; +tr_opt_integer(Int, State, Min, Max) -> + tr_integer(Int, State, Min, Max). + +tr_integer(Int, _State, Min, Max) -> + verify_count(Int, Min, Max), + Int. + +%% Verify that Count is within the range of Min and Max +verify_count(Count, Min, Max) -> + if + is_integer(Count) -> + if + is_integer(Min) andalso (Count >= Min) -> + if + is_integer(Max) andalso (Count =< Max) -> + Count; + Max =:= infinity -> + Count; + true -> + error({count_too_large, Count, Max}) + end; + true -> + error({count_too_small, Count, Min}) + end; + true -> + error({count_not_an_integer, Count}) + end. + + +%% ------------------------------------------------------------------- + +error(Reason) -> + erlang:error(Reason). + + diff --git a/lib/megaco/src/binary/megaco_binary_transformer_prev3b.erl b/lib/megaco/src/binary/megaco_binary_transformer_prev3b.erl new file mode 100644 index 0000000000..baca84bbfe --- /dev/null +++ b/lib/megaco/src/binary/megaco_binary_transformer_prev3b.erl @@ -0,0 +1,1629 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Transform internal form of Megaco/H.248 messages +%%---------------------------------------------------------------------- + +-module(megaco_binary_transformer_prev3b). + +-include_lib("megaco/include/megaco.hrl"). +%% -include_lib("megaco/include/megaco_message.hrl"). +-include_lib("megaco/include/megaco_message_prev3b.hrl"). +-include_lib("megaco/src/app/megaco_internal.hrl"). + +-export([tr_message/3, tr_transaction/3]). + +-define(DEFAULT_NAME_RESOLVER, megaco_binary_name_resolver_prev3b). + +-record(state, {mode, % verify | encode | decode + resolver_module, % + resolver_options}). + +resolve(Type, Item, State, Constraint) -> + case State#state.mode of + verify -> + Item; + encode -> + ?d("resolve(encode) -> encode: ~p",[Item]), + Mod = State#state.resolver_module, + Opt = State#state.resolver_options, + EncodedItem = Mod:encode_name(Opt, Type, Item), + ?d("resolve -> verify contraint for ~p",[EncodedItem]), + verify_constraint(EncodedItem, Constraint); + decode -> + ?d("resolve(decode) -> verify contraint for ~p",[Item]), + DecodedItem = verify_constraint(Item, Constraint), + Mod = State#state.resolver_module, + Opt = State#state.resolver_options, + ?d("resolve(decode) -> decode: ~p",[DecodedItem]), + Mod:decode_name(Opt, Type, DecodedItem) + end. + +verify_constraint(Item, valid) -> + Item; +verify_constraint(Item, Constraint) when is_function(Constraint) -> + Constraint(Item). + +tr_message(MegaMsg, Mode, Config) -> + case Config of + [native] -> + MegaMsg; + [verify] -> + State = #state{mode = verify}, + tr_MegacoMessage(MegaMsg, State); + [] -> + State = #state{mode = Mode, + resolver_module = ?DEFAULT_NAME_RESOLVER, + resolver_options = [8, 8, 8]}, + tr_MegacoMessage(MegaMsg, State); + [{binary_name_resolver, {Module, Options}}] when is_atom(Module) -> + State = #state{mode = Mode, + resolver_module = Module, + resolver_options = Options}, + tr_MegacoMessage(MegaMsg, State) + end. + +tr_transaction(Trans, Mode, Config) -> + case Config of + [native] -> + Trans; + [verify] -> + State = #state{mode = verify}, + tr_Transaction(Trans, State); + [] -> + State = #state{mode = Mode, + resolver_module = ?DEFAULT_NAME_RESOLVER, + resolver_options = [8, 8, 8]}, + tr_Transaction(Trans, State); + [{binary_name_resolver, {Module, Options}}] when is_atom(Module) -> + State = #state{mode = Mode, + resolver_module = Module, + resolver_options = Options}, + tr_Transaction(Trans, State) + end. + +tr_MegacoMessage(#'MegacoMessage'{authHeader = Auth, + mess = Mess}, + State) -> + ?d("tr_MegacoMessage -> entry with" + "~n Auth: ~p" + "~n Mess: ~p" + "~n State: ~p", [Auth, Mess, State]), + #'MegacoMessage'{authHeader = tr_opt_AuthenticationHeader(Auth, State), + mess = tr_Message(Mess, State)}. + +tr_opt_AuthenticationHeader(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_AuthenticationHeader(#'AuthenticationHeader'{secParmIndex = SPI, + seqNum = SN, + ad = AuthData}, + State) -> + #'AuthenticationHeader'{secParmIndex = tr_SecurityParmIndex(SPI, State), + seqNum = tr_SequenceNum(SN, State), + ad = tr_AuthData(AuthData, State)}. + +tr_SecurityParmIndex(SPI, State) -> + tr_HEXDIG(SPI, State, 4, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_SequenceNum(SN, State) -> + tr_HEXDIG(SN, State, 4, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_AuthData(AuthData, State) -> + tr_HEXDIG(AuthData, State, 12, 32). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_Message(#'Message'{version = Version, + mId = MID, + messageBody = Body}, + State) -> + #'Message'{version = tr_version(Version, State), + mId = tr_MId(MID, State), + messageBody = tr_Message_messageBody(Body, State)}. + +tr_version(Version, State) -> + tr_DIGIT(Version, State, 0, 99). + +tr_Message_messageBody({Tag, Val}, State) -> + Val2 = + case Tag of + messageError -> tr_ErrorDescriptor(Val, State); + transactions when is_list(Val) -> [tr_Transaction(T, State) || T <- Val] + end, + {Tag, Val2}. + +tr_MId({Tag, Val}, State) -> + Val2 = + case Tag of + ip4Address -> tr_IP4Address(Val, State); + ip6Address -> tr_IP6Address(Val, State); + domainName -> tr_DomainName(Val, State); + deviceName -> tr_PathName(Val, State); + mtpAddress -> tr_mtpAddress(Val, State) + end, + {Tag, Val2}. + +tr_mtpAddress(MtpAddr, State) -> + tr_OCTET_STRING(MtpAddr, State, 2, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_DomainName(#'DomainName'{name = Name, + portNumber = Port}, + State) -> + Domain = #'DomainName'{name = tr_STRING(Name, State), % BUGBUG: Mismatch between ASN.1 and ABNF + portNumber = tr_opt_portNumber(Port, State)}, + {domainName, Domain2} = resolve(mid, {domainName, Domain}, State, valid), + Domain2. + +tr_IP4Address(#'IP4Address'{address = [A1, A2, A3, A4], + portNumber = Port}, + State) -> + #'IP4Address'{address = [tr_V4hex(A1, State), + tr_V4hex(A2, State), + tr_V4hex(A3, State), + tr_V4hex(A4, State)], + portNumber = tr_opt_portNumber(Port, State)}. + +tr_V4hex(Val, State) -> + tr_DIGIT(Val, State, 0, 255). + +tr_IP6Address(_Val, _State) -> + error(ipv6_not_supported). %% BUGBUG: nyi + +tr_PathName(Path, State) -> + %% BUGBUG: ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" ) + %% BUGBUG: ["@" pathDomainName ] + Constraint = fun({deviceName, Item}) -> tr_STRING(Item, State, 1, 64) end, + resolve(mid, {deviceName, Path}, State, Constraint). + +tr_Transaction({Tag, Val}, State) -> + Val2 = + case Tag of + transactionRequest -> tr_TransactionRequest(Val, State); + transactionPending -> tr_TransactionPending(Val, State); + transactionReply -> tr_TransactionReply(Val, State); + transactionResponseAck -> [tr_TransactionAck(T, State) || T <- Val] + end, + {Tag, Val2}. + +tr_TransactionAck(#'TransactionAck'{firstAck = First, + lastAck = Last}, + State) -> + #'TransactionAck'{firstAck = tr_TransactionId(First, State), + lastAck = tr_opt_TransactionId(Last, State)}. + +tr_opt_TransactionId(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TransactionId(Id, State) -> + tr_TransactionId(Id, State). + +tr_TransactionId(Id, State) -> + tr_UINT32(Id, State). + +tr_TransactionRequest(#'TransactionRequest'{transactionId = Id, + actions = Actions}, + State) when is_list(Actions) -> + + #'TransactionRequest'{transactionId = tr_TransactionId(Id, State), + actions = [tr_ActionRequest(ActReq, State) || ActReq <- Actions]}. + +tr_TransactionPending(#'TransactionPending'{transactionId = Id}, + State) -> + #'TransactionPending'{transactionId = tr_TransactionId(Id, State)}. + +tr_TransactionReply(#'TransactionReply'{transactionId = Id, + immAckRequired = ImmAck, + transactionResult = TransRes, + %% These fields are actually not + %% supported in this implementation, + %% but because the messanger module + %% cannot see any diff between the + %% various v3 implementations... + segmentNumber = asn1_NOVALUE, + segmentationComplete = asn1_NOVALUE}, + State) -> + #'TransactionReply'{transactionId = tr_TransactionId(Id, State), + immAckRequired = tr_opt_null(ImmAck, State), + transactionResult = tr_TransactionReply_transactionResult(TransRes, State), + segmentNumber = asn1_NOVALUE, + segmentationComplete = asn1_NOVALUE}; +tr_TransactionReply(TR, _State) -> + error({unsupported_TransactionReply, TR}). + +tr_opt_null(asn1_NOVALUE, _State) -> asn1_NOVALUE; +tr_opt_null('NULL', _State) -> 'NULL'. + +tr_TransactionReply_transactionResult({Tag, Val}, State) -> + Val2 = + case Tag of + transactionError -> + tr_ErrorDescriptor(Val, State); + actionReplies when is_list(Val) andalso (Val =/= []) -> + [tr_ActionReply(ActRep, State) || ActRep <- Val] + end, + {Tag, Val2}. + +tr_opt_ErrorDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ErrorDescriptor(ErrDesc, State) -> + tr_ErrorDescriptor(ErrDesc, State). + +tr_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code, + errorText = Text}, + State) -> + #'ErrorDescriptor'{errorCode = tr_ErrorCode(Code, State), + errorText = tr_opt_ErrorText(Text, State)}. + +tr_ErrorCode(Code, State) -> + tr_DIGIT(Code, State, 0, 999). + +tr_opt_ErrorText(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ErrorText(Text, State) -> + tr_QUOTED_STRING(Text, State). + +tr_ContextID(CtxId, State) -> + case CtxId of + ?megaco_all_context_id -> ?megaco_all_context_id; + ?megaco_null_context_id -> ?megaco_null_context_id; + ?megaco_choose_context_id -> ?megaco_choose_context_id; + Int when is_integer(Int) -> tr_UINT32(Int, State) + end. + +tr_ActionRequest(#'ActionRequest'{contextId = CtxId, + contextRequest = CtxReq, + contextAttrAuditReq = CtxAuditReq, + commandRequests = CmdReqList}, + State) -> + #'ActionRequest'{contextId = tr_ContextID(CtxId, State), + contextRequest = tr_opt_ContextRequest(CtxReq, State), + contextAttrAuditReq = tr_opt_ContextAttrAuditRequest(CtxAuditReq, State), + commandRequests = [tr_CommandRequest(CmdReq, State) || CmdReq <- CmdReqList]}. + +tr_ActionReply(#'ActionReply'{contextId = CtxId, + errorDescriptor = ErrDesc, + contextReply = CtxRep, + commandReply = CmdRepList}, + State) -> + CmdRepList2 = [tr_CommandReply(CmdRep, State) || CmdRep <- CmdRepList], + #'ActionReply'{contextId = tr_ContextID(CtxId, State), + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State), + contextReply = tr_opt_ContextRequest(CtxRep, State), + commandReply = CmdRepList2}. + +tr_opt_ContextRequest(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ContextRequest(CR, State) -> + tr_ContextRequest(CR, State). + +tr_ContextRequest(#'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = TopReqList, + iepscallind = Ind, + contextProp = Props}, + State) -> + Prio2 = + case Prio of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_integer(Prio, State, 0, 15) + end, + Em2 = + case Em of + asn1_NOVALUE -> asn1_NOVALUE; + false -> false; + true -> true + end, + TopReqList2 = + case TopReqList of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_TopologyRequest(TopReq, State) || + TopReq <- TopReqList] + end, + Ind2 = + case Ind of + asn1_NOVALUE -> asn1_NOVALUE; + false -> false; + true -> true + end, + Props2 = + case Props of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_PropertyParm(Prop, State) || Prop <- Props] + end, + #'ContextRequest'{priority = Prio2, + emergency = Em2, + topologyReq = TopReqList2, + iepscallind = Ind2, + contextProp = Props2}. + +tr_opt_ContextAttrAuditRequest(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ContextAttrAuditRequest(CAAR, State) -> + tr_ContextAttrAuditRequest(CAAR, State). + +tr_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ind, + contextPropAud = Props}, + State) -> + Top2 = tr_opt_null(Top, State), + Em2 = tr_opt_null(Em, State), + Prio2 = tr_opt_null(Prio, State), + Ind2 = tr_opt_null(Ind, State), + Props2 = + case Props of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + [tr_indAudPropertyParm(Prop, State) || Prop <- Props] + end, + #'ContextAttrAuditRequest'{topology = Top2, + emergency = Em2, + priority = Prio2, + iepscallind = Ind2, + contextPropAud = Props2}. + +tr_CommandRequest(#'CommandRequest'{command = Cmd, + optional = Opt, + wildcardReturn = Wild}, + State) -> + #'CommandRequest'{optional = tr_opt_null(Opt, State), + wildcardReturn = tr_opt_null(Wild, State), + command = tr_Command(Cmd, State)}. + +tr_Command({Tag, Val}, State) -> + Val2 = + case Tag of + addReq -> tr_AmmRequest(Val, State); + moveReq -> tr_AmmRequest(Val, State); + modReq -> tr_AmmRequest(Val, State); + subtractReq -> tr_SubtractRequest(Val, State); + auditCapRequest -> tr_AuditRequest(Val, State); + auditValueRequest -> tr_AuditRequest(Val, State); + notifyReq -> tr_NotifyRequest(Val, State); + serviceChangeReq -> tr_ServiceChangeRequest(Val, State) + end, + {Tag, Val2}. + +tr_CommandReply({Tag, Val}, State) -> + Val2 = + case Tag of + addReply -> tr_AmmsReply(Val, State); + moveReply -> tr_AmmsReply(Val, State); + modReply -> tr_AmmsReply(Val, State); + subtractReply -> tr_AmmsReply(Val, State); + auditCapReply -> tr_AuditReply(Val, State); + auditValueReply -> tr_AuditReply(Val, State); + notifyReply -> tr_NotifyReply(Val, State); + serviceChangeReply -> tr_ServiceChangeReply(Val, State) + end, + {Tag, Val2}. + +tr_TopologyRequest(#'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = Dir}, + State) -> + Dir2 = + case Dir of + bothway -> bothway; + isolate -> isolate; + oneway -> oneway + end, + #'TopologyRequest'{terminationFrom = tr_TerminationID(From, State), + terminationTo = tr_TerminationID(To, State), + topologyDirection = Dir2}. + +tr_AmmRequest(#'AmmRequest'{terminationID = IdList, + descriptors = DescList}, + State) -> + #'AmmRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + descriptors = tr_ammDescriptors(DescList, [], State)}. + +tr_ammDescriptors([], Acc, _State) -> + lists:reverse(Acc); +tr_ammDescriptors([Desc|Descs], Acc, State) -> + case tr_ammDescriptor(Desc, State) of + {_, deprecated} when State#state.mode =:= encode -> + error({deprecated, Desc}); + {_, deprecated} when State#state.mode =:= decode -> + %% SKIP + tr_ammDescriptors(Descs, Acc, State); + {_, deprecated} -> + %% SKIP + tr_ammDescriptors(Descs, Acc, State); + NewDesc -> + tr_ammDescriptors(Descs, [NewDesc|Acc], State) + end. + +tr_ammDescriptor({Tag, Desc}, State) -> + Desc2 = + case Tag of + mediaDescriptor -> tr_MediaDescriptor(Desc, State); + modemDescriptor -> tr_ModemDescriptor(Desc, State); + muxDescriptor -> tr_MuxDescriptor(Desc, State); + eventsDescriptor -> tr_EventsDescriptor(Desc, State); + eventBufferDescriptor -> tr_EventBufferDescriptor(Desc, State); + signalsDescriptor -> tr_SignalsDescriptor(Desc, State); + digitMapDescriptor -> tr_DigitMapDescriptor(Desc, State); + auditDescriptor -> tr_AuditDescriptor(Desc, State); + statisticsDescriptor -> tr_StatisticsDescriptor(Desc, State) + end, + {Tag, Desc2}. + +tr_AmmsReply(#'AmmsReply'{terminationID = IdList, + terminationAudit = TermAudit}, + State) -> + TermAudit2 = + case TermAudit of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_TerminationAudit(TermAudit, State) + end, + #'AmmsReply'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + terminationAudit = TermAudit2}. + +tr_SubtractRequest(#'SubtractRequest'{terminationID = IdList, + auditDescriptor = Desc}, + State) -> + #'SubtractRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + auditDescriptor = tr_opt_AuditDescriptor(Desc, State)}. + +tr_AuditRequest(#'AuditRequest'{terminationID = Id, + auditDescriptor = Desc}, + State) -> + #'AuditRequest'{terminationID = tr_TerminationID(Id, State), + auditDescriptor = tr_AuditDescriptor(Desc, State)}. + +%% auditReply = (AuditValueToken / AuditCapToken ) +%% ( contextTerminationAudit / auditOther) +%% auditOther = EQUAL TerminationID LBRKT +%% terminationAudit RBRKT +%% terminationAudit = auditReturnParameter *(COMMA auditReturnParameter) +%% +%% contextTerminationAudit = EQUAL CtxToken ( terminationIDList / +%% LBRKT errorDescriptor RBRKT ) + +tr_AuditReply({Tag, Val}, State) -> + Val2 = + case Tag of + contextAuditResult -> + [tr_TerminationID(Id, State) || Id <- Val]; + error -> + tr_ErrorDescriptor(Val, State); + auditResult -> + tr_AuditResult(Val, State) + end, + {Tag, Val2}. + +tr_AuditResult(#'AuditResult'{terminationID = Id, + terminationAuditResult = AuditRes}, + State) -> + #'AuditResult'{terminationID = tr_TerminationID(Id, State), + terminationAuditResult = tr_TerminationAudit(AuditRes, State)}. + +tr_opt_AuditDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_AuditDescriptor(Desc, State) -> + tr_AuditDescriptor(Desc, State). + +%% BUGBUG BUGBUG BUGBUG +%% With this construction it is possible to have both auditToken +%% and auditPropertyToken, but it is actually valid? +tr_AuditDescriptor(#'AuditDescriptor'{auditToken = Tokens, + auditPropertyToken = APTs}, + State) -> + Tokens2 = + case Tokens of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_auditItem(Token, State) || Token <- Tokens] + end, + %% v2 + APTs2 = + case APTs of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + [tr_indAuditParameter(APT, State) || APT <- APTs] + end, + #'AuditDescriptor'{auditToken = Tokens2, + auditPropertyToken = APTs2}. + +tr_auditItem(Token, _State) -> + case Token of + muxToken -> muxToken; + modemToken -> modemToken; + mediaToken -> mediaToken; + eventsToken -> eventsToken; + signalsToken -> signalsToken; + digitMapToken -> digitMapToken; + statsToken -> statsToken; + observedEventsToken -> observedEventsToken; + packagesToken -> packagesToken; + eventBufferToken -> eventBufferToken + end. + +%% --- v2 begin --- + +tr_indAuditParameter({Tag, Val}, State) -> + Val2 = + case Tag of + indAudMediaDescriptor -> + tr_indAudMediaDescriptor(Val, State); + indAudEventsDescriptor -> + tr_indAudEventsDescriptor(Val, State); + indAudSignalsDescriptor -> + tr_indAudSignalsDescriptor(Val, State); + indAudDigitMapDescriptor -> + tr_indAudDigitMapDescriptor(Val, State); + indAudEventBufferDescriptor -> + tr_indAudEventBufferDescriptor(Val, State); + indAudStatisticsDescriptor -> + tr_indAudStatisticsDescriptor(Val, State); + indAudPackagesDescriptor -> + tr_indAudPackagesDescriptor(Val, State) + end, + {Tag, Val2}. + + +%% - + +tr_indAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = S}, + State) -> + TSD2 = + case TSD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudTerminationStateDescriptor(TSD, State) + end, + S2 = + case S of + asn1_NOVALUE -> + asn1_NOVALUE; + {oneStream, OS} -> + {oneStream, tr_indAudStreamParms(OS, State)}; + {multiStream, MS} -> + MS2 = [tr_indAudStreamDescriptor(MS1, State) || MS1 <- MS], + {multiStream, MS2} + end, + #'IndAudMediaDescriptor'{termStateDescr = TSD2, + streams = S2}. + +tr_indAudTerminationStateDescriptor(Val, State) + when is_record(Val, 'IndAudTerminationStateDescriptor') -> + #'IndAudTerminationStateDescriptor'{propertyParms = Parms, + eventBufferControl = EBC, + serviceState = SS} = Val, + Parms2 = [tr_indAudPropertyParm(Parm, State) || Parm <- Parms], + EBC2 = tr_opt_null(EBC, State), + SS2 = tr_opt_null(SS, State), + #'IndAudTerminationStateDescriptor'{propertyParms = Parms2, + eventBufferControl = EBC2, + serviceState = SS2}. + + +tr_indAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD, + statisticsDescriptor = SD}, + State) -> + LCD2 = + case LCD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudLocalControlDescriptor(LCD, State) + end, + LD2 = + case LD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudLocalRemoteDescriptor(LD, State) + end, + RD2 = + case RD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudLocalRemoteDescriptor(RD, State) + end, + SD2 = + case SD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudStatisticsDescriptor(SD, State) + end, + #'IndAudStreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2, + statisticsDescriptor = SD2}. + +tr_indAudLocalControlDescriptor(Val, State) + when is_record(Val, 'IndAudLocalControlDescriptor') -> + #'IndAudLocalControlDescriptor'{streamMode = M, + reserveValue = V, + reserveGroup = G, + propertyParms = P} = Val, + M2 = tr_opt_null(M, State), + V2 = tr_opt_null(V, State), + G2 = tr_opt_null(G, State), + P2 = tr_indAudLocalControlDescriptor_propertyParms(P, State), + #'IndAudLocalControlDescriptor'{streamMode = M2, + reserveValue = V2, + reserveGroup = G2, + propertyParms = P2}. + +tr_indAudLocalControlDescriptor_propertyParms(Parms, State) + when is_list(Parms) andalso (length(Parms) > 0) -> + [tr_indAudPropertyParm(Parm, State) || Parm <- Parms]; +tr_indAudLocalControlDescriptor_propertyParms(asn1_NOVALUE, _State) -> + asn1_NOVALUE. + +tr_indAudLocalRemoteDescriptor(#'IndAudLocalRemoteDescriptor'{propGroupID = ID, + propGrps = Grps}, + State) -> + #'IndAudLocalRemoteDescriptor'{propGroupID = tr_opt_UINT16(ID, State), + propGrps = tr_indAudPropertyGroup(Grps, + State)}. + +tr_indAudPropertyGroup(Grps, State) when is_list(Grps) -> + [tr_indAudPropertyParm(Parm, State) || Parm <- Grps]. + +tr_indAudPropertyParm(#'IndAudPropertyParm'{name = Name0}, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(property, Name0, State, Constraint), + #'IndAudPropertyParm'{name = Name}. + + +tr_indAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = ID, + streamParms = Parms}, + State) -> + #'IndAudStreamDescriptor'{streamID = tr_StreamID(ID, State), + streamParms = tr_indAudStreamParms(Parms, + State)}. + + +%% - + +tr_indAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID, + pkgdName = Name0, + streamID = SID}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(event, Name0, State, Constraint), + #'IndAudEventsDescriptor'{requestID = tr_opt_RequestID(RID, State), + pkgdName = Name, + streamID = tr_opt_StreamID(SID, State)}. + + +%% - + +tr_indAudSignalsDescriptor({Tag, Val}, State) -> + case Tag of + signal -> + {signal, tr_indAudSignal(Val, State)}; + seqSigList -> + {seqSigList, tr_indAudSeqSigList(Val, State)} + end. + +tr_opt_indAudSignal(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_indAudSignal(Val, State) -> + tr_indAudSignal(Val, State). + +tr_indAudSignal(#'IndAudSignal'{signalName = Name0, + streamID = SID}, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(signal, Name0, State, Constraint), + #'IndAudSignal'{signalName = Name, + streamID = tr_opt_StreamID(SID, State)}. + +tr_indAudSeqSigList(#'IndAudSeqSigList'{id = ID, + signalList = SigList}, State) -> + #'IndAudSeqSigList'{id = tr_integer(ID, State, 0, 65535), + signalList = tr_opt_indAudSignal(SigList, State)}. + +%% - + +tr_indAudDigitMapDescriptor(#'IndAudDigitMapDescriptor'{digitMapName = Name}, + State) -> + #'IndAudDigitMapDescriptor'{digitMapName = + tr_opt_DigitMapName(Name, State)}. + + +%% - + +tr_indAudEventBufferDescriptor(#'IndAudEventBufferDescriptor'{eventName = N, + streamID = SID}, + State) -> + ?d("tr_indAudEventBufferDescriptor -> entry with" + "~n N: ~p" + "~n SID: ~p", [N, SID]), + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(event, N, State, Constraint), + ?d("tr_indAudEventBufferDescriptor -> entry with" + "~n Name: ~p", [Name]), + #'IndAudEventBufferDescriptor'{eventName = Name, + streamID = tr_opt_StreamID(SID, State)}. + +%% - + +tr_indAudStatisticsDescriptor(#'IndAudStatisticsDescriptor'{statName = N}, + State) -> + ?d("tr_indAudEventBufferDescriptor -> entry with" + "~n N: ~p", [N]), + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(statistics, N, State, Constraint), + #'IndAudStatisticsDescriptor'{statName = Name}. + + +%% - + +tr_indAudPackagesDescriptor(#'IndAudPackagesDescriptor'{packageName = N, + packageVersion = V}, + State) -> + ?d("tr_indAudPackagesDescriptor -> entry with" + "~n N: ~p" + "~n V: ~p", [N, V]), + Constraint = fun(Item) -> tr_Name(Item, State) end, + Name = resolve(package, N, State, Constraint), + ?d("tr_indAudPackagesDescriptor -> entry with" + "~n Name: ~p", [Name]), + #'IndAudPackagesDescriptor'{packageName = Name, + packageVersion = tr_integer(V, State, 0, 99)}. + +%% -- v2 end -- + + +tr_TerminationAudit(ParmList, State) when is_list(ParmList) -> + do_tr_TerminationAudit(ParmList, [], State). + +do_tr_TerminationAudit([], Acc, _State) -> + lists:reverse(Acc); +do_tr_TerminationAudit([Parm|ParmList], Acc, State) -> + case tr_AuditReturnParameter(Parm, State) of + {_, deprecated} when State#state.mode =:= encode -> + error({deprecated, Parm}); + {_, deprecated} when State#state.mode =:= decode -> + %% SKIP + do_tr_TerminationAudit(ParmList, Acc, State); + {_, deprecated} -> + %% SKIP + do_tr_TerminationAudit(ParmList, Acc, State); + NewParm -> + do_tr_TerminationAudit(ParmList, [NewParm|Acc], State) + end. + +tr_AuditReturnParameter({Tag, Val}, State) -> + Val2 = + case Tag of + errorDescriptor -> + tr_ErrorDescriptor(Val, State); + mediaDescriptor -> + tr_MediaDescriptor(Val, State); + modemDescriptor -> + tr_ModemDescriptor(Val, State); + muxDescriptor -> + tr_MuxDescriptor(Val, State); + eventsDescriptor -> + tr_EventsDescriptor(Val, State); + eventBufferDescriptor -> + tr_EventBufferDescriptor(Val, State); + signalsDescriptor -> + tr_SignalsDescriptor(Val, State); + digitMapDescriptor -> + tr_DigitMapDescriptor(Val, State); + observedEventsDescriptor -> + tr_ObservedEventsDescriptor(Val, State); + statisticsDescriptor -> + tr_StatisticsDescriptor(Val, State); + packagesDescriptor -> + tr_PackagesDescriptor(Val, State); + emptyDescriptors -> + tr_EmptyDescriptors(Val, State) + end, + {Tag, Val2}. + +tr_EmptyDescriptors(#'AuditDescriptor'{auditToken = Tokens}, + State) -> + case Tokens of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_auditItem(Token, State) || Token <- Tokens] + end. + +tr_NotifyRequest(#'NotifyRequest'{terminationID = IdList, + observedEventsDescriptor = ObsDesc, + errorDescriptor = ErrDesc}, + State) -> + %% BUGBUG: Mismatch between ASN.1 and ABNF + %% BUGBUG: The following ought to be a 'choice' + #'NotifyRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + observedEventsDescriptor = tr_ObservedEventsDescriptor(ObsDesc, State), + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State)}. + +tr_NotifyReply(#'NotifyReply'{terminationID = IdList, + errorDescriptor = ErrDesc}, + State) -> + #'NotifyReply'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State)}. + +tr_ObservedEventsDescriptor(#'ObservedEventsDescriptor'{requestId = Id, + observedEventLst = Events}, + State) when is_list(Events) -> + #'ObservedEventsDescriptor'{requestId = tr_RequestID(Id, State), + observedEventLst = [tr_ObservedEvent(E, State) || E <- Events]}. + +%% ;time per event, because it might be buffered +%% observedEvent = [ TimeStamp LWSP COLON] LWSP +%% pkgdName [ LBRKT observedEventParameter +%% *(COMMA observedEventParameter) RBRKT ] +%% +%% ;at-most-once eventStream, every eventParameterName at most once +%% observedEventParameter = eventStream / eventOther + +tr_ObservedEvent(#'ObservedEvent'{eventName = Name, + streamID = Id, + eventParList = Parms, + timeNotation = Time}, + State) -> + #'ObservedEvent'{eventName = tr_EventName(Name, State), + streamID = tr_opt_StreamID(Id, State), + eventParList = [tr_EventParameter(P, Name, State) || P <- Parms], + timeNotation = tr_opt_TimeNotation(Time, State)}. + +tr_EventName(Name, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + resolve(event, Name, State, Constraint). + +tr_EventParameter(#'EventParameter'{eventParameterName = ParName, + value = Value, + extraInfo = Extra}, + EventName, + State) -> + %% BUGBUG: event parameter name + Constraint = fun(Item) -> tr_Name(Item, State) end, + N = resolve({event_parameter, EventName}, ParName, State, Constraint), + #'EventParameter'{eventParameterName = N, + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_ServiceChangeRequest(#'ServiceChangeRequest'{terminationID = IdList, + serviceChangeParms = Parms}, + State) -> + #'ServiceChangeRequest'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + serviceChangeParms = tr_ServiceChangeParm(Parms, State)}. + +%% serviceChangeReply = ServiceChangeToken EQUAL TerminationID +%% [LBRKT (errorDescriptor / +%% serviceChangeReplyDescriptor) RBRKT] +%% serviceChangeReplyDescriptor = ServicesToken LBRKT +%% servChgReplyParm *(COMMA servChgReplyParm) RBRKT +%% +%% ;at-most-once. Version is REQUIRED on first ServiceChange response +%% servChgReplyParm = (serviceChangeAddress / serviceChangeMgcId / +%% serviceChangeProfile / serviceChangeVersion ) +tr_ServiceChangeReply(#'ServiceChangeReply'{terminationID = IdList, + serviceChangeResult = Res}, + State) -> + #'ServiceChangeReply'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + serviceChangeResult = tr_ServiceChangeResult(Res, State)}. + +tr_ServiceChangeResult({Tag, Val}, State) -> + Val2 = + case Tag of + errorDescriptor -> tr_ErrorDescriptor(Val, State); + serviceChangeResParms -> tr_ServiceChangeResParm(Val, State) + end, + {Tag, Val2}. + +%% TerminationID = "ROOT" / pathNAME / "$" / "*" +%% ; Total length of pathNAME must not exceed 64 chars. +%% pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" ) +%% ["@" pathDomainName ] + +tr_TerminationID(TermId, State) when State#state.mode =/= verify -> + resolve(term_id, TermId, State, valid); +tr_TerminationID(#'TerminationID'{wildcard = Wild, + id = Id}, + _State) -> + #'TerminationID'{wildcard = Wild, + id = Id}; +tr_TerminationID(#megaco_term_id{contains_wildcards = IsWild, + id = Id}, + State) -> + #megaco_term_id{contains_wildcards = tr_bool(IsWild, State), + id = [tr_term_id_component(Sub, State) || Sub <- Id]}. + +tr_opt_bool(asn1_NOVALUE, _State) -> asn1_NOVALUE; +tr_opt_bool(Bool, State) -> tr_bool(Bool, State). + +tr_bool(true, _State) -> true; +tr_bool(false, _State) -> false. + +tr_term_id_component(Sub, _State) -> + case Sub of + all -> all; + choose -> choose; + Char when is_integer(Char) -> Char + end. + +%% mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT +%% ; at-most-once per item +%% ; and either streamParm or streamDescriptor but not both +%% mediaParm = (streamParm / streamDescriptor / +%% terminationStateDescriptor) +%% ; at-most-once +%% streamParm = ( localDescriptor / remoteDescriptor / +%% localControlDescriptor ) +%% streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm +%% *(COMMA streamParm) RBRKT +tr_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TermState, + streams = Streams}, + State) -> + #'MediaDescriptor'{termStateDescr = tr_opt_TerminationStateDescriptor(TermState, State), + streams = tr_opt_streams(Streams, State)}. + +tr_opt_streams(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_streams({Tag, Val}, State) -> + Val2 = + case Tag of + oneStream -> tr_StreamParms(Val, State); + multiStream -> [tr_StreamDescriptor(SD, State) || SD <- Val] + end, + {Tag, Val2}. + +tr_StreamParms(#'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD, + statisticsDescriptor = SD}, + State) -> + LCD2 = tr_opt_LocalControlDescriptor(LCD, State), + LD2 = tr_opt_LocalRemoteDescriptor(LD, State), + RD2 = tr_opt_LocalRemoteDescriptor(RD, State), + SD2 = tr_opt_StatisticsDescriptor(SD, State), + #'StreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2, + statisticsDescriptor = SD2}. + +tr_StreamDescriptor(#'StreamDescriptor'{streamID = Id, + streamParms = Parms}, + State) -> + #'StreamDescriptor'{streamID = tr_StreamID(Id, State), + streamParms = tr_StreamParms(Parms, State)}. + +%% localControlDescriptor = LocalControlToken LBRKT localParm +%% *(COMMA localParm) RBRKT +%% +%% ; at-most-once per item +%% localParm = ( streamMode / propertyParm / +%% reservedValueMode / reservedGroupMode ) +%% reservedValueMode = ReservedValueToken EQUAL ( "ON" / "OFF" ) +%% reservedGroupMode = ReservedGroupToken EQUAL ( "ON" / "OFF" ) +%% +%% reservedMode = ReservedToken EQUAL ( "ON" / "OFF" ) +%% +%% streamMode = ModeToken EQUAL streamModes +tr_opt_LocalControlDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = Mode, + reserveGroup = Group, + reserveValue = Value, + propertyParms = Props}, + State) -> + #'LocalControlDescriptor'{streamMode = tr_opt_StreamMode(Mode, State), + reserveGroup = tr_opt_bool(Group, State), + reserveValue = tr_opt_bool(Value, State), + propertyParms = [tr_PropertyParm(P, State) || P <- Props]}. + +tr_opt_StreamMode(Mode, _State) -> + case Mode of + asn1_NOVALUE -> asn1_NOVALUE; + sendOnly -> sendOnly; + recvOnly -> recvOnly; + sendRecv -> sendRecv; + inactive -> inactive; + loopBack -> loopBack + end. + +tr_Name(Name, State) -> + %% BUGBUG: transform + %% BUGBUG: NAME = ALPHA *63(ALPHA / DIGIT / "_" ) + tr_STRING(Name, State, 2, 2). + +tr_PkgdName(Name, State) -> + %% BUGBUG: transform + %% BUGBUG: pkgdName = (NAME / "*") SLASH (ItemID / "*" ) + tr_OCTET_STRING(Name, State, 4, 4). + +%% When text encoding the protocol, the descriptors consist of session +%% descriptions as defined in SDP (RFC2327), except that the "s=", "t=" +%% and "o=" lines are optional. When multiple session descriptions are +%% provided in one descriptor, the "v=" lines are required as delimiters; +%% otherwise they are optional. Implementations shall accept session +%% descriptions that are fully conformant to RFC2327. When binary +%% encoding the protocol the descriptor consists of groups of properties +%% (tag-value pairs) as specified in Annex C. Each such group may +%% contain the parameters of a session description. +tr_opt_LocalRemoteDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = Groups}, + State) -> + #'LocalRemoteDescriptor'{propGrps = [tr_PropertyGroup(G, State) || G <- Groups]}. + +tr_PropertyGroup(Props, State) -> + [tr_PropertyGroupParm(P, State) || P <- Props]. + +tr_PropertyGroupParm(#'PropertyParm'{name = Name, + value = Value}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'PropertyParm'{name = resolve(property, Name, State, Constraint), + value = tr_OCTET_STRING(Value, State, 0, infinity)}. + +tr_PropertyParm(#'PropertyParm'{name = Name, + value = Value, + extraInfo = Extra}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'PropertyParm'{name = resolve(property, Name, State, Constraint), + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_opt_extraInfo(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_extraInfo({relation, Rel}, _State) -> + Rel2 = + case Rel of + greaterThan -> greaterThan; + smallerThan -> smallerThan; + unequalTo -> unequalTo + end, + {relation, Rel2}; +tr_opt_extraInfo({range, Range}, State) -> + Range2 = tr_bool(Range, State), + {range, Range2}; +tr_opt_extraInfo({sublist, Sub}, State) -> + Sub2 = tr_bool(Sub, State), + {sublist, Sub2}. + +tr_opt_TerminationStateDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TerminationStateDescriptor(#'TerminationStateDescriptor'{propertyParms = Props, + eventBufferControl = Control, + serviceState = Service}, + State) -> + #'TerminationStateDescriptor'{propertyParms = [tr_PropertyParm(P, State) || P <- Props], + eventBufferControl = tr_opt_EventBufferControl(Control, State), + serviceState = tr_opt_ServiceState(Service, State)}. + +tr_opt_EventBufferControl(Control, _State) -> + case Control of + asn1_NOVALUE -> asn1_NOVALUE; + off -> off; + lockStep -> lockStep + end. + +tr_opt_ServiceState(Service, _State) -> + case Service of + asn1_NOVALUE -> asn1_NOVALUE; + test -> test; + outOfSvc -> outOfSvc; + inSvc -> inSvc + end. + +tr_MuxDescriptor(#'MuxDescriptor'{muxType = Type, + termList = IdList}, + State) -> + #'MuxDescriptor'{muxType = tr_MuxType(Type, State), + termList = [tr_TerminationID(Id, State) || Id <- IdList]}. + +tr_MuxType(Type, _State) -> + case Type of + h221 -> h221; + h223 -> h223; + h226 -> h226; + v76 -> v76 + end. + +tr_opt_StreamID(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_StreamID(Id, State) -> + tr_StreamID(Id, State). + +tr_StreamID(Id, State) -> + tr_UINT16(Id, State). + +tr_EventsDescriptor(#'EventsDescriptor'{requestID = Id, + eventList = Events}, + State) -> + #'EventsDescriptor'{requestID = tr_opt_RequestID(Id, State), + eventList = [tr_RequestedEvent(E, State) || E <- Events]}. + +tr_RequestedEvent(#'RequestedEvent'{pkgdName = Name, + streamID = Id, + evParList = Parms, + eventAction = Actions}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'RequestedEvent'{pkgdName = resolve(event, Name, State, Constraint), + streamID = tr_opt_StreamID(Id, State), + eventAction = tr_opt_RequestedActions(Actions, State), + evParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + +tr_opt_RequestedActions(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_RequestedActions(#'RequestedActions'{keepActive = Keep, + eventDM = DM, + secondEvent = Event, + signalsDescriptor = SigDesc}, + State) -> + #'RequestedActions'{keepActive = tr_opt_keepActive(Keep, State), + eventDM = tr_opt_EventDM(DM, State), + secondEvent = tr_opt_SecondEventsDescriptor(Event, State), + signalsDescriptor = tr_opt_SignalsDescriptor(SigDesc, State)}. + +tr_opt_keepActive(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_keepActive(Keep, State) -> + tr_bool(Keep, State). + +tr_opt_EventDM(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_EventDM({Tag, Val}, State) -> + Val2 = + case Tag of + digitMapName -> tr_DigitMapName(Val, State); + digitMapValue -> tr_DigitMapValue(Val, State) + end, + {Tag, Val2}. + +tr_opt_SecondEventsDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = Id, + eventList = Events}, + State) -> + #'SecondEventsDescriptor'{requestID = tr_RequestID(Id, State), %% IG v6 6.8 withdrawn + eventList = [tr_SecondRequestedEvent(E, State) || E <- Events]}. + +tr_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = Name, + streamID = Id, + evParList = Parms, + eventAction = Actions}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'SecondRequestedEvent'{pkgdName = resolve(event, Name, State, Constraint), + streamID = tr_opt_StreamID(Id, State), + eventAction = tr_opt_SecondRequestedActions(Actions, State), + evParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + + +tr_opt_SecondRequestedActions(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SecondRequestedActions(#'SecondRequestedActions'{keepActive = Keep, + eventDM = DM, + signalsDescriptor = SigDesc}, + State) -> + #'SecondRequestedActions'{keepActive = tr_opt_keepActive(Keep, State), + eventDM = tr_opt_EventDM(DM, State), + signalsDescriptor = tr_opt_SignalsDescriptor(SigDesc, State)}. + +tr_EventBufferDescriptor(EventSpecs, State) -> + [tr_EventSpec(ES, State) || ES <- EventSpecs]. + +tr_EventSpec(#'EventSpec'{eventName = Name, + streamID = Id, + eventParList = Parms}, + State) -> + #'EventSpec'{eventName = tr_EventName(Name, State), + streamID = tr_opt_StreamID(Id, State), + eventParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + +tr_opt_SignalsDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SignalsDescriptor(SigDesc, State) -> + tr_SignalsDescriptor(SigDesc, State). + +tr_SignalsDescriptor(SigDesc, State) when is_list(SigDesc) -> + [tr_SignalRequest(SigReq, State) || SigReq <- SigDesc]. + +tr_SignalRequest({Tag, Val}, State) -> + Val2 = + case Tag of + signal -> tr_Signal(Val, State); + seqSigList -> tr_SeqSigList(Val, State) + end, + {Tag, Val2}. + + +tr_SeqSigList(#'SeqSigList'{id = Id, + signalList = SigList}, + State) when is_list(SigList) -> + #'SeqSigList'{id = tr_UINT16(Id, State), + signalList = [tr_Signal(Sig, State) || Sig <- SigList]}. + +tr_Signal(#'Signal'{signalName = Name, + streamID = SID, + sigType = Type, + duration = Dur, + notifyCompletion = Compl, + keepActive = Keep, + sigParList = Parms, + direction = Dir, + requestID = RID}, + State) -> + Name2 = tr_SignalName(Name, State), + SID2 = tr_opt_StreamID(SID, State), + Type2 = tr_opt_SignalType(Type, State), + Dur2 = tr_opt_duration(Dur, State), + Compl2 = tr_opt_NotifyCompletion(Compl, State), + Keep2 = tr_opt_keepActive(Keep, State), + Parms2 = [tr_SigParameter(P, Name, State) || P <- Parms], + Dir2 = tr_opt_SignalDirection(Dir, State), + RID2 = tr_opt_RequestID(RID, State), + #'Signal'{signalName = Name2, + streamID = SID2, + sigType = Type2, + duration = Dur2, + notifyCompletion = Compl2, + keepActive = Keep2, + sigParList = Parms2, + direction = Dir2, + requestID = RID2}. + +tr_opt_duration(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_duration(Dur, State) -> + tr_UINT16(Dur, State). + +tr_opt_NotifyCompletion(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_NotifyCompletion(Items, State) when is_list(Items) -> + [tr_notifyCompletionItem(I, State) || I <- Items]. + +tr_notifyCompletionItem(Item, _State) -> + case Item of + onTimeOut -> onTimeOut; + onInterruptByEvent -> onInterruptByEvent; + onInterruptByNewSignalDescr -> onInterruptByNewSignalDescr; + otherReason -> otherReason + end. + +tr_opt_SignalType(asn1_NOVALUE = Type, _State) -> + Type; +tr_opt_SignalType(Type, _State) -> + case Type of + brief -> brief; + onOff -> onOff; + timeOut -> timeOut + end. + +tr_opt_SignalDirection(asn1_NOVALUE = SD, _State) -> + SD; +tr_opt_SignalDirection(SD, _State) -> + case SD of + internal -> internal; + external -> external; + both -> both + end. + +tr_SignalName(Name, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + resolve(signal, Name, State, Constraint). + +tr_SigParameter(#'SigParameter'{sigParameterName = ParName, + value = Value, + extraInfo = Extra}, + SigName, + State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + N = resolve({signal_parameter, SigName}, ParName, State, Constraint), + #'SigParameter'{sigParameterName = N, + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_opt_RequestID(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_RequestID(Id, State) -> + tr_RequestID(Id, State). + +tr_RequestID(Id, _State) when Id =:= ?megaco_all_request_id -> + ?megaco_all_request_id; +tr_RequestID(Id, State) -> + tr_UINT32(Id, State). + +tr_ModemDescriptor(_MD, _State) -> + deprecated. + +tr_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value}, + State) -> + #'DigitMapDescriptor'{digitMapName = tr_opt_DigitMapName(Name, State), + digitMapValue = tr_opt_DigitMapValue(Value, State)}. + +tr_opt_DigitMapName(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_DigitMapName(Name, State) -> + tr_DigitMapName(Name, State). + +tr_DigitMapName(Name, State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + resolve(dialplan, Name, State, Constraint). + +tr_opt_DigitMapValue(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_DigitMapValue(Value, State) -> + tr_DigitMapValue(Value, State). + +tr_DigitMapValue(#'DigitMapValue'{digitMapBody = Body, + startTimer = Start, + shortTimer = Short, + longTimer = Long}, + State) -> + #'DigitMapValue'{startTimer = tr_opt_timer(Start, State), + shortTimer = tr_opt_timer(Short, State), + longTimer = tr_opt_timer(Long, State), + digitMapBody = tr_STRING(Body, State)}. %% BUGBUG: digitMapBody not handled at all + +tr_opt_timer(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_timer(Timer, State) -> + tr_DIGIT(Timer, State, 0, 99). + +tr_ServiceChangeParm( + #'ServiceChangeParm'{serviceChangeMethod = Method, + serviceChangeAddress = Addr, + serviceChangeVersion = Version, + serviceChangeProfile = Profile, + serviceChangeReason = Reason, + serviceChangeDelay = Delay, + serviceChangeMgcId = MgcId, + timeStamp = Time, + serviceChangeInfo = Info, + serviceChangeIncompleteFlag = Incomplete}, + State) -> + Method2 = tr_ServiceChangeMethod(Method, State), + Addr2 = tr_opt_ServiceChangeAddress(Addr, State), + Version2 = tr_opt_serviceChangeVersion(Version, State), + Profile2 = tr_opt_ServiceChangeProfile(Profile, State), + Reason2 = tr_serviceChangeReason(Reason, State), + Delay2 = tr_opt_serviceChangeDelay(Delay, State), + MgcId2 = tr_opt_serviceChangeMgcId(MgcId, State), + Time2 = tr_opt_TimeNotation(Time, State), + Info2 = tr_opt_AuditDescriptor(Info, State), + Incomplete2 = tr_opt_null(Incomplete, State), + #'ServiceChangeParm'{serviceChangeMethod = Method2, + serviceChangeAddress = Addr2, + serviceChangeVersion = Version2, + serviceChangeProfile = Profile2, + serviceChangeReason = Reason2, + serviceChangeDelay = Delay2, + serviceChangeMgcId = MgcId2, + timeStamp = Time2, + serviceChangeInfo = Info2, + serviceChangeIncompleteFlag = Incomplete2}. + +tr_ServiceChangeMethod(Method, _State) -> + case Method of + failover -> failover; + forced -> forced; + graceful -> graceful; + restart -> restart; + disconnected -> disconnected; + handOff -> handOff + end. %% BUGBUG: extension + +tr_opt_ServiceChangeAddress(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ServiceChangeAddress({Tag, Val}, State) -> + Val2 = + case Tag of + portNumber -> tr_portNumber(Val, State); + ip4Address -> tr_IP4Address(Val, State); + ip6Address -> tr_IP6Address(Val, State); + domainName -> tr_DomainName(Val, State); + deviceName -> tr_PathName(Val, State); + mtpAddress -> tr_mtpAddress(Val, State) + end, + {Tag, Val2}. + +tr_opt_serviceChangeVersion(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeVersion(Version, State) -> + tr_version(Version, State). + +tr_opt_ServiceChangeProfile(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +%% Decode +tr_opt_ServiceChangeProfile({'ServiceChangeProfile', ProfileName}, State) -> + case string:tokens(ProfileName, "/") of + [Name0, Version0] -> + Name = tr_STRING(Name0, State, 1, 64), + Version = tr_version(list_to_integer(Version0), State), + #'ServiceChangeProfile'{profileName = Name, + version = Version} + end; +%% Encode +tr_opt_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = Name0, + version = Version0}, + State) -> + Name = tr_STRING(Name0, State, 1, 64), + Version = tr_version(Version0, State), + ProfileName = lists:flatten(io_lib:format("~s/~w", [Name, Version])), + {'ServiceChangeProfile', ProfileName}. + +tr_serviceChangeReason([_] = Reason, State) -> + tr_Value(Reason, State). + +tr_opt_serviceChangeDelay(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeDelay(Delay, State) -> + tr_UINT32(Delay, State). + +tr_opt_serviceChangeMgcId(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeMgcId(MgcId, State) -> + tr_MId(MgcId, State). + +tr_opt_portNumber(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_portNumber(Port, State) -> + tr_portNumber(Port, State). + +tr_portNumber(Port, State) when is_integer(Port) andalso (Port >= 0) -> + tr_UINT16(Port, State). + +tr_ServiceChangeResParm(#'ServiceChangeResParm'{serviceChangeMgcId = MgcId, + serviceChangeAddress = Addr, + serviceChangeVersion = Version, + serviceChangeProfile = Profile, + timeStamp = Time}, + State) -> + #'ServiceChangeResParm'{serviceChangeMgcId = tr_opt_serviceChangeMgcId(MgcId, State), + serviceChangeAddress = tr_opt_ServiceChangeAddress(Addr, State), + serviceChangeVersion = tr_opt_serviceChangeVersion(Version, State), + serviceChangeProfile = tr_opt_ServiceChangeProfile(Profile, State), + timeStamp = tr_opt_TimeNotation(Time, State)}. + +tr_PackagesDescriptor(Items, State) when is_list(Items) -> + [tr_PackagesItem(I, State) || I <- Items]. + +tr_PackagesItem(#'PackagesItem'{packageName = Name, + packageVersion = Version}, + State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + #'PackagesItem'{packageName = resolve(package, Name, State, Constraint), + packageVersion = tr_UINT16(Version, State)}. + +tr_opt_StatisticsDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_StatisticsDescriptor(Parms, State) -> + tr_StatisticsDescriptor(Parms, State). + +tr_StatisticsDescriptor(Parms, State) when is_list(Parms) -> + [tr_StatisticsParameter(P, State) || P <- Parms]. + +tr_StatisticsParameter(#'StatisticsParameter'{statName = Name, + statValue = Value}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'StatisticsParameter'{statName = resolve(statistics, Name, State, Constraint), + statValue = tr_opt_Value(Value, State)}. + +tr_opt_TimeNotation(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TimeNotation(#'TimeNotation'{date = Date, + time = Time}, + State) -> + #'TimeNotation'{date = tr_STRING(Date, State, 8, 8), % "yyyymmdd" + time = tr_STRING(Time, State, 8, 8)}.% "hhmmssss" + +%% BUGBUG: Does not verify that string must contain at least one char +%% BUGBUG: This violation of the is required in order to comply with +%% BUGBUG: the dd/ce ds parameter that may possibly be empty. + +tr_opt_Value(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_Value(Value, State) -> + tr_Value(Value, State). + +tr_Value(Strings, _State) when is_list(Strings) -> + [[Char || Char <- String] || String <- Strings]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Encode an octet string, escape } by \ if necessary +tr_OCTET_STRING(String, _State, Min, Max) when is_list(String) -> + verify_count(length(String), Min, Max), + String. + +tr_QUOTED_STRING(String, _State) when is_list(String) -> + verify_count(length(String), 1, infinity), + String. + +%% The internal format of hex digits is a list of octets +%% Min and Max means #hexDigits +%% Leading zeros are prepended in order to fulfill Min +tr_HEXDIG(Octets, _State, Min, Max) when is_list(Octets) -> + verify_count(length(Octets), Min, Max), + Octets. + +tr_DIGIT(Val, State, Min, Max) -> + tr_integer(Val, State, Min, Max). + +tr_STRING(String, _State) when is_list(String) -> + String. + +tr_STRING(String, _State, Min, Max) when is_list(String) -> + verify_count(length(String), Min, Max), + String. + +tr_opt_UINT16(Val, State) -> + tr_opt_integer(Val, State, 0, 65535). + +tr_UINT16(Val, State) -> + tr_integer(Val, State, 0, 65535). + +tr_UINT32(Val, State) -> + tr_integer(Val, State, 0, 4294967295). + +tr_opt_integer(asn1_NOVALUE, _State, _Min, _Max) -> + asn1_NOVALUE; +tr_opt_integer(Int, State, Min, Max) -> + tr_integer(Int, State, Min, Max). + +tr_integer(Int, _State, Min, Max) -> + verify_count(Int, Min, Max), + Int. + +%% Verify that Count is within the range of Min and Max +verify_count(Count, Min, Max) -> + if + is_integer(Count) -> + if + is_integer(Min) andalso (Count >= Min) -> + if + is_integer(Max) andalso (Count =< Max) -> + Count; + Max =:= infinity -> + Count; + true -> + error({count_too_large, Count, Max}) + end; + true -> + error({count_too_small, Count, Min}) + end; + true -> + error({count_not_an_integer, Count}) + end. + + +%% ------------------------------------------------------------------- + +error(Reason) -> + erlang:error(Reason). + + diff --git a/lib/megaco/src/binary/megaco_binary_transformer_prev3c.erl b/lib/megaco/src/binary/megaco_binary_transformer_prev3c.erl new file mode 100644 index 0000000000..8d2f9eea38 --- /dev/null +++ b/lib/megaco/src/binary/megaco_binary_transformer_prev3c.erl @@ -0,0 +1,1756 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Transform internal form of Megaco/H.248 messages +%%---------------------------------------------------------------------- + +-module(megaco_binary_transformer_prev3c). + +-include_lib("megaco/include/megaco.hrl"). +%% -include_lib("megaco/include/megaco_message.hrl"). +-include_lib("megaco/include/megaco_message_prev3c.hrl"). +-include_lib("megaco/src/app/megaco_internal.hrl"). + +-export([tr_message/3, tr_transaction/3]). + +-define(DEFAULT_NAME_RESOLVER, megaco_binary_name_resolver_prev3c). + +-record(state, {mode, % verify | encode | decode + resolver_module, % + resolver_options}). + +resolve(Type, Item, State, Constraint) -> + case State#state.mode of + verify -> + Item; + encode -> + ?d("resolve(encode) -> encode: ~p",[Item]), + Mod = State#state.resolver_module, + Opt = State#state.resolver_options, + EncodedItem = Mod:encode_name(Opt, Type, Item), + ?d("resolve -> verify contraint for ~p",[EncodedItem]), + verify_constraint(EncodedItem, Constraint); + decode -> + ?d("resolve(decode) -> verify contraint for ~p",[Item]), + DecodedItem = verify_constraint(Item, Constraint), + Mod = State#state.resolver_module, + Opt = State#state.resolver_options, + ?d("resolve(decode) -> decode: ~p",[DecodedItem]), + Mod:decode_name(Opt, Type, DecodedItem) + end. + +verify_constraint(Item, valid) -> + Item; +verify_constraint(Item, Constraint) when is_function(Constraint) -> + Constraint(Item). + +tr_message(MegaMsg, Mode, Config) -> + case Config of + [native] -> + MegaMsg; + [verify] -> + State = #state{mode = verify}, + tr_MegacoMessage(MegaMsg, State); + [] -> + State = #state{mode = Mode, + resolver_module = ?DEFAULT_NAME_RESOLVER, + resolver_options = [8, 8, 8]}, + tr_MegacoMessage(MegaMsg, State); + [{binary_name_resolver, {Module, Options}}] when is_atom(Module) -> + State = #state{mode = Mode, + resolver_module = Module, + resolver_options = Options}, + tr_MegacoMessage(MegaMsg, State) + end. + +tr_transaction(Trans, Mode, Config) -> + case Config of + [native] -> + Trans; + [verify] -> + State = #state{mode = verify}, + tr_Transaction(Trans, State); + [] -> + State = #state{mode = Mode, + resolver_module = ?DEFAULT_NAME_RESOLVER, + resolver_options = [8, 8, 8]}, + tr_Transaction(Trans, State); + [{binary_name_resolver, {Module, Options}}] when is_atom(Module) -> + State = #state{mode = Mode, + resolver_module = Module, + resolver_options = Options}, + tr_Transaction(Trans, State) + end. + +tr_MegacoMessage(#'MegacoMessage'{authHeader = Auth, + mess = Mess}, + State) -> + ?d("tr_MegacoMessage -> entry with" + "~n Auth: ~p" + "~n Mess: ~p" + "~n State: ~p", [Auth, Mess, State]), + #'MegacoMessage'{authHeader = tr_opt_AuthenticationHeader(Auth, State), + mess = tr_Message(Mess, State)}. + +tr_opt_AuthenticationHeader(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_AuthenticationHeader(#'AuthenticationHeader'{secParmIndex = SPI, + seqNum = SN, + ad = AuthData}, + State) -> + #'AuthenticationHeader'{secParmIndex = tr_SecurityParmIndex(SPI, State), + seqNum = tr_SequenceNum(SN, State), + ad = tr_AuthData(AuthData, State)}. + +tr_SecurityParmIndex(SPI, State) -> + tr_HEXDIG(SPI, State, 4, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_SequenceNum(SN, State) -> + tr_HEXDIG(SN, State, 4, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_AuthData(AuthData, State) -> + tr_HEXDIG(AuthData, State, 12, 32). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_Message(#'Message'{version = Version, + mId = MID, + messageBody = Body}, + State) -> + #'Message'{version = tr_version(Version, State), + mId = tr_MId(MID, State), + messageBody = tr_Message_messageBody(Body, State)}. + +tr_version(Version, State) -> + tr_DIGIT(Version, State, 0, 99). + +tr_Message_messageBody({Tag, Val}, State) -> + Val2 = + case Tag of + messageError -> tr_ErrorDescriptor(Val, State); + transactions when is_list(Val) -> [tr_Transaction(T, State) || T <- Val] + end, + {Tag, Val2}. + +tr_MId({Tag, Val}, State) -> + Val2 = + case Tag of + ip4Address -> tr_IP4Address(Val, State); + ip6Address -> tr_IP6Address(Val, State); + domainName -> tr_DomainName(Val, State); + deviceName -> tr_PathName(Val, State); + mtpAddress -> tr_mtpAddress(Val, State) + end, + {Tag, Val2}. + +tr_mtpAddress(MtpAddr, State) -> + tr_OCTET_STRING(MtpAddr, State, 2, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_DomainName(#'DomainName'{name = Name, + portNumber = Port}, + State) -> + Domain = #'DomainName'{name = tr_STRING(Name, State), % BUGBUG: Mismatch between ASN.1 and ABNF + portNumber = tr_opt_portNumber(Port, State)}, + {domainName, Domain2} = resolve(mid, {domainName, Domain}, State, valid), + Domain2. + +tr_IP4Address(#'IP4Address'{address = [A1, A2, A3, A4], + portNumber = Port}, + State) -> + #'IP4Address'{address = [tr_V4hex(A1, State), + tr_V4hex(A2, State), + tr_V4hex(A3, State), + tr_V4hex(A4, State)], + portNumber = tr_opt_portNumber(Port, State)}. + +tr_V4hex(Val, State) -> + tr_DIGIT(Val, State, 0, 255). + +tr_IP6Address(_Val, _State) -> + error(ipv6_not_supported). %% BUGBUG: nyi + +tr_PathName(Path, State) -> + %% BUGBUG: ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" ) + %% BUGBUG: ["@" pathDomainName ] + Constraint = fun({deviceName, Item}) -> tr_STRING(Item, State, 1, 64) end, + resolve(mid, {deviceName, Path}, State, Constraint). + +tr_Transaction({Tag, Val}, State) -> + Val2 = + case Tag of + transactionRequest -> tr_TransactionRequest(Val, State); + transactionPending -> tr_TransactionPending(Val, State); + transactionReply -> tr_TransactionReply(Val, State); + transactionResponseAck -> [tr_TransactionAck(T, State) || T <- Val] + end, + {Tag, Val2}. + +tr_TransactionAck(#'TransactionAck'{firstAck = First, + lastAck = Last}, + State) -> + #'TransactionAck'{firstAck = tr_TransactionId(First, State), + lastAck = tr_opt_TransactionId(Last, State)}. + +tr_opt_TransactionId(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TransactionId(Id, State) -> + tr_TransactionId(Id, State). + +tr_TransactionId(Id, State) -> + tr_UINT32(Id, State). + +tr_TransactionRequest(#'TransactionRequest'{transactionId = Id, + actions = Actions}, + State) when is_list(Actions) -> + + #'TransactionRequest'{transactionId = tr_TransactionId(Id, State), + actions = [tr_ActionRequest(ActReq, State) || ActReq <- Actions]}. + +tr_TransactionPending(#'TransactionPending'{transactionId = Id}, + State) -> + #'TransactionPending'{transactionId = tr_TransactionId(Id, State)}. + +tr_TransactionReply(#'TransactionReply'{transactionId = Id, + immAckRequired = ImmAck, + transactionResult = TransRes, + %% These fields are actually not + %% supported in this implementation, + %% but because the messanger module + %% cannot see any diff between the + %% various v3 implementations... + segmentNumber = asn1_NOVALUE, + segmentationComplete = asn1_NOVALUE}, + State) -> + #'TransactionReply'{transactionId = tr_TransactionId(Id, State), + immAckRequired = tr_opt_null(ImmAck, State), + transactionResult = tr_TransactionReply_transactionResult(TransRes, State), + segmentNumber = asn1_NOVALUE, + segmentationComplete = asn1_NOVALUE}; +tr_TransactionReply(TR, _State) -> + error({unsupported_TransactionReply, TR}). + +tr_opt_null(asn1_NOVALUE, _State) -> asn1_NOVALUE; +tr_opt_null('NULL', _State) -> 'NULL'. + +tr_TransactionReply_transactionResult({Tag, Val}, State) -> + Val2 = + case Tag of + transactionError -> + tr_ErrorDescriptor(Val, State); + actionReplies when is_list(Val) andalso (Val =/= []) -> + [tr_ActionReply(ActRep, State) || ActRep <- Val] + end, + {Tag, Val2}. + +tr_opt_ErrorDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ErrorDescriptor(ErrDesc, State) -> + tr_ErrorDescriptor(ErrDesc, State). + +tr_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code, + errorText = Text}, + State) -> + #'ErrorDescriptor'{errorCode = tr_ErrorCode(Code, State), + errorText = tr_opt_ErrorText(Text, State)}. + +tr_ErrorCode(Code, State) -> + tr_DIGIT(Code, State, 0, 999). + +tr_opt_ErrorText(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ErrorText(Text, State) -> + tr_QUOTED_STRING(Text, State). + +tr_ContextID(CtxId, State) -> + case CtxId of + ?megaco_all_context_id -> ?megaco_all_context_id; + ?megaco_null_context_id -> ?megaco_null_context_id; + ?megaco_choose_context_id -> ?megaco_choose_context_id; + Int when is_integer(Int) -> tr_UINT32(Int, State) + end. + +tr_ActionRequest(#'ActionRequest'{contextId = CtxId, + contextRequest = CtxReq, + contextAttrAuditReq = CtxAuditReq, + commandRequests = CmdReqList}, + State) -> + #'ActionRequest'{contextId = tr_ContextID(CtxId, State), + contextRequest = tr_opt_ContextRequest(CtxReq, State), + contextAttrAuditReq = tr_opt_ContextAttrAuditRequest(CtxAuditReq, State), + commandRequests = [tr_CommandRequest(CmdReq, State) || CmdReq <- CmdReqList]}. + +tr_ActionReply(#'ActionReply'{contextId = CtxId, + errorDescriptor = ErrDesc, + contextReply = CtxRep, + commandReply = CmdRepList}, + State) -> + CmdRepList2 = [tr_CommandReply(CmdRep, State) || CmdRep <- CmdRepList], + #'ActionReply'{contextId = tr_ContextID(CtxId, State), + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State), + contextReply = tr_opt_ContextRequest(CtxRep, State), + commandReply = CmdRepList2}. + +tr_opt_ContextRequest(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ContextRequest(CR, State) -> + tr_ContextRequest(CR, State). + +tr_ContextRequest(#'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = TopReqList, + iepscallind = Ind, + contextProp = CtxProps, + contextList = CtxList}, + State) -> + Prio2 = + case Prio of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_integer(Prio, State, 0, 15) + end, + Em2 = + case Em of + asn1_NOVALUE -> asn1_NOVALUE; + false -> false; + true -> true + end, + TopReqList2 = + case TopReqList of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_TopologyRequest(TopReq, State) || + TopReq <- TopReqList] + end, + Ind2 = + case Ind of + asn1_NOVALUE -> asn1_NOVALUE; + false -> false; + true -> true + end, + CtxProps2 = + case CtxProps of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_PropertyParm(Prop, State) || Prop <- CtxProps] + end, + CtxList2 = + case CtxList of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_ContextID(Id, State) || Id <- CtxList] + end, + #'ContextRequest'{priority = Prio2, + emergency = Em2, + topologyReq = TopReqList2, + iepscallind = Ind2, + contextProp = CtxProps2, + contextList = CtxList2}. + +tr_opt_ContextAttrAuditRequest(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ContextAttrAuditRequest(CAAR, State) -> + tr_ContextAttrAuditRequest(CAAR, State). + +tr_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ind, + contextPropAud = Props, + selectpriority = SPrio, + selectemergency = SEm, + selectiepscallind = SInd, + selectLogic = SLog}, + State) -> + Top2 = tr_opt_null(Top, State), + Em2 = tr_opt_null(Em, State), + Prio2 = tr_opt_null(Prio, State), + Ind2 = tr_opt_null(Ind, State), + Props2 = + case Props of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + [tr_indAudPropertyParm(Prop, State) || Prop <- Props] + end, + SPrio2 = + case SPrio of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_integer(SPrio, State, 0, 15) + end, + SEm2 = + case SEm of + asn1_NOVALUE -> asn1_NOVALUE; + false -> false; + true -> true + end, + SInd2 = + case SInd of + asn1_NOVALUE -> asn1_NOVALUE; + false -> false; + true -> true + end, + SLog2 = + case SLog of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_SelectLogic(SLog, State) + end, + #'ContextAttrAuditRequest'{topology = Top2, + emergency = Em2, + priority = Prio2, + iepscallind = Ind2, + contextPropAud = Props2, + selectpriority = SPrio2, + selectemergency = SEm2, + selectiepscallind = SInd2, + selectLogic = SLog2}. + +tr_SelectLogic({andAUDITSelect, 'NULL'} = Val, _State) -> + Val; +tr_SelectLogic({orAUDITSelect, 'NULL'} = Val, _State) -> + Val. + +tr_CommandRequest(#'CommandRequest'{command = Cmd, + optional = Opt, + wildcardReturn = Wild}, + State) -> + #'CommandRequest'{optional = tr_opt_null(Opt, State), + wildcardReturn = tr_opt_null(Wild, State), + command = tr_Command(Cmd, State)}. + +tr_Command({Tag, Val}, State) -> + Val2 = + case Tag of + addReq -> tr_AmmRequest(Val, State); + moveReq -> tr_AmmRequest(Val, State); + modReq -> tr_AmmRequest(Val, State); + subtractReq -> tr_SubtractRequest(Val, State); + auditCapRequest -> tr_AuditRequest(Val, State); + auditValueRequest -> tr_AuditRequest(Val, State); + notifyReq -> tr_NotifyRequest(Val, State); + serviceChangeReq -> tr_ServiceChangeRequest(Val, State) + end, + {Tag, Val2}. + +tr_CommandReply({Tag, Val}, State) -> + Val2 = + case Tag of + addReply -> tr_AmmsReply(Val, State); + moveReply -> tr_AmmsReply(Val, State); + modReply -> tr_AmmsReply(Val, State); + subtractReply -> tr_AmmsReply(Val, State); + auditCapReply -> tr_AuditReply(Val, State); + auditValueReply -> tr_AuditReply(Val, State); + notifyReply -> tr_NotifyReply(Val, State); + serviceChangeReply -> tr_ServiceChangeReply(Val, State) + end, + {Tag, Val2}. + +tr_TopologyRequest(#'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = Dir, + streamID = SID, + topologyDirectionExtension = TDE}, + State) -> + Dir2 = + case Dir of + bothway -> bothway; + isolate -> isolate; + oneway -> oneway + end, + TDE2 = + case TDE of + onewayexternal -> onewayexternal; + onewayboth -> onewayboth; + asn1_NOVALUE -> asn1_NOVALUE + end, + #'TopologyRequest'{terminationFrom = tr_TerminationID(From, State), + terminationTo = tr_TerminationID(To, State), + topologyDirection = Dir2, + streamID = tr_opt_StreamID(SID, State), + topologyDirectionExtension = TDE2}. + +tr_AmmRequest(#'AmmRequest'{terminationID = IdList, + descriptors = DescList}, + State) -> + #'AmmRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + descriptors = tr_ammDescriptors(DescList, [], State)}. + +tr_ammDescriptors([], Acc, _State) -> + lists:reverse(Acc); +tr_ammDescriptors([Desc|Descs], Acc, State) -> + case tr_ammDescriptor(Desc, State) of + {_, deprecated} when State#state.mode =:= encode -> + error({deprecated, Desc}); + {_, deprecated} when State#state.mode =:= decode -> + %% SKIP + tr_ammDescriptors(Descs, Acc, State); + {_, deprecated} -> + %% SKIP + tr_ammDescriptors(Descs, Acc, State); + NewDesc -> + tr_ammDescriptors(Descs, [NewDesc|Acc], State) + end. + +tr_ammDescriptor({Tag, Desc}, State) -> + Desc2 = + case Tag of + mediaDescriptor -> tr_MediaDescriptor(Desc, State); + modemDescriptor -> tr_ModemDescriptor(Desc, State); + muxDescriptor -> tr_MuxDescriptor(Desc, State); + eventsDescriptor -> tr_EventsDescriptor(Desc, State); + eventBufferDescriptor -> tr_EventBufferDescriptor(Desc, State); + signalsDescriptor -> tr_SignalsDescriptor(Desc, State); + digitMapDescriptor -> tr_DigitMapDescriptor(Desc, State); + auditDescriptor -> tr_AuditDescriptor(Desc, State); + statisticsDescriptor -> tr_StatisticsDescriptor(Desc, State) + end, + {Tag, Desc2}. + +tr_AmmsReply(#'AmmsReply'{terminationID = IdList, + terminationAudit = TermAudit}, + State) -> + TermAudit2 = + case TermAudit of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_TerminationAudit(TermAudit, State) + end, + #'AmmsReply'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + terminationAudit = TermAudit2}. + +tr_SubtractRequest(#'SubtractRequest'{terminationID = IdList, + auditDescriptor = Desc}, + State) -> + #'SubtractRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + auditDescriptor = tr_opt_AuditDescriptor(Desc, State)}. + +tr_AuditRequest(#'AuditRequest'{terminationID = Id, + auditDescriptor = Desc, + terminationIDList = TIDList}, + State) -> + TIDList2 = + case TIDList of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_TerminationID(TID, State) || TID <- TIDList] + end, + #'AuditRequest'{terminationID = tr_TerminationID(Id, State), + auditDescriptor = tr_AuditDescriptor(Desc, State), + terminationIDList = TIDList2}. + +%% auditReply = (AuditValueToken / AuditCapToken ) +%% ( contextTerminationAudit / auditOther) +%% auditOther = EQUAL TerminationID LBRKT +%% terminationAudit RBRKT +%% terminationAudit = auditReturnParameter *(COMMA auditReturnParameter) +%% +%% contextTerminationAudit = EQUAL CtxToken ( terminationIDList / +%% LBRKT errorDescriptor RBRKT ) + +tr_AuditReply({Tag, Val}, State) -> + Val2 = + case Tag of + contextAuditResult -> + [tr_TerminationID(Id, State) || Id <- Val]; + error -> + tr_ErrorDescriptor(Val, State); + auditResult -> + tr_AuditResult(Val, State); + auditResultTermList -> + tr_TermListAuditResult(Val, State) + end, + {Tag, Val2}. + +tr_AuditResult(#'AuditResult'{terminationID = Id, + terminationAuditResult = AuditRes}, + State) -> + #'AuditResult'{terminationID = tr_TerminationID(Id, State), + terminationAuditResult = tr_TerminationAudit(AuditRes, State)}. + +tr_TermListAuditResult( + #'TermListAuditResult'{terminationIDList = TIDList, + terminationAuditResult = TAR}, + State) -> + TIDList2 = [tr_TerminationID(TID, State) || TID <- TIDList], + TAR2 = tr_TerminationAudit(TAR, State), + #'TermListAuditResult'{terminationIDList = TIDList2, + terminationAuditResult = TAR2}. + + +tr_opt_AuditDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_AuditDescriptor(Desc, State) -> + tr_AuditDescriptor(Desc, State). + +%% BUGBUG BUGBUG BUGBUG +%% With this construction it is possible to have both auditToken +%% and auditPropertyToken, but it is actually valid? +tr_AuditDescriptor(#'AuditDescriptor'{auditToken = Tokens, + auditPropertyToken = APTs}, + State) -> + Tokens2 = + case Tokens of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_auditItem(Token, State) || Token <- Tokens] + end, + %% v2 + APTs2 = + case APTs of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + [tr_indAuditParameter(APT, State) || APT <- APTs] + end, + #'AuditDescriptor'{auditToken = Tokens2, + auditPropertyToken = APTs2}. + +tr_auditItem(Token, _State) -> + case Token of + muxToken -> muxToken; + modemToken -> modemToken; + mediaToken -> mediaToken; + eventsToken -> eventsToken; + signalsToken -> signalsToken; + digitMapToken -> digitMapToken; + statsToken -> statsToken; + observedEventsToken -> observedEventsToken; + packagesToken -> packagesToken; + eventBufferToken -> eventBufferToken + end. + +%% --- v2 begin --- + +tr_indAuditParameter({Tag, Val}, State) -> + Val2 = + case Tag of + indAudMediaDescriptor -> + tr_indAudMediaDescriptor(Val, State); + indAudEventsDescriptor -> + tr_indAudEventsDescriptor(Val, State); + indAudSignalsDescriptor -> + tr_indAudSignalsDescriptor(Val, State); + indAudDigitMapDescriptor -> + tr_indAudDigitMapDescriptor(Val, State); + indAudEventBufferDescriptor -> + tr_indAudEventBufferDescriptor(Val, State); + indAudStatisticsDescriptor -> + tr_indAudStatisticsDescriptor(Val, State); + indAudPackagesDescriptor -> + tr_indAudPackagesDescriptor(Val, State) + end, + {Tag, Val2}. + + +%% - + +tr_indAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = S}, + State) -> + TSD2 = + case TSD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudTerminationStateDescriptor(TSD, State) + end, + S2 = + case S of + asn1_NOVALUE -> + asn1_NOVALUE; + {oneStream, OS} -> + {oneStream, tr_indAudStreamParms(OS, State)}; + {multiStream, MS} -> + MS2 = [tr_indAudStreamDescriptor(MS1, State) || MS1 <- MS], + {multiStream, MS2} + end, + #'IndAudMediaDescriptor'{termStateDescr = TSD2, + streams = S2}. + +tr_indAudTerminationStateDescriptor(Val, State) + when is_record(Val, 'IndAudTerminationStateDescriptor') -> + #'IndAudTerminationStateDescriptor'{propertyParms = Parms, + eventBufferControl = EBC, + serviceState = SS, + serviceStateSel = SSS} = Val, + Parms2 = [tr_indAudPropertyParm(Parm, State) || Parm <- Parms], + EBC2 = tr_opt_null(EBC, State), + SS2 = tr_opt_null(SS, State), + SSS2 = tr_opt_ServiceState(SSS, State), + #'IndAudTerminationStateDescriptor'{propertyParms = Parms2, + eventBufferControl = EBC2, + serviceState = SS2, + serviceStateSel = SSS2}. + + +tr_indAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD, + statisticsDescriptor = SD}, + State) -> + LCD2 = + case LCD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudLocalControlDescriptor(LCD, State) + end, + LD2 = + case LD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudLocalRemoteDescriptor(LD, State) + end, + RD2 = + case RD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudLocalRemoteDescriptor(RD, State) + end, + SD2 = + case SD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudStatisticsDescriptor(SD, State) + end, + #'IndAudStreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2, + statisticsDescriptor = SD2}. + +tr_indAudLocalControlDescriptor(Val, State) + when is_record(Val, 'IndAudLocalControlDescriptor') -> + #'IndAudLocalControlDescriptor'{streamMode = M, + reserveValue = V, + reserveGroup = G, + propertyParms = P, + streamModeSel = SMS} = Val, + M2 = tr_opt_null(M, State), + V2 = tr_opt_null(V, State), + G2 = tr_opt_null(G, State), + P2 = tr_indAudLocalControlDescriptor_propertyParms(P, State), + SMS2 = tr_opt_StreamMode(SMS, State), + #'IndAudLocalControlDescriptor'{streamMode = M2, + reserveValue = V2, + reserveGroup = G2, + propertyParms = P2, + streamModeSel = SMS2}. + +tr_indAudLocalControlDescriptor_propertyParms(Parms, State) + when is_list(Parms) andalso (length(Parms) > 0) -> + [tr_indAudPropertyParm(Parm, State) || Parm <- Parms]; +tr_indAudLocalControlDescriptor_propertyParms(asn1_NOVALUE, _State) -> + asn1_NOVALUE. + +tr_indAudLocalRemoteDescriptor(#'IndAudLocalRemoteDescriptor'{propGroupID = ID, + propGrps = Grps}, + State) -> + #'IndAudLocalRemoteDescriptor'{propGroupID = tr_opt_UINT16(ID, State), + propGrps = tr_indAudPropertyGroup(Grps, + State)}. + +tr_indAudPropertyGroup(Grps, State) when is_list(Grps) -> + [tr_indAudPropertyParm(Parm, State) || Parm <- Grps]. + +tr_indAudPropertyParm(#'IndAudPropertyParm'{name = Name0, + propertyParms = Prop0}, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(property, Name0, State, Constraint), + Prop = + case Prop0 of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_PropertyParm(Prop0, State) + end, + #'IndAudPropertyParm'{name = Name, + propertyParms = Prop}. + + +tr_indAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = ID, + streamParms = Parms}, + State) -> + #'IndAudStreamDescriptor'{streamID = tr_StreamID(ID, State), + streamParms = tr_indAudStreamParms(Parms, + State)}. + + +%% - + +tr_indAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID, + pkgdName = Name0, + streamID = SID}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(event, Name0, State, Constraint), + #'IndAudEventsDescriptor'{requestID = tr_opt_RequestID(RID, State), + pkgdName = Name, + streamID = tr_opt_StreamID(SID, State)}. + + +%% - + +tr_indAudSignalsDescriptor({Tag, Val}, State) -> + case Tag of + signal -> + {signal, tr_indAudSignal(Val, State)}; + seqSigList -> + {seqSigList, tr_indAudSeqSigList(Val, State)} + end. + +tr_opt_indAudSignal(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_indAudSignal(Val, State) -> + tr_indAudSignal(Val, State). + +tr_indAudSignal(#'IndAudSignal'{signalName = Name0, + streamID = SID, + signalRequestID = RID}, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(signal, Name0, State, Constraint), + #'IndAudSignal'{signalName = Name, + streamID = tr_opt_StreamID(SID, State), + signalRequestID = tr_opt_RequestID(RID, State)}. + +tr_indAudSeqSigList(#'IndAudSeqSigList'{id = ID, + signalList = SigList}, State) -> + #'IndAudSeqSigList'{id = tr_integer(ID, State, 0, 65535), + signalList = tr_opt_indAudSignal(SigList, State)}. + +%% - + +tr_indAudDigitMapDescriptor(#'IndAudDigitMapDescriptor'{digitMapName = Name}, + State) -> + #'IndAudDigitMapDescriptor'{digitMapName = + tr_opt_DigitMapName(Name, State)}. + + +%% - + +tr_indAudEventBufferDescriptor(#'IndAudEventBufferDescriptor'{eventName = N, + streamID = SID}, + State) -> + ?d("tr_indAudEventBufferDescriptor -> entry with" + "~n N: ~p" + "~n SID: ~p", [N, SID]), + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(event, N, State, Constraint), + ?d("tr_indAudEventBufferDescriptor -> entry with" + "~n Name: ~p", [Name]), + #'IndAudEventBufferDescriptor'{eventName = Name, + streamID = tr_opt_StreamID(SID, State)}. + +%% - + +tr_indAudStatisticsDescriptor(#'IndAudStatisticsDescriptor'{statName = N}, + State) -> + ?d("tr_indAudEventBufferDescriptor -> entry with" + "~n N: ~p", [N]), + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(statistics, N, State, Constraint), + #'IndAudStatisticsDescriptor'{statName = Name}. + + +%% - + +tr_indAudPackagesDescriptor(#'IndAudPackagesDescriptor'{packageName = N, + packageVersion = V}, + State) -> + ?d("tr_indAudPackagesDescriptor -> entry with" + "~n N: ~p" + "~n V: ~p", [N, V]), + Constraint = fun(Item) -> tr_Name(Item, State) end, + Name = resolve(package, N, State, Constraint), + ?d("tr_indAudPackagesDescriptor -> entry with" + "~n Name: ~p", [Name]), + #'IndAudPackagesDescriptor'{packageName = Name, + packageVersion = tr_integer(V, State, 0, 99)}. + +%% -- v2 end -- + + +tr_TerminationAudit(ParmList, State) when is_list(ParmList) -> + do_tr_TerminationAudit(ParmList, [], State). + +do_tr_TerminationAudit([], Acc, _State) -> + lists:reverse(Acc); +do_tr_TerminationAudit([Parm|ParmList], Acc, State) -> + case tr_AuditReturnParameter(Parm, State) of + {_, deprecated} when State#state.mode =:= encode -> + error({deprecated, Parm}); + {_, deprecated} when State#state.mode =:= decode -> + %% SKIP + do_tr_TerminationAudit(ParmList, Acc, State); + {_, deprecated} -> + %% SKIP + do_tr_TerminationAudit(ParmList, Acc, State); + NewParm -> + do_tr_TerminationAudit(ParmList, [NewParm|Acc], State) + end. + +tr_AuditReturnParameter({Tag, Val}, State) -> + Val2 = + case Tag of + errorDescriptor -> + tr_ErrorDescriptor(Val, State); + mediaDescriptor -> + tr_MediaDescriptor(Val, State); + modemDescriptor -> + tr_ModemDescriptor(Val, State); + muxDescriptor -> + tr_MuxDescriptor(Val, State); + eventsDescriptor -> + tr_EventsDescriptor(Val, State); + eventBufferDescriptor -> + tr_EventBufferDescriptor(Val, State); + signalsDescriptor -> + tr_SignalsDescriptor(Val, State); + digitMapDescriptor -> + tr_DigitMapDescriptor(Val, State); + observedEventsDescriptor -> + tr_ObservedEventsDescriptor(Val, State); + statisticsDescriptor -> + tr_StatisticsDescriptor(Val, State); + packagesDescriptor -> + tr_PackagesDescriptor(Val, State); + emptyDescriptors -> + tr_EmptyDescriptors(Val, State) + end, + {Tag, Val2}. + +tr_EmptyDescriptors(#'AuditDescriptor'{auditToken = Tokens}, + State) -> + Tokens2 = + case Tokens of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_auditItem(Token, State) || Token <- Tokens] + end, + #'AuditDescriptor'{auditToken = Tokens2}. + +tr_NotifyRequest(#'NotifyRequest'{terminationID = IdList, + observedEventsDescriptor = ObsDesc, + errorDescriptor = ErrDesc}, + State) -> + %% BUGBUG: Mismatch between ASN.1 and ABNF + %% BUGBUG: The following ought to be a 'choice' + #'NotifyRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + observedEventsDescriptor = tr_ObservedEventsDescriptor(ObsDesc, State), + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State)}. + +tr_NotifyReply(#'NotifyReply'{terminationID = IdList, + errorDescriptor = ErrDesc}, + State) -> + #'NotifyReply'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State)}. + +tr_ObservedEventsDescriptor(#'ObservedEventsDescriptor'{requestId = Id, + observedEventLst = Events}, + State) when is_list(Events) -> + #'ObservedEventsDescriptor'{requestId = tr_RequestID(Id, State), + observedEventLst = [tr_ObservedEvent(E, State) || E <- Events]}. + +%% ;time per event, because it might be buffered +%% observedEvent = [ TimeStamp LWSP COLON] LWSP +%% pkgdName [ LBRKT observedEventParameter +%% *(COMMA observedEventParameter) RBRKT ] +%% +%% ;at-most-once eventStream, every eventParameterName at most once +%% observedEventParameter = eventStream / eventOther + +tr_ObservedEvent(#'ObservedEvent'{eventName = Name, + streamID = Id, + eventParList = Parms, + timeNotation = Time}, + State) -> + #'ObservedEvent'{eventName = tr_EventName(Name, State), + streamID = tr_opt_StreamID(Id, State), + eventParList = [tr_EventParameter(P, Name, State) || P <- Parms], + timeNotation = tr_opt_TimeNotation(Time, State)}. + +tr_EventName(Name, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + resolve(event, Name, State, Constraint). + +tr_EventParameter(#'EventParameter'{eventParameterName = ParName, + value = Value, + extraInfo = Extra}, + EventName, + State) -> + %% BUGBUG: event parameter name + Constraint = fun(Item) -> tr_Name(Item, State) end, + N = resolve({event_parameter, EventName}, ParName, State, Constraint), + #'EventParameter'{eventParameterName = N, + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_ServiceChangeRequest(#'ServiceChangeRequest'{terminationID = IdList, + serviceChangeParms = Parms}, + State) -> + #'ServiceChangeRequest'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + serviceChangeParms = tr_ServiceChangeParm(Parms, State)}. + +%% serviceChangeReply = ServiceChangeToken EQUAL TerminationID +%% [LBRKT (errorDescriptor / +%% serviceChangeReplyDescriptor) RBRKT] +%% serviceChangeReplyDescriptor = ServicesToken LBRKT +%% servChgReplyParm *(COMMA servChgReplyParm) RBRKT +%% +%% ;at-most-once. Version is REQUIRED on first ServiceChange response +%% servChgReplyParm = (serviceChangeAddress / serviceChangeMgcId / +%% serviceChangeProfile / serviceChangeVersion ) +tr_ServiceChangeReply(#'ServiceChangeReply'{terminationID = IdList, + serviceChangeResult = Res}, + State) -> + #'ServiceChangeReply'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + serviceChangeResult = tr_ServiceChangeResult(Res, State)}. + +tr_ServiceChangeResult({Tag, Val}, State) -> + Val2 = + case Tag of + errorDescriptor -> tr_ErrorDescriptor(Val, State); + serviceChangeResParms -> tr_ServiceChangeResParm(Val, State) + end, + {Tag, Val2}. + +%% TerminationID = "ROOT" / pathNAME / "$" / "*" +%% ; Total length of pathNAME must not exceed 64 chars. +%% pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" ) +%% ["@" pathDomainName ] + +tr_TerminationID(TermId, State) when State#state.mode =/= verify -> + resolve(term_id, TermId, State, valid); +tr_TerminationID(#'TerminationID'{wildcard = Wild, + id = Id}, + _State) -> + #'TerminationID'{wildcard = Wild, + id = Id}; +tr_TerminationID(#megaco_term_id{contains_wildcards = IsWild, + id = Id}, + State) -> + #megaco_term_id{contains_wildcards = tr_bool(IsWild, State), + id = [tr_term_id_component(Sub, State) || Sub <- Id]}. + +tr_opt_bool(asn1_NOVALUE, _State) -> asn1_NOVALUE; +tr_opt_bool(Bool, State) -> tr_bool(Bool, State). + +tr_bool(true, _State) -> true; +tr_bool(false, _State) -> false. + +tr_term_id_component(Sub, _State) -> + case Sub of + all -> all; + choose -> choose; + Char when is_integer(Char) -> Char + end. + +%% mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT +%% ; at-most-once per item +%% ; and either streamParm or streamDescriptor but not both +%% mediaParm = (streamParm / streamDescriptor / +%% terminationStateDescriptor) +%% ; at-most-once +%% streamParm = ( localDescriptor / remoteDescriptor / +%% localControlDescriptor ) +%% streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm +%% *(COMMA streamParm) RBRKT +tr_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TermState, + streams = Streams}, + State) -> + #'MediaDescriptor'{termStateDescr = tr_opt_TerminationStateDescriptor(TermState, State), + streams = tr_opt_streams(Streams, State)}. + +tr_opt_streams(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_streams({Tag, Val}, State) -> + Val2 = + case Tag of + oneStream -> tr_StreamParms(Val, State); + multiStream -> [tr_StreamDescriptor(SD, State) || SD <- Val] + end, + {Tag, Val2}. + +tr_StreamParms(#'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD, + statisticsDescriptor = SD}, + State) -> + LCD2 = tr_opt_LocalControlDescriptor(LCD, State), + LD2 = tr_opt_LocalRemoteDescriptor(LD, State), + RD2 = tr_opt_LocalRemoteDescriptor(RD, State), + SD2 = tr_opt_StatisticsDescriptor(SD, State), + #'StreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2, + statisticsDescriptor = SD2}. + +tr_StreamDescriptor(#'StreamDescriptor'{streamID = Id, + streamParms = Parms}, + State) -> + #'StreamDescriptor'{streamID = tr_StreamID(Id, State), + streamParms = tr_StreamParms(Parms, State)}. + +%% localControlDescriptor = LocalControlToken LBRKT localParm +%% *(COMMA localParm) RBRKT +%% +%% ; at-most-once per item +%% localParm = ( streamMode / propertyParm / +%% reservedValueMode / reservedGroupMode ) +%% reservedValueMode = ReservedValueToken EQUAL ( "ON" / "OFF" ) +%% reservedGroupMode = ReservedGroupToken EQUAL ( "ON" / "OFF" ) +%% +%% reservedMode = ReservedToken EQUAL ( "ON" / "OFF" ) +%% +%% streamMode = ModeToken EQUAL streamModes +tr_opt_LocalControlDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = Mode, + reserveGroup = Group, + reserveValue = Value, + propertyParms = Props}, + State) -> + #'LocalControlDescriptor'{streamMode = tr_opt_StreamMode(Mode, State), + reserveGroup = tr_opt_bool(Group, State), + reserveValue = tr_opt_bool(Value, State), + propertyParms = [tr_PropertyParm(P, State) || P <- Props]}. + +tr_opt_StreamMode(Mode, _State) -> + case Mode of + asn1_NOVALUE -> asn1_NOVALUE; + sendOnly -> sendOnly; + recvOnly -> recvOnly; + sendRecv -> sendRecv; + inactive -> inactive; + loopBack -> loopBack + end. + +tr_Name(Name, State) -> + %% BUGBUG: transform + %% BUGBUG: NAME = ALPHA *63(ALPHA / DIGIT / "_" ) + tr_STRING(Name, State, 2, 2). + +tr_PkgdName(Name, State) -> + %% BUGBUG: transform + %% BUGBUG: pkgdName = (NAME / "*") SLASH (ItemID / "*" ) + tr_OCTET_STRING(Name, State, 4, 4). + +%% When text encoding the protocol, the descriptors consist of session +%% descriptions as defined in SDP (RFC2327), except that the "s=", "t=" +%% and "o=" lines are optional. When multiple session descriptions are +%% provided in one descriptor, the "v=" lines are required as delimiters; +%% otherwise they are optional. Implementations shall accept session +%% descriptions that are fully conformant to RFC2327. When binary +%% encoding the protocol the descriptor consists of groups of properties +%% (tag-value pairs) as specified in Annex C. Each such group may +%% contain the parameters of a session description. +tr_opt_LocalRemoteDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = Groups}, + State) -> + #'LocalRemoteDescriptor'{propGrps = [tr_PropertyGroup(G, State) || G <- Groups]}. + +tr_PropertyGroup(Props, State) -> + [tr_PropertyGroupParm(P, State) || P <- Props]. + +tr_PropertyGroupParm(#'PropertyParm'{name = Name, + value = Value}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'PropertyParm'{name = resolve(property, Name, State, Constraint), + value = tr_OCTET_STRING(Value, State, 0, infinity)}. + +tr_PropertyParm(#'PropertyParm'{name = Name, + value = Value, + extraInfo = Extra}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'PropertyParm'{name = resolve(property, Name, State, Constraint), + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_opt_extraInfo(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_extraInfo({relation, Rel}, _State) -> + Rel2 = + case Rel of + greaterThan -> greaterThan; + smallerThan -> smallerThan; + unequalTo -> unequalTo + end, + {relation, Rel2}; +tr_opt_extraInfo({range, Range}, State) -> + Range2 = tr_bool(Range, State), + {range, Range2}; +tr_opt_extraInfo({sublist, Sub}, State) -> + Sub2 = tr_bool(Sub, State), + {sublist, Sub2}. + +tr_opt_TerminationStateDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TerminationStateDescriptor(#'TerminationStateDescriptor'{propertyParms = Props, + eventBufferControl = Control, + serviceState = Service}, + State) -> + #'TerminationStateDescriptor'{propertyParms = [tr_PropertyParm(P, State) || P <- Props], + eventBufferControl = tr_opt_EventBufferControl(Control, State), + serviceState = tr_opt_ServiceState(Service, State)}. + +tr_opt_EventBufferControl(Control, _State) -> + case Control of + asn1_NOVALUE -> asn1_NOVALUE; + off -> off; + lockStep -> lockStep + end. + +tr_opt_ServiceState(Service, _State) -> + case Service of + asn1_NOVALUE -> asn1_NOVALUE; + test -> test; + outOfSvc -> outOfSvc; + inSvc -> inSvc + end. + +tr_MuxDescriptor(#'MuxDescriptor'{muxType = Type, + termList = IdList}, + State) -> + #'MuxDescriptor'{muxType = tr_MuxType(Type, State), + termList = [tr_TerminationID(Id, State) || Id <- IdList]}. + +tr_MuxType(Type, _State) -> + case Type of + h221 -> h221; + h223 -> h223; + h226 -> h226; + v76 -> v76 + end. + +tr_opt_StreamID(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_StreamID(Id, State) -> + tr_StreamID(Id, State). + +tr_StreamID(Id, State) -> + tr_UINT16(Id, State). + +tr_EventsDescriptor(#'EventsDescriptor'{requestID = Id, + eventList = Events}, + State) -> + #'EventsDescriptor'{requestID = tr_opt_RequestID(Id, State), + eventList = [tr_RequestedEvent(E, State) || E <- Events]}. + +tr_RequestedEvent(#'RequestedEvent'{pkgdName = Name, + streamID = Id, + evParList = Parms, + eventAction = Actions}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'RequestedEvent'{pkgdName = resolve(event, Name, State, Constraint), + streamID = tr_opt_StreamID(Id, State), + eventAction = tr_opt_RequestedActions(Actions, State), + evParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + +tr_RegulatedEmbeddedDescriptor( + #'RegulatedEmbeddedDescriptor'{secondEvent = SE, + signalsDescriptor = SD}, State) -> + SE2 = tr_opt_SecondEventsDescriptor(SE, State), + SD2 = tr_opt_SignalsDescriptor(SD, State), + #'RegulatedEmbeddedDescriptor'{secondEvent = SE2, + signalsDescriptor = SD2}. + +tr_opt_NotifyBehaviour(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_NotifyBehaviour(NB, State) -> + tr_NotifyBehaviour(NB, State). + +tr_NotifyBehaviour({notifyImmediate, 'NULL'} = NB, _State) -> + NB; +tr_NotifyBehaviour({notifyRegulated = Tag, Val}, State) -> + {Tag, tr_RegulatedEmbeddedDescriptor(Val, State)}; +tr_NotifyBehaviour({neverNotify, 'NULL'} = NB, _State) -> + NB. + +tr_opt_RequestedActions(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_RequestedActions(#'RequestedActions'{keepActive = KA, + eventDM = DM, + secondEvent = SE, + signalsDescriptor = SD, + notifyBehaviour = NB, + resetEventsDescriptor = RSD}, + State) -> + KA2 = tr_opt_keepActive(KA, State), + DM2 = tr_opt_EventDM(DM, State), + SE2 = tr_opt_SecondEventsDescriptor(SE, State), + SD2 = tr_opt_SignalsDescriptor(SD, State), + NB2 = tr_opt_NotifyBehaviour(NB, State), + RSD2 = tr_opt_null(RSD, State), + #'RequestedActions'{keepActive = KA2, + eventDM = DM2, + secondEvent = SE2, + signalsDescriptor = SD2, + notifyBehaviour = NB2, + resetEventsDescriptor = RSD2}. + +tr_opt_keepActive(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_keepActive(Keep, State) -> + tr_bool(Keep, State). + +tr_opt_EventDM(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_EventDM({Tag, Val}, State) -> + Val2 = + case Tag of + digitMapName -> tr_DigitMapName(Val, State); + digitMapValue -> tr_DigitMapValue(Val, State) + end, + {Tag, Val2}. + +tr_opt_SecondEventsDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = Id, + eventList = Events}, + State) -> + #'SecondEventsDescriptor'{requestID = tr_RequestID(Id, State), %% IG v6 6.8 withdrawn + eventList = [tr_SecondRequestedEvent(E, State) || E <- Events]}. + +tr_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = Name, + streamID = Id, + evParList = Parms, + eventAction = Actions}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'SecondRequestedEvent'{pkgdName = resolve(event, Name, State, Constraint), + streamID = tr_opt_StreamID(Id, State), + eventAction = tr_opt_SecondRequestedActions(Actions, State), + evParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + + +tr_opt_SecondRequestedActions(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SecondRequestedActions( + #'SecondRequestedActions'{keepActive = KA, + eventDM = DM, + signalsDescriptor = SD, + notifyBehaviour = NB, + resetEventsDescriptor = RSD}, + State) -> + KA2 = tr_opt_keepActive(KA, State), + DM2 = tr_opt_EventDM(DM, State), + SD2 = tr_opt_SignalsDescriptor(SD, State), + NB2 = tr_opt_NotifyBehaviour(NB, State), + RSD2 = tr_opt_null(RSD, State), + #'SecondRequestedActions'{keepActive = KA2, + eventDM = DM2, + signalsDescriptor = SD2, + notifyBehaviour = NB2, + resetEventsDescriptor = RSD2}. + +tr_EventBufferDescriptor(EventSpecs, State) -> + [tr_EventSpec(ES, State) || ES <- EventSpecs]. + +tr_EventSpec(#'EventSpec'{eventName = Name, + streamID = Id, + eventParList = Parms}, + State) -> + #'EventSpec'{eventName = tr_EventName(Name, State), + streamID = tr_opt_StreamID(Id, State), + eventParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + +tr_opt_SignalsDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SignalsDescriptor(SigDesc, State) -> + tr_SignalsDescriptor(SigDesc, State). + +tr_SignalsDescriptor(SigDesc, State) when is_list(SigDesc) -> + [tr_SignalRequest(SigReq, State) || SigReq <- SigDesc]. + +tr_SignalRequest({Tag, Val}, State) -> + Val2 = + case Tag of + signal -> tr_Signal(Val, State); + seqSigList -> tr_SeqSigList(Val, State) + end, + {Tag, Val2}. + + +tr_SeqSigList(#'SeqSigList'{id = Id, + signalList = SigList}, + State) when is_list(SigList) -> + #'SeqSigList'{id = tr_UINT16(Id, State), + signalList = [tr_Signal(Sig, State) || Sig <- SigList]}. + +tr_Signal(#'Signal'{signalName = Name, + streamID = SID, + sigType = Type, + duration = Dur, + notifyCompletion = Compl, + keepActive = Keep, + sigParList = Parms, + direction = Dir, + requestID = RID, + intersigDelay = ID}, + State) -> + Name2 = tr_SignalName(Name, State), + SID2 = tr_opt_StreamID(SID, State), + Type2 = tr_opt_SignalType(Type, State), + Dur2 = tr_opt_UINT16(Dur, State), + Compl2 = tr_opt_NotifyCompletion(Compl, State), + Keep2 = tr_opt_keepActive(Keep, State), + Parms2 = [tr_SigParameter(P, Name, State) || P <- Parms], + Dir2 = tr_opt_SignalDirection(Dir, State), + RID2 = tr_opt_RequestID(RID, State), + ID2 = tr_opt_UINT16(ID, State), + #'Signal'{signalName = Name2, + streamID = SID2, + sigType = Type2, + duration = Dur2, + notifyCompletion = Compl2, + keepActive = Keep2, + sigParList = Parms2, + direction = Dir2, + requestID = RID2, + intersigDelay = ID2}. + +tr_opt_NotifyCompletion(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_NotifyCompletion(Items, State) when is_list(Items) -> + [tr_notifyCompletionItem(I, State) || I <- Items]. + +tr_notifyCompletionItem(Item, _State) -> + case Item of + onTimeOut -> onTimeOut; + onInterruptByEvent -> onInterruptByEvent; + onInterruptByNewSignalDescr -> onInterruptByNewSignalDescr; + otherReason -> otherReason; + onIteration -> onIteration + end. + +tr_opt_SignalType(asn1_NOVALUE = Type, _State) -> + Type; +tr_opt_SignalType(Type, _State) -> + case Type of + brief -> brief; + onOff -> onOff; + timeOut -> timeOut + end. + +tr_opt_SignalDirection(asn1_NOVALUE = SD, _State) -> + SD; +tr_opt_SignalDirection(SD, _State) -> + case SD of + internal -> internal; + external -> external; + both -> both + end. + +tr_SignalName(Name, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + resolve(signal, Name, State, Constraint). + +tr_SigParameter(#'SigParameter'{sigParameterName = ParName, + value = Value, + extraInfo = Extra}, + SigName, + State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + N = resolve({signal_parameter, SigName}, ParName, State, Constraint), + #'SigParameter'{sigParameterName = N, + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_opt_RequestID(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_RequestID(Id, State) -> + tr_RequestID(Id, State). + +tr_RequestID(Id, _State) when Id =:= ?megaco_all_request_id -> + ?megaco_all_request_id; +tr_RequestID(Id, State) -> + tr_UINT32(Id, State). + +tr_ModemDescriptor(_MD, _State) -> + deprecated. + +tr_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value}, + State) -> + #'DigitMapDescriptor'{digitMapName = tr_opt_DigitMapName(Name, State), + digitMapValue = tr_opt_DigitMapValue(Value, State)}. + +tr_opt_DigitMapName(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_DigitMapName(Name, State) -> + tr_DigitMapName(Name, State). + +tr_DigitMapName(Name, State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + resolve(dialplan, Name, State, Constraint). + +tr_opt_DigitMapValue(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_DigitMapValue(Value, State) -> + tr_DigitMapValue(Value, State). + +tr_DigitMapValue(#'DigitMapValue'{digitMapBody = Body, + startTimer = Start, + shortTimer = Short, + longTimer = Long}, + State) -> + #'DigitMapValue'{startTimer = tr_opt_timer(Start, State), + shortTimer = tr_opt_timer(Short, State), + longTimer = tr_opt_timer(Long, State), + digitMapBody = tr_STRING(Body, State)}. %% BUGBUG: digitMapBody not handled at all + +tr_opt_timer(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_timer(Timer, State) -> + tr_DIGIT(Timer, State, 0, 99). + +tr_ServiceChangeParm( + #'ServiceChangeParm'{serviceChangeMethod = Method, + serviceChangeAddress = Addr, + serviceChangeVersion = Version, + serviceChangeProfile = Profile, + serviceChangeReason = Reason, + serviceChangeDelay = Delay, + serviceChangeMgcId = MgcId, + timeStamp = Time, + serviceChangeInfo = Info, + serviceChangeIncompleteFlag = Incomplete}, + State) -> + Method2 = tr_ServiceChangeMethod(Method, State), + Addr2 = tr_opt_ServiceChangeAddress(Addr, State), + Version2 = tr_opt_serviceChangeVersion(Version, State), + Profile2 = tr_opt_ServiceChangeProfile(Profile, State), + Reason2 = tr_serviceChangeReason(Reason, State), + Delay2 = tr_opt_serviceChangeDelay(Delay, State), + MgcId2 = tr_opt_serviceChangeMgcId(MgcId, State), + Time2 = tr_opt_TimeNotation(Time, State), + Info2 = tr_opt_AuditDescriptor(Info, State), + Incomplete2 = tr_opt_null(Incomplete, State), + #'ServiceChangeParm'{serviceChangeMethod = Method2, + serviceChangeAddress = Addr2, + serviceChangeVersion = Version2, + serviceChangeProfile = Profile2, + serviceChangeReason = Reason2, + serviceChangeDelay = Delay2, + serviceChangeMgcId = MgcId2, + timeStamp = Time2, + serviceChangeInfo = Info2, + serviceChangeIncompleteFlag = Incomplete2}. + +tr_ServiceChangeMethod(Method, _State) -> + case Method of + failover -> failover; + forced -> forced; + graceful -> graceful; + restart -> restart; + disconnected -> disconnected; + handOff -> handOff + end. %% BUGBUG: extension + +tr_opt_ServiceChangeAddress(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ServiceChangeAddress({Tag, Val}, State) -> + Val2 = + case Tag of + portNumber -> tr_portNumber(Val, State); + ip4Address -> tr_IP4Address(Val, State); + ip6Address -> tr_IP6Address(Val, State); + domainName -> tr_DomainName(Val, State); + deviceName -> tr_PathName(Val, State); + mtpAddress -> tr_mtpAddress(Val, State) + end, + {Tag, Val2}. + +tr_opt_serviceChangeVersion(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeVersion(Version, State) -> + tr_version(Version, State). + +tr_opt_ServiceChangeProfile(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +%% Decode +tr_opt_ServiceChangeProfile({'ServiceChangeProfile', ProfileName}, State) -> + case string:tokens(ProfileName, "/") of + [Name0, Version0] -> + Name = tr_STRING(Name0, State, 1, 64), + Version = tr_version(list_to_integer(Version0), State), + #'ServiceChangeProfile'{profileName = Name, + version = Version} + end; +%% Encode +tr_opt_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = Name0, + version = Version0}, + State) -> + Name = tr_STRING(Name0, State, 1, 64), + Version = tr_version(Version0, State), + ProfileName = lists:flatten(io_lib:format("~s/~w", [Name, Version])), + {'ServiceChangeProfile', ProfileName}. + +tr_serviceChangeReason([_] = Reason, State) -> + tr_Value(Reason, State). + +tr_opt_serviceChangeDelay(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeDelay(Delay, State) -> + tr_UINT32(Delay, State). + +tr_opt_serviceChangeMgcId(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeMgcId(MgcId, State) -> + tr_MId(MgcId, State). + +tr_opt_portNumber(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_portNumber(Port, State) -> + tr_portNumber(Port, State). + +tr_portNumber(Port, State) when is_integer(Port) andalso (Port >= 0) -> + tr_UINT16(Port, State). + +tr_ServiceChangeResParm(#'ServiceChangeResParm'{serviceChangeMgcId = MgcId, + serviceChangeAddress = Addr, + serviceChangeVersion = Version, + serviceChangeProfile = Profile, + timeStamp = Time}, + State) -> + #'ServiceChangeResParm'{serviceChangeMgcId = tr_opt_serviceChangeMgcId(MgcId, State), + serviceChangeAddress = tr_opt_ServiceChangeAddress(Addr, State), + serviceChangeVersion = tr_opt_serviceChangeVersion(Version, State), + serviceChangeProfile = tr_opt_ServiceChangeProfile(Profile, State), + timeStamp = tr_opt_TimeNotation(Time, State)}. + +tr_PackagesDescriptor(Items, State) when is_list(Items) -> + [tr_PackagesItem(I, State) || I <- Items]. + +tr_PackagesItem(#'PackagesItem'{packageName = Name, + packageVersion = Version}, + State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + #'PackagesItem'{packageName = resolve(package, Name, State, Constraint), + packageVersion = tr_UINT16(Version, State)}. + +tr_opt_StatisticsDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_StatisticsDescriptor(Parms, State) -> + tr_StatisticsDescriptor(Parms, State). + +tr_StatisticsDescriptor(Parms, State) when is_list(Parms) -> + [tr_StatisticsParameter(P, State) || P <- Parms]. + +tr_StatisticsParameter(#'StatisticsParameter'{statName = Name, + statValue = Value}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'StatisticsParameter'{statName = resolve(statistics, Name, State, Constraint), + statValue = tr_opt_Value(Value, State)}. + +tr_opt_TimeNotation(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TimeNotation(#'TimeNotation'{date = Date, + time = Time}, + State) -> + #'TimeNotation'{date = tr_STRING(Date, State, 8, 8), % "yyyymmdd" + time = tr_STRING(Time, State, 8, 8)}.% "hhmmssss" + +%% BUGBUG: Does not verify that string must contain at least one char +%% BUGBUG: This violation of the is required in order to comply with +%% BUGBUG: the dd/ce ds parameter that may possibly be empty. + +tr_opt_Value(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_Value(Value, State) -> + tr_Value(Value, State). + +tr_Value(Strings, _State) when is_list(Strings) -> + [[Char || Char <- String] || String <- Strings]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Encode an octet string, escape } by \ if necessary +tr_OCTET_STRING(String, _State, Min, Max) when is_list(String) -> + verify_count(length(String), Min, Max), + String. + +tr_QUOTED_STRING(String, _State) when is_list(String) -> + verify_count(length(String), 1, infinity), + String. + +%% The internal format of hex digits is a list of octets +%% Min and Max means #hexDigits +%% Leading zeros are prepended in order to fulfill Min +tr_HEXDIG(Octets, _State, Min, Max) when is_list(Octets) -> + verify_count(length(Octets), Min, Max), + Octets. + +tr_DIGIT(Val, State, Min, Max) -> + tr_integer(Val, State, Min, Max). + +tr_STRING(String, _State) when is_list(String) -> + String. + +tr_STRING(String, _State, Min, Max) when is_list(String) -> + verify_count(length(String), Min, Max), + String. + +tr_opt_UINT16(Val, State) -> + tr_opt_integer(Val, State, 0, 65535). + +tr_UINT16(Val, State) -> + tr_integer(Val, State, 0, 65535). + +tr_UINT32(Val, State) -> + tr_integer(Val, State, 0, 4294967295). + +tr_opt_integer(asn1_NOVALUE, _State, _Min, _Max) -> + asn1_NOVALUE; +tr_opt_integer(Int, State, Min, Max) -> + tr_integer(Int, State, Min, Max). + +tr_integer(Int, _State, Min, Max) -> + verify_count(Int, Min, Max), + Int. + +%% Verify that Count is within the range of Min and Max +verify_count(Count, Min, Max) -> + if + is_integer(Count) -> + if + is_integer(Min) andalso (Count >= Min) -> + if + is_integer(Max) andalso (Count =< Max) -> + Count; + Max =:= infinity -> + Count; + true -> + error({count_too_large, Count, Max}) + end; + true -> + error({count_too_small, Count, Min}) + end; + true -> + error({count_not_an_integer, Count}) + end. + + +%% ------------------------------------------------------------------- + +error(Reason) -> + erlang:error(Reason). + + diff --git a/lib/megaco/src/binary/megaco_binary_transformer_v1.erl b/lib/megaco/src/binary/megaco_binary_transformer_v1.erl new file mode 100644 index 0000000000..7236c0a9e1 --- /dev/null +++ b/lib/megaco/src/binary/megaco_binary_transformer_v1.erl @@ -0,0 +1,1261 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Transform internal form of Megaco/H.248 messages +%%---------------------------------------------------------------------- + +-module(megaco_binary_transformer_v1). + +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). + +-export([tr_message/3, tr_transaction/3]). + +-define(DEFAULT_NAME_RESOLVER,megaco_binary_name_resolver_v1). +-define(error(R), erlang:error({error, R})). + +-record(state, {mode, % verify | encode | decode + resolver_module, % + resolver_options}). + +resolve(Type, Item, State, Constraint) -> + case State#state.mode of + verify -> + Item; + encode -> + %% i("resolve(encode) -> encode: ~p",[Item]), + Mod = State#state.resolver_module, + Opt = State#state.resolver_options, + EncodedItem = Mod:encode_name(Opt, Type, Item), + %% i("resolve -> verify contraint for ~p",[EncodedItem]), + verify_constraint(EncodedItem, Constraint); + decode -> + %% i("resolve(decode) -> verify contraint for ~p",[Item]), + DecodedItem = verify_constraint(Item, Constraint), + Mod = State#state.resolver_module, + Opt = State#state.resolver_options, + %% i("resolve(decode) -> decode: ~p",[DecodedItem]), + Mod:decode_name(Opt, Type, DecodedItem) + end. + +verify_constraint(Item, valid) -> + Item; +verify_constraint(Item, Constraint) when is_function(Constraint) -> + Constraint(Item). + +tr_message(MegaMsg, Mode, Config) -> + case Config of + [native] -> + MegaMsg; + [verify] -> + State = #state{mode = verify}, + tr_MegacoMessage(MegaMsg, State); + [] -> + State = #state{mode = Mode, + resolver_module = ?DEFAULT_NAME_RESOLVER, + resolver_options = [8, 8, 8]}, + tr_MegacoMessage(MegaMsg, State); + [{binary_name_resolver, {Module, Options}}] when is_atom(Module) -> + State = #state{mode = Mode, + resolver_module = Module, + resolver_options = Options}, + tr_MegacoMessage(MegaMsg, State) + end. + +tr_transaction(Trans, Mode, Config) -> + case Config of + [native] -> + Trans; + [verify] -> + State = #state{mode = verify}, + tr_Transaction(Trans, State); + [] -> + State = #state{mode = Mode, + resolver_module = ?DEFAULT_NAME_RESOLVER, + resolver_options = [8, 8, 8]}, + tr_Transaction(Trans, State); + [{binary_name_resolver, {Module, Options}}] when is_atom(Module) -> + State = #state{mode = Mode, + resolver_module = Module, + resolver_options = Options}, + tr_Transaction(Trans, State) + end. + +tr_MegacoMessage(#'MegacoMessage'{authHeader = Auth, + mess = Mess}, + State) -> + #'MegacoMessage'{authHeader = tr_opt_AuthenticationHeader(Auth, State), + mess = tr_Message(Mess, State)}. + +tr_opt_AuthenticationHeader(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_AuthenticationHeader(#'AuthenticationHeader'{secParmIndex = SPI, + seqNum = SN, + ad = AuthData}, + State) -> + #'AuthenticationHeader'{secParmIndex = tr_SecurityParmIndex(SPI, State), + seqNum = tr_SequenceNum(SN, State), + ad = tr_AuthData(AuthData, State)}. + +tr_SecurityParmIndex(SPI, State) -> + tr_HEXDIG(SPI, State, 4, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_SequenceNum(SN, State) -> + tr_HEXDIG(SN, State, 4, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_AuthData(AuthData, State) -> + tr_HEXDIG(AuthData, State, 12, 32). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_Message(#'Message'{version = Version, + mId = MID, + messageBody = Body}, + State) -> + #'Message'{version = tr_version(Version, State), + mId = tr_MId(MID, State), + messageBody = tr_Message_messageBody(Body, State)}. + +tr_version(Version, State) -> + tr_DIGIT(Version, State, 0, 99). + +tr_Message_messageBody({Tag, Val}, State) -> + Val2 = + case Tag of + messageError -> tr_ErrorDescriptor(Val, State); + transactions when is_list(Val) -> [tr_Transaction(T, State) || T <- Val] + end, + {Tag, Val2}. + +tr_MId({Tag, Val}, State) -> + Val2 = + case Tag of + ip4Address -> tr_IP4Address(Val, State); + ip6Address -> tr_IP6Address(Val, State); + domainName -> tr_DomainName(Val, State); + deviceName -> tr_PathName(Val, State); + mtpAddress -> tr_mtpAddress(Val, State) + end, + {Tag, Val2}. + +tr_mtpAddress(MtpAddr, State) -> + tr_OCTET_STRING(MtpAddr, State, 2, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_DomainName(#'DomainName'{name = Name, + portNumber = Port}, + State) -> + Domain = #'DomainName'{name = tr_STRING(Name, State), % BUGBUG: Mismatch between ASN.1 and ABNF + portNumber = tr_opt_portNumber(Port, State)}, + {domainName, Domain2} = resolve(mid, {domainName, Domain}, State, valid), + Domain2. + +tr_IP4Address(#'IP4Address'{address = [A1, A2, A3, A4], + portNumber = Port}, + State) -> + #'IP4Address'{address = [tr_V4hex(A1, State), + tr_V4hex(A2, State), + tr_V4hex(A3, State), + tr_V4hex(A4, State)], + portNumber = tr_opt_portNumber(Port, State)}. + +tr_V4hex(Val, State) -> + tr_DIGIT(Val, State, 0, 255). + +tr_IP6Address(_Val, _State) -> + ?error(ipv6_not_supported). %% BUGBUG: nyi + +tr_PathName(Path, State) -> + %% BUGBUG: ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" ) + %% BUGBUG: ["@" pathDomainName ] + Constraint = fun({deviceName, Item}) -> tr_STRING(Item, State, 1, 64) end, + resolve(mid, {deviceName, Path}, State, Constraint). + +tr_Transaction({Tag, Val}, State) -> + Val2 = + case Tag of + transactionRequest -> tr_TransactionRequest(Val, State); + transactionPending -> tr_TransactionPending(Val, State); + transactionReply -> tr_TransactionReply(Val, State); + transactionResponseAck -> [tr_TransactionAck(T, State) || T <- Val] + end, + {Tag, Val2}. + +tr_TransactionAck(#'TransactionAck'{firstAck = First, + lastAck = Last}, + State) -> + #'TransactionAck'{firstAck = tr_TransactionId(First, State), + lastAck = tr_opt_TransactionId(Last, State)}. + +tr_opt_TransactionId(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TransactionId(Id, State) -> + tr_TransactionId(Id, State). + +tr_TransactionId(Id, State) -> + tr_UINT32(Id, State). + +tr_TransactionRequest(#'TransactionRequest'{transactionId = Id, + actions = Actions}, + State) when is_list(Actions) -> + + #'TransactionRequest'{transactionId = tr_TransactionId(Id, State), + actions = [tr_ActionRequest(ActReq, State) || ActReq <- Actions]}. + +tr_TransactionPending(#'TransactionPending'{transactionId = Id}, + State) -> + #'TransactionPending'{transactionId = tr_TransactionId(Id, State)}. + +tr_TransactionReply(#'TransactionReply'{transactionId = Id, + immAckRequired = ImmAck, + transactionResult = TransRes}, + State) -> + #'TransactionReply'{transactionId = tr_TransactionId(Id, State), + immAckRequired = tr_opt_null(ImmAck, State), + transactionResult = tr_TransactionReply_transactionResult(TransRes, State)}. + +tr_opt_null(asn1_NOVALUE, _State) -> asn1_NOVALUE; +tr_opt_null('NULL', _State) -> 'NULL'. + +tr_TransactionReply_transactionResult({Tag, Val}, State) -> + Val2 = + case Tag of + transactionError -> + tr_ErrorDescriptor(Val, State); + actionReplies when is_list(Val) andalso (Val =/= []) -> + [tr_ActionReply(ActRep, State) || ActRep <- Val] + end, + {Tag, Val2}. + +tr_opt_ErrorDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ErrorDescriptor(ErrDesc, State) -> + tr_ErrorDescriptor(ErrDesc, State). + +tr_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code, + errorText = Text}, + State) -> + #'ErrorDescriptor'{errorCode = tr_ErrorCode(Code, State), + errorText = tr_opt_ErrorText(Text, State)}. + +tr_ErrorCode(Code, State) -> + tr_DIGIT(Code, State, 0, 999). + +tr_opt_ErrorText(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ErrorText(Text, State) -> + tr_QUOTED_STRING(Text, State). + +tr_ContextID(CtxId, State) -> + case CtxId of + ?megaco_all_context_id -> ?megaco_all_context_id; + ?megaco_null_context_id -> ?megaco_null_context_id; + ?megaco_choose_context_id -> ?megaco_choose_context_id; + Int when is_integer(Int) -> tr_UINT32(Int, State) + end. + +tr_ActionRequest(#'ActionRequest'{contextId = CtxId, + contextRequest = CtxReq, + contextAttrAuditReq = CtxAuditReq, + commandRequests = CmdReqList}, + State) -> + #'ActionRequest'{contextId = tr_ContextID(CtxId, State), + contextRequest = tr_opt_ContextRequest(CtxReq, State), + contextAttrAuditReq = tr_opt_ContextAttrAuditRequest(CtxAuditReq, State), + commandRequests = [tr_CommandRequest(CmdReq, State) || CmdReq <- CmdReqList]}. + +tr_ActionReply(#'ActionReply'{contextId = CtxId, + errorDescriptor = ErrDesc, + contextReply = CtxRep, + commandReply = CmdRepList}, + State) -> + CmdRepList2 = [tr_CommandReply(CmdRep, State) || CmdRep <- CmdRepList], + #'ActionReply'{contextId = tr_ContextID(CtxId, State), + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State), + contextReply = tr_opt_ContextRequest(CtxRep, State), + commandReply = CmdRepList2}. + +tr_opt_ContextRequest(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ContextRequest(#'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = TopReqList}, + State) -> + Prio2 = + case Prio of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_integer(Prio, State, 0, 15) + end, + Em2 = + case Em of + asn1_NOVALUE -> asn1_NOVALUE; + false -> false; + true -> true + end, + TopReqList2 = + case TopReqList of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_TopologyRequest(TopReq, State) || + TopReq <- TopReqList] + end, + #'ContextRequest'{priority = Prio2, + emergency = Em2, + topologyReq = TopReqList2}. + +tr_opt_ContextAttrAuditRequest(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio}, + State) -> + #'ContextAttrAuditRequest'{topology = tr_opt_null(Top, State), + emergency = tr_opt_null(Em, State), + priority = tr_opt_null(Prio, State)}. + +tr_CommandRequest(#'CommandRequest'{command = Cmd, + optional = Opt, + wildcardReturn = Wild}, + State) -> + #'CommandRequest'{optional = tr_opt_null(Opt, State), + wildcardReturn = tr_opt_null(Wild, State), + command = tr_Command(Cmd, State)}. + +tr_Command({Tag, Val}, State) -> + Val2 = + case Tag of + addReq -> tr_AmmRequest(Val, State); + moveReq -> tr_AmmRequest(Val, State); + modReq -> tr_AmmRequest(Val, State); + subtractReq -> tr_SubtractRequest(Val, State); + auditCapRequest -> tr_AuditRequest(Val, State); + auditValueRequest -> tr_AuditRequest(Val, State); + notifyReq -> tr_NotifyRequest(Val, State); + serviceChangeReq -> tr_ServiceChangeRequest(Val, State) + end, + {Tag, Val2}. + +tr_CommandReply({Tag, Val}, State) -> + Val2 = + case Tag of + addReply -> tr_AmmsReply(Val, State); + moveReply -> tr_AmmsReply(Val, State); + modReply -> tr_AmmsReply(Val, State); + subtractReply -> tr_AmmsReply(Val, State); + auditCapReply -> tr_AuditReply(Val, State); + auditValueReply -> tr_AuditReply(Val, State); + notifyReply -> tr_NotifyReply(Val, State); + serviceChangeReply -> tr_ServiceChangeReply(Val, State) + end, + {Tag, Val2}. + +tr_TopologyRequest(#'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = Dir}, + State) -> + Dir2 = + case Dir of + bothway -> bothway; + isolate -> isolate; + oneway -> oneway + end, + #'TopologyRequest'{terminationFrom = tr_TerminationID(From, State), + terminationTo = tr_TerminationID(To, State), + topologyDirection = Dir2}. + +tr_AmmRequest(#'AmmRequest'{terminationID = IdList, + descriptors = DescList}, + State) -> + #'AmmRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + descriptors = [tr_ammDescriptor(Desc, State) || + Desc <- DescList]}. + +tr_ammDescriptor({Tag, Desc}, State) -> + Desc2 = + case Tag of + mediaDescriptor -> tr_MediaDescriptor(Desc, State); + modemDescriptor -> tr_ModemDescriptor(Desc, State); + muxDescriptor -> tr_MuxDescriptor(Desc, State); + eventsDescriptor -> tr_EventsDescriptor(Desc, State); + eventBufferDescriptor -> tr_EventBufferDescriptor(Desc, State); + signalsDescriptor -> tr_SignalsDescriptor(Desc, State); + digitMapDescriptor -> tr_DigitMapDescriptor(Desc, State); + auditDescriptor -> tr_AuditDescriptor(Desc, State) + end, + {Tag, Desc2}. + +tr_AmmsReply(#'AmmsReply'{terminationID = IdList, + terminationAudit = TermAudit}, + State) -> + TermAudit2 = + case TermAudit of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_TerminationAudit(TermAudit, State) + end, + #'AmmsReply'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + terminationAudit = TermAudit2}. + +tr_SubtractRequest(#'SubtractRequest'{terminationID = IdList, + auditDescriptor = Desc}, + State) -> + #'SubtractRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + auditDescriptor = tr_opt_AuditDescriptor(Desc, State)}. + +tr_AuditRequest(#'AuditRequest'{terminationID = Id, + auditDescriptor = Desc}, + State) -> + #'AuditRequest'{terminationID = tr_TerminationID(Id, State), + auditDescriptor = tr_AuditDescriptor(Desc, State)}. + +%% auditReply = (AuditValueToken / AuditCapToken ) +%% ( contextTerminationAudit / auditOther) +%% auditOther = EQUAL TerminationID LBRKT +%% terminationAudit RBRKT +%% terminationAudit = auditReturnParameter *(COMMA auditReturnParameter) +%% +%% contextTerminationAudit = EQUAL CtxToken ( terminationIDList / +%% LBRKT errorDescriptor RBRKT ) + +tr_AuditReply({Tag, Val}, State) -> + Val2 = + case Tag of + contextAuditResult -> + [tr_TerminationID(Id, State) || Id <- Val]; + error -> + tr_ErrorDescriptor(Val, State); + auditResult -> + tr_AuditResult(Val, State) + end, + {Tag, Val2}. + +tr_AuditResult(#'AuditResult'{terminationID = Id, + terminationAuditResult = AuditRes}, + State) -> + #'AuditResult'{terminationID = tr_TerminationID(Id, State), + terminationAuditResult = tr_TerminationAudit(AuditRes, State)}. + +tr_opt_AuditDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_AuditDescriptor(Desc, State) -> + tr_AuditDescriptor(Desc, State). + +tr_AuditDescriptor(#'AuditDescriptor'{auditToken = Tokens}, + State) -> + Tokens2 = + case Tokens of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_auditItem(Token, State) || Token <- Tokens] + end, + #'AuditDescriptor'{auditToken = Tokens2}. + +tr_auditItem(Token, _State) -> + case Token of + muxToken -> muxToken; + modemToken -> modemToken; + mediaToken -> mediaToken; + eventsToken -> eventsToken; + signalsToken -> signalsToken; + digitMapToken -> digitMapToken; + statsToken -> statsToken; + observedEventsToken -> observedEventsToken; + packagesToken -> packagesToken; + eventBufferToken -> eventBufferToken + end. + +tr_TerminationAudit(ParmList, State) when is_list(ParmList) -> + [tr_AuditReturnParameter(Parm, State) || Parm <- ParmList]. + +tr_AuditReturnParameter({Tag, Val}, State) -> + Val2 = + case Tag of + errorDescriptor -> + tr_ErrorDescriptor(Val, State); + mediaDescriptor -> + tr_MediaDescriptor(Val, State); + modemDescriptor -> + tr_ModemDescriptor(Val, State); + muxDescriptor -> + tr_MuxDescriptor(Val, State); + eventsDescriptor -> + tr_EventsDescriptor(Val, State); + eventBufferDescriptor -> + tr_EventBufferDescriptor(Val, State); + signalsDescriptor -> + tr_SignalsDescriptor(Val, State); + digitMapDescriptor -> + tr_DigitMapDescriptor(Val, State); + observedEventsDescriptor -> + tr_ObservedEventsDescriptor(Val, State); + statisticsDescriptor -> + tr_StatisticsDescriptor(Val, State); + packagesDescriptor -> + tr_PackagesDescriptor(Val, State); + emptyDescriptors -> + tr_EmptyDescriptors(Val, State) + end, + {Tag, Val2}. + +tr_EmptyDescriptors(#'AuditDescriptor'{auditToken = Tokens}, + State) -> + case Tokens of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_auditItem(Token, State) || Token <- Tokens] + end. + +tr_NotifyRequest(#'NotifyRequest'{terminationID = IdList, + observedEventsDescriptor = ObsDesc, + errorDescriptor = ErrDesc}, + State) -> + %% BUGBUG: Mismatch between ASN.1 and ABNF + %% BUGBUG: The following ought to be a 'choice' + #'NotifyRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + observedEventsDescriptor = tr_ObservedEventsDescriptor(ObsDesc, State), + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State)}. + +tr_NotifyReply(#'NotifyReply'{terminationID = IdList, + errorDescriptor = ErrDesc}, + State) -> + #'NotifyReply'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State)}. + +tr_ObservedEventsDescriptor(#'ObservedEventsDescriptor'{requestId = Id, + observedEventLst = Events}, + State) when is_list(Events) -> + #'ObservedEventsDescriptor'{requestId = tr_RequestID(Id, State), + observedEventLst = [tr_ObservedEvent(E, State) || E <- Events]}. + +%% ;time per event, because it might be buffered +%% observedEvent = [ TimeStamp LWSP COLON] LWSP +%% pkgdName [ LBRKT observedEventParameter +%% *(COMMA observedEventParameter) RBRKT ] +%% +%% ;at-most-once eventStream, every eventParameterName at most once +%% observedEventParameter = eventStream / eventOther + +tr_ObservedEvent(#'ObservedEvent'{eventName = Name, + streamID = Id, + eventParList = Parms, + timeNotation = Time}, + State) -> + #'ObservedEvent'{eventName = tr_EventName(Name, State), + streamID = tr_opt_StreamID(Id, State), + eventParList = [tr_EventParameter(P, Name, State) || P <- Parms], + timeNotation = tr_opt_TimeNotation(Time, State)}. + +tr_EventName(Name, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + resolve(event, Name, State, Constraint). + +tr_EventParameter(#'EventParameter'{eventParameterName = ParName, + value = Value, + extraInfo = Extra}, + EventName, + State) -> + %% BUGBUG: event parameter name + Constraint = fun(Item) -> tr_Name(Item, State) end, + N = resolve({event_parameter, EventName}, ParName, State, Constraint), + #'EventParameter'{eventParameterName = N, + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_ServiceChangeRequest(#'ServiceChangeRequest'{terminationID = IdList, + serviceChangeParms = Parms}, + State) -> + #'ServiceChangeRequest'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + serviceChangeParms = tr_ServiceChangeParm(Parms, State)}. + +%% serviceChangeReply = ServiceChangeToken EQUAL TerminationID +%% [LBRKT (errorDescriptor / +%% serviceChangeReplyDescriptor) RBRKT] +%% serviceChangeReplyDescriptor = ServicesToken LBRKT +%% servChgReplyParm *(COMMA servChgReplyParm) RBRKT +%% +%% ;at-most-once. Version is REQUIRED on first ServiceChange response +%% servChgReplyParm = (serviceChangeAddress / serviceChangeMgcId / +%% serviceChangeProfile / serviceChangeVersion ) +tr_ServiceChangeReply(#'ServiceChangeReply'{terminationID = IdList, + serviceChangeResult = Res}, + State) -> + #'ServiceChangeReply'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + serviceChangeResult = tr_ServiceChangeResult(Res, State)}. + +tr_ServiceChangeResult({Tag, Val}, State) -> + Val2 = + case Tag of + errorDescriptor -> tr_ErrorDescriptor(Val, State); + serviceChangeResParms -> tr_ServiceChangeResParm(Val, State) + end, + {Tag, Val2}. + +%% TerminationID = "ROOT" / pathNAME / "$" / "*" +%% ; Total length of pathNAME must not exceed 64 chars. +%% pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" ) +%% ["@" pathDomainName ] + +tr_TerminationID(TermId, State) when State#state.mode =/= verify -> + resolve(term_id, TermId, State, valid); +tr_TerminationID(#'TerminationID'{wildcard = Wild, + id = Id}, + _State) -> + #'TerminationID'{wildcard = Wild, + id = Id}; +tr_TerminationID(#megaco_term_id{contains_wildcards = IsWild, + id = Id}, + State) -> + #megaco_term_id{contains_wildcards = tr_bool(IsWild, State), + id = [tr_term_id_component(Sub, State) || Sub <- Id]}. + +tr_opt_bool(asn1_NOVALUE, _State) -> asn1_NOVALUE; +tr_opt_bool(Bool, State) -> tr_bool(Bool, State). + +tr_bool(true, _State) -> true; +tr_bool(false, _State) -> false. + +tr_term_id_component(Sub, _State) -> + case Sub of + all -> all; + choose -> choose; + Char when is_integer(Char) -> Char + end. + +%% mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT +%% ; at-most-once per item +%% ; and either streamParm or streamDescriptor but not both +%% mediaParm = (streamParm / streamDescriptor / +%% terminationStateDescriptor) +%% ; at-most-once +%% streamParm = ( localDescriptor / remoteDescriptor / +%% localControlDescriptor ) +%% streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm +%% *(COMMA streamParm) RBRKT +tr_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TermState, + streams = Streams}, + State) -> + #'MediaDescriptor'{termStateDescr = tr_opt_TerminationStateDescriptor(TermState, State), + streams = tr_opt_streams(Streams, State)}. + +tr_opt_streams(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_streams({Tag, Val}, State) -> + Val2 = + case Tag of + oneStream -> tr_StreamParms(Val, State); + multiStream -> [tr_StreamDescriptor(SD, State) || SD <- Val] + end, + {Tag, Val2}. + +tr_StreamParms(#'StreamParms'{localControlDescriptor = Control, + localDescriptor = Local, + remoteDescriptor = Remote}, + State) -> + #'StreamParms'{localControlDescriptor = tr_opt_LocalControlDescriptor(Control, State), + localDescriptor = tr_opt_LocalRemoteDescriptor(Local, State), + remoteDescriptor = tr_opt_LocalRemoteDescriptor(Remote, State)}. + +tr_StreamDescriptor(#'StreamDescriptor'{streamID = Id, + streamParms = Parms}, + State) -> + #'StreamDescriptor'{streamID = tr_StreamID(Id, State), + streamParms = tr_StreamParms(Parms, State)}. + +%% localControlDescriptor = LocalControlToken LBRKT localParm +%% *(COMMA localParm) RBRKT +%% +%% ; at-most-once per item +%% localParm = ( streamMode / propertyParm / +%% reservedValueMode / reservedGroupMode ) +%% reservedValueMode = ReservedValueToken EQUAL ( "ON" / "OFF" ) +%% reservedGroupMode = ReservedGroupToken EQUAL ( "ON" / "OFF" ) +%% +%% reservedMode = ReservedToken EQUAL ( "ON" / "OFF" ) +%% +%% streamMode = ModeToken EQUAL streamModes +tr_opt_LocalControlDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = Mode, + reserveGroup = Group, + reserveValue = Value, + propertyParms = Props}, + State) -> + #'LocalControlDescriptor'{streamMode = tr_opt_StreamMode(Mode, State), + reserveGroup = tr_opt_bool(Group, State), + reserveValue = tr_opt_bool(Value, State), + propertyParms = [tr_PropertyParm(P, State) || P <- Props]}. + +tr_opt_StreamMode(Mode, _State) -> + case Mode of + asn1_NOVALUE -> asn1_NOVALUE; + sendOnly -> sendOnly; + recvOnly -> recvOnly; + sendRecv -> sendRecv; + inactive -> inactive; + loopBack -> loopBack + end. + +tr_Name(Name, State) -> + %% BUGBUG: transform + %% BUGBUG: NAME = ALPHA *63(ALPHA / DIGIT / "_" ) + tr_STRING(Name, State, 2, 2). + +tr_PkgdName(Name, State) -> + %% BUGBUG: transform + %% BUGBUG: pkgdName = (NAME / "*") SLASH (ItemID / "*" ) + tr_OCTET_STRING(Name, State, 4, 4). + +%% When text encoding the protocol, the descriptors consist of session +%% descriptions as defined in SDP (RFC2327), except that the "s=", "t=" +%% and "o=" lines are optional. When multiple session descriptions are +%% provided in one descriptor, the "v=" lines are required as delimiters; +%% otherwise they are optional. Implementations shall accept session +%% descriptions that are fully conformant to RFC2327. When binary +%% encoding the protocol the descriptor consists of groups of properties +%% (tag-value pairs) as specified in Annex C. Each such group may +%% contain the parameters of a session description. +tr_opt_LocalRemoteDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = Groups}, + State) -> + #'LocalRemoteDescriptor'{propGrps = [tr_PropertyGroup(G, State) || G <- Groups]}. + +tr_PropertyGroup(Props, State) -> + [tr_PropertyGroupParm(P, State) || P <- Props]. + +tr_PropertyGroupParm(#'PropertyParm'{name = Name, + value = Value}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'PropertyParm'{name = resolve(property, Name, State, Constraint), + value = tr_OCTET_STRING(Value, State, 0, infinity)}. + +tr_PropertyParm(#'PropertyParm'{name = Name, + value = Value, + extraInfo = Extra}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'PropertyParm'{name = resolve(property, Name, State, Constraint), + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_opt_extraInfo(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_extraInfo({relation, Rel}, _State) -> + Rel2 = + case Rel of + greaterThan -> greaterThan; + smallerThan -> smallerThan; + unequalTo -> unequalTo + end, + {relation, Rel2}; +tr_opt_extraInfo({range, Range}, State) -> + Range2 = tr_bool(Range, State), + {range, Range2}; +tr_opt_extraInfo({sublist, Sub}, State) -> + Sub2 = tr_bool(Sub, State), + {sublist, Sub2}. + +tr_opt_TerminationStateDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TerminationStateDescriptor(#'TerminationStateDescriptor'{propertyParms = Props, + eventBufferControl = Control, + serviceState = Service}, + State) -> + #'TerminationStateDescriptor'{propertyParms = [tr_PropertyParm(P, State) || P <- Props], + eventBufferControl = tr_opt_EventBufferControl(Control, State), + serviceState = tr_opt_ServiceState(Service, State)}. + +tr_opt_EventBufferControl(Control, _State) -> + case Control of + asn1_NOVALUE -> asn1_NOVALUE; + off -> off; + lockStep -> lockStep + end. + +tr_opt_ServiceState(Service, _State) -> + case Service of + asn1_NOVALUE -> asn1_NOVALUE; + test -> test; + outOfSvc -> outOfSvc; + inSvc -> inSvc + end. + +tr_MuxDescriptor(#'MuxDescriptor'{muxType = Type, + termList = IdList}, + State) -> + #'MuxDescriptor'{muxType = tr_MuxType(Type, State), + termList = [tr_TerminationID(Id, State) || Id <- IdList]}. + +tr_MuxType(Type, _State) -> + case Type of + h221 -> h221; + h223 -> h223; + h226 -> h226; + v76 -> v76 + end. + +tr_opt_StreamID(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_StreamID(Id, State) -> + tr_StreamID(Id, State). + +tr_StreamID(Id, State) -> + tr_UINT16(Id, State). + +tr_EventsDescriptor(#'EventsDescriptor'{requestID = Id, + eventList = Events}, + State) -> + #'EventsDescriptor'{requestID = tr_opt_RequestID(Id, State), + eventList = [tr_RequestedEvent(E, State) || E <- Events]}. + +tr_RequestedEvent(#'RequestedEvent'{pkgdName = Name, + streamID = Id, + evParList = Parms, + eventAction = Actions}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'RequestedEvent'{pkgdName = resolve(event, Name, State, Constraint), + streamID = tr_opt_StreamID(Id, State), + eventAction = tr_opt_RequestedActions(Actions, State), + evParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + +tr_opt_RequestedActions(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_RequestedActions(#'RequestedActions'{keepActive = Keep, + eventDM = DM, + secondEvent = Event, + signalsDescriptor = SigDesc}, + State) -> + #'RequestedActions'{keepActive = tr_opt_keepActive(Keep, State), + eventDM = tr_opt_EventDM(DM, State), + secondEvent = tr_opt_SecondEventsDescriptor(Event, State), + signalsDescriptor = tr_opt_SignalsDescriptor(SigDesc, State)}. + +tr_opt_keepActive(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_keepActive(Keep, State) -> + tr_bool(Keep, State). + +tr_opt_EventDM(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_EventDM({Tag, Val}, State) -> + Val2 = + case Tag of + digitMapName -> tr_DigitMapName(Val, State); + digitMapValue -> tr_DigitMapValue(Val, State) + end, + {Tag, Val2}. + +tr_opt_SecondEventsDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = Id, + eventList = Events}, + State) -> + #'SecondEventsDescriptor'{requestID = tr_RequestID(Id, State), %% IG v6 6.8 withdrawn + eventList = [tr_SecondRequestedEvent(E, State) || E <- Events]}. + +tr_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = Name, + streamID = Id, + evParList = Parms, + eventAction = Actions}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'SecondRequestedEvent'{pkgdName = resolve(event, Name, State, Constraint), + streamID = tr_opt_StreamID(Id, State), + eventAction = tr_opt_SecondRequestedActions(Actions, State), + evParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + + +tr_opt_SecondRequestedActions(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SecondRequestedActions(#'SecondRequestedActions'{keepActive = Keep, + eventDM = DM, + signalsDescriptor = SigDesc}, + State) -> + #'SecondRequestedActions'{keepActive = tr_opt_keepActive(Keep, State), + eventDM = tr_opt_EventDM(DM, State), + signalsDescriptor = tr_opt_SignalsDescriptor(SigDesc, State)}. + +tr_EventBufferDescriptor(EventSpecs, State) -> + [tr_EventSpec(ES, State) || ES <- EventSpecs]. + +tr_EventSpec(#'EventSpec'{eventName = Name, + streamID = Id, + eventParList = Parms}, + State) -> + #'EventSpec'{eventName = tr_EventName(Name, State), + streamID = tr_opt_StreamID(Id, State), + eventParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + +tr_opt_SignalsDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SignalsDescriptor(SigDesc, State) -> + tr_SignalsDescriptor(SigDesc, State). + +tr_SignalsDescriptor(SigDesc, State) when is_list(SigDesc) -> + [tr_SignalRequest(SigReq, State) || SigReq <- SigDesc]. + +tr_SignalRequest({Tag, Val}, State) -> + Val2 = + case Tag of + signal -> tr_Signal(Val, State); + seqSigList -> tr_SeqSigList(Val, State) + end, + {Tag, Val2}. + + +tr_SeqSigList(#'SeqSigList'{id = Id, + signalList = SigList}, + State) when is_list(SigList) -> + #'SeqSigList'{id = tr_UINT16(Id, State), + signalList = [tr_Signal(Sig, State) || Sig <- SigList]}. + +tr_Signal(#'Signal'{signalName = Name, + streamID = Id, + sigType = Type, + duration = Dur, + notifyCompletion = Compl, + keepActive = Keep, + sigParList = Parms}, + State) -> + #'Signal'{signalName = tr_SignalName(Name, State), + streamID = tr_opt_StreamID(Id, State), + sigType = tr_opt_SignalType(Type, State), + duration = tr_opt_duration(Dur, State), + notifyCompletion = tr_opt_NotifyCompletion(Compl, State), + keepActive = tr_opt_keepActive(Keep, State), + sigParList = [tr_SigParameter(P, Name, State) || P <- Parms]}. + +tr_opt_duration(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_duration(Dur, State) -> + tr_UINT16(Dur, State). + +tr_opt_NotifyCompletion(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_NotifyCompletion(Items, State) when is_list(Items) -> + [tr_notifyCompletionItem(I, State) || I <- Items]. + +tr_notifyCompletionItem(Item, _State) -> + case Item of + onTimeOut -> onTimeOut; + onInterruptByEvent -> onInterruptByEvent; + onInterruptByNewSignalDescr -> onInterruptByNewSignalDescr; + otherReason -> otherReason + end. + +tr_opt_SignalType(Type, _State) -> + case Type of + asn1_NOVALUE -> asn1_NOVALUE; + brief -> brief; + onOff -> onOff; + timeOut -> timeOut + end. + +tr_SignalName(Name, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + resolve(signal, Name, State, Constraint). + +tr_SigParameter(#'SigParameter'{sigParameterName = ParName, + value = Value, + extraInfo = Extra}, + SigName, + State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + N = resolve({signal_parameter, SigName}, ParName, State, Constraint), + #'SigParameter'{sigParameterName = N, + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_opt_RequestID(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_RequestID(Id, State) -> + tr_RequestID(Id, State). + +tr_RequestID(Id, _State) when Id =:= ?megaco_all_request_id -> + ?megaco_all_request_id; +tr_RequestID(Id, State) -> + tr_UINT32(Id, State). + +tr_ModemDescriptor(#'ModemDescriptor'{mtl = Types, + mpl = Props}, + State) when is_list(Types) andalso is_list(Props) -> + %% BUGBUG: Does not handle extensionParameter + #'ModemDescriptor'{mtl = [tr_ModemType(T, State) || T <- Types], + mpl = [tr_PropertyParm(P, State) || P <- Props]}. + +tr_ModemType(Type, _State) -> + %% BUGBUG: Does not handle extensionParameter + case Type of + v18 -> v18; + v22 -> v22; + v22bis -> v22bis; + v32 -> v32; + v32bis -> v32bis; + v34 -> v34; + v90 -> v90; + v91 -> v91; + synchISDN -> synchISDN + end. + +tr_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value}, + State) -> + #'DigitMapDescriptor'{digitMapName = tr_opt_DigitMapName(Name, State), + digitMapValue = tr_opt_DigitMapValue(Value, State)}. + +tr_opt_DigitMapName(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_DigitMapName(Name, State) -> + tr_DigitMapName(Name, State). + +tr_DigitMapName(Name, State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + resolve(dialplan, Name, State, Constraint). + +tr_opt_DigitMapValue(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_DigitMapValue(Value, State) -> + tr_DigitMapValue(Value, State). + +tr_DigitMapValue(#'DigitMapValue'{digitMapBody = Body, + startTimer = Start, + shortTimer = Short, + longTimer = Long}, + State) -> + #'DigitMapValue'{startTimer = tr_opt_timer(Start, State), + shortTimer = tr_opt_timer(Short, State), + longTimer = tr_opt_timer(Long, State), + digitMapBody = tr_STRING(Body, State)}. %% BUGBUG: digitMapBody not handled at all + +tr_opt_timer(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_timer(Timer, State) -> + tr_DIGIT(Timer, State, 0, 99). + +tr_ServiceChangeParm(#'ServiceChangeParm'{serviceChangeMethod = Method, + serviceChangeAddress = Addr, + serviceChangeVersion = Version, + serviceChangeProfile = Profile, + serviceChangeReason = Reason, + serviceChangeDelay = Delay, + serviceChangeMgcId = MgcId, + timeStamp = Time}, + State) -> + #'ServiceChangeParm'{serviceChangeMethod = tr_ServiceChangeMethod(Method, State), + serviceChangeAddress = tr_opt_ServiceChangeAddress(Addr, State), + serviceChangeVersion = tr_opt_serviceChangeVersion(Version, State), + serviceChangeProfile = tr_opt_ServiceChangeProfile(Profile, State), + serviceChangeReason = tr_serviceChangeReason(Reason, State), + serviceChangeDelay = tr_opt_serviceChangeDelay(Delay, State), + serviceChangeMgcId = tr_opt_serviceChangeMgcId(MgcId, State), + timeStamp = tr_opt_TimeNotation(Time, State)}. + +tr_ServiceChangeMethod(Method, _State) -> + case Method of + failover -> failover; + forced -> forced; + graceful -> graceful; + restart -> restart; + disconnected -> disconnected; + handOff -> handOff + end. %% BUGBUG: extension + +tr_opt_ServiceChangeAddress(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ServiceChangeAddress({Tag, Val}, State) -> + Val2 = + case Tag of + portNumber -> tr_portNumber(Val, State); + ip4Address -> tr_IP4Address(Val, State); + ip6Address -> tr_IP6Address(Val, State); + domainName -> tr_DomainName(Val, State); + deviceName -> tr_PathName(Val, State); + mtpAddress -> tr_mtpAddress(Val, State) + end, + {Tag, Val2}. + +tr_opt_serviceChangeVersion(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeVersion(Version, State) -> + tr_version(Version, State). + +tr_opt_ServiceChangeProfile(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +%% Decode +tr_opt_ServiceChangeProfile({'ServiceChangeProfile', ProfileName}, State) -> + case string:tokens(ProfileName, "/") of + [Name0, Version0] -> + Name = tr_STRING(Name0, State, 1, 64), + Version = tr_version(list_to_integer(Version0), State), + #'ServiceChangeProfile'{profileName = Name, + version = Version} + end; +%% Encode +tr_opt_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = Name0, + version = Version0}, + State) -> + Name = tr_STRING(Name0, State, 1, 64), + Version = tr_version(Version0, State), + ProfileName = lists:flatten(io_lib:format("~s/~w", [Name, Version])), + {'ServiceChangeProfile', ProfileName}. + +tr_serviceChangeReason([_] = Reason, State) -> + tr_Value(Reason, State). + +tr_opt_serviceChangeDelay(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeDelay(Delay, State) -> + tr_UINT32(Delay, State). + +tr_opt_serviceChangeMgcId(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeMgcId(MgcId, State) -> + tr_MId(MgcId, State). + +tr_opt_portNumber(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_portNumber(Port, State) -> + tr_portNumber(Port, State). + +tr_portNumber(Port, State) when is_integer(Port) andalso (Port >= 0) -> + tr_UINT16(Port, State). + +tr_ServiceChangeResParm(#'ServiceChangeResParm'{serviceChangeMgcId = MgcId, + serviceChangeAddress = Addr, + serviceChangeVersion = Version, + serviceChangeProfile = Profile, + timeStamp = Time}, + State) -> + #'ServiceChangeResParm'{serviceChangeMgcId = tr_opt_serviceChangeMgcId(MgcId, State), + serviceChangeAddress = tr_opt_ServiceChangeAddress(Addr, State), + serviceChangeVersion = tr_opt_serviceChangeVersion(Version, State), + serviceChangeProfile = tr_opt_ServiceChangeProfile(Profile, State), + timeStamp = tr_opt_TimeNotation(Time, State)}. + +tr_PackagesDescriptor(Items, State) when is_list(Items) -> + [tr_PackagesItem(I, State) || I <- Items]. + +tr_PackagesItem(#'PackagesItem'{packageName = Name, + packageVersion = Version}, + State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + #'PackagesItem'{packageName = resolve(package, Name, State, Constraint), + packageVersion = tr_UINT16(Version, State)}. + +tr_StatisticsDescriptor(Parms, State) when is_list(Parms) -> + [tr_StatisticsParameter(P, State) || P <- Parms]. + +tr_StatisticsParameter(#'StatisticsParameter'{statName = Name, + statValue = Value}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'StatisticsParameter'{statName = resolve(statistics, Name, State, Constraint), + statValue = tr_opt_Value(Value, State)}. + +tr_opt_TimeNotation(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TimeNotation(#'TimeNotation'{date = Date, + time = Time}, + State) -> + #'TimeNotation'{date = tr_STRING(Date, State, 8, 8), % "yyyymmdd" + time = tr_STRING(Time, State, 8, 8)}.% "hhmmssss" + +%% BUGBUG: Does not verify that string must contain at least one char +%% BUGBUG: This violation of the is required in order to comply with +%% BUGBUG: the dd/ce ds parameter that may possibly be empty. + +tr_opt_Value(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_Value(Value, State) -> + tr_Value(Value, State). + +tr_Value(Strings, _State) when is_list(Strings) -> + [[Char || Char <- String] || String <- Strings]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Encode an octet string, escape } by \ if necessary +tr_OCTET_STRING(String, _State, Min, Max) when is_list(String) -> + verify_count(length(String), Min, Max), + String. + +tr_QUOTED_STRING(String, _State) when is_list(String) -> + verify_count(length(String), 1, infinity), + String. + +%% The internal format of hex digits is a list of octets +%% Min and Max means #hexDigits +%% Leading zeros are prepended in order to fulfill Min +tr_HEXDIG(Octets, _State, Min, Max) when is_list(Octets) -> + verify_count(length(Octets), Min, Max), + Octets. + +tr_DIGIT(Val, State, Min, Max) -> + tr_integer(Val, State, Min, Max). + +tr_STRING(String, _State) when is_list(String) -> + String. + +tr_STRING(String, _State, Min, Max) when is_list(String) -> + verify_count(length(String), Min, Max), + String. + +tr_UINT16(Val, State) -> + tr_integer(Val, State, 0, 65535). + +tr_UINT32(Val, State) -> + tr_integer(Val, State, 0, 4294967295). + +tr_integer(Int, _State, Min, Max) -> + verify_count(Int, Min, Max), + Int. + +%% Verify that Count is within the range of Min and Max +verify_count(Count, Min, Max) -> + if + is_integer(Count) -> + if + is_integer(Min) andalso (Count >= Min) -> + if + is_integer(Max) andalso (Count =< Max) -> + Count; + Max =:= infinity -> + Count; + true -> + ?error({count_too_large, Count, Max}) + end; + true -> + ?error({count_too_small, Count, Min}) + end; + true -> + ?error({count_not_an_integer, Count}) + end. + + +% i(F,A) -> +% %% i(true,F,A). +% i(get(dbg),F,A). + +% i(true,F,A) -> +% S1 = io_lib:format("TRANSF-v1: " ++ F ++ "~n",A), +% S2 = lists:flatten(S1), +% io:format("~s",[S2]); +% i(_,_F,_A) -> +% ok. diff --git a/lib/megaco/src/binary/megaco_binary_transformer_v2.erl b/lib/megaco/src/binary/megaco_binary_transformer_v2.erl new file mode 100644 index 0000000000..686e384a29 --- /dev/null +++ b/lib/megaco/src/binary/megaco_binary_transformer_v2.erl @@ -0,0 +1,1544 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Transform internal form of Megaco/H.248 messages +%%---------------------------------------------------------------------- + +-module(megaco_binary_transformer_v2). + +-include_lib("megaco/include/megaco.hrl"). +%% -include_lib("megaco/include/megaco_message.hrl"). +-include_lib("megaco/include/megaco_message_v2.hrl"). + +-export([tr_message/3, tr_transaction/3]). + +-define(DEFAULT_NAME_RESOLVER,megaco_binary_name_resolver_v2). +-define(error(R), erlang:error({error, R})). + +-record(state, {mode, % verify | encode | decode + resolver_module, % + resolver_options}). + +resolve(Type, Item, State, Constraint) -> + case State#state.mode of + verify -> + Item; + encode -> + %% i("resolve(encode) -> encode: ~p",[Item]), + Mod = State#state.resolver_module, + Opt = State#state.resolver_options, + EncodedItem = Mod:encode_name(Opt, Type, Item), + %% i("resolve -> verify contraint for ~p",[EncodedItem]), + verify_constraint(EncodedItem, Constraint); + decode -> + %% i("resolve(decode) -> verify contraint for ~p",[Item]), + DecodedItem = verify_constraint(Item, Constraint), + Mod = State#state.resolver_module, + Opt = State#state.resolver_options, + %% i("resolve(decode) -> decode: ~p",[DecodedItem]), + Mod:decode_name(Opt, Type, DecodedItem) + end. + +verify_constraint(Item, valid) -> + Item; +verify_constraint(Item, Constraint) when is_function(Constraint) -> + Constraint(Item). + +tr_message(MegaMsg, Mode, Config) -> + case Config of + [native] -> + MegaMsg; + [verify] -> + State = #state{mode = verify}, + tr_MegacoMessage(MegaMsg, State); + [] -> + State = #state{mode = Mode, + resolver_module = ?DEFAULT_NAME_RESOLVER, + resolver_options = [8, 8, 8]}, + tr_MegacoMessage(MegaMsg, State); + [{binary_name_resolver, {Module, Options}}] when is_atom(Module) -> + State = #state{mode = Mode, + resolver_module = Module, + resolver_options = Options}, + tr_MegacoMessage(MegaMsg, State) + end. + +tr_transaction(Trans, Mode, Config) -> + case Config of + [native] -> + Trans; + [verify] -> + State = #state{mode = verify}, + tr_Transaction(Trans, State); + [] -> + State = #state{mode = Mode, + resolver_module = ?DEFAULT_NAME_RESOLVER, + resolver_options = [8, 8, 8]}, + tr_Transaction(Trans, State); + [{binary_name_resolver, {Module, Options}}] when is_atom(Module) -> + State = #state{mode = Mode, + resolver_module = Module, + resolver_options = Options}, + tr_Transaction(Trans, State) + end. + +tr_MegacoMessage(#'MegacoMessage'{authHeader = Auth, + mess = Mess}, + State) -> +% i("tr_MegacoMessage -> entry with" +% "~n Auth: ~p" +% "~n Mess: ~p" +% "~n State: ~p", [Auth, Mess, State]), + #'MegacoMessage'{authHeader = tr_opt_AuthenticationHeader(Auth, State), + mess = tr_Message(Mess, State)}. + +tr_opt_AuthenticationHeader(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_AuthenticationHeader(#'AuthenticationHeader'{secParmIndex = SPI, + seqNum = SN, + ad = AuthData}, + State) -> + #'AuthenticationHeader'{secParmIndex = tr_SecurityParmIndex(SPI, State), + seqNum = tr_SequenceNum(SN, State), + ad = tr_AuthData(AuthData, State)}. + +tr_SecurityParmIndex(SPI, State) -> + tr_HEXDIG(SPI, State, 4, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_SequenceNum(SN, State) -> + tr_HEXDIG(SN, State, 4, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_AuthData(AuthData, State) -> + tr_HEXDIG(AuthData, State, 12, 32). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_Message(#'Message'{version = Version, + mId = MID, + messageBody = Body}, + State) -> + #'Message'{version = tr_version(Version, State), + mId = tr_MId(MID, State), + messageBody = tr_Message_messageBody(Body, State)}. + +tr_version(Version, State) -> + tr_DIGIT(Version, State, 0, 99). + +tr_Message_messageBody({Tag, Val}, State) -> + Val2 = + case Tag of + messageError -> tr_ErrorDescriptor(Val, State); + transactions when is_list(Val) -> [tr_Transaction(T, State) || T <- Val] + end, + {Tag, Val2}. + +tr_MId({Tag, Val}, State) -> + Val2 = + case Tag of + ip4Address -> tr_IP4Address(Val, State); + ip6Address -> tr_IP6Address(Val, State); + domainName -> tr_DomainName(Val, State); + deviceName -> tr_PathName(Val, State); + mtpAddress -> tr_mtpAddress(Val, State) + end, + {Tag, Val2}. + +tr_mtpAddress(MtpAddr, State) -> + tr_OCTET_STRING(MtpAddr, State, 2, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_DomainName(#'DomainName'{name = Name, + portNumber = Port}, + State) -> + Domain = #'DomainName'{name = tr_STRING(Name, State), % BUGBUG: Mismatch between ASN.1 and ABNF + portNumber = tr_opt_portNumber(Port, State)}, + {domainName, Domain2} = resolve(mid, {domainName, Domain}, State, valid), + Domain2. + +tr_IP4Address(#'IP4Address'{address = [A1, A2, A3, A4], + portNumber = Port}, + State) -> + #'IP4Address'{address = [tr_V4hex(A1, State), + tr_V4hex(A2, State), + tr_V4hex(A3, State), + tr_V4hex(A4, State)], + portNumber = tr_opt_portNumber(Port, State)}. + +tr_V4hex(Val, State) -> + tr_DIGIT(Val, State, 0, 255). + +tr_IP6Address(_Val, _State) -> + ?error(ipv6_not_supported). %% BUGBUG: nyi + +tr_PathName(Path, State) -> + %% BUGBUG: ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" ) + %% BUGBUG: ["@" pathDomainName ] + Constraint = fun({deviceName, Item}) -> tr_STRING(Item, State, 1, 64) end, + resolve(mid, {deviceName, Path}, State, Constraint). + +tr_Transaction({Tag, Val}, State) -> + Val2 = + case Tag of + transactionRequest -> tr_TransactionRequest(Val, State); + transactionPending -> tr_TransactionPending(Val, State); + transactionReply -> tr_TransactionReply(Val, State); + transactionResponseAck -> [tr_TransactionAck(T, State) || T <- Val] + end, + {Tag, Val2}. + +tr_TransactionAck(#'TransactionAck'{firstAck = First, + lastAck = Last}, + State) -> + #'TransactionAck'{firstAck = tr_TransactionId(First, State), + lastAck = tr_opt_TransactionId(Last, State)}. + +tr_opt_TransactionId(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TransactionId(Id, State) -> + tr_TransactionId(Id, State). + +tr_TransactionId(Id, State) -> + tr_UINT32(Id, State). + +tr_TransactionRequest(#'TransactionRequest'{transactionId = Id, + actions = Actions}, + State) when is_list(Actions) -> + + #'TransactionRequest'{transactionId = tr_TransactionId(Id, State), + actions = [tr_ActionRequest(ActReq, State) || ActReq <- Actions]}. + +tr_TransactionPending(#'TransactionPending'{transactionId = Id}, + State) -> + #'TransactionPending'{transactionId = tr_TransactionId(Id, State)}. + +tr_TransactionReply(#'TransactionReply'{transactionId = Id, + immAckRequired = ImmAck, + transactionResult = TransRes}, + State) -> + #'TransactionReply'{transactionId = tr_TransactionId(Id, State), + immAckRequired = tr_opt_null(ImmAck, State), + transactionResult = tr_TransactionReply_transactionResult(TransRes, State)}. + +tr_opt_null(asn1_NOVALUE, _State) -> asn1_NOVALUE; +tr_opt_null('NULL', _State) -> 'NULL'. + +tr_TransactionReply_transactionResult({Tag, Val}, State) -> + Val2 = + case Tag of + transactionError -> + tr_ErrorDescriptor(Val, State); + actionReplies when is_list(Val) andalso (Val =/= []) -> + [tr_ActionReply(ActRep, State) || ActRep <- Val] + end, + {Tag, Val2}. + +tr_opt_ErrorDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ErrorDescriptor(ErrDesc, State) -> + tr_ErrorDescriptor(ErrDesc, State). + +tr_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code, + errorText = Text}, + State) -> + #'ErrorDescriptor'{errorCode = tr_ErrorCode(Code, State), + errorText = tr_opt_ErrorText(Text, State)}. + +tr_ErrorCode(Code, State) -> + tr_DIGIT(Code, State, 0, 999). + +tr_opt_ErrorText(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ErrorText(Text, State) -> + tr_QUOTED_STRING(Text, State). + +tr_ContextID(CtxId, State) -> + case CtxId of + ?megaco_all_context_id -> ?megaco_all_context_id; + ?megaco_null_context_id -> ?megaco_null_context_id; + ?megaco_choose_context_id -> ?megaco_choose_context_id; + Int when is_integer(Int) -> tr_UINT32(Int, State) + end. + +tr_ActionRequest(#'ActionRequest'{contextId = CtxId, + contextRequest = CtxReq, + contextAttrAuditReq = CtxAuditReq, + commandRequests = CmdReqList}, + State) -> + #'ActionRequest'{contextId = tr_ContextID(CtxId, State), + contextRequest = tr_opt_ContextRequest(CtxReq, State), + contextAttrAuditReq = tr_opt_ContextAttrAuditRequest(CtxAuditReq, State), + commandRequests = [tr_CommandRequest(CmdReq, State) || CmdReq <- CmdReqList]}. + +tr_ActionReply(#'ActionReply'{contextId = CtxId, + errorDescriptor = ErrDesc, + contextReply = CtxRep, + commandReply = CmdRepList}, + State) -> + CmdRepList2 = [tr_CommandReply(CmdRep, State) || CmdRep <- CmdRepList], + #'ActionReply'{contextId = tr_ContextID(CtxId, State), + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State), + contextReply = tr_opt_ContextRequest(CtxRep, State), + commandReply = CmdRepList2}. + +tr_opt_ContextRequest(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ContextRequest(#'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = TopReqList}, + State) -> + Prio2 = + case Prio of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_integer(Prio, State, 0, 15) + end, + Em2 = + case Em of + asn1_NOVALUE -> asn1_NOVALUE; + false -> false; + true -> true + end, + TopReqList2 = + case TopReqList of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_TopologyRequest(TopReq, State) || + TopReq <- TopReqList] + end, + #'ContextRequest'{priority = Prio2, + emergency = Em2, + topologyReq = TopReqList2}. + +tr_opt_ContextAttrAuditRequest(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio}, + State) -> + #'ContextAttrAuditRequest'{topology = tr_opt_null(Top, State), + emergency = tr_opt_null(Em, State), + priority = tr_opt_null(Prio, State)}. + +tr_CommandRequest(#'CommandRequest'{command = Cmd, + optional = Opt, + wildcardReturn = Wild}, + State) -> + #'CommandRequest'{optional = tr_opt_null(Opt, State), + wildcardReturn = tr_opt_null(Wild, State), + command = tr_Command(Cmd, State)}. + +tr_Command({Tag, Val}, State) -> + Val2 = + case Tag of + addReq -> tr_AmmRequest(Val, State); + moveReq -> tr_AmmRequest(Val, State); + modReq -> tr_AmmRequest(Val, State); + subtractReq -> tr_SubtractRequest(Val, State); + auditCapRequest -> tr_AuditRequest(Val, State); + auditValueRequest -> tr_AuditRequest(Val, State); + notifyReq -> tr_NotifyRequest(Val, State); + serviceChangeReq -> tr_ServiceChangeRequest(Val, State) + end, + {Tag, Val2}. + +tr_CommandReply({Tag, Val}, State) -> + Val2 = + case Tag of + addReply -> tr_AmmsReply(Val, State); + moveReply -> tr_AmmsReply(Val, State); + modReply -> tr_AmmsReply(Val, State); + subtractReply -> tr_AmmsReply(Val, State); + auditCapReply -> tr_AuditReply(Val, State); + auditValueReply -> tr_AuditReply(Val, State); + notifyReply -> tr_NotifyReply(Val, State); + serviceChangeReply -> tr_ServiceChangeReply(Val, State) + end, + {Tag, Val2}. + +tr_TopologyRequest(#'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = Dir}, + State) -> + Dir2 = + case Dir of + bothway -> bothway; + isolate -> isolate; + oneway -> oneway + end, + #'TopologyRequest'{terminationFrom = tr_TerminationID(From, State), + terminationTo = tr_TerminationID(To, State), + topologyDirection = Dir2}. + +tr_AmmRequest(#'AmmRequest'{terminationID = IdList, + descriptors = DescList}, + State) -> + #'AmmRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + descriptors = tr_ammDescriptors(DescList, [], State)}. + +tr_ammDescriptors([], Acc, _State) -> + lists:reverse(Acc); +tr_ammDescriptors([Desc|Descs], Acc, State) -> + case tr_ammDescriptor(Desc, State) of + {_, deprecated} when State#state.mode =:= encode -> + ?error({deprecated, Desc}); + {_, deprecated} when State#state.mode =:= decode -> + %% SKIP + tr_ammDescriptors(Descs, Acc, State); + {_, deprecated} -> + %% SKIP + tr_ammDescriptors(Descs, Acc, State); + NewDesc -> + tr_ammDescriptors(Descs, [NewDesc|Acc], State) + end. + +tr_ammDescriptor({Tag, Desc}, State) -> + Desc2 = + case Tag of + mediaDescriptor -> tr_MediaDescriptor(Desc, State); + modemDescriptor -> tr_ModemDescriptor(Desc, State); + muxDescriptor -> tr_MuxDescriptor(Desc, State); + eventsDescriptor -> tr_EventsDescriptor(Desc, State); + eventBufferDescriptor -> tr_EventBufferDescriptor(Desc, State); + signalsDescriptor -> tr_SignalsDescriptor(Desc, State); + digitMapDescriptor -> tr_DigitMapDescriptor(Desc, State); + auditDescriptor -> tr_AuditDescriptor(Desc, State) + end, + {Tag, Desc2}. + +tr_AmmsReply(#'AmmsReply'{terminationID = IdList, + terminationAudit = TermAudit}, + State) -> + TermAudit2 = + case TermAudit of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_TerminationAudit(TermAudit, State) + end, + #'AmmsReply'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + terminationAudit = TermAudit2}. + +tr_SubtractRequest(#'SubtractRequest'{terminationID = IdList, + auditDescriptor = Desc}, + State) -> + #'SubtractRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + auditDescriptor = tr_opt_AuditDescriptor(Desc, State)}. + +tr_AuditRequest(#'AuditRequest'{terminationID = Id, + auditDescriptor = Desc}, + State) -> + #'AuditRequest'{terminationID = tr_TerminationID(Id, State), + auditDescriptor = tr_AuditDescriptor(Desc, State)}. + +%% auditReply = (AuditValueToken / AuditCapToken ) +%% ( contextTerminationAudit / auditOther) +%% auditOther = EQUAL TerminationID LBRKT +%% terminationAudit RBRKT +%% terminationAudit = auditReturnParameter *(COMMA auditReturnParameter) +%% +%% contextTerminationAudit = EQUAL CtxToken ( terminationIDList / +%% LBRKT errorDescriptor RBRKT ) + +tr_AuditReply({Tag, Val}, State) -> + Val2 = + case Tag of + contextAuditResult -> + [tr_TerminationID(Id, State) || Id <- Val]; + error -> + tr_ErrorDescriptor(Val, State); + auditResult -> + tr_AuditResult(Val, State) + end, + {Tag, Val2}. + +tr_AuditResult(#'AuditResult'{terminationID = Id, + terminationAuditResult = AuditRes}, + State) -> + #'AuditResult'{terminationID = tr_TerminationID(Id, State), + terminationAuditResult = tr_TerminationAudit(AuditRes, State)}. + +tr_opt_AuditDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_AuditDescriptor(Desc, State) -> + tr_AuditDescriptor(Desc, State). + +%% BUGBUG BUGBUG BUGBUG +%% With this construction it is possible to have both auditToken +%% and auditPropertyToken, but it is actually valid? +tr_AuditDescriptor(#'AuditDescriptor'{auditToken = Tokens, + auditPropertyToken = APTs}, + State) -> + Tokens2 = + case Tokens of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_auditItem(Token, State) || Token <- Tokens] + end, + %% v2 + APTs2 = + case APTs of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + [tr_indAuditParameter(APT, State) || APT <- APTs] + end, + #'AuditDescriptor'{auditToken = Tokens2, + auditPropertyToken = APTs2}. + +tr_auditItem(Token, _State) -> + case Token of + muxToken -> muxToken; + modemToken -> modemToken; + mediaToken -> mediaToken; + eventsToken -> eventsToken; + signalsToken -> signalsToken; + digitMapToken -> digitMapToken; + statsToken -> statsToken; + observedEventsToken -> observedEventsToken; + packagesToken -> packagesToken; + eventBufferToken -> eventBufferToken + end. + +%% --- v2 begin --- + +tr_indAuditParameter({Tag, Val}, State) -> + Val2 = + case Tag of + indAudMediaDescriptor -> + tr_indAudMediaDescriptor(Val, State); + indAudEventsDescriptor -> + tr_indAudEventsDescriptor(Val, State); + indAudSignalsDescriptor -> + tr_indAudSignalsDescriptor(Val, State); + indAudDigitMapDescriptor -> + tr_indAudDigitMapDescriptor(Val, State); + indAudEventBufferDescriptor -> + tr_indAudEventBufferDescriptor(Val, State); + indAudStatisticsDescriptor -> + tr_indAudStatisticsDescriptor(Val, State); + indAudPackagesDescriptor -> + tr_indAudPackagesDescriptor(Val, State) + end, + {Tag, Val2}. + + +%% - + +tr_indAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = S}, + State) -> + TSD2 = + case TSD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudTerminationStateDescriptor(TSD, State) + end, + S2 = + case S of + asn1_NOVALUE -> + asn1_NOVALUE; + {oneStream, OS} -> + {oneStream, tr_indAudStreamParms(OS, State)}; + {multiStream, MS} -> + MS2 = [tr_indAudStreamDescriptor(MS1, State) || MS1 <- MS], + {multiStream, MS2} + end, + #'IndAudMediaDescriptor'{termStateDescr = TSD2, + streams = S2}. + +tr_indAudTerminationStateDescriptor(Val, State) + when is_record(Val, 'IndAudTerminationStateDescriptor') -> + #'IndAudTerminationStateDescriptor'{propertyParms = Parms, + eventBufferControl = EBC, + serviceState = SS} = Val, + Parms2 = [tr_indAudPropertyParm(Parm, State) || Parm <- Parms], + EBC2 = tr_opt_null(EBC, State), + SS2 = tr_opt_null(SS, State), + #'IndAudTerminationStateDescriptor'{propertyParms = Parms2, + eventBufferControl = EBC2, + serviceState = SS2}. + + +tr_indAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD}, + State) -> + LCD2 = + case LCD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudLocalControlDescriptor(LCD, State) + end, + LD2 = + case LD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudLocalRemoteDescriptor(LD, State) + end, + RD2 = + case RD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudLocalRemoteDescriptor(RD, State) + end, + #'IndAudStreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2}. + +tr_indAudLocalControlDescriptor(Val, State) + when is_record(Val, 'IndAudLocalControlDescriptor') -> + #'IndAudLocalControlDescriptor'{streamMode = M, + reserveValue = V, + reserveGroup = G, + propertyParms = P} = Val, + M2 = tr_opt_null(M, State), + V2 = tr_opt_null(V, State), + G2 = tr_opt_null(G, State), + P2 = tr_indAudLocalControlDescriptor_propertyParms(P, State), + #'IndAudLocalControlDescriptor'{streamMode = M2, + reserveValue = V2, + reserveGroup = G2, + propertyParms = P2}. + +tr_indAudLocalControlDescriptor_propertyParms(Parms, State) + when is_list(Parms) andalso (length(Parms) > 0) -> + [tr_indAudPropertyParm(Parm, State) || Parm <- Parms]; +tr_indAudLocalControlDescriptor_propertyParms(asn1_NOVALUE, _State) -> + asn1_NOVALUE. + +tr_indAudLocalRemoteDescriptor(#'IndAudLocalRemoteDescriptor'{propGroupID = ID, + propGrps = Grps}, + State) -> + #'IndAudLocalRemoteDescriptor'{propGroupID = tr_opt_UINT16(ID, State), + propGrps = tr_indAudPropertyGroup(Grps, + State)}. + +tr_indAudPropertyGroup(Grps, State) when is_list(Grps) -> + [tr_indAudPropertyParm(Parm, State) || Parm <- Grps]. + +tr_indAudPropertyParm(#'IndAudPropertyParm'{name = Name0}, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(property, Name0, State, Constraint), + #'IndAudPropertyParm'{name = Name}. + + +tr_indAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = ID, + streamParms = Parms}, + State) -> + #'IndAudStreamDescriptor'{streamID = tr_StreamID(ID, State), + streamParms = tr_indAudStreamParms(Parms, + State)}. + + +%% - + +tr_indAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID, + pkgdName = Name0, + streamID = SID}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(event, Name0, State, Constraint), + #'IndAudEventsDescriptor'{requestID = tr_opt_RequestID(RID, State), + pkgdName = Name, + streamID = tr_opt_StreamID(SID, State)}. + + +%% - + +tr_indAudSignalsDescriptor({Tag, Val}, State) -> + case Tag of + signal -> + {signal, tr_indAudSignal(Val, State)}; + seqSigList -> + {seqSigList, tr_indAudSeqSigList(Val, State)} + end. + +tr_opt_indAudSignal(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_indAudSignal(Val, State) -> + tr_indAudSignal(Val, State). + +tr_indAudSignal(#'IndAudSignal'{signalName = Name0, + streamID = SID}, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(signal, Name0, State, Constraint), + #'IndAudSignal'{signalName = Name, + streamID = tr_opt_StreamID(SID, State)}. + +tr_indAudSeqSigList(#'IndAudSeqSigList'{id = ID, + signalList = SigList}, State) -> + #'IndAudSeqSigList'{id = tr_integer(ID, State, 0, 65535), + signalList = tr_opt_indAudSignal(SigList, State)}. + +%% - + +tr_indAudDigitMapDescriptor(#'IndAudDigitMapDescriptor'{digitMapName = Name}, + State) -> + #'IndAudDigitMapDescriptor'{digitMapName = + tr_opt_DigitMapName(Name, State)}. + + +%% - + +tr_indAudEventBufferDescriptor(#'IndAudEventBufferDescriptor'{eventName = N, + streamID = SID}, + State) -> +% i("tr_indAudEventBufferDescriptor -> entry with" +% "~n N: ~p" +% "~n SID: ~p", [N, SID]), + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(event, N, State, Constraint), +% i("tr_indAudEventBufferDescriptor -> entry with" +% "~n Name: ~p", [Name]), + #'IndAudEventBufferDescriptor'{eventName = Name, + streamID = tr_opt_StreamID(SID, State)}. + +%% - + +tr_indAudStatisticsDescriptor(#'IndAudStatisticsDescriptor'{statName = N}, + State) -> +% i("tr_indAudEventBufferDescriptor -> entry with" +% "~n N: ~p" +% "~n SID: ~p", [N, SID]), + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(statistics, N, State, Constraint), + #'IndAudStatisticsDescriptor'{statName = Name}. + + +%% - + +tr_indAudPackagesDescriptor(#'IndAudPackagesDescriptor'{packageName = N, + packageVersion = V}, + State) -> +% i("tr_indAudPackagesDescriptor -> entry with" +% "~n N: ~p" +% "~n V: ~p", [N, V]), + Constraint = fun(Item) -> tr_Name(Item, State) end, + Name = resolve(package, N, State, Constraint), +% i("tr_indAudPackagesDescriptor -> entry with" +% "~n Name: ~p", [Name]), + #'IndAudPackagesDescriptor'{packageName = Name, + packageVersion = tr_integer(V, State, 0, 99)}. + +%% -- v2 end -- + + +tr_TerminationAudit(ParmList, State) when is_list(ParmList) -> + do_tr_TerminationAudit(ParmList, [], State). + +do_tr_TerminationAudit([], Acc, _State) -> + lists:reverse(Acc); +do_tr_TerminationAudit([Parm|ParmList], Acc, State) -> + case tr_AuditReturnParameter(Parm, State) of + {_, deprecated} when State#state.mode =:= encode -> + ?error({deprecated, Parm}); + {_, deprecated} when State#state.mode =:= decode -> + %% SKIP + do_tr_TerminationAudit(ParmList, Acc, State); + {_, deprecated} -> + %% SKIP + do_tr_TerminationAudit(ParmList, Acc, State); + NewParm -> + do_tr_TerminationAudit(ParmList, [NewParm|Acc], State) + end. + +tr_AuditReturnParameter({Tag, Val}, State) -> + Val2 = + case Tag of + errorDescriptor -> + tr_ErrorDescriptor(Val, State); + mediaDescriptor -> + tr_MediaDescriptor(Val, State); + modemDescriptor -> + tr_ModemDescriptor(Val, State); + muxDescriptor -> + tr_MuxDescriptor(Val, State); + eventsDescriptor -> + tr_EventsDescriptor(Val, State); + eventBufferDescriptor -> + tr_EventBufferDescriptor(Val, State); + signalsDescriptor -> + tr_SignalsDescriptor(Val, State); + digitMapDescriptor -> + tr_DigitMapDescriptor(Val, State); + observedEventsDescriptor -> + tr_ObservedEventsDescriptor(Val, State); + statisticsDescriptor -> + tr_StatisticsDescriptor(Val, State); + packagesDescriptor -> + tr_PackagesDescriptor(Val, State); + emptyDescriptors -> + tr_EmptyDescriptors(Val, State) + end, + {Tag, Val2}. + +tr_EmptyDescriptors(#'AuditDescriptor'{auditToken = Tokens}, + State) -> + case Tokens of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_auditItem(Token, State) || Token <- Tokens] + end. + +tr_NotifyRequest(#'NotifyRequest'{terminationID = IdList, + observedEventsDescriptor = ObsDesc, + errorDescriptor = ErrDesc}, + State) -> + %% BUGBUG: Mismatch between ASN.1 and ABNF + %% BUGBUG: The following ought to be a 'choice' + #'NotifyRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + observedEventsDescriptor = tr_ObservedEventsDescriptor(ObsDesc, State), + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State)}. + +tr_NotifyReply(#'NotifyReply'{terminationID = IdList, + errorDescriptor = ErrDesc}, + State) -> + #'NotifyReply'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State)}. + +tr_ObservedEventsDescriptor(#'ObservedEventsDescriptor'{requestId = Id, + observedEventLst = Events}, + State) when is_list(Events) -> + #'ObservedEventsDescriptor'{requestId = tr_RequestID(Id, State), + observedEventLst = [tr_ObservedEvent(E, State) || E <- Events]}. + +%% ;time per event, because it might be buffered +%% observedEvent = [ TimeStamp LWSP COLON] LWSP +%% pkgdName [ LBRKT observedEventParameter +%% *(COMMA observedEventParameter) RBRKT ] +%% +%% ;at-most-once eventStream, every eventParameterName at most once +%% observedEventParameter = eventStream / eventOther + +tr_ObservedEvent(#'ObservedEvent'{eventName = Name, + streamID = Id, + eventParList = Parms, + timeNotation = Time}, + State) -> + #'ObservedEvent'{eventName = tr_EventName(Name, State), + streamID = tr_opt_StreamID(Id, State), + eventParList = [tr_EventParameter(P, Name, State) || P <- Parms], + timeNotation = tr_opt_TimeNotation(Time, State)}. + +tr_EventName(Name, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + resolve(event, Name, State, Constraint). + +tr_EventParameter(#'EventParameter'{eventParameterName = ParName, + value = Value, + extraInfo = Extra}, + EventName, + State) -> + %% BUGBUG: event parameter name + Constraint = fun(Item) -> tr_Name(Item, State) end, + N = resolve({event_parameter, EventName}, ParName, State, Constraint), + #'EventParameter'{eventParameterName = N, + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_ServiceChangeRequest(#'ServiceChangeRequest'{terminationID = IdList, + serviceChangeParms = Parms}, + State) -> + #'ServiceChangeRequest'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + serviceChangeParms = tr_ServiceChangeParm(Parms, State)}. + +%% serviceChangeReply = ServiceChangeToken EQUAL TerminationID +%% [LBRKT (errorDescriptor / +%% serviceChangeReplyDescriptor) RBRKT] +%% serviceChangeReplyDescriptor = ServicesToken LBRKT +%% servChgReplyParm *(COMMA servChgReplyParm) RBRKT +%% +%% ;at-most-once. Version is REQUIRED on first ServiceChange response +%% servChgReplyParm = (serviceChangeAddress / serviceChangeMgcId / +%% serviceChangeProfile / serviceChangeVersion ) +tr_ServiceChangeReply(#'ServiceChangeReply'{terminationID = IdList, + serviceChangeResult = Res}, + State) -> + #'ServiceChangeReply'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + serviceChangeResult = tr_ServiceChangeResult(Res, State)}. + +tr_ServiceChangeResult({Tag, Val}, State) -> + Val2 = + case Tag of + errorDescriptor -> tr_ErrorDescriptor(Val, State); + serviceChangeResParms -> tr_ServiceChangeResParm(Val, State) + end, + {Tag, Val2}. + +%% TerminationID = "ROOT" / pathNAME / "$" / "*" +%% ; Total length of pathNAME must not exceed 64 chars. +%% pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" ) +%% ["@" pathDomainName ] + +tr_TerminationID(TermId, State) when State#state.mode =/= verify -> + resolve(term_id, TermId, State, valid); +tr_TerminationID(#'TerminationID'{wildcard = Wild, + id = Id}, + _State) -> + #'TerminationID'{wildcard = Wild, + id = Id}; +tr_TerminationID(#megaco_term_id{contains_wildcards = IsWild, + id = Id}, + State) -> + #megaco_term_id{contains_wildcards = tr_bool(IsWild, State), + id = [tr_term_id_component(Sub, State) || Sub <- Id]}. + +tr_opt_bool(asn1_NOVALUE, _State) -> asn1_NOVALUE; +tr_opt_bool(Bool, State) -> tr_bool(Bool, State). + +tr_bool(true, _State) -> true; +tr_bool(false, _State) -> false. + +tr_term_id_component(Sub, _State) -> + case Sub of + all -> all; + choose -> choose; + Char when is_integer(Char) -> Char + end. + +%% mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT +%% ; at-most-once per item +%% ; and either streamParm or streamDescriptor but not both +%% mediaParm = (streamParm / streamDescriptor / +%% terminationStateDescriptor) +%% ; at-most-once +%% streamParm = ( localDescriptor / remoteDescriptor / +%% localControlDescriptor ) +%% streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm +%% *(COMMA streamParm) RBRKT +tr_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TermState, + streams = Streams}, + State) -> + #'MediaDescriptor'{termStateDescr = tr_opt_TerminationStateDescriptor(TermState, State), + streams = tr_opt_streams(Streams, State)}. + +tr_opt_streams(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_streams({Tag, Val}, State) -> + Val2 = + case Tag of + oneStream -> tr_StreamParms(Val, State); + multiStream -> [tr_StreamDescriptor(SD, State) || SD <- Val] + end, + {Tag, Val2}. + +tr_StreamParms(#'StreamParms'{localControlDescriptor = Control, + localDescriptor = Local, + remoteDescriptor = Remote}, + State) -> + #'StreamParms'{localControlDescriptor = tr_opt_LocalControlDescriptor(Control, State), + localDescriptor = tr_opt_LocalRemoteDescriptor(Local, State), + remoteDescriptor = tr_opt_LocalRemoteDescriptor(Remote, State)}. + +tr_StreamDescriptor(#'StreamDescriptor'{streamID = Id, + streamParms = Parms}, + State) -> + #'StreamDescriptor'{streamID = tr_StreamID(Id, State), + streamParms = tr_StreamParms(Parms, State)}. + +%% localControlDescriptor = LocalControlToken LBRKT localParm +%% *(COMMA localParm) RBRKT +%% +%% ; at-most-once per item +%% localParm = ( streamMode / propertyParm / +%% reservedValueMode / reservedGroupMode ) +%% reservedValueMode = ReservedValueToken EQUAL ( "ON" / "OFF" ) +%% reservedGroupMode = ReservedGroupToken EQUAL ( "ON" / "OFF" ) +%% +%% reservedMode = ReservedToken EQUAL ( "ON" / "OFF" ) +%% +%% streamMode = ModeToken EQUAL streamModes +tr_opt_LocalControlDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = Mode, + reserveGroup = Group, + reserveValue = Value, + propertyParms = Props}, + State) -> + #'LocalControlDescriptor'{streamMode = tr_opt_StreamMode(Mode, State), + reserveGroup = tr_opt_bool(Group, State), + reserveValue = tr_opt_bool(Value, State), + propertyParms = [tr_PropertyParm(P, State) || P <- Props]}. + +tr_opt_StreamMode(Mode, _State) -> + case Mode of + asn1_NOVALUE -> asn1_NOVALUE; + sendOnly -> sendOnly; + recvOnly -> recvOnly; + sendRecv -> sendRecv; + inactive -> inactive; + loopBack -> loopBack + end. + +tr_Name(Name, State) -> + %% BUGBUG: transform + %% BUGBUG: NAME = ALPHA *63(ALPHA / DIGIT / "_" ) + tr_STRING(Name, State, 2, 2). + +tr_PkgdName(Name, State) -> + %% BUGBUG: transform + %% BUGBUG: pkgdName = (NAME / "*") SLASH (ItemID / "*" ) + tr_OCTET_STRING(Name, State, 4, 4). + +%% When text encoding the protocol, the descriptors consist of session +%% descriptions as defined in SDP (RFC2327), except that the "s=", "t=" +%% and "o=" lines are optional. When multiple session descriptions are +%% provided in one descriptor, the "v=" lines are required as delimiters; +%% otherwise they are optional. Implementations shall accept session +%% descriptions that are fully conformant to RFC2327. When binary +%% encoding the protocol the descriptor consists of groups of properties +%% (tag-value pairs) as specified in Annex C. Each such group may +%% contain the parameters of a session description. +tr_opt_LocalRemoteDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = Groups}, + State) -> + #'LocalRemoteDescriptor'{propGrps = [tr_PropertyGroup(G, State) || G <- Groups]}. + +tr_PropertyGroup(Props, State) -> + [tr_PropertyGroupParm(P, State) || P <- Props]. + +tr_PropertyGroupParm(#'PropertyParm'{name = Name, + value = Value}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'PropertyParm'{name = resolve(property, Name, State, Constraint), + value = tr_OCTET_STRING(Value, State, 0, infinity)}. + +tr_PropertyParm(#'PropertyParm'{name = Name, + value = Value, + extraInfo = Extra}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'PropertyParm'{name = resolve(property, Name, State, Constraint), + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_opt_extraInfo(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_extraInfo({relation, Rel}, _State) -> + Rel2 = + case Rel of + greaterThan -> greaterThan; + smallerThan -> smallerThan; + unequalTo -> unequalTo + end, + {relation, Rel2}; +tr_opt_extraInfo({range, Range}, State) -> + Range2 = tr_bool(Range, State), + {range, Range2}; +tr_opt_extraInfo({sublist, Sub}, State) -> + Sub2 = tr_bool(Sub, State), + {sublist, Sub2}. + +tr_opt_TerminationStateDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TerminationStateDescriptor(#'TerminationStateDescriptor'{propertyParms = Props, + eventBufferControl = Control, + serviceState = Service}, + State) -> + #'TerminationStateDescriptor'{propertyParms = [tr_PropertyParm(P, State) || P <- Props], + eventBufferControl = tr_opt_EventBufferControl(Control, State), + serviceState = tr_opt_ServiceState(Service, State)}. + +tr_opt_EventBufferControl(Control, _State) -> + case Control of + asn1_NOVALUE -> asn1_NOVALUE; + off -> off; + lockStep -> lockStep + end. + +tr_opt_ServiceState(Service, _State) -> + case Service of + asn1_NOVALUE -> asn1_NOVALUE; + test -> test; + outOfSvc -> outOfSvc; + inSvc -> inSvc + end. + +tr_MuxDescriptor(#'MuxDescriptor'{muxType = Type, + termList = IdList}, + State) -> + #'MuxDescriptor'{muxType = tr_MuxType(Type, State), + termList = [tr_TerminationID(Id, State) || Id <- IdList]}. + +tr_MuxType(Type, _State) -> + case Type of + h221 -> h221; + h223 -> h223; + h226 -> h226; + v76 -> v76 + end. + +tr_opt_StreamID(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_StreamID(Id, State) -> + tr_StreamID(Id, State). + +tr_StreamID(Id, State) -> + tr_UINT16(Id, State). + +tr_EventsDescriptor(#'EventsDescriptor'{requestID = Id, + eventList = Events}, + State) -> + #'EventsDescriptor'{requestID = tr_opt_RequestID(Id, State), + eventList = [tr_RequestedEvent(E, State) || E <- Events]}. + +tr_RequestedEvent(#'RequestedEvent'{pkgdName = Name, + streamID = Id, + evParList = Parms, + eventAction = Actions}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'RequestedEvent'{pkgdName = resolve(event, Name, State, Constraint), + streamID = tr_opt_StreamID(Id, State), + eventAction = tr_opt_RequestedActions(Actions, State), + evParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + +tr_opt_RequestedActions(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_RequestedActions(#'RequestedActions'{keepActive = Keep, + eventDM = DM, + secondEvent = Event, + signalsDescriptor = SigDesc}, + State) -> + #'RequestedActions'{keepActive = tr_opt_keepActive(Keep, State), + eventDM = tr_opt_EventDM(DM, State), + secondEvent = tr_opt_SecondEventsDescriptor(Event, State), + signalsDescriptor = tr_opt_SignalsDescriptor(SigDesc, State)}. + +tr_opt_keepActive(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_keepActive(Keep, State) -> + tr_bool(Keep, State). + +tr_opt_EventDM(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_EventDM({Tag, Val}, State) -> + Val2 = + case Tag of + digitMapName -> tr_DigitMapName(Val, State); + digitMapValue -> tr_DigitMapValue(Val, State) + end, + {Tag, Val2}. + +tr_opt_SecondEventsDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = Id, + eventList = Events}, + State) -> + #'SecondEventsDescriptor'{requestID = tr_RequestID(Id, State), %% IG v6 6.8 withdrawn + eventList = [tr_SecondRequestedEvent(E, State) || E <- Events]}. + +tr_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = Name, + streamID = Id, + evParList = Parms, + eventAction = Actions}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'SecondRequestedEvent'{pkgdName = resolve(event, Name, State, Constraint), + streamID = tr_opt_StreamID(Id, State), + eventAction = tr_opt_SecondRequestedActions(Actions, State), + evParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + + +tr_opt_SecondRequestedActions(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SecondRequestedActions(#'SecondRequestedActions'{keepActive = Keep, + eventDM = DM, + signalsDescriptor = SigDesc}, + State) -> + #'SecondRequestedActions'{keepActive = tr_opt_keepActive(Keep, State), + eventDM = tr_opt_EventDM(DM, State), + signalsDescriptor = tr_opt_SignalsDescriptor(SigDesc, State)}. + +tr_EventBufferDescriptor(EventSpecs, State) -> + [tr_EventSpec(ES, State) || ES <- EventSpecs]. + +tr_EventSpec(#'EventSpec'{eventName = Name, + streamID = Id, + eventParList = Parms}, + State) -> + #'EventSpec'{eventName = tr_EventName(Name, State), + streamID = tr_opt_StreamID(Id, State), + eventParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + +tr_opt_SignalsDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SignalsDescriptor(SigDesc, State) -> + tr_SignalsDescriptor(SigDesc, State). + +tr_SignalsDescriptor(SigDesc, State) when is_list(SigDesc) -> + [tr_SignalRequest(SigReq, State) || SigReq <- SigDesc]. + +tr_SignalRequest({Tag, Val}, State) -> + Val2 = + case Tag of + signal -> tr_Signal(Val, State); + seqSigList -> tr_SeqSigList(Val, State) + end, + {Tag, Val2}. + + +tr_SeqSigList(#'SeqSigList'{id = Id, + signalList = SigList}, + State) when is_list(SigList) -> + #'SeqSigList'{id = tr_UINT16(Id, State), + signalList = [tr_Signal(Sig, State) || Sig <- SigList]}. + +tr_Signal(#'Signal'{signalName = Name, + streamID = Id, + sigType = Type, + duration = Dur, + notifyCompletion = Compl, + keepActive = Keep, + sigParList = Parms}, + State) -> + #'Signal'{signalName = tr_SignalName(Name, State), + streamID = tr_opt_StreamID(Id, State), + sigType = tr_opt_SignalType(Type, State), + duration = tr_opt_duration(Dur, State), + notifyCompletion = tr_opt_NotifyCompletion(Compl, State), + keepActive = tr_opt_keepActive(Keep, State), + sigParList = [tr_SigParameter(P, Name, State) || P <- Parms]}. + +tr_opt_duration(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_duration(Dur, State) -> + tr_UINT16(Dur, State). + +tr_opt_NotifyCompletion(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_NotifyCompletion(Items, State) when is_list(Items) -> + [tr_notifyCompletionItem(I, State) || I <- Items]. + +tr_notifyCompletionItem(Item, _State) -> + case Item of + onTimeOut -> onTimeOut; + onInterruptByEvent -> onInterruptByEvent; + onInterruptByNewSignalDescr -> onInterruptByNewSignalDescr; + otherReason -> otherReason + end. + +tr_opt_SignalType(Type, _State) -> + case Type of + asn1_NOVALUE -> asn1_NOVALUE; + brief -> brief; + onOff -> onOff; + timeOut -> timeOut + end. + +tr_SignalName(Name, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + resolve(signal, Name, State, Constraint). + +tr_SigParameter(#'SigParameter'{sigParameterName = ParName, + value = Value, + extraInfo = Extra}, + SigName, + State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + N = resolve({signal_parameter, SigName}, ParName, State, Constraint), + #'SigParameter'{sigParameterName = N, + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_opt_RequestID(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_RequestID(Id, State) -> + tr_RequestID(Id, State). + +tr_RequestID(Id, _State) when Id =:= ?megaco_all_request_id -> + ?megaco_all_request_id; +tr_RequestID(Id, State) -> + tr_UINT32(Id, State). + +tr_ModemDescriptor(_MD, _State) -> + deprecated. +% tr_ModemDescriptor(#'ModemDescriptor'{mtl = Types, +% mpl = Props}, +% State) when list(Types), list(Props) -> +% %% BUGBUG: Does not handle extensionParameter +% #'ModemDescriptor'{mtl = [tr_ModemType(T, State) || T <- Types], +% mpl = [tr_PropertyParm(P, State) || P <- Props]}. + +% tr_ModemType(Type, _State) -> +% %% BUGBUG: Does not handle extensionParameter +% case Type of +% v18 -> v18; +% v22 -> v22; +% v22bis -> v22bis; +% v32 -> v32; +% v32bis -> v32bis; +% v34 -> v34; +% v90 -> v90; +% v91 -> v91; +% synchISDN -> synchISDN +% end. + +tr_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value}, + State) -> + #'DigitMapDescriptor'{digitMapName = tr_opt_DigitMapName(Name, State), + digitMapValue = tr_opt_DigitMapValue(Value, State)}. + +tr_opt_DigitMapName(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_DigitMapName(Name, State) -> + tr_DigitMapName(Name, State). + +tr_DigitMapName(Name, State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + resolve(dialplan, Name, State, Constraint). + +tr_opt_DigitMapValue(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_DigitMapValue(Value, State) -> + tr_DigitMapValue(Value, State). + +tr_DigitMapValue(#'DigitMapValue'{digitMapBody = Body, + startTimer = Start, + shortTimer = Short, + longTimer = Long}, + State) -> + #'DigitMapValue'{startTimer = tr_opt_timer(Start, State), + shortTimer = tr_opt_timer(Short, State), + longTimer = tr_opt_timer(Long, State), + digitMapBody = tr_STRING(Body, State)}. %% BUGBUG: digitMapBody not handled at all + +tr_opt_timer(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_timer(Timer, State) -> + tr_DIGIT(Timer, State, 0, 99). + +tr_ServiceChangeParm(#'ServiceChangeParm'{serviceChangeMethod = Method, + serviceChangeAddress = Addr, + serviceChangeVersion = Version, + serviceChangeProfile = Profile, + serviceChangeReason = Reason, + serviceChangeDelay = Delay, + serviceChangeMgcId = MgcId, + timeStamp = Time, + serviceChangeInfo = Info}, + State) -> + #'ServiceChangeParm'{serviceChangeMethod = tr_ServiceChangeMethod(Method, State), + serviceChangeAddress = tr_opt_ServiceChangeAddress(Addr, State), + serviceChangeVersion = tr_opt_serviceChangeVersion(Version, State), + serviceChangeProfile = tr_opt_ServiceChangeProfile(Profile, State), + serviceChangeReason = tr_serviceChangeReason(Reason, State), + serviceChangeDelay = tr_opt_serviceChangeDelay(Delay, State), + serviceChangeMgcId = tr_opt_serviceChangeMgcId(MgcId, State), + timeStamp = tr_opt_TimeNotation(Time, State), + serviceChangeInfo = tr_opt_AuditDescriptor(Info, State)}. + +tr_ServiceChangeMethod(Method, _State) -> + case Method of + failover -> failover; + forced -> forced; + graceful -> graceful; + restart -> restart; + disconnected -> disconnected; + handOff -> handOff + end. %% BUGBUG: extension + +tr_opt_ServiceChangeAddress(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ServiceChangeAddress({Tag, Val}, State) -> + Val2 = + case Tag of + portNumber -> tr_portNumber(Val, State); + ip4Address -> tr_IP4Address(Val, State); + ip6Address -> tr_IP6Address(Val, State); + domainName -> tr_DomainName(Val, State); + deviceName -> tr_PathName(Val, State); + mtpAddress -> tr_mtpAddress(Val, State) + end, + {Tag, Val2}. + +tr_opt_serviceChangeVersion(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeVersion(Version, State) -> + tr_version(Version, State). + +tr_opt_ServiceChangeProfile(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +%% Decode +tr_opt_ServiceChangeProfile({'ServiceChangeProfile', ProfileName}, State) -> + case string:tokens(ProfileName, "/") of + [Name0, Version0] -> + Name = tr_STRING(Name0, State, 1, 64), + Version = tr_version(list_to_integer(Version0), State), + #'ServiceChangeProfile'{profileName = Name, + version = Version} + end; +%% Encode +tr_opt_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = Name0, + version = Version0}, + State) -> + Name = tr_STRING(Name0, State, 1, 64), + Version = tr_version(Version0, State), + ProfileName = lists:flatten(io_lib:format("~s/~w", [Name, Version])), + {'ServiceChangeProfile', ProfileName}. + +tr_serviceChangeReason([_] = Reason, State) -> + tr_Value(Reason, State). + +tr_opt_serviceChangeDelay(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeDelay(Delay, State) -> + tr_UINT32(Delay, State). + +tr_opt_serviceChangeMgcId(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeMgcId(MgcId, State) -> + tr_MId(MgcId, State). + +tr_opt_portNumber(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_portNumber(Port, State) -> + tr_portNumber(Port, State). + +tr_portNumber(Port, State) when is_integer(Port) andalso (Port >= 0) -> + tr_UINT16(Port, State). + +tr_ServiceChangeResParm(#'ServiceChangeResParm'{serviceChangeMgcId = MgcId, + serviceChangeAddress = Addr, + serviceChangeVersion = Version, + serviceChangeProfile = Profile, + timeStamp = Time}, + State) -> + #'ServiceChangeResParm'{serviceChangeMgcId = tr_opt_serviceChangeMgcId(MgcId, State), + serviceChangeAddress = tr_opt_ServiceChangeAddress(Addr, State), + serviceChangeVersion = tr_opt_serviceChangeVersion(Version, State), + serviceChangeProfile = tr_opt_ServiceChangeProfile(Profile, State), + timeStamp = tr_opt_TimeNotation(Time, State)}. + +tr_PackagesDescriptor(Items, State) when is_list(Items) -> + [tr_PackagesItem(I, State) || I <- Items]. + +tr_PackagesItem(#'PackagesItem'{packageName = Name, + packageVersion = Version}, + State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + #'PackagesItem'{packageName = resolve(package, Name, State, Constraint), + packageVersion = tr_UINT16(Version, State)}. + +tr_StatisticsDescriptor(Parms, State) when is_list(Parms) -> + [tr_StatisticsParameter(P, State) || P <- Parms]. + +tr_StatisticsParameter(#'StatisticsParameter'{statName = Name, + statValue = Value}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'StatisticsParameter'{statName = resolve(statistics, Name, State, Constraint), + statValue = tr_opt_Value(Value, State)}. + +tr_opt_TimeNotation(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TimeNotation(#'TimeNotation'{date = Date, + time = Time}, + State) -> + #'TimeNotation'{date = tr_STRING(Date, State, 8, 8), % "yyyymmdd" + time = tr_STRING(Time, State, 8, 8)}.% "hhmmssss" + +%% BUGBUG: Does not verify that string must contain at least one char +%% BUGBUG: This violation of the is required in order to comply with +%% BUGBUG: the dd/ce ds parameter that may possibly be empty. + +tr_opt_Value(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_Value(Value, State) -> + tr_Value(Value, State). + +tr_Value(Strings, _State) when is_list(Strings) -> + [[Char || Char <- String] || String <- Strings]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Encode an octet string, escape } by \ if necessary +tr_OCTET_STRING(String, _State, Min, Max) when is_list(String) -> + verify_count(length(String), Min, Max), + String. + +tr_QUOTED_STRING(String, _State) when is_list(String) -> + verify_count(length(String), 1, infinity), + String. + +%% The internal format of hex digits is a list of octets +%% Min and Max means #hexDigits +%% Leading zeros are prepended in order to fulfill Min +tr_HEXDIG(Octets, _State, Min, Max) when is_list(Octets) -> + verify_count(length(Octets), Min, Max), + Octets. + +tr_DIGIT(Val, State, Min, Max) -> + tr_integer(Val, State, Min, Max). + +tr_STRING(String, _State) when is_list(String) -> + String. + +tr_STRING(String, _State, Min, Max) when is_list(String) -> + verify_count(length(String), Min, Max), + String. + +tr_opt_UINT16(Val, State) -> + tr_opt_integer(Val, State, 0, 65535). + +tr_UINT16(Val, State) -> + tr_integer(Val, State, 0, 65535). + +tr_UINT32(Val, State) -> + tr_integer(Val, State, 0, 4294967295). + +tr_opt_integer(asn1_NOVALUE, _State, _Min, _Max) -> + asn1_NOVALUE; +tr_opt_integer(Int, State, Min, Max) -> + tr_integer(Int, State, Min, Max). + +tr_integer(Int, _State, Min, Max) -> + verify_count(Int, Min, Max), + Int. + +%% Verify that Count is within the range of Min and Max +verify_count(Count, Min, Max) -> + if + is_integer(Count) -> + if + is_integer(Min) andalso (Count >= Min) -> + if + is_integer(Max) andalso (Count =< Max) -> + Count; + Max =:= infinity -> + Count; + true -> + ?error({count_too_large, Count, Max}) + end; + true -> + ?error({count_too_small, Count, Min}) + end; + true -> + ?error({count_not_an_integer, Count}) + end. + + +% i(F,A) -> +% S1 = io_lib:format("TRANSF-v2: " ++ F ++ "~n",A), +% S2 = lists:flatten(S1), +% io:format("~s",[S2]). diff --git a/lib/megaco/src/binary/megaco_binary_transformer_v3.erl b/lib/megaco/src/binary/megaco_binary_transformer_v3.erl new file mode 100644 index 0000000000..cef49b03fd --- /dev/null +++ b/lib/megaco/src/binary/megaco_binary_transformer_v3.erl @@ -0,0 +1,1763 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Transform internal form of Megaco/H.248 messages +%%---------------------------------------------------------------------- + +-module(megaco_binary_transformer_v3). + +-include_lib("megaco/include/megaco.hrl"). +%% -include_lib("megaco/include/megaco_message.hrl"). +-include_lib("megaco/include/megaco_message_v3.hrl"). +-include_lib("megaco/src/app/megaco_internal.hrl"). + +-export([tr_message/3, tr_transaction/3]). + +-define(DEFAULT_NAME_RESOLVER, megaco_binary_name_resolver_v3). + +-record(state, {mode, % verify | encode | decode + resolver_module, % + resolver_options}). + +resolve(Type, Item, State, Constraint) -> + case State#state.mode of + verify -> + Item; + encode -> + ?d("resolve(encode) -> encode: ~p",[Item]), + Mod = State#state.resolver_module, + Opt = State#state.resolver_options, + EncodedItem = Mod:encode_name(Opt, Type, Item), + ?d("resolve -> verify contraint for ~p",[EncodedItem]), + verify_constraint(EncodedItem, Constraint); + decode -> + ?d("resolve(decode) -> verify contraint for ~p",[Item]), + DecodedItem = verify_constraint(Item, Constraint), + Mod = State#state.resolver_module, + Opt = State#state.resolver_options, + ?d("resolve(decode) -> decode: ~p",[DecodedItem]), + Mod:decode_name(Opt, Type, DecodedItem) + end. + +verify_constraint(Item, valid) -> + Item; +verify_constraint(Item, Constraint) when is_function(Constraint) -> + Constraint(Item). + +tr_message(MegaMsg, Mode, Config) -> + case Config of + [native] -> + MegaMsg; + [verify] -> + State = #state{mode = verify}, + tr_MegacoMessage(MegaMsg, State); + [] -> + State = #state{mode = Mode, + resolver_module = ?DEFAULT_NAME_RESOLVER, + resolver_options = [8, 8, 8]}, + tr_MegacoMessage(MegaMsg, State); + [{binary_name_resolver, {Module, Options}}] when is_atom(Module) -> + State = #state{mode = Mode, + resolver_module = Module, + resolver_options = Options}, + tr_MegacoMessage(MegaMsg, State) + end. + +tr_transaction(Trans, Mode, Config) -> + case Config of + [native] -> + Trans; + [verify] -> + State = #state{mode = verify}, + tr_Transaction(Trans, State); + [] -> + State = #state{mode = Mode, + resolver_module = ?DEFAULT_NAME_RESOLVER, + resolver_options = [8, 8, 8]}, + tr_Transaction(Trans, State); + [{binary_name_resolver, {Module, Options}}] when is_atom(Module) -> + State = #state{mode = Mode, + resolver_module = Module, + resolver_options = Options}, + tr_Transaction(Trans, State) + end. + +tr_MegacoMessage(#'MegacoMessage'{authHeader = Auth, + mess = Mess}, + State) -> + ?d("tr_MegacoMessage -> entry with" + "~n Auth: ~p" + "~n Mess: ~p" + "~n State: ~p", [Auth, Mess, State]), + #'MegacoMessage'{authHeader = tr_opt_AuthenticationHeader(Auth, State), + mess = tr_Message(Mess, State)}. + +tr_opt_AuthenticationHeader(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_AuthenticationHeader(#'AuthenticationHeader'{secParmIndex = SPI, + seqNum = SN, + ad = AuthData}, + State) -> + #'AuthenticationHeader'{secParmIndex = tr_SecurityParmIndex(SPI, State), + seqNum = tr_SequenceNum(SN, State), + ad = tr_AuthData(AuthData, State)}. + +tr_SecurityParmIndex(SPI, State) -> + tr_HEXDIG(SPI, State, 4, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_SequenceNum(SN, State) -> + tr_HEXDIG(SN, State, 4, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_AuthData(AuthData, State) -> + tr_HEXDIG(AuthData, State, 12, 32). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_Message(#'Message'{version = Version, + mId = MID, + messageBody = Body}, + State) -> + #'Message'{version = tr_version(Version, State), + mId = tr_MId(MID, State), + messageBody = tr_Message_messageBody(Body, State)}. + +tr_version(Version, State) -> + tr_DIGIT(Version, State, 0, 99). + +tr_Message_messageBody({Tag, Val}, State) -> + Val2 = + case Tag of + messageError -> tr_ErrorDescriptor(Val, State); + transactions when is_list(Val) -> [tr_Transaction(T, State) || T <- Val] + end, + {Tag, Val2}. + +tr_MId({Tag, Val}, State) -> + Val2 = + case Tag of + ip4Address -> tr_IP4Address(Val, State); + ip6Address -> tr_IP6Address(Val, State); + domainName -> tr_DomainName(Val, State); + deviceName -> tr_PathName(Val, State); + mtpAddress -> tr_mtpAddress(Val, State) + end, + {Tag, Val2}. + +tr_mtpAddress(MtpAddr, State) -> + tr_OCTET_STRING(MtpAddr, State, 2, 4). % BUGBUG: Mismatch between ASN.1 and ABNF + +tr_DomainName(#'DomainName'{name = Name, + portNumber = Port}, + State) -> + Domain = #'DomainName'{name = tr_STRING(Name, State), % BUGBUG: Mismatch between ASN.1 and ABNF + portNumber = tr_opt_portNumber(Port, State)}, + {domainName, Domain2} = resolve(mid, {domainName, Domain}, State, valid), + Domain2. + +tr_IP4Address(#'IP4Address'{address = [A1, A2, A3, A4], + portNumber = Port}, + State) -> + #'IP4Address'{address = [tr_V4hex(A1, State), + tr_V4hex(A2, State), + tr_V4hex(A3, State), + tr_V4hex(A4, State)], + portNumber = tr_opt_portNumber(Port, State)}. + +tr_V4hex(Val, State) -> + tr_DIGIT(Val, State, 0, 255). + +tr_IP6Address(_Val, _State) -> + error(ipv6_not_supported). %% BUGBUG: nyi + +tr_PathName(Path, State) -> + %% BUGBUG: ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" ) + %% BUGBUG: ["@" pathDomainName ] + Constraint = fun({deviceName, Item}) -> tr_STRING(Item, State, 1, 64) end, + resolve(mid, {deviceName, Path}, State, Constraint). + +tr_Transaction({Tag, Val}, State) -> + Val2 = + case Tag of + transactionRequest -> tr_TransactionRequest(Val, State); + transactionPending -> tr_TransactionPending(Val, State); + transactionReply -> tr_TransactionReply(Val, State); + transactionResponseAck -> [tr_TransactionAck(T, State) || T <- Val]; + segmentReply -> tr_SegmentReply(Val, State) + end, + {Tag, Val2}. + +tr_TransactionAck(#'TransactionAck'{firstAck = First, + lastAck = Last}, + State) -> + #'TransactionAck'{firstAck = tr_TransactionId(First, State), + lastAck = tr_opt_TransactionId(Last, State)}. + +tr_opt_TransactionId(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TransactionId(Id, State) -> + tr_TransactionId(Id, State). + +tr_TransactionId(Id, State) -> + tr_UINT32(Id, State). + +tr_TransactionRequest(#'TransactionRequest'{transactionId = Id, + actions = Actions}, + State) when is_list(Actions) -> + + #'TransactionRequest'{transactionId = tr_TransactionId(Id, State), + actions = [tr_ActionRequest(ActReq, State) || ActReq <- Actions]}. + +tr_TransactionPending(#'TransactionPending'{transactionId = Id}, + State) -> + #'TransactionPending'{transactionId = tr_TransactionId(Id, State)}. + +tr_TransactionReply(#'TransactionReply'{transactionId = Id, + immAckRequired = ImmAck, + transactionResult = TransRes, + segmentNumber = SN, + segmentationComplete = SC}, + State) -> + #'TransactionReply'{transactionId = tr_TransactionId(Id, State), + immAckRequired = tr_opt_null(ImmAck, State), + transactionResult = tr_TransactionReply_transactionResult(TransRes, State), + segmentNumber = tr_opt_SegmentNumber(SN, State), + segmentationComplete = tr_opt_null(SC, State)}. + +tr_opt_null(asn1_NOVALUE, _State) -> asn1_NOVALUE; +tr_opt_null('NULL', _State) -> 'NULL'. + +tr_SegmentNumber(Num, State) -> + tr_UINT16(Num, State). + +tr_opt_SegmentNumber(Num, State) -> + tr_opt_UINT16(Num, State). + +tr_SegmentReply(#'SegmentReply'{transactionId = TID, + segmentNumber = SN, + segmentationComplete = SC}, State) -> + #'SegmentReply'{transactionId = tr_TransactionId(TID, State), + segmentNumber = tr_SegmentNumber(SN, State), + segmentationComplete = tr_opt_null(SC, State)}. + +tr_TransactionReply_transactionResult({Tag, Val}, State) -> + Val2 = + case Tag of + transactionError -> + tr_ErrorDescriptor(Val, State); + actionReplies when is_list(Val) andalso (Val =/= []) -> + [tr_ActionReply(ActRep, State) || ActRep <- Val] + end, + {Tag, Val2}. + +tr_opt_ErrorDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ErrorDescriptor(ErrDesc, State) -> + tr_ErrorDescriptor(ErrDesc, State). + +tr_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code, + errorText = Text}, + State) -> + #'ErrorDescriptor'{errorCode = tr_ErrorCode(Code, State), + errorText = tr_opt_ErrorText(Text, State)}. + +tr_ErrorCode(Code, State) -> + tr_DIGIT(Code, State, 0, 999). + +tr_opt_ErrorText(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ErrorText(Text, State) -> + tr_QUOTED_STRING(Text, State). + +tr_ContextID(CtxId, State) -> + case CtxId of + ?megaco_all_context_id -> ?megaco_all_context_id; + ?megaco_null_context_id -> ?megaco_null_context_id; + ?megaco_choose_context_id -> ?megaco_choose_context_id; + Int when is_integer(Int) -> tr_UINT32(Int, State) + end. + +tr_ActionRequest(#'ActionRequest'{contextId = CtxId, + contextRequest = CtxReq, + contextAttrAuditReq = CtxAuditReq, + commandRequests = CmdReqList}, + State) -> + #'ActionRequest'{contextId = tr_ContextID(CtxId, State), + contextRequest = tr_opt_ContextRequest(CtxReq, State), + contextAttrAuditReq = tr_opt_ContextAttrAuditRequest(CtxAuditReq, State), + commandRequests = [tr_CommandRequest(CmdReq, State) || CmdReq <- CmdReqList]}. + +tr_ActionReply(#'ActionReply'{contextId = CtxId, + errorDescriptor = ErrDesc, + contextReply = CtxRep, + commandReply = CmdRepList}, + State) -> + CmdRepList2 = [tr_CommandReply(CmdRep, State) || CmdRep <- CmdRepList], + #'ActionReply'{contextId = tr_ContextID(CtxId, State), + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State), + contextReply = tr_opt_ContextRequest(CtxRep, State), + commandReply = CmdRepList2}. + +tr_opt_ContextRequest(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ContextRequest(CR, State) -> + tr_ContextRequest(CR, State). + +tr_ContextRequest(#'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = TopReqList, + iepscallind = Ind, + contextProp = CtxProps, + contextList = CtxList}, + State) -> + Prio2 = + case Prio of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_integer(Prio, State, 0, 15) + end, + Em2 = + case Em of + asn1_NOVALUE -> asn1_NOVALUE; + false -> false; + true -> true + end, + TopReqList2 = + case TopReqList of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_TopologyRequest(TopReq, State) || + TopReq <- TopReqList] + end, + Ind2 = + case Ind of + asn1_NOVALUE -> asn1_NOVALUE; + false -> false; + true -> true + end, + CtxProps2 = + case CtxProps of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_PropertyParm(Prop, State) || Prop <- CtxProps] + end, + CtxList2 = + case CtxList of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_ContextID(Id, State) || Id <- CtxList] + end, + #'ContextRequest'{priority = Prio2, + emergency = Em2, + topologyReq = TopReqList2, + iepscallind = Ind2, + contextProp = CtxProps2, + contextList = CtxList2}. + +tr_opt_ContextAttrAuditRequest(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ContextAttrAuditRequest(CAAR, State) -> + tr_ContextAttrAuditRequest(CAAR, State). + +tr_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ind, + contextPropAud = Props, + selectpriority = SPrio, + selectemergency = SEm, + selectiepscallind = SInd, + selectLogic = SLog}, + State) -> + Top2 = tr_opt_null(Top, State), + Em2 = tr_opt_null(Em, State), + Prio2 = tr_opt_null(Prio, State), + Ind2 = tr_opt_null(Ind, State), + Props2 = + case Props of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + [tr_indAudPropertyParm(Prop, State) || Prop <- Props] + end, + SPrio2 = + case SPrio of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_integer(SPrio, State, 0, 15) + end, + SEm2 = + case SEm of + asn1_NOVALUE -> asn1_NOVALUE; + false -> false; + true -> true + end, + SInd2 = + case SInd of + asn1_NOVALUE -> asn1_NOVALUE; + false -> false; + true -> true + end, + SLog2 = + case SLog of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_SelectLogic(SLog, State) + end, + #'ContextAttrAuditRequest'{topology = Top2, + emergency = Em2, + priority = Prio2, + iepscallind = Ind2, + contextPropAud = Props2, + selectpriority = SPrio2, + selectemergency = SEm2, + selectiepscallind = SInd2, + selectLogic = SLog2}. + +tr_SelectLogic({andAUDITSelect, 'NULL'} = Val, _State) -> + Val; +tr_SelectLogic({orAUDITSelect, 'NULL'} = Val, _State) -> + Val. + +tr_CommandRequest(#'CommandRequest'{command = Cmd, + optional = Opt, + wildcardReturn = Wild}, + State) -> + #'CommandRequest'{optional = tr_opt_null(Opt, State), + wildcardReturn = tr_opt_null(Wild, State), + command = tr_Command(Cmd, State)}. + +tr_Command({Tag, Val}, State) -> + Val2 = + case Tag of + addReq -> tr_AmmRequest(Val, State); + moveReq -> tr_AmmRequest(Val, State); + modReq -> tr_AmmRequest(Val, State); + subtractReq -> tr_SubtractRequest(Val, State); + auditCapRequest -> tr_AuditRequest(Val, State); + auditValueRequest -> tr_AuditRequest(Val, State); + notifyReq -> tr_NotifyRequest(Val, State); + serviceChangeReq -> tr_ServiceChangeRequest(Val, State) + end, + {Tag, Val2}. + +tr_CommandReply({Tag, Val}, State) -> + Val2 = + case Tag of + addReply -> tr_AmmsReply(Val, State); + moveReply -> tr_AmmsReply(Val, State); + modReply -> tr_AmmsReply(Val, State); + subtractReply -> tr_AmmsReply(Val, State); + auditCapReply -> tr_AuditReply(Val, State); + auditValueReply -> tr_AuditReply(Val, State); + notifyReply -> tr_NotifyReply(Val, State); + serviceChangeReply -> tr_ServiceChangeReply(Val, State) + end, + {Tag, Val2}. + +tr_TopologyRequest(#'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = Dir, + streamID = SID, + topologyDirectionExtension = TDE}, + State) -> + Dir2 = + case Dir of + bothway -> bothway; + isolate -> isolate; + oneway -> oneway + end, + TDE2 = + case TDE of + onewayexternal -> onewayexternal; + onewayboth -> onewayboth; + asn1_NOVALUE -> asn1_NOVALUE + end, + #'TopologyRequest'{terminationFrom = tr_TerminationID(From, State), + terminationTo = tr_TerminationID(To, State), + topologyDirection = Dir2, + streamID = tr_opt_StreamID(SID, State), + topologyDirectionExtension = TDE2}. + +tr_AmmRequest(#'AmmRequest'{terminationID = IdList, + descriptors = DescList}, + State) -> + #'AmmRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + descriptors = tr_ammDescriptors(DescList, [], State)}. + +tr_ammDescriptors([], Acc, _State) -> + lists:reverse(Acc); +tr_ammDescriptors([Desc|Descs], Acc, State) -> + case tr_ammDescriptor(Desc, State) of + {_, deprecated} when State#state.mode =:= encode -> + error({deprecated, Desc}); + {_, deprecated} when State#state.mode =:= decode -> + %% SKIP + tr_ammDescriptors(Descs, Acc, State); + {_, deprecated} -> + %% SKIP + tr_ammDescriptors(Descs, Acc, State); + NewDesc -> + tr_ammDescriptors(Descs, [NewDesc|Acc], State) + end. + +tr_ammDescriptor({Tag, Desc}, State) -> + Desc2 = + case Tag of + mediaDescriptor -> tr_MediaDescriptor(Desc, State); + modemDescriptor -> tr_ModemDescriptor(Desc, State); + muxDescriptor -> tr_MuxDescriptor(Desc, State); + eventsDescriptor -> tr_EventsDescriptor(Desc, State); + eventBufferDescriptor -> tr_EventBufferDescriptor(Desc, State); + signalsDescriptor -> tr_SignalsDescriptor(Desc, State); + digitMapDescriptor -> tr_DigitMapDescriptor(Desc, State); + auditDescriptor -> tr_AuditDescriptor(Desc, State); + statisticsDescriptor -> tr_StatisticsDescriptor(Desc, State) + end, + {Tag, Desc2}. + +tr_AmmsReply(#'AmmsReply'{terminationID = IdList, + terminationAudit = TermAudit}, + State) -> + TermAudit2 = + case TermAudit of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_TerminationAudit(TermAudit, State) + end, + #'AmmsReply'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + terminationAudit = TermAudit2}. + +tr_SubtractRequest(#'SubtractRequest'{terminationID = IdList, + auditDescriptor = Desc}, + State) -> + #'SubtractRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + auditDescriptor = tr_opt_AuditDescriptor(Desc, State)}. + +tr_AuditRequest(#'AuditRequest'{terminationID = Id, + auditDescriptor = Desc, + terminationIDList = TIDList}, + State) -> + TIDList2 = + case TIDList of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_TerminationID(TID, State) || TID <- TIDList] + end, + #'AuditRequest'{terminationID = tr_TerminationID(Id, State), + auditDescriptor = tr_AuditDescriptor(Desc, State), + terminationIDList = TIDList2}. + +%% auditReply = (AuditValueToken / AuditCapToken ) +%% ( contextTerminationAudit / auditOther) +%% auditOther = EQUAL TerminationID LBRKT +%% terminationAudit RBRKT +%% terminationAudit = auditReturnParameter *(COMMA auditReturnParameter) +%% +%% contextTerminationAudit = EQUAL CtxToken ( terminationIDList / +%% LBRKT errorDescriptor RBRKT ) + +tr_AuditReply({Tag, Val}, State) -> + Val2 = + case Tag of + contextAuditResult -> + [tr_TerminationID(Id, State) || Id <- Val]; + error -> + tr_ErrorDescriptor(Val, State); + auditResult -> + tr_AuditResult(Val, State); + auditResultTermList -> + tr_TermListAuditResult(Val, State) + end, + {Tag, Val2}. + +tr_AuditResult(#'AuditResult'{terminationID = Id, + terminationAuditResult = AuditRes}, + State) -> + #'AuditResult'{terminationID = tr_TerminationID(Id, State), + terminationAuditResult = tr_TerminationAudit(AuditRes, State)}. + +tr_TermListAuditResult( + #'TermListAuditResult'{terminationIDList = TIDList, + terminationAuditResult = TAR}, + State) -> + TIDList2 = [tr_TerminationID(TID, State) || TID <- TIDList], + TAR2 = tr_TerminationAudit(TAR, State), + #'TermListAuditResult'{terminationIDList = TIDList2, + terminationAuditResult = TAR2}. + + +tr_opt_AuditDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_AuditDescriptor(Desc, State) -> + tr_AuditDescriptor(Desc, State). + +%% BUGBUG BUGBUG BUGBUG +%% With this construction it is possible to have both auditToken +%% and auditPropertyToken, but it is actually valid? +tr_AuditDescriptor(#'AuditDescriptor'{auditToken = Tokens, + auditPropertyToken = APTs}, + State) -> + Tokens2 = + case Tokens of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_auditItem(Token, State) || Token <- Tokens] + end, + %% v2 + APTs2 = + case APTs of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + [tr_indAuditParameter(APT, State) || APT <- APTs] + end, + #'AuditDescriptor'{auditToken = Tokens2, + auditPropertyToken = APTs2}. + +tr_auditItem(Token, _State) -> + case Token of + muxToken -> muxToken; + modemToken -> modemToken; + mediaToken -> mediaToken; + eventsToken -> eventsToken; + signalsToken -> signalsToken; + digitMapToken -> digitMapToken; + statsToken -> statsToken; + observedEventsToken -> observedEventsToken; + packagesToken -> packagesToken; + eventBufferToken -> eventBufferToken + end. + +%% --- v2 begin --- + +tr_indAuditParameter({Tag, Val}, State) -> + Val2 = + case Tag of + indAudMediaDescriptor -> + tr_indAudMediaDescriptor(Val, State); + indAudEventsDescriptor -> + tr_indAudEventsDescriptor(Val, State); + indAudSignalsDescriptor -> + tr_indAudSignalsDescriptor(Val, State); + indAudDigitMapDescriptor -> + tr_indAudDigitMapDescriptor(Val, State); + indAudEventBufferDescriptor -> + tr_indAudEventBufferDescriptor(Val, State); + indAudStatisticsDescriptor -> + tr_indAudStatisticsDescriptor(Val, State); + indAudPackagesDescriptor -> + tr_indAudPackagesDescriptor(Val, State) + end, + {Tag, Val2}. + + +%% - + +tr_indAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = S}, + State) -> + TSD2 = + case TSD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudTerminationStateDescriptor(TSD, State) + end, + S2 = + case S of + asn1_NOVALUE -> + asn1_NOVALUE; + {oneStream, OS} -> + {oneStream, tr_indAudStreamParms(OS, State)}; + {multiStream, MS} -> + MS2 = [tr_indAudStreamDescriptor(MS1, State) || MS1 <- MS], + {multiStream, MS2} + end, + #'IndAudMediaDescriptor'{termStateDescr = TSD2, + streams = S2}. + +tr_indAudTerminationStateDescriptor(Val, State) + when is_record(Val, 'IndAudTerminationStateDescriptor') -> + #'IndAudTerminationStateDescriptor'{propertyParms = Parms, + eventBufferControl = EBC, + serviceState = SS, + serviceStateSel = SSS} = Val, + Parms2 = [tr_indAudPropertyParm(Parm, State) || Parm <- Parms], + EBC2 = tr_opt_null(EBC, State), + SS2 = tr_opt_null(SS, State), + SSS2 = tr_opt_ServiceState(SSS, State), + #'IndAudTerminationStateDescriptor'{propertyParms = Parms2, + eventBufferControl = EBC2, + serviceState = SS2, + serviceStateSel = SSS2}. + + +tr_indAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD, + statisticsDescriptor = SD}, + State) -> + LCD2 = + case LCD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudLocalControlDescriptor(LCD, State) + end, + LD2 = + case LD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudLocalRemoteDescriptor(LD, State) + end, + RD2 = + case RD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudLocalRemoteDescriptor(RD, State) + end, + SD2 = + case SD of + asn1_NOVALUE -> + asn1_NOVALUE; + _ -> + tr_indAudStatisticsDescriptor(SD, State) + end, + #'IndAudStreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2, + statisticsDescriptor = SD2}. + +tr_indAudLocalControlDescriptor(Val, State) + when is_record(Val, 'IndAudLocalControlDescriptor') -> + #'IndAudLocalControlDescriptor'{streamMode = M, + reserveValue = V, + reserveGroup = G, + propertyParms = P, + streamModeSel = SMS} = Val, + M2 = tr_opt_null(M, State), + V2 = tr_opt_null(V, State), + G2 = tr_opt_null(G, State), + P2 = tr_indAudLocalControlDescriptor_propertyParms(P, State), + SMS2 = tr_opt_StreamMode(SMS, State), + #'IndAudLocalControlDescriptor'{streamMode = M2, + reserveValue = V2, + reserveGroup = G2, + propertyParms = P2, + streamModeSel = SMS2}. + +tr_indAudLocalControlDescriptor_propertyParms(Parms, State) + when is_list(Parms) andalso (length(Parms) > 0) -> + [tr_indAudPropertyParm(Parm, State) || Parm <- Parms]; +tr_indAudLocalControlDescriptor_propertyParms(asn1_NOVALUE, _State) -> + asn1_NOVALUE. + +tr_indAudLocalRemoteDescriptor(#'IndAudLocalRemoteDescriptor'{propGroupID = ID, + propGrps = Grps}, + State) -> + #'IndAudLocalRemoteDescriptor'{propGroupID = tr_opt_UINT16(ID, State), + propGrps = tr_indAudPropertyGroup(Grps, + State)}. + +tr_indAudPropertyGroup(Grps, State) when is_list(Grps) -> + [tr_indAudPropertyParm(Parm, State) || Parm <- Grps]. + +tr_indAudPropertyParm(#'IndAudPropertyParm'{name = Name0, + propertyParms = Prop0}, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(property, Name0, State, Constraint), + Prop = + case Prop0 of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> tr_PropertyParm(Prop0, State) + end, + #'IndAudPropertyParm'{name = Name, + propertyParms = Prop}. + + +tr_indAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = ID, + streamParms = Parms}, + State) -> + #'IndAudStreamDescriptor'{streamID = tr_StreamID(ID, State), + streamParms = tr_indAudStreamParms(Parms, + State)}. + + +%% - + +tr_indAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID, + pkgdName = Name0, + streamID = SID}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(event, Name0, State, Constraint), + #'IndAudEventsDescriptor'{requestID = tr_opt_RequestID(RID, State), + pkgdName = Name, + streamID = tr_opt_StreamID(SID, State)}. + + +%% - + +tr_indAudSignalsDescriptor({Tag, Val}, State) -> + case Tag of + signal -> + {signal, tr_indAudSignal(Val, State)}; + seqSigList -> + {seqSigList, tr_indAudSeqSigList(Val, State)} + end. + +tr_opt_indAudSignal(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_indAudSignal(Val, State) -> + tr_indAudSignal(Val, State). + +tr_indAudSignal(#'IndAudSignal'{signalName = Name0, + streamID = SID, + signalRequestID = RID}, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(signal, Name0, State, Constraint), + #'IndAudSignal'{signalName = Name, + streamID = tr_opt_StreamID(SID, State), + signalRequestID = tr_opt_RequestID(RID, State)}. + +tr_indAudSeqSigList(#'IndAudSeqSigList'{id = ID, + signalList = SigList}, State) -> + #'IndAudSeqSigList'{id = tr_integer(ID, State, 0, 65535), + signalList = tr_opt_indAudSignal(SigList, State)}. + +%% - + +tr_indAudDigitMapDescriptor(#'IndAudDigitMapDescriptor'{digitMapName = Name}, + State) -> + #'IndAudDigitMapDescriptor'{digitMapName = + tr_opt_DigitMapName(Name, State)}. + + +%% - + +tr_indAudEventBufferDescriptor(#'IndAudEventBufferDescriptor'{eventName = N, + streamID = SID}, + State) -> + ?d("tr_indAudEventBufferDescriptor -> entry with" + "~n N: ~p" + "~n SID: ~p", [N, SID]), + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(event, N, State, Constraint), + ?d("tr_indAudEventBufferDescriptor -> entry with" + "~n Name: ~p", [Name]), + #'IndAudEventBufferDescriptor'{eventName = Name, + streamID = tr_opt_StreamID(SID, State)}. + +%% - + +tr_indAudStatisticsDescriptor(#'IndAudStatisticsDescriptor'{statName = N}, + State) -> + ?d("tr_indAudEventBufferDescriptor -> entry with" + "~n N: ~p", [N]), + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + Name = resolve(statistics, N, State, Constraint), + #'IndAudStatisticsDescriptor'{statName = Name}. + + +%% - + +tr_indAudPackagesDescriptor(#'IndAudPackagesDescriptor'{packageName = N, + packageVersion = V}, + State) -> + ?d("tr_indAudPackagesDescriptor -> entry with" + "~n N: ~p" + "~n V: ~p", [N, V]), + Constraint = fun(Item) -> tr_Name(Item, State) end, + Name = resolve(package, N, State, Constraint), + ?d("tr_indAudPackagesDescriptor -> entry with" + "~n Name: ~p", [Name]), + #'IndAudPackagesDescriptor'{packageName = Name, + packageVersion = tr_integer(V, State, 0, 99)}. + +%% -- v2 end -- + + +tr_TerminationAudit(ParmList, State) when is_list(ParmList) -> + do_tr_TerminationAudit(ParmList, [], State). + +do_tr_TerminationAudit([], Acc, _State) -> + lists:reverse(Acc); +do_tr_TerminationAudit([Parm|ParmList], Acc, State) -> + case tr_AuditReturnParameter(Parm, State) of + {_, deprecated} when State#state.mode =:= encode -> + error({deprecated, Parm}); + {_, deprecated} when State#state.mode =:= decode -> + %% SKIP + do_tr_TerminationAudit(ParmList, Acc, State); + {_, deprecated} -> + %% SKIP + do_tr_TerminationAudit(ParmList, Acc, State); + NewParm -> + do_tr_TerminationAudit(ParmList, [NewParm|Acc], State) + end. + +tr_AuditReturnParameter({Tag, Val}, State) -> + Val2 = + case Tag of + errorDescriptor -> + tr_ErrorDescriptor(Val, State); + mediaDescriptor -> + tr_MediaDescriptor(Val, State); + modemDescriptor -> + tr_ModemDescriptor(Val, State); + muxDescriptor -> + tr_MuxDescriptor(Val, State); + eventsDescriptor -> + tr_EventsDescriptor(Val, State); + eventBufferDescriptor -> + tr_EventBufferDescriptor(Val, State); + signalsDescriptor -> + tr_SignalsDescriptor(Val, State); + digitMapDescriptor -> + tr_DigitMapDescriptor(Val, State); + observedEventsDescriptor -> + tr_ObservedEventsDescriptor(Val, State); + statisticsDescriptor -> + tr_StatisticsDescriptor(Val, State); + packagesDescriptor -> + tr_PackagesDescriptor(Val, State); + emptyDescriptors -> + tr_EmptyDescriptors(Val, State) + end, + {Tag, Val2}. + +tr_EmptyDescriptors(#'AuditDescriptor'{auditToken = Tokens}, + State) -> + Tokens2 = + case Tokens of + asn1_NOVALUE -> asn1_NOVALUE; + _ -> [tr_auditItem(Token, State) || Token <- Tokens] + end, + #'AuditDescriptor'{auditToken = Tokens2}. + +tr_NotifyRequest(#'NotifyRequest'{terminationID = IdList, + observedEventsDescriptor = ObsDesc, + errorDescriptor = ErrDesc}, + State) -> + %% BUGBUG: Mismatch between ASN.1 and ABNF + %% BUGBUG: The following ought to be a 'choice' + #'NotifyRequest'{terminationID = [tr_TerminationID(Id, State) || + Id <- IdList], + observedEventsDescriptor = tr_ObservedEventsDescriptor(ObsDesc, State), + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State)}. + +tr_NotifyReply(#'NotifyReply'{terminationID = IdList, + errorDescriptor = ErrDesc}, + State) -> + #'NotifyReply'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + errorDescriptor = tr_opt_ErrorDescriptor(ErrDesc, State)}. + +tr_ObservedEventsDescriptor(#'ObservedEventsDescriptor'{requestId = Id, + observedEventLst = Events}, + State) when is_list (Events) -> + #'ObservedEventsDescriptor'{requestId = tr_RequestID(Id, State), + observedEventLst = [tr_ObservedEvent(E, State) || E <- Events]}. + +%% ;time per event, because it might be buffered +%% observedEvent = [ TimeStamp LWSP COLON] LWSP +%% pkgdName [ LBRKT observedEventParameter +%% *(COMMA observedEventParameter) RBRKT ] +%% +%% ;at-most-once eventStream, every eventParameterName at most once +%% observedEventParameter = eventStream / eventOther + +tr_ObservedEvent(#'ObservedEvent'{eventName = Name, + streamID = Id, + eventParList = Parms, + timeNotation = Time}, + State) -> + #'ObservedEvent'{eventName = tr_EventName(Name, State), + streamID = tr_opt_StreamID(Id, State), + eventParList = [tr_EventParameter(P, Name, State) || P <- Parms], + timeNotation = tr_opt_TimeNotation(Time, State)}. + +tr_EventName(Name, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + resolve(event, Name, State, Constraint). + +tr_EventParameter(#'EventParameter'{eventParameterName = ParName, + value = Value, + extraInfo = Extra}, + EventName, + State) -> + %% BUGBUG: event parameter name + Constraint = fun(Item) -> tr_Name(Item, State) end, + N = resolve({event_parameter, EventName}, ParName, State, Constraint), + #'EventParameter'{eventParameterName = N, + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_ServiceChangeRequest(#'ServiceChangeRequest'{terminationID = IdList, + serviceChangeParms = Parms}, + State) -> + #'ServiceChangeRequest'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + serviceChangeParms = tr_ServiceChangeParm(Parms, State)}. + +%% serviceChangeReply = ServiceChangeToken EQUAL TerminationID +%% [LBRKT (errorDescriptor / +%% serviceChangeReplyDescriptor) RBRKT] +%% serviceChangeReplyDescriptor = ServicesToken LBRKT +%% servChgReplyParm *(COMMA servChgReplyParm) RBRKT +%% +%% ;at-most-once. Version is REQUIRED on first ServiceChange response +%% servChgReplyParm = (serviceChangeAddress / serviceChangeMgcId / +%% serviceChangeProfile / serviceChangeVersion ) +tr_ServiceChangeReply(#'ServiceChangeReply'{terminationID = IdList, + serviceChangeResult = Res}, + State) -> + #'ServiceChangeReply'{terminationID = [tr_TerminationID(Id, State) || Id <- IdList], + serviceChangeResult = tr_ServiceChangeResult(Res, State)}. + +tr_ServiceChangeResult({Tag, Val}, State) -> + Val2 = + case Tag of + errorDescriptor -> tr_ErrorDescriptor(Val, State); + serviceChangeResParms -> tr_ServiceChangeResParm(Val, State) + end, + {Tag, Val2}. + +%% TerminationID = "ROOT" / pathNAME / "$" / "*" +%% ; Total length of pathNAME must not exceed 64 chars. +%% pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" ) +%% ["@" pathDomainName ] + +tr_TerminationID(TermId, State) when State#state.mode =/= verify -> + resolve(term_id, TermId, State, valid); +tr_TerminationID(#'TerminationID'{wildcard = Wild, + id = Id}, + _State) -> + #'TerminationID'{wildcard = Wild, + id = Id}; +tr_TerminationID(#megaco_term_id{contains_wildcards = IsWild, + id = Id}, + State) -> + #megaco_term_id{contains_wildcards = tr_bool(IsWild, State), + id = [tr_term_id_component(Sub, State) || Sub <- Id]}. + +tr_opt_bool(asn1_NOVALUE, _State) -> asn1_NOVALUE; +tr_opt_bool(Bool, State) -> tr_bool(Bool, State). + +tr_bool(true, _State) -> true; +tr_bool(false, _State) -> false. + +tr_term_id_component(Sub, _State) -> + case Sub of + all -> all; + choose -> choose; + Char when is_integer(Char) -> Char + end. + +%% mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT +%% ; at-most-once per item +%% ; and either streamParm or streamDescriptor but not both +%% mediaParm = (streamParm / streamDescriptor / +%% terminationStateDescriptor) +%% ; at-most-once +%% streamParm = ( localDescriptor / remoteDescriptor / +%% localControlDescriptor ) +%% streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm +%% *(COMMA streamParm) RBRKT +tr_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TermState, + streams = Streams}, + State) -> + #'MediaDescriptor'{termStateDescr = tr_opt_TerminationStateDescriptor(TermState, State), + streams = tr_opt_streams(Streams, State)}. + +tr_opt_streams(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_streams({Tag, Val}, State) -> + Val2 = + case Tag of + oneStream -> tr_StreamParms(Val, State); + multiStream -> [tr_StreamDescriptor(SD, State) || SD <- Val] + end, + {Tag, Val2}. + +tr_StreamParms(#'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD, + statisticsDescriptor = SD}, + State) -> + LCD2 = tr_opt_LocalControlDescriptor(LCD, State), + LD2 = tr_opt_LocalRemoteDescriptor(LD, State), + RD2 = tr_opt_LocalRemoteDescriptor(RD, State), + SD2 = tr_opt_StatisticsDescriptor(SD, State), + #'StreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2, + statisticsDescriptor = SD2}. + +tr_StreamDescriptor(#'StreamDescriptor'{streamID = Id, + streamParms = Parms}, + State) -> + #'StreamDescriptor'{streamID = tr_StreamID(Id, State), + streamParms = tr_StreamParms(Parms, State)}. + +%% localControlDescriptor = LocalControlToken LBRKT localParm +%% *(COMMA localParm) RBRKT +%% +%% ; at-most-once per item +%% localParm = ( streamMode / propertyParm / +%% reservedValueMode / reservedGroupMode ) +%% reservedValueMode = ReservedValueToken EQUAL ( "ON" / "OFF" ) +%% reservedGroupMode = ReservedGroupToken EQUAL ( "ON" / "OFF" ) +%% +%% reservedMode = ReservedToken EQUAL ( "ON" / "OFF" ) +%% +%% streamMode = ModeToken EQUAL streamModes +tr_opt_LocalControlDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = Mode, + reserveGroup = Group, + reserveValue = Value, + propertyParms = Props}, + State) -> + #'LocalControlDescriptor'{streamMode = tr_opt_StreamMode(Mode, State), + reserveGroup = tr_opt_bool(Group, State), + reserveValue = tr_opt_bool(Value, State), + propertyParms = [tr_PropertyParm(P, State) || P <- Props]}. + +tr_opt_StreamMode(Mode, _State) -> + case Mode of + asn1_NOVALUE -> asn1_NOVALUE; + sendOnly -> sendOnly; + recvOnly -> recvOnly; + sendRecv -> sendRecv; + inactive -> inactive; + loopBack -> loopBack + end. + +tr_Name(Name, State) -> + %% BUGBUG: transform + %% BUGBUG: NAME = ALPHA *63(ALPHA / DIGIT / "_" ) + tr_STRING(Name, State, 2, 2). + +tr_PkgdName(Name, State) -> + %% BUGBUG: transform + %% BUGBUG: pkgdName = (NAME / "*") SLASH (ItemID / "*" ) + tr_OCTET_STRING(Name, State, 4, 4). + +%% When text encoding the protocol, the descriptors consist of session +%% descriptions as defined in SDP (RFC2327), except that the "s=", "t=" +%% and "o=" lines are optional. When multiple session descriptions are +%% provided in one descriptor, the "v=" lines are required as delimiters; +%% otherwise they are optional. Implementations shall accept session +%% descriptions that are fully conformant to RFC2327. When binary +%% encoding the protocol the descriptor consists of groups of properties +%% (tag-value pairs) as specified in Annex C. Each such group may +%% contain the parameters of a session description. +tr_opt_LocalRemoteDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = Groups}, + State) -> + #'LocalRemoteDescriptor'{propGrps = [tr_PropertyGroup(G, State) || G <- Groups]}. + +tr_PropertyGroup(Props, State) -> + [tr_PropertyGroupParm(P, State) || P <- Props]. + +tr_PropertyGroupParm(#'PropertyParm'{name = Name, + value = Value}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'PropertyParm'{name = resolve(property, Name, State, Constraint), + value = tr_OCTET_STRING(Value, State, 0, infinity)}. + +tr_PropertyParm(#'PropertyParm'{name = Name, + value = Value, + extraInfo = Extra}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'PropertyParm'{name = resolve(property, Name, State, Constraint), + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_opt_extraInfo(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_extraInfo({relation, Rel}, _State) -> + Rel2 = + case Rel of + greaterThan -> greaterThan; + smallerThan -> smallerThan; + unequalTo -> unequalTo + end, + {relation, Rel2}; +tr_opt_extraInfo({range, Range}, State) -> + Range2 = tr_bool(Range, State), + {range, Range2}; +tr_opt_extraInfo({sublist, Sub}, State) -> + Sub2 = tr_bool(Sub, State), + {sublist, Sub2}. + +tr_opt_TerminationStateDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TerminationStateDescriptor(#'TerminationStateDescriptor'{propertyParms = Props, + eventBufferControl = Control, + serviceState = Service}, + State) -> + #'TerminationStateDescriptor'{propertyParms = [tr_PropertyParm(P, State) || P <- Props], + eventBufferControl = tr_opt_EventBufferControl(Control, State), + serviceState = tr_opt_ServiceState(Service, State)}. + +tr_opt_EventBufferControl(Control, _State) -> + case Control of + asn1_NOVALUE -> asn1_NOVALUE; + off -> off; + lockStep -> lockStep + end. + +tr_opt_ServiceState(Service, _State) -> + case Service of + asn1_NOVALUE -> asn1_NOVALUE; + test -> test; + outOfSvc -> outOfSvc; + inSvc -> inSvc + end. + +tr_MuxDescriptor(#'MuxDescriptor'{muxType = Type, + termList = IdList}, + State) -> + #'MuxDescriptor'{muxType = tr_MuxType(Type, State), + termList = [tr_TerminationID(Id, State) || Id <- IdList]}. + +tr_MuxType(Type, _State) -> + case Type of + h221 -> h221; + h223 -> h223; + h226 -> h226; + v76 -> v76 + end. + +tr_opt_StreamID(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_StreamID(Id, State) -> + tr_StreamID(Id, State). + +tr_StreamID(Id, State) -> + tr_UINT16(Id, State). + +tr_EventsDescriptor(#'EventsDescriptor'{requestID = Id, + eventList = Events}, + State) -> + #'EventsDescriptor'{requestID = tr_opt_RequestID(Id, State), + eventList = [tr_RequestedEvent(E, State) || E <- Events]}. + +tr_RequestedEvent(#'RequestedEvent'{pkgdName = Name, + streamID = Id, + evParList = Parms, + eventAction = Actions}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'RequestedEvent'{pkgdName = resolve(event, Name, State, Constraint), + streamID = tr_opt_StreamID(Id, State), + eventAction = tr_opt_RequestedActions(Actions, State), + evParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + +tr_RegulatedEmbeddedDescriptor( + #'RegulatedEmbeddedDescriptor'{secondEvent = SE, + signalsDescriptor = SD}, State) -> + SE2 = tr_opt_SecondEventsDescriptor(SE, State), + SD2 = tr_opt_SignalsDescriptor(SD, State), + #'RegulatedEmbeddedDescriptor'{secondEvent = SE2, + signalsDescriptor = SD2}. + +tr_opt_NotifyBehaviour(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_NotifyBehaviour(NB, State) -> + tr_NotifyBehaviour(NB, State). + +tr_NotifyBehaviour({notifyImmediate, 'NULL'} = NB, _State) -> + NB; +tr_NotifyBehaviour({notifyRegulated = Tag, Val}, State) -> + {Tag, tr_RegulatedEmbeddedDescriptor(Val, State)}; +tr_NotifyBehaviour({neverNotify, 'NULL'} = NB, _State) -> + NB. + +tr_opt_RequestedActions(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_RequestedActions(#'RequestedActions'{keepActive = KA, + eventDM = DM, + secondEvent = SE, + signalsDescriptor = SD, + notifyBehaviour = NB, + resetEventsDescriptor = RSD}, + State) -> + KA2 = tr_opt_keepActive(KA, State), + DM2 = tr_opt_EventDM(DM, State), + SE2 = tr_opt_SecondEventsDescriptor(SE, State), + SD2 = tr_opt_SignalsDescriptor(SD, State), + NB2 = tr_opt_NotifyBehaviour(NB, State), + RSD2 = tr_opt_null(RSD, State), + #'RequestedActions'{keepActive = KA2, + eventDM = DM2, + secondEvent = SE2, + signalsDescriptor = SD2, + notifyBehaviour = NB2, + resetEventsDescriptor = RSD2}. + +tr_opt_keepActive(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_keepActive(Keep, State) -> + tr_bool(Keep, State). + +tr_opt_EventDM(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_EventDM({Tag, Val}, State) -> + Val2 = + case Tag of + digitMapName -> tr_DigitMapName(Val, State); + digitMapValue -> tr_DigitMapValue(Val, State) + end, + {Tag, Val2}. + +tr_opt_SecondEventsDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = Id, + eventList = Events}, + State) -> + #'SecondEventsDescriptor'{requestID = tr_RequestID(Id, State), %% IG v6 6.8 withdrawn + eventList = [tr_SecondRequestedEvent(E, State) || E <- Events]}. + +tr_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = Name, + streamID = Id, + evParList = Parms, + eventAction = Actions}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'SecondRequestedEvent'{pkgdName = resolve(event, Name, State, Constraint), + streamID = tr_opt_StreamID(Id, State), + eventAction = tr_opt_SecondRequestedActions(Actions, State), + evParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + + +tr_opt_SecondRequestedActions(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SecondRequestedActions( + #'SecondRequestedActions'{keepActive = KA, + eventDM = DM, + signalsDescriptor = SD, + notifyBehaviour = NB, + resetEventsDescriptor = RSD}, + State) -> + KA2 = tr_opt_keepActive(KA, State), + DM2 = tr_opt_EventDM(DM, State), + SD2 = tr_opt_SignalsDescriptor(SD, State), + NB2 = tr_opt_NotifyBehaviour(NB, State), + RSD2 = tr_opt_null(RSD, State), + #'SecondRequestedActions'{keepActive = KA2, + eventDM = DM2, + signalsDescriptor = SD2, + notifyBehaviour = NB2, + resetEventsDescriptor = RSD2}. + +tr_EventBufferDescriptor(EventSpecs, State) -> + [tr_EventSpec(ES, State) || ES <- EventSpecs]. + +tr_EventSpec(#'EventSpec'{eventName = Name, + streamID = Id, + eventParList = Parms}, + State) -> + #'EventSpec'{eventName = tr_EventName(Name, State), + streamID = tr_opt_StreamID(Id, State), + eventParList = [tr_EventParameter(P, Name, State) || P <- Parms]}. + +tr_opt_SignalsDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_SignalsDescriptor(SigDesc, State) -> + tr_SignalsDescriptor(SigDesc, State). + +tr_SignalsDescriptor(SigDesc, State) when is_list(SigDesc) -> + [tr_SignalRequest(SigReq, State) || SigReq <- SigDesc]. + +tr_SignalRequest({Tag, Val}, State) -> + Val2 = + case Tag of + signal -> tr_Signal(Val, State); + seqSigList -> tr_SeqSigList(Val, State) + end, + {Tag, Val2}. + + +tr_SeqSigList(#'SeqSigList'{id = Id, + signalList = SigList}, + State) when is_list(SigList) -> + #'SeqSigList'{id = tr_UINT16(Id, State), + signalList = [tr_Signal(Sig, State) || Sig <- SigList]}. + +tr_Signal(#'Signal'{signalName = Name, + streamID = SID, + sigType = Type, + duration = Dur, + notifyCompletion = Compl, + keepActive = Keep, + sigParList = Parms, + direction = Dir, + requestID = RID, + intersigDelay = ID}, + State) -> + Name2 = tr_SignalName(Name, State), + SID2 = tr_opt_StreamID(SID, State), + Type2 = tr_opt_SignalType(Type, State), + Dur2 = tr_opt_UINT16(Dur, State), + Compl2 = tr_opt_NotifyCompletion(Compl, State), + Keep2 = tr_opt_keepActive(Keep, State), + Parms2 = [tr_SigParameter(P, Name, State) || P <- Parms], + Dir2 = tr_opt_SignalDirection(Dir, State), + RID2 = tr_opt_RequestID(RID, State), + ID2 = tr_opt_UINT16(ID, State), + #'Signal'{signalName = Name2, + streamID = SID2, + sigType = Type2, + duration = Dur2, + notifyCompletion = Compl2, + keepActive = Keep2, + sigParList = Parms2, + direction = Dir2, + requestID = RID2, + intersigDelay = ID2}. + +tr_opt_NotifyCompletion(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_NotifyCompletion(Items, State) when is_list(Items) -> + [tr_notifyCompletionItem(I, State) || I <- Items]. + +tr_notifyCompletionItem(Item, _State) -> + case Item of + onTimeOut -> onTimeOut; + onInterruptByEvent -> onInterruptByEvent; + onInterruptByNewSignalDescr -> onInterruptByNewSignalDescr; + otherReason -> otherReason; + onIteration -> onIteration + end. + +tr_opt_SignalType(asn1_NOVALUE = Type, _State) -> + Type; +tr_opt_SignalType(Type, _State) -> + case Type of + brief -> brief; + onOff -> onOff; + timeOut -> timeOut + end. + +tr_opt_SignalDirection(asn1_NOVALUE = SD, _State) -> + SD; +tr_opt_SignalDirection(SD, _State) -> + case SD of + internal -> internal; + external -> external; + both -> both + end. + +tr_SignalName(Name, State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + resolve(signal, Name, State, Constraint). + +tr_SigParameter(#'SigParameter'{sigParameterName = ParName, + value = Value, + extraInfo = Extra}, + SigName, + State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + N = resolve({signal_parameter, SigName}, ParName, State, Constraint), + #'SigParameter'{sigParameterName = N, + value = tr_Value(Value, State), + extraInfo = tr_opt_extraInfo(Extra, State)}. + +tr_opt_RequestID(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_RequestID(Id, State) -> + tr_RequestID(Id, State). + +tr_RequestID(Id, _State) when Id =:= ?megaco_all_request_id -> + ?megaco_all_request_id; +tr_RequestID(Id, State) -> + tr_UINT32(Id, State). + +tr_ModemDescriptor(_MD, _State) -> + deprecated. + +tr_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value}, + State) -> + #'DigitMapDescriptor'{digitMapName = tr_opt_DigitMapName(Name, State), + digitMapValue = tr_opt_DigitMapValue(Value, State)}. + +tr_opt_DigitMapName(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_DigitMapName(Name, State) -> + tr_DigitMapName(Name, State). + +tr_DigitMapName(Name, State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + resolve(dialplan, Name, State, Constraint). + +tr_opt_DigitMapValue(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_DigitMapValue(Value, State) -> + tr_DigitMapValue(Value, State). + +tr_DigitMapValue(#'DigitMapValue'{digitMapBody = Body, + startTimer = Start, + shortTimer = Short, + longTimer = Long}, + State) -> + #'DigitMapValue'{startTimer = tr_opt_timer(Start, State), + shortTimer = tr_opt_timer(Short, State), + longTimer = tr_opt_timer(Long, State), + digitMapBody = tr_STRING(Body, State)}. %% BUGBUG: digitMapBody not handled at all + +tr_opt_timer(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_timer(Timer, State) -> + tr_DIGIT(Timer, State, 0, 99). + +tr_ServiceChangeParm( + #'ServiceChangeParm'{serviceChangeMethod = Method, + serviceChangeAddress = Addr, + serviceChangeVersion = Version, + serviceChangeProfile = Profile, + serviceChangeReason = Reason, + serviceChangeDelay = Delay, + serviceChangeMgcId = MgcId, + timeStamp = Time, + serviceChangeInfo = Info, + serviceChangeIncompleteFlag = Incomplete}, + State) -> + Method2 = tr_ServiceChangeMethod(Method, State), + Addr2 = tr_opt_ServiceChangeAddress(Addr, State), + Version2 = tr_opt_serviceChangeVersion(Version, State), + Profile2 = tr_opt_ServiceChangeProfile(Profile, State), + Reason2 = tr_serviceChangeReason(Reason, State), + Delay2 = tr_opt_serviceChangeDelay(Delay, State), + MgcId2 = tr_opt_serviceChangeMgcId(MgcId, State), + Time2 = tr_opt_TimeNotation(Time, State), + Info2 = tr_opt_AuditDescriptor(Info, State), + Incomplete2 = tr_opt_null(Incomplete, State), + #'ServiceChangeParm'{serviceChangeMethod = Method2, + serviceChangeAddress = Addr2, + serviceChangeVersion = Version2, + serviceChangeProfile = Profile2, + serviceChangeReason = Reason2, + serviceChangeDelay = Delay2, + serviceChangeMgcId = MgcId2, + timeStamp = Time2, + serviceChangeInfo = Info2, + serviceChangeIncompleteFlag = Incomplete2}. + +tr_ServiceChangeMethod(Method, _State) -> + case Method of + failover -> failover; + forced -> forced; + graceful -> graceful; + restart -> restart; + disconnected -> disconnected; + handOff -> handOff + end. %% BUGBUG: extension + +tr_opt_ServiceChangeAddress(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_ServiceChangeAddress({Tag, Val}, State) -> + Val2 = + case Tag of + portNumber -> tr_portNumber(Val, State); + ip4Address -> tr_IP4Address(Val, State); + ip6Address -> tr_IP6Address(Val, State); + domainName -> tr_DomainName(Val, State); + deviceName -> tr_PathName(Val, State); + mtpAddress -> tr_mtpAddress(Val, State) + end, + {Tag, Val2}. + +tr_opt_serviceChangeVersion(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeVersion(Version, State) -> + tr_version(Version, State). + +tr_opt_ServiceChangeProfile(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +%% Decode +tr_opt_ServiceChangeProfile({'ServiceChangeProfile', ProfileName}, State) -> + case string:tokens(ProfileName, "/") of + [Name0, Version0] -> + Name = tr_STRING(Name0, State, 1, 64), + Version = tr_version(list_to_integer(Version0), State), + #'ServiceChangeProfile'{profileName = Name, + version = Version} + end; +%% Encode +tr_opt_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = Name0, + version = Version0}, + State) -> + Name = tr_STRING(Name0, State, 1, 64), + Version = tr_version(Version0, State), + ProfileName = lists:flatten(io_lib:format("~s/~w", [Name, Version])), + {'ServiceChangeProfile', ProfileName}. + +tr_serviceChangeReason([_] = Reason, State) -> + tr_Value(Reason, State). + +tr_opt_serviceChangeDelay(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeDelay(Delay, State) -> + tr_UINT32(Delay, State). + +tr_opt_serviceChangeMgcId(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_serviceChangeMgcId(MgcId, State) -> + tr_MId(MgcId, State). + +tr_opt_portNumber(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_portNumber(Port, State) -> + tr_portNumber(Port, State). + +tr_portNumber(Port, State) when is_integer(Port) andalso (Port >= 0) -> + tr_UINT16(Port, State). + +tr_ServiceChangeResParm(#'ServiceChangeResParm'{serviceChangeMgcId = MgcId, + serviceChangeAddress = Addr, + serviceChangeVersion = Version, + serviceChangeProfile = Profile, + timeStamp = Time}, + State) -> + #'ServiceChangeResParm'{serviceChangeMgcId = tr_opt_serviceChangeMgcId(MgcId, State), + serviceChangeAddress = tr_opt_ServiceChangeAddress(Addr, State), + serviceChangeVersion = tr_opt_serviceChangeVersion(Version, State), + serviceChangeProfile = tr_opt_ServiceChangeProfile(Profile, State), + timeStamp = tr_opt_TimeNotation(Time, State)}. + +tr_PackagesDescriptor(Items, State) when is_list(Items) -> + [tr_PackagesItem(I, State) || I <- Items]. + +tr_PackagesItem(#'PackagesItem'{packageName = Name, + packageVersion = Version}, + State) -> + Constraint = fun(Item) -> tr_Name(Item, State) end, + #'PackagesItem'{packageName = resolve(package, Name, State, Constraint), + packageVersion = tr_UINT16(Version, State)}. + +tr_opt_StatisticsDescriptor(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_StatisticsDescriptor(Parms, State) -> + tr_StatisticsDescriptor(Parms, State). + +tr_StatisticsDescriptor(Parms, State) when is_list(Parms) -> + [tr_StatisticsParameter(P, State) || P <- Parms]. + +tr_StatisticsParameter(#'StatisticsParameter'{statName = Name, + statValue = Value}, + State) -> + Constraint = fun(Item) -> tr_PkgdName(Item, State) end, + #'StatisticsParameter'{statName = resolve(statistics, Name, State, Constraint), + statValue = tr_opt_Value(Value, State)}. + +tr_opt_TimeNotation(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_TimeNotation(#'TimeNotation'{date = Date, + time = Time}, + State) -> + #'TimeNotation'{date = tr_STRING(Date, State, 8, 8), % "yyyymmdd" + time = tr_STRING(Time, State, 8, 8)}.% "hhmmssss" + +%% BUGBUG: Does not verify that string must contain at least one char +%% BUGBUG: This violation of the is required in order to comply with +%% BUGBUG: the dd/ce ds parameter that may possibly be empty. + +tr_opt_Value(asn1_NOVALUE, _State) -> + asn1_NOVALUE; +tr_opt_Value(Value, State) -> + tr_Value(Value, State). + +tr_Value(Strings, _State) when is_list(Strings) -> + [[Char || Char <- String] || String <- Strings]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Encode an octet string, escape } by \ if necessary +tr_OCTET_STRING(String, _State, Min, Max) when is_list(String) -> + verify_count(length(String), Min, Max), + String. + +tr_QUOTED_STRING(String, _State) when is_list(String) -> + verify_count(length(String), 1, infinity), + String. + +%% The internal format of hex digits is a list of octets +%% Min and Max means #hexDigits +%% Leading zeros are prepended in order to fulfill Min +tr_HEXDIG(Octets, _State, Min, Max) when is_list(Octets) -> + verify_count(length(Octets), Min, Max), + Octets. + +tr_DIGIT(Val, State, Min, Max) -> + tr_integer(Val, State, Min, Max). + +tr_STRING(String, _State) when is_list(String) -> + String. + +tr_STRING(String, _State, Min, Max) when is_list(String) -> + verify_count(length(String), Min, Max), + String. + +tr_opt_UINT16(Val, State) -> + tr_opt_integer(Val, State, 0, 65535). + +tr_UINT16(Val, State) -> + tr_integer(Val, State, 0, 65535). + +tr_UINT32(Val, State) -> + tr_integer(Val, State, 0, 4294967295). + +tr_opt_integer(asn1_NOVALUE, _State, _Min, _Max) -> + asn1_NOVALUE; +tr_opt_integer(Int, State, Min, Max) -> + tr_integer(Int, State, Min, Max). + +tr_integer(Int, _State, Min, Max) -> + verify_count(Int, Min, Max), + Int. + +%% Verify that Count is within the range of Min and Max +verify_count(Count, Min, Max) -> + if + is_integer(Count) -> + if + is_integer(Min) andalso (Count >= Min) -> + if + is_integer(Max) andalso (Count =< Max) -> + Count; + Max =:= infinity -> + Count; + true -> + error({count_too_large, Count, Max}) + end; + true -> + error({count_too_small, Count, Min}) + end; + true -> + error({count_not_an_integer, Count}) + end. + + +%% ------------------------------------------------------------------- + +error(Reason) -> + erlang:error(Reason). + + diff --git a/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_prev3a.set.asn b/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_prev3a.set.asn new file mode 100644 index 0000000000..b9ba7ffdb4 --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_prev3a.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3a.asn diff --git a/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_prev3b.set.asn b/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_prev3b.set.asn new file mode 100644 index 0000000000..0437bde310 --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_prev3b.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3b.asn diff --git a/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_prev3c.set.asn b/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_prev3c.set.asn new file mode 100644 index 0000000000..e78055fbad --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_prev3c.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3c.asn diff --git a/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_v1.set.asn b/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_v1.set.asn new file mode 100644 index 0000000000..0f5a92dba1 --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_v1.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v1.asn diff --git a/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_v2.set.asn b/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_v2.set.asn new file mode 100644 index 0000000000..7fc82b127f --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_v2.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v2.asn diff --git a/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_v3.set.asn b/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_v3.set.asn new file mode 100644 index 0000000000..1d7950a283 --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_v3.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v3.asn diff --git a/lib/megaco/src/binary/megaco_per_bin_encoder.erl b/lib/megaco/src/binary/megaco_per_bin_encoder.erl new file mode 100644 index 0000000000..f7280f4e04 --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_bin_encoder.erl @@ -0,0 +1,447 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose : Handle ASN.1 PER encoding of Megaco/H.248 +%%---------------------------------------------------------------------- + +-module(megaco_per_bin_encoder). + +-behaviour(megaco_encoder). + +-export([encode_message/3, decode_message/3, + decode_mini_message/3, + + encode_transaction/3, + encode_action_requests/3, + encode_action_request/3, + encode_action_reply/3, + + version_of/2]). + +%% Backward compatible functions: +-export([encode_message/2, decode_message/2]). + +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). + +-define(V1_ASN1_MOD, megaco_per_bin_media_gateway_control_v1). +-define(V2_ASN1_MOD, megaco_per_bin_media_gateway_control_v2). +-define(V3_ASN1_MOD, megaco_per_bin_media_gateway_control_v3). +-define(PREV3A_ASN1_MOD, megaco_per_bin_media_gateway_control_prev3a). +-define(PREV3B_ASN1_MOD, megaco_per_bin_media_gateway_control_prev3b). +-define(PREV3C_ASN1_MOD, megaco_per_bin_media_gateway_control_prev3c). +-define(V1_ASN1_MOD_DRV, megaco_per_bin_drv_media_gateway_control_v1). +-define(V2_ASN1_MOD_DRV, megaco_per_bin_drv_media_gateway_control_v2). +-define(V3_ASN1_MOD_DRV, megaco_per_bin_drv_media_gateway_control_v3). +-define(PREV3A_ASN1_MOD_DRV, megaco_per_bin_drv_media_gateway_control_prev3a). +-define(PREV3B_ASN1_MOD_DRV, megaco_per_bin_drv_media_gateway_control_prev3b). +-define(PREV3C_ASN1_MOD_DRV, megaco_per_bin_drv_media_gateway_control_prev3c). + +-define(V1_TRANS_MOD, megaco_binary_transformer_v1). +-define(V2_TRANS_MOD, megaco_binary_transformer_v2). +-define(V3_TRANS_MOD, megaco_binary_transformer_v3). +-define(PREV3A_TRANS_MOD, megaco_binary_transformer_prev3a). +-define(PREV3B_TRANS_MOD, megaco_binary_transformer_prev3b). +-define(PREV3C_TRANS_MOD, megaco_binary_transformer_prev3c). + +-define(BIN_LIB, megaco_binary_encoder_lib). + + +%%---------------------------------------------------------------------- +%% Detect (check/get) message version +%% Return {ok, Version} | {error, Reason} +%%---------------------------------------------------------------------- + +version_of([{version3,v3},driver|EC], Binary) -> + Decoders = [?V1_ASN1_MOD_DRV, ?V2_ASN1_MOD_DRV, ?V3_ASN1_MOD_DRV], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([{version3,prev3c},driver|EC], Binary) -> + Decoders = [?V1_ASN1_MOD_DRV, ?V2_ASN1_MOD_DRV, ?PREV3C_ASN1_MOD_DRV], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([{version3,prev3b},driver|EC], Binary) -> + Decoders = [?V1_ASN1_MOD_DRV, ?V2_ASN1_MOD_DRV, ?PREV3B_ASN1_MOD_DRV], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([{version3,prev3a},driver|EC], Binary) -> + Decoders = [?V1_ASN1_MOD_DRV, ?V2_ASN1_MOD_DRV, ?PREV3A_ASN1_MOD_DRV], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([driver|EC], Binary) -> + Decoders = [?V1_ASN1_MOD_DRV, ?V2_ASN1_MOD_DRV, ?V3_ASN1_MOD_DRV], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([{version3,v3}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?V3_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([{version3,prev3c}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3C_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([{version3,prev3b}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3B_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([{version3,prev3a}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3A_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); + +%% All values we need to take (special) care of has been delt with, +%% so just pass the rest on +version_of(EC, Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?V3_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders). + + +%%---------------------------------------------------------------------- +%% Convert a 'MegacoMessage' record into a binary +%% Return {ok, Binary} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_message(EC, + #'MegacoMessage'{mess = #'Message'{version = V}} = MegaMsg) -> + encode_message(EC, V, MegaMsg). + + +%% -- Version 1 -- + +encode_message([{version3, _},driver|EC], 1, MegaMsg) -> + AsnMod = ?V1_ASN1_MOD_DRV, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([driver|EC], 1, MegaMsg) -> + AsnMod = ?V1_ASN1_MOD_DRV, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,_}|EC], 1, MegaMsg) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); + +%% All values we need to take (special) care of has been delt with, +%% so just pass the rest on +encode_message(EC, 1, MegaMsg) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); + + +%% -- Version 2 -- + +encode_message([{version3,_},driver|EC], 2, MegaMsg) -> + AsnMod = ?V2_ASN1_MOD_DRV, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([driver|EC], 2, MegaMsg) -> + AsnMod = ?V2_ASN1_MOD_DRV, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,_}|EC], 2, MegaMsg) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); + +%% All values we need to take (special) care of has been delt with, +%% so just pass the rest on +encode_message(EC, 2, MegaMsg) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); + + +%% -- Version 3 -- + +encode_message([{version3,v3},driver|EC], 3, MegaMsg) -> + AsnMod = ?V3_ASN1_MOD_DRV, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3c},driver|EC], 3, MegaMsg) -> + AsnMod = ?PREV3C_ASN1_MOD_DRV, + TransMod = ?PREV3C_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3b},driver|EC], 3, MegaMsg) -> + AsnMod = ?PREV3B_ASN1_MOD_DRV, + TransMod = ?PREV3B_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3a},driver|EC], 3, MegaMsg) -> + AsnMod = ?PREV3A_ASN1_MOD_DRV, + TransMod = ?PREV3A_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([driver|EC], 3, MegaMsg) -> + AsnMod = ?V3_ASN1_MOD_DRV, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,v3}|EC], 3, MegaMsg) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3c}|EC], 3, MegaMsg) -> + AsnMod = ?PREV3C_ASN1_MOD, + TransMod = ?PREV3C_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3b}|EC], 3, MegaMsg) -> + AsnMod = ?PREV3B_ASN1_MOD, + TransMod = ?PREV3B_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3a}|EC], 3, MegaMsg) -> + AsnMod = ?PREV3A_ASN1_MOD, + TransMod = ?PREV3A_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); + +%% All values we need to take (special) care of has been delt with, +%% so just pass the rest on +encode_message(EC, 3, MegaMsg) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list). + + +%%---------------------------------------------------------------------- +%% Convert a transaction (or transactions in the case of ack) record(s) +%% into a binary +%% Return {ok, Binary} | {error, Reason} +%%---------------------------------------------------------------------- + +%% encode_transaction([] = EC, 1, Trans) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +%% encode_transaction([native] = EC, 1, Trans) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +%% encode_transaction([driver|EC], 1, Trans) -> +%% AsnMod = ?V1_ASN1_MOD_DRV, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +encode_transaction(_EC, 1, _Trans) -> + %% AsnMod = ?V1_ASN1_MOD, + %% TransMod = ?V1_TRANS_MOD, + %% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, + %% io_list); + {error, not_implemented}; + +%% encode_transaction([] = EC, 2, Trans) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +%% encode_transaction([native] = EC, 2, Trans) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +%% encode_transaction([driver|EC], 2, Trans) -> +%% AsnMod = ?V2_ASN1_MOD_DRV, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +encode_transaction(_EC, 2, _Trans) -> + %% AsnMod = ?V2_ASN1_MOD, + %% TransMod = ?V2_TRANS_MOD, + %% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, + %% io_list). + {error, not_implemented}; + +%% encode_transaction([] = EC, 3, Trans) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +%% encode_transaction([native] = EC, 3, Trans) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +%% encode_transaction([driver|EC], 3, Trans) -> +%% AsnMod = ?V3_ASN1_MOD_DRV, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); +encode_transaction(_EC, 3, _Trans) -> + %% AsnMod = ?V3_ASN1_MOD, + %% TransMod = ?V3_TRANS_MOD, + %% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, %% io_list). + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a list of ActionRequest record's into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +encode_action_requests(_EC, 1, ActReqs) when is_list(ActReqs) -> + %% ?BIN_LIB:encode_action_requests(EC, ActReqs, + %% ?V1_ASN1_MOD, + %% ?V1_TRANS_MOD, + %% io_list); + {error, not_implemented}; +encode_action_requests(_EC, 2, ActReqs) when is_list(ActReqs) -> + %% ?BIN_LIB:encode_action_requests(EC, ActReqs, + %% ?V1_ASN1_MOD, + %% ?V1_TRANS_MOD, + %% io_list). + {error, not_implemented}; +encode_action_requests(_EC, 3, ActReqs) when is_list(ActReqs) -> + %% ?BIN_LIB:encode_action_requests(EC, ActReqs, + %% ?V1_ASN1_MOD, + %% ?V1_TRANS_MOD, + %% io_list). + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a ActionRequest record into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +encode_action_request(_EC, 1, _ActReq) -> + %% ?BIN_LIB:encode_action_request(EC, ActReq, + %% ?V1_ASN1_MOD, + %% ?V1_TRANS_MOD, + %% io_list); + {error, not_implemented}; +encode_action_request(_EC, 2, _ActReq) -> + %% ?BIN_LIB:encode_action_request(EC, ActReq, + %% ?V1_ASN1_MOD, + %% ?V1_TRANS_MOD, + %% io_list). + {error, not_implemented}; +encode_action_request(_EC, 3, _ActReq) -> + %% ?BIN_LIB:encode_action_request(EC, ActReq, + %% ?V1_ASN1_MOD, + %% ?V1_TRANS_MOD, + %% io_list). + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a action reply into a deep io list +%% Not yest supported by this binary codec! +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_action_reply(_EC, _V, _AcionReply) -> + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a binary into a 'MegacoMessage' record +%% Return {ok, MegacoMessageRecord} | {error, Reason} +%%---------------------------------------------------------------------- + +decode_message(EC, Binary) -> + decode_message(EC, 1, Binary). + +%% PER does not support partial decode, so this means V1 +decode_message(EC, dynamic, Binary) -> + decode_message(EC, 1, Binary); + + +%% -- Version 1 -- + +decode_message([{version3,_},driver|EC], 1, Binary) -> + AsnMod = ?V1_ASN1_MOD_DRV, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([driver|EC], 1, Binary) -> + AsnMod = ?V1_ASN1_MOD_DRV, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,_}|EC], 1, Binary) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +%% All values we need to take (special) care of has been delt with, +%% so just pass the rest on +decode_message(EC, 1, Binary) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + + +%% -- Version 2 -- + +decode_message([{version3,_},driver|EC], 2, Binary) -> + AsnMod = ?V2_ASN1_MOD_DRV, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([driver|EC], 2, Binary) -> + AsnMod = ?V2_ASN1_MOD_DRV, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,_}|EC], 2, Binary) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +%% All values we need to take (special) care of has been delt with, +%% so just pass the rest on +decode_message(EC, 2, Binary) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + + +%% -- Version 3 -- + +decode_message([{version3,v3},driver|EC], 3, Binary) -> + AsnMod = ?V3_ASN1_MOD_DRV, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3c},driver|EC], 3, Binary) -> + AsnMod = ?PREV3C_ASN1_MOD_DRV, + TransMod = ?PREV3C_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3b},driver|EC], 3, Binary) -> + AsnMod = ?PREV3B_ASN1_MOD_DRV, + TransMod = ?PREV3B_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3a},driver|EC], 3, Binary) -> + AsnMod = ?PREV3A_ASN1_MOD_DRV, + TransMod = ?PREV3A_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([driver|EC], 3, Binary) -> + AsnMod = ?V3_ASN1_MOD_DRV, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,v3}|EC], 3, Binary) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3c}|EC], 3, Binary) -> + AsnMod = ?PREV3C_ASN1_MOD, + TransMod = ?PREV3C_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3b}|EC], 3, Binary) -> + AsnMod = ?PREV3B_ASN1_MOD, + TransMod = ?PREV3B_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3a}|EC], 3, Binary) -> + AsnMod = ?PREV3A_ASN1_MOD, + TransMod = ?PREV3A_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +%% All values we need to take (special) care of has been delt with, +%% so just pass the rest on +decode_message(EC, 3, Binary) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary). + + +decode_mini_message(_EC, _Vsn, _Bin) -> + {error, not_implemented}. diff --git a/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_prev3a.set.asn b/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_prev3a.set.asn new file mode 100644 index 0000000000..b9ba7ffdb4 --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_prev3a.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3a.asn diff --git a/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_prev3b.set.asn b/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_prev3b.set.asn new file mode 100644 index 0000000000..0437bde310 --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_prev3b.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3b.asn diff --git a/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_prev3c.set.asn b/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_prev3c.set.asn new file mode 100644 index 0000000000..e78055fbad --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_prev3c.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3c.asn diff --git a/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_v1.set.asn b/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_v1.set.asn new file mode 100644 index 0000000000..0f5a92dba1 --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_v1.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v1.asn diff --git a/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_v2.set.asn b/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_v2.set.asn new file mode 100644 index 0000000000..7fc82b127f --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_v2.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v2.asn diff --git a/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_v3.set.asn b/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_v3.set.asn new file mode 100644 index 0000000000..1d7950a283 --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_bin_media_gateway_control_v3.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v3.asn diff --git a/lib/megaco/src/binary/megaco_per_encoder.erl b/lib/megaco/src/binary/megaco_per_encoder.erl new file mode 100644 index 0000000000..596e621c65 --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_encoder.erl @@ -0,0 +1,291 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose : Handle ASN.1 PER encoding of Megaco/H.248 +%%---------------------------------------------------------------------- + +-module(megaco_per_encoder). + +-behaviour(megaco_encoder). + +-export([encode_message/3, decode_message/3, + decode_mini_message/3, + + encode_transaction/3, + encode_action_requests/3, + encode_action_request/3, + encode_action_reply/3, + + version_of/2]). + +%% Backward compatible functions: +-export([encode_message/2, decode_message/2]). + +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). + +-define(V1_ASN1_MOD, megaco_per_media_gateway_control_v1). +-define(V2_ASN1_MOD, megaco_per_media_gateway_control_v2). +-define(V3_ASN1_MOD, megaco_per_media_gateway_control_v3). +-define(PREV3A_ASN1_MOD, megaco_per_media_gateway_control_prev3a). +-define(PREV3B_ASN1_MOD, megaco_per_media_gateway_control_prev3b). +-define(PREV3C_ASN1_MOD, megaco_per_media_gateway_control_prev3c). + +-define(V1_TRANS_MOD, megaco_binary_transformer_v1). +-define(V2_TRANS_MOD, megaco_binary_transformer_v2). +-define(V3_TRANS_MOD, megaco_binary_transformer_v3). +-define(PREV3A_TRANS_MOD, megaco_binary_transformer_prev3a). +-define(PREV3B_TRANS_MOD, megaco_binary_transformer_prev3b). +-define(PREV3C_TRANS_MOD, megaco_binary_transformer_prev3c). + +-define(BIN_LIB, megaco_binary_encoder_lib). + + +%%---------------------------------------------------------------------- +%% Detect (check/get) message version +%% Return {ok, Version} | {error, Reason} +%%---------------------------------------------------------------------- + +version_of([{version3,v3}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?V3_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([{version3,prev3c}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3C_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([{version3,prev3b}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3B_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([{version3,prev3a}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3A_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of(EC, Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?V3_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders). + + +%%---------------------------------------------------------------------- +%% Convert a 'MegacoMessage' record into a binary +%% Return {ok, Binary} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_message(EC, + #'MegacoMessage'{mess = #'Message'{version = V}} = MegaMsg) -> + encode_message(EC, V, MegaMsg). + + +%% -- Version 1 -- + +encode_message([{version3,_}|EC], 1, MegaMsg) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message(EC, 1, MegaMsg) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); + + +%% -- Version 2 -- + +encode_message([{version3,_}|EC], 2, MegaMsg) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message(EC, 2, MegaMsg) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); + + +%% -- Version 3 -- + +encode_message([{version3,v3}|EC], 3, MegaMsg) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3c}|EC], 3, MegaMsg) -> + AsnMod = ?PREV3C_ASN1_MOD, + TransMod = ?PREV3C_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3b}|EC], 3, MegaMsg) -> + AsnMod = ?PREV3B_ASN1_MOD, + TransMod = ?PREV3B_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message([{version3,prev3a}|EC], 3, MegaMsg) -> + AsnMod = ?PREV3A_ASN1_MOD, + TransMod = ?PREV3A_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list); +encode_message(EC, 3, MegaMsg) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:encode_message(EC, MegaMsg, AsnMod, TransMod, io_list). + + +%%---------------------------------------------------------------------- +%% Convert a transaction (or transactions in the case of ack) record(s) +%% into a binary +%% Return {ok, Binary} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_transaction(_EC, 1, _Trans) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); + {error, not_implemented}; +encode_transaction(_EC, 2, _Trans) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); + {error, not_implemented}; +encode_transaction(_EC, 3, _Trans) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_transaction(EC, Trans, AsnMod, TransMod, +%% io_list); + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a list of ActionRequest record's into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +encode_action_requests(_EC, 1, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); + {error, not_implemented}; +encode_action_requests(_EC, 2, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); + {error, not_implemented}; +encode_action_requests(_EC, 3, ActReqs) when is_list(ActReqs) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_action_requests(EC, ActReqs, +%% AsnMod, TransMod, +%% io_list); + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a ActionRequest record into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +encode_action_request(_EC, 1, _ActReq) -> +%% AsnMod = ?V1_ASN1_MOD, +%% TransMod = ?V1_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); + {error, not_implemented}; +encode_action_request(_EC, 2, _ActReq) -> +%% AsnMod = ?V2_ASN1_MOD, +%% TransMod = ?V2_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); + {error, not_implemented}; +encode_action_request(_EC, 3, _ActReq) -> +%% AsnMod = ?V3_ASN1_MOD, +%% TransMod = ?V3_TRANS_MOD, +%% ?BIN_LIB:encode_action_request(EC, ActReq, +%% AsnMod, TransMod, +%% io_list); + {error, not_implemented}. + + + +%%---------------------------------------------------------------------- +%% Convert a action reply into a deep io list +%% Not yest supported by this binary codec! +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_action_reply(_EC, _V, _AcionReply) -> + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a binary into a 'MegacoMessage' record +%% Return {ok, MegacoMessageRecord} | {error, Reason} +%%---------------------------------------------------------------------- + +decode_message(EC, Binary) -> + decode_message(EC, 1, Binary). + +%% PER does not support partial decode, so this means V1 +decode_message(EC, dynamic, Binary) -> + decode_message(EC, 1, Binary); + + +%% -- Version 1 -- + +decode_message([{version3,_}|EC], 1, Binary) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, io_list); +decode_message(EC, 1, Binary) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, io_list); + +%% -- Version 2 -- + +decode_message([{version3,_}|EC], 2, Binary) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, io_list); +decode_message(EC, 2, Binary) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, io_list); + +%% -- Version 3 -- + +decode_message([{version3,v3}|EC], 3, Binary) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, io_list); +decode_message([{version3,prev3c}|EC], 3, Binary) -> + AsnMod = ?PREV3C_ASN1_MOD, + TransMod = ?PREV3C_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, io_list); +decode_message([{version3,prev3b}|EC], 3, Binary) -> + AsnMod = ?PREV3B_ASN1_MOD, + TransMod = ?PREV3B_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, io_list); +decode_message([{version3,prev3a}|EC], 3, Binary) -> + AsnMod = ?PREV3A_ASN1_MOD, + TransMod = ?PREV3A_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, io_list); +decode_message(EC, 3, Binary) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, io_list). + +decode_mini_message(_EC, _Vsn, _Bin) -> + {error, not_implemented}. diff --git a/lib/megaco/src/binary/megaco_per_media_gateway_control_prev3a.set.asn b/lib/megaco/src/binary/megaco_per_media_gateway_control_prev3a.set.asn new file mode 100644 index 0000000000..b9ba7ffdb4 --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_media_gateway_control_prev3a.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3a.asn diff --git a/lib/megaco/src/binary/megaco_per_media_gateway_control_prev3b.set.asn b/lib/megaco/src/binary/megaco_per_media_gateway_control_prev3b.set.asn new file mode 100644 index 0000000000..0437bde310 --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_media_gateway_control_prev3b.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3b.asn diff --git a/lib/megaco/src/binary/megaco_per_media_gateway_control_prev3c.set.asn b/lib/megaco/src/binary/megaco_per_media_gateway_control_prev3c.set.asn new file mode 100644 index 0000000000..e78055fbad --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_media_gateway_control_prev3c.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-prev3c.asn diff --git a/lib/megaco/src/binary/megaco_per_media_gateway_control_v1.set.asn b/lib/megaco/src/binary/megaco_per_media_gateway_control_v1.set.asn new file mode 100644 index 0000000000..0f5a92dba1 --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_media_gateway_control_v1.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v1.asn diff --git a/lib/megaco/src/binary/megaco_per_media_gateway_control_v2.set.asn b/lib/megaco/src/binary/megaco_per_media_gateway_control_v2.set.asn new file mode 100644 index 0000000000..7fc82b127f --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_media_gateway_control_v2.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v2.asn diff --git a/lib/megaco/src/binary/megaco_per_media_gateway_control_v3.set.asn b/lib/megaco/src/binary/megaco_per_media_gateway_control_v3.set.asn new file mode 100644 index 0000000000..1d7950a283 --- /dev/null +++ b/lib/megaco/src/binary/megaco_per_media_gateway_control_v3.set.asn @@ -0,0 +1 @@ +MEDIA-GATEWAY-CONTROL-v3.asn diff --git a/lib/megaco/src/binary/modules.mk b/lib/megaco/src/binary/modules.mk new file mode 100644 index 0000000000..a86ce2aecc --- /dev/null +++ b/lib/megaco/src/binary/modules.mk @@ -0,0 +1,128 @@ +#-*-makefile-*- ; force emacs to enter makefile-mode + +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% + +MODULES = \ + megaco_binary_encoder \ + megaco_binary_encoder_lib \ + megaco_ber_encoder \ + megaco_ber_media_gateway_control_v1 \ + megaco_ber_media_gateway_control_v2 \ + megaco_ber_media_gateway_control_prev3a \ + megaco_ber_media_gateway_control_prev3b \ + megaco_ber_media_gateway_control_prev3c \ + megaco_ber_media_gateway_control_v3 \ + megaco_ber_bin_encoder \ + megaco_ber_bin_media_gateway_control_v1 \ + megaco_ber_bin_media_gateway_control_v2 \ + megaco_ber_bin_media_gateway_control_prev3a \ + megaco_ber_bin_media_gateway_control_prev3b \ + megaco_ber_bin_media_gateway_control_prev3c \ + megaco_ber_bin_media_gateway_control_v3 \ + megaco_ber_bin_drv_media_gateway_control_v1 \ + megaco_ber_bin_drv_media_gateway_control_v2 \ + megaco_ber_bin_drv_media_gateway_control_prev3a \ + megaco_ber_bin_drv_media_gateway_control_prev3b \ + megaco_ber_bin_drv_media_gateway_control_prev3c \ + megaco_ber_bin_drv_media_gateway_control_v3 \ + megaco_per_encoder \ + megaco_per_media_gateway_control_v1 \ + megaco_per_media_gateway_control_v2 \ + megaco_per_media_gateway_control_prev3a \ + megaco_per_media_gateway_control_prev3b \ + megaco_per_media_gateway_control_prev3c \ + megaco_per_media_gateway_control_v3 \ + megaco_per_bin_encoder \ + megaco_per_bin_media_gateway_control_v1 \ + megaco_per_bin_media_gateway_control_v2 \ + megaco_per_bin_media_gateway_control_prev3a \ + megaco_per_bin_media_gateway_control_prev3b \ + megaco_per_bin_media_gateway_control_prev3c \ + megaco_per_bin_media_gateway_control_v3 \ + megaco_per_bin_drv_media_gateway_control_v1 \ + megaco_per_bin_drv_media_gateway_control_v2 \ + megaco_per_bin_drv_media_gateway_control_prev3a \ + megaco_per_bin_drv_media_gateway_control_prev3b \ + megaco_per_bin_drv_media_gateway_control_prev3c \ + megaco_per_bin_drv_media_gateway_control_v3 \ + megaco_binary_name_resolver_v1 \ + megaco_binary_name_resolver_v2 \ + megaco_binary_name_resolver_prev3a \ + megaco_binary_name_resolver_prev3b \ + megaco_binary_name_resolver_prev3c \ + megaco_binary_name_resolver_v3 \ + megaco_binary_term_id \ + megaco_binary_term_id_gen \ + megaco_binary_transformer_v1 \ + megaco_binary_transformer_v2 \ + megaco_binary_transformer_prev3a \ + megaco_binary_transformer_prev3b \ + megaco_binary_transformer_prev3c \ + megaco_binary_transformer_v3 + +INTERNAL_HRL_FILES = + +ASN1_V1_SPEC = MEDIA-GATEWAY-CONTROL-v1 +ASN1_V2_SPEC = MEDIA-GATEWAY-CONTROL-v2 +ASN1_PREV3A_SPEC = MEDIA-GATEWAY-CONTROL-prev3a +ASN1_PREV3B_SPEC = MEDIA-GATEWAY-CONTROL-prev3b +ASN1_PREV3C_SPEC = MEDIA-GATEWAY-CONTROL-prev3c +ASN1_V3_SPEC = MEDIA-GATEWAY-CONTROL-v3 + +BER_ASN1_V1_SPEC = megaco_ber_media_gateway_control_v1 +BER_BIN_ASN1_V1_SPEC = megaco_ber_bin_media_gateway_control_v1 +BER_BIN_DRV_ASN1_V1_SPEC = megaco_ber_bin_drv_media_gateway_control_v1 +PER_ASN1_V1_SPEC = megaco_per_media_gateway_control_v1 +PER_BIN_ASN1_V1_SPEC = megaco_per_bin_media_gateway_control_v1 +PER_BIN_DRV_ASN1_V1_SPEC = megaco_per_bin_drv_media_gateway_control_v1 + +BER_ASN1_V2_SPEC = megaco_ber_media_gateway_control_v2 +BER_BIN_ASN1_V2_SPEC = megaco_ber_bin_media_gateway_control_v2 +BER_BIN_DRV_ASN1_V2_SPEC = megaco_ber_bin_drv_media_gateway_control_v2 +PER_ASN1_V2_SPEC = megaco_per_media_gateway_control_v2 +PER_BIN_ASN1_V2_SPEC = megaco_per_bin_media_gateway_control_v2 +PER_BIN_DRV_ASN1_V2_SPEC = megaco_per_bin_drv_media_gateway_control_v2 + +BER_ASN1_PREV3A_SPEC = megaco_ber_media_gateway_control_prev3a +BER_BIN_ASN1_PREV3A_SPEC = megaco_ber_bin_media_gateway_control_prev3a +BER_BIN_DRV_ASN1_PREV3A_SPEC = megaco_ber_bin_drv_media_gateway_control_prev3a +PER_ASN1_PREV3A_SPEC = megaco_per_media_gateway_control_prev3a +PER_BIN_ASN1_PREV3A_SPEC = megaco_per_bin_media_gateway_control_prev3a +PER_BIN_DRV_ASN1_PREV3A_SPEC = megaco_per_bin_drv_media_gateway_control_prev3a + +BER_ASN1_PREV3B_SPEC = megaco_ber_media_gateway_control_prev3b +BER_BIN_ASN1_PREV3B_SPEC = megaco_ber_bin_media_gateway_control_prev3b +BER_BIN_DRV_ASN1_PREV3B_SPEC = megaco_ber_bin_drv_media_gateway_control_prev3b +PER_ASN1_PREV3B_SPEC = megaco_per_media_gateway_control_prev3b +PER_BIN_ASN1_PREV3B_SPEC = megaco_per_bin_media_gateway_control_prev3b +PER_BIN_DRV_ASN1_PREV3B_SPEC = megaco_per_bin_drv_media_gateway_control_prev3b + +BER_ASN1_PREV3C_SPEC = megaco_ber_media_gateway_control_prev3c +BER_BIN_ASN1_PREV3C_SPEC = megaco_ber_bin_media_gateway_control_prev3c +BER_BIN_DRV_ASN1_PREV3C_SPEC = megaco_ber_bin_drv_media_gateway_control_prev3c +PER_ASN1_PREV3C_SPEC = megaco_per_media_gateway_control_prev3c +PER_BIN_ASN1_PREV3C_SPEC = megaco_per_bin_media_gateway_control_prev3c +PER_BIN_DRV_ASN1_PREV3C_SPEC = megaco_per_bin_drv_media_gateway_control_prev3c + +BER_ASN1_V3_SPEC = megaco_ber_media_gateway_control_v3 +BER_BIN_ASN1_V3_SPEC = megaco_ber_bin_media_gateway_control_v3 +BER_BIN_DRV_ASN1_V3_SPEC = megaco_ber_bin_drv_media_gateway_control_v3 +PER_ASN1_V3_SPEC = megaco_per_media_gateway_control_v3 +PER_BIN_ASN1_V3_SPEC = megaco_per_bin_media_gateway_control_v3 +PER_BIN_DRV_ASN1_V3_SPEC = megaco_per_bin_drv_media_gateway_control_v3 + diff --git a/lib/megaco/src/binary/old/megaco_ber_bin_drv_encoder.erl b/lib/megaco/src/binary/old/megaco_ber_bin_drv_encoder.erl new file mode 100644 index 0000000000..a9217940a1 --- /dev/null +++ b/lib/megaco/src/binary/old/megaco_ber_bin_drv_encoder.erl @@ -0,0 +1,319 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose : Handle ASN.1 BER encoding of Megaco/H.248 +%%---------------------------------------------------------------------- + +-module(megaco_ber_bin_drv_encoder). + +-behaviour(megaco_encoder). + +-export([encode_message/3, decode_message/3, + decode_mini_message/3, + + encode_transaction/3, + encode_action_requests/3, + encode_action_request/3, + encode_action_reply/3, + + version_of/2]). + +%% Backward compatible functions: +-export([encode_message/2, decode_message/2]). + +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). + +-define(V1_ASN1_MOD, megaco_ber_bin_drv_media_gateway_control_v1). +-define(V2_ASN1_MOD, megaco_ber_bin_drv_media_gateway_control_v2). +-define(V3_ASN1_MOD, megaco_ber_bin_drv_media_gateway_control_v3). +-define(PREV3A_ASN1_MOD, megaco_ber_bin_drv_media_gateway_control_prev3a). +-define(PREV3B_ASN1_MOD, megaco_ber_bin_drv_media_gateway_control_prev3b). +-define(PREV3C_ASN1_MOD, megaco_ber_bin_drv_media_gateway_control_prev3c). + +-define(V1_TRANS_MOD, megaco_binary_transformer_v1). +-define(V2_TRANS_MOD, megaco_binary_transformer_v2). +-define(V3_TRANS_MOD, megaco_binary_transformer_v3). +-define(PREV3A_TRANS_MOD, megaco_binary_transformer_prev3a). +-define(PREV3B_TRANS_MOD, megaco_binary_transformer_prev3b). +-define(PREV3C_TRANS_MOD, megaco_binary_transformer_prev3c). + +-define(BIN_LIB, megaco_binary_encoder_lib). + + +%%---------------------------------------------------------------------- +%% Detect (check) which version a message is +%% Return {ok, Version} | {error, Reason} +%%---------------------------------------------------------------------- + +version_of([{version3,v3}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?V3_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,prev3c}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3C_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,prev3b}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3B_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of([{version3,prev3a}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3A_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders); +version_of(EC, Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?V3_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, dynamic, Decoders). + + +%%---------------------------------------------------------------------- +%% Convert a 'MegacoMessage' record into a binary +%% Return {ok, Binary} | {error, Reason} +%%---------------------------------------------------------------------- + + +encode_message(EC, + #'MegacoMessage'{mess = #'Message'{version = V}} = MegaMsg) -> + encode_message(EC, V, MegaMsg). + +encode_message([{version3,_}|EC], 1, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, ?V1_ASN1_MOD, ?V1_TRANS_MOD, io_list); +encode_message(EC, 1, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, ?V1_ASN1_MOD, ?V1_TRANS_MOD, io_list); +encode_message([{version3,_}|EC], 2, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, ?V2_ASN1_MOD, ?V2_TRANS_MOD, io_list); +encode_message(EC, 2, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, ?V2_ASN1_MOD, ?V2_TRANS_MOD, io_list); +encode_message([{version3,v3}|EC], 3, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, ?V3_ASN1_MOD, ?V3_TRANS_MOD, io_list); +encode_message([{version3,prev3c}|EC], 3, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, + ?PREV3C_ASN1_MOD, ?PREV3C_TRANS_MOD, io_list); +encode_message([{version3,prev3b}|EC], 3, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, + ?PREV3B_ASN1_MOD, ?PREV3B_TRANS_MOD, io_list); +encode_message([{version3,prev3a}|EC], 3, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, + ?PREV3A_ASN1_MOD, ?PREV3A_TRANS_MOD, io_list); +encode_message(EC, 3, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, ?V3_ASN1_MOD, ?V3_TRANS_MOD, io_list). + + +%%---------------------------------------------------------------------- +%% Convert a transaction (or transactions in the case of ack) record(s) +%% into a binary +%% Return {ok, Binary} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_transaction(EC, 1, Trans) -> + %% ?BIN_LIB:encode_transaction(EC, Trans, + %% ?V1_ASN1_MOD, + %% ?V1_TRANS_MOD, + %% io_list); + {error, not_implemented}; +encode_transaction(EC, 2, Trans) -> + %% ?BIN_LIB:encode_transaction(EC, Trans, + %% ?V2_ASN1_MOD, + %% ?V2_TRANS_MOD, + %% io_list). + {error, not_implemented}; +encode_transaction(EC, 3, Trans) -> + %% ?BIN_LIB:encode_transaction(EC, Trans, + %% ?V3_ASN1_MOD, + %% ?V3_TRANS_MOD, + %% io_list). + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a list of ActionRequest record's into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +encode_action_requests(EC, 1, ActReqs) when is_list(ActReqs) -> + %% ?BIN_LIB:encode_action_requests(EC, ActReqs, + %% ?V1_ASN1_MOD, + %% ?V1_TRANS_MOD, + %% io_list); + {error, not_implemented}; +encode_action_requests(EC, 2, ActReqs) when is_list(ActReqs) -> + %% ?BIN_LIB:encode_action_requests(EC, ActReqs, + %% ?V2_ASN1_MOD, + %% ?V2_TRANS_MOD, + %% io_list). + {error, not_implemented}; +encode_action_requests(EC, 3, ActReqs) when is_list(ActReqs) -> + %% ?BIN_LIB:encode_action_requests(EC, ActReqs, + %% ?V3_ASN1_MOD, + %% ?V3_TRANS_MOD, + %% io_list). + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a ActionRequest record into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +encode_action_request(EC, 1, ActReq) -> + %% ?BIN_LIB:encode_action_request(EC, ActReq, + %% ?V1_ASN1_MOD, + %% ?V1_TRANS_MOD, + %% io_list); + {error, not_implemented}; +encode_action_request(EC, 2, ActReq) -> + %% ?BIN_LIB:encode_action_request(EC, ActReq, + %% ?V2_ASN1_MOD, + %% ?V2_TRANS_MOD, + %% io_list). + {error, not_implemented}; +encode_action_request(EC, 3, ActReq) -> + %% ?BIN_LIB:encode_action_request(EC, ActReq, + %% ?V3_ASN1_MOD, + %% ?V3_TRANS_MOD, + %% io_list). + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a action reply into a deep io list +%% Not yest supported by this binary codec! +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_action_reply(_EC, _V, _AcionReply) -> + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a binary into a 'MegacoMessage' record +%% Return {ok, MegacoMessageRecord} | {error, Reason} +%%---------------------------------------------------------------------- + +%% Old decode function +decode_message(EC, Binary) -> + decode_message(EC, 1, Binary). + +%% Select from message +%% This does not work at the moment so, we use version 1 for this +decode_message([{version3,v3}|EC], dynamic, Binary) -> + Mods = [{?V1_ASN1_MOD, ?V1_TRANS_MOD}, + {?V2_ASN1_MOD, ?V2_TRANS_MOD}, + {?V3_ASN1_MOD, ?V3_TRANS_MOD}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Mods, binary); +decode_message([{version3,prev3c}|EC], dynamic, Binary) -> + Mods = [{?V1_ASN1_MOD, ?V1_TRANS_MOD}, + {?V2_ASN1_MOD, ?V2_TRANS_MOD}, + {?PREV3C_ASN1_MOD, ?PREV3C_TRANS_MOD}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Mods, binary); +decode_message([{version3,prev3b}|EC], dynamic, Binary) -> + Mods = [{?V1_ASN1_MOD, ?V1_TRANS_MOD}, + {?V2_ASN1_MOD, ?V2_TRANS_MOD}, + {?PREV3B_ASN1_MOD, ?PREV3B_TRANS_MOD}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Mods, binary); +decode_message([{version3,prev3a}|EC], dynamic, Binary) -> + Mods = [{?V1_ASN1_MOD, ?V1_TRANS_MOD}, + {?V2_ASN1_MOD, ?V2_TRANS_MOD}, + {?PREV3A_ASN1_MOD, ?PREV3A_TRANS_MOD}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Mods, binary); +decode_message(EC, dynamic, Binary) -> + Mods = [{?V1_ASN1_MOD, ?V1_TRANS_MOD}, + {?V2_ASN1_MOD, ?V2_TRANS_MOD}, + {?V3_ASN1_MOD, ?V3_TRANS_MOD}], + ?BIN_LIB:decode_message_dynamic(EC, Binary, Mods, binary); + +decode_message([{version3,_}|EC], 1, Binary) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message(EC, 1, Binary) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +decode_message([{version3,_}|EC], 2, Binary) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message(EC, 2, Binary) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +decode_message([{version3,v3}|EC], 3, Binary) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3c}|EC], 3, Binary) -> + AsnMod = ?PREV3C_ASN1_MOD, + TransMod = ?PREV3C_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3b}|EC], 3, Binary) -> + AsnMod = ?PREV3B_ASN1_MOD, + TransMod = ?PREV3B_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3a}|EC], 3, Binary) -> + AsnMod = ?PREV3A_ASN1_MOD, + TransMod = ?PREV3A_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message(EC, 3, Binary) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + + +decode_mini_message([{version3,v3}|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?V3_ASN1_MOD], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3c}|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3C_ASN1_MOD], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3b}|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3B_ASN1_MOD], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message([{version3,prev3a}|EC], dynamic, Bin) -> + Mods = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3A_ASN1_MOD], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); +decode_mini_message(EC, dynamic, Bin) -> + Mods = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?V3_ASN1_MOD], + ?BIN_LIB:decode_mini_message_dynamic(EC, Bin, Mods, binary); + +decode_mini_message([{version3,_}|EC], 1, Bin) -> + AsnMod = ?V1_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message(EC, 1, Bin) -> + AsnMod = ?V1_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,_}|EC], 2, Bin) -> + AsnMod = ?V2_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message(EC, 2, Bin) -> + AsnMod = ?V2_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,v3}|EC], 3, Bin) -> + AsnMod = ?V3_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3c}|EC], 3, Bin) -> + AsnMod = ?PREV3C_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3b}|EC], 3, Bin) -> + AsnMod = ?PREV3B_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message([{version3,prev3a}|EC], 3, Bin) -> + AsnMod = ?PREV3A_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary); +decode_mini_message(EC, 3, Bin) -> + AsnMod = ?V3_ASN1_MOD, + ?BIN_LIB:decode_mini_message(EC, Bin, AsnMod, binary). diff --git a/lib/megaco/src/binary/old/megaco_per_bin_drv_encoder.erl b/lib/megaco/src/binary/old/megaco_per_bin_drv_encoder.erl new file mode 100644 index 0000000000..0afe6d9f36 --- /dev/null +++ b/lib/megaco/src/binary/old/megaco_per_bin_drv_encoder.erl @@ -0,0 +1,255 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose : Handle ASN.1 PER encoding of Megaco/H.248 +%%---------------------------------------------------------------------- + +-module(megaco_per_bin_drv_encoder). + +-behaviour(megaco_encoder). + +-export([encode_message/2, decode_message/2, + encode_message/3, decode_message/3, + decode_mini_message/3, + + encode_transaction/3, + encode_action_requests/3, + encode_action_request/3, + encode_action_reply/3, + + version_of/2]). + +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). + +-define(V1_ASN1_MOD, megaco_per_bin_drv_media_gateway_control_v1). +-define(V2_ASN1_MOD, megaco_per_bin_drv_media_gateway_control_v2). +-define(V3_ASN1_MOD, megaco_per_bin_drv_media_gateway_control_v3). +-define(PREV3A_ASN1_MOD, megaco_per_bin_drv_media_gateway_control_prev3a). +-define(PREV3B_ASN1_MOD, megaco_per_bin_drv_media_gateway_control_prev3b). +-define(PREV3C_ASN1_MOD, megaco_per_bin_drv_media_gateway_control_prev3c). + +-define(V1_TRANS_MOD, megaco_binary_transformer_v1). +-define(V2_TRANS_MOD, megaco_binary_transformer_v2). +-define(V3_TRANS_MOD, megaco_binary_transformer_V3). +-define(PREV3A_TRANS_MOD, megaco_binary_transformer_prev3a). +-define(PREV3B_TRANS_MOD, megaco_binary_transformer_prev3b). +-define(PREV3C_TRANS_MOD, megaco_binary_transformer_prev3c). + +-define(BIN_LIB, megaco_binary_encoder_lib). + + +%%---------------------------------------------------------------------- +%% Detect (check) which version a message is +%% Return {ok, Version} | {error, Reason} +%%---------------------------------------------------------------------- + +version_of([{version3,v3}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?V3_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([{version3,prev3c}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3C_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([{version3,prev3b}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3B_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of([{version3,prev3a}|EC], Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?PREV3A_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders); +version_of(EC, Binary) -> + Decoders = [?V1_ASN1_MOD, ?V2_ASN1_MOD, ?V3_ASN1_MOD], + ?BIN_LIB:version_of(EC, Binary, 1, Decoders). + + +%%---------------------------------------------------------------------- +%% Convert a 'MegacoMessage' record into a binary +%% Return {ok, Binary} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_message(EC, + #'MegacoMessage'{mess = #'Message'{version = V}} = MegaMsg) -> + encode_message(EC, V, MegaMsg). + +encode_message([{version3,_}|EC], 1, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, ?V1_ASN1_MOD, ?V1_TRANS_MOD, io_list); +encode_message(EC, 1, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, ?V1_ASN1_MOD, ?V1_TRANS_MOD, io_list); +encode_message([{version3,_}|EC], 2, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, ?V2_ASN1_MOD, ?V2_TRANS_MOD, io_list); +encode_message(EC, 2, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, ?V2_ASN1_MOD, ?V2_TRANS_MOD, io_list); +encode_message([{version3,v3}|EC], 3, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, ?V3_ASN1_MOD, ?V3_TRANS_MOD, io_list); +encode_message([{version3,prev3c}|EC], 3, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, + ?PREV3C_ASN1_MOD, ?PREV3C_TRANS_MOD, io_list); +encode_message([{version3,prev3b}|EC], 3, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, + ?PREV3B_ASN1_MOD, ?PREV3B_TRANS_MOD, io_list); +encode_message([{version3,prev3a}|EC], 3, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, + ?PREV3A_ASN1_MOD, ?PREV3A_TRANS_MOD, io_list); +encode_message(EC, 3, MegaMsg) -> + ?BIN_LIB:encode_message(EC, MegaMsg, ?V3_ASN1_MOD, ?V3_TRANS_MOD, io_list). + + +%%---------------------------------------------------------------------- +%% Convert a transaction (or transactions in the case of ack) record(s) +%% into a binary +%% Return {ok, Binary} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_transaction(_EC, 1, _Trans) -> + %% ?BIN_LIB:encode_transaction(EC, + %% Trans, + %% ?V1_ASN1_MOD, + %% ?V1_TRANS_MOD, + %% io_list); + {error, not_implemented}; +encode_transaction(_EC, 2, _Trans) -> + %% ?BIN_LIB:encode_transaction(EC, + %% Trans, + %% ?V2_ASN1_MOD, + %% ?V2_TRANS_MOD, + %% io_list). + {error, not_implemented}; +encode_transaction(EC, prev3a, Trans) -> + %% ?BIN_LIB:encode_transaction(EC, Trans, + %% ?V3_ASN1_MOD, + %% ?V3_TRANS_MOD, + %% io_list). + {error, not_implemented}; +encode_transaction(EC, 3, Trans) -> + encode_transaction(EC, prev3a, Trans). + + +%%---------------------------------------------------------------------- +%% Convert a list of ActionRequest record's into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +encode_action_requests(_EC, 1, ActReqs) when is_list(ActReqs) -> + %% ?BIN_LIB:encode_action_requests(EC, ActReqs, + %% ?V1_ASN1_MOD, + %% ?V1_TRANS_MOD, + %% io_list); + {error, not_implemented}; +encode_action_requests(_EC, 2, ActReqs) when is_list(ActReqs) -> + %% ?BIN_LIB:encode_action_requests(EC, ActReqs, + %% ?V1_ASN1_MOD, + %% ?V1_TRANS_MOD, + %% io_list). + {error, not_implemented}; +encode_action_requests(EC, 3, ActReqs) when is_list(ActReqs) -> + %% ?BIN_LIB:encode_action_requests(EC, ActReqs, + %% ?V3_ASN1_MOD, + %% ?V3_TRANS_MOD, + %% io_list). + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a ActionRequest record into a binary +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- +encode_action_request(_EC, 1, _ActReq) -> + %% ?BIN_LIB:encode_action_request(EC, ActReq, + %% ?V1_ASN1_MOD, + %% ?V1_TRANS_MOD, + %% io_list); + {error, not_implemented}; +encode_action_request(_EC, 2, _ActReq) -> + %% ?BIN_LIB:encode_action_request(EC, ActReq, + %% ?V1_ASN1_MOD, + %% ?V1_TRANS_MOD, + %% io_list). + {error, not_implemented}; +encode_action_request(EC, 3, ActReq) -> + %% ?BIN_LIB:encode_action_request(EC, ActReq, + %% ?V3_ASN1_MOD, + %% ?V3_TRANS_MOD, + %% io_list). + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a action reply into a deep io list +%% Not yest supported by this binary codec! +%% Return {ok, DeepIoList} | {error, Reason} +%%---------------------------------------------------------------------- + +encode_action_reply(_EC, _V, _AcionReply) -> + {error, not_implemented}. + + +%%---------------------------------------------------------------------- +%% Convert a binary into a 'MegacoMessage' record +%% Return {ok, MegacoMessageRecord} | {error, Reason} +%%---------------------------------------------------------------------- + +%% Old decode function +decode_message(EC, Binary) -> + decode_message(EC, 1, Binary). + +%% PER does not support partial decode, so this means V1 +decode_message(EC, dynamic, Binary) -> + decode_message(EC, 1, Binary); + +decode_message([{version3,_}|EC], 1, Binary) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message(EC, 1, Binary) -> + AsnMod = ?V1_ASN1_MOD, + TransMod = ?V1_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +decode_message([{version3,_}|EC], 2, Binary) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message(EC, 2, Binary) -> + AsnMod = ?V2_ASN1_MOD, + TransMod = ?V2_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); + +decode_message([{version3,v3}|EC], 3, Binary) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3c}|EC], 3, Binary) -> + AsnMod = ?PREV3C_ASN1_MOD, + TransMod = ?PREV3C_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3b}|EC], 3, Binary) -> + AsnMod = ?PREV3B_ASN1_MOD, + TransMod = ?PREV3B_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message([{version3,prev3a}|EC], 3, Binary) -> + AsnMod = ?PREV3A_ASN1_MOD, + TransMod = ?PREV3A_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary); +decode_message(EC, 3, Binary) -> + AsnMod = ?V3_ASN1_MOD, + TransMod = ?V3_TRANS_MOD, + ?BIN_LIB:decode_message(EC, Binary, AsnMod, TransMod, binary). + +decode_mini_message(_EC, _Vsn, _Bin) -> + {error, not_implemented}. + |