aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer/test/user_SUITE_data
diff options
context:
space:
mode:
authorStavros Aronis <[email protected]>2011-04-02 18:57:42 +0300
committerHenrik Nord <[email protected]>2011-05-04 15:06:15 +0200
commitca4633fd683527097451ca1398c90c87bb5c14fc (patch)
tree3d8e18c9becd4feb7d3ceb1eed24bdce2ef69dd6 /lib/dialyzer/test/user_SUITE_data
parentbc619f0cbf9555df6dfc44a499f0cd9cee8bd1be (diff)
downloadotp-ca4633fd683527097451ca1398c90c87bb5c14fc.tar.gz
otp-ca4633fd683527097451ca1398c90c87bb5c14fc.tar.bz2
otp-ca4633fd683527097451ca1398c90c87bb5c14fc.zip
Rename suite data directories
Diffstat (limited to 'lib/dialyzer/test/user_SUITE_data')
-rw-r--r--lib/dialyzer/test/user_SUITE_data/dialyzer_options2
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/broken_dialyzer0
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/gcpFlowControl2
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/qlc_error0
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/spvcOrig193
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/wsp_pdu25
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/broken_dialyzer.erl130
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/gcp.hrl166
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/gcpFlowControl.erl397
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/qlc_error.erl15
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/spvcOrig.erl3520
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/wdp.hrl96
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/wsp.hrl239
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/wsp_pdu.erl5423
14 files changed, 10208 insertions, 0 deletions
diff --git a/lib/dialyzer/test/user_SUITE_data/dialyzer_options b/lib/dialyzer/test/user_SUITE_data/dialyzer_options
new file mode 100644
index 0000000000..513ed7752b
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/dialyzer_options
@@ -0,0 +1,2 @@
+{dialyzer_options, []}.
+{time_limit, 3}. \ No newline at end of file
diff --git a/lib/dialyzer/test/user_SUITE_data/results/broken_dialyzer b/lib/dialyzer/test/user_SUITE_data/results/broken_dialyzer
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/results/broken_dialyzer
diff --git a/lib/dialyzer/test/user_SUITE_data/results/gcpFlowControl b/lib/dialyzer/test/user_SUITE_data/results/gcpFlowControl
new file mode 100644
index 0000000000..7938c53fc6
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/results/gcpFlowControl
@@ -0,0 +1,2 @@
+
+gcpFlowControl.erl:171: The pattern <Key, 'errors', X> can never match the type <_,'available' | 'bucket' | 'rejectable' | 'rejects' | 'window',0 | 1 | 20>
diff --git a/lib/dialyzer/test/user_SUITE_data/results/qlc_error b/lib/dialyzer/test/user_SUITE_data/results/qlc_error
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/results/qlc_error
diff --git a/lib/dialyzer/test/user_SUITE_data/results/spvcOrig b/lib/dialyzer/test/user_SUITE_data/results/spvcOrig
new file mode 100644
index 0000000000..8c57358af0
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/results/spvcOrig
@@ -0,0 +1,193 @@
+
+spvcOrig.erl:1238: Guard test is_record(Spvc::[] | #spvcObj{},'spvcVcc',25) can never succeed
+spvcOrig.erl:1241: Guard test is_record(Spvc::[] | #spvcObj{},'spvcVpc',20) can never succeed
+spvcOrig.erl:1244: Guard test is_record(Spvc::[] | #spvcObj{},'spvcVpcPerm',12) can never succeed
+spvcOrig.erl:1247: Guard test is_record(Spvc::[] | #spvcObj{},'spvcVccPerm',17) can never succeed
+spvcOrig.erl:1250: Guard test is_record(Spvc::[] | #spvcObj{},'spvcTargetVc',6) can never succeed
+spvcOrig.erl:1253: Guard test is_record(Spvc::[] | #spvcObj{},'spvcTargetVp',6) can never succeed
+spvcOrig.erl:1256: Guard test is_record(Spvc::[] | #spvcObj{},'pchVc',32) can never succeed
+spvcOrig.erl:1259: Guard test is_record(Spvc::[] | #spvcObj{},'pchVp',33) can never succeed
+spvcOrig.erl:1262: Guard test is_record(Spvc::[] | #spvcObj{},'spvcFr',21) can never succeed
+spvcOrig.erl:1265: Guard test is_record(Spvc::[] | #spvcObj{},'spvcFrPerm',6) can never succeed
+spvcOrig.erl:1268: The pattern {If_Value, _, _, _} can never match the type [] | #spvcObj{}
+spvcOrig.erl:1270: The pattern {If_Value, _, _} can never match the type [] | #spvcObj{}
+spvcOrig.erl:1272: The pattern {If_Value, _} can never match the type [] | #spvcObj{}
+spvcOrig.erl:1274: The pattern [If_Value | _] can never match the type [] | #spvcObj{}
+spvcOrig.erl:1380: The variable _ can never match since previous clauses completely covered the type any()
+spvcOrig.erl:1389: The variable _ can never match since previous clauses completely covered the type any()
+spvcOrig.erl:1576: Guard test is_record(Row::[any(),...],'spvcObj',24) can never succeed
+spvcOrig.erl:1583: Guard test is_record(Row::[any(),...],'spvcVcc',25) can never succeed
+spvcOrig.erl:1586: Guard test is_record(Row::[any(),...],'spvcVpc',20) can never succeed
+spvcOrig.erl:1589: Guard test is_record(Row::[any(),...],'spvcVpcPerm',12) can never succeed
+spvcOrig.erl:1592: Guard test is_record(Row::[any(),...],'spvcVccPerm',17) can never succeed
+spvcOrig.erl:1595: Guard test is_record(Row::[any(),...],'spvcTargetVc',6) can never succeed
+spvcOrig.erl:1598: Guard test is_record(Row::[any(),...],'spvcTargetVp',6) can never succeed
+spvcOrig.erl:1601: Guard test is_record(Row::[any(),...],'pchVc',32) can never succeed
+spvcOrig.erl:1604: Guard test is_record(Row::[any(),...],'pchVp',33) can never succeed
+spvcOrig.erl:1607: Guard test is_record(Row::[any(),...],'spvcFr',21) can never succeed
+spvcOrig.erl:1610: Guard test is_record(Row::[any(),...],'spvcFrPerm',6) can never succeed
+spvcOrig.erl:1613: The pattern {If_Value, _, _, _} can never match the type [any(),...]
+spvcOrig.erl:1615: The pattern {If_Value, _, _} can never match the type [any(),...]
+spvcOrig.erl:1617: The pattern {If_Value, _} can never match the type [any(),...]
+spvcOrig.erl:1621: The variable _ can never match since previous clauses completely covered the type [any(),...]
+spvcOrig.erl:1731: The pattern [_, _, _, _] can never match the type tuple()
+spvcOrig.erl:1733: The pattern [_, _, _] can never match the type tuple()
+spvcOrig.erl:1735: The pattern [_, _] can never match the type tuple()
+spvcOrig.erl:264: The pattern {If_Value, Vpi_Value} can never match the type {_,_,_}
+spvcOrig.erl:271: Guard test is_integer(Vci_Value::'no_vc') can never succeed
+spvcOrig.erl:275: The pattern {If_Value, Vpi_Value} can never match the type {_,_,'no_vc'}
+spvcOrig.erl:305: The pattern {'spvcVcc', 'targetAddress'} can never match the type {'spvcFr','rowStatus'} | {'spvcVcc','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:307: The pattern {'spvcVcc', 'selectType'} can never match the type {'spvcFr','rowStatus'} | {'spvcVcc','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:309: The pattern {'spvcVcc', 'targetVpi'} can never match the type {'spvcFr','rowStatus'} | {'spvcVcc','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:311: The pattern {'spvcVcc', 'targetVci'} can never match the type {'spvcFr','rowStatus'} | {'spvcVcc','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:313: The pattern {'spvcVcc', 'releaseCause'} can never match the type {'spvcFr','rowStatus'} | {'spvcVcc','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:315: The pattern {'spvcVcc', 'releaseDiagnostic'} can never match the type {'spvcFr','rowStatus'} | {'spvcVcc','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:317: The pattern {'spvcVcc', 'retryInterval'} can never match the type {'spvcFr','rowStatus'} | {'spvcVcc','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:319: The pattern {'spvcVcc', 'retryTimer'} can never match the type {'spvcFr','rowStatus'} | {'spvcVcc','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:321: The pattern {'spvcVcc', 'retryThreshold'} can never match the type {'spvcFr','rowStatus'} | {'spvcVcc','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:323: The pattern {'spvcVcc', 'retryFailures'} can never match the type {'spvcFr','rowStatus'} | {'spvcVcc','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:325: The pattern {'spvcVcc', 'retryLimit'} can never match the type {'spvcFr','rowStatus'} | {'spvcVcc','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:329: The pattern {'spvcVcc', 'restart'} can never match the type {'spvcFr','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:331: The pattern {'spvcVcc', 'targetSelectType_any'} can never match the type {'spvcFr','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:333: The pattern {'spvcVcc', 'targetSelectType_required'} can never match the type {'spvcFr','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:335: The pattern {'spvcVpc', 'targetAddress'} can never match the type {'spvcFr','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:337: The pattern {'spvcVpc', 'selectType'} can never match the type {'spvcFr','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:339: The pattern {'spvcVpc', 'targetVpi'} can never match the type {'spvcFr','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:341: The pattern {'spvcVpc', 'releaseCause'} can never match the type {'spvcFr','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:343: The pattern {'spvcVpc', 'releaseDiagnostic'} can never match the type {'spvcFr','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:345: The pattern {'spvcVpc', 'retryInterval'} can never match the type {'spvcFr','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:347: The pattern {'spvcVpc', 'retryTimer'} can never match the type {'spvcFr','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:349: The pattern {'spvcVpc', 'retryThreshold'} can never match the type {'spvcFr','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:351: The pattern {'spvcVpc', 'retryFailures'} can never match the type {'spvcFr','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:353: The pattern {'spvcVpc', 'retryLimit'} can never match the type {'spvcFr','rowStatus'} | {'spvcVpc','rowStatus'}
+spvcOrig.erl:357: The pattern {'spvcVpc', 'restart'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:359: The pattern {'spvcVpc', 'targetSelectType_any'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:361: The pattern {'spvcVpc', 'targetSelectType_required'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:363: The pattern {'spvcFr', 'targetAddress'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:365: The pattern {'spvcFr', 'selectType'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:367: The pattern {'spvcFr', 'identifier'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:369: The pattern {'spvcFr', 'targetVpi'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:371: The pattern {'spvcFr', 'targetVci'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:373: The pattern {'spvcFr', 'translation'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:375: The pattern {'spvcFr', 'releaseCause'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:377: The pattern {'spvcFr', 'releaseDiagnostic'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:379: The pattern {'spvcFr', 'operStatus'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:381: The pattern {'spvcFr', 'adminStatus'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:383: The pattern {'spvcFr', 'restart'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:385: The pattern {'spvcFr', 'retryInterval'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:387: The pattern {'spvcFr', 'retryTimer'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:389: The pattern {'spvcFr', 'retryThreshold'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:391: The pattern {'spvcFr', 'retryFailures'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:393: The pattern {'spvcFr', 'retryLimit'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:395: The pattern {'spvcFr', 'lastChange'} can never match the type {'spvcFr','rowStatus'}
+spvcOrig.erl:404: Guard test is_record(Row::[any(),...],'spvcObj',24) can never succeed
+spvcOrig.erl:411: Guard test is_record(Row::[any(),...],'spvcVcc',25) can never succeed
+spvcOrig.erl:414: Guard test is_record(Row::[any(),...],'spvcVpc',20) can never succeed
+spvcOrig.erl:417: Guard test is_record(Row::[any(),...],'spvcVpcPerm',12) can never succeed
+spvcOrig.erl:420: Guard test is_record(Row::[any(),...],'spvcVccPerm',17) can never succeed
+spvcOrig.erl:423: Guard test is_record(Row::[any(),...],'spvcTargetVc',6) can never succeed
+spvcOrig.erl:426: Guard test is_record(Row::[any(),...],'spvcTargetVp',6) can never succeed
+spvcOrig.erl:429: Guard test is_record(Row::[any(),...],'pchVc',32) can never succeed
+spvcOrig.erl:432: Guard test is_record(Row::[any(),...],'pchVp',33) can never succeed
+spvcOrig.erl:435: Guard test is_record(Row::[any(),...],'spvcFr',21) can never succeed
+spvcOrig.erl:438: Guard test is_record(Row::[any(),...],'spvcFrPerm',6) can never succeed
+spvcOrig.erl:441: The pattern {If_Value, _, _, _} can never match the type [any(),...]
+spvcOrig.erl:443: The pattern {If_Value, _, _} can never match the type [any(),...]
+spvcOrig.erl:445: The pattern {If_Value, _} can never match the type [any(),...]
+spvcOrig.erl:449: The variable _ can never match since previous clauses completely covered the type [any(),...]
+spvcOrig.erl:468: Guard test is_record(Row::[any(),...],'spvcObj',24) can never succeed
+spvcOrig.erl:475: Guard test is_record(Row::[any(),...],'spvcVcc',25) can never succeed
+spvcOrig.erl:478: Guard test is_record(Row::[any(),...],'spvcVpc',20) can never succeed
+spvcOrig.erl:481: Guard test is_record(Row::[any(),...],'spvcVpcPerm',12) can never succeed
+spvcOrig.erl:484: Guard test is_record(Row::[any(),...],'spvcVccPerm',17) can never succeed
+spvcOrig.erl:487: Guard test is_record(Row::[any(),...],'spvcTargetVc',6) can never succeed
+spvcOrig.erl:490: Guard test is_record(Row::[any(),...],'spvcTargetVp',6) can never succeed
+spvcOrig.erl:493: Guard test is_record(Row::[any(),...],'pchVc',32) can never succeed
+spvcOrig.erl:496: Guard test is_record(Row::[any(),...],'pchVp',33) can never succeed
+spvcOrig.erl:499: Guard test is_record(Row::[any(),...],'spvcFr',21) can never succeed
+spvcOrig.erl:502: Guard test is_record(Row::[any(),...],'spvcFrPerm',6) can never succeed
+spvcOrig.erl:505: The pattern {If_Value, _, _, _} can never match the type [any(),...]
+spvcOrig.erl:507: The pattern {If_Value, _, _} can never match the type [any(),...]
+spvcOrig.erl:509: The pattern {If_Value, _} can never match the type [any(),...]
+spvcOrig.erl:513: The variable _ can never match since previous clauses completely covered the type [any(),...]
+spvcOrig.erl:546: The pattern {_, _, _, _} can never match the type [any(),...]
+spvcOrig.erl:548: The pattern {_, _, _} can never match the type [any(),...]
+spvcOrig.erl:550: The pattern {_, _} can never match the type [any(),...]
+spvcOrig.erl:559: The pattern {'spvcVcc', 'targetAddress'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:561: The pattern {'spvcVcc', 'selectType'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:563: The pattern {'spvcVcc', 'targetVpi'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:565: The pattern {'spvcVcc', 'targetVci'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:567: The pattern {'spvcVcc', 'releaseCause'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:569: The pattern {'spvcVcc', 'releaseDiagnostic'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:571: The pattern {'spvcVcc', 'retryInterval'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:573: The pattern {'spvcVcc', 'retryTimer'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:575: The pattern {'spvcVcc', 'retryThreshold'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:577: The pattern {'spvcVcc', 'retryFailures'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:579: The pattern {'spvcVcc', 'retryLimit'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:581: The pattern {'spvcVcc', 'rowStatus'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:585: The pattern {'spvcVcc', 'targetSelectType_any'} can never match the type {'spvcFr','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:587: The pattern {'spvcVcc', 'targetSelectType_required'} can never match the type {'spvcFr','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:589: The pattern {'spvcVpc', 'targetAddress'} can never match the type {'spvcFr','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:591: The pattern {'spvcVpc', 'selectType'} can never match the type {'spvcFr','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:593: The pattern {'spvcVpc', 'targetVpi'} can never match the type {'spvcFr','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:595: The pattern {'spvcVpc', 'releaseCause'} can never match the type {'spvcFr','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:597: The pattern {'spvcVpc', 'releaseDiagnostic'} can never match the type {'spvcFr','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:599: The pattern {'spvcVpc', 'retryInterval'} can never match the type {'spvcFr','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:601: The pattern {'spvcVpc', 'retryTimer'} can never match the type {'spvcFr','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:603: The pattern {'spvcVpc', 'retryThreshold'} can never match the type {'spvcFr','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:605: The pattern {'spvcVpc', 'retryFailures'} can never match the type {'spvcFr','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:607: The pattern {'spvcVpc', 'retryLimit'} can never match the type {'spvcFr','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:609: The pattern {'spvcVpc', 'rowStatus'} can never match the type {'spvcFr','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:613: The pattern {'spvcVpc', 'targetSelectType_any'} can never match the type {'spvcFr','restart'}
+spvcOrig.erl:615: The pattern {'spvcVpc', 'targetSelectType_required'} can never match the type {'spvcFr','restart'}
+spvcOrig.erl:617: The pattern {'spvcFr', 'targetAddress'} can never match the type {'spvcFr','restart'}
+spvcOrig.erl:619: The pattern {'spvcFr', 'selectType'} can never match the type {'spvcFr','restart'}
+spvcOrig.erl:621: The pattern {'spvcFr', 'identifier'} can never match the type {'spvcFr','restart'}
+spvcOrig.erl:623: The pattern {'spvcFr', 'targetVpi'} can never match the type {'spvcFr','restart'}
+spvcOrig.erl:625: The pattern {'spvcFr', 'targetVci'} can never match the type {'spvcFr','restart'}
+spvcOrig.erl:627: The pattern {'spvcFr', 'translation'} can never match the type {'spvcFr','restart'}
+spvcOrig.erl:629: The pattern {'spvcFr', 'releaseCause'} can never match the type {'spvcFr','restart'}
+spvcOrig.erl:631: The pattern {'spvcFr', 'releaseDiagnostic'} can never match the type {'spvcFr','restart'}
+spvcOrig.erl:633: The pattern {'spvcFr', 'operStatus'} can never match the type {'spvcFr','restart'}
+spvcOrig.erl:635: The pattern {'spvcFr', 'adminStatus'} can never match the type {'spvcFr','restart'}
+spvcOrig.erl:639: The pattern {'spvcFr', 'retryInterval'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:641: The pattern {'spvcFr', 'retryTimer'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:643: The pattern {'spvcFr', 'retryThreshold'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:645: The pattern {'spvcFr', 'retryFailures'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:647: The pattern {'spvcFr', 'retryLimit'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:649: The pattern {'spvcFr', 'lastChange'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:651: The pattern {'spvcFr', 'rowStatus'} can never match the type {'spvcFr','restart'} | {'spvcVcc','restart'} | {'spvcVpc','restart'}
+spvcOrig.erl:730: Guard test is_record(Spvc::[] | #spvcObj{},'spvcVcc',25) can never succeed
+spvcOrig.erl:733: Guard test is_record(Spvc::[] | #spvcObj{},'spvcVpc',20) can never succeed
+spvcOrig.erl:736: Guard test is_record(Spvc::[] | #spvcObj{},'spvcVpcPerm',12) can never succeed
+spvcOrig.erl:739: Guard test is_record(Spvc::[] | #spvcObj{},'spvcVccPerm',17) can never succeed
+spvcOrig.erl:742: Guard test is_record(Spvc::[] | #spvcObj{},'spvcTargetVc',6) can never succeed
+spvcOrig.erl:745: Guard test is_record(Spvc::[] | #spvcObj{},'spvcTargetVp',6) can never succeed
+spvcOrig.erl:748: Guard test is_record(Spvc::[] | #spvcObj{},'pchVc',32) can never succeed
+spvcOrig.erl:751: Guard test is_record(Spvc::[] | #spvcObj{},'pchVp',33) can never succeed
+spvcOrig.erl:754: Guard test is_record(Spvc::[] | #spvcObj{},'spvcFr',21) can never succeed
+spvcOrig.erl:757: Guard test is_record(Spvc::[] | #spvcObj{},'spvcFrPerm',6) can never succeed
+spvcOrig.erl:760: The pattern {If_Value, _, _, _} can never match the type [] | #spvcObj{}
+spvcOrig.erl:762: The pattern {If_Value, _, _} can never match the type [] | #spvcObj{}
+spvcOrig.erl:764: The pattern {If_Value, _} can never match the type [] | #spvcObj{}
+spvcOrig.erl:766: The pattern [If_Value | _] can never match the type [] | #spvcObj{}
+spvcOrig.erl:802: Guard test is_record(Spvc::[] | #spvcObj{},'spvcVcc',25) can never succeed
+spvcOrig.erl:805: Guard test is_record(Spvc::[] | #spvcObj{},'spvcVpc',20) can never succeed
+spvcOrig.erl:808: Guard test is_record(Spvc::[] | #spvcObj{},'spvcVpcPerm',12) can never succeed
+spvcOrig.erl:811: Guard test is_record(Spvc::[] | #spvcObj{},'spvcVccPerm',17) can never succeed
+spvcOrig.erl:814: Guard test is_record(Spvc::[] | #spvcObj{},'spvcTargetVc',6) can never succeed
+spvcOrig.erl:817: Guard test is_record(Spvc::[] | #spvcObj{},'spvcTargetVp',6) can never succeed
+spvcOrig.erl:820: Guard test is_record(Spvc::[] | #spvcObj{},'pchVc',32) can never succeed
+spvcOrig.erl:823: Guard test is_record(Spvc::[] | #spvcObj{},'pchVp',33) can never succeed
+spvcOrig.erl:826: Guard test is_record(Spvc::[] | #spvcObj{},'spvcFr',21) can never succeed
+spvcOrig.erl:829: Guard test is_record(Spvc::[] | #spvcObj{},'spvcFrPerm',6) can never succeed
+spvcOrig.erl:832: The pattern {If_Value, _, _, _} can never match the type [] | #spvcObj{}
+spvcOrig.erl:834: The pattern {If_Value, _, _} can never match the type [] | #spvcObj{}
+spvcOrig.erl:836: The pattern {If_Value, _} can never match the type [] | #spvcObj{}
+spvcOrig.erl:838: The pattern [If_Value | _] can never match the type [] | #spvcObj{}
+spvcOrig.erl:951: The pattern [IfIndex_Value, Vpi_Value, Vci_Value, _] can never match the type tuple()
+spvcOrig.erl:953: The pattern [IfIndex_Value, Vpi_Value, _] can never match the type tuple()
+spvcOrig.erl:974: The pattern [IfIndex_Value, Vpi_Value, Vci_Value, _] can never match the type tuple()
+spvcOrig.erl:976: The pattern [IfIndex_Value, Vpi_Value, _] can never match the type tuple()
+spvcOrig.erl:996: The pattern [IfIndex_Value, Vpi_Value, Vci_Value, _] can never match the type tuple()
+spvcOrig.erl:998: The pattern [IfIndex_Value, Vpi_Value, _] can never match the type tuple()
diff --git a/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu b/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu
new file mode 100644
index 0000000000..a47b1f1f2c
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu
@@ -0,0 +1,25 @@
+
+wsp_pdu.erl:1063: The pattern [H | Hs] can never match the type []
+wsp_pdu.erl:1162: The call wsp_pdu:parse_push_flag(Value::[any()]) will never return since it differs in the 1st argument from the success typing arguments: (integer())
+wsp_pdu.erl:2400: Function decode_retry_after/2 has no local return
+wsp_pdu.erl:2403: The call wsp_pdu:d_date(Data1::binary()) will never return since it differs in the 1st argument from the success typing arguments: (integer() | {'short',binary()})
+wsp_pdu.erl:2406: Guard test is_integer(Sec::{[byte()] | byte() | {'long',binary()} | {'short',binary()},binary()}) can never succeed
+wsp_pdu.erl:2408: The pattern {'short', Data2} can never match the type {[byte()] | byte() | {'long',binary()} | {'short',binary()},binary()}
+wsp_pdu.erl:2755: Function parse_push_flag/1 has no local return
+wsp_pdu.erl:2756: The call erlang:integer_to_list(Value::[any()]) will never return since it differs in the 1st argument from the success typing arguments: (integer())
+wsp_pdu.erl:2875: The call wsp_pdu:d_text_string(Data::byte()) will never return since it differs in the 1st argument from the success typing arguments: (binary())
+wsp_pdu.erl:2976: The call wsp_pdu:d_q_value(QData::byte()) will never return since it differs in the 1st argument from the success typing arguments: (<<_:8,_:_*8>>)
+wsp_pdu.erl:3336: The call wsp_pdu:encode_typed_field(Ver::any(),'Q-value',ParamValue::any()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),'Constrained-encoding' | 'Date-value' | 'No-value' | 'Short-integer' | 'Text-string' | 'Text-value' | 'Well-known-charset',any())
+wsp_pdu.erl:3342: The call wsp_pdu:encode_typed_field(Ver::any(),'Ver-value',ParamValue::any()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),'Constrained-encoding' | 'Date-value' | 'No-value' | 'Short-integer' | 'Text-string' | 'Text-value' | 'Well-known-charset',any())
+wsp_pdu.erl:3349: The call wsp_pdu:encode_typed_field(Ver::any(),'Integer-value',ParamValue::any()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),'Constrained-encoding' | 'Date-value' | 'No-value' | 'Short-integer' | 'Text-string' | 'Text-value' | 'Well-known-charset',any())
+wsp_pdu.erl:3367: The call wsp_pdu:encode_typed_field(Ver::any(),'Field-name',ParamValue::any()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),'Constrained-encoding' | 'Date-value' | 'No-value' | 'Short-integer' | 'Text-string' | 'Text-value' | 'Well-known-charset',any())
+wsp_pdu.erl:3405: The call wsp_pdu:encode_typed_field(Ver::any(),'Delta-seconds-value',ParamValue::any()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),'Constrained-encoding' | 'Date-value' | 'No-value' | 'Short-integer' | 'Text-string' | 'Text-value' | 'Well-known-charset',any())
+wsp_pdu.erl:3437: The call wsp_pdu:encode_typed_field(Ver::any(),'Integer-value',ParamValue::any()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),'Constrained-encoding' | 'Date-value' | 'No-value' | 'Short-integer' | 'Text-string' | 'Text-value' | 'Well-known-charset',any())
+wsp_pdu.erl:3455: The call wsp_pdu:decode_typed_field('Version-value',Data::binary(),Version::any()) will never return since it differs in the 1st argument from the success typing arguments: ('Constrained-encoding' | 'Date-value' | 'Delta-seconds-value' | 'Field-name' | 'No-value' | 'Q-value' | 'Short-integer' | 'Text-string' | 'Text-value' | 'Well-known-charset',binary(),any())
+wsp_pdu.erl:3459: The call wsp_pdu:decode_typed_field('Integer-value',Data::binary(),Version::any()) will never return since it differs in the 1st argument from the success typing arguments: ('Constrained-encoding' | 'Date-value' | 'Delta-seconds-value' | 'Field-name' | 'No-value' | 'Q-value' | 'Short-integer' | 'Text-string' | 'Text-value' | 'Well-known-charset',binary(),any())
+wsp_pdu.erl:3531: The call wsp_pdu:decode_typed_field('Integer-value',Data::binary(),Version::any()) will never return since it differs in the 1st argument from the success typing arguments: ('Constrained-encoding' | 'Date-value' | 'Delta-seconds-value' | 'Field-name' | 'No-value' | 'Q-value' | 'Short-integer' | 'Text-string' | 'Text-value' | 'Well-known-charset',binary(),any())
+wsp_pdu.erl:3593: The pattern 'Delta-Seconds-value' can never match the type 'Delta-seconds-value' | 'Field-name' | 'Integer-value' | 'No-value' | 'Q-value' | 'Ver-value'
+wsp_pdu.erl:4844: The call wsp_pdu:d_long('data') will never return since it differs in the 1st argument from the success typing arguments: (binary())
+wsp_pdu.erl:510: The variable _ can never match since previous clauses completely covered the type 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
+wsp_pdu.erl:512: The variable _ can never match since previous clauses completely covered the type 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
+wsp_pdu.erl:5265: Call to missing or unexported function inet:ip_to_bytes/1
diff --git a/lib/dialyzer/test/user_SUITE_data/src/broken_dialyzer.erl b/lib/dialyzer/test/user_SUITE_data/src/broken_dialyzer.erl
new file mode 100644
index 0000000000..1e0612a345
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/broken_dialyzer.erl
@@ -0,0 +1,130 @@
+-module(broken_dialyzer).
+
+-export([do_move_next/1]).
+
+-define(ap_indices, 512).
+-define(dp_indices, 504).
+
+
+-record(apR,{a,c=[],n=[],nc=0,nn=0,nl=[]}).
+-define(apL(L), [#apR{a=A} || A <- L]).
+
+-define(gr, get(my_return_value)).
+-define(pr(PR), put(my_return_value, PR)).
+-record(bit,{i,c,n,s}). % index, current, next, state
+
+
+do_move_next({BL,AL}) ->
+ Max = max(length(BL), length(AL)),
+ Max2 = max(length(BL)*2, length(AL)),
+ MoveTo = [A || A <- AL, A#apR.nn < Max, A#apR.nn+A#apR.nc < Max2],
+ MoveFrom = [A || A <- AL,
+ (A#apR.nn > Max) orelse (A#apR.nn+A#apR.nc > Max2)],
+ Unchanged = (AL--MoveTo)--MoveFrom,
+ {BL1,{AL1,{AL2,AL3}}} =
+ lists:mapfoldl(
+ fun(B=#bit{i=I,c=C,s=S,n=Next}, {From,{To,FilledUp}})
+ when S==ok;S==lost_replica;S==moved_replica ->
+ case lists:keysearch(Next,#apR.a,From) of
+ {value, F=#apR{n=N1,nn=NN1,nc=NC1}}
+ when (NN1>Max) or (NN1+NC1>Max2) ->
+ case C of
+ [] ->
+ {B, {From,{To,FilledUp}}};
+ ShortList ->
+ T=#apR{a=NewNext,n=N2,nn=NN2} =
+ find_next(Next,ShortList),
+ {value, {C,NL_from}} =
+ lists:keysearch(C,1,F#apR.nl),
+ {value, {C,NL_to}} =
+ lists:keysearch(C,1,T#apR.nl),
+ NewNL_from = lists:keyreplace(
+ C,1,F#apR.nl,{C,NL_from--[I]}),
+ NewNL_to = lists:keyreplace(
+ C,1,T#apR.nl,{C,[I|NL_to]}),
+
+ NewT = T#apR{n=[I|N2],nn=NN2+1,
+ nl=NewNL_to},
+
+ {B#bit{n=NewNext,
+ s = if
+ S == lost_replica ->
+ lost_replica;
+ true ->
+ moved_replica
+ end},
+ {lists:keyreplace(
+ Next,#apR.a,From,
+ F#apR{n=N1--[I],nn=NN1-1,nl=NewNL_from}),
+ if
+ (NewT#apR.nn+NewT#apR.nc >= Max2)
+ or (NewT#apR.nn >= Max) ->
+ {lists:keydelete(NewNext,#apR.a,To),
+ [NewT|FilledUp]};
+ true ->
+ {lists:keyreplace(
+ NewNext,#apR.a,To,NewT),
+ FilledUp}
+ end}}
+ end;
+ _ ->
+ {B, {From,{To,FilledUp}}}
+ end;
+ (B, A) ->
+ {B, A}
+ end, {MoveFrom,{MoveTo,[]}},BL),
+ {BL1,Unchanged++AL1++AL2++AL3}.
+
+%%% -----------------------------------------------------------------
+%%% find_next/2
+%%%
+%%% ------------------------------------------------------------------
+
+find_next(Ap,L) ->
+ hd(catch
+ lists:foreach(
+ fun(SelVal) ->
+ case [ApR ||
+ ApR <- L,
+ begin
+ {value,{Ap,NL}} =
+ lists:keysearch(Ap,1,ApR#apR.nl),
+ length(NL) =< SelVal
+ end] of
+ [] ->
+ ok;
+ ShortList ->
+ throw(ShortList)
+ end
+ end,
+ lists:seq(0,?ap_indices))).
+
+%%% -----------------------------------------------------------------
+%%% max/2
+%%%
+%%% Calculates max number of indices per AP, given number of indices
+%%% and number of APs.
+%%% -----------------------------------------------------------------
+max(F,S) ->
+ (F div S) + if
+ (F rem S) == 0 ->
+ 0;
+ true ->
+ 1
+ end.
+
+%%% ==============================================================
+%%% ADMINISTRATIVE INFORMATION
+%%% ==============================================================
+%%% #Copyright (C) 2005
+%%% by ERICSSON TELECOM AB
+%%% S - 125 26 STOCKHOLM
+%%% SWEDEN, tel int + 46 8 719 0000
+%%%
+%%% The program may be used and/or copied only with the written
+%%% permission from ERICSSON TELECOM AB, or in accordance with
+%%% the terms and conditions stipulated in the agreement/contract
+%%% under which the program has been supplied.
+%%%
+%%% All rights reserved
+%%%
diff --git a/lib/dialyzer/test/user_SUITE_data/src/gcp.hrl b/lib/dialyzer/test/user_SUITE_data/src/gcp.hrl
new file mode 100644
index 0000000000..0b0f1246b5
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/gcp.hrl
@@ -0,0 +1,166 @@
+%%% #0. BASIC INFORMATION
+%%% ----------------------------------------------------------
+%%% %CCaseFile: gcp.hrl %
+%%% Author: EAB/UPD/AV
+%%% Description: Internal include file.
+%%% ----------------------------------------------------------
+-hrl_id('9/190 55-CNA 113 033 Ux').
+-hrl_vsn('/main/R1A/21').
+-hrl_date('2005-05-31').
+-hrl_author('uabasve').
+%%% %CCaseTemplateFile: module.hrl %
+%%% %CCaseTemplateId: 17/002 01-FEA 202 714 Ux, Rev: /main/4 %
+%%%
+%%% Copyright (C) 2000-2005 by Ericsson Telecom AB
+%%% SE-126 25 STOCKHOLM
+%%% SWEDEN, tel int + 46 8 719 0000
+%%%
+%%% The program may be used and/or copied only with the written
+%%% permission from Ericsson Telecom AB, or in accordance with
+%%% the terms and conditions stipulated in the agreement/contract
+%%% under which the program has been supplied.
+%%%
+%%% All rights reserved
+%%%
+%%% ----------------------------------------------------------
+%%% #1. REVISION LOG
+%%% ----------------------------------------------------------
+%%% Rev Date Name What
+%%% ----- ------- -------- ------------------------
+%%% R1A/1 05-02-07 uabasve Copied from EAS R7A/9
+%%% R1A/2 05-02-08 ejojmjn Removed SAAL
+%%% R1A/3- 05-03-18 uabasve Clean.
+%%% ----------------------------------------------------------
+%%%
+%%% #2. CODE
+%%% #---------------------------------------------------------
+%%% #2.1 DEFINITION OF CONSTANTS
+%%% #---------------------------------------------------------
+
+%% Keys into gcpVariables for various options/values.
+-define(TRAFFIC_DESCRIPTOR_KEY, traffic_descriptor).
+
+%% H.248 version at link creation.
+-define(INITIAL_H248_VERSION, 1).
+
+%% Exceptions for use within a module. ?MODULE is just extra protection
+%% against catching something unexpected.
+-define(THROW(Reason), throw({error, ?MODULE, ?LINE, Reason})).
+-define(CATCH(Expr), try Expr
+ catch throw: ?FAILURE(Reason) -> {error, Reason}
+ end).
+-define(FAILURE(T), {error, ?MODULE, _, T}).
+
+%% The SendHandle used by a GCP transport process must be a tuple
+%% of length >= 2 whose first two elements are the pid of the
+%% transport process and index (aka #gcpLinkTable.key) of the link
+%% upon which incoming data has arrived.
+-define(SH_PID(SendHandle), element(1, SendHandle)).
+-define(SH_LINK(SendHandle), element(2, SendHandle)).
+-define(SH_SET_PID(SendHandle, Pid), setelement(1, SendHandle, Pid)).
+
+%% Megaco process that CH and OM servers monitor. This needs to be
+%% replaced by a documented method.
+-define(MEGACO_APP, megaco_config).
+
+%% The message that gcpI:send_reply sends to the process that's waiting
+%% for an action reply.
+-define(ACTION_REPLY_MESSAGE(ActionReplies, Result),
+ {reply, ActionReplies, Result}).
+
+%%% #---------------------------------------------------------
+%%% #2.2 DEFINITION OF RECORDS
+%%% #---------------------------------------------------------
+
+-record(mg, {pref}).
+-record(mgc, {mgid}).
+
+%% User configuration that gets mapped into megaco user info by
+%% gcpLib:make_user_info/1. GCP exposes only a subset of what's
+%% possible to set in megaco.
+-record(user_config,
+ {reply_timer = 30000, %% ms to wait for reply ack
+ %% Incoming transactions:
+ pending_timer = 10000, %% ms until outgoing transaction pending
+ sent_pending_limit = 5, %% nr of outgoing pendings before 506
+ %% Outgoing transactions:
+ recv_pending_limit = infinity,%% nr of incoming pendings before fail
+ request_timer = 3000, %% ms to wait for response before resend
+ request_retries = 5, %% nr unanswered sends before fail
+ long_request_timer = 15000, %% ms to wait for reply after pending
+ long_request_retries = 5}). %% nr of pendings/timeouts before fail
+
+%% Record passed into transport implementations at transport start.
+%% Expected to be passed back to gcpTransportI.
+-record(receive_handle,
+ {megaco_receive_handle, %% passed to megaco:receive_message
+ receive_message}). %% gcpLinkTable.receive_message
+
+%%% ---------------------------------------------------------------------------
+%%% # gcpRegistrationTable
+%%%
+%%% Record containing defined MGC's/MG's (aka megaco users).
+%%% ---------------------------------------------------------------------------
+
+-record(gcpRegistrationTable,
+ {key, %% user reference (aka MG/MGC id)
+ role, %% mg | mgc
+ mid, %% H.248 mid of the MGC/MG
+ version, %% of H.248
+ callback, %% {Module, ExtraArgs}
+ config = #user_config{}}).
+
+%%% ----------------------------------------------------------
+%%% # gcpLinkTable
+%%% ----------------------------------------------------------
+
+-record(gcpLinkTable,
+ {key, %% link reference
+ endpoint, %% #mgc{} | #mg{}
+ user, %% registration table key
+ chid, %% call handler of transport
+ admin_state, %% up | down
+ op_state, %% up | down | pending | disabled
+ restart = auto, %% auto | user
+ encoding_mod, %% module implementing megaco_encoder
+ encoding_config, %% as passed to encoding_mod
+ transport_start, %% {M,F,ExtraArgs} for transport start
+ transport_data, %% arbitrary, passed to transport_mod
+ send_message, %% {default|sysrpc|transport|module, Module}
+ receive_message, %% local | {M,F,ExtraArgs} for decode node
+ tried = false, %% Only for links owned by a MG.
+ %% Used to indicate that a setup attempt
+ %% has been performed on this link.
+ t95_period = 350000}).
+
+%%% ----------------------------------------------------------
+%%% # gcpActiveLinkTable
+%%% ----------------------------------------------------------
+
+-record(gcpActiveLinkTable,
+ {key, %% {mg|mgc, MgId}
+ link, %% link reference
+ chid, %% CH the link is tied to
+ node, %% node the link is on
+ conn_handle, %% record megaco_conn_handle
+ send_handle, %% {TransportPid, LinkIdx, ...}
+ version = ?INITIAL_H248_VERSION}).
+
+%%% ----------------------------------------------------------
+%%% # gcpVariables
+%%% ----------------------------------------------------------
+
+-record(gcpVariables,
+ {key,
+ value}).
+
+%%% ----------------------------------------------------------
+%%% # gcpReplyData
+%%% ----------------------------------------------------------
+
+-record(gcpReplyData,
+ {callback, %% {Module, Args}
+ mgid,
+ user_data, %% As passed by the user on send
+ prio,
+ timestamp}).
diff --git a/lib/dialyzer/test/user_SUITE_data/src/gcpFlowControl.erl b/lib/dialyzer/test/user_SUITE_data/src/gcpFlowControl.erl
new file mode 100644
index 0000000000..8598efb5d1
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/gcpFlowControl.erl
@@ -0,0 +1,397 @@
+%%%-------------------------------------------------------------------
+%%% File : gcpFlowControl.erl
+%%% Author : EAB/UPD/AV
+%%% Description : Implements overload protection.
+%%%-------------------------------------------------------------------
+-module(gcpFlowControl).
+-id('24/190 55-CNA 113 033 Ux').
+-vsn('/main/R1A/14').
+-date('2005-05-04').
+-author('uabasve').
+%%% ----------------------------------------------------------
+%%% %CCaseTemplateFile: module.erl %
+%%% %CCaseTemplateId: 16/002 01-FEA 202 714 Ux, Rev: /main/4 %
+%%%
+%%% Copyright (C) 2001-2005 by Ericsson Telecom AB
+%%% SE-126 25 STOCKHOLM
+%%% SWEDEN, tel int + 46 8 719 0000
+%%%
+%%% The program may be used and/or copied only with the written
+%%% permission from Ericsson Telecom AB, or in accordance with
+%%% the terms and conditions stipulated in the agreement/contract
+%%% under which the program has been supplied.
+%%%
+%%% All rights reserved
+%%%
+%%%
+%%% ----------------------------------------------------------
+%%% #1. REVISION LOG
+%%% ----------------------------------------------------------
+%%% Rev Date Name What
+%%% -------- -------- -------- ------------------------
+%%% R1A/1-2 05-02-07 ejojmjn Copied from EAS R7A/11.
+%%% R1A/3-14 05-03-14 uabasve Clean.
+%%%--------------------------------------------------------------------
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_v1.hrl").
+-include("gcp.hrl").
+
+-export([send_request/4, %% user send from gcpInterface
+ receive_reply/2, %% from callback in gcpTransaction
+ init_ets_tables/1,
+ init_data/2]).
+
+-define(PRIO_INFINITY, 16).
+-define(MIN_WINDOW, 10).
+-define(MAX_WINDOW, 100).
+
+-define(BUCKET_MAX, 100).
+-define(BUCKET_THRESH_HIGH, 80).
+-define(BUCKET_THRESH_LOW, 20).
+
+-define(ALLOW_TIMEOUT, 1000).
+
+%% Holds counters for flow control in GCP
+-record(gcpFlowControlTable,
+ {key,
+ window = 50,
+ available = 50,
+ bucket = 0,
+ q = 0,
+ sent = 0, %% Counts all attempts
+ rejectable = 0, %% Counts rejectable attempts
+ t95,
+ errors = 0,
+ rejects = 0,
+ replies = 0}).
+
+-record(gcpFlowControlBitmap,
+ {key,
+ count = 0}).
+
+%%====================================================================
+%% External functions
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: send_request/4
+%%
+%% Output: ok | {error, Reason}
+%%--------------------------------------------------------------------
+
+send_request(ActiveLink, TimerOptions, ActionRequests, UserData) ->
+ #gcpActiveLinkTable{key = Key,
+ conn_handle = ConnHandle}
+ = ActiveLink,
+ Prio = prio(ActionRequests),
+ incr(Key, sent),
+ case allow(Key, Prio) of
+ {true, Timestamp} ->
+ grant_request(user_data(ConnHandle),
+ Key,
+ Prio,
+ Timestamp,
+ ConnHandle,
+ TimerOptions,
+ ActionRequests,
+ UserData);
+ false ->
+ {error, rejected}
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: receive_reply/2
+%% Description:
+%%--------------------------------------------------------------------
+
+receive_reply(Key, Timestamp) ->
+ incr(Key, available),
+ incr(Key, replies),
+ release(Key),
+ report_time(Key, Timestamp).
+
+%%--------------------------------------------------------------------
+%% Func: init_ets_tables/1
+%%
+%% Returns: ok
+%%--------------------------------------------------------------------
+
+init_ets_tables(Role) ->
+ create_ets(Role, gcpFlowControlTable, #gcpFlowControlTable.key),
+ create_ets(Role, gcpFlowControlBitmap, #gcpFlowControlBitmap.key),
+ ok.
+
+create_ets(Role, Table, Pos) when integer(Pos) ->
+ create_ets(Role,
+ Table,
+ [named_table, ordered_set, public, {keypos, Pos}]);
+
+create_ets(test, Table, ArgList) ->
+ ets:new(Table, ArgList);
+create_ets(Role, Table, ArgList) ->
+ case ets:info(Table) of
+ undefined ->
+ sysCmd:ets_new(Table, ArgList);
+ _ when Role == ch ->
+ sysCmd:inherit_tables([Table]);
+ _ when Role == om ->
+ ok
+ end.
+
+%%--------------------------------------------------------------------
+%% Func: init_data/2
+%%--------------------------------------------------------------------
+
+init_data(Key, T95) ->
+ ets:insert(gcpFlowControlTable, #gcpFlowControlTable{key = Key,
+ t95 = T95}).
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
+%%% ----------------------------------------------------------
+%%% incr
+%%% ----------------------------------------------------------
+
+cntr(Key, Field) ->
+ incr(Key, Field, 0).
+
+incr(Key, Field) ->
+ incr(Key, Field, 1).
+
+-define(INCR(Field),
+ incr(Key, Field, X) -> upd_c(Key, {#gcpFlowControlTable.Field, X})).
+
+?INCR(sent);
+?INCR(replies);
+?INCR(q);
+?INCR(t95);
+?INCR(errors);
+?INCR(rejects);
+?INCR(rejectable);
+?INCR(window);
+?INCR(available);
+
+incr(Key, bucket, X)->
+ upd_c(Key, {#gcpFlowControlTable.bucket, X, ?BUCKET_MAX, ?BUCKET_MAX}).
+
+upd_c(Key, N) ->
+ ets:update_counter(gcpFlowControlTable, Key, N).
+
+%%% ----------------------------------------------------------
+%%% decr
+%%%
+%%% Beware that decr is implemented as incr, care has to be taken
+%%% not to bungle things when max/min values are used.
+%%% ----------------------------------------------------------
+
+decr(Key, available, X) ->
+ upd_c(Key, {#gcpFlowControlTable.available, -X});
+decr(Key, window, X) ->
+ upd_c(Key, {#gcpFlowControlTable.window, -X});
+decr(Key, bucket, X) ->
+ upd_c(Key, {#gcpFlowControlTable.bucket, -X, 0, 0}).
+
+decr(Key, Field) ->
+ decr(Key, Field, 1).
+
+%%% ----------------------------------------------------------
+%%% allow
+%%% ----------------------------------------------------------
+
+allow(Key, ?PRIO_INFINITY) ->
+ decr(Key, available),
+ {true, now()};
+
+allow(Key, Prio) ->
+ incr(Key, rejectable),
+ case decr(Key, available) of
+ N when N > 0 ->
+ {true, no_stamp};
+ _ ->
+ %% We did not send it, therefore incr available again
+ incr(Key, available),
+ queue(Key, Prio)
+ end.
+
+%%% ----------------------------------------------------------
+%%% queue
+%%% ----------------------------------------------------------
+
+queue(Key, Prio) ->
+ incr(Key, q),
+ T = {Key, Prio, now(), self()},
+ ets:insert(gcpFlowControlBitmap, #gcpFlowControlBitmap{key = T}),
+ wait(T).
+
+%%% ----------------------------------------------------------
+%%% wait
+%%% ----------------------------------------------------------
+
+wait({Key, _Prio, _When, _Self} = T) ->
+ receive
+ allow ->
+ ets:delete(gcpFlowControlBitmap, T),
+ decr(Key, available),
+ {true, no_stamp}
+ after ?ALLOW_TIMEOUT ->
+ timeout(T),
+ adjust_window(Key),
+ incr(Key, rejects),
+ false
+ end.
+
+timeout(T) ->
+ case ets:update_counter(gcpFlowControlBitmap, T, 1) of
+ 1 ->
+ %% Got the lock: no one has released Key and sent 'allow'.
+ ets:delete(gcpFlowControlBitmap, T),
+ ok;
+ _ ->
+ %% A releasing process got the lock: 'allow' has been
+ %% sent. Try to remove the message before proceeding.
+ %% (This is to keep mdisp from complaining apparently.)
+ ets:delete(gcpFlowControlBitmap, T),
+ receive
+ allow ->
+ ok
+ after ?ALLOW_TIMEOUT ->
+ io:format("~p: errant allow: ~p~n", [?MODULE, T])
+ end
+ end.
+
+%% Now, if we reject and our general response time is low
+%% (i.e. low bucket) then we increase the window size.
+adjust_window(Key) ->
+ adjust_window(Key,
+ cntr(Key, bucket) < ?BUCKET_THRESH_LOW
+ andalso cntr(Key, window) < ?MAX_WINDOW).
+
+adjust_window(Key, true) ->
+ incr(Key, window),
+ incr(Key, available),
+ incr(Key, bucket, 20);
+adjust_window(_, false) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Func: report_time/2
+%%--------------------------------------------------------------------
+
+report_time(_, no_stamp) ->
+ ok;
+report_time(Key, {MS, S, Ms})->
+ {MegaSecs, Secs, MicroSecs} = now(),
+ p(Key,
+ MicroSecs - Ms + 1000000*(Secs - S + 1000000*(MegaSecs - MS)),
+ cntr(Key, t95)).
+
+%%% ----------------------------------------------------------
+%%% p
+%%% ----------------------------------------------------------
+
+p(Key, Time, T95) when Time =< T95 ->
+ decr(Key, bucket);
+p(Key, _Time, _T95) ->
+ %% If we have a long response time, then increase the leaky
+ %% bucket. If the bucket is over the high watermark and the window
+ %% is not already at its minimum size, then decrease the window
+ %% and available.
+ case {cntr(Key, window), incr(Key, bucket, 20)} of
+ {Window, Bucket} when Window > ?MIN_WINDOW,
+ Bucket > ?BUCKET_THRESH_HIGH ->
+ decr(Key, window),
+ decr(Key, available);
+ _ ->
+ ok
+ end.
+
+%%% ----------------------------------------------------------
+%%% release
+%%% ----------------------------------------------------------
+
+release(Key) ->
+ %% The choice of the key below will cause ets:prev/2 to return
+ %% the key with the highest priority which was queued most
+ %% recently. This relies on the fact that integers sort before
+ %% atoms, the atom 'prio' in this case. The atoms 'queued' and
+ %% 'pid' are of no significance.
+ release(Key, {Key, prio, queued, pid}).
+
+%% This isn't a (FIFO) queue within each priority, but a (LIFO) stack.
+
+release(Key, T) ->
+ release(Key, cntr(Key, available), ets:prev(gcpFlowControlBitmap, T)).
+
+%% Note that only keys on the same Key are matched.
+release(Key, N, {Key, _Prio, _When, Pid} = T) when N > 0 ->
+ case catch ets:update_counter(gcpFlowControlBitmap, T, 1) of
+ 1 ->
+ Pid ! allow;
+ _ ->
+ %% Another process has released this key.
+ release(Key, T)
+ end;
+
+release(_, _, _)->
+ ok.
+
+%%% ----------------------------------------------------------
+%%% user_data
+%%% ----------------------------------------------------------
+
+user_data(ConnHandle) ->
+ case catch megaco:conn_info(ConnHandle, reply_data) of
+ {'EXIT', _Reason} ->
+ false;
+ Rec ->
+ {value, Rec}
+ end.
+
+%%% ----------------------------------------------------------
+%%% grant_request
+%%% ----------------------------------------------------------
+
+grant_request({value, Rec},
+ Key, Prio, Time,
+ ConnHandle, Options, ActionRequests, UserData) ->
+ ReplyData = Rec#gcpReplyData{user_data = UserData,
+ prio = Prio,
+ timestamp = Time},
+ cast_rc(megaco:cast(ConnHandle,
+ ActionRequests,
+ [{reply_data, ReplyData} | Options]),
+ Key,
+ ActionRequests);
+
+grant_request(false, Key, _, _, _, _, _, _) ->
+ incr(Key, available),
+ {error, reply_data}.
+
+cast_rc(ok = Ok, _, _) ->
+ Ok;
+cast_rc({error, Reason}, Key, ActionRequests) ->
+ incr(Key, available),
+ gcpLib:error_report(?MODULE, send_request, [ActionRequests],
+ "send failed",
+ Reason),
+ {error, {encode, Reason}}.
+
+%%--------------------------------------------------------------------
+%% Func: prio/1
+%% Returns: The priority of the request
+%%--------------------------------------------------------------------
+
+prio([ActionRequest | _]) ->
+ #'ActionRequest'{contextId = ContextId,
+ contextRequest = ContextRequest}
+ = ActionRequest,
+ prio(ContextId, ContextRequest).
+
+prio(?megaco_choose_context_id, #'ContextRequest'{priority = Prio})
+ when integer(Prio) ->
+ Prio;
+prio(_, _) ->
+ ?PRIO_INFINITY.
diff --git a/lib/dialyzer/test/user_SUITE_data/src/qlc_error.erl b/lib/dialyzer/test/user_SUITE_data/src/qlc_error.erl
new file mode 100644
index 0000000000..04e621dd4b
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/qlc_error.erl
@@ -0,0 +1,15 @@
+%% -*- erlang-indent-level: 2 -*-
+%% $Id: qlc_error.erl,v 1.1 2008/12/17 09:53:52 mikpe Exp $
+
+%% @author Daniel Luna <[email protected]>
+%% @copyright 2006 Daniel Luna
+%%
+%% @doc
+%%
+
+-module(qlc_error).
+-export([fix/0]).
+-include_lib("stdlib/include/qlc.hrl").
+
+fix() ->
+ qlc:eval(qlc:q([I || I <- []])).
diff --git a/lib/dialyzer/test/user_SUITE_data/src/spvcOrig.erl b/lib/dialyzer/test/user_SUITE_data/src/spvcOrig.erl
new file mode 100644
index 0000000000..279caffdde
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/spvcOrig.erl
@@ -0,0 +1,3520 @@
+%%%=======================================================================
+%%%
+%%% Test from Mats Cronqvist <[email protected]>. The
+%%% analysis crasched due to the handling of tuples-as-funs in
+%%% hipe_icode_type.erl, and it also exposed a bug when a control flow
+%%% path is first analyzed and then shown to be infeasible.
+%%%
+
+-file("./spvcOrig.erl", 1).
+
+-module(spvcOrig).
+
+-author(qamarma).
+
+-id('3/190 55-CNA 121 64').
+
+-vsn('/main/Inc4/R2A/R4A/R6A/R7A/R7D/R8B/R10A/R11A/2').
+
+-date('2004-10-26').
+
+-export([gen_set/3,gen_set/4,connect/3,release_comp_nu/3,release_nu/3,timeout/2,restart_spvc/1,restart_multi_spvcs/1,forced_release/1,error_handler/3,get_backoff_table/2,timeout_event/1]).
+
+-export([release_incumbent/2,switch_over/2]).
+
+-export([call_failure/1,get_backoff_table/2]).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/pchTables.hrl", 1).
+
+-hrl_id('2/190 55-CNA 121 08').
+
+-hrl_vsn('/main/Inc3/Inc4/R2A/R3A/R3B/R5A/R6A/R7A/R7D/R8B/13').
+
+-hrl_date('2003-01-24').
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../derived_hrl/mib/AXD301-PCH-MIB.hrl", 1).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/pchTables.hrl", 58).
+
+-record(pchVp, {vplEntry,
+ vplLastChange,
+ vplReceiveTrafficDescrIndex = 0,
+ vplTransmitTrafficDescrIndex = 0,
+ vplCcIdentifier,
+ vplConnId,
+ vplMpId,
+ vplLeafId,
+ vplChargingIndicator = 1,
+ vplRemoteChargingInd = 1,
+ vplChargablePartyIdentifier,
+ vplSegmentEndPoint = 2,
+ vplRowStatus,
+ vplCastType = 1,
+ vplConnKind = 1,
+ vplServiceType = 2,
+ vplEndPointData,
+ vplContinuityCheck = 1,
+ vplUpcNpcMode = 2,
+ vplPreventInbandCc = 1,
+ vplMonAisRdi = 2,
+ vpcAdminStatus = 2,
+ vplSpvcAutoTarget = 2,
+ vplSchedulingFlag = 2,
+ vplApplication,
+ vplRemoteData,
+ vpccAdminStatus = 2,
+ vplContCheckSearch = 1,
+ vplPmSearch = 1,
+ vplLastBuffFlagRead,
+ vplShapingMode = 1,
+ vplGroupShapingId}).
+
+-record(pchVpDb, {vplEntry,
+ vplLastChange,
+ vplReceiveTrafficDescrIndex = 0,
+ vplTransmitTrafficDescrIndex = 0,
+ vplCcIdentifier,
+ vplConnId,
+ vplMpId,
+ vplLeafId,
+ vplAttributes,
+ vplChargablePartyIdentifier,
+ vplRowStatus,
+ vplEndPointData,
+ vplApplication,
+ vplRemoteData,
+ vplLastBuffFlagRead,
+ vplShapingMode,
+ vplGroupShapingId}).
+
+-record(pchVpExt, {vplExtEntry,
+ vplExtReceiveTdIndex,
+ vplExtTransmitTdIndex,
+ vplExtUserName = [],
+ vplExtProviderName = [],
+ vplExtUserOperator}).
+
+-record(pchVc, {vclEntry,
+ vclLastChange,
+ vclReceiveTrafficDescrIndex = 0,
+ vclTransmitTrafficDescrIndex = 0,
+ vclCcIdentifier,
+ vclConnId,
+ vclMpId,
+ vclLeafId,
+ vclChargingIndicator = 1,
+ vclRemoteChargingInd = 1,
+ vclChargablePartyIdentifier,
+ vclPacketDiscard = 2,
+ vclSegmentEndPoint = 2,
+ vclRowStatus,
+ vclCastType = 1,
+ vclConnKind = 1,
+ vclContinuityCheck = 1,
+ vclUpcNpcMode = 2,
+ vclEndPointData,
+ vclPreventInbandCc = 1,
+ vclMonAisRdi = 2,
+ vclSpvcAutoTarget = 2,
+ vclSchedulingFlag = 2,
+ vclApplication,
+ vclRemoteData,
+ vcccAdminStatus = 2,
+ vclContCheckSearch = 1,
+ vclPmSearch = 1,
+ vclLastBuffFlagRead,
+ vclChargingIfChanid,
+ vclShapingMode = 1}).
+
+-record(pchVcDb, {vclEntry,
+ vclLastChange,
+ vclReceiveTrafficDescrIndex = 0,
+ vclTransmitTrafficDescrIndex = 0,
+ vclCcIdentifier,
+ vclConnId,
+ vclMpId,
+ vclLeafId,
+ vclAttributes,
+ vclChargablePartyIdentifier,
+ vclRowStatus,
+ vclEndPointData,
+ vclApplication,
+ vclRemoteData,
+ vclLastBuffFlagRead,
+ vclChargingIfChanid,
+ vclShapingMode}).
+
+-record(pchAtd, {tdIndex,
+ tdType,
+ tdParam1 = 0,
+ tdParam2 = 0,
+ tdParam3 = 0,
+ tdParam4 = 0,
+ tdParam5 = 0,
+ tdTrafficQoSClass = 0,
+ tdRowStatus = 1,
+ tdServiceCategory = 6,
+ tdVcCapability = 1,
+ tdName = [],
+ tdUserCounter = 0,
+ tdUser = []}).
+
+-record(pchAbr, {abrIndex,
+ abrIcr,
+ abrTbe = 16277215,
+ abrFrtt = 0,
+ abrRdf = 11,
+ abrRif = 11,
+ abrNrm = 4,
+ abrTrm = 7,
+ abrCdf = 3,
+ abrAdtf = 50,
+ abrRowStatus = 1}).
+
+-record(pchIndexNext, {key,
+ tdIndexNext,
+ vpccIndexNext,
+ vcccIndexNext,
+ scheduledVpCcIndexNext,
+ scheduledVcCcIndexNext}).
+
+-record(pchSchedVpCc, {schedVpCcIndex,
+ schedVpCcTarget,
+ schedVpCcReceiveTdIndex,
+ schedVpCcTransmitTdIndex,
+ schedVpCcOpTime,
+ schedVpCcOpInd,
+ schedVpCcOpStatus,
+ schedVpCcTimerRef,
+ schedVpCcRowStatus,
+ schedVpCcErrorCode,
+ schedVpCcUserName = [],
+ schedVpCcProviderName = []}).
+
+-record(pchVpCc, {vpccId,
+ vpccUserName = [],
+ vpccAdminStatus,
+ vpccApplication,
+ vpccProviderName = []}).
+
+-record(pchSchedVcCc, {schedVcCcIndex,
+ schedVcCcTarget,
+ schedVcCcReceiveTdIndex,
+ schedVcCcTransmitTdIndex,
+ schedVcCcOpTime,
+ schedVcCcOpInd,
+ schedVcCcOpStatus,
+ schedVcCcTimerRef,
+ schedVcCcRowStatus,
+ schedVcCcErrorCode,
+ schedVcCcUserName = [],
+ schedVcCcProviderName = []}).
+
+-record(pchVcCc, {vcccId,
+ vcccUserName = [],
+ vcccAdminStatus,
+ vcccApplication,
+ vcccProviderName = []}).
+
+-record(pchSigChannels, {et_entry,
+ cp_entry,
+ sb_cp_entry,
+ membership,
+ status,
+ sb_status,
+ application = {0,[]}}).
+
+-record(pchSigChannelExt, {et_entry,
+ user_name,
+ provider_name}).
+
+-record(pchApplication, {key,
+ application,
+ rights}).
+
+-record(pchCurrAlarm, {key,
+ type_of_fault,
+ fault_id}).
+
+-record(pchIfAddress, {ifAddressEntry,
+ ifAddressRowStatus}).
+
+-record(pchAddressToIf, {address,
+ if_index}).
+
+-record(pchPreferences, {key,
+ if_format}).
+
+-record(pchSigChannelCallback, {key,
+ callback,
+ function,
+ args,
+ data}).
+
+-record(pchTermHcId, {hcId,
+ vclEntry}).
+
+-record(pchChg, {chgEntry,
+ chgStatus}).
+
+-record(pchCommState, {key,
+ ccid,
+ request,
+ low_cp_state,
+ high_cp_state,
+ et_side,
+ application,
+ data,
+ timestamp,
+ timer_id,
+ callback}).
+
+-record(pchBufferedCmd, {key,
+ resource,
+ module,
+ function,
+ arguments,
+ data}).
+
+-record(pchAnswerCh, {conn_id,
+ chg_data,
+ call_back_cp,
+ old_rtd,
+ old_ttd,
+ old_EpData,
+ action,
+ resource,
+ data,
+ fail_cause}).
+
+-record(pchAnswerOm, {conn_id}).
+
+-record(ccPch, {rowInd,
+ admState = 2}).
+
+-record(pchIf, {ilmiVpi = 0,
+ ilmiVci = 0,
+ ilmiS = 1,
+ ilmiT = 5,
+ ilmiK = 4,
+ neighborIfName = [],
+ neighborIpAddr = [0,0,0,0],
+ maxVciSvc,
+ overbookingFactor = {0,0},
+ shapingMode = 0,
+ maxVpiSvc,
+ cdvtMultFactor = 100,
+ scBandwidth1 = 0,
+ scBandwidth2 = 0,
+ scBandwidth3 = 0,
+ scBandwidth4 = 0}).
+
+-record(pchMpTemp, {key,
+ data}).
+
+-record(pchLatestErrorCode, {key,
+ errorCode}).
+
+-record(pchRangeTable, {node,
+ tdIndexRange,
+ vpccIndexRange,
+ vcccIndexRange}).
+
+-record(pchIndexBitmaps, {key,
+ available,
+ bitmap}).
+
+-record(pchLinkState, {key,
+ op_state,
+ last_change}).
+
+-record(pchFailedVpl, {vplEntry,
+ vplLastChange}).
+
+-record(pchFailedVcl, {vclEntry,
+ vclLastChange}).
+
+-record(pchStatCounters, {key,
+ ingress,
+ egress}).
+
+-record(pchEtStatTable, {index,
+ value = 0}).
+
+-record(pchAuditResult, {key,
+ passed,
+ not_passed,
+ sizes,
+ obj_keys}).
+
+-record(pch_fault_reqc, {fault_type,
+ fault_location}).
+
+-record(pch_cid, {conn_id,
+ mp_id,
+ leaf_id}).
+
+-file("./spvcOrig.erl", 207).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/pchI.hrl", 1).
+
+-hrl_id('52/190 55-CNA 121 08 Ux').
+
+-hrl_vsn('/main/R6A/R7A/R7D/R8B/3').
+
+-hrl_date('2002-10-14').
+
+-hrl_author(uabdomo).
+
+-record(pch_vc_rec, {ifIndex,
+ vpi,
+ vci,
+ application}).
+
+-record(pch_vp_rec, {ifIndex,
+ vpi}).
+
+-record(pch_td_index, {rtd_index,
+ ttd_index}).
+
+-record(pch_td, {service_cat,
+ pcr,
+ scr,
+ mbs,
+ mcr,
+ cdvt,
+ tagging,
+ clp_significance}).
+
+-record(pch_call_back_req, {module,
+ function,
+ user_data}).
+
+-record(pch_chg_rec, {chg_type,
+ chg_interface,
+ chg_chan_id,
+ chg_party_name}).
+
+-record(pch_polic_rec, {policing,
+ packet_discard}).
+
+-record(pch_user_name_rec, {user_name}).
+
+-record(pch_shaping_rec, {shaping}).
+
+-record(pch_audit_callback, {mod,
+ arg}).
+
+-file("./spvcOrig.erl", 208).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/plc.hrl", 1).
+
+-hrl_id('12/190 55-CNA 121 45 Ux').
+
+-hrl_vsn('/main/R6A/R6B/R7A/R7D/R8B/R9A/R11A/4').
+
+-hrl_date('2004-12-07').
+
+-hrl_author(ethrba).
+
+-record(plcQueues, {name,
+ type,
+ weight,
+ maxlength,
+ owner}).
+
+-record(plcSettings, {flag,
+ value}).
+
+-record(plcAlarm, {flag,
+ value}).
+
+-file("./spvcOrig.erl", 209).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/spvcTables.hrl", 1).
+
+-hrl_id('10/190 55-CNA 121 64').
+
+-hrl_vsn('/main/Inc4/R2A/R3A/R3B/R5A/R6A/R7A/R7D/R8B/4').
+
+-hrl_date('2003-02-12').
+
+-hrl_author(etxovp).
+
+-record(spvcVpc, {spvcVpcEntry,
+ spvcVpcTargetAddress,
+ spvcVpcTargetSelectType,
+ spvcVpcTargetVpi,
+ spvcVpcLastReleaseCause,
+ spvcVpcLastReleaseDiagnostic,
+ spvcVpcRetryInterval = 1000,
+ spvcVpcRetryTimer = 0,
+ spvcVpcRetryThreshold = 1,
+ spvcVpcRetryFailures = 0,
+ spvcVpcRetryLimit = 15,
+ spvcVpcRowStatus,
+ spvcVpcUserName = [],
+ spvcVpcProviderName = [],
+ currentState,
+ crankBackCounter = 0,
+ spvcVpcApplication,
+ spvcRerCap = false,
+ spvcRerStatus = false}).
+
+-record(spvcVpcOpState, {state,
+ timeOfChange}).
+
+-record(spvcVpcPerm, {spvcVpcEntry,
+ spvcVpcTargetAddress,
+ spvcVpcTargetSelectType,
+ spvcVpcTargetVpi,
+ spvcVpcRetryInterval = 1000,
+ spvcVpcRetryThreshold = 1,
+ spvcVpcRetryLimit = 15,
+ spvcVpcRowStatus,
+ spvcVpcUserName,
+ spvcVpcProviderName,
+ spvcVpcApplication}).
+
+-record(spvcVpcDyn, {spvcVpcEntry,
+ spvcVpcLastReleaseCause,
+ spvcVpcLastReleaseDiagnostic,
+ spvcVpcRetryTimer = 0,
+ spvcVpcRetryFailures = 0,
+ currentState,
+ crankBackCounter = 0}).
+
+-record(spvcVcc, {spvcVccEntry,
+ spvcVccTargetAddress,
+ spvcVccTargetSelectType,
+ spvcVccTargetVpi,
+ spvcVccTargetVci,
+ spvcVccLastReleaseCause,
+ spvcVccLastReleaseDiagnostic,
+ spvcVccRetryInterval = 1000,
+ spvcVccRetryTimer = 0,
+ spvcVccRetryThreshold = 1,
+ spvcVccRetryFailures = 0,
+ spvcVccRetryLimit = 15,
+ spvcVccRowStatus,
+ spvcVccUserName = [],
+ spvcVccProviderName = [],
+ currentState,
+ crankBackCounter = 0,
+ spvcVccTargetDlci,
+ spvcVccTargetType,
+ spvcVccApplication,
+ spvcVccFrKey,
+ spvcVccTranslationMode,
+ spvcRerCap = false,
+ spvcRerStatus = false}).
+
+-record(spvcVccOpState, {state,
+ timeOfChange}).
+
+-record(spvcVccPerm, {spvcVccEntry,
+ spvcVccTargetAddress,
+ spvcVccTargetSelectType,
+ spvcVccTargetVpi,
+ spvcVccTargetVci,
+ spvcVccRetryInterval = 1000,
+ spvcVccRetryThreshold = 1,
+ spvcVccRetryLimit = 15,
+ spvcVccRowStatus,
+ spvcVccUserName,
+ spvcVccProviderName,
+ spvcVccTargetDlci,
+ spvcVccTargetType,
+ spvcVccApplication,
+ spvcVccFrKey,
+ spvcVccTranslationMode = 2}).
+
+-record(spvcVccDyn, {spvcVccEntry,
+ spvcVccLastReleaseCause,
+ spvcVccLastReleaseDiagnostic,
+ spvcVccRetryTimer = 0,
+ spvcVccRetryFailures = 0,
+ currentState,
+ crankBackCounter = 0}).
+
+-record(spvcFailures, {dummy_key,
+ spvcCallFailuresTrapEnable = 2,
+ spvcNotificationInterval = 30,
+ backoff_interval = 0.100000,
+ delay_factor = 2,
+ max_delay = 200000}).
+
+-record(spvcCounters, {key,
+ value}).
+
+-record(spvcEventIndicator, {dummy_key,
+ spvcTimerInd = 2,
+ spvcSendEventInd = 2}).
+
+-record(spvcIndexNext, {dummy_key,
+ schedVccIndexNext = 1,
+ schedVpcIndexNext = 1}).
+
+-record(spvcHcIdToTp, {hcId,
+ tpEntry}).
+
+-record(spvcTpToHcId, {tpEntry,
+ hcId,
+ orig_number,
+ orig_vpi,
+ orig_vci,
+ orig_dlci,
+ frKey}).
+
+-record(spvcSchedVpc, {schedVpcIndex,
+ schedVpcSource,
+ schedVpcTargetAddr,
+ schedVpcTargetSelType,
+ schedVpcTargetVpi,
+ schedVpcRetryInt,
+ schedVpcRetryThres,
+ schedVpcRetryLimit,
+ schedVpcOpTime,
+ schedVpcOpInd,
+ schedVpcOpStatus,
+ schedVpcTimerRef,
+ schedVpcRowStatus,
+ schedVpcUserName,
+ schedVpcProviderName,
+ schedVpcFaultCause,
+ schedVpcRerCap = false}).
+
+-record(spvcSchedVcc, {schedVccIndex,
+ schedVccSource,
+ schedVccTargetAddr,
+ schedVccTargetSelType,
+ schedVccTargetVpi,
+ schedVccTargetVci,
+ schedVccRetryInt,
+ schedVccRetryThres,
+ schedVccRetryLimit,
+ schedVccOpTime,
+ schedVccOpInd,
+ schedVccOpStatus,
+ schedVccTimerRef,
+ schedVccRowStatus,
+ schedVccUserName,
+ schedVccProviderName,
+ schedVccFaultCause,
+ schedVccRerCap = false}).
+
+-record(spvcCurrAlarm, {key,
+ fault_id,
+ data}).
+
+-record(spvcChg, {key,
+ data}).
+
+-record(spvcBackoff, {key,
+ delay_time,
+ flag}).
+
+-record(spvcAutoVp, {entry,
+ lastChange,
+ receiveTrafficDescrIndex,
+ transmitTrafficDescrIndex,
+ ccIdentifier,
+ connId,
+ mpId,
+ leafId,
+ chargingIndicator = 1,
+ remoteChargingInd = 1,
+ chargablePartyIdentifier,
+ segmentEndPoint = 2,
+ rowStatus,
+ castType = 1,
+ connKind,
+ serviceType = 2,
+ endPointData,
+ continuityCheck = 1,
+ upcNpcMode = 2,
+ preventInbandCc = 1,
+ monAisRdi = 2,
+ adminStatus,
+ autoTarget = 1,
+ schedulingFlag = 2,
+ application = [],
+ remoteData,
+ vpccAdminStatus = 2,
+ contCheckSearch = 1,
+ pmSearch = 1,
+ lastBuffFlagRead,
+ shapingMode = 1,
+ groupShapingId}).
+
+-record(spvcAutoVc, {entry,
+ lastChange,
+ receiveTrafficDescrIndex,
+ transmitTrafficDescrIndex,
+ ccIdentifier,
+ connId,
+ mpId,
+ leafId,
+ chargingIndicator = 1,
+ remoteChargingInd = 1,
+ chargablePartyIdentifier,
+ packetDiscard = 2,
+ segmentEndPoint = 2,
+ rowStatus,
+ castType = 1,
+ connKind,
+ continuityCheck = 1,
+ upcNpcMode = 2,
+ endPointData,
+ preventInbandCc = 1,
+ monAisRdi = 2,
+ autoTarget = 1,
+ schedulingFlag = 2,
+ application = [],
+ remoteData,
+ vcccAdminStatus = 2,
+ contCheckSearch = 1,
+ pmSearch = 1,
+ lastBuffFlagRead,
+ chargingIfChanid,
+ shapingMode = 1}).
+
+-record(spvcAutoAtd, {index,
+ type,
+ param1 = 0,
+ param2 = 0,
+ param3 = 0,
+ param4 = 0,
+ param5 = 0,
+ trafficQoSClass = 0,
+ rowStatus = 1,
+ serviceCategory = 6,
+ vcCapability = 1,
+ name = [],
+ userCounter = 0}).
+
+-record(spvcAutoAbr, {index,
+ icr,
+ tbe = 16277215,
+ frtt = 0,
+ rdf = 11,
+ rif = 11,
+ nrm = 4,
+ trm = 7,
+ cdf = 3,
+ adtf = 50,
+ rowStatus = 1}).
+
+-record(spvcLatestErrorCode, {key,
+ errorCode}).
+
+-record(spvcVcDyn, {vclEntry,
+ vclCcIdentifier,
+ vclConnId,
+ vclMpId,
+ vclLeafId}).
+
+-record(spvcVpDyn, {vplEntry,
+ vplCcIdentifier,
+ vplConnId,
+ vplMpId,
+ vplLeafId}).
+
+-record(spvcObj, {spvcEntry,
+ spvcTargetAddress,
+ spvcTargetSelectType,
+ spvcTargetVpi,
+ spvcTargetVci,
+ spvcLastReleaseCause,
+ spvcLastReleaseDiagnostic,
+ spvcRetryInterval = 1000,
+ spvcRetryTimer = 0,
+ spvcRetryThreshold = 1,
+ spvcRetryFailures = 0,
+ spvcRetryLimit = 15,
+ spvcRowStatus,
+ spvcUserName,
+ spvcProviderName,
+ currentState,
+ spvcTargetDlci,
+ spvcTargetType,
+ spvcApplication,
+ spvcFrKey,
+ spvcVccTranslationMode = 2,
+ spvcRerCap = false,
+ spvcRerStatus = false}).
+
+-record(spvcTargetVc, {entry,
+ userName = [],
+ providerName = [],
+ opState,
+ rowStatus}).
+
+-record(spvcTargetVp, {entry,
+ userName = [],
+ providerName = [],
+ opState,
+ rowStatus}).
+
+-record(spvcReestablishTimer, {time,
+ timer_id,
+ module,
+ function,
+ args}).
+
+-record(spvcRerVp, {entry,
+ rerCap,
+ rerData}).
+
+-record(spvcRerVc, {entry,
+ rerCap,
+ rerData}).
+
+-record(spvcHcEtStat, {key,
+ counter = 0}).
+
+-record(spvcSaEtStat, {key,
+ counter = 0}).
+
+-file("./spvcOrig.erl", 210).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/spvcDefines.hrl", 1).
+
+-hrl_id('41/190 55-CNA 121 64 Ux').
+
+-hrl_vsn('/main/R6A/R7A/R7D/R8B/3').
+
+-hrl_date('2003-02-21').
+
+-hrl_author(etxhebl).
+
+-file("./spvcOrig.erl", 211).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/spvcFr.hrl", 1).
+
+-hrl_id('48/190 55-CNA 121 64 Ux').
+
+-hrl_vsn('/main/R7A/R7D/2').
+
+-hrl_date('2001-12-06').
+
+-hrl_author(etxhtb).
+
+-record(spvcFr, {spvcFrEntry,
+ spvcFrAtmEntry,
+ spvcFrTargetAddress,
+ spvcFrTargetSelectType,
+ spvcFrTargetIdentifier,
+ spvcFrTargetVpi,
+ spvcFrTargetVci,
+ spvcFrAtmTranslation,
+ spvcFrLastReleaseCause,
+ spvcFrLastReleaseDiagnostic,
+ spvcFrAdminStatus,
+ spvcFrRetryInterval = 1000,
+ spvcFrRetryTimer = 0,
+ spvcFrRetryThreshold = 1,
+ spvcFrRetryFailures = 0,
+ spvcFrRetryLimit = 15,
+ spvcFrRowStatus,
+ spvcFrUserName,
+ spvcFrProviderName,
+ currentState}).
+
+-record(spvcFrPerm, {spvcFrEntry,
+ spvcFrAtmEntry,
+ spvcFrAtmTranslation,
+ spvcFrAdminStatus,
+ spvcFrConnect}).
+
+-record(spvcFrAddress, {addressEntry,
+ addressRowStatus}).
+
+-record(spvcFrAddressToIf, {address,
+ if_index}).
+
+-record(fr_end_point, {ifIndex,
+ dlci}).
+
+-record(fr_atm_translation, {routedIp = off,
+ routedOsi = off,
+ otherRouted = off,
+ arpTranslation = off}).
+
+-record(link_layer_core_parameters, {outgoing_max_ifs,
+ incoming_max_ifs}).
+
+-record(priority_and_service_class, {outgoing_transfer_priority,
+ incoming_transfer_priority,
+ outgoing_discard_priority,
+ incoming_discard_priority}).
+
+-file("./spvcOrig.erl", 212).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../derived_hrl/mib/AXD301-PCH-MIB.hrl", 1).
+
+-file("./spvcOrig.erl", 213).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../derived_hrl/mib/AXD301-SPVC-MIB.hrl", 1).
+
+-file("./spvcOrig.erl", 214).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../derived_hrl/mib/AXD301-FRSPVC-MIB.hrl", 1).
+
+-file("./spvcOrig.erl", 215).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/sysDefines.hrl", 1).
+
+-hrl_id('3/190 55-CNA 121 70').
+
+-hrl_vsn('/main/Inc3/Inc4/Inc5/R3B/R4A/R5B/R6A/R7A/R8B/2').
+
+-hrl_date('2002-06-07').
+
+-hrl_author(etxjotj).
+
+-file("./spvcOrig.erl", 216).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/hciMsg.hrl", 1).
+
+-hrl_id('4/190 55-CNA 121 159 Ux').
+
+-hrl_vsn('/main/R7A/R8B/10').
+
+-hrl_date('2003-02-21').
+
+-hrl_author(etxmexa).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/hciComp.hrl", 1).
+
+-hrl_id('3/190 55-CNA 121 159 Ux').
+
+-hrl_vsn('/main/R7A/1').
+
+-hrl_date('00-03-22').
+
+-hrl_author(etxmexa).
+
+-record(hci_comp_info, {required_FC = 0,
+ desired_FC = 0}).
+
+-record(hci_comp_res, {not_supported_required_FCs,
+ not_supported_desired_FCs,
+ all_supported_FCs}).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/hciMsg.hrl", 14).
+
+-record(hci_add_party, {hci_cpn,
+ hci_aal,
+ hci_bhli,
+ hci_blli,
+ hci_blli_bici,
+ hci_bsco,
+ hci_epr,
+ hci_e2etd,
+ hci_noti,
+ hci_cpsa,
+ hci_clpn,
+ hci_clpsa,
+ hci_cpn_soft,
+ hci_clpn_soft,
+ hci_geidt_list = [],
+ hci_dtl_bin_list = [],
+ hci_pa_list = [],
+ hci_gat_list = [],
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_add_party_ack, {hci_epr,
+ hci_aal,
+ hci_blli,
+ hci_blli_bici,
+ hci_e2etd,
+ hci_noti,
+ hci_cpn_soft,
+ hci_cnosa,
+ hci_cno,
+ hci_geidt_list = [],
+ hci_pa_list = [],
+ hci_gat_list = [],
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_add_party_rej, {hci_cause,
+ hci_epr,
+ hci_geidt_list = [],
+ hci_cb,
+ hci_pa_list = [],
+ hci_internal_rel_info,
+ hci_gat_list = [],
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_alerting, {hci_mci,
+ hci_unrps,
+ hci_cdpi,
+ hci_epr,
+ hci_prog_list = [],
+ hci_nbc,
+ hci_nbhlc,
+ hci_noti,
+ hci_geidt_list = [],
+ hci_pa_list = [],
+ hci_gat_list = [],
+ hci_ssie,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_b_resources, {hci_rem_dataB,
+ hci_vpiB,
+ hci_vciB,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_connect, {hci_mci,
+ hci_unrps,
+ hci_aal,
+ hci_blli,
+ hci_blli_bici,
+ hci_epr,
+ hci_atd,
+ hci_e2etd,
+ hci_noti,
+ hci_abrs,
+ hci_abra,
+ hci_nbc,
+ hci_nbhlc,
+ hci_nbllc,
+ hci_prog_list = [],
+ hci_geidt_list = [],
+ hci_eqos,
+ hci_cpn_soft,
+ hci_cnosa,
+ hci_cno,
+ hci_pa_list = [],
+ hci_gat_list = [],
+ hci_rem_dataB,
+ hci_con_dir = both,
+ hci_ssie,
+ hci_rer_services,
+ hci_rer,
+ hci_opt_traf,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_drop_party, {hci_cause,
+ hci_epr,
+ hci_noti,
+ hci_geidt_list = [],
+ hci_pa_list = [],
+ hci_internal_rel_info,
+ hci_gat_list = [],
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_local_connect, {hci_rem_data,
+ hci_con_dir,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_local_connected, {hci_rem_data,
+ hci_con_dir,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_local_disconnect, {hci_discon_dir,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_local_disconnected, {hci_data,
+ hci_prot_comp}).
+
+-record(hci_notify, {hci_epr,
+ hci_noti,
+ hci_pa_list = [],
+ hci_gat_list = [],
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_party_alerting, {hci_epr,
+ hci_noti,
+ hci_geidt_list = [],
+ hci_pa_list = [],
+ hci_gat_list = [],
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_progress, {hci_mci,
+ hci_unrps,
+ hci_cdpi,
+ hci_prog_list = [],
+ hci_nbc,
+ hci_nbhlc,
+ hci_noti,
+ hci_pa_list = [],
+ hci_gat_list = [],
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_release, {hci_mci,
+ hci_unrps,
+ hci_cause_list = [],
+ hci_noti,
+ hci_prog_list = [],
+ hci_geidt_list = [],
+ hci_cb,
+ hci_pa_list = [],
+ hci_internal_rel_info,
+ hci_gat_list = [],
+ hci_ssie,
+ hci_rer_cause,
+ hci_data,
+ hci_prot_comp,
+ hci_internal_dbg_cc,
+ hci_internal_dbg_l3}).
+
+-record(hci_setup, {hci_mci,
+ hci_unrps,
+ hci_atd,
+ hci_bbc,
+ hci_qos,
+ hci_cpn,
+ hci_aal,
+ hci_bhli,
+ hci_blli_brep,
+ hci_blli_bici,
+ hci_bsco,
+ hci_epr,
+ hci_lpt,
+ hci_e2etd,
+ hci_noti,
+ hci_abrs,
+ hci_abra,
+ hci_prog_list = [],
+ hci_eqos,
+ hci_cpsa_list = [],
+ hci_clpn,
+ hci_bici_clpn,
+ hci_clpsa_list = [],
+ hci_cgpc,
+ hci_nbc_brep,
+ hci_nbhlc_list = [],
+ hci_nbllc_brep,
+ hci_conss,
+ hci_geidt_list = [],
+ hci_cpn_soft,
+ hci_clpn_soft,
+ hci_dtl_bin_list = [],
+ hci_pa_list = [],
+ hci_ncci,
+ hci_routing_address,
+ hci_protocol_internal_info,
+ hci_gat_list = [],
+ hci_con_dir = both,
+ hci_ssie,
+ hci_rer_services,
+ hci_rer,
+ hci_opt_traf,
+ hci_data_setup,
+ hci_prot_comp}).
+
+-record(hci_setup_ack, {hci_assign,
+ hci_rem_dataB,
+ hci_con_dir = both,
+ hci_vpiB,
+ hci_vciB,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_status, {hci_state,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_status_enq, {hci_state,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_remote_data, {hci_prot_type,
+ hci_data,
+ hci_dummy1,
+ hci_dummy2}).
+
+-record(hci_unrec, {hci_mci,
+ hci_head,
+ hci_binary,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_atd, {hci_pci,
+ hci_apci,
+ hci_fwd_pcr_clp_0,
+ hci_bwd_pcr_clp_0,
+ hci_fwd_pcr_clp_0_1,
+ hci_bwd_pcr_clp_0_1,
+ hci_fwd_scr_clp_0,
+ hci_bwd_scr_clp_0,
+ hci_fwd_scr_clp_0_1,
+ hci_bwd_scr_clp_0_1,
+ hci_fwd_mbs_clp_0,
+ hci_bwd_mbs_clp_0,
+ hci_fwd_mbs_clp_0_1,
+ hci_bwd_mbs_clp_0_1,
+ hci_best_effort_ind = 0,
+ hci_fwd_frame_discard = 0,
+ hci_bwd_frame_discard = 0,
+ hci_tagging_bwd = 0,
+ hci_tagging_fwd = 0,
+ hci_fwd_abr_mcr,
+ hci_bwd_abr_mcr,
+ hci_binary}).
+
+-record(hci_bbc, {hci_pci,
+ hci_bearer_class,
+ hci_atm_transfer_capability,
+ hci_user_plane_connection_configuration,
+ hci_susceptibility_to_clipping,
+ hci_binary}).
+
+-record(hci_cause, {hci_pci,
+ hci_location,
+ hci_cause_value,
+ hci_diagnostics_list = [],
+ hci_binary}).
+
+-record(hci_cpn, {hci_pci,
+ hci_type_of_number,
+ hci_intern_netw_numb_indic,
+ hci_numbering_plan_indicator,
+ hci_number_digits,
+ hci_orig_native = false}).
+
+-record(hci_clpn, {hci_pci,
+ hci_type_of_number,
+ hci_numbering_plan_indicator,
+ hci_presentation_indicator,
+ hci_screening_indicator,
+ hci_number_digits,
+ hci_incomplete_indicator = 0,
+ hci_binary}).
+
+-record(hci_cno, {hci_type_of_number,
+ hci_numbering_plan_indicator,
+ hci_presentation_indicator,
+ hci_screening_indicator,
+ hci_number_digits,
+ hci_binary}).
+
+-record(hci_cnosa, {hci_binary}).
+
+-record(hci_cpn_soft, {hci_select_type,
+ hci_soft_vpi,
+ hci_soft_vci,
+ hci_soft_dlci,
+ hci_binary}).
+
+-record(hci_clpn_soft, {hci_soft_vpi,
+ hci_soft_vci,
+ hci_soft_dlci,
+ hci_binary}).
+
+-record(hci_rer_services, {hci_inter_req_hard,
+ hci_inter_cap_hard,
+ hci_intra_req_soft,
+ hci_intra_req_hard,
+ hci_intra_cap_asym,
+ hci_intra_cap_sym,
+ hci_intra_cap_hard,
+ hci_binary}).
+
+-record(hci_rer, {hci_func_addr,
+ hci_endpoint_key,
+ hci_switchover,
+ hci_incarnation,
+ hci_pnni_cumul_fw_max_cell_td,
+ hci_cumul_fw_p2p_cdv,
+ hci_cumul_bw_p2p_cdv,
+ hci_binary}).
+
+-record(hci_rer_cause, {hci_rer_rel_cause,
+ hci_binary}).
+
+-record(hci_opt_traf, {hci_origin,
+ hci_cumul_fw_aw,
+ hci_cumul_bw_aw,
+ hci_binary}).
+
+-record(hci_qos, {hci_pci,
+ hci_qos_class_fwd,
+ hci_qos_class_bwd,
+ hci_binary}).
+
+-record(hci_aal, {hci_pci,
+ hci_binary}).
+
+-record(hci_bhli, {hci_pci,
+ hci_binary}).
+
+-record(hci_blli_brep, {hci_brep,
+ hci_blli_list = []}).
+
+-record(hci_blli, {hci_binary}).
+
+-record(hci_blli_bici, {hci_repeated,
+ hci_priority,
+ hci_pci,
+ hci_binary}).
+
+-record(hci_cpsa, {hci_pci,
+ hci_binary}).
+
+-record(hci_clpsa, {hci_pci,
+ hci_binary}).
+
+-record(hci_gat, {hci_binary}).
+
+-record(hci_epr, {hci_epr_type,
+ hci_epr_value,
+ hci_epr_flag,
+ hci_binary}).
+
+-record(hci_eqos, {hci_origin,
+ hci_acc_fwd_p2p_cdv,
+ hci_acc_bwd_p2p_cdv,
+ hci_cum_fwd_p2p_cdv,
+ hci_cum_bwd_p2p_cdv,
+ hci_acc_fwd_clr,
+ hci_acc_bwd_clr,
+ hci_binary}).
+
+-record(hci_brep, {hci_binary}).
+
+-record(hci_bsco, {hci_binary}).
+
+-record(hci_noti, {hci_binary}).
+
+-record(hci_abrs, {hci_fwd_abr_icr,
+ hci_bwd_abr_icr,
+ hci_fwd_abr_tbe,
+ hci_bwd_abr_tbe,
+ hci_cum_rm_fix_round_trip,
+ hci_fwd_rif,
+ hci_bwd_rif,
+ hci_fwd_rdf,
+ hci_bwd_rdf,
+ hci_binary}).
+
+-record(hci_abra, {hci_fwd_nrm,
+ hci_fwd_trm,
+ hci_fwd_cdf,
+ hci_fwd_atdf,
+ hci_bwd_nrm,
+ hci_bwd_trm,
+ hci_bwd_cdf,
+ hci_bwd_atdf,
+ hci_binary}).
+
+-record(hci_prog, {hci_coding_std,
+ hci_location,
+ hci_prog_desc,
+ hci_binary}).
+
+-record(hci_nbc_brep, {hci_brep,
+ hci_nbc_list = []}).
+
+-record(hci_nbc, {hci_binary}).
+
+-record(hci_nbhlc, {hci_binary}).
+
+-record(hci_nbllc_brep, {hci_brep,
+ hci_nbllc_list = []}).
+
+-record(hci_nbllc, {hci_binary}).
+
+-record(hci_geidt, {hci_binary}).
+
+-record(hci_conss, {hci_type_of_conn_scope,
+ hci_conn_scope,
+ hci_binary}).
+
+-record(hci_e2etd, {hci_pci,
+ hci_cumul_td,
+ hci_max_td,
+ hci_pnni_cumul_td,
+ hci_pnni_accept_fwd_max_td,
+ hci_netw_gen}).
+
+-record(hci_cdpi, {hci_pci,
+ hci_cdpci,
+ hci_cdpsi,
+ hci_binary}).
+
+-record(hci_cgpc, {hci_pci,
+ hci_binary}).
+
+-record(hci_lpt, {hci_pci,
+ hci_ptype}).
+
+-record(hci_cb, {hci_cb_level,
+ hci_bl_transit_type,
+ hci_bl_node_id,
+ hci_bl_link_proc_node_id,
+ hci_bl_link_port_id,
+ hci_bl_link_succ_node_id,
+ cause_value,
+ hci_cb_diagnostics,
+ hci_binary}).
+
+-record(hci_pa, {hci_ie_id,
+ hci_coding,
+ hci_action,
+ hci_length,
+ hci_binary,
+ hci_error_type}).
+
+-record(hci_ncci, {hci_pci,
+ hci_ni,
+ hci_point_code,
+ hci_call_id}).
+
+-record(hci_ssie, {hci_ssie_sas = [],
+ hci_binary}).
+
+-record(hci_sas, {hci_sas_vsn,
+ hci_sas_transp_ind,
+ hci_sas_flow_ind,
+ hci_sas_discard,
+ hci_sas_scope,
+ hci_sas_relative_id,
+ hci_binary}).
+
+-record(hci_data, {hci_hcid,
+ hci_sender_ifindex,
+ hci_sender_hcid}).
+
+-record(hci_data_setup, {hci_hcidA,
+ hci_pidA,
+ hci_protA,
+ hci_protB,
+ hci_portB,
+ hci_hcidB,
+ hci_rem_dataA,
+ hci_assign,
+ hci_ifindexB,
+ hci_node_id,
+ hci_succ_node_id,
+ hci_ifindexA,
+ hci_vpiA,
+ hci_vciA,
+ hci_cpA,
+ hci_cpB}).
+
+-record(hci_prot_comp, {hci_requiredFC = 0,
+ hci_desiredFC = 0}).
+
+-file("./spvcOrig.erl", 217).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/ccCd.hrl", 1).
+
+-hrl_id('13/190 55-CNA 121 101 Ux').
+
+-hrl_vsn('/main/R6A/R7A/R8A/R8B/8').
+
+-hrl_date('2003-02-21').
+
+-hrl_author(etxmexa).
+
+-record(ccCdRR, {hcid,
+ vpi,
+ vci,
+ ifindexA,
+ call_type,
+ spvc = false,
+ reserve = yes,
+ etA,
+ destdata,
+ leafdata,
+ loopdata,
+ l3,
+ l3_loop,
+ cc}).
+
+-record(ccCdRD, {destid,
+ loopdata,
+ cc}).
+
+-record(ccCdRL, {leafid,
+ protTypeB,
+ loopdata,
+ l3,
+ l3_loop,
+ cc}).
+
+-record(ccCdDD, {hcid,
+ hcidA,
+ vpi,
+ vci,
+ ifindexB,
+ portB,
+ call_type,
+ spvc = false,
+ reserve = yes,
+ protTypeA,
+ etB,
+ leafdata,
+ loopdata,
+ l3,
+ l3_loop,
+ cc}).
+
+-record(ccCdDL, {leafid,
+ loopdata,
+ l3,
+ l3_loop,
+ cc}).
+
+-record(ccRR, {protTypeA,
+ remote_dataA,
+ remote_dataB,
+ chg_counters,
+ sc,
+ chg_decision = on,
+ cc_loop}).
+
+-record(ccRL, {hcidB,
+ charging,
+ cc_loop}).
+
+-record(ccRD, {portB,
+ ifindexB,
+ cpB,
+ vpiB,
+ vciB,
+ cc_loop}).
+
+-record(ccDD, {protTypeB,
+ remote_dataA,
+ remote_dataB,
+ ifindexA,
+ cpA,
+ vpiA,
+ vciA,
+ chg_counters,
+ sc,
+ chg_decision = on,
+ cc_loop}).
+
+-record(ccDL, {cc_loop}).
+
+-record(loopRR, {vpList,
+ nodeid,
+ succ_nodeid,
+ connection_type,
+ policing,
+ delay_contrib,
+ charging = on,
+ prev_routing_data}).
+
+-record(loopRD, {}).
+
+-record(loopRL, {msg_rec,
+ providerName,
+ userName,
+ partyId,
+ serviceIfA,
+ serviceIdA,
+ serviceIfB,
+ serviceIdB,
+ estAw,
+ dtlLevels}).
+
+-record(loopDD, {nodeid,
+ succ_nodeid,
+ vpList,
+ connection_type,
+ policing,
+ assign,
+ delay_contrib,
+ charging = on}).
+
+-record(loopDL, {msg_rec,
+ providerName,
+ userName,
+ partyId,
+ serviceIfA,
+ serviceIdA,
+ serviceIfB,
+ serviceIdB}).
+
+-record(ccLoopRR, {pidB,
+ qos,
+ atd,
+ bbc,
+ cscope,
+ e2etd,
+ eqos,
+ con_state = none,
+ con_order = both,
+ mr_flag,
+ catch_up_id,
+ cpA}).
+
+-record(ccLoopRD, {}).
+
+-record(ccLoopRL, {route,
+ linklist,
+ routelist,
+ failurelist = [],
+ nodeidlist,
+ cb,
+ cpn,
+ dtl,
+ routing_state,
+ assign,
+ timer_counter = 0,
+ timer_ref,
+ status_enq_ind,
+ link_CB,
+ node_CB,
+ pnnir_rlp,
+ pnni_only}).
+
+-record(ccLoopDD, {pidA,
+ con_state = none,
+ con_order = both,
+ mr_flag,
+ catch_up_id,
+ cpB}).
+
+-record(ccLoopDL, {timer_counter = 0,
+ timer_ref,
+ status_enq_ind}).
+
+-file("./spvcOrig.erl", 218).
+
+-file("/export/localhome/locmacr/built/lib/erlang/lib/snmp-4.1.2/include/STANDARD-MIB.hrl", 1).
+
+-file("./spvcOrig.erl", 219).
+
+error_handler({From,Tag},{M,F,Args},EXITReason) ->
+ spvcLib:do_report(sccm,M,F,Args,"",EXITReason).
+
+connect(HcId,Connect,Key) ->
+ debug_disabled,
+ Obj = spvcDataBase:db_read({spvcObj,Key}),
+ orig_state_machine(Obj#spvcObj.currentState,connect_nu,Obj,[HcId,Connect]).
+
+release_nu(HcId,Release,Key) ->
+ debug_disabled,
+ Obj = spvcDataBase:db_read({spvcObj,Key}),
+ spvcDataBase:db_delete({spvcHcIdToTp,HcId}),
+ orig_state_machine(Obj#spvcObj.currentState,release_nu,Obj,[HcId,Release]).
+
+release_comp_nu(HcId,Release_comp,Key) ->
+ debug_disabled,
+ Obj = spvcDataBase:db_read({spvcObj,Key}),
+ spvcDataBase:db_delete({spvcHcIdToTp,HcId}),
+ orig_state_machine(Obj#spvcObj.currentState,release_comp_nu,Obj,[HcId,Release_comp]).
+
+release_incumbent(HcId,Release) ->
+ debug_disabled,
+ release_incumbent2(spvcDataBase:db_read({spvcHcIdToTp,HcId}),Release).
+
+release_incumbent2(SpvcHcIdToTp,Release) ->
+ release_incumbent3(SpvcHcIdToTp#spvcHcIdToTp.tpEntry,Release).
+
+release_incumbent3({orig,If,Vpi,Vci,Leaf},Release) ->
+ release_incumbent4({If,Vpi,Vci,Leaf},Release);
+release_incumbent3({orig,If,Vpi,Leaf},Release) ->
+ release_incumbent4({If,Vpi,Leaf},Release).
+
+release_incumbent4(TpKey,Release) ->
+ Spvc = spvcDataBase:db_read({spvcObj,TpKey}),
+ active = Spvc#spvcObj.currentState,
+ orig_state_machine(active,release_incumbent,Spvc,[Release]).
+
+switch_over(HcId,{If,Vpi,Vci}) ->
+ Key = case {If,Vpi,Vci} of
+ {If_Value,Vpi_Value,Vci_Value} when integer(Vci_Value) ->
+ {If_Value,Vpi_Value,Vci_Value,1};
+ {If_Value,Vpi_Value,_} ->
+ {If_Value,Vpi_Value,1};
+ {If_Value,Vpi_Value} ->
+ {If_Value,Vpi_Value,1}
+ end,
+ Spvc = spvcDataBase:db_read({spvcObj,Key}),
+ do_switch_over(HcId,Spvc);
+switch_over(HcId,{If,Vpi}) ->
+ Key = case {If,Vpi,no_vc} of
+ {If_Value,Vpi_Value,Vci_Value} when integer(Vci_Value) ->
+ {If_Value,Vpi_Value,Vci_Value,1};
+ {If_Value,Vpi_Value,_} ->
+ {If_Value,Vpi_Value,1};
+ {If_Value,Vpi_Value} ->
+ {If_Value,Vpi_Value,1}
+ end,
+ Spvc = spvcDataBase:db_read({spvcObj,Key}),
+ do_switch_over(HcId,Spvc).
+
+do_switch_over(HcId,Spvc) ->
+ State = Spvc#spvcObj.currentState,
+ orig_state_machine(State,switch_over,Spvc,[HcId]).
+
+gen_set(Type,Row,Cols) ->
+ debug_disabled,
+ gen_set(Type,Row,Cols,undefined).
+
+gen_set(Type,Row,Cols,FrKey) ->
+ debug_disabled,
+ case lists:keysearch(case {case Row of
+ {_,_,_,_} ->
+ spvcVcc;
+ {_,_,_} ->
+ spvcVpc;
+ {_,_} ->
+ spvcFr;
+ [_,_,_,_] ->
+ spvcVcc;
+ [_,_,_] ->
+ spvcVpc;
+ [_,_] ->
+ spvcFr
+ end,rowStatus} of
+ {spvcVcc,targetAddress} ->
+ 2;
+ {spvcVcc,selectType} ->
+ 3;
+ {spvcVcc,targetVpi} ->
+ 18;
+ {spvcVcc,targetVci} ->
+ 5;
+ {spvcVcc,releaseCause} ->
+ 6;
+ {spvcVcc,releaseDiagnostic} ->
+ 7;
+ {spvcVcc,retryInterval} ->
+ 10;
+ {spvcVcc,retryTimer} ->
+ 11;
+ {spvcVcc,retryThreshold} ->
+ 12;
+ {spvcVcc,retryFailures} ->
+ 13;
+ {spvcVcc,retryLimit} ->
+ 14;
+ {spvcVcc,rowStatus} ->
+ 15;
+ {spvcVcc,restart} ->
+ 9;
+ {spvcVcc,targetSelectType_any} ->
+ 2;
+ {spvcVcc,targetSelectType_required} ->
+ 1;
+ {spvcVpc,targetAddress} ->
+ 2;
+ {spvcVpc,selectType} ->
+ 3;
+ {spvcVpc,targetVpi} ->
+ 15;
+ {spvcVpc,releaseCause} ->
+ 5;
+ {spvcVpc,releaseDiagnostic} ->
+ 6;
+ {spvcVpc,retryInterval} ->
+ 9;
+ {spvcVpc,retryTimer} ->
+ 10;
+ {spvcVpc,retryThreshold} ->
+ 11;
+ {spvcVpc,retryFailures} ->
+ 12;
+ {spvcVpc,retryLimit} ->
+ 13;
+ {spvcVpc,rowStatus} ->
+ 14;
+ {spvcVpc,restart} ->
+ 8;
+ {spvcVpc,targetSelectType_any} ->
+ 2;
+ {spvcVpc,targetSelectType_required} ->
+ 1;
+ {spvcFr,targetAddress} ->
+ 3;
+ {spvcFr,selectType} ->
+ 5;
+ {spvcFr,identifier} ->
+ 6;
+ {spvcFr,targetVpi} ->
+ 7;
+ {spvcFr,targetVci} ->
+ 8;
+ {spvcFr,translation} ->
+ 9;
+ {spvcFr,releaseCause} ->
+ 10;
+ {spvcFr,releaseDiagnostic} ->
+ 11;
+ {spvcFr,operStatus} ->
+ 12;
+ {spvcFr,adminStatus} ->
+ 13;
+ {spvcFr,restart} ->
+ 14;
+ {spvcFr,retryInterval} ->
+ 15;
+ {spvcFr,retryTimer} ->
+ 16;
+ {spvcFr,retryThreshold} ->
+ 17;
+ {spvcFr,retryFailures} ->
+ 18;
+ {spvcFr,retryLimit} ->
+ 19;
+ {spvcFr,lastChange} ->
+ 20;
+ {spvcFr,rowStatus} ->
+ 21
+ end,1,Cols) of
+ {value,{_,4}} ->
+ debug_disabled,
+ mnesia:dirty_update_counter(spvcHcEtStat,spvcLib:get_board(hd(Row)),1),
+ case get_link_state(case Row of
+ Row when record(Row,spvcObj) ->
+ case Row#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Row when record(Row,spvcVcc) ->
+ {If_Value,_,_,_} = Row#spvcVcc.spvcVccEntry,
+ If_Value;
+ Row when record(Row,spvcVpc) ->
+ {If_Value,_,_} = Row#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Row when record(Row,spvcVpcPerm) ->
+ {If_Value,_,_} = Row#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Row when record(Row,spvcVccPerm) ->
+ {If_Value,_,_,_} = Row#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Row when record(Row,spvcTargetVc) ->
+ {If_Value,_,_} = Row#spvcTargetVc.entry,
+ If_Value;
+ Row when record(Row,spvcTargetVp) ->
+ {If_Value,_} = Row#spvcTargetVp.entry,
+ If_Value;
+ Row when record(Row,pchVc) ->
+ {If_Value,_,_} = Row#pchVc.vclEntry,
+ If_Value;
+ Row when record(Row,pchVp) ->
+ {If_Value,_} = Row#pchVp.vplEntry,
+ If_Value;
+ Row when record(Row,spvcFr) ->
+ {If_Value,_} = Row#spvcFr.spvcFrEntry,
+ If_Value;
+ Row when record(Row,spvcFrPerm) ->
+ {If_Value,_} = Row#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end) of
+ disabled ->
+ orig_state_machine(null,createAndGo_disabled,[],[Row,Cols,Type,FrKey]);
+ enabled ->
+ orig_state_machine(null,createAndGo_enabled,[],[Row,Cols,Type,FrKey])
+ end;
+ {value,{_,5}} ->
+ debug_disabled,
+ mnesia:dirty_update_counter(spvcHcEtStat,spvcLib:get_board(hd(Row)),1),
+ orig_state_machine(null,createAndWait,[],[Row,Cols,Type,FrKey]);
+ {value,{_,1}} ->
+ debug_disabled,
+ case spvcDataBase:db_read({spvcObj,list_to_tuple(Row)}) of
+ [] ->
+ ok;
+ Spvc ->
+ case get_link_state(case Row of
+ Row when record(Row,spvcObj) ->
+ case Row#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Row when record(Row,spvcVcc) ->
+ {If_Value,_,_,_} = Row#spvcVcc.spvcVccEntry,
+ If_Value;
+ Row when record(Row,spvcVpc) ->
+ {If_Value,_,_} = Row#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Row when record(Row,spvcVpcPerm) ->
+ {If_Value,_,_} = Row#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Row when record(Row,spvcVccPerm) ->
+ {If_Value,_,_,_} = Row#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Row when record(Row,spvcTargetVc) ->
+ {If_Value,_,_} = Row#spvcTargetVc.entry,
+ If_Value;
+ Row when record(Row,spvcTargetVp) ->
+ {If_Value,_} = Row#spvcTargetVp.entry,
+ If_Value;
+ Row when record(Row,pchVc) ->
+ {If_Value,_,_} = Row#pchVc.vclEntry,
+ If_Value;
+ Row when record(Row,pchVp) ->
+ {If_Value,_} = Row#pchVp.vplEntry,
+ If_Value;
+ Row when record(Row,spvcFr) ->
+ {If_Value,_} = Row#spvcFr.spvcFrEntry,
+ If_Value;
+ Row when record(Row,spvcFrPerm) ->
+ {If_Value,_} = Row#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end) of
+ disabled ->
+ orig_state_machine(Spvc#spvcObj.currentState,activate_disabled,Spvc,Cols);
+ enabled ->
+ orig_state_machine(Spvc#spvcObj.currentState,activate_enabled,Spvc,Cols)
+ end
+ end;
+ {value,{_,6}} ->
+ debug_disabled,
+ case spvcDataBase:db_read({spvcObj,list_to_tuple(Row)}) of
+ [] ->
+ ok;
+ Spvc ->
+ mnesia:dirty_update_counter(spvcHcEtStat,spvcLib:get_board(hd(Row)),- 1),
+ orig_state_machine(Spvc#spvcObj.currentState,destroy,Spvc,Cols)
+ end;
+ {value,{_,2}} ->
+ debug_disabled,
+ case spvcDataBase:db_read({spvcObj,list_to_tuple(Row)}) of
+ [] ->
+ mnesia:dirty_update_counter(spvcHcEtStat,spvcLib:get_board(hd(Row)),1),
+ ok;
+ Spvc ->
+ orig_state_machine(Spvc#spvcObj.currentState,not_in_service,Spvc,Cols)
+ end;
+ false ->
+ debug_disabled,
+ Spvc = spvcDataBase:db_read({spvcObj,list_to_tuple(Row)}),
+ CurrentState = Spvc#spvcObj.currentState,
+ NewSpvc = set_attrs(Spvc,Cols),
+ Restart = case {case Row of
+ {_,_,_,_} ->
+ spvcVcc;
+ {_,_,_} ->
+ spvcVpc;
+ {_,_} ->
+ spvcFr;
+ [_,_,_,_] ->
+ spvcVcc;
+ [_,_,_] ->
+ spvcVpc;
+ [_,_] ->
+ spvcFr
+ end,restart} of
+ {spvcVcc,targetAddress} ->
+ 2;
+ {spvcVcc,selectType} ->
+ 3;
+ {spvcVcc,targetVpi} ->
+ 18;
+ {spvcVcc,targetVci} ->
+ 5;
+ {spvcVcc,releaseCause} ->
+ 6;
+ {spvcVcc,releaseDiagnostic} ->
+ 7;
+ {spvcVcc,retryInterval} ->
+ 10;
+ {spvcVcc,retryTimer} ->
+ 11;
+ {spvcVcc,retryThreshold} ->
+ 12;
+ {spvcVcc,retryFailures} ->
+ 13;
+ {spvcVcc,retryLimit} ->
+ 14;
+ {spvcVcc,rowStatus} ->
+ 15;
+ {spvcVcc,restart} ->
+ 9;
+ {spvcVcc,targetSelectType_any} ->
+ 2;
+ {spvcVcc,targetSelectType_required} ->
+ 1;
+ {spvcVpc,targetAddress} ->
+ 2;
+ {spvcVpc,selectType} ->
+ 3;
+ {spvcVpc,targetVpi} ->
+ 15;
+ {spvcVpc,releaseCause} ->
+ 5;
+ {spvcVpc,releaseDiagnostic} ->
+ 6;
+ {spvcVpc,retryInterval} ->
+ 9;
+ {spvcVpc,retryTimer} ->
+ 10;
+ {spvcVpc,retryThreshold} ->
+ 11;
+ {spvcVpc,retryFailures} ->
+ 12;
+ {spvcVpc,retryLimit} ->
+ 13;
+ {spvcVpc,rowStatus} ->
+ 14;
+ {spvcVpc,restart} ->
+ 8;
+ {spvcVpc,targetSelectType_any} ->
+ 2;
+ {spvcVpc,targetSelectType_required} ->
+ 1;
+ {spvcFr,targetAddress} ->
+ 3;
+ {spvcFr,selectType} ->
+ 5;
+ {spvcFr,identifier} ->
+ 6;
+ {spvcFr,targetVpi} ->
+ 7;
+ {spvcFr,targetVci} ->
+ 8;
+ {spvcFr,translation} ->
+ 9;
+ {spvcFr,releaseCause} ->
+ 10;
+ {spvcFr,releaseDiagnostic} ->
+ 11;
+ {spvcFr,operStatus} ->
+ 12;
+ {spvcFr,adminStatus} ->
+ 13;
+ {spvcFr,restart} ->
+ 14;
+ {spvcFr,retryInterval} ->
+ 15;
+ {spvcFr,retryTimer} ->
+ 16;
+ {spvcFr,retryThreshold} ->
+ 17;
+ {spvcFr,retryFailures} ->
+ 18;
+ {spvcFr,retryLimit} ->
+ 19;
+ {spvcFr,lastChange} ->
+ 20;
+ {spvcFr,rowStatus} ->
+ 21
+ end,
+ case lists:keysearch(Restart,1,Cols) of
+ {value,{Restart,1}} ->
+ orig_state_machine(CurrentState,restart,NewSpvc,Cols);
+ _ ->
+ spvcDataBase:db_write(NewSpvc),
+ ok
+ end
+ end,
+ {noError,0}.
+
+restart_spvc(Key) ->
+ debug_disabled,
+ Spvc = spvcDataBase:db_read({spvcObj,Key}),
+ handle_restart_spvc(Spvc#spvcObj.currentState,Spvc),
+ ok.
+
+handle_restart_spvc(rest_in_peace,Spvc) ->
+ debug_disabled,
+ rest_in_peace(restart,Spvc,undefined);
+handle_restart_spvc(_,_) ->
+ ok.
+
+restart_multi_spvcs(Key) ->
+ debug_disabled,
+ Spvc = spvcDataBase:db_read({spvcObj,Key}),
+ handle_restart_multi_spvcs(Spvc#spvcObj.currentState,Spvc),
+ ok.
+
+handle_restart_multi_spvcs(rest_in_peace,Spvc) ->
+ debug_disabled,
+ handle_restart_spvc(rest_in_peace,Spvc);
+handle_restart_multi_spvcs(active,Spvc) ->
+ debug_disabled,
+ active(restart,Spvc,undefined);
+handle_restart_multi_spvcs(outgoing_callproceeding,Spvc) ->
+ debug_disabled,
+ outgoing_callproceeding(restart,Spvc,undefined);
+handle_restart_multi_spvcs(release_at_restart,Spvc) ->
+ debug_disabled,
+ release_at_restart(restart,Spvc,undefined);
+handle_restart_multi_spvcs(wait,Spvc) ->
+ debug_disabled,
+ wait(restart,Spvc,undefined);
+handle_restart_multi_spvcs(rest_in_peace,Spvc) ->
+ debug_disabled,
+ rest_in_peace(restart,Spvc,undefined);
+handle_restart_multi_spvcs(_,_) ->
+ ok.
+
+orig_state_machine(null,createAndGo_enabled,Spvc,Attrs) ->
+ null(createAndGo_enabled,Spvc,Attrs);
+orig_state_machine(null,createAndGo_disabled,Spvc,Attrs) ->
+ null(createAndGo_disabled,Spvc,Attrs);
+orig_state_machine(null,createAndWait,Spvc,Attrs) ->
+ null(createAndWait,Spvc,Attrs);
+orig_state_machine(created,activate_disabled,Spvc,Attrs) ->
+ created(activate_disabled,Spvc,Attrs);
+orig_state_machine(created,activate_enabled,Spvc,Attrs) ->
+ created(activate_enabled,Spvc,Attrs);
+orig_state_machine(created,destroy,Spvc,Attrs) ->
+ created(destroy,Spvc,Attrs);
+orig_state_machine(outgoing_callproceeding,connect_nu,Spvc,Attrs) ->
+ outgoing_callproceeding(connect_nu,Spvc,Attrs);
+orig_state_machine(outgoing_callproceeding,destroy,Spvc,Attrs) ->
+ outgoing_callproceeding(destroy,Spvc,Attrs);
+orig_state_machine(outgoing_callproceeding,restart,Spvc,Attrs) ->
+ outgoing_callproceeding(restart,Spvc,Attrs);
+orig_state_machine(outgoing_callproceeding,release_nu,Spvc,Attrs) ->
+ case get_link_state_intf(case Spvc of
+ Spvc when record(Spvc,spvcObj) ->
+ case Spvc#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Spvc when record(Spvc,spvcVcc) ->
+ {If_Value,_,_,_} = Spvc#spvcVcc.spvcVccEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVpc) ->
+ {If_Value,_,_} = Spvc#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVpcPerm) ->
+ {If_Value,_,_} = Spvc#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVccPerm) ->
+ {If_Value,_,_,_} = Spvc#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcTargetVc) ->
+ {If_Value,_,_} = Spvc#spvcTargetVc.entry,
+ If_Value;
+ Spvc when record(Spvc,spvcTargetVp) ->
+ {If_Value,_} = Spvc#spvcTargetVp.entry,
+ If_Value;
+ Spvc when record(Spvc,pchVc) ->
+ {If_Value,_,_} = Spvc#pchVc.vclEntry,
+ If_Value;
+ Spvc when record(Spvc,pchVp) ->
+ {If_Value,_} = Spvc#pchVp.vplEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcFr) ->
+ {If_Value,_} = Spvc#spvcFr.spvcFrEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcFrPerm) ->
+ {If_Value,_} = Spvc#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end,release_nu) of
+ disabled ->
+ outgoing_callproceeding(release_nu_disabled,Spvc,Attrs);
+ enabled ->
+ outgoing_callproceeding(release_nu_enabled,Spvc,Attrs)
+ end;
+orig_state_machine(outgoing_callproceeding,release_comp_nu,Spvc,Attrs) ->
+ case get_link_state_intf(tuple_to_list(Spvc#spvcObj.spvcEntry),release_comp_nu) of
+ disabled ->
+ outgoing_callproceeding(release_comp_nu_disabled,Spvc,Attrs);
+ enabled ->
+ outgoing_callproceeding(release_comp_nu_enabled,Spvc,Attrs)
+ end;
+orig_state_machine(outgoing_callproceeding,not_in_service,Spvc,Attrs) ->
+ outgoing_callproceeding(not_in_service,Spvc,Attrs);
+orig_state_machine(outgoing_callproceeding,activate_enabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(outgoing_callproceeding,activate_disabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(active,destroy,Spvc,Attrs) ->
+ active(destroy,Spvc,Attrs);
+orig_state_machine(active,restart,Spvc,Attrs) ->
+ active(restart,Spvc,Attrs);
+orig_state_machine(active,release_nu,Spvc,Attrs) ->
+ case cnhChi:get_link_opstate(case Spvc of
+ Spvc when record(Spvc,spvcObj) ->
+ case Spvc#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Spvc when record(Spvc,spvcVcc) ->
+ {If_Value,_,_,_} = Spvc#spvcVcc.spvcVccEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVpc) ->
+ {If_Value,_,_} = Spvc#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVpcPerm) ->
+ {If_Value,_,_} = Spvc#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVccPerm) ->
+ {If_Value,_,_,_} = Spvc#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcTargetVc) ->
+ {If_Value,_,_} = Spvc#spvcTargetVc.entry,
+ If_Value;
+ Spvc when record(Spvc,spvcTargetVp) ->
+ {If_Value,_} = Spvc#spvcTargetVp.entry,
+ If_Value;
+ Spvc when record(Spvc,pchVc) ->
+ {If_Value,_,_} = Spvc#pchVc.vclEntry,
+ If_Value;
+ Spvc when record(Spvc,pchVp) ->
+ {If_Value,_} = Spvc#pchVp.vplEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcFr) ->
+ {If_Value,_} = Spvc#spvcFr.spvcFrEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcFrPerm) ->
+ {If_Value,_} = Spvc#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end) of
+ disabled ->
+ active(release_nu_disabled,Spvc,Attrs);
+ enabled ->
+ active(release_nu_enabled,Spvc,Attrs)
+ end;
+orig_state_machine(active,release_comp_nu,Spvc,Attrs) ->
+ release_at_restart(release_comp_nu,Spvc,Attrs);
+orig_state_machine(active,not_in_service,Spvc,Attrs) ->
+ active(not_in_service,Spvc,Attrs);
+orig_state_machine(active,activate_enabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(active,activate_disabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(active,release_incumbent,Spvc,Attrs) ->
+ active(release_incumbent,Spvc,Attrs);
+orig_state_machine(wait,destroy,Spvc,Attrs) ->
+ wait(destroy,Spvc,Attrs);
+orig_state_machine(wait,timeout,Spvc,Attrs) ->
+ wait(timeout,Spvc,Attrs);
+orig_state_machine(wait,restart,Spvc,Attrs) ->
+ wait(restart,Spvc,Attrs);
+orig_state_machine(wait,release_nu,Spvc,Attrs) ->
+ ok;
+orig_state_machine(wait,not_in_service,Spvc,Attrs) ->
+ wait(not_in_service,Spvc,Attrs);
+orig_state_machine(wait,activate_enabled,Spvc,Attrs) ->
+ wait(timeout,Spvc,Attrs);
+orig_state_machine(wait,activate_disabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(release_at_restart,release_comp_nu,Spvc,Attrs) ->
+ release_at_restart(release_comp_nu,Spvc,Attrs);
+orig_state_machine(release_at_restart,release_nu,Spvc,Attrs) ->
+ release_at_restart(release_nu,Spvc,Attrs);
+orig_state_machine(release_at_restart,connect_nu,Spvc,Attrs) ->
+ release_at_restart(connect_nu,Spvc,Attrs);
+orig_state_machine(release_at_restart,destroy,Spvc,Attrs) ->
+ release_at_restart(destroy,Spvc,Attrs);
+orig_state_machine(release_at_restart,not_in_service,Spvc,Attrs) ->
+ release_at_restart(not_in_service,Spvc,Attrs);
+orig_state_machine(release_at_restart,activate_enabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(release_at_restart,activate_disabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(release_request,release_comp_nu,Spvc,Attrs) ->
+ release_request(release_comp_nu,Spvc,Attrs);
+orig_state_machine(release_request,release_nu,Spvc,Attrs) ->
+ release_request(release_nu,Spvc,Attrs);
+orig_state_machine(release_request,destroy,Spvc,Attrs) ->
+ release_request(destroy,Spvc,Attrs);
+orig_state_machine(release_request,not_in_service,Spvc,Attrs) ->
+ release_request(not_in_service,Spvc,Attrs);
+orig_state_machine(release_request,activate_enabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(release_request,activate_disabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(rest_in_peace,restart,Spvc,Attrs) ->
+ rest_in_peace(restart,Spvc,Attrs);
+orig_state_machine(rest_in_peace,destroy,Spvc,Attrs) ->
+ rest_in_peace(destroy,Spvc,Attrs);
+orig_state_machine(rest_in_peace,not_in_service,Spvc,Attrs) ->
+ rest_in_peace(not_in_service,Spvc,Attrs);
+orig_state_machine(rest_in_peace,connect_nu,Spvc,Attrs) ->
+ rest_in_peace(connect_nu,Spvc,Attrs);
+orig_state_machine(rest_in_peace,activate_enabled,Spvc,Attrs) ->
+ rest_in_peace(restart,Spvc,Attrs);
+orig_state_machine(rest_in_peace,activate_disabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(rest_in_peace,release_nu,Spvc,Attrs) ->
+ ok;
+orig_state_machine(rest_in_peace,release_comp_nu,Spvc,Attrs) ->
+ ok;
+orig_state_machine(not_in_service,activate_enabled,Spvc,Attrs) ->
+ not_in_service(activate_enabled,Spvc,Attrs);
+orig_state_machine(not_in_service,activate_disabled,Spvc,Attrs) ->
+ not_in_service(activate_disabled,Spvc,Attrs);
+orig_state_machine(not_in_service,destroy,Spvc,Attrs) ->
+ not_in_service(destroy,Spvc,Attrs);
+orig_state_machine(not_in_service,connect_nu,Spvc,Attrs) ->
+ not_in_service(connect_nu,Spvc,Attrs);
+orig_state_machine(not_in_service,_,Spvc,Attrs) ->
+ ok;
+orig_state_machine(awaiting_switch_over,switch_over,Spvc,[HcId]) ->
+ awaiting_switch_over(switch_over,Spvc,[HcId]);
+orig_state_machine(awaiting_switch_over,activate_disabled,Spvc,Attrs) ->
+ awaiting_switch_over(activate_disabled,Spvc,Attrs);
+orig_state_machine(awaiting_switch_over,destroy,Spvc,Attrs) ->
+ awaiting_switch_over(destroy,Spvc,Attrs);
+orig_state_machine(awaiting_switch_over,restart,Spvc,Attrs) ->
+ awaiting_switch_over(restart,Spvc,Attrs);
+orig_state_machine(awaiting_switch_over,_,Spvc,Attrs) ->
+ ok;
+orig_state_machine(undefined,destroy,Spvc,Attrs) ->
+ rest_in_peace(destroy,Spvc,Attrs).
+
+null(createAndGo_enabled,[],[Row,Cols,Type,FrKey]) ->
+ debug_disabled,
+ Key = list_to_tuple(Row),
+ Spvc = #spvcObj{spvcEntry = Key,
+ spvcApplication = Type,
+ spvcRowStatus = 1,
+ spvcFrKey = FrKey},
+ Spvc1 = set_attrs(Spvc,Cols),
+ {Spvc2,HcId,Setup} = new_state_outgoing_call_proceeding(Spvc1),
+ pchTpUpdate(case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end),
+ spvcDataBase:db_write(Spvc2),
+ setup(HcId,Setup,Spvc2);
+null(createAndGo_disabled,[],[Row,Cols,Type,FrKey]) ->
+ debug_disabled,
+ case get_link_state_intf(Row,null_createAndGo_disabled) of
+ disabled ->
+ Key = list_to_tuple(Row),
+ Spvc = #spvcObj{spvcEntry = Key,
+ spvcRowStatus = 1,
+ currentState = rest_in_peace,
+ spvcApplication = Type,
+ spvcFrKey = FrKey},
+ Spvc1 = set_attrs(Spvc,Cols),
+ pchTpUpdate(case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end),
+ set_call_failure_data_and_send_spvcFailingAlarm(Key),
+ spvcDataBase:db_write(Spvc1);
+ enabled ->
+ null(createAndGo_enabled,[],[Row,Cols,Type,FrKey])
+ end;
+null(createAndWait,[],[Row,Cols,Type,FrKey]) ->
+ debug_disabled,
+ Key = list_to_tuple(Row),
+ Spvc = #spvcObj{spvcEntry = Key,
+ spvcApplication = Type,
+ spvcFrKey = FrKey},
+ Spvc1 = new_state_created(Spvc,Cols),
+ pchTpUpdate(case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end),
+ spvcDataBase:db_write(Spvc1).
+
+pchTpUpdate({If,Vpi,Vci}) ->
+ spvcDataBase:db_write(#spvcVcDyn{vclEntry = {If,Vpi,Vci},
+ vclCcIdentifier = 0});
+pchTpUpdate({If,Vpi}) ->
+ spvcDataBase:db_write(#spvcVpDyn{vplEntry = {If,Vpi},
+ vplCcIdentifier = 0}).
+
+created(activate_enabled,Spvc,Attrs) ->
+ debug_disabled,
+ Spvc1 = set_attrs(Spvc,Attrs),
+ Spvc2 = Spvc1#spvcObj{spvcRowStatus = 1},
+ {Spvc3,HcId,HciMsg} = new_state_outgoing_call_proceeding(Spvc1),
+ spvcDataBase:db_write(Spvc3),
+ setup(HcId,HciMsg,Spvc3);
+created(activate_disabled,Spvc,Attrs) ->
+ debug_disabled,
+ Spvc1 = set_attrs(Spvc,Attrs),
+ Spvc2 = Spvc1#spvcObj{currentState = rest_in_peace,
+ spvcRowStatus = 1},
+ update_state(Spvc,4),
+ spvcDataBase:db_write(Spvc2);
+created(destroy,Spvc,Attrs) ->
+ debug_disabled,
+ clear(Spvc).
+
+outgoing_callproceeding(connect_nu,Spvc,[HcId,Connect]) ->
+ debug_disabled,
+ Spvc1 = new_state_active(Spvc),
+ case Spvc#spvcObj.spvcTargetSelectType of
+ 2 ->
+ Cpn = Connect#hci_connect.hci_cpn_soft,
+ TargetVpi = Cpn#hci_cpn_soft.hci_soft_vpi,
+ TargetVci = Cpn#hci_cpn_soft.hci_soft_vci,
+ TargetDlci = Cpn#hci_cpn_soft.hci_soft_dlci,
+ Spvc2 = Spvc1#spvcObj{spvcTargetSelectType = 1,
+ spvcTargetVpi = TargetVpi,
+ spvcTargetVci = TargetVci,
+ spvcTargetDlci = TargetDlci},
+ spvcDataBase:db_write(Spvc2);
+ 1 ->
+ spvcDataBase:db_write(ets,Spvc1);
+ 2 ->
+ Cpn = Connect#hci_connect.hci_cpn_soft,
+ TargetVpi = Cpn#hci_cpn_soft.hci_soft_vpi,
+ TargetDlci = Cpn#hci_cpn_soft.hci_soft_dlci,
+ Spvc2 = Spvc1#spvcObj{spvcTargetSelectType = 1,
+ spvcTargetVpi = TargetVpi,
+ spvcTargetDlci = TargetDlci},
+ spvcDataBase:db_write(Spvc2);
+ 1 ->
+ spvcDataBase:db_write(ets,Spvc1)
+ end,
+ Key = Spvc#spvcObj.spvcEntry,
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ SpvcDyn = case PchKey of
+ {_,_,_} ->
+ case spvcDataBase:db_read({spvcVcDyn,PchKey}) of
+ [] ->
+ #spvcVcDyn{vclEntry = PchKey,
+ vclCcIdentifier = 0,
+ vclConnId = HcId};
+ SpvcVcDyn ->
+ SpvcVcDyn#spvcVcDyn{vclEntry = PchKey,
+ vclConnId = HcId}
+ end;
+ {_,_} ->
+ case spvcDataBase:db_read({spvcVpDyn,PchKey}) of
+ [] ->
+ #spvcVpDyn{vplEntry = PchKey,
+ vplCcIdentifier = 0,
+ vplConnId = HcId};
+ SpvcVpDyn ->
+ SpvcVpDyn#spvcVpDyn{vplEntry = PchKey,
+ vplConnId = HcId}
+ end
+ end,
+ spvcDataBase:db_write(SpvcDyn),
+ CbCValue = get(no_of_rerouting),
+ CbC = case CbCValue of
+ undefined ->
+ debug_disabled,
+ 0;
+ _ ->
+ CbCValue
+ end,
+ SpvcDyn2 = case Key of
+ {_,_,_,_} ->
+ case spvcDataBase:db_read({spvcVccDyn,Key}) of
+ [] ->
+ #spvcVccDyn{spvcVccEntry = Key,
+ crankBackCounter = CbC};
+ SpvcVccDyn ->
+ SpvcVccDyn#spvcVccDyn{spvcVccEntry = Key,
+ crankBackCounter = CbC}
+ end;
+ {_,_,_} ->
+ case spvcDataBase:db_read({spvcVpcDyn,Key}) of
+ [] ->
+ #spvcVpcDyn{spvcVpcEntry = Key,
+ crankBackCounter = CbC};
+ SpvcVpcDyn ->
+ SpvcVpcDyn#spvcVpcDyn{spvcVpcEntry = Key,
+ crankBackCounter = CbC}
+ end
+ end,
+ spvcDataBase:db_write(SpvcDyn2),
+ NewPch = spvcDataBase:db_read({pch,PchKey}),
+ spvcLib:clear_spvcStillTryingAlarm(Key),
+ case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ spvcLib:ilmi_change(PchKey,1),
+ ok;
+ FrEndPoint ->
+ SpvcFrObj = spvcDataBase:db_read({spvcFrPerm,FrEndPoint}),
+ NewSpvcFrObj = SpvcFrObj#spvcFrPerm{spvcFrConnect = 3},
+ spvcDataBase:db_write(NewSpvcFrObj),
+ spvcLib:ilmi_change(PchKey,1),
+ set_fr_atm_iw_admin_state(FrEndPoint,up,Spvc)
+ end;
+outgoing_callproceeding(restart,Spvc,_) ->
+ Key = Spvc#spvcObj.spvcEntry,
+ debug_disabled,
+ Spvc1 = new_state_release_at_restart(Spvc),
+ spvcDataBase:db_write(ets,Spvc1),
+ spvcLib:clear_spvcStillTryingAlarm(Key);
+outgoing_callproceeding(release_nu_enabled,Spvc,[HcId,HciMsg]) ->
+ debug_disabled,
+ Spvc1 = new_state_rest_in_peace_or_wait(Spvc,[HcId,HciMsg]),
+ [CcCause|_] = HciMsg#hci_release.hci_cause_list,
+ Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = CcCause#hci_cause.hci_cause_value,
+ spvcLastReleaseDiagnostic = CcCause#hci_cause.hci_diagnostics_list},
+ spvcDataBase:db_write(ets,Spvc2);
+outgoing_callproceeding(release_nu_disabled,Spvc,[HcId,Release]) ->
+ debug_disabled,
+ Spvc1 = new_state_rest_in_peace(Spvc),
+ [CcCause|_] = Release#hci_release.hci_cause_list,
+ Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = CcCause#hci_cause.hci_cause_value,
+ spvcLastReleaseDiagnostic = CcCause#hci_cause.hci_diagnostics_list},
+ spvcDataBase:db_write(ets,Spvc2),
+ spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry);
+outgoing_callproceeding(release_comp_nu_enabled,Spvc,[HcId,Release_complete]) ->
+ debug_disabled,
+ Spvc1 = new_state_rest_in_peace_or_wait(Spvc,[HcId,Release_complete]),
+ spvcDataBase:db_write(ets,Spvc1);
+outgoing_callproceeding(release_comp_nu_disabled,Spvc,[HcId,Release_complete]) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_rest_in_peace(Spvc),
+ spvcDataBase:db_write(ets,Spvc1),
+ spvcLib:clear_spvcStillTryingAlarm(Key);
+outgoing_callproceeding(destroy,Spvc,_) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_release_request(Spvc),
+ spvcDataBase:db_write(ets,Spvc1),
+ SpvcTpToHcId = read_spvcTpToHcId(Key),
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc1),
+ spvcLib:clear_spvcStillTryingAlarm(Key);
+outgoing_callproceeding(not_in_service,Spvc,_) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_not_in_service(Spvc),
+ spvcDataBase:db_write(Spvc1),
+ SpvcTpToHcId = read_spvcTpToHcId(Key),
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc1),
+ spvcLib:clear_spvcStillTryingAlarm(Key).
+
+active(restart,Spvc,_) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_release_at_restart(Spvc),
+ spvcDataBase:db_write(ets,Spvc1),
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ spvcLib:ilmi_change(PchKey,2),
+ case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ ok;
+ FrEndPoint ->
+ set_fr_atm_iw_admin_state(FrEndPoint,down,Spvc)
+ end;
+active(release_nu_enabled,Spvc,[HcId,Release]) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_rest_in_peace_or_wait(Spvc,[HcId,Release]),
+ [CcCause|_] = Release#hci_release.hci_cause_list,
+ Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = CcCause#hci_cause.hci_cause_value,
+ spvcLastReleaseDiagnostic = CcCause#hci_cause.hci_diagnostics_list},
+ spvcDataBase:db_write(ets,Spvc2),
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ spvcLib:ilmi_change(PchKey,2),
+ case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ ok;
+ FrEndPoint ->
+ set_fr_atm_iw_admin_state(FrEndPoint,down,Spvc)
+ end;
+active(release_nu_disabled,Spvc,[HcId,Release]) ->
+ debug_disabled,
+ case get_link_state_intf(case Spvc of
+ Spvc when record(Spvc,spvcObj) ->
+ case Spvc#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Spvc when record(Spvc,spvcVcc) ->
+ {If_Value,_,_,_} = Spvc#spvcVcc.spvcVccEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVpc) ->
+ {If_Value,_,_} = Spvc#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVpcPerm) ->
+ {If_Value,_,_} = Spvc#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVccPerm) ->
+ {If_Value,_,_,_} = Spvc#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcTargetVc) ->
+ {If_Value,_,_} = Spvc#spvcTargetVc.entry,
+ If_Value;
+ Spvc when record(Spvc,spvcTargetVp) ->
+ {If_Value,_} = Spvc#spvcTargetVp.entry,
+ If_Value;
+ Spvc when record(Spvc,pchVc) ->
+ {If_Value,_,_} = Spvc#pchVc.vclEntry,
+ If_Value;
+ Spvc when record(Spvc,pchVp) ->
+ {If_Value,_} = Spvc#pchVp.vplEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcFr) ->
+ {If_Value,_} = Spvc#spvcFr.spvcFrEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcFrPerm) ->
+ {If_Value,_} = Spvc#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end,active_release_nu_disabled) of
+ disabled ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = Spvc#spvcObj{currentState = rest_in_peace},
+ [CcCause|_] = Release#hci_release.hci_cause_list,
+ Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = CcCause#hci_cause.hci_cause_value,
+ spvcLastReleaseDiagnostic = CcCause#hci_cause.hci_diagnostics_list},
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ spvcLib:ilmi_change(PchKey,2),
+ update_state(Spvc,4),
+ spvcDataBase:db_write(ets,Spvc2),
+ case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ ok;
+ FrEndPoint ->
+ set_fr_atm_iw_admin_state(FrEndPoint,down,Spvc)
+ end;
+ enabled ->
+ active(release_nu_enabled,Spvc,[HcId,Release])
+ end;
+active(destroy,Spvc,_) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_release_request(Spvc),
+ spvcDataBase:db_write(ets,Spvc1),
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ spvcLib:ilmi_change(PchKey,2),
+ SpvcTpToHcId = read_spvcTpToHcId(Key),
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc);
+active(not_in_service,Spvc,_) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_not_in_service(Spvc),
+ spvcDataBase:db_write(Spvc1),
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ spvcLib:ilmi_change(PchKey,2),
+ SpvcTpToHcId = read_spvcTpToHcId(Key),
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc1),
+ case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ ok;
+ FrEndPoint ->
+ set_fr_atm_iw_admin_state(FrEndPoint,down,Spvc)
+ end;
+active(release_incumbent,Spvc,[Release]) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_awaiting_switch_over(Spvc),
+ spvcDataBase:db_write(Spvc1),
+ SpvcTpToHcId = read_spvcTpToHcId(Key),
+ spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc1).
+
+read_spvcTpToHcId({If,Vpi,Vci,Leaf}) ->
+ spvcDataBase:db_read({spvcTpToHcId,{orig,If,Vpi,Vci,Leaf}});
+read_spvcTpToHcId({If,Vpi,Leaf}) ->
+ spvcDataBase:db_read({spvcTpToHcId,{orig,If,Vpi,Leaf}}).
+
+release_request(release_nu,Spvc,[HcId,Release]) ->
+ debug_disabled,
+ clear(Spvc);
+release_request(release_comp_nu,Spvc,[HcId,Release_comp]) ->
+ debug_disabled,
+ clear(Spvc);
+release_request(destroy,Spvc,_) ->
+ debug_disabled,
+ case Spvc#spvcObj.spvcEntry of
+ {If,Vpi,Vci,Leaf} ->
+ case spvcDataBase:db_read({spvcTpToHcId,{orig,If,Vpi,Vci,Leaf}}) of
+ SpvcTpToHcId ->
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc),
+ clear(Spvc);
+ _ ->
+ ok
+ end;
+ {If,Vpi,Leaf} ->
+ case spvcDataBase:db_read({spvcTpToHcId,{orig,If,Vpi,Leaf}}) of
+ SpvcTpToHcId ->
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc),
+ clear(Spvc);
+ _ ->
+ ok
+ end
+ end,
+ ok;
+release_request(not_in_service,Spvc,_) ->
+ debug_disabled,
+ ok.
+
+release_at_restart(release_nu,Spvc,[HcId,Release]) ->
+ debug_disabled,
+ {Spvc1,NewHcId,Setup} = new_state_outgoing_call_proceeding(Spvc),
+ [CcCause|_] = Release#hci_release.hci_cause_list,
+ Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = CcCause#hci_cause.hci_cause_value,
+ spvcLastReleaseDiagnostic = CcCause#hci_cause.hci_diagnostics_list},
+ spvcDataBase:db_write(ets,Spvc2),
+ timer:sleep(500),
+ setup(NewHcId,Setup,Spvc2);
+release_at_restart(release_comp_nu,Spvc,[HcId,Release_complete]) ->
+ debug_disabled,
+ {Spvc1,NewHcId,Setup} = new_state_outgoing_call_proceeding(Spvc),
+ Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = 31,
+ spvcLastReleaseDiagnostic = []},
+ spvcDataBase:db_write(ets,Spvc2),
+ timer:sleep(500),
+ setup(NewHcId,Setup,Spvc1);
+release_at_restart(connect_nu,Spvc,_) ->
+ debug_disabled,
+ ok;
+release_at_restart(destroy,Spvc,_) ->
+ debug_disabled,
+ Spvc1 = new_state_release_request(Spvc),
+ spvcDataBase:db_write(ets,Spvc1);
+release_at_restart(restart,Spvc,_) ->
+ debug_disabled,
+ Spvc1 = new_state_release_at_restart(Spvc);
+release_at_restart(not_in_service,Spvc,_) ->
+ debug_disabled,
+ Spvc1 = new_state_not_in_service(Spvc),
+ spvcDataBase:db_write(Spvc1).
+
+wait(timeout,Spvc,_) ->
+ debug_disabled,
+ {Spvc1,HcId,Setup} = new_state_outgoing_call_proceeding(Spvc),
+ spvcDataBase:db_write(ets,Spvc1),
+ setup(HcId,Setup,Spvc1);
+wait(destroy,Spvc,_) ->
+ debug_disabled,
+ spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
+ clear(Spvc);
+wait(restart,Spvc,_) ->
+ debug_disabled,
+ {Spvc1,HcId,Setup} = new_state_outgoing_call_proceeding(Spvc#spvcObj{spvcRetryFailures = 0}),
+ spvcDataBase:db_write(ets,Spvc1),
+ spvcReestablishTimer:cancel(Spvc#spvcObj.spvcEntry),
+ spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
+ setup(HcId,Setup,Spvc1);
+wait(not_in_service,Spvc,_) ->
+ debug_disabled,
+ Spvc1 = new_state_not_in_service(Spvc),
+ spvcDataBase:db_write(Spvc1),
+ spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry).
+
+rest_in_peace(restart,Spvc,_) ->
+ debug_disabled,
+ {Spvc1,HcId,Setup} = new_state_outgoing_call_proceeding(Spvc#spvcObj{spvcRetryFailures = 0}),
+ spvcDataBase:db_write(ets,Spvc1),
+ setup(HcId,Setup,Spvc1),
+ sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcLib,clear_spvcFailingAlarm,[spvcLib:get_membership(node())]);
+rest_in_peace(destroy,Spvc,_) ->
+ debug_disabled,
+ sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcLib,clear_spvcFailingAlarm,[spvcLib:get_membership(node())]),
+ clear(Spvc);
+rest_in_peace(connect_nu,Spvc,_) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ SpvcTpToHcId = read_spvcTpToHcId(Key),
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(b_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc);
+rest_in_peace(not_in_service,Spvc,_) ->
+ debug_disabled,
+ Spvc1 = new_state_not_in_service(Spvc),
+ spvcDataBase:db_write(Spvc1),
+ sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcLib,clear_spvcFailingAlarm,[spvcLib:get_membership(node())]).
+
+not_in_service(activate_enabled,Spvc,_) ->
+ debug_disabled,
+ {Spvc1,HcId,Setup} = new_state_outgoing_call_proceeding(Spvc#spvcObj{spvcRetryFailures = 0}),
+ spvcDataBase:db_write(Spvc1#spvcObj{spvcRowStatus = 1}),
+ setup(HcId,Setup,Spvc1);
+not_in_service(activate_disabled,Spvc,_) ->
+ debug_disabled,
+ Spvc1 = new_state_rest_in_peace(Spvc),
+ spvcDataBase:db_write(Spvc1#spvcObj{spvcRowStatus = 1});
+not_in_service(connect_nu,Spvc,_) ->
+ debug_disabled,
+ Spvc1 = new_state_rest_in_peace(Spvc),
+ spvcDataBase:db_write(Spvc1#spvcObj{spvcRowStatus = 1}),
+ Key = Spvc#spvcObj.spvcEntry,
+ SpvcTpToHcId = read_spvcTpToHcId(Key),
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(b_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc1);
+not_in_service(destroy,Spvc,_) ->
+ debug_disabled,
+ clear(Spvc).
+
+awaiting_switch_over(switch_over,Spvc,[HcId]) ->
+ debug_disabled,
+ Spvc1 = Spvc#spvcObj{currentState = active},
+ Index = Spvc#spvcObj.spvcEntry,
+ TpIndex = create_tp_index(Index),
+ spvcDataBase:db_write(Spvc1),
+ ets:insert(spvcTpToHcId,#spvcTpToHcId{tpEntry = TpIndex,
+ hcId = HcId}),
+ ets:insert(spvcHcIdToTp,#spvcHcIdToTp{tpEntry = TpIndex,
+ hcId = HcId}),
+ update_dyn_table_hcid(Index,HcId),
+ ok;
+awaiting_switch_over(activate_disabled,Spvc,Attrs) ->
+ Spvc1 = new_state_rest_in_peace(Spvc),
+ spvcDataBase:db_write(Spvc1),
+ ok;
+awaiting_switch_over(restart,Spvc,Attrs) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_release_at_restart(Spvc),
+ spvcDataBase:db_write(ets,Spvc1),
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ spvcLib:ilmi_change(PchKey,2),
+ case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ ok;
+ FrEndPoint ->
+ set_fr_atm_iw_admin_state(FrEndPoint,down,Spvc)
+ end;
+awaiting_switch_over(destroy,Spvc,Attrs) ->
+ clear(Spvc).
+
+create_tp_index({If,Vpi,Vci,Leaf}) ->
+ list_to_tuple([orig,If,Vpi,Vci,Leaf]);
+create_tp_index({If,Vpi,Leaf}) ->
+ list_to_tuple([orig,If,Vpi,Leaf]).
+
+update_dyn_table_hcid({If,Vpi,Vci,Leaf},HcId) ->
+ [VcDyn] = ets:lookup(spvcVcDyn,{If,Vpi,Vci}),
+ ets:insert(spvcVcDyn,VcDyn#spvcVcDyn{vclConnId = HcId});
+update_dyn_table_hcid({If,Vpi,Leaf},HcId) ->
+ [VpDyn] = ets:lookup(spvcVpDyn,{If,Vpi}),
+ ets:insert(spvcVpDyn,VpDyn#spvcVpDyn{vplConnId = HcId}).
+
+new_state_outgoing_call_proceeding(Spvc) ->
+ debug_disabled,
+ Spvc1 = Spvc#spvcObj{spvcRowStatus = 1,
+ currentState = outgoing_callproceeding},
+ Key = Spvc1#spvcObj.spvcEntry,
+ update_state(Spvc,outgoing_callproceeding),
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ {FwdAtdIndex,BwdAtdIndex} = case PchKey of
+ {_,_,_} ->
+ Vc = spvcDataBase:db_read({pchVc,PchKey}),
+ {Vc#pchVc.vclReceiveTrafficDescrIndex,Vc#pchVc.vclTransmitTrafficDescrIndex};
+ {_,_} ->
+ Vp = spvcDataBase:db_read({pchVp,PchKey}),
+ {Vp#pchVp.vplReceiveTrafficDescrIndex,Vp#pchVp.vplTransmitTrafficDescrIndex}
+ end,
+ FwdPchAtd = spvcDataBase:db_read({pchAtd,FwdAtdIndex}),
+ BwdPchAtd = spvcDataBase:db_read({pchAtd,BwdAtdIndex}),
+ Row = tuple_to_list(Key),
+ HcId = spvcLib:create_hcid(Row,case Row of
+ Row when record(Row,spvcObj) ->
+ case Row#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Row when record(Row,spvcVcc) ->
+ {If_Value,_,_,_} = Row#spvcVcc.spvcVccEntry,
+ If_Value;
+ Row when record(Row,spvcVpc) ->
+ {If_Value,_,_} = Row#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Row when record(Row,spvcVpcPerm) ->
+ {If_Value,_,_} = Row#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Row when record(Row,spvcVccPerm) ->
+ {If_Value,_,_,_} = Row#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Row when record(Row,spvcTargetVc) ->
+ {If_Value,_,_} = Row#spvcTargetVc.entry,
+ If_Value;
+ Row when record(Row,spvcTargetVp) ->
+ {If_Value,_} = Row#spvcTargetVp.entry,
+ If_Value;
+ Row when record(Row,pchVc) ->
+ {If_Value,_,_} = Row#pchVc.vclEntry,
+ If_Value;
+ Row when record(Row,pchVp) ->
+ {If_Value,_} = Row#pchVp.vplEntry,
+ If_Value;
+ Row when record(Row,spvcFr) ->
+ {If_Value,_} = Row#spvcFr.spvcFrEntry,
+ If_Value;
+ Row when record(Row,spvcFrPerm) ->
+ {If_Value,_} = Row#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end),
+ Setup = spvcEncode:encode_cc_setup(Row,Spvc1,FwdPchAtd,BwdPchAtd),
+ debug_disabled,
+ debug_disabled,
+ debug_disabled,
+ {Spvc1,HcId,Setup}.
+
+new_state_release_request(Spvc) ->
+ debug_disabled,
+ update_state(Spvc,release_request),
+ Spvc#spvcObj{currentState = release_request}.
+
+new_state_release_at_restart(Spvc) ->
+ debug_disabled,
+ Spvc1 = Spvc#spvcObj{spvcRetryFailures = 0,
+ currentState = release_at_restart},
+ update_state(Spvc,release_at_restart),
+ HcId = spvcEncode:encode_cc_hcid(Spvc1#spvcObj.spvcEntry),
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(a_side,HcId,Release,Spvc1),
+ Spvc1.
+
+new_state_rest_in_peace_or_wait(Spvc,[HcId,HciMsg]) ->
+ debug_disabled,
+ Spvc1 = Spvc#spvcObj{spvcRetryFailures = Spvc#spvcObj.spvcRetryFailures + 1},
+ case check_limits(Spvc1) of
+ {ok,ok,no_retries} ->
+ send_spvcFailingAlarm(Spvc#spvcObj.spvcEntry),
+ update_state(Spvc,4),
+ spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
+ Spvc1#spvcObj{currentState = rest_in_peace};
+ {ok,ok,_} ->
+ Spvc2 = Spvc1#spvcObj{spvcRetryTimer = time(),
+ currentState = wait},
+ update_state(Spvc,wait),
+ start_timer(wait,Spvc2),
+ Spvc2;
+ {retry_threshold,ok,no_retries} ->
+ Spvc2 = Spvc1#spvcObj{currentState = rest_in_peace},
+ update_state(Spvc,4),
+ send_call_failure(Spvc),
+ send_spvcFailingAlarm(Spvc#spvcObj.spvcEntry),
+ spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
+ Spvc2;
+ {retry_threshold,ok,_} ->
+ Spvc2 = Spvc1#spvcObj{spvcRetryTimer = time(),
+ currentState = wait},
+ update_state(Spvc,wait),
+ send_call_failure(Spvc2),
+ start_timer(wait,Spvc2),
+ Spvc2;
+ {ok,retry_limit,_} ->
+ send_spvcFailingAlarm(Spvc#spvcObj.spvcEntry),
+ update_state(Spvc,4),
+ spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
+ Spvc1#spvcObj{currentState = rest_in_peace};
+ {retry_threshold,retry_limit,_} ->
+ Spvc2 = Spvc1#spvcObj{currentState = rest_in_peace},
+ update_state(Spvc,4),
+ send_call_failure(Spvc2),
+ send_spvcFailingAlarm(Spvc#spvcObj.spvcEntry),
+ spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
+ Spvc2
+ end.
+
+send_call_failure(Spvc) ->
+ case Spvc#spvcObj.spvcRetryThreshold of
+ 0 ->
+ ok;
+ _ ->
+ sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcOrig,call_failure,[Spvc])
+ end.
+
+new_state_rest_in_peace(Spvc) ->
+ debug_disabled,
+ update_state(Spvc,4),
+ Spvc1 = Spvc#spvcObj{spvcRetryFailures = Spvc#spvcObj.spvcRetryFailures + 1},
+ send_spvcFailingAlarm(Spvc#spvcObj.spvcEntry),
+ case check_limits(Spvc1) of
+ {ok,_,_} ->
+ Spvc1#spvcObj{currentState = rest_in_peace};
+ {retry_threshold,_,_} ->
+ Spvc2 = Spvc1#spvcObj{currentState = rest_in_peace},
+ case Spvc2#spvcObj.spvcRetryThreshold of
+ 0 ->
+ ok;
+ _ ->
+ sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcOrig,call_failure,[Spvc2])
+ end,
+ Spvc2
+ end.
+
+new_state_active(Spvc) ->
+ debug_disabled,
+ update_state(Spvc,3),
+ Spvc#spvcObj{spvcRetryFailures = 0,
+ currentState = active}.
+
+new_state_created(Spvc,SetCols) ->
+ debug_disabled,
+ update_state(Spvc,created),
+ case spvcSNMP:is_all_values(case Spvc#spvcObj.spvcEntry of
+ {_,_,_,_} ->
+ spvcVcc;
+ {_,_,_} ->
+ spvcVpc;
+ {_,_} ->
+ spvcFr;
+ [_,_,_,_] ->
+ spvcVcc;
+ [_,_,_] ->
+ spvcVpc;
+ [_,_] ->
+ spvcFr
+ end,SetCols) of
+ true ->
+ Spvc1 = Spvc#spvcObj{spvcRowStatus = 2,
+ currentState = created},
+ set_attrs(Spvc1,SetCols);
+ false ->
+ Spvc1 = Spvc#spvcObj{spvcRowStatus = 3,
+ currentState = created},
+ set_attrs(Spvc1,SetCols)
+ end.
+
+new_state_not_in_service(Spvc) ->
+ debug_disabled,
+ update_state(Spvc,not_in_service),
+ Spvc#spvcObj{currentState = not_in_service,
+ spvcRowStatus = 2}.
+
+new_state_awaiting_switch_over(Spvc) ->
+ debug_disabled,
+ Spvc#spvcObj{currentState = awaiting_switch_over}.
+
+update_state(Spvc,NewState) ->
+ State = Spvc#spvcObj.currentState,
+ SpvcEntry = Spvc#spvcObj.spvcEntry,
+ debug_disabled,
+ spvcLib:update_state({State,SpvcEntry},NewState).
+
+send_spvcFailingAlarm(Key) ->
+ debug_disabled,
+ rpc:cast(spvcLib:get_cp(om_node),spvcLib,send_spvcFailingAlarm,[Key]).
+
+set_call_failure_data_and_send_spvcFailingAlarm({If,Vpi,Leaf}) ->
+ debug_disabled,
+ Spvc = spvcDataBase:db_read({spvcObj,{If,Vpi,Leaf}}),
+ if
+ Spvc == [] ->
+ ok;
+ true ->
+ spvcLib:update_state({Spvc#spvcObj.currentState,{If,Vpi,Leaf}},4)
+ end;
+set_call_failure_data_and_send_spvcFailingAlarm({If,Vpi,Vci,Leaf}) ->
+ debug_disabled,
+ Spvc = spvcDataBase:db_read({spvcObj,{If,Vpi,Vci,Leaf}}),
+ if
+ Spvc == [] ->
+ ok;
+ true ->
+ spvcLib:update_state({Spvc#spvcObj.currentState,{If,Vpi,Vci,Leaf}},4)
+ end.
+
+set_attrs(Spvc,SetCols) ->
+ case Spvc#spvcObj.spvcEntry of
+ {_,_,_,_} ->
+ set_attrs_spvcc(Spvc,SetCols);
+ {_,_,_} ->
+ set_attrs_spvpc(Spvc,SetCols)
+ end.
+
+set_attrs_spvcc(Spvc,[{2,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetAddress = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{3,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetSelectType = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{18,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetVpi = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{4,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetVpi = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{5,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetVci = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{6,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcLastReleaseCause = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{7,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcLastReleaseDiagnostic = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{10,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryInterval = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{11,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryTimer = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{12,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryThreshold = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{13,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryFailures = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{14,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryLimit = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{16,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetDlci = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{17,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetType = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[_|T]) ->
+ set_attrs_spvcc(Spvc,T);
+set_attrs_spvcc(Spvc,[]) ->
+ debug_disabled,
+ Spvc.
+
+set_attrs_spvpc(Spvc,[{2,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetAddress = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{3,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetSelectType = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{15,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetVpi = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{4,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetVpi = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{5,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcLastReleaseCause = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{6,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcLastReleaseDiagnostic = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{9,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryInterval = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{10,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryTimer = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{11,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryThreshold = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{12,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryFailures = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{13,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryLimit = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[_|T]) ->
+ set_attrs_spvpc(Spvc,T);
+set_attrs_spvpc(Spvc,[]) ->
+ Spvc.
+
+call_failure(Spvc) ->
+ debug_disabled,
+ Key = case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ spvcLib:update_counter(callFailures,1,spvcLib:get_membership(node())),
+ atm_spvc;
+ _ ->
+ spvcLib:update_counter(callFrFailures,1,spvcLib:get_membership(node())),
+ fr_spvc
+ end,
+ Obj = spvcDataBase:db_read({spvcFailures,Key}),
+ case Obj#spvcFailures.spvcCallFailuresTrapEnable of
+ 1 ->
+ EventIndObj = spvcDataBase:db_read({spvcEventIndicator,Key}),
+ case EventIndObj#spvcEventIndicator.spvcTimerInd of
+ 1 ->
+ spvcDataBase:db_write(EventIndObj#spvcEventIndicator{spvcSendEventInd = 1}),
+ NI = Obj#spvcFailures.spvcNotificationInterval,
+ sysTimer:apply_after(1000 * NI,spvcOrig,timeout_event,[EventIndObj]);
+ _ ->
+ spvcManager:send_event(Key),
+ NI = Obj#spvcFailures.spvcNotificationInterval,
+ sysTimer:apply_after(1000 * NI,spvcManager,timeout,[Key]),
+ spvcDataBase:db_write(EventIndObj#spvcEventIndicator{spvcTimerInd = 1,
+ spvcSendEventInd = 2})
+ end;
+ _ ->
+ ok
+ end.
+
+timeout_event(EventIndObj) ->
+ spvcDataBase:db_write(EventIndObj#spvcEventIndicator{spvcTimerInd = 2}).
+
+check_limits(Spvc) ->
+ debug_disabled,
+ T = Spvc#spvcObj.spvcRetryThreshold,
+ L = Spvc#spvcObj.spvcRetryLimit,
+ F = Spvc#spvcObj.spvcRetryFailures,
+ I = Spvc#spvcObj.spvcRetryInterval,
+ {check_threshold(F,T),check_limit(F,L),check_interval(I)}.
+
+check_threshold(Failures,Threshold) when Failures == Threshold ->
+ debug_disabled,
+ retry_threshold;
+check_threshold(Failures,Threshold) ->
+ debug_disabled,
+ ok.
+
+check_limit(Failures,0) ->
+ debug_disabled,
+ ok;
+check_limit(Failures,Limit) when Failures < Limit ->
+ debug_disabled,
+ ok;
+check_limit(Failures,Limit) ->
+ debug_disabled,
+ retry_limit.
+
+check_interval(0) ->
+ no_retries;
+check_interval(I) ->
+ I.
+
+start_timer(wait,Spvc) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Id = spvcReestablishTimer:apply_after(backoff_delay(Key),spvcServer,cast_to_spvc,[node(),spvcOrig,timeout,[wait,Key]]).
+
+timeout(wait,Key) ->
+ debug_disabled,
+ case spvcDataBase:db_read({spvcObj,Key}) of
+ [] ->
+ debug_disabled,
+ ok;
+ Spvc ->
+ case Spvc#spvcObj.currentState of
+ wait ->
+ IfIndex = element(1,Key),
+ case spvcOam:is_reassign_et_in_progress(IfIndex) of
+ true ->
+ ok;
+ _ ->
+ orig_state_machine(wait,timeout,Spvc,[])
+ end;
+ _ ->
+ ok
+ end
+ end;
+timeout(X,Y) ->
+ debug_disabled,
+ ok.
+
+clear(Spvc) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ spvcEndPoint:free_tp_spvc(PchKey),
+ spvcDataBase:db_delete({spvcObj,Key}),
+ update_state(Spvc,clear),
+ OrigKey = list_to_tuple([orig] ++ tuple_to_list(Key)),
+ case Spvc#spvcObj.currentState of
+ created ->
+ ok;
+ _ ->
+ case spvcDataBase:db_read({spvcTpToHcId,OrigKey}) of
+ [] ->
+ ok;
+ #spvcTpToHcId{hcId = HcId} ->
+ spvcDataBase:db_delete({spvcHcIdToTp,HcId})
+ end,
+ ets:delete(spvcTpToHcId,OrigKey),
+ spvcReestablishTimer:cancel(Key),
+ ets:delete(spvcBackoff,Spvc#spvcObj.spvcEntry)
+ end,
+ case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcEndPoint,remove_tp,[tuple_to_list(PchKey)]);
+ FrKey ->
+ spvcFr:clean_up(FrKey)
+ end,
+ case {Spvc#spvcObj.spvcRerCap,Spvc#spvcObj.spvcEntry} of
+ {false,_} ->
+ ok;
+ {true,Entry} when size(Entry) == 3 ->
+ spvcDataBase:db_delete({spvcRerVp,Entry});
+ {true,Entry} when size(Entry) == 4 ->
+ spvcDataBase:db_delete({spvcRerVc,Entry})
+ end.
+
+get_link_state(If) when integer(If) ->
+ debug_disabled,
+ cnhChi:get_link_opstate(If);
+get_link_state(Other) ->
+ debug_disabled,
+ disabled.
+
+get_link_state_intf(If,Msg) when integer(If) ->
+ debug_disabled,
+ case cnhChi:get_link_opstate(If) of
+ enabled ->
+ enabled;
+ _ ->
+ Om_Node = spvcLib:get_cp(om_node),
+ case rpc:call(Om_Node,intfI,get_link_op_state,[If]) of
+ {ok,enabled} ->
+ enabled;
+ Result ->
+ disabled
+ end
+ end;
+get_link_state_intf(Other,Msg) ->
+ debug_disabled,
+ disabled.
+
+setup(HcId,Setup,Spvc) ->
+ case spvcDataBase:db_read({spvcObj,Spvc#spvcObj.spvcEntry}) of
+ [] ->
+ ok;
+ Spvc1 ->
+ case Spvc#spvcObj.currentState == Spvc1#spvcObj.currentState of
+ true ->
+ spvcLib:increase_counter(spvcSaEtStat,Spvc),
+ case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ do_setup(HcId,Setup,Spvc#spvcObj.spvcRerCap);
+ FrKey ->
+ do_setup(HcId,Setup,FrKey)
+ end;
+ _ ->
+ ok
+ end
+ end.
+
+do_setup(HcId,Setup,Type) when Type == undefined; Type == false ->
+ debug_disabled,
+ ReturnData = {0,HcId},
+ L3Data = {0,[HcId,Setup]},
+ mdisp:msg(node(),{plcOperator,1,infinity},{HcId,{spvcI,ReturnData}},{ccI,l3_msg,[HcId,spvcI,L3Data]});
+do_setup(HcId,Setup,true) ->
+ debug_disabled,
+ ReturnData = {0,HcId},
+ L3Data = {0,[HcId,Setup]},
+ mdisp:msg(node(),{plcOperator,1,infinity},{HcId,{spvcRerI,ReturnData}},{ccI,l3_msg,[HcId,spvcRerI,L3Data]});
+do_setup(HcId,Setup,FrKey) ->
+ debug_disabled,
+ ReturnData = {0,HcId},
+ L3Data = {0,[HcId,Setup]},
+ mdisp:msg(node(),{plcOperator,1,infinity},{HcId,{spvcFrI,ReturnData}},{ccI,l3_msg,[HcId,spvcFrI,L3Data]}).
+
+backoff_delay(Key) ->
+ debug_disabled,
+ Obj = spvcDataBase:db_read({spvcObj,Key}),
+ Var = spvcDataBase:db_read({spvcFailures,atm_spvc}),
+ {Delay,Flag} = case Obj#spvcObj.spvcRetryFailures of
+ 0 ->
+ {100,no_alarm};
+ 1 ->
+ {Obj#spvcObj.spvcRetryInterval,no_alarm};
+ _ ->
+ Table = get_backoff_table(Key,Obj),
+ Max_Delay = Var#spvcFailures.max_delay,
+ case Var#spvcFailures.delay_factor * Table#spvcBackoff.delay_time of
+ DelayValue when DelayValue < Max_Delay ->
+ {DelayValue,no_alarm};
+ _ ->
+ Org_Retry_Interval = Obj#spvcObj.spvcRetryInterval,
+ if
+ Org_Retry_Interval < Max_Delay ->
+ spvcLib:send_spvcStillTryingAlarm(Key,Table#spvcBackoff.flag),
+ {Max_Delay,alarm};
+ true ->
+ spvcLib:send_spvcStillTryingAlarm(Key,Table#spvcBackoff.flag),
+ {Org_Retry_Interval,alarm}
+ end
+ end
+ end,
+ ets:insert(spvcBackoff,#spvcBackoff{key = Key,
+ delay_time = Delay,
+ flag = Flag}),
+ round(Delay).
+
+get_backoff_table(Index,Spvc) ->
+ case ets:lookup(spvcBackoff,Index) of
+ [Obj] ->
+ Obj;
+ _ ->
+ #spvcBackoff{key = Spvc#spvcObj.spvcEntry,
+ delay_time = Spvc#spvcObj.spvcRetryInterval,
+ flag = no_alarm}
+ end.
+
+set_fr_atm_iw_admin_state(FrEndPoint,up,Spvc) ->
+ ok;
+set_fr_atm_iw_admin_state(FrEndPoint,NewStatus,Spvc) ->
+ ok.
+
+forced_release(FrEndPoint) ->
+ FrPerm = spvcDataBase:db_read({spvcFr,FrEndPoint}),
+ case FrPerm of
+ [] ->
+ {error,no_fr_spvc};
+ _ ->
+ Key = FrPerm#spvcFr.spvcFrAtmEntry,
+ Spvc = spvcDataBase:db_read({spvcObj,Key}),
+ SpvcFrObj = spvcDataBase:db_read({spvcFrPerm,FrEndPoint}),
+ case SpvcFrObj#spvcFrPerm.spvcFrConnect of
+ 3 ->
+ SpvcTpToHcId = read_spvcTpToHcId(Key),
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(b_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc);
+ _ ->
+ {error,target_not_owned_by_this_connection}
+ end
+ end.
diff --git a/lib/dialyzer/test/user_SUITE_data/src/wdp.hrl b/lib/dialyzer/test/user_SUITE_data/src/wdp.hrl
new file mode 100644
index 0000000000..767e4d84c3
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/wdp.hrl
@@ -0,0 +1,96 @@
+
+%%
+%% WAP Port Number Definitions (WDP Appendix B.)
+%%
+
+-define(WAP_PORT_WTA_CL_SEC, 2805).
+-define(WAP_PORT_WTA_CO_SEC, 2923).
+-define(WAP_PORT_PUSH_CL, 2948).
+-define(WAP_PORT_PUSH_CL_SEC, 2949).
+
+-define(WAP_PORT_CL, 9200).
+-define(WAP_PORT_CO, 9201).
+-define(WAP_PORT_CL_SEC, 9202).
+-define(WAP_PORT_CO_SEC, 9203).
+-define(WAP_PORT_VCARD, 9204).
+-define(WAP_PORT_VCAL, 9205).
+-define(WAP_PORT_VCARD_SEC, 9206).
+-define(WAP_PORT_VCAL_SEC, 9207).
+
+-define(WAP_PORT_RINGTONE, 5505).
+-define(WAP_PORT_OPER_LOGO, 5506).
+-define(WAP_PORT_CLI_LOGO, 5507).
+
+%%
+%% WDP Bearer Type Assignments (WDP Appendix C.)
+%%
+
+%%
+%% Names after the tag WAP_BEARER_ is [network]_[bearer_type]_[address_type]
+%%
+-define(WAP_BEARER_ANY_ANY_IPV4, 16#00).
+-define(WAP_BEARER_ANY_ANY_IPV6, 16#01).
+-define(WAP_BEARER_GSM_USSD_ANY, 16#02).
+-define(WAP_BEARER_GSM_SMS_GSMMSISDN, 16#03).
+-define(WAP_BEARER_ANSI136_GUTS_ANSI136MSISDN, 16#04).
+-define(WAP_BEARER_IS95CDMA_SMS_IS637MSISDN, 16#05).
+-define(WAP_BEARER_IS95CDMA_CSD_IPV4, 16#06).
+-define(WAP_BEARER_IS95CDMA_PACKETDATA_IPV4, 16#07).
+-define(WAP_BEARER_ANSI136_CSD_IPV4, 16#08).
+-define(WAP_BEARER_ANSI136_PACKETDATA_IPV4, 16#09).
+-define(WAP_BEARER_GSM_CSD_IPV4, 16#0a).
+-define(WAP_BEARER_GSM_GPRS_IPV4, 16#0b).
+-define(WAP_BEARER_GSM_USSD_IPV4, 16#0c).
+-define(WAP_BEARER_AMPS_CDPD_IPV4, 16#0d).
+-define(WAP_BEARER_PDC_CSD_IPV4, 16#0e).
+-define(WAP_BEARER_PDC_PACKETDATA_IPV4, 16#0f).
+-define(WAP_BEARER_IDEN_SMS_IDENMSISDN, 16#10).
+-define(WAP_BEARER_IDEN_CSD_IPV4, 16#11).
+-define(WAP_BEARER_IDEN_PACKETDATA_IPV4, 16#12).
+-define(WAP_BEARER_PAGINGNETWORK_FLEX_FLEXMSISDN, 16#13).
+-define(WAP_BEARER_PHS_SMS_PHSMSISDN, 16#14).
+-define(WAP_BEARER_PHS_CSD_IPV4, 16#15).
+-define(WAP_BEARER_GSM_USSD_GSMSERVICECODE, 16#16).
+-define(WAP_BEARER_TETRA_SDS_TETRAITSI, 16#17).
+-define(WAP_BEARER_TETRA_SDS_TETRAMSISDN, 16#18).
+-define(WAP_BEARER_TETRA_PACKETDATA_IPV4, 16#19).
+-define(WAP_BEARER_PAGINGNETWORK_REFLEX_REFLEXMSISDN, 16#1a).
+-define(WAP_BEARER_GSM_USSD_GSMMSISDN, 16#1b).
+-define(WAP_BEARER_MOBITEX_MPAK_MAN, 16#1c).
+-define(WAP_BEARER_ANSI136_GHOST_GSMMSISDN, 16#1d).
+
+-record(wdp_address,
+ {
+ bearer,
+ address,
+ portnum
+ }).
+
+-record(wdp_sap_info,
+ {
+ mtu, %% max transmission unit (bytes)
+ mru %% max receive unit (bytes)
+ }).
+
+%%
+%% Source and destination address are wdp_addresses
+%%
+-record(wdp_socket_pair,
+ {
+ source,
+ destination
+ }).
+
+-record(wdp_local_port,
+ {
+ port, %% wdp "socket"
+ sap, %% source address
+ user, %% WDP user process
+ monitor %% monitor on WDP user
+ }).
+
+-record(wdp_local_sap,
+ {
+ sap, %% source address
+ port %% wdp "socket"
+ }).
diff --git a/lib/dialyzer/test/user_SUITE_data/src/wsp.hrl b/lib/dialyzer/test/user_SUITE_data/src/wsp.hrl
new file mode 100644
index 0000000000..0adcc13874
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/wsp.hrl
@@ -0,0 +1,239 @@
+
+%% WSP Table 34. PDU Type Assignments
+%%
+
+-define(WSP_Connect, 16#01).
+-define(WSP_ConnectReply, 16#02).
+-define(WSP_Redirect, 16#03).
+-define(WSP_Reply, 16#04).
+-define(WSP_Disconnect, 16#05).
+-define(WSP_Push, 16#06).
+-define(WSP_ConfirmedPush, 16#07).
+-define(WSP_Suspend, 16#08).
+-define(WSP_Resume, 16#09).
+
+-define(WSP_Get, 16#40).
+-define(WSP_Options, 16#41).
+-define(WSP_Head, 16#42).
+-define(WSP_Delete, 16#43).
+-define(WSP_Trace, 16#44).
+
+-define(WSP_Post, 16#60).
+-define(WSP_Put, 16#61).
+
+-define(WSP_DataFragmentPDU, 16#80).
+
+%%
+%% WSP Table 37. Capability Assignments
+%%
+
+-define(WSP_CAP_CLIENT_SDU_SIZE, 16#00).
+-define(WSP_CAP_SERVER_SDU_SIZE, 16#01).
+-define(WSP_CAP_PROTOCOL_OPTIONS, 16#02).
+-define(WSP_CAP_METHOD_MOR, 16#03).
+-define(WSP_CAP_PUSH_MOR, 16#04).
+-define(WSP_CAP_EXTENDED_METHODS, 16#05).
+-define(WSP_CAP_HEADER_CODE_PAGES, 16#06).
+-define(WSP_CAP_ALIASES, 16#07).
+-define(WSP_CAP_CLIENT_MESSAGE_SIZE, 16#08).
+-define(WSP_CAP_SERVER_MESSAGE_SIZE, 16#09).
+
+-define(WSP_CODEPAGE_1, 1).
+-define(WSP_DEFAULT_CODEPAGE, ?WSP_CODEPAGE_1).
+
+-define(ANY_LANGUAGE,128).
+
+-define(WSP_10, {1,0}).
+-define(WSP_11, {1,1}).
+-define(WSP_12, {1,2}).
+-define(WSP_13, {1,3}).
+-define(WSP_14, {1,4}).
+-define(WSP_15, {1,5}).
+
+-define(WSP_COMPLIENT_VERSION, ?WSP_15).
+-define(WSP_DEFAULT_VERSION, ?WSP_12).
+
+-define(WSP_STATUS_CONTINUE, 100).
+-define(WSP_STATUS_SWITCHING_PROTOCOLS, 101).
+-define(WSP_STATUS_OK, 200).
+-define(WSP_STATUS_CREATED, 201).
+-define(WSP_STATUS_ACCEPTED, 202).
+-define(WSP_STATUS_NON_AUTHORITATIVE_INFORMATION, 203).
+-define(WSP_STATUS_NO_CONTENT, 204).
+-define(WSP_STATUS_RESET_CONTENT, 205).
+-define(WSP_STATUS_PARTIAL_CONTENT, 206).
+-define(WSP_STATUS_MULTIPLE_CHOICES, 300).
+-define(WSP_STATUS_MOVED_PERMANENTLY, 301).
+-define(WSP_STATUS_MOVED_TEMPORARILY, 302).
+-define(WSP_STATUS_SEE_OTHER, 303).
+-define(WSP_STATUS_NOT_MODIFIED, 304).
+-define(WSP_STATUS_USE_PROXY, 305).
+-define(WSP_STATUS_RESERVED, 306).
+-define(WSP_STATUS_TEMPORARY_REDIRECT, 307).
+-define(WSP_STATUS_BAD_REQUEST, 400).
+-define(WSP_STATUS_UNAUTHORIZED, 401).
+-define(WSP_STATUS_PAYMENT_REQUIRED, 402).
+-define(WSP_STATUS_FORBIDDEN, 403).
+-define(WSP_STATUS_NOT_FOUND, 404).
+-define(WSP_STATUS_METHOD_NOT_ALLOWED, 405).
+-define(WSP_STATUS_NOT_ACCEPTABLE, 406).
+-define(WSP_STATUS_PROXY_AUTHENTICATION_REQUIRED, 407).
+-define(WSP_STATUS_REQUEST_TIMEOUT, 408).
+-define(WSP_STATUS_CONFLICT, 409).
+-define(WSP_STATUS_GONE, 410).
+-define(WSP_STATUS_LENGTH_REQUIRED, 411).
+-define(WSP_STATUS_PRECONDITION_FAILED, 412).
+-define(WSP_STATUS_REQUEST_ENTITY_TOO_LARGE, 413).
+-define(WSP_STATUS_REQUEST_URI_TOO_LARGE, 414).
+-define(WSP_STATUS_UNSUPPORTED_MEDIA_TYPE, 415).
+-define(WSP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE, 416).
+-define(WSP_STATUS_EXPECTATION_FAILED, 417).
+-define(WSP_STATUS_INTERNAL_SERVER_ERROR, 500).
+-define(WSP_STATUS_NOT_IMPLEMENTED, 501).
+-define(WSP_STATUS_BAD_GATEWAY, 502).
+-define(WSP_STATUS_SERVICE_UNAVAILABLE, 503).
+-define(WSP_STATUS_GATEWAY_TIMEOUT, 504).
+-define(WSP_STATUS_HTTP_VERSION_NOT_SUPPORTED, 505).
+
+-define(ENCODE_SHORT(X), <<1:1, (X):7>>).
+
+-define(ENCODE_LONG(X),
+ if (X) =< 16#ff -> <<1, (X):8>>;
+ (X) =< 16#ffff -> <<2, (X):16>>;
+ (X) =< 16#ffffff -> <<3, (X):24>>;
+ (X) =< 16#ffffffff -> <<4, (X):32>>;
+ true -> encode_long1(X)
+ end).
+
+
+-record(wsp_session,
+ {
+ id, %% uniq session id
+ ref, %% address quadruple (socketpair)
+ state=null, %% connected, suspended
+ version, %% encoding version to use
+ capabilities, %% client capabilities
+ headers %% client hop-by-hop headers!!!
+ }).
+
+-record(wsp_header,
+ {
+ name, %% field name
+ value, %% field value (binary value)
+ params=[] %% field params [{Name,Value} | Value]
+ }).
+
+-record(wsp_multipart_entry,
+ {
+ content_type, %% #wsp_header
+ headers=[],
+ data=(<<>>)
+ }).
+
+-record(wsp_capabilities,
+ {
+ aliases=[], %% [#wdp_address]
+ client_sdu_size=1400,
+ extended_methods=[], %% [{PduType, Name}]
+ header_code_pages=[], %% [{Page,Name}] | [Page]
+ protocol_options=[], %% [push,confirmed_push,resume,
+ %% acknowledgement_headers]
+ method_mor = 10, %% 1?
+ push_mor = 10, %% 1?
+ server_sdu_size=1400,
+ client_message_size,
+ server_message_size,
+ unknown=[]
+ }).
+
+%% WSP PDU records
+
+-record(wsp_connect,
+ {
+ version, %% protocol version, not wsp version?
+ capabilities,
+ headers
+ }).
+
+-record(wsp_connect_reply,
+ {
+ server_session_id,
+ capabilities,
+ headers=[]
+ }).
+
+-define(WSP_PERMANENT_REDIRECT, 16#80).
+-define(WSP_REUSE_SECURITY, 16#40).
+
+-record(wsp_redirect,
+ {
+ flags=[],
+ addresses=[]
+ }).
+
+-record(wsp_disconnect,
+ {
+ server_session_id
+ }).
+
+-record(wsp_get,
+ {
+ type,
+ uri,
+ headers=[]
+ }).
+
+-record(wsp_post,
+ {
+ type,
+ uri,
+ content_type, %% #wsp_header
+ headers=[],
+ data
+ }).
+
+-record(wsp_reply,
+ {
+ status,
+ content_type, %% #wsp_header
+ headers=[],
+ data
+ }).
+
+-record(wsp_data_fragment_pdu,
+ {
+ headers=[],
+ data
+ }).
+
+-record(wsp_push,
+ {
+ type = push,
+ content_type, %% #wsp_header
+ headers=[],
+ data
+ }).
+
+-record(wsp_suspend,
+ {
+ session_id
+ }).
+
+-record(wsp_resume,
+ {
+ session_id,
+ capabilities,
+ headers
+ }).
+
+%% NOTE: not a real pdu
+-record(wsp_acknowledgement_headers,
+ {
+ headers=[]
+ }).
+
+-record(wsp_unknown_pdu,
+ {
+ type, %% integer
+ data %% the payload
+ }).
diff --git a/lib/dialyzer/test/user_SUITE_data/src/wsp_pdu.erl b/lib/dialyzer/test/user_SUITE_data/src/wsp_pdu.erl
new file mode 100644
index 0000000000..e5b387478f
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/wsp_pdu.erl
@@ -0,0 +1,5423 @@
+%%%=======================================================================
+%%% File : wsp_pdu.erl
+%%% Author : Tony Rogvall <[email protected]>
+%%% Description : WSP PDU
+%%% Created : 18 Aug 2003 by <[email protected]>
+%%%=======================================================================
+%%%
+%%% There are a couple of bugs in this file. Some are detected by
+%%% Dialyzer v1.1 starting both from byte code and from source, some
+%%% other ones are detected only starting from sourse, while some
+%%% others go unnoticed (these are identified by "BUG" below). It is
+%%% expected that at least some of them are detected when the new type
+%%% analysis is integrated into Dialyzer. Some other ones, like the
+%%% one with the unused _Acc argument are harder to detect and might
+%%% require different techniques.
+%%%
+%%%=======================================================================
+
+-module(wsp_pdu).
+-export([encode/1, encode/2, decode/1, decode/2]).
+
+%% The following is just to suppress unused function warnings
+-export([decode_address/1, decode_header/2,
+ decode_headers/1, decode_mms_version/1, decode_multipart/1,
+ encode_headers/1, encode_mms_version/1, encode_multipart/1,
+ encode_language/1, encode_short_integer/1,
+ fmt_current_date/0,
+ format_header/1, format_headers/1,
+ parse_header/1, format/1]).
+
+-include("wsp.hrl").
+-include("wdp.hrl").
+
+-ifdef(debug).
+-define(dbg(Fmt,Args), io:format(Fmt, Args)).
+-else.
+-define(dbg(Fmt,Args), ok).
+-endif.
+
+-define(WARN(Cond, Message),
+ if (Cond) ->
+ io:format("Warning: ~s\n", [(Message)]);
+ true ->
+ ok
+ end).
+
+
+format(Pdu) ->
+ if record(Pdu, wsp_connect) ->
+ fmt(Pdu, record_info(fields, wsp_connect));
+ record(Pdu, wsp_connect_reply) ->
+ fmt(Pdu, record_info(fields, wsp_connect_reply));
+ record(Pdu, wsp_redirect) ->
+ fmt(Pdu, record_info(fields, wsp_redirect));
+ record(Pdu, wsp_disconnect) ->
+ fmt(Pdu, record_info(fields, wsp_disconnect));
+ record(Pdu, wsp_get) ->
+ fmt(Pdu, record_info(fields, wsp_get));
+ record(Pdu, wsp_post) ->
+ fmt(Pdu, record_info(fields, wsp_post));
+ record(Pdu,wsp_reply) ->
+ fmt(Pdu, record_info(fields, wsp_reply));
+ record(Pdu,wsp_data_fragment_pdu) ->
+ fmt(Pdu, record_info(fields, wsp_data_fragment_pdu));
+ record(Pdu,wsp_push) ->
+ fmt(Pdu, record_info(fields, wsp_push));
+ record(Pdu, wsp_suspend) ->
+ fmt(Pdu, record_info(fields, wsp_suspend));
+ record(Pdu, wsp_resume) ->
+ fmt(Pdu, record_info(fields, wsp_resume));
+ record(Pdu, wsp_unknown_pdu) ->
+ fmt(Pdu, record_info(fields, wsp_unknown_pdu))
+ end.
+
+fmt(Pdu, Fs) ->
+ [Name | Vs] = tuple_to_list(Pdu),
+ lists:flatten(["\n",atom_to_list(Name)," {\n" , fmt1(Fs, Vs), "\n}"]).
+
+fmt1([F|Fs],[V|Vs]) ->
+ [io_lib:format(" ~s: ~s;\n", [F,fmt_value(V)]) | fmt1(Fs, Vs)];
+fmt1([], []) ->
+ "".
+
+fmt_value(V) when binary(V) -> "#Bin";
+fmt_value(V) -> lists:flatten(io_lib:format("~p",[V])).
+
+
+%%
+%% Wsp pdu encoder
+%%
+encode(Pdu) ->
+ encode(Pdu, ?WSP_DEFAULT_VERSION).
+
+encode(Pdu, Version) ->
+ ?dbg("encode pdu using encoding version ~p\n", [Version]),
+ Enc = encode1(Pdu, Version),
+ ?dbg("pdu: ~p\nreversed pdu: ~p\n",
+ [Pdu, decode(Enc, Version)]),
+ Enc.
+
+
+encode1(Pdu, Version) ->
+ case Pdu of
+ #wsp_connect_reply {server_session_id=ServerSessionId,
+ capabilities=Capabilities,
+ headers=Headers} ->
+ EncServerSessionId = e_uintvar(ServerSessionId),
+ EncCapabilities = encode_capabilities(Capabilities),
+ EncCapabilitiesLength = e_uintvar(size(EncCapabilities)),
+ EncHeaders = encode_headers(Headers,Version),
+ EncHeadersLength = e_uintvar(size(EncHeaders)),
+ <<?WSP_ConnectReply,
+ EncServerSessionId/binary,
+ EncCapabilitiesLength/binary, EncHeadersLength/binary,
+ EncCapabilities/binary, EncHeaders/binary>>;
+
+ #wsp_reply{ status=Status,
+ content_type=ContentType,
+ headers=Headers,
+ data=Data} ->
+ EncStatus = encode_status_code(Status),
+ EncContentType = encode_content_type(ContentType,Version),
+ EncHeaders = encode_headers(Headers,Version),
+ EncHeadersLength = e_uintvar(size(EncContentType)+
+ size(EncHeaders)),
+ <<?WSP_Reply,
+ EncStatus:8,
+ EncHeadersLength/binary,
+ EncContentType/binary,
+ EncHeaders/binary,
+ Data/binary>>;
+
+ #wsp_post{type=Type, uri=URI, content_type=ContentType,
+ headers=Headers, data=Data} ->
+ %% WSP_Post, WSP_Put
+ PDUType = encode_pdu_type(Type),
+ UriLength = e_uintvar(length(URI)),
+ EncContentType = encode_content_type(ContentType,Version),
+ EncHeaders = encode_headers(Headers,Version),
+ EncHeadersLength = e_uintvar(size(EncContentType)+
+ size(EncHeaders)),
+ %% FIXME
+ <<PDUType:8,
+ UriLength/binary,
+ EncHeadersLength/binary,
+ (list_to_binary(URI))/binary,
+ EncContentType/binary,
+ EncHeaders/binary,
+ Data/binary>>;
+
+ #wsp_push{type=Type, content_type=ContentType,
+ headers=Headers, data=Data} ->
+ %% WSP_Push, WSP_ConfirmedPush
+ PDUType = encode_pdu_type(Type),
+ EncContentType = encode_content_type(ContentType,Version),
+ EncHeaders = encode_headers(Headers,Version),
+ ?dbg("Version ~p Headers ~p", [Version, Headers]),
+ ?dbg("EncHeaders ~p", [EncHeaders]),
+ EncHeadersLength = e_uintvar(size(EncContentType)+
+ size(EncHeaders)),
+ ?dbg("EncCT = ~w ~w", [ContentType, EncContentType]),
+ ?dbg("EncHL = ~w", [EncHeadersLength]),
+ <<PDUType:8,
+ EncHeadersLength/binary,
+ EncContentType/binary,
+ EncHeaders/binary,
+ Data/binary>>;
+
+ #wsp_get{type=Type, uri=URI, headers=Headers} ->
+ %% WSP_Get, WSP_Options, WSP_Head, WSP_Delete, WSP_Trace
+ PDUType = encode_pdu_type(Type),
+ UriLength = length(URI),
+ EncHeaders = encode_headers(Headers,Version),
+ <<PDUType:8,
+ (e_uintvar(UriLength))/binary,
+ (list_to_binary(URI))/binary,
+ EncHeaders/binary>>;
+
+ #wsp_redirect { flags = Flags, addresses = Addrs } ->
+ Flg = lists:foldl(fun(permanent,F) ->
+ ?WSP_PERMANENT_REDIRECT bor F;
+ (resue, F) ->
+ ?WSP_REUSE_SECURITY bor F
+ end, 0, Flags),
+ EncAddr = encode_addresses(Addrs),
+ <<?WSP_Redirect, Flg:8, EncAddr/binary >>;
+
+
+ #wsp_data_fragment_pdu { headers=Headers, data=Data } ->
+ EncHeaders = encode_headers(Headers,Version),
+ << ?WSP_DataFragmentPDU, EncHeaders/binary, Data/binary >>
+ end.
+
+decode(Data) ->
+ decode(Data, ?WSP_COMPLIENT_VERSION).
+
+decode(Data0, Version) ->
+ case Data0 of
+ <<?WSP_Connect:8,PduVersion:8,D0/binary>> ->
+ %% 8.2.2.1
+ {CapabilitiesLen,D1} = d_uintvar(D0),
+ {HeadersLen,D2} = d_uintvar(D1),
+ {Capabilities,D3} = split_binary(D2, CapabilitiesLen),
+ Caps = decode_capabilities(Capabilities,#wsp_capabilities{}),
+ {Headers,D4} = split_binary(D3, HeadersLen),
+ DecHeaders = decode_headers(Headers, Version),
+ ?WARN(D4 =/= <<>>, "Connect pdu contains trailing data"),
+ %% FIXME: warn when D4 is not <<>>
+ #wsp_connect{ version = PduVersion,
+ capabilities=Caps,
+ headers = DecHeaders };
+
+ <<?WSP_ConnectReply:8,D0/binary>> ->
+ %% 8.2.2.2
+ {ServerSessionId,D1} = d_uintvar(D0),
+ {CapabilitiesLen,D2} = d_uintvar(D1),
+ {HeadersLen,D3} = d_uintvar(D2),
+ {Capabilities,D4} = split_binary(D3, CapabilitiesLen),
+ Caps = decode_capabilities(Capabilities,#wsp_capabilities{}),
+ {Headers,D5} = split_binary(D4, HeadersLen),
+ DecHeaders = decode_headers(Headers, Version),
+ ?WARN(D5 =/= <<>>, "ConnectReply pdu contains trailing data"),
+ #wsp_connect_reply{server_session_id=ServerSessionId,
+ capabilities=Caps,
+ headers=DecHeaders};
+
+ <<?WSP_Redirect:8,Flg:8,D0/binary>> ->
+ Flags =
+ if Flg band ?WSP_PERMANENT_REDIRECT =/= 0 -> [permanent];
+ true -> []
+ end ++
+ if Flg band ?WSP_REUSE_SECURITY =/= 0 -> [security];
+ true -> []
+ end,
+ Addrs = decode_addresses(D0),
+ %% 8.2.2.3 Redirect
+ #wsp_redirect{flags=Flags,addresses=Addrs};
+
+
+ <<?WSP_Disconnect:8,D0/binary>> ->
+ %% 8.2.2.4 Disconnect
+ {ServerSessionId,_D1} = d_uintvar(D0),
+ #wsp_disconnect{server_session_id=ServerSessionId};
+
+ <<?WSP_Get:8,D0/binary>> ->
+ {URILength, D1} = d_uintvar(D0),
+ <<UriData:URILength/binary,D2/binary>> = D1,
+ Hs = decode_headers(D2, Version),
+ #wsp_get{type='GET',uri=binary_to_list(UriData),headers=Hs };
+
+ <<?WSP_Options:8,D0/binary>> ->
+ {URILength, D1} = d_uintvar(D0),
+ <<UriData:URILength/binary,D2/binary>> = D1,
+ Hs = decode_headers(D2, Version),
+ #wsp_get{type='OPTIONS',uri=binary_to_list(UriData),headers=Hs };
+
+ <<?WSP_Head:8,D0/binary>> ->
+ {URILength, D1} = d_uintvar(D0),
+ <<UriData:URILength/binary,D2/binary>> = D1,
+ Hs = decode_headers(D2, Version),
+ #wsp_get{type='HEAD',uri=binary_to_list(UriData),headers=Hs };
+
+ <<?WSP_Delete:8,D0/binary>> ->
+ {URILength, D1} = d_uintvar(D0),
+ <<UriData:URILength/binary,D2/binary>> = D1,
+ Hs = decode_headers(D2, Version),
+ #wsp_get{type='DELETE',uri=binary_to_list(UriData),headers=Hs };
+
+ <<?WSP_Trace:8,D0/binary>> ->
+ {URILength, D1} = d_uintvar(D0),
+ <<UriData:URILength/binary,D2/binary>> = D1,
+ Hs = decode_headers(D2, Version),
+ #wsp_get{type='TRACE',uri=binary_to_list(UriData),headers=Hs };
+
+ %% 8.2.3.2 Post
+ <<?WSP_Post:8,D0/binary>> ->
+ {URILen, D1} = d_uintvar(D0),
+ {HL0, D2} = d_uintvar(D1),
+ <<UriData:URILen/binary,D3/binary>> = D2,
+ {FieldData,D4} = scan_header_data(D3),
+ HL1 = (HL0-(size(D3)-size(D4))),
+ <<D5:HL1/binary,Data/binary>> = D4,
+ ContentType = decode_content_type(FieldData, Version),
+ Headers = decode_headers(D5, Version),
+ #wsp_post{ type='POST', uri=binary_to_list(UriData),
+ content_type=ContentType, headers=Headers, data=Data};
+
+ <<?WSP_Put:8,D0/binary>> ->
+ {URILen, D1} = d_uintvar(D0),
+ {HL0, D2} = d_uintvar(D1),
+ <<UriData:URILen/binary,D3/binary>> = D2,
+ {FieldData,D4} = scan_header_data(D3),
+ HL1 = (HL0-(size(D3)-size(D4))),
+ <<D5:HL1/binary,Data/binary>> = D4,
+ ContentType = decode_content_type(FieldData, Version),
+ Headers = decode_headers(D5, Version),
+ #wsp_post{ type='PUT', uri=binary_to_list(UriData),
+ content_type=ContentType, headers=Headers, data=Data};
+
+ <<?WSP_Reply:8,StatusCode:8,D0/binary>> ->
+ %% 8.2.3.3 Reply
+ Status = decode_status_code(StatusCode),
+ {HL0, D1} = d_uintvar(D0),
+ {FieldData, D2} = scan_header_data(D1),
+ ContentType = decode_content_type(FieldData, Version),
+ %% Headers are headersLength - binary size of content type
+ HL1 = (HL0-(size(D1)-size(D2))),
+ <<D3:HL1/binary,Data/binary>> = D2,
+ Hs = decode_headers(D3, Version),
+ #wsp_reply{status=Status, content_type=ContentType,
+ headers=Hs, data=Data};
+
+ <<?WSP_DataFragmentPDU:8,D0/binary>> ->
+ %% 8.2.3.4 Data Fragment PDU
+ {HL0, D1} = d_uintvar(D0),
+ <<D2:HL0/binary,Data/binary>> = D1,
+ Hs = decode_headers(D2, Version),
+ #wsp_data_fragment_pdu{headers=Hs, data=Data};
+
+ %% 8.2.4.1 Push or ConfirmedPush
+ <<?WSP_Push:8,D0/binary>> ->
+ {HeadersLength, T200} = d_uintvar(D0),
+ {FieldData, T300} = scan_header_data(T200),
+ ContentType = decode_content_type(FieldData, Version),
+ RealHeadersLength = (HeadersLength-(size(T200)-size(T300))),
+ <<T400:RealHeadersLength/binary,Data/binary>> = T300,
+ Headers = decode_headers(T400, Version),
+ #wsp_push{type=push,content_type=ContentType,
+ headers=Headers,data=Data};
+
+ <<?WSP_ConfirmedPush:8,D0/binary>> ->
+ {HeadersLength, T200} = d_uintvar(D0),
+ {FieldData, T300} = scan_header_data(T200),
+ ContentType = decode_content_type(FieldData, Version),
+ RealHeadersLength = (HeadersLength-(size(T200)-size(T300))),
+ <<T400:RealHeadersLength/binary,Data/binary>> = T300,
+ Headers = decode_headers(T400, Version),
+ #wsp_push{type=confirmed_push,
+ content_type=ContentType,
+ headers=Headers,data=Data};
+
+ <<PDUType:8,T100/binary>> ->
+ #wsp_unknown_pdu { type = PDUType, data = T100 }
+ end.
+
+
+encode_pdu_type(connect) -> ?WSP_Connect;
+encode_pdu_type(connect_reply) -> ?WSP_ConnectReply;
+encode_pdu_type(redirect) -> ?WSP_Redirect;
+encode_pdu_type(reply) -> ?WSP_Reply;
+encode_pdu_type(disconnect) -> ?WSP_Disconnect;
+encode_pdu_type(push) -> ?WSP_Push;
+encode_pdu_type(confirmed_push) -> ?WSP_ConfirmedPush;
+encode_pdu_type(suspend) -> ?WSP_Suspend;
+encode_pdu_type(resume) -> ?WSP_Resume;
+encode_pdu_type(data_fragment_pdu) -> ?WSP_DataFragmentPDU;
+encode_pdu_type('GET') -> ?WSP_Get;
+encode_pdu_type('OPTIONS') -> ?WSP_Options;
+encode_pdu_type('HEAD') -> ?WSP_Head;
+encode_pdu_type('DELETE') -> ?WSP_Delete;
+encode_pdu_type('TRACE') -> ?WSP_Trace;
+encode_pdu_type('POST') -> ?WSP_Post;
+encode_pdu_type('PUT') -> ?WSP_Put;
+encode_pdu_type(Type) when integer(Type) -> Type.
+
+
+decode_pdu_type(?WSP_Connect) -> connect;
+decode_pdu_type(?WSP_ConnectReply) -> connect_reply;
+decode_pdu_type(?WSP_Redirect) -> redirect;
+decode_pdu_type(?WSP_Reply) -> reply;
+decode_pdu_type(?WSP_Disconnect) -> disconnect;
+decode_pdu_type(?WSP_Push) -> push;
+decode_pdu_type(?WSP_ConfirmedPush) -> confirmed_push;
+decode_pdu_type(?WSP_Suspend) -> suspend;
+decode_pdu_type(?WSP_Resume) -> resume;
+decode_pdu_type(?WSP_DataFragmentPDU) -> data_fragment_pdu;
+decode_pdu_type(?WSP_Get) -> 'GET';
+decode_pdu_type(?WSP_Options) -> 'OPTIONS';
+decode_pdu_type(?WSP_Head) -> 'HEAD';
+decode_pdu_type(?WSP_Delete) -> 'DELETE';
+decode_pdu_type(?WSP_Trace) -> 'TRACE';
+decode_pdu_type(?WSP_Post) -> 'POST';
+decode_pdu_type(?WSP_Put) -> 'PUT';
+decode_pdu_type(Type) -> Type. %% allow unknown pdu types.
+
+
+%% Convert various data types to list
+
+to_list(I) when integer(I) ->
+ integer_to_list(I);
+to_list(A) when atom(A) ->
+ atom_to_list(A);
+to_list(Version={X,Y}) when integer(X), integer(Y) ->
+ format_version(Version);
+to_list(DateTime={{_,_,_},{_,_,_}}) ->
+ fmt_date(DateTime);
+to_list(L) when list(L) ->
+ L.
+
+
+
+encode_capabilities(Capa) ->
+ encode_capabilities(Capa,#wsp_capabilities{}).
+
+encode_capabilities(Cap,Def) ->
+ Known =
+ [encode_capability(?WSP_CAP_ALIASES,
+ Cap#wsp_capabilities.aliases,
+ Def#wsp_capabilities.aliases),
+ encode_capability(?WSP_CAP_CLIENT_SDU_SIZE,
+ Cap#wsp_capabilities.client_sdu_size,
+ Def#wsp_capabilities.client_sdu_size),
+ encode_capability(?WSP_CAP_SERVER_SDU_SIZE,
+ Cap#wsp_capabilities.server_sdu_size,
+ Def#wsp_capabilities.server_sdu_size),
+ encode_capability(?WSP_CAP_PROTOCOL_OPTIONS,
+ Cap#wsp_capabilities.protocol_options,
+ Def#wsp_capabilities.protocol_options),
+ encode_capability(?WSP_CAP_METHOD_MOR,
+ Cap#wsp_capabilities.method_mor,
+ Def#wsp_capabilities.method_mor),
+ encode_capability(?WSP_CAP_PUSH_MOR,
+ Cap#wsp_capabilities.push_mor,
+ Def#wsp_capabilities.push_mor),
+ encode_capability(?WSP_CAP_EXTENDED_METHODS,
+ Cap#wsp_capabilities.extended_methods,
+ Def#wsp_capabilities.extended_methods),
+ encode_capability(?WSP_CAP_HEADER_CODE_PAGES,
+ Cap#wsp_capabilities.header_code_pages,
+ Def#wsp_capabilities.header_code_pages),
+ encode_capability(?WSP_CAP_CLIENT_MESSAGE_SIZE,
+ Cap#wsp_capabilities.client_message_size,
+ Def#wsp_capabilities.client_message_size),
+ encode_capability(?WSP_CAP_SERVER_MESSAGE_SIZE,
+ Cap#wsp_capabilities.server_message_size,
+ Def#wsp_capabilities.server_message_size)],
+ Unknown =
+ lists:map(fun({Id, Data}) when integer(Id) ->
+ <<1:1, Id:7, Data/binary>>;
+ ({Id,Data}) ->
+ <<(encode_text_string(Id))/binary, Data/binary>>
+ end, Cap#wsp_capabilities.unknown),
+ list_to_binary(
+ lists:map(fun(<<>>) -> [];
+ (Bin) ->
+ [e_uintvar(size(Bin)), Bin]
+ end, Known ++ Unknown)).
+
+
+
+
+encode_capability(_Capa, Default, Default) ->
+ <<>>;
+encode_capability(Capa, Value, _) ->
+ case Capa of
+ ?WSP_CAP_ALIASES ->
+ <<1:1, ?WSP_CAP_ALIASES:7, (encode_addresses(Value))/binary>>;
+
+ ?WSP_CAP_CLIENT_SDU_SIZE ->
+ <<1:1, ?WSP_CAP_CLIENT_SDU_SIZE:7, (e_uintvar(Value))/binary>>;
+
+ ?WSP_CAP_SERVER_SDU_SIZE ->
+ <<1:1, ?WSP_CAP_SERVER_SDU_SIZE:7, (e_uintvar(Value))/binary>>;
+
+ ?WSP_CAP_PROTOCOL_OPTIONS ->
+ Opts = case lists:member(confirmed_push, Value) of
+ true -> 16#80;
+ false -> 0
+ end bor
+ case lists:member(push, Value) of
+ true -> 16#40;
+ false -> 0
+ end bor
+ case lists:member(resume, Value) of
+ true -> 16#20;
+ false -> 0
+ end bor
+ case lists:member(acknowledgement_headers, Value) of
+ true -> 16#10;
+ false -> 0
+ end,
+ %% FIXME: symbolic encode/decode of options
+ <<1:1, ?WSP_CAP_PROTOCOL_OPTIONS:7, Opts>>;
+
+ ?WSP_CAP_METHOD_MOR ->
+ <<1:1, ?WSP_CAP_METHOD_MOR:7, (e_uintvar(Value))/binary>>;
+
+ ?WSP_CAP_PUSH_MOR ->
+ <<1:1, ?WSP_CAP_PUSH_MOR:7, (e_uintvar(Value))/binary>>;
+
+ ?WSP_CAP_EXTENDED_METHODS ->
+ <<1:1, ?WSP_CAP_EXTENDED_METHODS:7,
+ (encode_extended_methods(Value))/binary>>;
+
+ ?WSP_CAP_HEADER_CODE_PAGES ->
+ Data = list_to_binary(
+ lists:map(fun(Page) when integer(Page) -> Page;
+ ({Page,Name}) ->
+ [Page, encode_text_string(Name)]
+ end, Value)),
+ <<1:1, ?WSP_CAP_HEADER_CODE_PAGES:7, Data/binary>>;
+
+ ?WSP_CAP_CLIENT_MESSAGE_SIZE ->
+ <<1:1, ?WSP_CAP_CLIENT_MESSAGE_SIZE:7,
+ (e_uintvar(Value))/binary>>;
+
+ ?WSP_CAP_SERVER_MESSAGE_SIZE ->
+ <<1:1, ?WSP_CAP_SERVER_MESSAGE_SIZE:7,
+ (e_uintvar(Value))/binary>>;
+ _ when integer(Capa) ->
+ <<1:1, Capa:7, Value/binary>>;
+ _ when list(Capa) ->
+ <<(encode_text_string(Capa))/binary, Value/binary>>
+ end.
+
+
+decode_capabilities(<<>>, WspCaps) ->
+ WspCaps;
+decode_capabilities(D0,WspCaps) ->
+ {Len, D1} = d_uintvar(D0),
+ <<Capa:Len/binary, D2/binary>> = D1,
+ WspCaps1 =
+ case Capa of
+ <<1:1, Id:7, Data/binary>> ->
+ decode_capa(Id, Data, WspCaps);
+ _ ->
+ {Id,Data} = d_text_string(Capa),
+ decode_capa(Id, Data, WspCaps)
+ end,
+ decode_capabilities(D2, WspCaps1).
+
+
+
+decode_capa(Id,Data, WspCaps) ->
+ case Id of
+ ?WSP_CAP_SERVER_SDU_SIZE ->
+ {Val,_} = d_uintvar(Data),
+ WspCaps#wsp_capabilities{server_sdu_size=Val};
+
+ ?WSP_CAP_CLIENT_SDU_SIZE ->
+ {Val,_} = d_uintvar(Data),
+ WspCaps#wsp_capabilities{client_sdu_size=Val};
+
+ ?WSP_CAP_PROTOCOL_OPTIONS ->
+ <<POP,_/binary>> = Data,
+ Opts =
+ if POP band 16#80 == 16#80 -> [confirmed_push];
+ true -> []
+ end ++
+ if POP band 16#40 == 16#40 -> [push];
+ true -> []
+ end ++
+ if POP band 16#20 == 16#20 -> [resume];
+ true -> []
+ end ++
+ if POP band 16#10 == 16#10 -> [acknowledgement_headers];
+ true -> []
+ end,
+ WspCaps#wsp_capabilities{protocol_options=Opts};
+
+ ?WSP_CAP_METHOD_MOR ->
+ {Val,_} = d_uintvar(Data),
+ WspCaps#wsp_capabilities{method_mor=Val};
+
+ ?WSP_CAP_PUSH_MOR ->
+ {Val,_} = d_uintvar(Data),
+ WspCaps#wsp_capabilities{push_mor=Val};
+
+ ?WSP_CAP_EXTENDED_METHODS ->
+ Extended = decode_extended_methods(Data),
+ WspCaps#wsp_capabilities { extended_methods = Extended };
+
+ ?WSP_CAP_HEADER_CODE_PAGES ->
+ %% Client send [Code(uint8) Name(text-string)]*
+ %% Server send [Code(uint8)]*
+ io:format("FIXME: Header Code Pages = ~p\n",[Data]),
+ WspCaps;
+
+ ?WSP_CAP_ALIASES ->
+ Aliases = decode_addresses(Data),
+ WspCaps#wsp_capabilities { aliases = Aliases };
+
+ ?WSP_CAP_CLIENT_MESSAGE_SIZE ->
+ {Val,_} = d_uintvar(Data),
+ WspCaps#wsp_capabilities{client_message_size=Val};
+
+ ?WSP_CAP_SERVER_MESSAGE_SIZE ->
+ {Val,_} = d_uintvar(Data),
+ WspCaps#wsp_capabilities{server_message_size=Val};
+ _ ->
+ Unknown = [{Id, Data} | WspCaps#wsp_capabilities.unknown],
+ io:format("WARNING: ignoring unknown capability ~p\n",
+ [Unknown]),
+ WspCaps#wsp_capabilities{unknown = Unknown}
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Headers = [ Header ]
+%% Header = {FieldName, FieldValue}
+%% FieldName = atom()
+%% FieldValue = {Value, Params}
+%% | Value
+%%
+%% Params = [{Param,Value} | Param]
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-define(WH(Name,Value,Params),
+ #wsp_header { name = (Name), value = (Value), params = Params}).
+
+encode_headers(Headers) ->
+ encode_headers(Headers, ?WSP_DEFAULT_VERSION).
+
+encode_headers(Headers, Version) ->
+ encode_headers(Headers, Version, []).
+
+encode_headers([H|T], Version, Acc) ->
+ encode_headers(T, Version, [encode_header(H, Version)|Acc]);
+encode_headers([], _, Acc) ->
+ list_to_binary(lists:reverse(Acc)).
+
+
+decode_headers(Bin) ->
+ decode_headers(Bin, ?WSP_DEFAULT_VERSION).
+
+decode_headers(<<>>, _Version) ->
+ [];
+decode_headers(Data, Version) ->
+ decode_headers(Data, [], Version, ?WSP_DEFAULT_CODEPAGE).
+
+
+decode_headers(<<1:1,Code:7,Data/binary>>,Acc,Version,CP) ->
+ FieldName = lookup_field_name(Code),
+ {FieldData,Data1} = scan_header_data(Data),
+ H = decode_header(FieldName, FieldData,Version,CP),
+ ?dbg("header: ~p, field data=~p, header=~p\n",
+ [FieldName, FieldData, H]),
+ if H#wsp_header.name == 'Encoding-Version' ->
+ Version1 = H#wsp_header.value,
+ ?dbg("Version switch from ~w to ~w\n", [Version, Version1]),
+ decode_headers(Data1,[H|Acc],Version1, CP);
+ true ->
+ decode_headers(Data1,[H|Acc],Version, CP)
+ end;
+decode_headers(Data = <<Code,_/binary>>,Acc,Version,CP)
+ when Code >= 32, Code < 127->
+ {TmpField,Data1} = d_text_string(Data),
+ FieldName = normalise_field_name(TmpField),
+ {FieldData,Data2} = scan_header_data(Data1),
+ H = decode_header(FieldName,FieldData,Version,CP),
+ ?dbg("header: ~p, field data=~p, header=~p\n",
+ [FieldName, FieldData, H]),
+ if H#wsp_header.name == 'Encoding-Version' ->
+ Version1 = H#wsp_header.value,
+ ?dbg("Version switch from ~w to ~w\n", [Version, Version1]),
+ decode_headers(Data2,[H|Acc],Version1, CP);
+ true ->
+ decode_headers(Data2,[H|Acc],Version, CP)
+ end;
+decode_headers(<<CP1,Data/binary>>,Acc,Version,_CP) when CP1 >= 1, CP1 =< 31 ->
+ ?dbg("decode_headers: codpage changed form ~w -> ~w\n",[_CP,CP1]),
+ decode_headers(Data,Acc,Version,CP1);
+decode_headers(<<16#7f,CP1,Data/binary>>,Acc,Version,_CP) ->
+ ?dbg("decode_headers: codpage changed form ~w -> ~w\n",[_CP,CP1]),
+ decode_headers(Data,Acc,Version,CP1);
+
+decode_headers(<<>>, Acc, _Version, _CP) ->
+ lists:reverse(Acc).
+
+%%
+%% Retrive the header data
+%% (this makes it possible to skip unknown encoding)
+%%
+scan_header_data(Data = <<N,Data0/binary>>) ->
+ if N >= 0, N =< 30 ->
+ <<Value:N/binary, Data1/binary>> = Data0,
+ {{short,Value}, Data1};
+ N == 31 ->
+ {N1, Data1} = d_uintvar(Data0),
+ <<Value:N1/binary, Data2/binary>> = Data1,
+ {{long,Value}, Data2};
+ N >= 32, N =< 127 ->
+ d_text_string(Data);
+ true ->
+ { N band 16#7f, Data0}
+ end.
+
+%%
+%% Decode header: return #wsp_header
+%%
+decode_header(Field, Value) ->
+ decode_header(Field, Value,
+ ?WSP_DEFAULT_VERSION,
+ ?WSP_DEFAULT_CODEPAGE).
+
+decode_header(Field, Value, Version, 1) ->
+ case Field of
+ 'Accept' ->
+ decode_accept(Value, Version);
+
+ 'Accept-Charset' when Version >= ?WSP_13 ->
+ decode_accept_charset(Value, Version);
+ 'Accept-Charset' ->
+ decode_accept_charset(Value, Version);
+
+ 'Accept-Encoding' when Version >= ?WSP_13 ->
+ decode_accept_encoding(Value, Version);
+ 'Accept-Encoding' ->
+ decode_accept_encoding(Value, Version);
+
+ 'Accept-Language' ->
+ decode_accept_language(Value, Version);
+ 'Accept-Ranges' ->
+ decode_accept_ranges(Value, Version);
+ 'Age' ->
+ decode_age(Value,Version);
+ 'Allow' ->
+ decode_allow(Value,Version);
+ 'Authorization' ->
+ decode_authorization(Value,Version);
+
+ 'Cache-Control' when Version >= ?WSP_14 ->
+ decode_cache_control(Value,Version);
+ 'Cache-Control' when Version >= ?WSP_13 ->
+ decode_cache_control(Value,Version);
+ 'Cache-Control' ->
+ decode_cache_control(Value,Version);
+
+ 'Connection' ->
+ decode_connection(Value,Version);
+ 'Content-Base' ->
+ decode_content_base(Value,Version);
+ 'Content-Encoding' ->
+ decode_content_encoding(Value,Version);
+ 'Content-Language' ->
+ decode_content_language(Value,Version);
+ 'Content-Length' ->
+ decode_content_length(Value,Version);
+ 'Content-Location' ->
+ decode_content_location(Value,Version);
+ 'Content-Md5' ->
+ decode_content_md5(Value,Version);
+
+ 'Content-Range' when Version >= ?WSP_13 ->
+ decode_content_range(Value,Version);
+ 'Content-Range' ->
+ decode_content_range(Value,Version);
+
+ 'Content-Type' ->
+ decode_content_type(Value,Version);
+ 'Date' ->
+ decode_date(Value, Version);
+ 'Etag' ->
+ decode_etag(Value,Version);
+ 'Expires' ->
+ decode_expires(Value,Version);
+ 'From' ->
+ decode_from(Value,Version);
+ 'Host' ->
+ decode_host(Value,Version);
+ 'If-Modified-Since' ->
+ decode_if_modified_since(Value,Version);
+ 'If-Match' ->
+ decode_if_match(Value,Version);
+ 'If-None-Match' ->
+ decode_if_none_match(Value,Version);
+ 'If-Range' ->
+ decode_if_range(Value,Version);
+ 'If-Unmodified-Since' ->
+ decode_if_unmodified_since(Value,Version);
+ 'Location' ->
+ decode_location(Value,Version);
+ 'Last-Modified' ->
+ decode_last_modified(Value,Version);
+ 'Max-Forwards' ->
+ decode_max_forwards(Value,Version);
+ 'Pragma' ->
+ decode_pragma(Value,Version);
+ 'Proxy-Authenticate' ->
+ decode_proxy_authenticate(Value,Version);
+ 'Proxy-Authorization' ->
+ decode_proxy_authorization(Value,Version);
+ 'Public' ->
+ decode_public(Value,Version);
+ 'Range' ->
+ decode_range(Value,Version);
+ 'Referer' ->
+ decode_referer(Value,Version);
+ 'Retry-After' ->
+ decode_retry_after(Value,Version);
+ 'Server' ->
+ decode_server(Value,Version);
+ 'Transfer-Encoding' ->
+ decode_transfer_encoding(Value,Version);
+ 'Upgrade' ->
+ decode_upgrade(Value,Version);
+ 'User-Agent' ->
+ decode_user_agent(Value,Version);
+ 'Vary' ->
+ decode_vary(Value,Version);
+ 'Via' ->
+ decode_via(Value,Version);
+ 'Warning' ->
+ decode_warning(Value,Version);
+ 'Www-Authenticate' ->
+ decode_www_authenticate(Value,Version);
+
+ 'Content-Disposition' when Version >= ?WSP_14 ->
+ decode_content_disposition(Value,Version);
+ 'Content-Disposition' ->
+ decode_content_disposition(Value,Version);
+
+ 'X-Wap-Application-Id' when Version >= ?WSP_12 ->
+ decode_x_wap_application_id(Value,Version);
+
+ 'X-Wap-Content-Uri' when Version >= ?WSP_12 ->
+ decode_x_wap_content_uri(Value,Version);
+
+ 'X-Wap-Initiator-Uri' when Version >= ?WSP_12 ->
+ decode_x_wap_initiator_uri(Value,Version);
+
+ 'Accept-Application' when Version >= ?WSP_12 ->
+ decode_accept_application(Value,Version);
+
+ 'Bearer-Indication' when Version >= ?WSP_12 ->
+ decode_bearer_indication(Value,Version);
+
+ 'Push-Flag' when Version >= ?WSP_12 ->
+ decode_push_flag(Value,Version);
+
+ 'Profile' when Version >= ?WSP_12 ->
+ decode_profile(Value,Version);
+
+ 'Profile-Diff' when Version >= ?WSP_12 ->
+ decode_profile_diff(Value,Version);
+
+ 'Profile-Warning' when Version >= ?WSP_12 ->
+ decode_profile_warning(Value,Version);
+
+ 'Expect' when Version >= ?WSP_15 ->
+ decode_expect(Value,Version);
+ 'Expect' when Version >= ?WSP_13 ->
+ decode_expect(Value,Version);
+
+ 'Te' when Version >= ?WSP_13 ->
+ decode_te(Value,Version);
+ 'Trailer' when Version >= ?WSP_13 ->
+ decode_trailer(Value,Version);
+
+ 'X-Wap-Tod' when Version >= ?WSP_13 ->
+ decode_x_wap_tod(Value,Version);
+ 'X-Wap.tod' when Version >= ?WSP_13 ->
+ decode_x_wap_tod(Value,Version);
+
+ 'Content-Id' when Version >= ?WSP_13 ->
+ decode_content_id(Value,Version);
+ 'Set-Cookie' when Version >= ?WSP_13 ->
+ decode_set_cookie(Value,Version);
+ 'Cookie' when Version >= ?WSP_13 ->
+ decode_cookie(Value,Version);
+
+ 'Encoding-Version' when Version >= ?WSP_13 ->
+ decode_encoding_version(Value,Version);
+ 'Profile-Warning' when Version >= ?WSP_14 ->
+ decode_profile_warning(Value,Version);
+
+ 'X-Wap-Security' when Version >= ?WSP_14 ->
+ decode_x_wap_security(Value,Version);
+ 'X-Wap-Loc-Invocation' when Version >= ?WSP_15 ->
+ decode_x_wap_loc_invocation(Value,Version); %% ???
+ 'X-Wap-Loc-Delivery' when Version >= ?WSP_15 ->
+ decode_x_wap_loc_delivery(Value,Version); %% ???
+ _ ->
+ ?dbg("Warning: none standard field ~p in version ~p codepage=1\n",
+ [Field, Version]),
+ ?WH(Field, Value, [])
+ end;
+decode_header(Field, Value, _Version, _CP) ->
+ ?dbg("Warning: none standard field ~p in version ~p codepage=~w\n",
+ [Field, _Version, _CP]),
+ ?WH(Field, Value, []).
+
+%%
+%% Encode field and value according to version
+%% FIXME: spilt multiple header values (i.e Via) into multiple
+%% headers
+%%
+encode_header(H, Version) ->
+ case H#wsp_header.name of
+ 'Accept' ->
+ [16#80, encode_accept(H, Version)];
+ 'Accept-Charset' when Version >= ?WSP_13 ->
+ [16#bb, encode_accept_charset(H, Version)];
+ 'Accept-Charset' ->
+ [16#81, encode_accept_charset(H, Version)];
+ 'Accept-Encoding' when Version >= ?WSP_13 ->
+ [16#bc, encode_accept_encoding(H, Version)];
+ 'Accept-Encoding' ->
+ [16#82, encode_accept_encoding(H, Version)];
+ 'Accept-Language' ->
+ [16#83, encode_accept_language(H, Version)];
+ 'Accept-Ranges' ->
+ [16#84, encode_accept_ranges(H, Version)];
+ 'Accept-Application' when Version >= ?WSP_12 ->
+ [16#b2, encode_accept_application(H,Version)];
+ 'Age' ->
+ [16#85, encode_age(H, Version)];
+ 'Allow' ->
+ [16#86, encode_allow(H, Version)];
+ 'Authorization' ->
+ [16#87, encode_authorization(H, Version)];
+ 'Cache-Control' when Version >= ?WSP_14 ->
+ [16#c7, encode_cache_control(H, Version)];
+ 'Cache-Control' when Version >= ?WSP_13 ->
+ [16#bd, encode_cache_control(H, Version)];
+ 'Cache-Control' ->
+ [16#88, encode_cache_control(H, Version)];
+ 'Connection' ->
+ [16#89, encode_connection(H, Version)];
+ 'Content-Base' ->
+ [16#8a, encode_content_base(H, Version)];
+ 'Content-Encoding' ->
+ [16#8b, encode_content_encoding(H, Version)];
+
+ 'Content-Language' ->
+ [16#8c, encode_content_language(H,Version)];
+ 'Content-Length' ->
+ [16#8d, encode_content_length(H,Version)];
+ 'Content-Location' ->
+ [16#8e, encode_content_location(H,Version)];
+ 'Content-Md5' ->
+ [16#8f, encode_content_md5(H,Version)];
+ 'Content-Range' when Version >= ?WSP_13 ->
+ [16#be, encode_content_range(H,Version)];
+ 'Content-Range' ->
+ [16#90, encode_content_range(H,Version)];
+ 'Content-Type' ->
+ [16#91, encode_content_type(H,Version)];
+ 'Date' ->
+ [16#92, encode_date(H,Version)];
+ 'Etag' ->
+ [16#93, encode_etag(H,Version)];
+ 'Expires' ->
+ [16#94, encode_expires(H,Version)];
+ 'From' ->
+ [16#95, encode_from(H,Version)];
+ 'Host' ->
+ [16#96, encode_host(H,Version)];
+ 'If-Modified-Since' ->
+ [16#97, encode_if_modified_since(H,Version)];
+ 'If-Match' ->
+ [16#98, encode_if_match(H,Version)];
+ 'If-None-Match' ->
+ [16#99, encode_if_none_match(H,Version)];
+ 'If-Range' ->
+ [16#9a, encode_if_range(H,Version)];
+ 'If-Unmodified-Since' ->
+ [16#9b, encode_if_unmodified_since(H,Version)];
+ 'Location' ->
+ [16#9c, encode_location(H,Version)];
+ 'Last-Modified' ->
+ [16#9d, encode_last_modified(H,Version)];
+ 'Max-Forwards' ->
+ [16#9e, encode_max_forwards(H,Version)];
+ 'Pragma' ->
+ [16#9f, encode_pragma(H,Version)];
+ 'Proxy-Authenticate' ->
+ [16#a0, encode_proxy_authenticate(H,Version)];
+ 'Proxy-Authorization' ->
+ [16#a1, encode_proxy_authorization(H,Version)];
+ 'Public' ->
+ [16#a2, encode_public(H,Version)];
+ 'Range' ->
+ [16#a3, encode_range(H,Version)];
+ 'Referer' ->
+ [16#a4, encode_referer(H,Version)];
+ 'Retry-After' ->
+ [16#a5, encode_retry_after(H,Version)];
+ 'Server' ->
+ [16#a6, encode_server(H,Version)];
+ 'Transfer-Encoding' ->
+ [16#a7, encode_transfer_encoding(H,Version)];
+ 'Upgrade' ->
+ [16#a8, encode_upgrade(H,Version)];
+ 'User-Agent' ->
+ [16#a9, encode_user_agent(H,Version)];
+ 'Vary' ->
+ [16#aa, encode_vary(H,Version)];
+ 'Via' ->
+ [16#ab, encode_via(H,Version)];
+ 'Warning' ->
+ [16#ac, encode_warning(H,Version)];
+ 'Www-Authenticate' ->
+ [16#ad, encode_www_authenticate(H,Version)];
+
+ 'Content-Disposition' when Version >= ?WSP_14 ->
+ [16#c5, encode_content_disposition(H,Version)];
+ 'Content-Disposition' ->
+ [16#ae, encode_content_disposition(H,Version)];
+
+
+ 'X-Wap-Application-Id' when Version >= ?WSP_12 ->
+ [16#af, encode_x_wap_application_id(H,Version)];
+ 'X-Wap-Content-Uri' when Version >= ?WSP_12 ->
+ [16#b0, encode_x_wap_content_uri(H,Version)];
+ 'X-Wap-Initiator-Uri' when Version >= ?WSP_12 ->
+ [16#b1, encode_x_wap_initiator_uri(H,Version)];
+
+ 'Bearer-Indication' when Version >= ?WSP_12 ->
+ [16#b3, encode_bearer_indication(H,Version)];
+ 'Push-Flag' when Version >= ?WSP_12 ->
+ [16#b4, encode_push_flag(H,Version)];
+
+ 'Profile' when Version >= ?WSP_12 ->
+ [16#b5, encode_profile(H,Version)];
+ 'Profile-Diff' when Version >= ?WSP_12 ->
+ [16#b6, encode_profile_diff(H,Version)];
+ 'Profile-Warning' when Version >= ?WSP_14 ->
+ [16#c4, encode_profile_warning(H,Version)];
+ 'Profile-Warning' when Version >= ?WSP_12 ->
+ [16#b7, encode_profile_warning(H,Version)];
+
+ 'Expect' when Version >= ?WSP_15 ->
+ [16#c8, encode_expect(H,Version)];
+ 'Expect' when Version >= ?WSP_13 ->
+ [16#b8, encode_expect(H,Version)];
+ 'Te' when Version >= ?WSP_13 ->
+ [16#b9, encode_te(H,Version)];
+ 'Trailer' when Version >= ?WSP_13 ->
+ [16#ba, encode_trailer(H,Version)];
+ 'X-Wap-Tod' when Version >= ?WSP_13 ->
+ [16#bf, encode_x_wap_tod(H,Version)];
+ 'Content-Id' when Version >= ?WSP_13 ->
+ [16#c0, encode_content_id(H,Version)];
+ 'Set-Cookie' when Version >= ?WSP_13 ->
+ [16#c1, encode_set_cookie(H,Version)];
+ 'Cookie' when Version >= ?WSP_13 ->
+ [16#c2, encode_cookie(H,Version)];
+ 'Encoding-Version' when Version >= ?WSP_13 ->
+ [16#c3, encode_encoding_version(H,Version)];
+ 'Encoding-Version' when Version < ?WSP_13 ->
+ [encode_text_string("Encoding-Version"),
+ encode_text_string(lists:flatten(format_version(H#wsp_header.value)))];
+
+ 'X-Wap-Security' when Version >= ?WSP_14 ->
+ [16#c6, encode_x_wap_security(H,Version)];
+ 'X-Wap-Loc-Invocation' when Version >= ?WSP_15 ->
+ [16#c9, encode_x_wap_loc_invocation(H,Version)];
+ 'X-Wap-Loc-Delivery' when Version >= ?WSP_15 ->
+ [16#ca, encode_x_wap_loc_delivery(H,Version)];
+ Field when atom(Field) ->
+ [encode_text_string(atom_to_list(Field)),
+ encode_text_string(H#wsp_header.value)];
+ Field when list(Field) ->
+ [encode_text_string(Field),
+ encode_text_string(H#wsp_header.value)]
+ end.
+
+%%
+%% Convert HTTP headers into WSP headers
+%%
+parse_headers([H | Hs]) ->
+ parse_header(H, Hs);
+parse_headers([]) ->
+ [].
+
+parse_header(H) ->
+ parse_header(H, []).
+
+parse_header({FieldName,FieldValue}, Hs) ->
+ case single_comma_field(FieldName) of
+ true ->
+ io:format("parse: ~s: ~s\n", [FieldName, FieldValue]),
+ H = parse_hdr(FieldName,FieldValue),
+ io:format("header: ~p\n", [H]),
+ [H | parse_headers(Hs)];
+ false ->
+ Values = string:tokens(FieldValue, ","),
+ parse_header(FieldName, Values, Hs)
+ end.
+
+parse_header(FieldName, [Value|Vs], Hs) ->
+ io:format("parse: ~s: ~s\n", [FieldName, Value]),
+ H = parse_hdr(FieldName, Value),
+ io:format("header: ~p\n", [H]),
+ [H | parse_header(FieldName, Vs, Hs)];
+parse_header(_FieldName, [], Hs) ->
+ parse_headers(Hs).
+
+
+single_comma_field(Field) ->
+ case Field of
+ 'Set-Cookie' -> true; %% FIXME (Is multiple!)
+ 'Date' -> true;
+ 'Expires' -> true;
+ 'If-Modified-Since' -> true;
+ 'If-Range' -> true;
+ 'If-Unmodified-Since' -> true;
+ 'Last-Modified' -> true;
+ 'Retry-After' -> true;
+ 'X-Wap-Tod' -> true;
+ _ -> false
+ end.
+
+
+parse_hdr(Field, Value0) ->
+ Value = trim(Value0),
+ case Field of
+ 'Accept' -> parse_accept(Value);
+ 'Accept-Charset' -> parse_accept_charset(Value);
+ 'Accept-Encoding' -> parse_accept_encoding(Value);
+ 'Accept-Language' -> parse_accept_language(Value);
+ 'Accept-Ranges' -> parse_accept_ranges(Value);
+ 'Age' -> parse_age(Value);
+ 'Allow' -> parse_allow(Value);
+ 'Authorization' -> parse_authorization(Value);
+ 'Cache-Control' -> parse_cache_control(Value);
+ 'Connection' -> parse_connection(Value);
+ 'Content-Base' -> parse_content_base(Value);
+ 'Content-Encoding' -> parse_content_encoding(Value);
+ 'Content-Language' -> parse_content_language(Value);
+ 'Content-Length' -> parse_content_length(Value);
+ 'Content-Location' -> parse_content_location(Value);
+ 'Content-Md5' -> parse_content_md5(Value);
+ 'Content-Range' -> parse_content_range(Value);
+ 'Content-Type' -> parse_content_type(Value);
+ 'Date' -> parse_date(Value);
+ 'Etag' -> parse_etag(Value);
+ 'Expires' -> parse_expires(Value);
+ 'From' -> parse_from(Value);
+ 'Host' -> parse_host(Value);
+ 'If-Modified-Since' -> parse_if_modified_since(Value);
+ 'If-Match' -> parse_if_match(Value);
+ 'If-None-Match' -> parse_if_none_match(Value);
+ 'If-Range' -> parse_if_range(Value);
+ 'If-Unmodified-Since' -> parse_if_unmodified_since(Value);
+ 'Location' -> parse_location(Value);
+ 'Last-Modified' -> parse_last_modified(Value);
+ 'Max-Forwards' -> parse_max_forwards(Value);
+ 'Pragma' -> parse_pragma(Value);
+ 'Proxy-Authenticate' -> parse_proxy_authenticate(Value);
+ 'Proxy-Authorization' -> parse_proxy_authorization(Value);
+ 'Public' -> parse_public(Value);
+ 'Range' -> parse_range(Value);
+ 'Referer' -> parse_referer(Value);
+ 'Retry-After' -> parse_retry_after(Value);
+ 'Server' -> parse_server(Value);
+ 'Transfer-Encoding' -> parse_transfer_encoding(Value);
+ 'Upgrade' -> parse_upgrade(Value);
+ 'User-Agent' -> parse_user_agent(Value);
+ 'Vary' -> parse_vary(Value);
+ 'Via' -> parse_via(Value);
+ 'Warning' -> parse_warning(Value);
+ 'Www-Authenticate' -> parse_www_authenticate(Value);
+ 'Content-Disposition' -> parse_content_disposition(Value);
+ 'X-Wap-Application-Id' -> parse_x_wap_application_id(Value);
+ 'X-Wap-Content-Uri' -> parse_x_wap_content_uri(Value);
+ 'X-Wap-Initiator-Uri' -> parse_x_wap_initiator_uri(Value);
+ 'Accept-Application' -> parse_accept_application(Value);
+ 'Bearer-Indication' -> parse_bearer_indication(Value);
+ 'Push-Flag' -> parse_push_flag(Value);
+ 'Profile' -> parse_profile(Value);
+ 'Profile-Diff' -> parse_profile_diff(Value);
+ 'Profile-Warning' -> parse_profile_warning(Value);
+ 'Expect' -> parse_expect(Value);
+ 'Te' -> parse_te(Value);
+ 'Trailer' -> parse_trailer(Value);
+ 'X-Wap-Tod' -> parse_x_wap_tod(Value);
+ 'Content-Id' -> parse_content_id(Value);
+ 'Set-Cookie' -> parse_set_cookie(Value);
+ 'Cookie' -> parse_cookie(Value);
+ 'Encoding-Version' -> parse_encoding_version(Value);
+ 'X-Wap-Security' -> parse_x_wap_security(Value);
+ 'X-Wap-Loc-Invocation' -> parse_x_wap_loc_invocation(Value);
+ 'X-Wap-Loc-Delivery' -> parse_x_wap_loc_delivery(Value);
+ _ ->
+ ?dbg("Warning: header field ~p not recognissed\n",[Field]),
+ #wsp_header { name = Field, value = Value}
+ end.
+
+%%
+%% Format headers, will combine multiple headers into one
+%% FIXME: if length is < MAX_HTTP_HEADER_LENGTH
+%%
+format_headers(Hs) ->
+ format_hdrs(lists:keysort(#wsp_header.name,Hs), []).
+
+format_hdrs([H | Hs], Acc) ->
+ V1 = format_value(H),
+ format_hdrs(Hs, H#wsp_header.name, V1, Acc);
+format_hdrs([], Acc) ->
+ lists:reverse(Acc).
+
+format_hdrs([H|Hs], FieldName, FieldValue, Acc)
+ when FieldName == H#wsp_header.name ->
+ V1 = format_value(H),
+ format_hdrs(Hs, FieldName, [FieldValue,",",V1], Acc);
+format_hdrs(Hs, FieldName, FieldValue, Acc) ->
+ format_hdrs(Hs, [{FieldName, lists:flatten(FieldValue)} | Acc]).
+
+
+%%
+%% Format header: #wsp_header => {FieldName, Value}
+%%
+
+format_header(H) ->
+ {H#wsp_header.name, format_value(H)}.
+
+format_value(H) ->
+ case H#wsp_header.name of
+ 'Accept' -> format_accept(H);
+ 'Accept-Charset' -> format_accept_charset(H);
+ 'Accept-Encoding' -> format_accept_encoding(H);
+ 'Accept-Language' -> format_accept_language(H);
+ 'Accept-Ranges' -> format_accept_ranges(H);
+ 'Age' -> format_age(H);
+ 'Allow' -> format_allow(H);
+ 'Authorization' -> format_authorization(H);
+ 'Cache-Control' -> format_cache_control(H);
+ 'Connection' -> format_connection(H);
+ 'Content-Base' -> format_content_base(H);
+ 'Content-Encoding' -> format_content_encoding(H);
+ 'Content-Language' -> format_content_language(H);
+ 'Content-Length' -> format_content_length(H);
+ 'Content-Location' -> format_content_location(H);
+ 'Content-Md5' -> format_content_md5(H);
+ 'Content-Range' -> format_content_range(H);
+ 'Content-Type' -> format_content_type(H);
+ 'Date' -> format_date(H);
+ 'Etag' -> format_etag(H);
+ 'Expires' -> format_expires(H);
+ 'From' -> format_from(H);
+ 'Host' -> format_host(H);
+ 'If-Modified-Since' -> format_if_modified_since(H);
+ 'If-Match' -> format_if_match(H);
+ 'If-None-Match' -> format_if_none_match(H);
+ 'If-Range' -> format_if_range(H);
+ 'If-Unmodified-Since' -> format_if_unmodified_since(H);
+ 'Location' -> format_location(H);
+ 'Last-Modified' -> format_last_modified(H);
+ 'Max-Forwards' -> format_max_forwards(H);
+ 'Pragma' -> format_pragma(H);
+ 'Proxy-Authenticate' -> format_proxy_authenticate(H);
+ 'Proxy-Authorization' -> format_proxy_authorization(H);
+ 'Public' -> format_public(H);
+ 'Range' -> format_range(H);
+ 'Referer' -> format_referer(H);
+ 'Retry-After' -> format_retry_after(H);
+ 'Server' -> format_server(H);
+ 'Transfer-Encoding' -> format_transfer_encoding(H);
+ 'Upgrade' -> format_upgrade(H);
+ 'User-Agent' -> format_user_agent(H);
+ 'Vary' -> format_vary(H);
+ 'Via' -> format_via(H);
+ 'Warning' -> format_warning(H);
+ 'Www-Authenticate' -> format_www_authenticate(H);
+ 'Content-Disposition' -> format_content_disposition(H);
+ 'X-Wap-Application-Id' -> format_x_wap_application_id(H);
+ 'X-Wap-Content-Uri' -> format_x_wap_content_uri(H);
+ 'X-Wap-Initiator-Uri' -> format_x_wap_initiator_uri(H);
+ 'Accept-Application' -> format_accept_application(H);
+ 'Bearer-Indication' -> format_bearer_indication(H);
+ 'Push-Flag' -> format_push_flag(H);
+ 'Profile' -> format_profile(H);
+ 'Profile-Diff' -> format_profile_diff(H);
+ 'Profile-Warning' -> format_profile_warning(H);
+ 'Expect' -> format_expect(H);
+ 'Te' -> format_te(H);
+ 'Trailer' -> format_trailer(H);
+ 'X-Wap-Tod' -> format_x_wap_tod(H);
+ 'Content-Id' -> format_content_id(H);
+ 'Set-Cookie' -> format_set_cookie(H);
+ 'Cookie' -> format_cookie(H);
+ 'Encoding-Version' -> format_encoding_version(H);
+ 'X-Wap-Security' -> format_x_wap_security(H);
+ 'X-Wap-Loc-Invocation' -> format_x_wap_loc_invocation(H);
+ 'X-Wap-Loc-Delivery' -> format_x_wap_loc_delivery(H);
+ _Field ->
+ ?dbg("Warning: header field ~s not recognissed\n",[_Field]),
+ to_list(H#wsp_header.value)
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Encode of field values
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Accept: <content-type> [q=<q-value>] [params]
+%% Type: Multiple
+%% Ref: 8.4.2.7
+%%
+%% Accept-value = Constrained-media | Accept-general-form
+%%
+%% Accept-general-form = Value-length Media-range [Accept-parameters]
+%% Media-range = (Well-known-media | Extension-media) *(Parameter)
+%% Accept-parameters = Q-token Q-value *(Accept-extension)
+%% Accept-extension = Parameter
+%% Constrain-media = Constrained-encoding
+%% Well-known-media = Integer-value
+%% Constrained-encoding = Short-Integer | Extension-media
+%% Q-token = <Octet 128>
+%%
+parse_accept(String) ->
+ %% FIXME
+ ?WH('Accept',String,[]).
+
+format_accept(H) ->
+ [H#wsp_header.value, format_params(H#wsp_header.params)].
+
+encode_accept(H, Version) ->
+ case encode_params(H#wsp_header.params,Version) of
+ <<>> ->
+ encode_well_known_media(H#wsp_header.value, Version);
+ Params ->
+ Media = encode_well_known_media(H#wsp_header.value, Version),
+ e_value(Media, Params)
+ end.
+
+decode_accept(Value, Version) when integer(Value) ->
+ %% Constrained-encoding: Short-Integer
+ ?WH('Accept',decode_well_known_media(Value, Version),[]);
+decode_accept(Value, Version) when list(Value) ->
+ ?WH('Accept',decode_well_known_media(Value,Version),[]);
+decode_accept({_,Data}, Version) ->
+ %% Accept-general-form
+ {Value,QData} = scan_header_data(Data),
+ Media_Range = decode_well_known_media(Value,Version),
+ Params = decode_params(QData, Version),
+ ?WH('Accept',Media_Range,Params).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Accept-Charset: <charset> | * [q=<q-value>]
+%% Type: Multiple
+%% Ref: 8.4.2.8
+%% Note that the definition of this one is a mess!!!!
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_accept_charset(String) ->
+ %% FIXME
+ ?WH('Accept-Charset',String,[]).
+
+format_accept_charset(H) ->
+ [H#wsp_header.value, format_params(H#wsp_header.params)].
+
+encode_accept_charset(H, _Version) ->
+ %% FIXME
+ encode_text_string(H#wsp_header.value).
+
+decode_accept_charset(0, _Version) ->
+ ?WH('Accept-Charset',"*",[]);
+decode_accept_charset(Value, _Version) when integer(Value) ->
+ ?WH('Accept-Charset', decode_charset(Value),[]);
+decode_accept_charset(Value, _Version) when list(Value) ->
+ ?WH('Accept-Charset',Value,[]);
+decode_accept_charset({short,Data}, _Version) ->
+ %% Me guessing that the short form SHOULD be mulit octet integer!!!
+ Value = d_long(Data),
+ ?WH('Accept-Charset', decode_charset(Value),[]);
+decode_accept_charset({long,Value}, _Version) ->
+ {Data1, QData} = scan_header_data(Value),
+ CharSet = case Data1 of
+ 0 ->
+ "*";
+ Value1 when integer(Value1) ->
+ decode_charset(Value1);
+ Value1 when list(Value1) ->
+ Value1;
+ {short,Value1} ->
+ Value2 = d_long(Value1),
+ decode_charset(Value2)
+ end,
+ Params = if QData == <<>> ->
+ [];
+ true ->
+ {QValue,_} = d_q_value(QData),
+ {CharSet,[{q, QValue}]}
+ end,
+ ?WH('Accept-Charset',CharSet, Params).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Accept-Encoding: gzip | compress | deflate | * [q=<q-value>]
+%% Ref:
+%% Type: Multiple
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_accept_encoding(String) ->
+ ?WH('Accept-Encoding',String,[]).
+
+format_accept_encoding(H) ->
+ [H#wsp_header.value, format_params(H#wsp_header.params)].
+
+encode_accept_encoding(H, _Version) ->
+ %% FIXME general form
+ case H#wsp_header.value of
+ "gzip" -> ?ENCODE_SHORT(0);
+ "compress" -> ?ENCODE_SHORT(1);
+ "deflate" -> ?ENCODE_SHORT(2);
+ Value -> encode_text_string(Value)
+ end.
+
+decode_accept_encoding(0, _Version) ->
+ ?WH('Accept-Encoding',"gzip",[]);
+decode_accept_encoding(1, _Version) ->
+ ?WH('Accept-Encoding',"compress",[]);
+decode_accept_encoding(2, _Version) ->
+ ?WH('Accept-Encoding',"deflate",[]);
+decode_accept_encoding(Value, Version) when list(Version) ->
+ ?WH('Accept-Encoding',Value,[]);
+decode_accept_encoding({_,Data}, _Version) when binary(Data) ->
+ {Enc, Data1} = scan_header_data(Data),
+ Params = if Data1 == <<>> ->
+ [];
+ true ->
+ {QVal,_} = d_q_value(Data1),
+ [{q, QVal}]
+ end,
+ case Enc of
+ 0 -> ?WH('Accept-Encoding',"gzip",Params);
+ 1 -> ?WH('Accept-Encoding',"compress",Params);
+ 2 -> ?WH('Accept-Encoding',"deflate",Params);
+ 3 -> ?WH('Accept-Encoding',"*",Params);
+ _ when list(Enc) ->
+ ?WH('Accept-Encoding',Enc,Params)
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%
+%% Accept-Language: * | <lang> [q=<q-value>]
+%% Type: Multiple
+%% Ref: 8.4.2.10
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_accept_language(Value) ->
+ ?WH('Accept-Language',Value,[]).
+
+format_accept_language(H) ->
+ [H#wsp_header.value, format_params(H#wsp_header.params)].
+
+encode_accept_language(H, _Version) ->
+ case H#wsp_header.value of
+ "*" -> ?ENCODE_SHORT(0);
+ Lang -> case catch encode_lang(Lang) of
+ {'EXIT', _} -> encode_text_string(Lang);
+ Code -> encode_integer(Code)
+ end
+ end.
+
+decode_accept_language(0, _Version) ->
+ ?WH('Accept-Language',"*",[]);
+decode_accept_language(Value, _Version) when integer(Value) ->
+ ?WH('Accept-Language',decode_lang(Value),[]);
+decode_accept_language(Value, _Version) when list(Value) ->
+ ?WH('Accept-Language',Value,[]);
+decode_accept_language({_,Data}, _Version) ->
+ {Data1, QData} = scan_header_data(Data),
+ Charset = case Data1 of
+ 0 ->
+ "*";
+ Value1 when integer(Value1) ->
+ decode_lang(Value1);
+ Value1 when list(Value1) ->
+ Value1;
+ {short,Data2} ->
+ decode_lang(d_long(Data2))
+ end,
+ Params =
+ if QData == <<>> ->
+ [];
+ true ->
+ {QVal,_} = d_q_value(QData),
+ [{q, QVal}]
+ end,
+ ?WH('Accept-Language',Charset,Params).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Accept-Ranges: none | bytes | <extension>
+%% Type: single
+%% Ref:
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_accept_ranges(Value) ->
+ ?WH('Accept-Ranges', Value, []).
+
+format_accept_ranges(H) ->
+ H#wsp_header.value.
+
+encode_accept_ranges(H, _Version) ->
+ case H#wsp_header.value of
+ "none" -> ?ENCODE_SHORT(0);
+ "bytes" -> ?ENCODE_SHORT(1);
+ Value -> encode_text_string(Value)
+ end.
+
+decode_accept_ranges(0, _Version) ->
+ ?WH('Accept-Ranges', "none", []);
+decode_accept_ranges(1, _Version) ->
+ ?WH('Accept-Ranges', "bytes", []);
+decode_accept_ranges(Value, _Version) when list(Value) ->
+ ?WH('Accept-Ranges', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Age: <delta-seconds>
+%% Type: single
+%% Ref:
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_age(Value) ->
+ %% FIXME
+ ?WH('Age', Value, []).
+
+format_age(H) ->
+ integer_to_list(H#wsp_header.value).
+
+encode_age(H, _Version) ->
+ e_delta_seconds(H#wsp_header.value).
+
+decode_age(Value, _Version) when integer(Value) ->
+ ?WH('Age', Value, []);
+decode_age({short,Data}, _Version) ->
+ ?WH('Age', d_long(Data), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Allow: <well-known-method>
+%% Type: multiple
+%% Ref:
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_allow(Value) ->
+ ?WH('Allow', parse_well_known_method(Value), []).
+
+format_allow(H) ->
+ atom_to_list(H#wsp_header.value).
+
+encode_allow(H, Version) ->
+ encode_well_known_method(H#wsp_header.value, Version).
+
+decode_allow(Value, Version) ->
+ ?WH('Allow', decode_well_known_method(Value,Version), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Authorization:
+%% Ref: 8.4.2.14
+%% Type: server-to-client
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_authorization(Value) ->
+ parse_credentials('Authorization', Value).
+
+format_authorization(H) ->
+ format_credentials(H#wsp_header.value, H#wsp_header.params).
+
+encode_authorization(H, Version) ->
+ encode_credentials(H#wsp_header.value, H#wsp_header.params, Version).
+
+decode_authorization({_,Data}, Version) ->
+ decode_credentials('Authorization', Data, Version).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%%
+%% Cache-Control:
+%% 8.4.2.15
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_cache_control(Value) ->
+ case Value of
+ "no-cache" -> ?WH('Cache-Control',Value,[]);
+ "no-store" -> ?WH('Cache-Control',Value,[]);
+ "max-stale" -> ?WH('Cache-Control',Value,[]);
+ "only-if-cached" -> ?WH('Cache-Control',Value,[]);
+ "private" -> ?WH('Cache-Control',Value,[]);
+ "public" -> ?WH('Cache-Control',Value,[]);
+ "no-transform" -> ?WH('Cache-Control',Value,[]);
+ "must-revalidate" -> ?WH('Cache-Control',Value,[]);
+ "proxy-revalidate" -> ?WH('Cache-Control',Value,[]);
+ _ ->
+ Params = parse_params([Value]),
+ ?WH('Cache-Control',"",Params)
+ end.
+
+format_cache_control(H) ->
+ if H#wsp_header.value == "" ->
+ format_params0(H#wsp_header.params);
+ true ->
+ [H#wsp_header.value, format_params(H#wsp_header.params)]
+ end.
+
+
+
+encode_cache_control(H, Version) ->
+ case H#wsp_header.value of
+ "no-cache" -> ?ENCODE_SHORT(0);
+ "no-store" -> ?ENCODE_SHORT(1);
+ "max-stale" -> ?ENCODE_SHORT(3);
+ "only-if-cached" -> ?ENCODE_SHORT(5);
+ "private" -> ?ENCODE_SHORT(7);
+ "public" -> ?ENCODE_SHORT(6);
+ "no-transform" -> ?ENCODE_SHORT(8);
+ "must-revalidate" -> ?ENCODE_SHORT(9);
+ "proxy-revalidate" -> ?ENCODE_SHORT(10);
+ "" ->
+ case H#wsp_header.params of
+ [{'no-cache',Field}] ->
+ e_value(?ENCODE_SHORT(0),
+ e_field_name(Field,Version));
+ [{'max-age',Sec}] ->
+ e_value(?ENCODE_SHORT(2),
+ e_delta_seconds(Sec));
+ [{'max-fresh',Sec}] ->
+ e_value(?ENCODE_SHORT(4),
+ e_delta_seconds(Sec));
+ [{'private',Field}] ->
+ e_value(?ENCODE_SHORT(7),
+ e_field_name(Field,Version));
+ [{'s-maxage',Sec}] ->
+ e_value(?ENCODE_SHORT(11),
+ e_delta_seconds(Sec))
+ end;
+ Ext ->
+ [Param] = H#wsp_header.params,
+ e_value(encode_text_string(Ext),
+ encode_parameter(Param, Version))
+ end.
+
+
+decode_cache_control(Value, _Version) when integer(Value) ->
+ case Value of
+ 0 -> ?WH('Cache-Control',"no-cache",[]);
+ 1 -> ?WH('Cache-Control',"no-store",[]);
+ 3 -> ?WH('Cache-Control',"max-stale",[]);
+ 5 -> ?WH('Cache-Control',"only-if-cached",[]);
+ 7 -> ?WH('Cache-Control',"private",[]);
+ 6 -> ?WH('Cache-Control',"public",[]);
+ 8 -> ?WH('Cache-Control',"no-transform",[]);
+ 9 -> ?WH('Cache-Control',"must-revalidate",[]);
+ 10 -> ?WH('Cache-Control',"proxy-revalidate",[])
+ end;
+decode_cache_control(Value, _Version) when list(Value) ->
+ ?WH('Cache-Control',Value,[]);
+decode_cache_control({_,Data},Version) ->
+ {CacheDir, Data1} = scan_header_data(Data),
+ case CacheDir of
+ 0 ->
+ {Field,_} = d_field_name(Data1),
+ ?WH('Cache-Control',"",[{'no-cache',Field}]);
+ 2 ->
+ {Sec,_} = d_integer_value(Data1),
+ ?WH('Cache-Control',"",[{'max-age',Sec}]);
+ 4 ->
+ {Sec,_} = d_integer_value(Data1),
+ ?WH('Cache-Control',"",[{'max-fresh',Sec}]);
+ 7 ->
+ {Field,_} = d_field_name(Data1),
+ ?WH('Cache-Control',"",[{private,Field}]);
+ 11 ->
+ {Sec,_} = d_integer_value(Data1),
+ ?WH('Cache-Control',"",[{'s-maxage',Sec}]);
+ Ext when list(Ext) ->
+ {Param,_} = decode_parameter(Data1, Version),
+ ?WH('Cache-Control',Ext,[Param])
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Connection: close | Ext
+%% Type: single
+%% Ref: 8.4.2.16
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_connection(Value) ->
+ ?WH('Connection', Value, []).
+
+format_connection(H) ->
+ H#wsp_header.value.
+
+encode_connection(H, _Version) ->
+ case H#wsp_header.value of
+ "close" -> ?ENCODE_SHORT(0);
+ Value -> encode_text_string(Value)
+ end.
+
+decode_connection(0, _Version) ->
+ ?WH('Connection', "close", []);
+decode_connection(Value, _Version) when list(Value) ->
+ ?WH('Connection', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Base: <uri>
+%% Type: single
+%% Ref:
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_content_base(Value) ->
+ ?WH('Content-Base', Value, []).
+
+format_content_base(H) ->
+ H#wsp_header.value.
+
+encode_content_base(H, _Version) ->
+ encode_uri_value(H#wsp_header.value).
+
+decode_content_base(Value, _Version) when list(Value) ->
+ ?WH('Content-Base', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Encoding:
+%% Ref: 8.4.2.18
+%% Type: single
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_content_encoding(Value) ->
+ ?WH('Content-Encoding', tolower(Value), []).
+
+format_content_encoding(H) ->
+ H#wsp_header.value.
+
+encode_content_encoding(H, _Version) ->
+ case H#wsp_header.value of
+ "gzip" -> ?ENCODE_SHORT(0);
+ "compress" -> ?ENCODE_SHORT(1);
+ "deflate" -> ?ENCODE_SHORT(2);
+ Value -> encode_text_string(Value)
+ end.
+
+decode_content_encoding(0, _Version) ->
+ ?WH('Content-Encoding', "gzip", []);
+decode_content_encoding(1, _Version) ->
+ ?WH('Content-Encoding', "compress", []);
+decode_content_encoding(2, _Version) ->
+ ?WH('Content-Encoding',"deflate", []);
+decode_content_encoding(Value, _Version) when list(Value) ->
+ ?WH('Content-Encoding', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Language:
+%% Ref: 8.4.2.19
+%% Type: single
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_content_language(Value) ->
+ ?WH('Content-Language', Value, []).
+
+format_content_language(H) ->
+ H#wsp_header.value.
+
+encode_content_language(H, _Version) ->
+ case H#wsp_header.value of
+ "*" -> ?ENCODE_SHORT(0);
+ Lang -> case catch encode_lang(Lang) of
+ {'EXIT', _} -> encode_text_string(Lang);
+ Code -> encode_integer(Code)
+ end
+ end.
+
+decode_content_language(0, _Version) ->
+ ?WH('Content-Language',"*",[]);
+decode_content_language(Value, _Version) when integer(Value) ->
+ ?WH('Content-Language',decode_lang(Value),[]);
+decode_content_language(Value, _Version) when list(Value) ->
+ ?WH('Content-Language',Value,[]);
+decode_content_language({short,Data}, _Version) ->
+ Value = d_long(Data),
+ ?WH('Content-Language',decode_lang(Value),[]);
+decode_content_language(Value, _Version) when list(Value) ->
+ ?WH('Content-Language',Value,[]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Length: <integer-value>
+%% Ref: 8.4.2.20
+%% Type: single
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_content_length(Value) ->
+ ?WH('Content-Length', list_to_integer(Value), []).
+
+format_content_length(H) ->
+ integer_to_list(H#wsp_header.value).
+
+encode_content_length(H, _Version) ->
+ encode_integer(H#wsp_header.value).
+
+decode_content_length(Value, _Version) when integer(Value) ->
+ ?WH('Content-Length', Value, []);
+decode_content_length({short,Data}, _Version) ->
+ Value = d_long(Data),
+ ?WH('Content-Length', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Location: <uri-value>
+%% Ref: 8.4.2.21
+%% Type: single
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_content_location(Value) ->
+ ?WH('Content-Location', Value, []).
+
+format_content_location(H) ->
+ H#wsp_header.value.
+
+encode_content_location(H, _Version) ->
+ encode_uri_value(H#wsp_header.value).
+
+decode_content_location(Value, _Version) when list(Value) ->
+ ?WH('Content-Location', decode_uri_value(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Md5: <value-length> <digest>
+%% Ref: 8.4.2.22
+%% Type: single, end-to-end
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_content_md5(Value) ->
+ ?WH('Content-Md5', base64:decode(Value), []).
+
+format_content_md5(H) ->
+ base64:encode(H#wsp_header.value).
+
+encode_content_md5(H, _Version) ->
+ e_value(H#wsp_header.value).
+
+decode_content_md5({_,Data}, _Version) ->
+ ?WH('Content-Md5', Data, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Range: <first-byte-pos> <entity-len>
+%% Ref: 8.4.2.23
+%% Type: single
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_content_range(Value) ->
+ %% FIXME:
+ ?WH('Content-Range', Value, []).
+
+format_content_range(H) ->
+ {Pos,Len} = H#wsp_header.value,
+ if Len == "*" ->
+ ["bytes ", integer_to_list(Pos), "-*/*"];
+ true ->
+ ["bytes ", integer_to_list(Pos),"-",integer_to_list(Len-1),
+ "/", integer_to_list(Len)]
+ end.
+
+encode_content_range(H, _Version) ->
+ case H#wsp_header.value of
+ {Pos, "*"} ->
+ e_value(e_uintvar(Pos), <<128>>);
+ {Pos, Len} ->
+ e_value(e_uintvar(Pos), e_uintvar(Len))
+ end.
+
+decode_content_range({_, Data}, _Version) ->
+ {Pos, Data1} = d_uintvar(Data),
+ Len =
+ case Data1 of
+ <<128>> -> "*";
+ _ ->
+ {L, _} = d_uintvar(Data1),
+ L
+ end,
+ ?WH('Content-Range', {Pos,Len}, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Type:
+%% Ref: 8.4.2.24
+%% Type: single, end-to-end
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_content_type(Value) ->
+ case string:tokens(Value, ";") of
+ [Type | Ps] ->
+ Params = parse_params(Ps),
+ ?WH('Content-Type', Type, Params);
+ [] ->
+ ?WH('Content-Type', Value, [])
+ end.
+
+format_content_type(H) ->
+ [H#wsp_header.value, format_params(H#wsp_header.params)].
+
+encode_content_type(H, Version) ->
+ case encode_params(H#wsp_header.params,Version) of
+ <<>> ->
+ encode_well_known_media(H#wsp_header.value, Version);
+ Params ->
+ Media = encode_well_known_media(H#wsp_header.value, Version),
+ e_value(Media, Params)
+ end.
+
+decode_content_type(Value,Version) when integer(Value) ->
+ ?WH('Content-Type', decode_well_known_media(Value,Version), []);
+decode_content_type(Value,Version) when list(Value) ->
+ ?WH('Content-Type', decode_well_known_media(Value,Version), []);
+decode_content_type({_, Data}, Version) ->
+ {Value,Data1} = scan_header_data(Data),
+ ContentType = if integer(Value) ->
+ decode_well_known_media(Value,Version);
+ list(Value) ->
+ decode_well_known_media(Value,Version);
+ true ->
+ {_,Data2} = Value,
+ decode_well_known_media(d_long(Data2),Version)
+ end,
+ Params = decode_params(Data1, Version),
+ ?WH('Content-Type', ContentType, Params).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Date: <http-date>
+%% Ref: 8.2.4.25
+%% Type: single, end-to-end
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_date(String) ->
+ {DateTime, _} = parse_http_date(String),
+ ?WH('Date', DateTime, []).
+
+format_date(H) ->
+ fmt_date(H#wsp_header.value).
+
+encode_date(H, _Version) ->
+ e_date(H#wsp_header.value).
+
+decode_date(Value, _Version) ->
+ ?WH('Date', d_date(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Etag: <text-string>
+%% Ref: 8.2.4.26
+%% Type: single, end-to-end
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_etag(Value) ->
+ ?WH('Etag', Value, []).
+
+format_etag(H) ->
+ H#wsp_header.value.
+
+encode_etag(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_etag(Value, _Version) ->
+ ?WH('Etag', decode_text_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Expires: <date-value>
+%% Ref: 8.4.2.27
+%% Type: single, end-to-end, server-to-client
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_expires(String) ->
+ {DateTime, _} = parse_http_date(String),
+ ?WH('Expires', DateTime, []).
+
+format_expires(H) ->
+ fmt_date(H#wsp_header.value).
+
+encode_expires(H, _Version) ->
+ e_date(H#wsp_header.value).
+
+decode_expires(Value, _Version) ->
+ ?WH('Expires', d_date(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% From: <text-string>
+%% Ref: 8.4.2.28
+%% Type: single,
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_from(Value) ->
+ ?WH('From', Value, []).
+
+format_from(H) ->
+ H#wsp_header.value.
+
+encode_from(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_from(Value, _Version) ->
+ ?WH('From', decode_text_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Host: <text-string>
+%% Ref: 8.4.2.29
+%% Type: single, end-to-end, client-to-server
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_host(Value) ->
+ ?WH('Host', Value, []).
+
+format_host(H) ->
+ H#wsp_header.value.
+
+encode_host(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_host(Value, _Version) ->
+ ?WH('Host', decode_text_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% If-Modified-Since: <date-value>
+%% Ref: 8.4.2.30
+%% Type: single, end-to-end, client-to-server
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_if_modified_since(String) ->
+ {DateTime, _} = parse_http_date(String),
+ ?WH('If-Modified-Since', DateTime, []).
+
+format_if_modified_since(H) ->
+ fmt_date(H#wsp_header.value).
+
+encode_if_modified_since(H, _Version) ->
+ e_date(H#wsp_header.value).
+
+decode_if_modified_since(Value, _Version) ->
+ ?WH('If-Modified-Since', d_date(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% If-Match: <text-string>
+%% Ref: 8.4.2.31
+%% Type: end-to-end, client-to-server
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_if_match(Value) ->
+ ?WH('If-Match', Value, []).
+
+format_if_match(H) ->
+ H#wsp_header.value.
+
+encode_if_match(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_if_match(Value, _Version) ->
+ ?WH('If-Match', decode_text_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% If-None-Match: <text-string>
+%% Ref: 8.4.2.32
+%% Type: end-to-end, client-to-server
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_if_none_match(Value) ->
+ ?WH('If-None-Match', Value, []).
+
+format_if_none_match(H) ->
+ H#wsp_header.value.
+
+encode_if_none_match(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_if_none_match(Value, _Version) ->
+ ?WH('If-None-Match', decode_text_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% If-Range: Text | Date
+%% Ref: 8.4.2.33
+%% Type: end-to-end, client-to-server
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_if_range(Value) ->
+ case catch parse_http_date(Value) of
+ {'EXIT', _} ->
+ ?WH('If-Range', Value, []);
+ {DateTime,_} ->
+ ?WH('If-Range', DateTime, [])
+ end.
+
+
+format_if_range(H) ->
+ case H#wsp_header.value of
+ Value when list(Value) -> Value;
+ DateTime -> fmt_date(DateTime)
+ end.
+
+encode_if_range(H, _Version) ->
+ case H#wsp_header.value of
+ Value when list(Value) ->
+ encode_text_string(Value);
+ DateTime ->
+ e_date(DateTime)
+ end.
+
+decode_if_range(Value, _Version) when list(Value) ->
+ ?WH('If-Range', decode_text_string(Value), []);
+decode_if_range(Value, _Version) ->
+ ?WH('If-Range', d_date(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% If-Unmodified-Since: <date-value>
+%% Ref: 8.4.2.34
+%% Type: single, end-to-end, client-to-server
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_if_unmodified_since(String) ->
+ {DateTime, _} = parse_http_date(String),
+ ?WH('If-Unmodified-Since', DateTime, []).
+
+format_if_unmodified_since(H) ->
+ fmt_date(H#wsp_header.value).
+
+encode_if_unmodified_since(H, _Version) ->
+ e_date(H#wsp_header.value).
+
+decode_if_unmodified_since(Value, _Version) ->
+ ?WH('If-Unmodified-Since', d_date(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Location: <uri-value>
+%% Ref: 8.4.2.36
+%% Type: single, end-to-end, server-to-client
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_location(Value) ->
+ ?WH('Location', Value, []).
+
+format_location(H) ->
+ H#wsp_header.value.
+
+encode_location(H, _Version) ->
+ encode_uri_value(H#wsp_header.value).
+
+decode_location(Value, _Version) when list(Value) ->
+ ?WH('Location', decode_uri_value(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Last-Modified: <date-value>
+%% Ref: 8.4.2.35
+%% Type: single, end-to-end, server-to-client
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_last_modified(String) ->
+ {DateTime, _} = parse_http_date(String),
+ ?WH('Last-Modified', DateTime, []).
+
+format_last_modified(H) ->
+ fmt_date(H#wsp_header.value).
+
+encode_last_modified(H, _Version) ->
+ e_date(H#wsp_header.value).
+
+decode_last_modified(Value, _Version) ->
+ ?WH('Last-Modified', d_date(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Max-Forwards: <integer-value>
+%% Ref: 8.4.2.37
+%% Type: single, end-to-end, server-to-client
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_max_forwards(String) ->
+ ?WH('Max-Forwards', list_to_integer(String), []).
+
+format_max_forwards(H) ->
+ integer_to_list(H#wsp_header.value).
+
+encode_max_forwards(H, _Version) ->
+ encode_integer(H#wsp_header.value).
+
+decode_max_forwards(Value, _Version) ->
+ decode_integer(Value).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Pragma: No-Cache | value-length Parameter
+%% Ref:
+%% Type:
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_pragma(Value) ->
+ ?WH('Pragma',Value,[]).
+
+format_pragma(H) ->
+ case H#wsp_header.value of
+ "" -> format_params(H#wsp_header.params);
+ Value -> Value
+ end.
+
+encode_pragma(H, Version) ->
+ case H#wsp_header.value of
+ "no-cache" -> ?ENCODE_SHORT(0);
+ "" ->
+ encode_parameter(hd(H#wsp_header.params), Version)
+ end.
+
+decode_pragma(0, _Version) ->
+ ?WH('Pragma',"no-cache",[]);
+decode_pragma({_,Data}, Version) ->
+ {Param,_} = decode_parameter(Data, Version),
+ ?WH('Pragma',"",[Param]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Proxy-Authenticate:
+%% Ref: 8.4.2.39
+%% Type: single?, client-to-proxy
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_proxy_authenticate(Value) ->
+ parse_challenge('Proxy-Authenticate', Value).
+
+format_proxy_authenticate(H) ->
+ format_challenge(H#wsp_header.value, H#wsp_header.params).
+
+encode_proxy_authenticate(H, Version) ->
+ encode_challenge(H#wsp_header.value,
+ H#wsp_header.params, Version).
+
+decode_proxy_authenticate({_, Data}, Version) ->
+ decode_challenge('Proxy-Authenticate', Data, Version).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Proxy-authorization:
+%% Ref: 8.4.2.40
+%% Type: single?, proxy-to-client
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_proxy_authorization(Value) ->
+ parse_credentials('Proxy-Authorization', Value).
+
+format_proxy_authorization(H) ->
+ format_credentials(H#wsp_header.value, H#wsp_header.params).
+
+encode_proxy_authorization(H, Version) ->
+ encode_credentials(H#wsp_header.value, H#wsp_header.params, Version).
+
+decode_proxy_authorization({_,Data}, Version) ->
+ decode_credentials('Proxy-Authorization', Data, Version).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Public: <well-known-method> | Token-Text
+%% Ref: 8.4.2.41
+%% Type:
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_public(Value) ->
+ ?WH('Public', parse_well_known_method(Value), []).
+
+format_public(H) ->
+ if atom(H#wsp_header.value) ->
+ atom_to_list(H#wsp_header.value);
+ list(H#wsp_header.value) ->
+ H#wsp_header.value
+ end.
+
+encode_public(H, Version) ->
+ if atom(H#wsp_header.value) ->
+ encode_well_known_method(H#wsp_header.value,Version);
+ list(H#wsp_header.value) ->
+ encode_text_string(H#wsp_header.value)
+ end.
+
+decode_public(Value, _Version) when list(Value) ->
+ ?WH('Public', Value, []);
+decode_public(Value, Version) ->
+ ?WH('Public', decode_well_known_method(Value,Version), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Range:
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_range(Value) ->
+ %% FIXME:
+ ?WH('Range', Value, []).
+
+format_range(H) ->
+ case H#wsp_header.value of
+ {First,undefined} ->
+ ["bytes=", integer_to_list(First), "-"];
+ {First,Last} ->
+ ["bytes=", integer_to_list(First), "-", integer_to_list(Last)];
+ Len when integer(Len) ->
+ ["bytes=-", integer_to_list(Len)]
+ end.
+
+encode_range(H, _Version) ->
+ case H#wsp_header.value of
+ {First,undefined} ->
+ e_value(?ENCODE_SHORT(0),
+ e_uintvar(First));
+ {First,Last} ->
+ e_value(?ENCODE_SHORT(0),
+ e_uintvar(First),
+ e_uintvar(Last));
+ Len when integer(Len) ->
+ e_value(?ENCODE_SHORT(1),
+ e_uintvar(Len))
+ end.
+
+decode_range({_,Data}, _Version) ->
+ case scan_header_data(Data) of
+ {0, Data1} ->
+ case d_uintvar(Data1) of
+ {First, <<>>} ->
+ ?WH('Range', {First, undefined},[]);
+ {First, Data2} ->
+ {Last, _} = d_uintvar(Data2),
+ ?WH('Range', {First, Last}, [])
+ end;
+ {1, Data1} ->
+ {Len, _} =d_uintvar(Data1),
+ ?WH('Range', Len, [])
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Referer: <uri-value>
+%% Ref: 8.4.2.43
+%% Type: single
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_referer(Value) ->
+ ?WH('Referer', Value, []).
+
+format_referer(H) ->
+ H#wsp_header.value.
+
+encode_referer(H, _Version) ->
+ encode_uri_value(H#wsp_header.value).
+
+decode_referer(Value, _Version) when list(Value) ->
+ ?WH('Referer', decode_uri_value(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Retry-After: Value-length (Retry-date-value | Retry-delta-seconds)
+%% Ref: 8.4.2.44
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_retry_after(Value) ->
+ case catch parse_http_date(Value) of
+ {'EXIT', _} ->
+ ?WH('Retry-After', list_to_integer(Value), []);
+ {DateTime,_} ->
+ ?WH('Retry-After', DateTime, [])
+ end.
+
+format_retry_after(H) ->
+ Value = H#wsp_header.value,
+ if integer(Value) ->
+ integer_to_list(Value);
+ true ->
+ fmt_date(Value)
+ end.
+
+encode_retry_after(H, _Version) ->
+ Value = H#wsp_header.value,
+ if integer(Value) ->
+ e_value(?ENCODE_SHORT(1),
+ e_delta_seconds(Value));
+ true ->
+ e_value(?ENCODE_SHORT(0),
+ e_date(Value))
+ end.
+
+decode_retry_after({_,Data}, _Version) ->
+ case scan_header_data(Data) of
+ {0, Data1} ->
+ ?WH('Retry-After', d_date(Data1), []);
+ {1, Data1} ->
+ case scan_header_data(Data1) of
+ Sec when integer(Sec) ->
+ ?WH('Retry-After', Sec, []);
+ {short,Data2} ->
+ ?WH('Retry-After', d_long(Data2), [])
+ end
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Server: <text-string>
+%% Ref: 8.4.2.45
+%% Type: server-to-client
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_server(Value) ->
+ ?WH('Server', Value, []).
+
+format_server(H) ->
+ H#wsp_header.value.
+
+encode_server(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_server(Value, _Version) ->
+ ?WH('Server', decode_text_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Transfer-Encoding:
+%% Ref: 8.4.2.46
+%% Type: hop-by-hop
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_transfer_encoding(Value) ->
+ ?WH('Transfer-Encoding', Value, []).
+
+format_transfer_encoding(H) ->
+ H#wsp_header.value.
+
+encode_transfer_encoding(H, _Version) ->
+ case H#wsp_header.value of
+ "chunked" -> ?ENCODE_SHORT(0);
+ Value -> encode_text_string(Value)
+ end.
+
+decode_transfer_encoding(0, _Version) ->
+ ?WH('Transfer-Encoding', "chunked", []);
+decode_transfer_encoding(Value, _Version) when list(Value)->
+ ?WH('Transfer-Encoding', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Upgrade: Text-String
+%% Ref: 8.4.2.47
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_upgrade(Value) ->
+ ?WH('Upgrade', Value, []).
+
+format_upgrade(H) ->
+ H#wsp_header.value.
+
+encode_upgrade(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_upgrade(Value, _Version) when list(Value) ->
+ ?WH('Upgrade', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% User-Agent:
+%% Ref: 8.4.2.48
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_user_agent(Value) ->
+ ?WH('User-Agent', Value, []).
+
+format_user_agent(H) ->
+ H#wsp_header.value.
+
+encode_user_agent(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_user_agent(Value, _Version) ->
+ ?WH('User-Agent', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Vary: Well-known-header-field | Token-text
+%% Ref: 8.4.2.49
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_vary(Value) ->
+ ?WH('Vary', normalise_field_name(Value), []).
+
+format_vary(H) ->
+ to_list(H#wsp_header.value).
+
+encode_vary(H, Version) ->
+ e_field_name(H#wsp_header.value, Version).
+
+decode_vary(Value, _Version) when integer(Value) ->
+ ?WH('Vary', lookup_field_name(Value), []);
+decode_vary(Value, _Version) when list(Value) ->
+ ?WH('Vary', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Via: <text-string>
+%% Ref: 8.4.2.50
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_via(Value) ->
+ ?WH('Via', Value, []).
+
+format_via(H) ->
+ H#wsp_header.value.
+
+encode_via(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_via(Value, _Version) when list(Value) ->
+ ?WH('Via', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Warning: Warn-Code | Warning-value
+%% Ref: 8.4.2.51
+%% Type: general, multiple
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_warning(Value) ->
+ case string:tokens(Value, " ") of
+ [Code] ->
+ ?WH('Warning', {list_to_integer(Code),"",""}, []);
+ [Code,Agent,Text] ->
+ ?WH('Warning', {list_to_integer(Code), Agent, Text}, [])
+ end.
+
+format_warning(H) ->
+ case H#wsp_header.value of
+ {Code, "", ""} ->
+ integer_to_list(Code);
+ {Code, Agent, Text} ->
+ [integer_to_list(Code), " ", Agent, " ", Text]
+ end.
+
+encode_warning(H, _Version) ->
+ case H#wsp_header.value of
+ {Code,"",""} ->
+ ?ENCODE_SHORT(Code);
+ {Code, Agent, Text} ->
+ e_value(?ENCODE_SHORT(Code),
+ encode_text_string(Agent),
+ encode_text_string(Text))
+ end.
+
+decode_warning(Value, _Version) when integer(Value) ->
+ ?WH('Warning', {Value, "", ""}, []);
+decode_warning({_, Data}, _Version) ->
+ {Code,Data1}= scan_header_data(Data),
+ {Agent,Data2} = d_text_string(Data1),
+ {Text,_Data3} = d_text_string(Data2),
+ ?WH('Warning', {Code,Agent,Text}, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% WWW-Authenticate: challenge
+%% Ref: 8.4.2.52
+%% Type: single? client-to-server
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_www_authenticate(Value) ->
+ parse_challenge('Www-Authenticate', Value).
+
+format_www_authenticate(H) ->
+ format_challenge(H#wsp_header.value, H#wsp_header.params).
+
+encode_www_authenticate(H, Version) ->
+ encode_challenge(H#wsp_header.value,
+ H#wsp_header.params, Version).
+
+decode_www_authenticate({_, Data}, Version) ->
+ decode_challenge('Www-Authenticate', Data, Version).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Disposition: "form-data" | "attachment" [<param>]*
+%% Ref: 8.4.2.53
+%% Type: single
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_content_disposition(Value) ->
+ ?WH('Content-Disposition', Value, []).
+
+format_content_disposition(H) ->
+ [H#wsp_header.value, format_params(H#wsp_header.params)].
+
+encode_content_disposition(H, Version) ->
+ case H#wsp_header.value of
+ "form-data" ->
+ e_value(?ENCODE_SHORT(0),
+ encode_params(H#wsp_header.params, Version));
+ "attachment" ->
+ e_value(?ENCODE_SHORT(1),
+ encode_params(H#wsp_header.params, Version))
+ end.
+
+decode_content_disposition({_,Data}, Version) when binary(Data) ->
+ case scan_header_data(Data) of
+ {0, Data1} ->
+ Params = decode_params(Data1, Version),
+ ?WH('Content-Disposition', "form-data", Params);
+ {1, Data1} ->
+ Params = decode_params(Data1, Version),
+ ?WH('Content-Disposition', "attachment", Params)
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% X-Wap-Application-Id:
+%% Ref: 8.4.2.54
+%% Type:
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_x_wap_application_id(Value) ->
+ ?WH('X-Wap-Application-Id', Value, []).
+
+format_x_wap_application_id(H) ->
+ H#wsp_header.value.
+
+encode_x_wap_application_id(H, _Version) ->
+ encode_push_application(H#wsp_header.value).
+
+decode_x_wap_application_id(Value, _Version) ->
+ ?WH('X-Wap-Application-Id', decode_push_application(Value),[]).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% X-Wap-Content-Uri: <uri-value>
+%% Ref: 8.4.2.55
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_x_wap_content_uri(Value) ->
+ ?WH('X-Wap-Content-Uri', Value, []).
+
+format_x_wap_content_uri(H) ->
+ H#wsp_header.value.
+
+encode_x_wap_content_uri(H, _Version) ->
+ encode_uri_value(H#wsp_header.value).
+
+decode_x_wap_content_uri(Value, _Version) when list(Value) ->
+ ?WH('X-Wap-Content-Uri', decode_uri_value(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% X-Wap-Initiator-Uri: <uri-value>
+%% Ref: 8.4.2.56
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_x_wap_initiator_uri(Value) ->
+ ?WH('X-Wap-Initiator-Uri', Value, []).
+
+format_x_wap_initiator_uri(H) ->
+ H#wsp_header.value.
+
+encode_x_wap_initiator_uri(H, _Version) ->
+ encode_uri_value(H#wsp_header.value).
+
+decode_x_wap_initiator_uri(Value, _Version) when list(Value) ->
+ ?WH('X-Wap-Initiator-Uri', decode_uri_value(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Accept-Application: Any-Application | Appication-Id-Value
+%% Ref: 8.4.2.57
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_accept_application(Value) ->
+ ?WH('Accept-Application', Value, []).
+
+format_accept_application(H) ->
+ H#wsp_header.value.
+
+
+encode_accept_application(H, _Version) ->
+ case H#wsp_header.value of
+ "*" -> ?ENCODE_SHORT(0);
+ Value ->
+ case catch encode_push_application(Value) of
+ {'EXIT',_} ->
+ encode_uri_value(Value);
+ App ->
+ encode_integer(App)
+ end
+ end.
+
+decode_accept_application(0, _Version) ->
+ ?WH('Accept-Application', "*", []);
+decode_accept_application(Value, _Version) when integer(Value) ->
+ ?WH('Accept-Application', decode_push_application(Value), []);
+decode_accept_application({short,Data}, _Version) ->
+ Value = d_long(Data),
+ ?WH('Accept-Application', decode_push_application(Value), []);
+decode_accept_application(Value, _Version) when list(Value) ->
+ ?WH('Accept-Application', decode_uri_value(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Bearer-Indication: <integer-value>
+%% Type: sinlge
+%% Ref: 8.4.2.58
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_bearer_indication(Value) ->
+ ?WH('Bearer-Indication', Value, []).
+
+format_bearer_indication(H) ->
+ integer_to_list(H#wsp_header.value).
+
+encode_bearer_indication(H, _Version) ->
+ encode_integer(H#wsp_header.value).
+
+decode_bearer_indication(Value, _Version) when integer(Value) ->
+ ?WH('Bearer-Indication', Value, []);
+decode_bearer_indication({short,Data}, _Version) ->
+ Value = d_long(Data),
+ ?WH('Bearer-Indication', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Push-Flag: Short-Integer
+%% Type: single
+%% Ref: 8.4.2.59
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_push_flag(Value) ->
+ ?WH('Push-Flag', integer_to_list(Value), []).
+
+format_push_flag(H) ->
+ integer_to_list(H#wsp_header.value).
+
+encode_push_flag(H, _Version) ->
+ ?ENCODE_SHORT(H#wsp_header.value).
+
+decode_push_flag(Value, _Version) when integer(Value) ->
+ ?WH('Push-Flag', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Profile: <uri-value>
+%% Ref: 8.4.2.60
+%% Type: single, hop-by-hop, client-to-proxy
+%%
+%% Note: Normally transfered as 'X-Wap-Profile'
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_profile(Value) ->
+ ?WH('Profile', Value, []).
+
+format_profile(H) ->
+ H#wsp_header.value.
+
+encode_profile(H, _Version) ->
+ encode_uri_value(H#wsp_header.value).
+
+decode_profile(Value, _Version) ->
+ ?WH('Profile', decode_uri_value(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Profile-Diff: Value-Length Octets
+%% Ref: 8.4.2.61
+%% Type: single, hop-by-hop, client-to-proxy
+%%
+%% Value is WBXML encoded profile diff information
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_profile_diff(Value) ->
+ %% FIXME parse XML code?
+ ?WH('Profile-Diff', Value, []).
+
+format_profile_diff(_H) ->
+ %% FIXME emit ???
+ "WBXML".
+
+encode_profile_diff(H, _Version) ->
+ e_value(H#wsp_header.value).
+
+decode_profile_diff({_,Value}, _Version) ->
+ ?WH('Profile-Diff', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Profile-Warning: Code
+%% Ref: 8.4.2.62
+%% Type: single
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_profile_warning(Value) ->
+ ?WH('Profile-Warning', {Value,"",undefined}, []).
+
+format_profile_warning(H) ->
+ {Code,Target,Date} = H#wsp_header.value,
+ CodeData = integer_to_list(Code),
+ if Target == "", Date == undefined ->
+ CodeData;
+ Date == undefined ->
+ [CodeData," ",Target];
+ true ->
+ [CodeData," ",Target," ",format_date(Date)]
+ end.
+
+
+encode_profile_warning(H, _Version) ->
+ {Code,Target,Date} = H#wsp_header.value,
+ CodeData = case Code of
+ 100 -> ?ENCODE_SHORT(16#10);
+ 101 -> ?ENCODE_SHORT(16#11);
+ 102 -> ?ENCODE_SHORT(16#12);
+ 200 -> ?ENCODE_SHORT(16#20);
+ 201 -> ?ENCODE_SHORT(16#21);
+ 202 -> ?ENCODE_SHORT(16#22);
+ 203 -> ?ENCODE_SHORT(16#23)
+ end,
+ if Target == "", Date == undefined ->
+ CodeData;
+ Date == undefined ->
+ e_value(CodeData, encode_text_string(Target));
+ true ->
+ e_value(CodeData, encode_text_string(Target), e_date(Date))
+ end.
+
+
+decode_profile_warning(Value, _Version) when integer(Value) ->
+ Code = case Value of
+ 16#10 -> 100;
+ 16#11 -> 101;
+ 16#12 -> 102;
+ 16#20 -> 200;
+ 16#21 -> 201;
+ 16#22 -> 202;
+ 16#23 -> 203
+ end,
+ ?WH('Profile-Warning', {Code,"",undefined}, []);
+decode_profile_warning({_, <<1:1, Value:7, Data>>}, _Version) ->
+ Code = case Value of
+ 16#10 -> 100;
+ 16#11 -> 101;
+ 16#12 -> 102;
+ 16#20 -> 200;
+ 16#21 -> 201;
+ 16#22 -> 202;
+ 16#23 -> 203
+ end,
+ {Target,Data1} = d_text_string(Data),
+ Date =
+ if Data1 == <<>> ->
+ undefined;
+ true ->
+ {DateValue,_} = scan_header_data(Data1),
+ d_date(DateValue)
+ end,
+ ?WH('Profile-Warning', {Code,Target,Date}, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Expect: 100-contine | Expect-expression
+%% Ref: 8.4.2.63
+%% Type: client-to-server
+%% Note: Bug in the spec value-length is missing !!!
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_expect(Value) ->
+ ?WH('Expect', Value, []).
+
+format_expect(H) ->
+ case H#wsp_header.value of
+ {Var,Val} ->
+ [Var,"=",Val, format_params(H#wsp_header.params)];
+ Val when list(Val) ->
+ Val
+ end.
+
+encode_expect(H, Version) ->
+ case H#wsp_header.value of
+ "100-continue" ->
+ ?ENCODE_SHORT(0);
+ {Var,Val} ->
+ e_value(encode_text_string(Var),
+ encode_text_string(Val),
+ encode_params(H#wsp_header.params,Version))
+ end.
+
+decode_expect(0, _Version) ->
+ ?WH('Expect', "100-continue", []);
+decode_expect({_, Data}, Version) ->
+ {Var, Data1} = d_text_string(Data),
+ {Val, Data2} = d_text_string(Data1),
+ Params = decode_params(Data2, Version),
+ ?WH('Expect', {decode_text_string(Var),
+ decode_text_string(Val)}, Params).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Te: Trailers | TE-General-From
+%% Ref: 8.4.2.64
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_te(Value) ->
+ ?WH('Te', Value, []).
+
+format_te(H) ->
+ [H#wsp_header.value, format_params(H#wsp_header.params)].
+
+encode_te(H, Version) ->
+ case H#wsp_header.value of
+ "trailers" -> ?ENCODE_SHORT(1);
+ "chunked" ->
+ e_value(?ENCODE_SHORT(2),
+ encode_params(H#wsp_header.params,Version));
+ "identity" ->
+ e_value(?ENCODE_SHORT(3),
+ encode_params(H#wsp_header.params,Version));
+ "gzip" ->
+ e_value(?ENCODE_SHORT(4),
+ encode_params(H#wsp_header.params,Version));
+ "compress" ->
+ e_value(?ENCODE_SHORT(5),
+ encode_params(H#wsp_header.params,Version));
+ "deflate" ->
+ e_value(?ENCODE_SHORT(6),
+ encode_params(H#wsp_header.params,Version));
+ Value ->
+ e_value(encode_text_string(Value),
+ encode_params(H#wsp_header.params,Version))
+ end.
+
+decode_te(1, _Version) ->
+ ?WH('Te', "trailers", []);
+decode_te({_, Data}, _Version) ->
+ {Val, Data1} = scan_header_data(Data),
+ Value =
+ case Val of
+ 2 -> "chunked";
+ 3 -> "identity";
+ 4 -> "gzip";
+ 5 -> "compress";
+ 6 -> "deflate";
+ V when list(V) -> V
+ end,
+ Params = case Data1 of
+ <<>> -> [];
+ <<128, QData>> ->
+ {QValue, _} = d_q_value(QData),
+ [{q, QValue}]
+ end,
+ ?WH('Te', Value, Params).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Trailer: Well-known-header-field | Token-text
+%% Ref: 8.4.2.65
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_trailer(Value) ->
+ ?WH('Trailer', normalise_field_name(Value), []).
+
+format_trailer(H) ->
+ to_list(H#wsp_header.value).
+
+encode_trailer(H, Version) ->
+ e_field_name(H#wsp_header.value, Version).
+
+decode_trailer(Value, _Version) when integer(Value) ->
+ ?WH('Trailer', lookup_field_name(Value), []);
+decode_trailer(Value, _Version) when list(Value) ->
+ ?WH('Trailer', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% X-Wap-Tod:
+%% Ref: 8.4.2.66
+%% Type: hop-by-hop
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_x_wap_tod(String) ->
+ {DateTime, _} = parse_http_date(String),
+ ?WH('X-Wap-Tod', DateTime, []).
+
+format_x_wap_tod(H) ->
+ fmt_date(H#wsp_header.value).
+
+encode_x_wap_tod(H, _Version) ->
+ e_date(H#wsp_header.value).
+
+decode_x_wap_tod(Value, _Version) ->
+ ?WH('X-Wap-Tod', d_date(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Id: <quoted-string>
+%% Type:
+%% Ref: 8.4.2.67
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_content_id(Value) ->
+ ?WH('Content-Id', Value, []).
+
+format_content_id(H) ->
+ [$", H#wsp_header.value, $"].
+
+encode_content_id(H, _Version) ->
+ encode_quoted_string(H#wsp_header.value).
+
+decode_content_id(Value, _Version) when list(Value) ->
+ ?WH('Content-Id', decode_quoted_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Set-Cookie: <len> <cookie-version> <cookie-name> <cokie-value> <parm>*
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_set_cookie(String) ->
+ %% MEGA FIXME; Cookie-value may be a quoted string and
+ %% contain both ,=; etc Fix several cookies on same line!!
+ case string:tokens(String, ";") of
+ [Cookie | Ps] ->
+ case string:tokens(Cookie, "=") of
+ [Name,Value] ->
+ Params = parse_params(Ps),
+ ?WH('Set-Cookie', {{1,0}, Name, Value}, Params);
+ [Name] ->
+ Params = parse_params(Ps),
+ ?WH('Set-Cookie', {{1,0}, Name, ""}, Params)
+ end;
+ [] ->
+ ?WH('Set-Cookie', {{1,0}, String, ""}, [])
+ end.
+
+format_set_cookie(H) ->
+ case H#wsp_header.value of
+ {{1,0},Name,Value} ->
+ [Name, "=", Value,format_params(H#wsp_header.params)];
+ {Version,Name,Value} ->
+ [format_version(Version)," ",
+ Name, "=", Value,
+ format_params(H#wsp_header.params)]
+ end.
+
+encode_set_cookie(H, Version) ->
+ {CookieVersion,Name,Value} = H#wsp_header.value,
+ e_value(encode_version(CookieVersion),
+ encode_text_string(Name),
+ encode_text_string(Value),
+ encode_params(H#wsp_header.params, Version)).
+
+decode_set_cookie({_, Data}, Version) ->
+ {CookieVersion, Data1} = scan_header_data(Data),
+ {CookieName, Data2} = scan_header_data(Data1),
+ {CookieValue, Data3} = scan_header_data(Data2),
+ Params = decode_params(Data3, Version),
+ ?WH('Set-Cookie', {decode_version(CookieVersion),
+ decode_text_string(CookieName),
+ decode_text_string(CookieValue)}, Params).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Cookie:
+%% Ref: 8.4.2.69
+%% Type: single?, client-to-server
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_cookie(Value) ->
+ %% FIXME parse cookie version etc
+ ?WH('Cookie', {{1,0},Value}, []).
+
+format_cookie(H) ->
+ case H#wsp_header.value of
+ {{1,0}, Cookies} ->
+ lists:map(fun({Name,Value,Ps}) ->
+ [Name,"=",Value, format_params(Ps)]
+ end, Cookies);
+ {Version, Cookies} ->
+ [format_version(Version)," ",
+ lists:map(fun({Name,Value,Ps}) ->
+ [Name,"=",Value, format_params(Ps)]
+ end, Cookies)]
+ end.
+
+encode_cookie(H, Version) ->
+ {Version, Cookies} = H#wsp_header.value,
+ e_value(encode_version(Version),
+ encode_cookies(Cookies, [])).
+
+encode_cookies([{Name,Value,Ps} | Cs], Acc) ->
+ List =
+ [encode_text_string(Name),
+ encode_text_string(Value) |
+ case Ps of
+ [{path,P},{domain,D}] ->
+ [encode_text_string(P), encode_text_string(D)];
+ [{domain,D},{path,P}] ->
+ [encode_text_string(P), encode_text_string(D)];
+ [{path,P}] ->
+ [encode_text_string(P)];
+ [{domain,D}] ->
+ [encode_text_string(""), encode_text_string(D)];
+ [] ->
+ []
+ end],
+ Sz = lists:sum(lists:map(fun(B) -> size(B) end, List)),
+ encode_cookies(Cs, [[e_uintvar(Sz) | List] | Acc]);
+encode_cookies([], Acc) ->
+ list_to_binary(lists:reverse(Acc)).
+
+
+decode_cookie({_, Data}, _Version) ->
+ {CookieVersion, Data1} = scan_header_data(Data),
+ Cookies = decode_cookies(Data1, []),
+ ?WH('Cookie', {decode_version(CookieVersion), Cookies}, []).
+
+decode_cookies(<<>>, Acc) ->
+ lists:reverse(Acc);
+decode_cookies(Data0, _Acc) -> %% IS IGNORING Acc A BUG OR NOT ?
+ {Len, Data1} = d_uintvar(Data0),
+ <<C0:Len/binary, Data2/binary>> = Data1,
+ {Name, C1} = scan_header_data(C0),
+ {Value, C2} = scan_header_data(C1),
+ {Ps1, C3} =
+ case d_text_string(C2) of
+ {"", C21} -> {[], C21};
+ {Path,C21} -> {[{path,Path}], C21}
+ end,
+ {Ps2, _} =
+ case C3 of
+ <<>> -> {[], <<>>};
+ _ ->
+ {Domain,C4} = d_text_string(C3),
+ {[{domain,Domain}], C4}
+ end,
+ decode_cookies(Data2, [{decode_text_string(Name),
+ decode_text_string(Value),
+ Ps1++Ps2}]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Encoding-Version: Version-Value | Value-length Code-Page [Version-Value]
+%% Ref: 8.4.2.70
+%% Type: single, hop-by-hop, client-and-proxys
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_encoding_version(Value) ->
+ ?WH('Encoding-Version', parse_version(Value), []).
+
+format_encoding_version(H) ->
+ format_version(H#wsp_header.value).
+
+encode_encoding_version(H, _Version) ->
+ encode_version(H#wsp_header.value).
+
+decode_encoding_version(Value, _Version) when integer(Value) ->
+ ?WH('Encoding-Version', decode_version(Value), []);
+decode_encoding_version(Value, _Version) when list(Value) ->
+ %% Note: in this case we parse the Value since we
+ %% Must know the Encoding version
+ ?WH('Encoding-Version', parse_version(Value), []);
+decode_encoding_version({_,<<_:1,_CodePage:7>>}, _Version) ->
+ %% ??? FIXME
+ ?WH('Encoding-Version', "", []);
+decode_encoding_version({_,<<_:1,_CodePage:7, Data1/binary>>}, _Version) ->
+ {Value,_Data2} = scan_header_data(Data1),
+ %% FIXME CodePage
+ ?WH('Encoding-Version', decode_version(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% X-Wap-Security:
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_x_wap_security(Value) ->
+ ?WH('X-Wap-Security', Value, []).
+
+format_x_wap_security(H) ->
+ H#wsp_header.value.
+
+encode_x_wap_security(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_x_wap_security(Value, _Version) ->
+ ?WH('X-Wap-Security', decode_text_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% X-Wap-Loc-Invocation:
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_x_wap_loc_invocation(Value) ->
+ ?WH('X-Wap-Loc-Invocation', Value, []).
+
+format_x_wap_loc_invocation(H) ->
+ H#wsp_header.value.
+
+encode_x_wap_loc_invocation(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_x_wap_loc_invocation(Value, _Version) ->
+ ?WH('X-Wap-Loc-Invocation', decode_text_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% X-Wap-Loc-Delivery:
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_x_wap_loc_delivery(Value) ->
+ ?WH('X-Wap-Loc-Delivery', Value, []).
+
+format_x_wap_loc_delivery(H) ->
+ H#wsp_header.value.
+
+encode_x_wap_loc_delivery(H, _Value) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_x_wap_loc_delivery(Value, _Version) ->
+ ?WH('X-Wap-Loc-Delivery', decode_text_string(Value), []).
+
+
+%%
+%% Header Field parameters
+%%
+
+parse_params([Param|Ps]) ->
+ case string:tokens(Param, "=") of
+ [Name,Value0] ->
+ Val = trim(Value0),
+ P = case trim(tolower(Name)) of
+ "q" ->{q,Val};
+ "charset" -> {charset,Val};
+ "level" -> {level,Val};
+ "type" -> {type,Val};
+ "name" -> {name,Val};
+ "filename" -> {filename,Val};
+ "differences" -> {differences,Val};
+ "padding" -> {padding,Val};
+ "start" -> {start,Val};
+ "start-info" -> {'start-info',Val};
+ "comment" -> {comment,Val};
+ "domain" -> {domain,Val};
+ "max-age" -> {'max-age',Val};
+ "path" -> {path,Val};
+ "secure" -> {secure,no_value};
+ "sec" -> {sec, Val};
+ "mac" -> {mac, Val};
+ "creation-date" -> {'creation-date', Val};
+ "modification-date" -> {'modification-date', Val};
+ "read-date" -> {'read-date', Val};
+ "size" -> {size, Val};
+ Nm -> {Nm, Val}
+ end,
+ [P | parse_params(Ps)];
+ _ ->
+ parse_params(Ps)
+ end;
+parse_params([]) ->
+ [].
+
+%% format Params without leading ";"
+format_params0([{Param,no_value}|Ps]) ->
+ [to_list(Param) | format_params(Ps)];
+format_params0([{Param,Value}|Ps]) ->
+ [to_list(Param),"=",to_list(Value) | format_params(Ps)].
+
+format_params(Ps) ->
+ lists:map(fun({Param,no_value}) ->
+ ["; ", to_list(Param)];
+ ({Param,Value})->
+ ["; ", to_list(Param),"=",to_list(Value)]
+ end, Ps).
+
+
+encode_params(Params, Version) ->
+ list_to_binary(encode_params1(Params,Version)).
+
+encode_params1([Param|Ps], Version) ->
+ [ encode_parameter(Param, Version) | encode_params1(Ps, Version)];
+encode_params1([], _Version) ->
+ [].
+
+
+decode_params(Data, Version) ->
+ decode_params(Data, [], Version).
+
+decode_params(<<>>, Ps, _Version) ->
+ lists:reverse(Ps);
+decode_params(Data, Ps, Version) ->
+ {ParamVal, Data1} = decode_parameter(Data, Version),
+ decode_params(Data1, [ParamVal | Ps], Version).
+
+
+
+
+encode_parameter({ParamName, ParamValue}, Ver) ->
+ case ParamName of
+ q when Ver >= 16#01 ->
+ <<1:1, 16#00:7,
+ (encode_typed_field(Ver,'Q-value', ParamValue))/binary>>;
+ charset when Ver >= 16#01 ->
+ <<1:1, 16#01:7,
+ (encode_typed_field(Ver,'Well-known-charset',ParamValue))/binary>>;
+ level when Ver >= 16#01 ->
+ <<1:1, 16#02:7,
+ (encode_typed_field(Ver,'Ver-value',ParamValue))/binary>>;
+
+ type when Ver >= ?WSP_12 ->
+ <<1:1, 16#09:7,
+ (encode_typed_field(Ver,'Constrained-encoding',ParamValue))/binary>>;
+ type when Ver >= 16#01 ->
+ <<1:1, 16#03:7,
+ (encode_typed_field(Ver,'Integer-value',ParamValue))/binary>>;
+
+ name when Ver >= ?WSP_14 ->
+ <<1:1, 16#17:7,
+ (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
+ name when Ver >= 16#01 ->
+ <<1:1, 16#05:7,
+ (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
+
+ filename when Ver >= ?WSP_14 ->
+ <<1:1, 16#18:7,
+ (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
+ filename when Ver >= 16#01 ->
+ <<1:1, 16#06:7,
+ (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
+
+ differences when Ver >= 16#01 ->
+ <<1:1, 16#07:7,
+ (encode_typed_field(Ver,'Field-name',ParamValue))/binary>>;
+
+ padding when Ver >= 16#01 ->
+ <<1:1, 16#08:7,
+ (encode_typed_field(Ver,'Short-integer',ParamValue))/binary>>;
+
+
+ start when Ver >= ?WSP_14 ->
+ <<1:1, 16#19:7,
+ (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
+ start when Ver >= ?WSP_12 ->
+ <<1:1, 16#0A:7,
+ (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
+
+
+ 'start-info' when Ver >= ?WSP_14 ->
+ <<1:1, 16#1A:7,
+ (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
+ 'start-info' when Ver >= ?WSP_12 ->
+ <<1:1, 16#0B:7,
+ (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
+
+ comment when Ver >= ?WSP_14 ->
+ <<1:1, 16#1B:7,
+ (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
+ comment when Ver >= ?WSP_13 ->
+ <<1:1, 16#0C:7,
+ (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
+
+ domain when Ver >= ?WSP_14 ->
+ <<1:1, 16#1C:7,
+ (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
+ domain when Ver >= ?WSP_13 ->
+ <<1:1, 16#0D:7,
+ (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
+
+ 'max-age' when Ver >= ?WSP_13 ->
+ <<1:1, 16#0E:7,
+ (encode_typed_field(Ver,'Delta-seconds-value',ParamValue))/binary>>;
+
+ path when Ver >= ?WSP_14 ->
+ <<1:1, 16#1D:7,
+ (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
+ path when Ver >= ?WSP_13 ->
+ <<1:1, 16#0F:7,
+ (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
+
+ secure when Ver >= ?WSP_13 ->
+ <<1:1, 16#10:7,
+ (encode_typed_field(Ver,'No-value',ParamValue))/binary>>;
+ %% NOTE: "sec" and "mac" are really 1.4 features but used by 1.3 client provisioning
+ %"sec" when Ver >= ?WSP_14 ->
+ sec when Ver >= ?WSP_13 ->
+ <<1:1, 16#11:7,
+ (encode_typed_field(Ver,'Short-integer',ParamValue))/binary>>;
+ %"mac" when Ver >= ?WSP_14 ->
+ mac when Ver >= ?WSP_13 ->
+ <<1:1, 16#12:7,
+ (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
+ 'creation-date' when Ver >= ?WSP_14 ->
+ <<1:1, 16#13:7,
+ (encode_typed_field(Ver,'Date-value',ParamValue))/binary>>;
+ 'modification-date' when Ver >= ?WSP_14 ->
+ <<1:1, 16#14:7,
+ (encode_typed_field(Ver,'Date-value',ParamValue))/binary>>;
+ 'read-date' when Ver >= ?WSP_14 ->
+ <<1:1, 16#15:7,
+ (encode_typed_field(Ver,'Date-value',ParamValue))/binary>>;
+ size when Ver >= ?WSP_14 ->
+ <<1:1, 16#16:7,
+ (encode_typed_field(Ver,'Integer-value',ParamValue))/binary>>;
+ _ ->
+ <<(encode_text_string(ParamName))/binary,
+ (encode_text_string(ParamValue))/binary >>
+ end.
+
+%% decode_parameter: return {ParameterName, ParamterValue}
+decode_parameter(<<1:1,Code:7,Data/binary>>, Version) ->
+ case Code of
+ 16#00 ->
+ {Val,Data1} = decode_typed_field('Q-value', Data, Version),
+ {{ q, Val}, Data1};
+
+ 16#01 ->
+ {Val,Data1} = decode_typed_field('Well-known-charset',Data,Version),
+ {{charset, Val}, Data1};
+
+ 16#02 ->
+ {Val,Data1} = decode_typed_field('Version-value',Data,Version),
+ {{level, Val}, Data1};
+
+ 16#03 ->
+ {Val,Data1} = decode_typed_field('Integer-value', Data,Version),
+ {{type, Val}, Data1};
+
+ 16#05 ->
+ {Val,Data1} = decode_typed_field('Text-string', Data,Version),
+ {{name, Val}, Data1};
+
+ 16#06 ->
+ {Val,Data1} = decode_typed_field('Text-string', Data,Version),
+ {{filename, Val}, Data1};
+
+ 16#07 ->
+ {Val,Data1} = decode_typed_field('Field-name', Data,Version),
+ {{differences, Val}, Data1};
+
+ 16#08 ->
+ {Val,Data1} = decode_typed_field('Short-integer', Data,Version),
+ {{padding, Val}, Data1};
+
+ 16#09 ->
+ {Val,Data1} = decode_typed_field('Constrained-encoding', Data,Version),
+ {{type, Val}, Data1};
+
+ 16#0A ->
+ {Val,Data1} = decode_typed_field('Text-string', Data,Version),
+ {{start, Val}, Data1};
+
+ 16#0B ->
+ {Val,Data1} = decode_typed_field('Text-string', Data,Version),
+ {{'start-info', Val}, Data1};
+
+ 16#0C ->
+ {Val,Data1} = decode_typed_field('Text-string', Data,Version),
+ {{comment, Val}, Data1};
+
+ 16#0D ->
+ {Val,Data1} = decode_typed_field('Text-string', Data,Version),
+ {{domain, Val}, Data1};
+
+ 16#0E ->
+ {Val,Data1} = decode_typed_field('Delta-seconds-value', Data,Version),
+ {{'max-age', Val}, Data1};
+
+ 16#0F ->
+ {Val,Data1} = decode_typed_field('Text-string', Data,Version),
+ {{path, Val}, Data1};
+
+ 16#10 ->
+ {Val,Data1} = decode_typed_field('No-value', Data,Version),
+ {{secure, Val}, Data1};
+
+ 16#11 ->
+ {Val,Data1} = decode_typed_field('Short-integer', Data,Version),
+ {{sec, Val}, Data1};
+
+ 16#12 ->
+ {Val,Data1} = decode_typed_field('Text-value', Data,Version),
+ {{mac, Val}, Data1};
+
+ 16#13 ->
+ {Val,Data1} = decode_typed_field('Date-value', Data,Version),
+ {{'creation-date', Val}, Data1};
+
+ 16#14 ->
+ {Val,Data1} = decode_typed_field('Date-value', Data,Version),
+ {{'modification-date', Val}, Data1};
+
+ 16#15 ->
+ {Val,Data1} = decode_typed_field('Date-value', Data,Version),
+ {{'read-date', Val}, Data1};
+
+ 16#16 ->
+ {Val,Data1} = decode_typed_field('Integer-value', Data,Version),
+ {{size, Val}, Data1};
+
+ 16#17 ->
+ {Val,Data1} = decode_typed_field('Text-value', Data,Version),
+ {{name, Val}, Data1};
+
+ 16#18 ->
+ {Val,Data1} = decode_typed_field('Text-value', Data,Version),
+ {{filename, Val}, Data1};
+
+ 16#19 ->
+ {Val,Data1} = decode_typed_field('Text-value', Data,Version),
+ {{start, Val}, Data1};
+
+ 16#1A ->
+ {Val,Data1} = decode_typed_field('Text-value', Data,Version),
+ {{'start-info', Val}, Data1};
+
+ 16#1B ->
+ {Val,Data1} = decode_typed_field('Text-value', Data,Version),
+ {{comment, Val}, Data1};
+
+ 16#1C ->
+ {Val,Data1} = decode_typed_field('Text-value', Data,Version),
+ {{domain, Val}, Data1};
+
+ 16#1D ->
+ {Val,Data1} = decode_typed_field('Text-value', Data,Version),
+ {{path, Val}, Data1};
+ _ ->
+ exit({error, unknown_parameter})
+ end;
+decode_parameter(Data, _Version) ->
+ %% Untyped-parameter: Token-Text Untype-value
+ {ParamName,Data1} = d_text_string(Data),
+ %% Untype-value: Integer-Value | Text-Value!
+ {ParamValue, Data2} = decode_untyped_value(Data1),
+ {{ParamName,ParamValue}, Data2}.
+
+
+encode_typed_field(Ver,Type,Value) ->
+ case Type of
+ 'Well-known-charset' ->
+ MIBenum = encode_charset(Value),
+ encode_integer(MIBenum);
+
+ 'Constrained-encoding' ->
+ encode_constrained_media(Value, Ver);
+
+ 'Text-string' ->
+ encode_text_string(Value);
+
+ 'Text-value' ->
+ encode_text_value(Value);
+
+ 'Short-integer' ->
+ ?ENCODE_SHORT(Value);
+
+ 'Date-value' ->
+ e_date(Value);
+
+ 'Delta-Seconds-value' ->
+ e_delta_seconds(Value);
+
+ 'No-value' ->
+ e_no_value(Value);
+
+ _ ->
+ io:format("FIXME: encode_typed_field unsupported type = ~p\n",
+ [Type]),
+ exit({error,badtype})
+ end.
+
+
+decode_typed_field(Type, Data, Version) ->
+ case Type of
+ 'Q-value' ->
+ d_q_value(Data);
+
+ 'Well-known-charset' ->
+ {MIBenum, T100} = d_integer_value(Data),
+ {decode_charset(MIBenum), T100};
+
+ 'Constrained-encoding' ->
+ {Value, Data1} = scan_header_data(Data),
+ {decode_constrained_media(Value,Version), Data1};
+
+ 'Text-string' ->
+ d_text_string(Data);
+
+ 'Text-value' ->
+ d_text_value(Data);
+
+ 'Short-integer' ->
+ decode_short_integer(Data);
+
+ 'Delta-seconds-value' ->
+ d_integer_value(Data);
+
+ 'Date-value' ->
+ {Val, Data1} = decode_long_integer(Data),
+ {d_date(Val), Data1};
+
+ 'Field-name' ->
+ d_field_name(Data);
+
+ 'No-value' ->
+ d_no_value(Data);
+
+ _ ->
+ io:format("FIXME: unsupported type = ~p\n",[Type]),
+ exit({error,badtype})
+ end.
+
+
+%% Integer-Value | Text-Value
+%% return as {Value, Tail}
+decode_untyped_value(<<1:1, Short:7, Tail/binary>>) ->
+ {Short, Tail};
+decode_untyped_value(<<0:3, Len:5, Data/binary>>) when Len =/= 31 ->
+ Sz = Len*8,
+ <<Long:Sz, Tail/binary>> = Data,
+ {Long, Tail};
+decode_untyped_value(Data) ->
+ d_text_string(Data).
+
+
+e_field_name(Value, Version) ->
+ case normalise_field_name(Value) of
+ 'Accept' -> <<16#80>>;
+ 'Accept-Charset' when Version >= ?WSP_13 -> <<16#bb>>;
+ 'Accept-Charset' -> <<16#81>>;
+ 'Accept-Encoding' when Version >= ?WSP_13 -> <<16#bc>>;
+ 'Accept-Encoding' -> <<16#82>>;
+ 'Accept-Language' -> <<16#83>>;
+ 'Accept-Ranges' -> <<16#84>>;
+ 'Age' -> <<16#85>>;
+ 'Allow' -> <<16#86>>;
+ 'Authorization' -> <<16#87>>;
+ 'Cache-Control' when Version >= ?WSP_14 -> <<16#c7>>;
+ 'Cache-Control' when Version >= ?WSP_13 -> <<16#bd>>;
+ 'Cache-Control' -> <<16#88>>;
+ 'Connection' -> <<16#89>>;
+ 'Content-Base' -> <<16#8a>>;
+ 'Content-Encoding' -> <<16#8b>>;
+ 'Content-Language' -> <<16#8c>>;
+ 'Content-Length' -> <<16#8d>>;
+ 'Content-Location' -> <<16#8e>>;
+ 'Content-Md5' -> <<16#8f>>;
+ 'Content-Range' when Version >= ?WSP_13 -> <<16#be>>;
+ 'Content-Range' -> <<16#90>>;
+ 'Content-Type' -> <<16#91>>;
+ 'Date' -> <<16#92>>;
+ 'Etag' -> <<16#93>>;
+ 'Expires' -> <<16#94>>;
+ 'From' -> <<16#95>>;
+ 'Host' -> <<16#96>>;
+ 'If-Modified-Since' -> <<16#97>>;
+ 'If-Match' -> <<16#98>>;
+ 'If-None-Match' -> <<16#99>>;
+ 'If-Range' -> <<16#9a>>;
+ 'If-Unmodified-Since' -> <<16#9b>>;
+ 'Location' -> <<16#9c>>;
+ 'Last-Modified' -> <<16#9d>>;
+ 'Max-Forwards' -> <<16#9e>>;
+ 'Pragma' -> <<16#9f>>;
+ 'Proxy-Authenticate' -> <<16#a0>>;
+ 'Proxy-Authorization' -> <<16#a1>>;
+ 'Public' -> <<16#a2>>;
+ 'Range' -> <<16#a3>>;
+ 'Referer' -> <<16#a4>>;
+ 'Retry-After' -> <<16#a5>>;
+ 'Server' -> <<16#a6>>;
+ 'Transfer-Encoding' -> <<16#a7>>;
+ 'Upgrade' -> <<16#a8>>;
+ 'User-Agent' -> <<16#a9>>;
+ 'Vary' -> <<16#aa>>;
+ 'Via' -> <<16#ab>>;
+ 'Warning' -> <<16#ac>>;
+ 'Www-Authenticate' -> <<16#ad>>;
+ 'Content-Disposition' when Version >= ?WSP_14 -> <<16#c5>>;
+ 'Content-Disposition' -> <<16#ae>>;
+ %% VERSION > 1.1
+ 'X-Wap-Application-Id' when Version >= ?WSP_12 -> <<16#af>>;
+ 'X-Wap-Content-Uri' when Version >= ?WSP_12 -> <<16#b0>>;
+ 'X-Wap-Initiator-Uri' when Version >= ?WSP_12 -> <<16#b1>>;
+ 'Accept-Application' when Version >= ?WSP_12 -> <<16#b2>>;
+ 'Bearer-Indication' when Version >= ?WSP_12 -> <<16#b3>>;
+ 'Push-Flag' when Version >= ?WSP_12 -> <<16#b4>>;
+ 'Profile' when Version >= ?WSP_12 -> <<16#b5>>;
+ 'Profile-Diff' when Version >= ?WSP_12 -> <<16#b6>>;
+ 'Profile-Warning' when Version >= ?WSP_12 -> <<16#b7>>;
+ 'Expect' when Version >= ?WSP_15 -> <<16#c8>>;
+ 'Expect' when Version >= ?WSP_13 -> <<16#b8>>;
+ 'Te' when Version >= ?WSP_13 -> <<16#b9>>;
+ 'Trailer' when Version >= ?WSP_13 -> <<16#ba>>;
+ 'X-Wap-Tod' when Version >= ?WSP_13 -> <<16#bf>>;
+ 'Content-Id' when Version >= ?WSP_13 -> <<16#c0>>;
+ 'Set-Cookie' when Version >= ?WSP_13 -> <<16#c1>>;
+ 'Cookie' when Version >= ?WSP_13 -> <<16#c2>>;
+ 'Encoding-Version' when Version >= ?WSP_13 -> <<16#c3>>;
+ 'Profile-Warning' when Version >= ?WSP_14 -> <<16#c4>>;
+ 'X-Wap-Security' when Version >= ?WSP_14 -> <<16#c6>>;
+ 'X-Wap-Loc-Invocation' when Version >= ?WSP_15 -> <<16#c9>>;
+ 'X-Wap-Loc-Delivery' when Version >= ?WSP_15 -> <<16#ca>>;
+ Field -> encode_text_string(atom_to_list(Field))
+ end.
+
+
+%%
+%% decode and normalise on form list_to_atom("Ulll-Ulll-Ull")
+%%
+normalise_field_name(Cs) when atom(Cs) ->
+ Cs;
+normalise_field_name(Cs) ->
+ list_to_atom(normalise_fieldU(Cs)).
+
+normalise_fieldU([C|Cs]) when C >= $a, C =< $z ->
+ [(C-$a)+$A | normalise_fieldL(Cs)];
+normalise_fieldU([C|Cs]) -> [ C | normalise_fieldL(Cs)];
+normalise_fieldU([]) -> [].
+
+normalise_fieldL([C|Cs]) when C >= $A, C =< $Z ->
+ [(C-$A)+$a | normalise_fieldL(Cs)];
+normalise_fieldL([$-|Cs]) -> [$- | normalise_fieldU(Cs)];
+normalise_fieldL([C|Cs]) -> [C | normalise_fieldL(Cs)];
+normalise_fieldL([]) -> [].
+
+
+tolower([C|Cs]) when C >= $A, C =< $Z ->
+ [(C-$A)+$a | tolower(Cs)];
+tolower([C|Cs]) -> [C|tolower(Cs)];
+tolower([]) -> [].
+
+trim(Cs) ->
+ lists:reverse(trim1(lists:reverse(trim1(Cs)))).
+
+trim1([$\s|Cs]) -> trim1(Cs);
+trim1([$\t|Cs]) -> trim1(Cs);
+trim1([$\r|Cs]) -> trim1(Cs);
+trim1([$\n|Cs]) -> trim1(Cs);
+trim1(Cs) -> Cs.
+
+
+d_field_name(Data) ->
+ case scan_header_data(Data) of
+ {Code, Data1} when integer(Code) ->
+ {lookup_field_name(Code), Data1};
+ {TmpField,Data1} when list(TmpField) ->
+ {normalise_field_name(TmpField), Data1}
+ end.
+
+d_no_value(<<0, Data/binary>>) ->
+ {no_value, Data}.
+
+e_no_value(_) ->
+ <<0>>.
+
+
+lookup_field_name(Code) ->
+ case Code of
+%%% Version 1.1
+ 16#00 -> 'Accept';
+ 16#01 -> 'Accept-Charset';
+ 16#02 -> 'Accept-Encoding';
+ 16#03 -> 'Accept-Language';
+ 16#04 -> 'Accept-Ranges';
+ 16#05 -> 'Age';
+ 16#06 -> 'Allow';
+ 16#07 -> 'Authorization';
+ 16#08 -> 'Cache-Control';
+ 16#09 -> 'Connection';
+ 16#0a -> 'Content-Base';
+ 16#0b -> 'Content-Encoding';
+ 16#0c -> 'Content-Language';
+ 16#0d -> 'Content-Length';
+ 16#0e -> 'Content-Location';
+ 16#0f -> 'Content-Md5';
+ 16#10 -> 'Content-Range';
+ 16#11 -> 'Content-Type';
+ 16#12 -> 'Date';
+ 16#13 -> 'Etag';
+ 16#14 -> 'Expires';
+ 16#15 -> 'From';
+ 16#16 -> 'Host';
+ 16#17 -> 'If-Modified-Since';
+ 16#18 -> 'If-Match';
+ 16#19 -> 'If-None-Match';
+ 16#1a -> 'If-Range';
+ 16#1b -> 'If-Unmodified-Since';
+ 16#1c -> 'Location';
+ 16#1d -> 'Last-Modified';
+ 16#1e -> 'Max-Forwards';
+ 16#1f -> 'Pragma';
+ 16#20 -> 'Proxy-Authenticate';
+ 16#21 -> 'Proxy-Authorization';
+ 16#22 -> 'Public';
+ 16#23 -> 'Range';
+ 16#24 -> 'Referer';
+ 16#25 -> 'Retry-After';
+ 16#26 -> 'Server';
+ 16#27 -> 'Transfer-Encoding';
+ 16#28 -> 'Upgrade';
+ 16#29 -> 'User-Agent';
+ 16#2a -> 'Vary';
+ 16#2b -> 'Via';
+ 16#2c -> 'Warning';
+ 16#2d -> 'Www-Authenticate';
+ 16#2e -> 'Content-Disposition';
+%%% Version 1.2
+ 16#2f -> 'X-Wap-Application-Id';
+ 16#30 -> 'X-Wap-Content-Uri';
+ 16#31 -> 'X-Wap-Initiator-Uri';
+ 16#32 -> 'Accept-Application';
+ 16#33 -> 'Bearer-Indication';
+ 16#34 -> 'Push-Flag';
+ 16#35 -> 'Profile';
+ 16#36 -> 'Profile-Diff';
+ 16#37 -> 'Profile-Warning';
+%%% Version 1.3
+ 16#38 -> 'Expect';
+ 16#39 -> 'Te';
+ 16#3a -> 'Trailer';
+ 16#3b -> 'Accept-Charset';
+ 16#3c -> 'Accept-Encoding';
+ 16#3d -> 'Cache-Control';
+ 16#3e -> 'Content-Range';
+ 16#3f -> 'X-Wap-Tod';
+ 16#40 -> 'Content-Id';
+ 16#41 -> 'Set-Cookie';
+ 16#42 -> 'Cookie';
+ 16#43 -> 'Encoding-Version';
+%%% Version 1.4
+ 16#44 -> 'Profile-Warning';
+ 16#45 -> 'Content-Disposition';
+ 16#46 -> 'X-Wap-Security';
+ 16#47 -> 'Cache-Control';
+%%% Version 1.5
+ 16#48 -> 'Expect';
+ 16#49 -> 'X-Wap-Loc-Invocation';
+ 16#4a -> 'X-Wap-Loc-Delivery';
+%% Unknown
+ _ ->
+ list_to_atom("X-Unknown-"++erlang:integer_to_list(Code, 16))
+ end.
+
+
+encode_charset(Charset) ->
+ %% FIXME: we should really resolve aliases as well
+ %% charset:from_aliases(Charset)
+ case charset:from_mime_name(Charset) of
+ 0 -> exit({error, unknown_charset});
+ MIBenum -> MIBenum
+ end.
+
+encode_language(Language) ->
+ Code = encode_lang(tolower(Language)),
+ <<Code>>.
+
+
+
+decode_charset(MIBenum) ->
+ case charset:to_mime_name(MIBenum) of
+ undefined ->
+ exit({error, unknown_charset});
+ Preferred ->
+ Preferred
+ end.
+
+%% ISO 639 Language Assignments, Appendix A, Table 41, Page 102-103
+decode_lang(Code) ->
+ case lookup_language(Code) of
+ [L|_] -> atom_to_list(L);
+ [] -> ""
+ end.
+
+
+lookup_language(Code) ->
+ case Code of
+ 16#01 -> ['aa','afar'];
+ 16#02 -> ['ab','abkhazian'];
+ 16#03 -> ['af','afrikans'];
+ 16#04 -> ['am','amharic'];
+ 16#05 -> ['ar','arabic'];
+ 16#06 -> ['as','assamese'];
+ 16#07 -> ['ay','aymara'];
+ 16#08 -> ['az','azerbaijani'];
+ 16#09 -> ['ba','bashkir'];
+ 16#0a -> ['be','byelorussian'];
+ 16#0b -> ['bg','bulgarian'];
+ 16#0c -> ['bh','bihari'];
+ 16#0d -> ['bi','bislama'];
+ 16#0e -> ['bn','bangla','bengali'];
+ 16#0f -> ['bo','tibetan'];
+ 16#10 -> ['br','breton'];
+ 16#11 -> ['ca','catalan'];
+ 16#12 -> ['co','corsican'];
+ 16#13 -> ['cs','czech'];
+ 16#14 -> ['cy','welsh'];
+ 16#15 -> ['da','danish'];
+ 16#16 -> ['de','german'];
+ 16#17 -> ['dz','bhutani'];
+ 16#18 -> ['el','greek'];
+ 16#19 -> ['en','english'];
+ 16#1a -> ['eo','esperanto'];
+ 16#1b -> ['es','spanish'];
+ 16#1c -> ['et','estonian'];
+ 16#1d -> ['eu','basque'];
+ 16#1e -> ['fa','persian'];
+ 16#1f -> ['fi','finnish'];
+ 16#20 -> ['fj','fiji'];
+ 16#82 -> ['fo','faeroese'];
+ 16#22 -> ['fr','french'];
+ 16#83 -> ['fy','frisian'];
+ 16#24 -> ['ga','irish'];
+ 16#25 -> ['gd','scots-gaelic'];
+ 16#26 -> ['gl','galician'];
+ 16#27 -> ['gn','guarani'];
+ 16#28 -> ['gu','gujarati'];
+ 16#29 -> ['ha','hausa'];
+ 16#2a -> ['he','hebrew'];
+ 16#2b -> ['hi','hindi'];
+ 16#2c -> ['hr','croatian'];
+ 16#2d -> ['hu','hungarian'];
+ 16#2e -> ['hy','armenian'];
+ 16#84 -> ['ia','interlingua'];
+ 16#30 -> ['id','indonesian'];
+ 16#86 -> ['ie','interlingue'];
+ 16#87 -> ['ik','inupiak'];
+ 16#33 -> ['is','icelandic'];
+ 16#34 -> ['it','italian'];
+ 16#89 -> ['iu','inuktitut'];
+ 16#36 -> ['ja','japanese'];
+ 16#37 -> ['jw','javanese'];
+ 16#38 -> ['ka','georgian'];
+ 16#39 -> ['kk','kazakh'];
+ 16#8a -> ['kl','greenlandic'];
+ 16#3b -> ['km','cambodian'];
+ 16#3c -> ['kn','kannada'];
+ 16#3d -> ['ko','korean'];
+ 16#3e -> ['ks','kashmiri'];
+ 16#3f -> ['ku','kurdish'];
+ 16#40 -> ['ky','kirghiz'];
+ 16#8b -> ['la','latin'];
+ 16#42 -> ['ln','lingala'];
+ 16#43 -> ['lo','laothian'];
+ 16#44 -> ['lt','lithuanian'];
+ 16#45 -> ['lv','lettish','latvian'];
+ 16#46 -> ['mg','malagese'];
+ 16#47 -> ['mi','maori'];
+ 16#48 -> ['mk','macedonian'];
+ 16#49 -> ['ml','malayalam'];
+ 16#4a -> ['mn','mongolian'];
+ 16#4b -> ['mo','moldavian'];
+ 16#4c -> ['mr','marathi'];
+ 16#4d -> ['ms','malay'];
+ 16#4e -> ['mt','maltese'];
+ 16#4f -> ['my','burmese'];
+ 16#81 -> ['na','nauru'];
+ 16#51 -> ['ne','nepali'];
+ 16#52 -> ['nl','dutch'];
+ 16#53 -> ['no','norwegian'];
+ 16#54 -> ['oc','occitan'];
+ 16#55 -> ['om','oromo'];
+ 16#56 -> ['or','oriya'];
+ 16#57 -> ['pa','punjabi'];
+ 16#58 -> ['po','polish'];
+ 16#59 -> ['ps','pushto','pashto'];
+ 16#5a -> ['pt','portugese'];
+ 16#5b -> ['qu','quechua'];
+ 16#8c -> ['rm','rhaeto-romance'];
+ 16#5d -> ['rn','kirundi'];
+ 16#5e -> ['ro','romanian'];
+ 16#5f -> ['ru','russian'];
+ 16#60 -> ['rw','kinyarwanda'];
+ 16#61 -> ['sa','sanskrit'];
+ 16#62 -> ['sd','sindhi'];
+ 16#63 -> ['sg','sangho'];
+ 16#64 -> ['sh','serbo-croatian'];
+ 16#65 -> ['si','sinhalese'];
+ 16#66 -> ['sk','slovak'];
+ 16#67 -> ['sl','slovenian'];
+ 16#68 -> ['sm','samoan'];
+ 16#69 -> ['sn','shona'];
+ 16#6a -> ['so','somali'];
+ 16#6b -> ['sq','albanian'];
+ 16#6c -> ['sr','serbian'];
+ 16#6d -> ['ss','siswati'];
+ 16#6e -> ['st','seshoto'];
+ 16#6f -> ['su','sundanese'];
+ 16#70 -> ['sv','swedish'];
+ 16#71 -> ['sw','swahili'];
+ 16#72 -> ['ta','tamil'];
+ 16#73 -> ['te','telugu'];
+ 16#74 -> ['tg','tajik'];
+ 16#75 -> ['th','thai'];
+ 16#76 -> ['ti','tigrinya'];
+ 16#77 -> ['tk','turkmen'];
+ 16#78 -> ['tl','tagalog'];
+ 16#79 -> ['tn','setswana'];
+ 16#7a -> ['to','tonga'];
+ 16#7b -> ['tr','turkish'];
+ 16#7c -> ['ts','tsonga'];
+ 16#7d -> ['tt','tatar'];
+ 16#7e -> ['tw','twi'];
+ 16#7f -> ['ug','uighur'];
+ 16#50 -> ['uk','ukrainian'];
+ 16#21 -> ['ur','urdu'];
+ 16#23 -> ['uz','uzbek'];
+ 16#2f -> ['vi','vietnamese'];
+ 16#85 -> ['vo','volapuk'];
+ 16#31 -> ['wo','wolof'];
+ 16#32 -> ['xh','xhosa'];
+ 16#88 -> ['yi','yiddish'];
+ 16#35 -> ['yo','yoruba'];
+ 16#3a -> ['za','zhuang'];
+ 16#41 -> ['zh','chinese'];
+ 16#5c -> ['zu','zulu'];
+ _ -> []
+ end.
+
+encode_lang(Language) ->
+ case tolower(Language) of
+ "aa" -> 16#01;
+ "afar" -> 16#01;
+ "ab" -> 16#02;
+ "abkhazian" -> 16#02;
+ "af" -> 16#03;
+ "afrikans" -> 16#03;
+ "am" -> 16#04;
+ "amharic" -> 16#04;
+ "ar" -> 16#05;
+ "arabic" -> 16#05;
+ "as" -> 16#06;
+ "assamese" -> 16#06;
+ "ay" -> 16#07;
+ "aymara" -> 16#07;
+ "az" -> 16#08;
+ "azerbaijani" -> 16#08;
+ "ba" -> 16#09;
+ "bashkir" -> 16#09;
+ "be" -> 16#0a;
+ "byelorussian" -> 16#0a;
+ "bg" -> 16#0b;
+ "bulgarian" -> 16#0b;
+ "bh" -> 16#0c;
+ "bihari" -> 16#0c;
+ "bi" -> 16#0d;
+ "bislama" -> 16#0d;
+ "bn" -> 16#0e;
+ "bangla" -> 16#0e;
+ "bengali" -> 16#0e;
+ "bo" -> 16#0f;
+ "tibetan" -> 16#0f;
+ "br" -> 16#10;
+ "breton" -> 16#10;
+ "ca" -> 16#11;
+ "catalan" -> 16#11;
+ "co" -> 16#12;
+ "corsican" -> 16#12;
+ "cs" -> 16#13;
+ "czech" -> 16#13;
+ "cy" -> 16#14;
+ "welsh" -> 16#14;
+ "da" -> 16#15;
+ "danish" -> 16#15;
+ "de" -> 16#16;
+ "german" -> 16#16;
+ "dz" -> 16#17;
+ "bhutani" -> 16#17;
+ "el" -> 16#18;
+ "greek" -> 16#18;
+ "en" -> 16#19;
+ "english" -> 16#19;
+ "eo" -> 16#1a;
+ "esperanto" -> 16#1a;
+ "es" -> 16#1b;
+ "spanish" -> 16#1b;
+ "et" -> 16#1c;
+ "estonian" -> 16#1c;
+ "eu" -> 16#1d;
+ "basque" -> 16#1d;
+ "fa" -> 16#1e;
+ "persian" -> 16#1e;
+ "fi" -> 16#1f;
+ "finnish" -> 16#1f;
+ "fj" -> 16#20;
+ "fiji" -> 16#20;
+ "fo" -> 16#82;
+ "faeroese" -> 16#82;
+ "fr" -> 16#22;
+ "french" -> 16#22;
+ "fy" -> 16#83;
+ "frisian" -> 16#83;
+ "ga" -> 16#24;
+ "irish" -> 16#24;
+ "gd" -> 16#25;
+ "scots-gaelic" -> 16#25;
+ "gl" -> 16#26;
+ "galician" -> 16#26;
+ "gn" -> 16#27;
+ "guarani" -> 16#27;
+ "gu" -> 16#28;
+ "gujarati" -> 16#28;
+ "ha" -> 16#29;
+ "hausa" -> 16#29;
+ "he" -> 16#2a;
+ "hebrew" -> 16#2a;
+ "hi" -> 16#2b;
+ "hindi" -> 16#2b;
+ "hr" -> 16#2c;
+ "croatian" -> 16#2c;
+ "hu" -> 16#2d;
+ "hungarian" -> 16#2d;
+ "hy" -> 16#2e;
+ "armenian" -> 16#2e;
+ "ia" -> 16#84;
+ "interlingua" -> 16#84;
+ "id" -> 16#30;
+ "indonesian" -> 16#30;
+ "ie" -> 16#86;
+ "interlingue" -> 16#86;
+ "ik" -> 16#87;
+ "inupiak" -> 16#87;
+ "is" -> 16#33;
+ "icelandic" -> 16#33;
+ "it" -> 16#34;
+ "italian" -> 16#34;
+ "iu" -> 16#89;
+ "inuktitut" -> 16#89;
+ "ja" -> 16#36;
+ "japanese" -> 16#36;
+ "jw" -> 16#37;
+ "javanese" -> 16#37;
+ "ka" -> 16#38;
+ "georgian" -> 16#38;
+ "kk" -> 16#39;
+ "kazakh" -> 16#39;
+ "kl" -> 16#8a;
+ "greenlandic" -> 16#8a;
+ "km" -> 16#3b;
+ "cambodian" -> 16#3b;
+ "kn" -> 16#3c;
+ "kannada" -> 16#3c;
+ "ko" -> 16#3d;
+ "korean" -> 16#3d;
+ "ks" -> 16#3e;
+ "kashmiri" -> 16#3e;
+ "ku" -> 16#3f;
+ "kurdish" -> 16#3f;
+ "ky" -> 16#40;
+ "kirghiz" -> 16#40;
+ "la" -> 16#8b;
+ "latin" -> 16#8b;
+ "ln" -> 16#42;
+ "lingala" -> 16#42;
+ "lo" -> 16#43;
+ "laothian" -> 16#43;
+ "lt" -> 16#44;
+ "lithuanian" -> 16#44;
+ "lv" -> 16#45;
+ "lettish" -> 16#45;
+ "latvian" -> 16#45;
+ "mg" -> 16#46;
+ "malagese" -> 16#46;
+ "mi" -> 16#47;
+ "maori" -> 16#47;
+ "mk" -> 16#48;
+ "macedonian" -> 16#48;
+ "ml" -> 16#49;
+ "malayalam" -> 16#49;
+ "mn" -> 16#4a;
+ "mongolian" -> 16#4a;
+ "mo" -> 16#4b;
+ "moldavian" -> 16#4b;
+ "mr" -> 16#4c;
+ "marathi" -> 16#4c;
+ "ms" -> 16#4d;
+ "malay" -> 16#4d;
+ "mt" -> 16#4e;
+ "maltese" -> 16#4e;
+ "my" -> 16#4f;
+ "burmese" -> 16#4f;
+ "na" -> 16#81;
+ "nauru" -> 16#81;
+ "ne" -> 16#51;
+ "nepali" -> 16#51;
+ "nl" -> 16#52;
+ "dutch" -> 16#52;
+ "no" -> 16#53;
+ "norwegian" -> 16#53;
+ "oc" -> 16#54;
+ "occitan" -> 16#54;
+ "om" -> 16#55;
+ "oromo" -> 16#55;
+ "or" -> 16#56;
+ "oriya" -> 16#56;
+ "pa" -> 16#57;
+ "punjabi" -> 16#57;
+ "po" -> 16#58;
+ "polish" -> 16#58;
+ "ps" -> 16#59;
+ "pushto" -> 16#59;
+ "pt" -> 16#5a;
+ "portugese" -> 16#5a;
+ "qu" -> 16#5b;
+ "quechua" -> 16#5b;
+ "rm" -> 16#8c;
+ "rhaeto-romance" -> 16#8c;
+ "rn" -> 16#5d;
+ "kirundi" -> 16#5d;
+ "ro" -> 16#5e;
+ "romanian" -> 16#5e;
+ "ru" -> 16#5f;
+ "russian" -> 16#5f;
+ "rw" -> 16#60;
+ "kinyarwanda" -> 16#60;
+ "sa" -> 16#61;
+ "sanskrit" -> 16#61;
+ "sd" -> 16#62;
+ "sindhi" -> 16#62;
+ "sg" -> 16#63;
+ "sangho" -> 16#63;
+ "sh" -> 16#64;
+ "serbo-croatian" -> 16#64;
+ "si" -> 16#65;
+ "sinhalese" -> 16#65;
+ "sk" -> 16#66;
+ "slovak" -> 16#66;
+ "sl" -> 16#67;
+ "slovenian" -> 16#67;
+ "sm" -> 16#68;
+ "samoan" -> 16#68;
+ "sn" -> 16#69;
+ "shona" -> 16#69;
+ "so" -> 16#6a;
+ "somali" -> 16#6a;
+ "sq" -> 16#6b;
+ "albanian" -> 16#6b;
+ "sr" -> 16#6c;
+ "serbian" -> 16#6c;
+ "ss" -> 16#6d;
+ "siswati" -> 16#6d;
+ "st" -> 16#6e;
+ "seshoto" -> 16#6e;
+ "su" -> 16#6f;
+ "sundanese" -> 16#6f;
+ "sv" -> 16#70;
+ "swedish" -> 16#70;
+ "sw" -> 16#71;
+ "swahili" -> 16#71;
+ "ta" -> 16#72;
+ "tamil" -> 16#72;
+ "te" -> 16#73;
+ "telugu" -> 16#73;
+ "tg" -> 16#74;
+ "tajik" -> 16#74;
+ "th" -> 16#75;
+ "thai" -> 16#75;
+ "ti" -> 16#76;
+ "tigrinya" -> 16#76;
+ "tk" -> 16#77;
+ "turkmen" -> 16#77;
+ "tl" -> 16#78;
+ "tagalog" -> 16#78;
+ "tn" -> 16#79;
+ "setswana" -> 16#79;
+ "to" -> 16#7a;
+ "tonga" -> 16#7a;
+ "tr" -> 16#7b;
+ "turkish" -> 16#7b;
+ "ts" -> 16#7c;
+ "tsonga" -> 16#7c;
+ "tt" -> 16#7d;
+ "tatar" -> 16#7d;
+ "tw" -> 16#7e;
+ "twi" -> 16#7e;
+ "ug" -> 16#7f;
+ "uighur" -> 16#7f;
+ "uk" -> 16#50;
+ "ukrainian" -> 16#50;
+ "ur" -> 16#21;
+ "urdu" -> 16#21;
+ "uz" -> 16#23;
+ "uzbek" -> 16#23;
+ "vi" -> 16#2f;
+ "vietnamese" -> 16#2f;
+ "vo" -> 16#85;
+ "volapuk" -> 16#85;
+ "wo" -> 16#31;
+ "wolof" -> 16#31;
+ "xh" -> 16#32;
+ "xhosa" -> 16#32;
+ "yi" -> 16#88;
+ "yiddish" -> 16#88;
+ "yo" -> 16#35;
+ "yoruba" -> 16#35;
+ "za" -> 16#3a;
+ "zhuang" -> 16#3a;
+ "zh" -> 16#41;
+ "chinese" -> 16#41;
+ "zu" -> 16#5c;
+ "zulu" -> 16#5c
+ end.
+
+
+%% Push Application ID Assignments
+%%
+%% Assingment are found at http://www.wapforum.org/wina/push-app-id.htm
+%%
+decode_push_application({short,Data}) ->
+ decode_push_application(d_long(Data));
+
+decode_push_application(Code) when integer(Code) ->
+ case Code of
+ 16#00 -> "x-wap-application:*";
+ 16#01 -> "x-wap-application:push.sia";
+ 16#02 -> "x-wap-application:wml.ua";
+ 16#03 -> "x-wap-application:wta.ua";
+ 16#04 -> "x-wap-application:mms.ua";
+ 16#05 -> "x-wap-application:push.syncml";
+ 16#06 -> "x-wap-application:loc.ua";
+ 16#07 -> "x-wap-application:syncml.dm";
+ 16#08 -> "x-wap-application:drm.ua";
+ 16#09 -> "x-wap-application:emn.ua";
+ 16#0A -> "x-wap-application:wv.ua";
+ 16#8000 -> "x-wap-microsoft:localcontent.ua";
+ 16#8001 -> "x-wap-microsoft:IMclient.ua";
+ 16#8002 -> "x-wap-docomo:imode.mail.ua";
+ 16#8003 -> "x-wap-docomo:imode.mr.ua";
+ 16#8004 -> "x-wap-docomo:imode.mf.ua";
+ 16#8005 -> "x-motorola:location.ua";
+ 16#8006 -> "x-motorola:now.ua";
+ 16#8007 -> "x-motorola:otaprov.ua";
+ 16#8008 -> "x-motorola:browser.ua";
+ 16#8009 -> "x-motorola:splash.ua";
+ 16#800B -> "x-wap-nai:mvsw.command";
+ 16#8010 -> "x-wap-openwave:iota.ua"
+ end;
+decode_push_application(App) when list(App) ->
+ App.
+
+
+
+encode_push_application(App) ->
+ case App of
+ "x-wap-application:*" -> ?ENCODE_SHORT(16#00);
+ "x-wap-application:push.sia" -> ?ENCODE_SHORT(16#01);
+ "x-wap-application:wml.ua" -> ?ENCODE_SHORT(16#02);
+ "x-wap-application:wta.ua" -> ?ENCODE_SHORT(16#03);
+ "x-wap-application:mms.ua" -> ?ENCODE_SHORT(16#04);
+ "x-wap-application:push.syncml" -> ?ENCODE_SHORT(16#05);
+ "x-wap-application:loc.ua" -> ?ENCODE_SHORT(16#06);
+ "x-wap-application:syncml.dm" -> ?ENCODE_SHORT(16#07);
+ "x-wap-application:drm.ua" -> ?ENCODE_SHORT(16#08);
+ "x-wap-application:emn.ua" -> ?ENCODE_SHORT(16#09);
+ "x-wap-application:wv.ua" -> ?ENCODE_SHORT(16#0A);
+ "x-wap-microsoft:localcontent.ua" -> encode_integer(16#8000);
+ "x-wap-microsoft:IMclient.ua" -> encode_integer(16#8001);
+ "x-wap-docomo:imode.mail.ua" -> encode_integer(16#8002);
+ "x-wap-docomo:imode.mr.ua" -> encode_integer(16#8003);
+ "x-wap-docomo:imode.mf.ua" -> encode_integer(16#8004);
+ "x-motorola:location.ua" -> encode_integer(16#8005);
+ "x-motorola:now.ua" -> encode_integer(16#8006);
+ "x-motorola:otaprov.ua" -> encode_integer(16#8007);
+ "x-motorola:browser.ua" -> encode_integer(16#8008);
+ "x-motorola:splash.ua" -> encode_integer(16#8009);
+ "x-wap-nai:mvsw.command" -> encode_integer(16#800B);
+ "x-wap-openwave:iota.ua" -> encode_integer(16#8010);
+ _ -> encode_uri_value(App)
+ end.
+
+
+
+
+%% WSP 8.5 Multipart handling
+
+encode_multipart(Entries) ->
+ encode_multipart(Entries, ?WSP_DEFAULT_VERSION).
+
+encode_multipart([], _Version) ->
+ <<>>;
+encode_multipart(Entries, Version) ->
+ EncEntries = encode_multipart_entries(Entries, Version),
+ <<(e_uintvar(length(Entries)))/binary, EncEntries/binary >>.
+
+encode_multipart_entries(Entries, Version) ->
+ encode_multipart_entries(Entries, Version, []).
+
+encode_multipart_entries([], _Version, Acc) ->
+ list_to_binary(lists:reverse(Acc));
+encode_multipart_entries([Entry|T], Version, Acc) ->
+ EncEntry = encode_multipart_entry(Entry, Version),
+ encode_multipart_entries(T, Version, [EncEntry | Acc]).
+
+encode_multipart_entry(Entry, Version) ->
+ #wsp_multipart_entry { content_type = ContentType,
+ headers = Headers,
+ data = Data } = Entry,
+ EncContentType = encode_content_type(ContentType,Version),
+ EncHeaders = encode_headers(Headers, Version),
+ EncHeadersLength = e_uintvar(size(EncContentType)+size(EncHeaders)),
+ DataLen = e_uintvar(size(Data)),
+ <<EncHeadersLength/binary,
+ DataLen/binary,
+ EncContentType/binary,
+ EncHeaders/binary,
+ Data/binary>>.
+
+
+decode_multipart(Data) ->
+ decode_multipart(Data, ?WSP_DEFAULT_VERSION).
+
+decode_multipart(<<>>, _Version) ->
+ {[], <<>>};
+decode_multipart(Data, Version) ->
+ {Entries, Data1} = d_uintvar(Data),
+ decode_multipart_entries(Entries, Data1, Version).
+
+decode_multipart_entries(Entries, Data, Version) ->
+ decode_multipart_entries(Entries, Data, Version, []).
+
+decode_multipart_entries(0, Data, _Version, Acc) ->
+ {lists:reverse(Acc), Data};
+decode_multipart_entries(Entries, Data, Version, Acc) ->
+ {MultiPartEntry, Data1} = decode_multipart_entry(Data,Version),
+ decode_multipart_entries(Entries-1, Data1, Version, [MultiPartEntry|Acc]).
+
+decode_multipart_entry(Data, Version) ->
+ {HeadersLen, Data1} = d_uintvar(Data),
+ {DataLen, Data2} = d_uintvar(Data1),
+ {FieldData,Data3} = scan_header_data(Data2),
+ ContentType = decode_content_type(FieldData, Version),
+ BinHeadersLen = (HeadersLen-(size(Data2)-size(Data3))),
+ <<BinHeaders:BinHeadersLen/binary,Data4/binary>> = Data3,
+ Headers = decode_headers(BinHeaders, Version),
+ <<ValueData:DataLen/binary, Data5/binary>> = Data4,
+ {#wsp_multipart_entry{content_type=ContentType,
+ headers=Headers,
+ data=ValueData},Data5}.
+
+
+parse_credentials(Field, Value) ->
+ %% FIXME
+ ?WH(Field, Value, []).
+
+format_credentials("basic", [User,Password]) ->
+ ["Basic ", base64:encode(User++":"++Password)];
+format_credentials(Scheme, Params) ->
+ [Scheme, format_params(Params)].
+
+encode_credentials("basic", [User,Password], _Version) ->
+ e_value(?ENCODE_SHORT(0),
+ encode_text_string(User),
+ encode_text_string(Password));
+encode_credentials(Scheme, Params, Version) ->
+ e_value(encode_text_string(Scheme), encode_params(Params, Version)).
+
+decode_credentials(Field, Data, Version) ->
+ case scan_header_data(Data) of
+ {0, Data0} ->
+ {User,Data1} = d_text_string(Data0),
+ {Password,_Data2} = d_text_string(Data1),
+ ?WH(Field, "basic", [User,Password]);
+ {Scheme, Data0} when list(Scheme) ->
+ Params = decode_params(Data0, Version),
+ ?WH(Field, Scheme, Params)
+ end.
+
+%%
+%% Challenge: Basic Realm-value | Auth-Scheme Realm *Auth-Params
+%%
+
+parse_challenge(Field, Value) ->
+ %% FIXME
+ ?WH(Field, Value, []).
+
+format_challenge({"basic",Realm}, []) ->
+ ["Basic ", Realm];
+format_challenge({Scheme,Realm}, Params) ->
+ [Scheme," ",Realm, format_params(Params)].
+
+encode_challenge({"basic",Realm}, [], _Version) ->
+ e_value(?ENCODE_SHORT(0),
+ encode_text_string(Realm));
+encode_challenge({Scheme,Realm}, Params, Version) ->
+ e_value(encode_text_string(Scheme),
+ encode_text_string(Realm),
+ encode_params(Params, Version)).
+
+decode_challenge(Field, Data, Version) ->
+ case scan_header_data(Data) of
+ {0, Data0} ->
+ {Realm,_} = d_text_string(Data0),
+ ?WH(Field, {"basic", Realm}, []);
+ {Scheme, Data0} when list(Scheme) ->
+ {Realm,_} = d_text_string(Data0),
+ Params = decode_params(Data0, Version),
+ ?WH(Field, {Scheme,Realm}, Params)
+ end.
+
+
+parse_well_known_method(Value) ->
+ case Value of
+ "GET" -> 'GET';
+ "OPTIONS" -> 'OPTIONS';
+ "HEAD" -> 'HEAD';
+ "DELETE" -> 'DELETE';
+ "TRACE" -> 'TRACE';
+ "POST" -> 'POST';
+ "PUT" -> 'PUT'
+ end.
+
+encode_well_known_method(Value, _Version) ->
+ case Value of
+ 'GET' -> ?ENCODE_SHORT(16#40);
+ 'OPTIONS' -> ?ENCODE_SHORT(16#41);
+ 'HEAD' -> ?ENCODE_SHORT(16#42);
+ 'DELETE' -> ?ENCODE_SHORT(16#43);
+ 'TRACE' -> ?ENCODE_SHORT(16#44);
+ 'POST' -> ?ENCODE_SHORT(16#60);
+ 'PUT' -> ?ENCODE_SHORT(16#61)
+ end.
+
+decode_well_known_method(Value, _Version) ->
+ case Value of
+ 16#40 -> 'GET';
+ 16#41 -> 'OPTIONS';
+ 16#42 -> 'HEAD';
+ 16#43 -> 'DELETE';
+ 16#44 -> 'TRACE';
+ 16#60 -> 'POST';
+ 16#61 -> 'PUT'
+ end.
+
+
+
+%%
+%% WSP Table 36. Status Code Assignments
+%%
+
+encode_status_code(Status) ->
+ case Status of
+ 100 -> 16#10; %% 'Continue'
+ 101 -> 16#11; %% 'Switching Protocols'
+ 200 -> 16#20; %% 'OK, Success'
+ 201 -> 16#21; %% 'Created'
+ 202 -> 16#22; %% 'Accepted'
+ 203 -> 16#23; %% 'Non-Authoritative Information'
+ 204 -> 16#24; %% 'No Content'
+ 205 -> 16#25; %% 'Reset Content'
+ 206 -> 16#26; %% 'Partial Content'
+ 300 -> 16#30; %% 'Multiple Choices'
+ 301 -> 16#31; %% 'Moved Permanently'
+ 302 -> 16#32; %% 'Moved temporarily'
+ 303 -> 16#33; %% 'See Other'
+ 304 -> 16#34; %% 'Not modified'
+ 305 -> 16#35; %% 'Use Proxy'
+ 306 -> 16#36; %% '(reserved)'
+ 307 -> 16#37; %% 'Temporary Redirect'
+ 400 -> 16#40; %% 'Bad Request - server could not understand request'
+ 401 -> 16#41; %% 'Unauthorized'
+ 402 -> 16#42; %% 'Payment required'
+ 403 -> 16#43; %% 'Forbidden operation is understood but refused'
+ 404 -> 16#44; %% 'Not Found'
+ 405 -> 16#45; %% 'Method not allowed'
+ 406 -> 16#46; %% 'Not Acceptable'
+ 407 -> 16#47; %% 'Proxy Authentication required'
+ 408 -> 16#48; %% 'Request Timeout'
+ 409 -> 16#49; %% 'Conflict'
+ 410 -> 16#4A; %% 'Gone'
+ 411 -> 16#4B; %% 'Length Required'
+ 412 -> 16#4C; %% 'Precondition failed'
+ 413 -> 16#4D; %% 'Request entity too large'
+ 414 -> 16#4E; %% 'Request-URI too large'
+ 415 -> 16#4F; %% 'Unsupported media type'
+ 416 -> 16#50; %% 'Requested Range Not Satisfiable'
+ 417 -> 16#51; %% 'Expectation Failed'
+ 500 -> 16#60; %% 'Internal Server Error'
+ 501 -> 16#61; %% 'Not Implemented'
+ 502 -> 16#62; %% 'Bad Gateway'
+ 503 -> 16#63; %% 'Service Unavailable'
+ 504 -> 16#64; %% 'Gateway Timeout'
+ 505 -> 16#65 %% 'HTTP version not supported'
+ end.
+
+
+decode_status_code(StatusCode) ->
+ case StatusCode of
+ 16#10 -> 100; %% 'Continue'
+ 16#11 -> 101; %% 'Switching Protocols'
+ 16#20 -> 200; %% 'OK, Success'
+ 16#21 -> 201; %% 'Created'
+ 16#22 -> 202; %% 'Accepted'
+ 16#23 -> 203; %% 'Non-Authoritative Information'
+ 16#24 -> 204; %% 'No Content'
+ 16#25 -> 205; %% 'Reset Content'
+ 16#26 -> 206; %% 'Partial Content'
+ 16#30 -> 300; %% 'Multiple Choices'
+ 16#31 -> 301; %% 'Moved Permanently'
+ 16#32 -> 302; %% 'Moved temporarily'
+ 16#33 -> 303; %% 'See Other'
+ 16#34 -> 304; %% 'Not modified'
+ 16#35 -> 305; %% 'Use Proxy'
+ 16#36 -> 306; %% '(reserved)'
+ 16#37 -> 307; %% 'Temporary Redirect'
+ 16#40 -> 400; %% 'Bad Request - server could not understand request'
+ 16#41 -> 401; %% 'Unauthorized'
+ 16#42 -> 402; %% 'Payment required'
+ 16#43 -> 403; %% 'Forbidden operation is understood but refused'
+ 16#44 -> 404; %% 'Not Found'
+ 16#45 -> 405; %% 'Method not allowed'
+ 16#46 -> 406; %% 'Not Acceptable'
+ 16#47 -> 407; %% 'Proxy Authentication required'
+ 16#48 -> 408; %% 'Request Timeout'
+ 16#49 -> 409; %% 'Conflict'
+ 16#4A -> 410; %% 'Gone'
+ 16#4B -> 411; %% 'Length Required'
+ 16#4C -> 412; %% 'Precondition failed'
+ 16#4D -> 413; %% 'Request entity too large'
+ 16#4E -> 414; %% 'Request-URI too large'
+ 16#4F -> 415; %% 'Unsupported media type'
+ 16#50 -> 416; %% 'Requested Range Not Satisfiable'
+ 16#51 -> 417; %% 'Expectation Failed'
+ 16#60 -> 500; %% 'Internal Server Error'
+ 16#61 -> 501; %% 'Not Implemented'
+ 16#62 -> 502; %% 'Bad Gateway'
+ 16#63 -> 503; %% 'Service Unavailable'
+ 16#64 -> 504; %% 'Gateway Timeout'
+ 16#65 -> 505 %% 'HTTP version not supported'
+ end.
+
+
+%%
+%% Content Type Assignments
+%%
+%% Assingment are found at http://www.wapforum.org/wina/wsp-content-type.htm
+%%
+%%
+%% string(Version, ContentType) -> Code
+%%
+encode_well_known_media(ContentType, Version) ->
+ case ContentType of
+ %% WSP_REGISTERED_CONTENT_TYPES
+ "application/vnd.uplanet.cacheop-wbxml" ->
+ encode_integer(16#0201);
+ "application/vnd.uplanet.signal" ->
+ encode_integer(16#0202);
+ "application/vnd.uplanet.alert-wbxml" ->
+ encode_integer(16#0203);
+ "application/vnd.uplanet.list-wbxml" ->
+ encode_integer(16#0204);
+ "application/vnd.uplanet.listcmd-wbxml" ->
+ encode_integer(16#0205);
+ "application/vnd.uplanet.channel-wbxml" ->
+ encode_integer(16#0206);
+ "application/vnd.uplanet.provisioning-status-uri" ->
+ encode_integer(16#0207);
+ "x-wap.multipart/vnd.uplanet.header-set" ->
+ encode_integer(16#0208);
+ "application/vnd.uplanet.bearer-choice-wbxml" ->
+ encode_integer(16#0209);
+ "application/vnd.phonecom.mmc-wbxml" ->
+ encode_integer(16#020A);
+ "application/vnd.nokia.syncset+wbxml" ->
+ encode_integer(16#020B);
+ "image/x-up-wpng" ->
+ encode_integer(16#020C);
+ _ ->
+ encode_constrained_media(ContentType, Version)
+ end.
+
+
+encode_constrained_media(ContentType, Version) ->
+ case ContentType of
+ "*/*" -> ?ENCODE_SHORT(16#00);
+ "text/*" -> ?ENCODE_SHORT(16#01);
+ "text/html" -> ?ENCODE_SHORT(16#02);
+ "text/plain" -> ?ENCODE_SHORT(16#03);
+ "text/x-hdml" -> ?ENCODE_SHORT(16#04);
+ "text/x-ttml" -> ?ENCODE_SHORT(16#05);
+ "text/x-vcalendar" -> ?ENCODE_SHORT(16#06);
+ "text/x-vcard" -> ?ENCODE_SHORT(16#07);
+ "text/vnd.wap.wml" -> ?ENCODE_SHORT(16#08);
+ "text/vnd.wap.wmlscript" -> ?ENCODE_SHORT(16#09);
+ "text/vnd.wap.wta-event" -> ?ENCODE_SHORT(16#0A);
+ "multipart/*" -> ?ENCODE_SHORT(16#0B);
+ "multipart/mixed" -> ?ENCODE_SHORT(16#0C);
+ "multipart/form-data" -> ?ENCODE_SHORT(16#0D);
+ "multipart/byterantes" -> ?ENCODE_SHORT(16#0E);
+ "multipart/alternative" -> ?ENCODE_SHORT(16#0F);
+ "application/*" -> ?ENCODE_SHORT(16#10);
+ "application/java-vm" -> ?ENCODE_SHORT(16#11);
+ "application/x-www-form-urlencoded" -> ?ENCODE_SHORT(16#12);
+ "application/x-hdmlc" -> ?ENCODE_SHORT(16#13);
+ "application/vnd.wap.wmlc" -> ?ENCODE_SHORT(16#14);
+ "application/vnd.wap.wmlscriptc" -> ?ENCODE_SHORT(16#15);
+ "application/vnd.wap.wta-eventc" -> ?ENCODE_SHORT(16#16);
+ "application/vnd.wap.uaprof" -> ?ENCODE_SHORT(16#17);
+ "application/vnd.wap.wtls-ca-certificate" -> ?ENCODE_SHORT(16#18);
+ "application/vnd.wap.wtls-user-certificate" -> ?ENCODE_SHORT(16#19);
+ "application/x-x509-ca-cert" -> ?ENCODE_SHORT(16#1A);
+ "application/x-x509-user-cert" -> ?ENCODE_SHORT(16#1B);
+ "image/*" -> ?ENCODE_SHORT(16#1C);
+ "image/gif" -> ?ENCODE_SHORT(16#1D);
+ "image/jpeg" -> ?ENCODE_SHORT(16#1E);
+ "image/tiff" -> ?ENCODE_SHORT(16#1F);
+ "image/png" -> ?ENCODE_SHORT(16#20);
+ "image/vnd.wap.wbmp" -> ?ENCODE_SHORT(16#21);
+ "application/vnd.wap.multipart.*" -> ?ENCODE_SHORT(16#22);
+ "application/vnd.wap.multipart.mixed" -> ?ENCODE_SHORT(16#23);
+ "application/vnd.wap.multipart.form-data" -> ?ENCODE_SHORT(16#24);
+ "application/vnd.wap.multipart.byteranges" -> ?ENCODE_SHORT(16#25);
+ "application/vnd.wap.multipart.alternative" -> ?ENCODE_SHORT(16#26);
+ "application/xml" -> ?ENCODE_SHORT(16#27);
+ "text/xml" -> ?ENCODE_SHORT(16#28);
+ "application/vnd.wap.wbxml" -> ?ENCODE_SHORT(16#29);
+ "application/x-x968-cross-cert" -> ?ENCODE_SHORT(16#2A);
+ "application/x-x968-ca-cert" -> ?ENCODE_SHORT(16#2B);
+ "application/x-x968-user-cert" -> ?ENCODE_SHORT(16#2C);
+
+ %% WAP Version 1.2
+ "text/vnd.wap.si" when Version >= ?WSP_12 ->
+ ?ENCODE_SHORT(16#2D);
+ "application/vnd.wap.sic" when Version >= ?WSP_12 ->
+ ?ENCODE_SHORT(16#2E);
+ "text/vnd.wap.sl" when Version >= ?WSP_12 ->
+ ?ENCODE_SHORT(16#2F);
+ "application/vnd.wap.slc" when Version >= ?WSP_12 ->
+ ?ENCODE_SHORT(16#30);
+ "text/vnd.wap.co" when Version >= ?WSP_12 ->
+ ?ENCODE_SHORT(16#31);
+ "application/vnd.wap.coc" when Version >= ?WSP_12 ->
+ ?ENCODE_SHORT(16#32);
+ "application/vnd.wap.multipart.related" when Version >= ?WSP_12 ->
+ ?ENCODE_SHORT(16#33);
+ "application/vnd.wap.sia" when Version >= ?WSP_12 ->
+ ?ENCODE_SHORT(16#34);
+ %% WAP Version 1.3
+ "text/vnd.wap.connectivity-xml" when Version >= ?WSP_13 ->
+ ?ENCODE_SHORT(16#35);
+ "application/vnd.wap.connectivity-wbxml" when Version >= ?WSP_13 ->
+ ?ENCODE_SHORT(16#36);
+ %% WAP Version 1.4
+ "application/pkcs7-mime" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#37);
+ "application/vnd.wap.hashed-certificate" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#38);
+ "application/vnd.wap.signed-certificate" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#39);
+ "application/vnd.wap.cert-response" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#3A);
+ "application/xhtml+xml" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#3B);
+ "application/wml+xml" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#3C);
+ "text/css" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#3D);
+ "application/vnd.wap.mms-message" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#3E);
+ "application/vnd.wap.rollover-certificate" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#3F);
+ %% WAP Version 1.5
+ "application/vnd.wap.locc+wbxml" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#40);
+ "application/vnd.wap.loc+xml" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#41);
+ "application/vnd.syncml.dm+wbxml" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#42);
+ "application/vnd.syncml.dm+xml" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#43);
+ "application/vnd.syncml.notification" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#44);
+ "application/vnd.wap.xhtml+xml" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#45);
+ "application/vnd.wv.csp.cir" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#46);
+ "application/vnd.oma.dd+xml" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#47);
+ "application/vnd.oma.drm.message" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#48);
+ "application/vnd.oma.drm.content" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#49);
+ "application/vnd.oma.drm.rights+xml" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#4A);
+ "application/vnd.oma.drm.rights+wbxml" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#4B);
+ _ ->
+ encode_text_string(ContentType)
+ end.
+
+
+decode_well_known_media(Code, Version) when integer(Code) ->
+ case Code of
+ %% WSP_REGISTERED_CONTENT_TYPES
+ 16#0201 -> "application/vnd.uplanet.cacheop-wbxml";
+ 16#0202 -> "application/vnd.uplanet.signal";
+ 16#0203 -> "application/vnd.uplanet.alert-wbxml";
+ 16#0204 -> "application/vnd.uplanet.list-wbxml";
+ 16#0205 -> "application/vnd.uplanet.listcmd-wbxml";
+ 16#0206 -> "application/vnd.uplanet.channel-wbxml";
+ 16#0207 -> "application/vnd.uplanet.provisioning-status-uri";
+ 16#0208 -> "x-wap.multipart/vnd.uplanet.header-set";
+ 16#0209 -> "application/vnd.uplanet.bearer-choice-wbxml";
+ 16#020A -> "application/vnd.phonecom.mmc-wbxml";
+ 16#020B -> "application/vnd.nokia.syncset+wbxml";
+ 16#020C -> "image/x-up-wpng";
+ _ -> decode_constrained_media(Code, Version)
+ end;
+decode_well_known_media(Media, _Version) when list(Media) ->
+ Media;
+decode_well_known_media({short,_Data}, Version) ->
+ decode_well_known_media(d_long(data), Version). %% BUG HERE: Data
+
+
+decode_constrained_media(Code, _Version) when integer(Code) ->
+ case Code of
+ 16#00 -> "*/*";
+ 16#01 -> "text/*";
+ 16#02 -> "text/html";
+ 16#03 -> "text/plain";
+ 16#04 -> "text/x-hdml";
+ 16#05 -> "text/x-ttml";
+ 16#06 -> "text/x-vcalendar";
+ 16#07 -> "text/x-vcard";
+ 16#08 -> "text/vnd.wap.wml";
+ 16#09 -> "text/vnd.wap.wmlscript";
+ 16#0A -> "text/vnd.wap.wta-event";
+ 16#0B -> "multipart/*";
+ 16#0C -> "multipart/mixed";
+ 16#0D -> "multipart/form-data";
+ 16#0E -> "multipart/byterantes";
+ 16#0F -> "multipart/alternative";
+ 16#10 -> "application/*";
+ 16#11 -> "application/java-vm";
+ 16#12 -> "application/x-www-form-urlencoded";
+ 16#13 -> "application/x-hdmlc";
+ 16#14 -> "application/vnd.wap.wmlc";
+ 16#15 -> "application/vnd.wap.wmlscriptc";
+ 16#16 -> "application/vnd.wap.wta-eventc";
+ 16#17 -> "application/vnd.wap.uaprof";
+ 16#18 -> "application/vnd.wap.wtls-ca-certificate";
+ 16#19 -> "application/vnd.wap.wtls-user-certificate";
+ 16#1A -> "application/x-x509-ca-cert";
+ 16#1B -> "application/x-x509-user-cert";
+ 16#1C -> "image/*";
+ 16#1D -> "image/gif";
+ 16#1E -> "image/jpeg";
+ 16#1F -> "image/tiff";
+ 16#20 -> "image/png";
+ 16#21 -> "image/vnd.wap.wbmp";
+ 16#22 -> "application/vnd.wap.multipart.*";
+ 16#23 -> "application/vnd.wap.multipart.mixed";
+ 16#24 -> "application/vnd.wap.multipart.form-data";
+ 16#25 -> "application/vnd.wap.multipart.byteranges";
+ 16#26 -> "application/vnd.wap.multipart.alternative";
+ 16#27 -> "application/xml";
+ 16#28 -> "text/xml";
+ 16#29 -> "application/vnd.wap.wbxml";
+ 16#2A -> "application/x-x968-cross-cert";
+ 16#2B -> "application/x-x968-ca-cert";
+ 16#2C -> "application/x-x968-user-cert";
+ %% WAP Version 1.2
+ 16#2D -> "text/vnd.wap.si";
+ 16#2E -> "application/vnd.wap.sic";
+ 16#2F -> "text/vnd.wap.sl";
+ 16#30 -> "application/vnd.wap.slc";
+ 16#31 -> "text/vnd.wap.co";
+ 16#32 -> "application/vnd.wap.coc";
+ 16#33 -> "application/vnd.wap.multipart.related";
+ 16#34 -> "application/vnd.wap.sia";
+ %% WAP Version 1.3
+ 16#35 -> "text/vnd.wap.connectivity-xml";
+ 16#36 -> "application/vnd.wap.connectivity-wbxml";
+ %% WAP Version 1.4
+ 16#37 -> "application/pkcs7-mime";
+ 16#38 -> "application/vnd.wap.hashed-certificate";
+ 16#39 -> "application/vnd.wap.signed-certificate";
+ 16#3A -> "application/vnd.wap.cert-response";
+ 16#3B -> "application/xhtml+xml";
+ 16#3C -> "application/wml+xml";
+ 16#3D -> "text/css";
+ 16#3E -> "application/vnd.wap.mms-message";
+ 16#3F -> "application/vnd.wap.rollover-certificate";
+ %% WAP Version 1.5
+ 16#40 -> "application/vnd.wap.locc+wbxml";
+ 16#41 -> "application/vnd.wap.loc+xml";
+ 16#42 -> "application/vnd.syncml.dm+wbxml";
+ 16#43 -> "application/vnd.syncml.dm+xml";
+ 16#44 -> "application/vnd.syncml.notification";
+ 16#45 -> "application/vnd.wap.xhtml+xml";
+ 16#46 -> "application/vnd.wv.csp.cir";
+ 16#47 -> "application/vnd.oma.dd+xml";
+ 16#48 -> "application/vnd.oma.drm.message";
+ 16#49 -> "application/vnd.oma.drm.content";
+ 16#4A -> "application/vnd.oma.drm.rights+xml";
+ 16#4B -> "application/vnd.oma.drm.rights+wbxml"
+ end;
+decode_constrained_media(Media, _Version) when list(Media) ->
+ Media.
+
+
+%% Parse <integer> or <integer>.<integer>
+
+parse_version(Value) ->
+ case string:tokens(Value, ".") of
+ [Major,Minor] ->
+ {list_to_integer(Major), list_to_integer(Minor)};
+ [Major] ->
+ case catch list_to_integer(Major) of
+ {'EXIT', _} ->
+ Value;
+ V -> V
+ end
+ end.
+
+format_version({Major,Minor}) ->
+ [integer_to_list(Major),".",integer_to_list(Minor)];
+format_version(Major) when integer(Major) ->
+ integer_to_list(Major);
+format_version(Version) when list(Version) ->
+ Version.
+
+encode_version({Major,Minor}) ->
+ Ver = (((Major-1) band 16#7) bsl 4) bor (Minor band 16#f),
+ ?ENCODE_SHORT(Ver);
+encode_version(Major) when integer(Major) ->
+ Ver = ((Major band 16#7) bsl 4) bor 16#f,
+ ?ENCODE_SHORT(Ver);
+encode_version(Value) when list(Value) ->
+ encode_text_string(Value).
+
+
+decode_version(Value) when integer(Value) ->
+ Major = (Value bsr 4) band 16#7,
+ Minor = Value band 16#f,
+ if Minor == 16#f ->
+ Major;
+ true ->
+ {Major+1,Minor}
+ end;
+decode_version(Value) when list(Value) ->
+ Value.
+
+
+encode_mms_version({Major,Minor}) ->
+ Ver = ((Major band 16#7) bsl 4) bor (Minor band 16#f),
+ ?ENCODE_SHORT(Ver);
+encode_mms_version(Major) when integer(Major) ->
+ Ver = ((Major band 16#7) bsl 4) bor 16#f,
+ ?ENCODE_SHORT(Ver);
+encode_mms_version(Value) when list(Value) ->
+ encode_text_string(Value).
+
+
+decode_mms_version(Value) when integer(Value) ->
+ Major = (Value bsr 4) band 16#7,
+ Minor = Value band 16#f,
+ if Minor == 16#f ->
+ Major;
+ true ->
+ {Major,Minor}
+ end;
+decode_mms_version(Value) when list(Value) ->
+ Value.
+
+
+%%%
+%%% Basic data types
+%%%
+
+e_delta_seconds(Value) ->
+ encode_integer(Value).
+
+
+encode_integer(I) when integer(I), I >= 0 , I < 127 ->
+ ?ENCODE_SHORT(I);
+encode_integer(I) when integer(I) ->
+ encode_long_integer(I);
+encode_integer(List) when list(List) ->
+ encode_integer(list_to_integer(List)).
+
+decode_integer(Value) when integer(Value) ->
+ Value;
+decode_integer({short,Data}) ->
+ Sz = size(Data)*8,
+ <<Value:Sz>> = Data,
+ Value.
+
+encode_short_integer(I) ->
+ ?ENCODE_SHORT(I).
+
+encode_long_integer(I) when I >= 0 ->
+ MOInt = encode_multioctet_integer(I, []),
+ MOIntLen = length(MOInt),
+ list_to_binary([MOIntLen band 16#1f | MOInt]).
+
+encode_multioctet_integer(I,Acc) when I < 256 ->
+ [I | Acc];
+encode_multioctet_integer(I,Acc) ->
+ encode_multioctet_integer(I bsr 8, [(I band 16#ff) | Acc]).
+
+
+%% Integer-Value: Short-Integer | Long-Integer
+%% Short-Integer: <<1:Short:7>>
+%% Long-Integer: <<0-30, X:0-30>>
+%% return {Integer,Tail}
+d_integer_value(<<1:1,Integer:7,Tail/binary>>) ->
+ {Integer, Tail};
+d_integer_value(<<0:3,Len:5,Data/binary>>) when Len =/= 31 ->
+ Sz = Len*8,
+ <<Integer:Sz, Tail/binary>> = Data,
+ {Integer, Tail}.
+
+decode_short_integer(<<1:1,Septet:7,T100/binary>>) ->
+ {Septet, T100}.
+
+decode_long_integer(<<0:3,Len:5,Data/binary>>) when Len =/= 31 ->
+ Sz = Len*8,
+ <<Val:Sz, Tail/binary>> = Data,
+ {Val, Tail}.
+
+d_long(Data) ->
+ Sz = size(Data)*8,
+ <<Value:Sz>> = Data,
+ Value.
+
+
+encode_uri_value(Data) ->
+ encode_text_string(Data).
+
+decode_uri_value(Data) when list(Data) ->
+ Data.
+
+%% parse quoted string
+decode_quoted_string([$" | List]) ->
+ List.
+
+encode_quoted_string([$" | Value]) ->
+ case lists:reverse(Value) of
+ [$" | Value1] ->
+ <<$", (list_to_binary(lists:reverse(Value1)))/binary, 0>>;
+ _ ->
+ <<$", (list_to_binary(Value))/binary, 0>>
+ end;
+encode_quoted_string(Value) ->
+ <<$", (list_to_binary(Value))/binary, 0>>.
+
+
+
+decode_text_string(List) when list(List) ->
+ List;
+decode_text_string(Bin) when binary(Bin) ->
+ binary_to_list(Bin).
+
+
+
+encode_text_string(A) when atom(A) ->
+ encode_text_string(atom_to_list(A));
+encode_text_string([H|T]) when H >= 128 ->
+ <<(list_to_binary([127,H|T]))/binary,0>>;
+encode_text_string(S) ->
+ <<(list_to_binary(S))/binary,0>>.
+
+
+encode_text_value(undefined) ->
+ <<0>>;
+encode_text_value([$"|T]) ->
+ %% remove ending quote ?
+ <<34,(list_to_binary(T))/binary>>;
+encode_text_value(L) ->
+ encode_text_string(L).
+
+
+d_text_value(<<0,T100/binary>>) ->
+ { "", T100};
+d_text_value(<<34,_Tail/binary>>=Data) ->
+ d_text_string(Data);
+d_text_value(Data) ->
+ d_text_string(Data).
+
+
+d_text_string(<<127,Data/binary>>) -> %% Remove quote
+ d_text_string(Data,[]);
+d_text_string(Data) ->
+ d_text_string(Data,[]).
+
+d_text_string(<<0,Tail/binary>>,A) ->
+ {lists:reverse(A), Tail};
+d_text_string(<<C,Tail/binary>>,A) ->
+ d_text_string(Tail,[C|A]);
+d_text_string(<<>>, A) ->
+ {lists:reverse(A), <<>>}.
+
+
+d_q_value(<<0:1,Q:7,Tail/binary>>) ->
+ QVal =
+ if Q >= 1, Q =< 100 ->
+ lists:flatten(io_lib:format("0.~2..0w", [Q-1]));
+ Q >= 101, Q =< 1099 ->
+ lists:flatten(io_lib:format("0.~3..0w", [Q-100]));
+ true ->
+ io:format("Q-value to big ~w\n", [Q]),
+ "***"
+ end,
+ {QVal, Tail};
+d_q_value(<<1:1,Q1:7,0:1,Q0:7,Tail/binary>>) ->
+ Q = (Q1 bsl 7) bor Q0,
+ QVal =
+ if Q >= 1, Q =< 100 ->
+ lists:flatten(io_lib:format("0.~2..0w", [Q-1]));
+ Q >= 101, Q =< 1099 ->
+ lists:flatten(io_lib:format("0.~3..0w", [Q-100]));
+ true ->
+ io:format("Q-value to big ~w\n", [Q]),
+ "***"
+ end,
+ {QVal, Tail}.
+
+
+%%
+%% Decode uintvar
+%%
+d_uintvar(<<0:1,S0:7,T100/binary>>) ->
+ {S0, T100};
+d_uintvar(<<1:1,S1:7,0:1,S0:7,T100/binary>>) ->
+ {(S1 bsl 7) bor S0, T100};
+d_uintvar(<<1:1,S2:7,1:1,S1:7,0:1,S0:7,T100/binary>>) ->
+ {(S2 bsl 14) bor (S1 bsl 7) bor S0, T100};
+d_uintvar(<<1:1,S3:7,1:1,S2:7,1:1,S1:7,0:1,S0:7,T100/binary>>) ->
+ {(S3 bsl 21) bor (S2 bsl 14) bor (S1 bsl 7) bor S0, T100};
+d_uintvar(<<1:1,S4:7,1:1,S3:7,1:1,S2:7,1:1,S1:7,0:1,S0:7,T100/binary>>) ->
+ {(S4 bsl 28) bor (S3 bsl 21) bor (S2 bsl 14) bor (S1 bsl 7) bor S0, T100}.
+
+
+e_uintvar(I) when I < 128 -> <<I>>;
+e_uintvar(I) -> e_uintvar(I,[]).
+
+e_uintvar(0,Acc) ->
+ list_to_binary(Acc);
+e_uintvar(I,[]) ->
+ e_uintvar(I bsr 7, [I band 16#7f]);
+e_uintvar(I,Acc) ->
+ e_uintvar(I bsr 7, [16#80 bor (I band 16#7f) | Acc]).
+
+
+e_value(B) ->
+ Sz = size(B),
+ if Sz =< 30 ->
+ <<Sz:8, B/binary>>;
+ true ->
+ <<31:8, (e_uintvar(Sz))/binary, B/binary >>
+ end.
+
+e_value(B1,B2) ->
+ Sz = size(B1)+size(B2),
+ if Sz =< 30 ->
+ <<Sz:8, B1/binary, B2/binary>>;
+ true ->
+ <<31:8, (e_uintvar(Sz))/binary, B1/binary, B2/binary >>
+ end.
+
+e_value(B1,B2,B3) ->
+ Sz = size(B1)+size(B2)+size(B3),
+ if Sz =< 30 ->
+ <<Sz:8, B1/binary,B2/binary,B3/binary>>;
+ true ->
+ <<31:8,(e_uintvar(Sz))/binary,B1/binary,B2/binary,B3/binary>>
+ end.
+
+e_value(B1,B2,B3,B4) ->
+ Sz = size(B1)+size(B2)+size(B3)+size(B4),
+ if Sz =< 30 ->
+ <<Sz:8, B1/binary,B2/binary,B3/binary,B4/binary>>;
+ true ->
+ <<31:8,(e_uintvar(Sz))/binary,B1/binary,
+ B2/binary,B3/binary,B4/binary>>
+ end.
+
+%%
+%% Extened methods
+%%
+decode_extended_methods(<<PduType:8, Data/binary>>) ->
+ Type = decode_pdu_type(PduType),
+ {Method, Data1} = d_text_string(Data),
+ [{Type,Method} | decode_extended_methods(Data1)];
+decode_extended_methods(<<>>) ->
+ [].
+
+encode_extended_methods(Ms) ->
+ list_to_binary(encode_ext_methods(Ms)).
+
+encode_ext_methods([{Type,Method} | T]) ->
+ [ encode_pdu_type(Type), encode_text_string(Method) |
+ encode_ext_methods(T)];
+encode_ext_methods([]) ->
+ [].
+
+%%
+%% Address lists used by redirect-pdu and aliases-capability
+%%
+decode_address(D0) ->
+ [A] = decode_addresses(D0),
+ A.
+
+decode_addresses(D0) ->
+ case D0 of
+ <<1:1, 1:1,Len:6,B:8,P:16,Addr:Len/binary,D1/binary>> ->
+ [#wdp_address { bearer = B, address = Addr, portnum=P } |
+ decode_addresses(D1)];
+ <<1:1, 0:1,Len:6,B:8,Addr:Len/binary,D1/binary>> ->
+ [#wdp_address { bearer = B, address = Addr } |
+ decode_addresses(D1)];
+ <<0:1, 1:1,Len:6,P:16,Addr:Len/binary,D1/binary>> ->
+ [#wdp_address { portnum=P, address=Addr } |
+ decode_addresses(D1)];
+ <<0:1, 0:1,Len:6,Addr:Len/binary,D1/binary>> ->
+ [#wdp_address { address=Addr } |
+ decode_addresses(D1)];
+ <<>> ->
+ []
+ end.
+
+encode_addresses(As) ->
+ encode_addresses(As, []).
+
+encode_addresses([A|As], Acc) ->
+ encode_addresses(As, [encode_address(A)|Acc]);
+encode_addresses([], Acc) ->
+ list_to_binary(lists:reverse(Acc)).
+
+encode_address(#wdp_address { bearer = B, address = Addr, portnum = P }) ->
+ BAddr = if tuple(Addr) ->
+ list_to_binary(inet:ip_to_bytes(Addr));
+ binary(Addr) ->
+ Addr
+ end,
+ Len = size(BAddr),
+ if B == undefined, P == undefined ->
+ <<0:1, 0:1, Len:6, BAddr/binary>>;
+ B == undefined ->
+ <<0:1, 1:1, Len:6, P:16, BAddr/binary>>;
+ P == undefined ->
+ <<1:1, 0:1, Len:6, B:8, BAddr/binary>>;
+ true ->
+ <<1:1, 1:1, Len:6, B:8, P:16, BAddr/binary>>
+ end.
+
+
+
+
+-define(UNIX_TIME_OFFSET, 62167219200).
+
+d_date(Val) when integer(Val) ->
+ calendar:gregorian_seconds_to_datetime(Val+?UNIX_TIME_OFFSET);
+d_date({short,Data}) ->
+ Sz = size(Data)*8,
+ <<Sec:Sz>> = Data,
+ calendar:gregorian_seconds_to_datetime(Sec+?UNIX_TIME_OFFSET).
+
+e_date(DateTime) ->
+ Sec = calendar:datetime_to_gregorian_seconds(DateTime),
+ encode_long_integer(Sec - ?UNIX_TIME_OFFSET).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% decode http-date (RFC 2068). (MUST be send in RFC1123 date format)
+%% HTTP-date = rfc1123-date | rfc850-date | asctime-date
+%% rfc1123-date = wkday "," SP date1 SP time SP "GMT"
+%% rfc850-date = weekday "," SP date2 SP time SP "GMT"
+%% asctime-date = wkday SP date3 SP time SP 4DIGIT
+%%
+%% date1 = 2DIGIT SP month SP 4DIGIT
+%% ; day month year (e.g., 02 Jun 1982)
+%% date2 = 2DIGIT "-" month "-" 2DIGIT
+%% ; day-month-year (e.g., 02-Jun-82)
+%% date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
+%% ; month day (e.g., Jun 2)
+%%
+%% time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
+%% ; 00:00:00 - 23:59:59
+%%
+%% wkday = "Mon" | "Tue" | "Wed"
+%% | "Thu" | "Fri" | "Sat" | "Sun"
+%%
+%%
+%% weekday = "Monday" | "Tuesday" | "Wednesday"
+%% | "Thursday" | "Friday" | "Saturday" | "Sunday"
+%%
+%% month = "Jan" | "Feb" | "Mar" | "Apr"
+%% | "May" | "Jun" | "Jul" | "Aug"
+%% | "Sep" | "Oct" | "Nov" | "Dec"
+%%
+%% decode date or crash!
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_http_date(Date) ->
+ parse_hdate(tolower(Date)).
+
+parse_hdate([$m,$o,$n,$d,$a,$y,$ | Cs]) -> date2(Cs);
+parse_hdate([$t,$u,$e,$s,$d,$a,$y,$ | Cs]) -> date2(Cs);
+parse_hdate([$w,$e,$d,$n,$s,$d,$a,$y,$ | Cs]) -> date2(Cs);
+parse_hdate([$t,$h,$u,$r,$s,$d,$a,$y,$ | Cs]) -> date2(Cs);
+parse_hdate([$f,$r,$i,$d,$a,$y,$ | Cs]) -> date2(Cs);
+parse_hdate([$s,$a,$t,$u,$r,$d,$a,$y,$ | Cs]) -> date2(Cs);
+parse_hdate([$s,$u,$n,$d,$a,$y,$ | Cs]) -> date2(Cs);
+parse_hdate([$m,$o,$n,X | Cs]) -> date13(X,Cs);
+parse_hdate([$t,$u,$e,X | Cs]) -> date13(X,Cs);
+parse_hdate([$w,$e,$d,X | Cs]) -> date13(X,Cs);
+parse_hdate([$t,$h,$u,X | Cs]) -> date13(X,Cs);
+parse_hdate([$f,$r,$i,X | Cs]) -> date13(X,Cs);
+parse_hdate([$s,$a,$t,X | Cs]) -> date13(X,Cs);
+parse_hdate([$s,$u,$n,X | Cs]) -> date13(X,Cs).
+
+date13($ , Cs) -> date3(Cs);
+date13($,, [$ |Cs]) -> date1(Cs).
+
+%% date1
+date1([D1,D2,$ ,M1,M2,M3,$ ,Y1,Y2,Y3,Y4,$ | Cs]) ->
+ M = parse_month([M1,M2,M3]),
+ D = list_to_integer([D1,D2]),
+ Y = list_to_integer([Y1,Y2,Y3,Y4]),
+ {Time,[$ ,$g,$m,$t|Cs1]} = parse_time(Cs),
+ { {{Y,M,D},Time}, Cs1}.
+
+%% date2
+date2([D1,D2,$-,M1,M2,M3,$-,Y1,Y2 | Cs]) ->
+ M = parse_month([M1,M2,M3]),
+ D = list_to_integer([D1,D2]),
+ Y = 1900 + list_to_integer([Y1,Y2]),
+ {Time, [$ ,$g,$m,$t|Cs1]} = parse_time(Cs),
+ {{{Y,M,D}, Time}, Cs1}.
+
+%% date3
+date3([M1,M2,M3,$ ,D1,D2,$ | Cs]) ->
+ M = parse_month([M1,M2,M3]),
+ D = if D1 == $ -> list_to_integer([D2]);
+ true -> list_to_integer([D1,D2])
+ end,
+ {Time,[$ ,Y1,Y2,Y3,Y4|Cs1]} = parse_time(Cs),
+ Y = list_to_integer([Y1,Y2,Y3,Y4]),
+ { {{Y,M,D}, Time}, Cs1 }.
+
+%% decode lowercase month
+parse_month("jan") -> 1;
+parse_month("feb") -> 2;
+parse_month("mar") -> 3;
+parse_month("apr") -> 4;
+parse_month("may") -> 5;
+parse_month("jun") -> 6;
+parse_month("jul") -> 7;
+parse_month("aug") -> 8;
+parse_month("sep") -> 9;
+parse_month("oct") -> 10;
+parse_month("nov") -> 11;
+parse_month("dec") -> 12.
+
+%% decode time HH:MM:SS
+parse_time([H1,H2,$:,M1,M2,$:,S1,S2|Cs]) ->
+ { {list_to_integer([H1,H2]),
+ list_to_integer([M1,M2]),
+ list_to_integer([S1,S2]) }, Cs}.
+
+%% encode date into rfc1123-date (must be a GMT time!!!)
+fmt_date({{Y,M,D},{TH,TM,TS}}) ->
+ WkDay = case calendar:day_of_the_week({Y,M,D}) of
+ 1 -> "Mon";
+ 2 -> "Tue";
+ 3 -> "Wed";
+ 4 -> "Thu";
+ 5 -> "Fri";
+ 6 -> "Sat";
+ 7 -> "Sun"
+ end,
+ lists:flatten(io_lib:format("~s, ~2..0w ~s ~4..0w "
+ "~2..0w:~2..0w:~2..0w GMT",
+ [WkDay, D, fmt_month(M), Y, TH, TM, TS])).
+
+fmt_current_date() ->
+ fmt_date(calendar:universal_time()).
+
+%% decode lowercase month
+fmt_month(1) -> "Jan";
+fmt_month(2) -> "Feb";
+fmt_month(3) -> "Mar";
+fmt_month(4) -> "Apr";
+fmt_month(5) -> "May";
+fmt_month(6) -> "Jun";
+fmt_month(7) -> "Jul";
+fmt_month(8) -> "Aug";
+fmt_month(9) -> "Sep";
+fmt_month(10) -> "Oct";
+fmt_month(11) -> "Nov";
+fmt_month(12) -> "Dec".