147
168
megaco_stats:reset_stats(megaco_stats, ConnHandleOrCounter).
172
%%----------------------------------------------------------------------
173
%% cleanup utility functions
174
%%----------------------------------------------------------------------
176
cleanup(#megaco_conn_handle{local_mid = LocalMid}, Force)
177
when (Force == true) or (Force == false) ->
178
Pat = #reply{trans_id = '$1',
179
local_mid = LocalMid,
182
do_cleanup(Pat, Force);
183
cleanup(LocalMid, Force)
184
when (Force == true) or (Force == false) ->
185
Pat = #reply{trans_id = '$1',
186
local_mid = LocalMid,
189
do_cleanup(Pat, Force).
191
do_cleanup(Pat, Force) ->
192
Match = megaco_monitor:which_replies(Pat),
193
Reps = [{V1, V2} || [V1, V2] <- Match],
194
do_cleanup2(Reps, Force).
196
do_cleanup2([], _) ->
198
do_cleanup2([{TransId, aborted}|T], Force = false) ->
199
megaco_monitor:delete_reply(TransId),
200
do_cleanup2(T, Force);
201
do_cleanup2([_|T], Force = false) ->
202
do_cleanup2(T, Force);
203
do_cleanup2([{TransId, _State}|T], Force = true) ->
204
megaco_monitor:delete_reply(TransId),
205
do_cleanup2(T, Force).
208
%%----------------------------------------------------------------------
209
%% which_requests and which_replies utility functions
210
%%----------------------------------------------------------------------
212
which_requests(#megaco_conn_handle{local_mid = LocalMid,
213
remote_mid = RemoteMid}) ->
214
Pat1 = #trans_id{mid = LocalMid,
215
serial = '$1', _ = '_'},
216
Pat2 = #request{trans_id = Pat1,
217
remote_mid = RemoteMid,
219
Match = megaco_monitor:which_requests(Pat2),
221
which_requests(LocalMid) ->
222
Pat1 = #trans_id{mid = LocalMid,
223
serial = '$1', _ = '_'},
224
Pat2 = #request{trans_id = Pat1,
225
remote_mid = '$2', _ = '_'},
226
Match0 = megaco_monitor:which_requests(Pat2),
227
Match1 = [{mk_ch(LocalMid, V2), V1} || [V1, V2] <- Match0],
228
which_requests1(lists:sort(Match1)).
230
which_requests1([]) ->
232
which_requests1([{CH, S}|T]) ->
233
which_requests2(T, CH, [S], []).
235
which_requests2([], CH, Serials, Reqs) ->
236
lists:reverse([{CH, Serials}|Reqs]);
237
which_requests2([{CH, S}|T], CH, Serials, Reqs) ->
238
which_requests2(T, CH, [S|Serials], Reqs);
239
which_requests2([{CH1, S}|T], CH2, Serials, Reqs) ->
240
which_requests2(T, CH1, [S], [{CH2, lists:reverse(Serials)}| Reqs]).
243
which_replies(#megaco_conn_handle{local_mid = LocalMid,
244
remote_mid = RemoteMid}) ->
245
Pat1 = #trans_id{mid = RemoteMid,
246
serial = '$1', _ = '_'},
247
Pat2 = #reply{trans_id = Pat1,
248
local_mid = LocalMid,
250
handler = '$3', _ = '_'},
251
Match = megaco_monitor:which_replies(Pat2),
252
[{V1, V2, V3} || [V1, V2, V3] <- Match];
253
which_replies(LocalMid) ->
254
Pat1 = #trans_id{mid = '$1',
255
serial = '$2', _ = '_'},
256
Pat2 = #reply{trans_id = Pat1,
257
local_mid = LocalMid,
259
handler = '$4', _ = '_'},
260
Match0 = megaco_monitor:which_replies(Pat2),
261
Match1 = [{mk_ch(LocalMid,V1),{V2,V3,V4}} || [V1, V2, V3, V4] <- Match0],
262
which_replies1(lists:sort(Match1)).
264
which_replies1([]) ->
266
which_replies1([{CH, Data}|T]) ->
267
which_replies2(T, CH, [Data], []).
269
which_replies2([], CH, Data, Reps) ->
270
lists:reverse([{CH, Data}|Reps]);
271
which_replies2([{CH, Data}|T], CH, Datas, Reps) ->
272
which_replies2(T, CH, [Data|Datas], Reps);
273
which_replies2([{CH1, Data}|T], CH2, Datas, Reps) ->
274
which_replies2(T, CH1, [Data], [{CH2, lists:reverse(Datas)}| Reps]).
278
#megaco_conn_handle{local_mid = LM, remote_mid = RM}.
150
281
%%----------------------------------------------------------------------
151
282
%% Register/unreister connections
152
283
%%----------------------------------------------------------------------
154
285
%% Returns {ok, ConnHandle} | {error, Reason}
155
286
connect(RH, RemoteMid, SendHandle, ControlPid)
156
when record(RH, megaco_receive_handle) ->
287
when is_record(RH, megaco_receive_handle) ->
157
288
case megaco_config:connect(RH, RemoteMid, SendHandle, ControlPid) of
158
289
{ok, ConnData} ->
159
290
do_connect(ConnData);
1084
1456
Res = (catch apply(UserMod, handle_trans_request, [ConnHandle, Version, Actions | UserArgs])),
1085
1457
?report_debug(ConnData, "return: trans request", [T, {return, Res}]),
1459
ignore -> %% NOTE: Only used for testing!!
1088
1460
{discard_ack, ignore};
1090
{discard_ack, Replies} when list(Replies) ->
1091
Reply = {actionReplies, Replies},
1093
maybe_send_reply(ConnData, TransId, Reply, asn1_NOVALUE),
1094
{discard_ack, SendReply};
1095
{discard_ack, Error} when record(Error, 'ErrorDescriptor') ->
1096
Reply = {transactionError, Error},
1098
maybe_send_reply(ConnData, TransId, Reply, asn1_NOVALUE),
1099
{discard_ack, SendReply};
1100
{{handle_ack, AckData}, Replies} when list(Replies) ->
1101
Reply = {actionReplies, Replies},
1103
maybe_send_reply(ConnData, TransId, Reply, 'NULL'),
1462
ignore_trans_request ->
1463
{discard_ack, ignore_trans_request};
1465
{discard_ack, Replies} when is_list(Replies) ->
1466
Reply = {actionReplies, Replies},
1467
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1469
{discard_ack, SendReply};
1470
{discard_ack, Error} when is_record(Error, 'ErrorDescriptor') ->
1471
Reply = {transactionError, Error},
1472
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1474
{discard_ack, SendReply};
1475
{discard_ack, Replies, SendOpts} when is_list(Replies) and
1476
is_list(SendOpts) ->
1477
Reply = {actionReplies, Replies},
1478
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1479
SendOpts, asn1_NOVALUE),
1480
{discard_ack, SendReply};
1481
{discard_ack, Error, SendOpts}
1482
when is_record(Error, 'ErrorDescriptor') and
1483
is_list(SendOpts) ->
1484
Reply = {transactionError, Error},
1485
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1486
SendOpts, asn1_NOVALUE),
1487
{discard_ack, SendReply};
1489
{{handle_pending_ack, AckData}, Replies} when is_list(Replies) ->
1490
Reply = {actionReplies, Replies},
1491
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1492
[], when_pending_sent),
1493
{{handle_ack, AckData}, SendReply};
1494
{{handle_pending_ack, AckData}, Error}
1495
when is_record(Error, 'ErrorDescriptor') ->
1496
Reply = {transactionError, Error},
1497
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1498
[], when_pending_sent),
1499
{{handle_ack, AckData}, SendReply};
1500
{{handle_pending_ack, AckData}, Replies, SendOpts}
1501
when is_list(Replies) and
1502
is_list(SendOpts) ->
1503
Reply = {actionReplies, Replies},
1504
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1505
SendOpts, when_pending_sent),
1506
{{handle_ack, AckData}, SendReply};
1507
{{handle_pending_ack, AckData}, Error, SendOpts}
1508
when is_record(Error, 'ErrorDescriptor') and
1509
is_list(SendOpts) ->
1510
Reply = {transactionError, Error},
1511
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1512
SendOpts, when_pending_sent),
1513
{{handle_ack, AckData}, SendReply};
1515
{{handle_ack, AckData}, Replies} when is_list(Replies) ->
1516
Reply = {actionReplies, Replies},
1517
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1104
1519
{{handle_ack, AckData}, SendReply};
1105
1520
{{handle_ack, AckData}, Error}
1106
when record(Error, 'ErrorDescriptor') ->
1107
Reply = {transactionError, Error},
1109
maybe_send_reply(ConnData, TransId, Reply, 'NULL'),
1110
{{handle_ack, AckData}, SendReply};
1111
{{handle_sloppy_ack, AckData}, Replies} when list(Replies) ->
1112
Reply = {actionReplies, Replies},
1114
maybe_send_reply(ConnData, TransId, Reply, asn1_NOVALUE),
1521
when is_record(Error, 'ErrorDescriptor') ->
1522
Reply = {transactionError, Error},
1523
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1525
{{handle_ack, AckData}, SendReply};
1526
{{handle_ack, AckData}, Replies, SendOpts}
1527
when is_list(Replies) and
1528
is_list(SendOpts) ->
1529
Reply = {actionReplies, Replies},
1530
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1532
{{handle_ack, AckData}, SendReply};
1533
{{handle_ack, AckData}, Error, SendOpts}
1534
when is_record(Error, 'ErrorDescriptor') and
1535
is_list(SendOpts) ->
1536
Reply = {transactionError, Error},
1537
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1539
{{handle_ack, AckData}, SendReply};
1541
{{handle_sloppy_ack, AckData}, Replies} when is_list(Replies) ->
1542
Reply = {actionReplies, Replies},
1543
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1115
1545
{{handle_ack, AckData}, SendReply};
1116
1546
{{handle_sloppy_ack, AckData}, Error}
1117
when record(Error, 'ErrorDescriptor') ->
1118
Reply = {transactionError, Error},
1120
maybe_send_reply(ConnData, TransId, Reply, asn1_NOVALUE),
1547
when is_record(Error, 'ErrorDescriptor') ->
1548
Reply = {transactionError, Error},
1549
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1551
{{handle_ack, AckData}, SendReply};
1552
{{handle_sloppy_ack, AckData}, Replies, SendOpts}
1553
when is_list(Replies) and
1554
is_list(SendOpts) ->
1555
Reply = {actionReplies, Replies},
1556
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1557
SendOpts, asn1_NOVALUE),
1558
{{handle_ack, AckData}, SendReply};
1559
{{handle_sloppy_ack, AckData}, Error, SendOpts}
1560
when is_record(Error, 'ErrorDescriptor') and
1561
is_list(SendOpts) ->
1562
Reply = {transactionError, Error},
1563
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1564
SendOpts, asn1_NOVALUE),
1121
1565
{{handle_ack, AckData}, SendReply};
1123
1567
{pending, RequestData} ->
1156
1601
{discard_ack, ignore};
1158
{discard_ack, Replies} when list(Replies) ->
1159
Reply = {actionReplies, Replies},
1161
maybe_send_reply(ConnData, TransId, Reply, asn1_NOVALUE),
1162
{discard_ack, SendReply};
1164
{{handle_ack, AckData}, Replies} when list(Replies) ->
1165
Reply = {actionReplies, Replies},
1167
maybe_send_reply(ConnData, TransId, Reply, 'NULL'),
1168
{{handle_ack, AckData}, SendReply};
1603
{discard_ack, Replies} when is_list(Replies) ->
1604
Reply = {actionReplies, Replies},
1605
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1607
{discard_ack, SendReply};
1608
{discard_ack, Replies, SendOpts} when is_list(Replies) and
1609
is_list(SendOpts) ->
1610
Reply = {actionReplies, Replies},
1611
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1612
SendOpts, asn1_NOVALUE),
1613
{discard_ack, SendReply};
1615
{{handle_ack, AckData}, Replies} when is_list(Replies) ->
1616
Reply = {actionReplies, Replies},
1617
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1619
{{handle_ack, AckData}, SendReply};
1620
{{handle_ack, AckData}, Replies, SendOpts} when is_list(Replies) and
1621
is_list(SendOpts) ->
1622
Reply = {actionReplies, Replies},
1623
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1625
{{handle_ack, AckData}, SendReply};
1171
1628
ErrorText = atom_to_list(UserMod),
1172
1629
ED = #'ErrorDescriptor'{errorCode = ?megaco_internal_gateway_error,
1173
1630
errorText = ErrorText},
1174
?report_important(ConnData, "callback: <ERROR> trans long request",
1631
?report_important(ConnData, "callback: <ERROR> trans long request",
1175
1632
[ED, {error, Error}]),
1176
error_msg("long trans request callback failed: ~w", [Error]),
1177
Reply = {transactionError, ED},
1179
maybe_send_reply(ConnData, TransId, Reply, asn1_NOVALUE),
1180
{discard_ack, SendReply}
1633
error_msg("long transaction request callback failed: ~w", [Error]),
1634
Reply = {transactionError, ED},
1635
SendReply = maybe_send_reply(ConnData, TransId, Reply,
1637
{discard_ack, SendReply}
1183
1640
handle_pending(ConnData, T) ->
1184
1641
TransId = to_local_trans_id(ConnData),
1642
?rt2("handle pending", [T, TransId]),
1185
1643
case megaco_monitor:lookup_request(TransId) of
1186
[#request{timer_ref = {short, Ref},
1187
init_long_timer = InitTimer} = Req] ->
1189
%% The request seems to take a while,
1190
%% let's reset our transmission timer.
1191
%% We now know the other side has got
1192
%% the request and is working on it,
1193
%% so there is no need to keep the binary
1194
%% message for re-transmission.
1196
%% Start using the long timer.
1197
%% We can now drop the "bytes", since we will
1198
%% not resend from now on.
1200
megaco_monitor:cancel_apply_after(Ref),
1201
{WaitFor, CurrTimer} = init_timer(InitTimer),
1202
ConnHandle = ConnData#conn_data.conn_handle,
1204
F = request_timeout,
1205
A = [ConnHandle, TransId],
1206
Ref2 = megaco_monitor:apply_after(M, F, A, WaitFor),
1207
Req2 = Req#request{bytes = {no_send, garb_binary},
1208
timer_ref = {long, Ref2},
1209
curr_timer = CurrTimer},
1210
?report_trace(ConnData,
1211
"trans pending (timer restarted)", [T]),
1212
megaco_monitor:insert_request(Req2); % Timing problem?
1214
[#request{timer_ref = {long, _Ref},
1215
curr_timer = timeout}] ->
1217
%% The request seems to take a while,
1218
%% let's reset our transmission timer.
1219
%% We now know the other side has got
1220
%% the request and is working on it,
1221
%% so there is no need to keep the binary
1222
%% message for re-transmission.
1224
%% This can happen if the timer is running for the last
1225
%% time. I.e. next time it expires, will be the last.
1226
%% Therefor we really do not need to do anything here.
1227
%% The cleanup will be done in request_timeout.
1231
[#request{timer_ref = {long, Ref},
1232
curr_timer = CurrTimer} = Req] ->
1234
%% The request seems to take a while,
1235
%% let's reset our transmission timer.
1236
%% We now know the other side has got
1237
%% the request and is working on it,
1238
%% so there is no need to keep the binary
1239
%% message for re-transmission.
1241
%% We just need to recalculate the timer, i.e.
1242
%% increment the timer (one "slot" has been consumed).
1244
megaco_monitor:cancel_apply_after(Ref),
1245
{WaitFor, Timer2} = recalc_timer(CurrTimer),
1246
ConnHandle = ConnData#conn_data.conn_handle,
1248
F = request_timeout,
1249
A = [ConnHandle, TransId],
1250
Ref2 = megaco_monitor:apply_after(M, F, A, WaitFor),
1251
Req2 = Req#request{timer_ref = {long, Ref2},
1252
curr_timer = Timer2},
1253
?report_trace(ConnData,
1254
"long trans pending"
1255
" (timer restarted)", [T]),
1257
megaco_monitor:insert_request(Req2);
1646
%% ------------------------------------------
1648
%% Check received pending limit
1650
%% ------------------------------------------
1652
Limit = ConnData#conn_data.recv_pending_limit,
1653
case check_and_maybe_incr_pending_limit(Limit,
1657
%% ----------------------------------------------------
1659
%% Received pending limit not exceeded
1661
%% ----------------------------------------------------
1663
handle_recv_pending(ConnData, TransId, Req, T);
1666
%% ----------------------------------------------------
1668
%% Received pending limit exceeded
1670
%% Time to give up on this transaction
1671
%% 1) Delete request record
1673
%% 3) Delete the (receive) pending counter
1674
%% 4) Inform the user (handle_trans_reply)
1676
%% ----------------------------------------------------
1678
handle_recv_pending_error(ConnData, TransId, Req, T);
1682
%% ----------------------------------------------------
1684
%% Received pending limit already exceeded
1686
%% BMK BMK BMK -- can this really happen?
1688
%% The user has already been notified about this
1689
%% (see error above)
1691
%% ----------------------------------------------------
1260
?report_trace(ConnData,
1261
"remote pending (no receiver)", [T]),
1698
?report_trace(ConnData, "remote pending (no receiver)", [T]),
1262
1699
return_unexpected_trans(ConnData, T)
1702
handle_recv_pending(#conn_data{long_request_resend = LRR,
1703
conn_handle = ConnHandle} = ConnData,
1705
#request{timer_ref = {short, Ref},
1706
init_long_timer = InitTimer} = Req, T) ->
1708
?rt2("handle pending - long request", [LRR, InitTimer]),
1710
%% The request seems to take a while,
1711
%% let's reset our transmission timer.
1712
%% We now know the other side has got
1713
%% the request and is working on it,
1714
%% so there is no need to keep the binary
1715
%% message for re-transmission.
1717
%% Start using the long timer.
1718
%% We can now drop the "bytes", since we will
1719
%% not resend from now on.
1721
megaco_monitor:cancel_apply_after(Ref),
1722
{WaitFor, CurrTimer} = init_timer(InitTimer),
1723
ConnHandle = ConnData#conn_data.conn_handle,
1725
F = request_timeout,
1726
A = [ConnHandle, TransId],
1727
Ref2 = megaco_monitor:apply_after(M, F, A, WaitFor),
1731
Req#request{timer_ref = {long, Ref2},
1732
curr_timer = CurrTimer};
1734
Req#request{bytes = {no_send, garb_binary},
1735
timer_ref = {long, Ref2},
1736
curr_timer = CurrTimer}
1738
?report_trace(ConnData, "trans pending (timer restarted)", [T]),
1739
megaco_monitor:insert_request(Req2); % Timing problem?
1741
handle_recv_pending(_ConnData, _TransId,
1742
#request{timer_ref = {long, _Ref},
1743
curr_timer = timeout}, _T) ->
1745
?rt3("handle pending - timeout"),
1747
%% The request seems to take a while,
1748
%% let's reset our transmission timer.
1749
%% We now know the other side has got
1750
%% the request and is working on it,
1751
%% so there is no need to keep the binary
1752
%% message for re-transmission.
1754
%% This can happen if the timer is running for the last
1755
%% time. I.e. next time it expires, will be the last.
1756
%% Therefor we really do not need to do anything here.
1757
%% The cleanup will be done in request_timeout.
1761
handle_recv_pending(#conn_data{conn_handle = ConnHandle} = ConnData, TransId,
1762
#request{timer_ref = {long, Ref},
1763
curr_timer = CurrTimer} = Req, T) ->
1765
?rt2("handle pending - still waiting", [CurrTimer]),
1767
%% The request seems to take a while,
1768
%% let's reset our transmission timer.
1769
%% We now know the other side has got
1770
%% the request and is working on it,
1771
%% so there is no need to keep the binary
1772
%% message for re-transmission.
1774
%% We just need to recalculate the timer, i.e.
1775
%% increment the timer (one "slot" has been consumed).
1777
megaco_monitor:cancel_apply_after(Ref),
1778
{WaitFor, Timer2} = recalc_timer(CurrTimer),
1779
ConnHandle = ConnData#conn_data.conn_handle,
1781
F = request_timeout,
1782
A = [ConnHandle, TransId],
1783
Ref2 = megaco_monitor:apply_after(M, F, A, WaitFor),
1784
Req2 = Req#request{timer_ref = {long, Ref2},
1785
curr_timer = Timer2},
1786
?report_trace(ConnData,
1787
"long trans pending"
1788
" (timer restarted)", [T]),
1790
megaco_monitor:insert_request(Req2).
1793
handle_recv_pending_error(ConnData, TransId, Req, T) ->
1794
%% 1) Delete the request record
1795
megaco_monitor:delete_request(TransId),
1797
%% 2) Possibly cancel the timer
1798
case Req#request.timer_ref of
1800
megaco_monitor:cancel_apply_after(Ref);
1805
%% 3) Delete the (receive) pending counter
1806
megaco_config:del_pending_counter(recv, TransId),
1808
%% 4) Inform the user that his/her request reached
1809
%% the receive pending limit
1810
UserMod = Req#request.user_mod,
1811
UserArgs = Req#request.user_args,
1812
Action = Req#request.reply_action,
1813
UserData = Req#request.reply_data,
1814
UserReply = {error, exceeded_recv_pending_limit},
1815
ConnData2 = ConnData#conn_data{user_mod = UserMod,
1816
user_args = UserArgs,
1817
reply_action = Action,
1818
reply_data = UserData},
1820
?report_trace(ConnData, "receive pending limit reached", [T]),
1821
return_reply(ConnData2, TransId, UserReply).
1265
1824
handle_reply(ConnData, T) ->
1266
1825
TransId = to_local_trans_id(ConnData),
1826
?rt2("handle reply", [T, TransId]),
1267
1827
case megaco_monitor:lookup_request(TransId) of
1268
1828
[#request{timer_ref = {_Type, Ref}} = Req] -> %% OTP-4843
1269
1829
%% Don't care about Req and Rep version diff
1778
2364
case megaco_config:verify_val(Key, Val) of
1780
2366
ConnData2 = ConnData#conn_data{long_request_timer = Val},
1781
override_send_options(ConnData2, Tail);
2367
override_req_send_options(ConnData2, Tail);
1783
2369
{error, {bad_send_option, {Key, Val}}}
1786
2372
ConnData2 = ConnData#conn_data{reply_data = Val},
1787
override_send_options(ConnData2, Tail);
1788
user_mod when atom(Val) ->
2373
override_req_send_options(ConnData2, Tail);
2374
user_mod when is_atom(Val) ->
1789
2375
ConnData2 = ConnData#conn_data{user_mod = Val},
1790
override_send_options(ConnData2, Tail);
1791
user_args when list(Val) ->
2376
override_req_send_options(ConnData2, Tail);
2377
user_args when is_list(Val) ->
1792
2378
ConnData2 = ConnData#conn_data{user_args = Val},
1793
override_send_options(ConnData2, Tail);
1794
trans_req when Val == false ->
1795
%% We only allow turning the transaction-sender off, since
1796
%% the opposite (turning it on) would causing to much headake...
1797
%% This vould allow not using the transaction sender for
1798
%% occasional messages
1799
ConnData2 = ConnData#conn_data{trans_req = Val,
1800
trans_sender = undefined},
1801
override_send_options(ConnData2, Tail);
1803
{error, {bad_send_option, {Key, Val}}}
1805
override_send_options(ConnData, []) ->
2379
override_req_send_options(ConnData2, Tail);
2380
trans_req when Val == false ->
2381
%% We only allow turning the transaction-sender off, since
2382
%% the opposite (turning it on) would causing to much headake...
2383
%% This vould allow not using the transaction sender for
2384
%% occasional messages
2385
ConnData2 = ConnData#conn_data{trans_req = Val,
2386
trans_sender = undefined},
2387
override_req_send_options(ConnData2, Tail);
2389
{error, {bad_send_option, {Key, Val}}}
2391
override_req_send_options(ConnData, []) ->
2394
override_rep_send_options(ConnData, [{Key, Val} | Tail]) ->
2397
ConnData2 = ConnData#conn_data{protocol_version = Val},
2398
override_rep_send_options(ConnData2, Tail);
2400
ConnData2 = ConnData#conn_data{send_handle = Val},
2401
override_rep_send_options(ConnData2, Tail);
2403
case megaco_config:verify_val(Key, Val) of
2405
ConnData2 = ConnData#conn_data{reply_timer = Val},
2406
override_rep_send_options(ConnData2, Tail);
2408
{error, {bad_send_option, {Key, Val}}}
2410
trans_req when Val == false ->
2411
%% We only allow turning the transaction-sender off, since
2412
%% the opposite (turning it on) would causing to much headake...
2413
%% This vould allow not using the transaction sender for
2414
%% occasional messages
2415
ConnData2 = ConnData#conn_data{trans_req = Val,
2416
trans_sender = undefined},
2417
override_rep_send_options(ConnData2, Tail);
2419
{error, {bad_send_option, {Key, Val}}}
2421
override_rep_send_options(ConnData, []) ->
1806
2422
{ok, ConnData}.
2139
2844
return_unexpected_trans_reply(ConnData, TransId, UserReply)
2143
cancel_reply(ConnData, Rep, Reason) when record(Rep, reply) ->
2144
?report_trace(ConnData, "cancel reply", [Reason]),
2847
cancel_reply(ConnData, #reply{state = waiting_for_ack} = Rep, Reason) ->
2848
?report_trace(ignore, "cancel reply [waiting_for_ack]", [Rep]),
2145
2849
megaco_monitor:cancel_apply_after(Rep#reply.pending_timer_ref),
2146
2850
Serial = (Rep#reply.trans_id)#trans_id.serial,
2147
2851
ConnData2 = ConnData#conn_data{serial = Serial},
2148
2852
T = #'TransactionAck'{firstAck = Serial},
2149
handle_ack(ConnData2, {error, Reason}, Rep, T).
2853
handle_ack(ConnData2, {error, Reason}, Rep, T);
2855
cancel_reply(_ConnData, #reply{state = aborted} = Rep, _Reason) ->
2856
?report_trace(ignore, "cancel reply [aborted]", [Rep]),
2857
#reply{trans_id = TransId,
2858
timer_ref = ReplyRef,
2859
pending_timer_ref = PendingRef} = Rep,
2860
megaco_monitor:delete_reply(TransId),
2861
megaco_monitor:cancel_apply_after(ReplyRef),
2862
megaco_monitor:cancel_apply_after(PendingRef), % BMK BMK Still running?
2863
megaco_config:del_pending_counter(TransId), % BMK BMK Still existing?
2866
cancel_reply(_ConnData, Rep, ignore) ->
2867
?report_trace(ignore, "cancel reply [ignore]", [Rep]),
2868
#reply{trans_id = TransId,
2869
timer_ref = ReplyRef,
2870
pending_timer_ref = PendingRef} = Rep,
2871
megaco_monitor:delete_reply(TransId),
2872
megaco_monitor:cancel_apply_after(ReplyRef),
2873
megaco_monitor:cancel_apply_after(PendingRef), % BMK BMK Still running?
2874
megaco_config:del_pending_counter(TransId), % BMK BMK Still existing?
2877
cancel_reply(_CD, _Rep, _Reason) ->
2878
%% io:format("cancel_reply -> entry with"
2882
%% "~n", [_CD, _Rep, _Reason]),
2152
2886
request_timeout(ConnHandle, TransId) ->
2887
?rt1(ConnHandle, "request timeout", [TransId]),
2153
2888
case megaco_monitor:lookup_request(TransId) of
2156
[Req] when record(Req, request) ->
2891
[Req] when is_record(Req, request) ->
2157
2892
case megaco_config:lookup_local_conn(ConnHandle) of
2159
2894
incNumTimerRecovery(ConnHandle),
2253
2998
maybe_encode(CD, TR)
2254
when record(TR, 'TransactionRequest') ->
2999
when is_record(TR, 'TransactionRequest') ->
2255
3000
Body = {transactions, [{transactionRequest, TR}]},
2256
3001
megaco_messenger_misc:encode_body(CD, "encode trans request msg", Body);
2257
3002
maybe_encode(_CD, Trash) ->
2258
3003
{error, {invalid_bin, Trash}}.
2260
maybe_send_message(CD, Bin) when binary(Bin) ->
3005
maybe_send_message(CD, Bin) when is_binary(Bin) ->
2261
3006
megaco_messenger_misc:send_message(CD, Bin);
2262
3007
maybe_send_message(#conn_data{trans_sender = Pid}, {Serial, Bin})
2263
when pid(Pid), integer(Serial), binary(Bin) ->
3008
when is_pid(Pid) and is_integer(Serial) and is_binary(Bin) ->
2264
3009
megaco_trans_sender:send_req(Pid, Serial, Bin).
2267
3012
reply_timeout(ConnHandle, TransId, timeout) ->
3013
handle_reply_timer_timeout(ConnHandle, TransId);
3015
%% This means that infinity_restartable was used for max_retries.
3016
%% There is currently no reason to use this for the reply_timeout,
3017
%% since there is no external event to restart the timer!
3018
reply_timeout(ConnHandle, TransId, {_, timeout}) ->
3019
handle_reply_timer_timeout(ConnHandle, TransId);
3021
reply_timeout(ConnHandle, TransId, Timer) ->
3022
?report_trace(ConnHandle, "reply timeout", [Timer, TransId]),
3024
%% d("reply_timeout -> entry with"
3025
%% "~n ConnHandle: ~p"
3027
%% "~n Timer: ~p", [ConnHandle, TransId, Timer]),
3029
case megaco_monitor:lookup_reply(TransId) of
3033
[#reply{state = waiting_for_ack,
3034
ack_action = {handle_ack, _}} = Rep] ->
3035
case megaco_config:lookup_local_conn(ConnHandle) of
3037
incNumTimerRecovery(ConnHandle),
3038
do_reply_timeout(ConnHandle, TransId, ConnData,
3041
incNumTimerRecovery(ConnHandle),
3042
ConnData = fake_conn_data(ConnHandle),
3043
do_reply_timeout(ConnHandle, TransId, ConnData,
3047
[#reply{state = waiting_for_ack} = Rep] ->
3048
do_reply_timeout(ConnHandle, TransId, Timer, Rep);
3050
[#reply{state = aborted} = Rep] ->
3051
do_reply_timeout(ConnHandle, TransId, Timer, Rep);
3058
do_reply_timeout(ConnHandle, TransId, ConnData, Timer,
3059
#reply{send_handle = SH,
3061
bytes = Bytes} = Rep) ->
3063
CD = ConnData#conn_data{send_handle = SH,
3064
protocol_version = V},
3066
%% d("do_reply_timeout -> entry with"
3067
%% "~n ConnHandle: ~p"
3071
%% "~n", [ConnHandle, TransId, Timer, Rep]),
3073
case megaco_messenger_misc:send_message(CD, Bytes) of
3079
?report_important(CD, "<ERROR> re-send trans reply failed",
3080
[{bytes, Bytes}, {error, Reason}])
3082
do_reply_timeout(ConnHandle, TransId, Timer, Rep).
3084
do_reply_timeout(ConnHandle, TransId, Timer, #reply{bytes = Bytes} = Rep) ->
3085
{WaitFor, Timer2} = recalc_timer(Timer),
3086
OptBin = opt_garb_binary(Timer2, Bytes),
3089
A = [ConnHandle, TransId, Timer2],
3090
Ref2 = megaco_monitor:apply_after(M, F, A, WaitFor),
3091
Rep2 = Rep#reply{bytes = OptBin,
3093
megaco_monitor:insert_reply(Rep2). % Timing problem?
3096
handle_reply_timer_timeout(ConnHandle, TransId) ->
2268
3097
?report_trace(ConnHandle, "reply timeout", [timeout,TransId]),
2269
3098
incNumTimerRecovery(ConnHandle),