Attention is currently required from: pespin.
Hello Jenkins Builder, pespin,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-sgsn/+/39564?usp=email
to look at the new patch set (#18).
The following approvals got outdated and were removed:
Code-Review+1 by pespin, Verified+1 by Jenkins Builder
Change subject: mm_state_gb_fsm: Allow Idle -> Ready transition for RA Update
......................................................................
mm_state_gb_fsm: Allow Idle -> Ready transition for RA Update
Change-Id: Ic26d237976f51a061ac394cee1daef20db048517
---
M src/sgsn/gprs_mm_state_gb_fsm.c
1 file changed, 4 insertions(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-sgsn refs/changes/64/39564/18
--
To view, visit https://gerrit.osmocom.org/c/osmo-sgsn/+/39564?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newpatchset
Gerrit-Project: osmo-sgsn
Gerrit-Branch: master
Gerrit-Change-Id: Ic26d237976f51a061ac394cee1daef20db048517
Gerrit-Change-Number: 39564
Gerrit-PatchSet: 18
Gerrit-Owner: lynxis lazus <lynxis(a)fe80.eu>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-CC: daniel <dwillmann(a)sysmocom.de>
Gerrit-Attention: pespin <pespin(a)sysmocom.de>
dexter has uploaded this change for review. ( https://gerrit.osmocom.org/c/onomondo-eim/+/43658?usp=email )
Change subject: mnesia_db_work: use distinct logic when fetching from rest table
......................................................................
mnesia_db_work: use distinct logic when fetching from rest table
When the fetch function fetches a work item from the rest table, it
selects anything that where the facility is not euicc. This is
correct since anything else are indeed items that the
esipa_asn1_handler can work on (euicc is to manage internal states,
and handled differently). This will continue to work unless we
introduce another facility, however let's prevent future problems
by just using a more distinct logic to select the facilities
explcitly.
Related: SYS#8100
Change-Id: I2e42bde0c03155e7b2bcf058b20174b75e8e0d97
---
M src/mnesia_db_work.erl
1 file changed, 4 insertions(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/onomondo-eim refs/changes/58/43658/1
diff --git a/src/mnesia_db_work.erl b/src/mnesia_db_work.erl
index 3c11112..a620ffa 100644
--- a/src/mnesia_db_work.erl
+++ b/src/mnesia_db_work.erl
@@ -48,7 +48,10 @@
|| X <- mnesia:table(rest),
X#rest.eidValue == EidValue,
X#rest.status == new,
- X#rest.facility =/= euicc
+ X#rest.facility == download orelse
+ X#rest.facility == psmo orelse
+ X#rest.facility == eco orelse
+ X#rest.facility == edr
]),
Rows = qlc:e(Q),
case Rows of
--
To view, visit https://gerrit.osmocom.org/c/onomondo-eim/+/43658?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: onomondo-eim
Gerrit-Branch: master
Gerrit-Change-Id: I2e42bde0c03155e7b2bcf058b20174b75e8e0d97
Gerrit-Change-Number: 43658
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Hello Jenkins Builder,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/onomondo-eim/+/43654?usp=email
to look at the new patch set (#2).
The following approvals got outdated and were removed:
Verified+1 by Jenkins Builder
Change subject: esipa_asn1_handler: fix typos
......................................................................
esipa_asn1_handler: fix typos
Related: SYS#8100
Change-Id: I14416250cdb523f5c1a20d3a3e3dbe5cc6c53bcd
---
M src/esipa_asn1_handler.erl
1 file changed, 3 insertions(+), 3 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/onomondo-eim refs/changes/54/43654/2
--
To view, visit https://gerrit.osmocom.org/c/onomondo-eim/+/43654?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newpatchset
Gerrit-Project: onomondo-eim
Gerrit-Branch: master
Gerrit-Change-Id: I14416250cdb523f5c1a20d3a3e3dbe5cc6c53bcd
Gerrit-Change-Number: 43654
Gerrit-PatchSet: 2
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
dexter has uploaded this change for review. ( https://gerrit.osmocom.org/c/onomondo-eim/+/43659?usp=email )
Change subject: mnesia_db_work: remove Pid based transaction recognition workaround
......................................................................
mnesia_db_work: remove Pid based transaction recognition workaround
In SGP.32 V.1.0.1, some message types had no TransactionId in them.
For those message types, the only way to distinguish incoming requests
was to look at the Pid of process that was handling the current
connection. This worked, but posed a limitation on the IPAd. Only
when the IPAd was maintaining a single TCP connection throughout the
entire transaction, the workaround was working. Individual requests
where each request uses a distinct connection didn't work.
Since SGP.32 V.1.2, we have a transactionId or eimTransactionId in each
message type. This means we can always recognize to which transaction
a request belongs. This means the workaround is no longer needed and we
may remove it in favor of a much simpler and cleaner implementation.
Related: SYS#8100
Change-Id: Idbf2604594627ab610cd5d65c91ae1705c3a72f4
---
M include/mnesia_db_work.hrl
M src/esipa_asn1_handler.erl
M src/esipa_asn1_handler_utils.erl
M src/esipa_asn1_http_handler.erl
M src/esipa_json_handler.erl
M src/esipa_json_http_handler.erl
M src/mnesia_db.erl
M src/mnesia_db_rest.erl
M src/mnesia_db_work.erl
9 files changed, 302 insertions(+), 316 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/onomondo-eim refs/changes/59/43659/1
diff --git a/include/mnesia_db_work.hrl b/include/mnesia_db_work.hrl
index 5096644..d78402e 100644
--- a/include/mnesia_db_work.hrl
+++ b/include/mnesia_db_work.hrl
@@ -1,19 +1,19 @@
% In this table record we hold the state (work item) of a transaction that is currently processed (worked on). A work
-% item is created when a requiest from the IPAd positively maps to a pending order in the REST table
+% item is created when a requiest from the IPAd positively maps (EID matches) to a pending order in the REST table
% (see mnesia_db_rest). A work item can be understood as the dynamic state of the ongoing connection between eIM and
% IPAd (and SM-DP+). When the transaction is done and the work is finished, the related work item is deleted and the
% outcome is recorded at the related REST resource.
-record(work, {
- % PID of the sub-process (cowbow) on which the work item is processed.
- pid :: pid(),
- % identifier of the related REST resource
+ % identifier of the related REST resource (primary key)
resourceId :: binary(),
- % transaction ID (either eimTransactionId or transactionId, see also SGP.32 and SGP.22)
+ % transaction ID (secondary key, see also SGP.32 and SGP.22)
transactionId :: binary(),
+ % EIM transaction ID (secondary key, see also SGP.32)
+ eimTransactionId :: binary(),
% EID of the related eUICC
eidValue :: binary(),
% order parameters received on creation of the related REST resource
order :: tuple(),
% intermediate results and states generated while processing the requested order
- state :: any()
+ state :: map()
}).
diff --git a/src/esipa_asn1_handler.erl b/src/esipa_asn1_handler.erl
index 9cb264a..f21d89f 100644
--- a/src/esipa_asn1_handler.erl
+++ b/src/esipa_asn1_handler.erl
@@ -7,15 +7,15 @@
-module(esipa_asn1_handler).
--export([handle_asn1/2]).
+-export([handle_asn1/1]).
%GSMA SGP.32, section 6.3.2.1
-handle_asn1(Pid, {initiateAuthenticationRequestEsipa, EsipaReq}) ->
+handle_asn1({initiateAuthenticationRequestEsipa, EsipaReq}) ->
EimTransactionId = maps:get(eimTransactionId, EsipaReq, none),
- {_, _, WorkState} = mnesia_db_work:pickup(Pid, EimTransactionId),
+ {_, _, WorkState} = mnesia_db_work:pickup(eimTransactionId, EimTransactionId),
BaseUrl = maps:get(smdpAddress, EsipaReq),
NewWorkState = WorkState#{smdpAddress => BaseUrl},
- mnesia_db_work:update(Pid, NewWorkState),
+ mnesia_db_work:update(eimTransactionId, EimTransactionId, NewWorkState),
% euiccInfo1 is also an optional field in initiateAuthenticationRequestEsipa and a mandatory field in
% initiateAuthenticationRequest. However the field is only missing in case the IPA capability minimizeEsipaBytes is
@@ -40,7 +40,7 @@
% TODO: Verify SM-DP+ OID. An Activation Code may contain an SM-DP+ OID. Make sure that this OID
% matches the OID from the serverCertificate (see also SGP.32, section 3.2.3.2, step 10).
TransactionId = maps:get(transactionId, InitAuthOk),
- mnesia_db_work:bind(Pid, TransactionId),
+ mnesia_db_work:bind(EimTransactionId, TransactionId),
% TODO: matchingId and ctxParams1 are not defined in the ES9+ InitiateAuthenticationResponse message.
% However in ESipa those fields are optional fields and either one of it should be populated in case an
% AC is used (which we do). This means we should populate those fields. The matchingId can be extracted
@@ -59,14 +59,14 @@
{initiateAuthenticationOkEsipa, InitAuthOkEsipa};
{initiateAuthenticationError, InitAuthErr} ->
Outcome = [{[{initiateAuthenticationError, InitAuthErr}]}],
- ok = mnesia_db_work:finish(Pid, Outcome, EsipaReq),
+ ok = mnesia_db_work:finish(eimTransactionId, EimTransactionId, Outcome, EsipaReq),
{initiateAuthenticationErrorEsipa, InitAuthErr}
end,
{initiateAuthenticationResponseEsipa, EsipaResp};
%GSMA SGP.32, section 6.3.2.2
-handle_asn1(Pid, {authenticateClientRequestEsipa, EsipaReq}) ->
+handle_asn1({authenticateClientRequestEsipa, EsipaReq}) ->
TransactionId = maps:get(transactionId, EsipaReq),
- {EidValue, Order, WorkState} = mnesia_db_work:pickup(Pid, TransactionId),
+ {EidValue, Order, WorkState} = mnesia_db_work:pickup(transactionId, TransactionId),
BaseUrl = maps:get(smdpAddress, WorkState),
% setup ES9+ request message
@@ -82,7 +82,7 @@
}};
{authenticateResponseError, AuthRespErr} ->
OutcomeEsipa = [{[{authenticateResponseError, AuthRespErr}]}],
- ok = mnesia_db_work:finish(Pid, OutcomeEsipa, EsipaReq),
+ ok = mnesia_db_work:finish(transactionId, TransactionId, OutcomeEsipa, EsipaReq),
{authenticateClientRequest, #{
transactionId => TransactionId,
authenticateServerResponse => {authenticateResponseError, AuthRespErr}
@@ -127,14 +127,14 @@
{authenticateClientOkDPEsipa, AuthenticateClientOkDPEsipa};
{authenticateClientError, AuthClntErr} ->
OutcomeEs9p = [{[{authenticateClientError, AuthClntErr}]}],
- ok = mnesia_db_work:finish(Pid, OutcomeEs9p, EsipaReq),
+ ok = mnesia_db_work:finish(transactionId, TransactionId, OutcomeEs9p, EsipaReq),
{authenticateClientErrorEsipa, AuthClntErr}
end,
{authenticateClientResponseEsipa, EsipaResp};
%GSMA SGP.32, section 6.3.2.3
-handle_asn1(Pid, {getBoundProfilePackageRequestEsipa, EsipaReq}) ->
+handle_asn1({getBoundProfilePackageRequestEsipa, EsipaReq}) ->
TransactionId = maps:get(transactionId, EsipaReq),
- {_, _, WorkState} = mnesia_db_work:pickup(Pid, TransactionId),
+ {_, _, WorkState} = mnesia_db_work:pickup(transactionId, TransactionId),
BaseUrl = maps:get(smdpAddress, WorkState),
% setup ES9+ request message
@@ -149,7 +149,7 @@
{downloadResponseError, DwnldRespErr} ->
DownloadErrorCode = maps:get(downloadErrorCode, DwnldRespErr),
OutcomeEsipa = [{[{downloadResponseError, DownloadErrorCode}]}],
- ok = mnesia_db_work:finish(Pid, OutcomeEsipa, EsipaReq),
+ ok = mnesia_db_work:finish(transactionId, TransactionId, OutcomeEsipa, EsipaReq),
{getBoundProfilePackageRequest, #{
transactionId => TransactionId,
prepareDownloadResponse => {downloadResponseError, DwnldRespErr}
@@ -171,14 +171,14 @@
{getBoundProfilePackageOkEsipa, GetBndPrflePkgOk};
{getBoundProfilePackageError, GetBndPrflePkgErr} ->
OutcomeEs9p = [{[{getBoundProfilePackageError, GetBndPrflePkgErr}]}],
- ok = mnesia_db_work:finish(Pid, OutcomeEs9p, EsipaReq),
+ ok = mnesia_db_work:finish(transactionId, TransactionId, OutcomeEs9p, EsipaReq),
{getBoundProfilePackageErrorEsipa, GetBndPrflePkgErr}
end,
{getBoundProfilePackageResponseEsipa, EsipaResp};
%GSMA SGP.32, section 6.3.2.5
-handle_asn1(Pid, {cancelSessionRequestEsipa, EsipaReq}) ->
+handle_asn1({cancelSessionRequestEsipa, EsipaReq}) ->
TransactionId = maps:get(transactionId, EsipaReq),
- {_, _, WorkState} = mnesia_db_work:pickup(Pid, TransactionId),
+ {_, _, WorkState} = mnesia_db_work:pickup(transactionId, TransactionId),
BaseUrl = maps:get(smdpAddress, WorkState),
% setup ES9+ request message
@@ -204,14 +204,14 @@
{cancelSessionResponseEs9, Es9Resp} = es9p_client:request_json(Es9Req, BaseUrl),
Outcome = esipa_rest_utils:cancelSessionResponse_to_outcome(CancelSessionResp),
- ok = mnesia_db_work:finish(Pid, Outcome, EsipaReq),
+ ok = mnesia_db_work:finish(transactionId, TransactionId, Outcome, EsipaReq),
% setup ESipa response message
% CancelSessionResponseEsipa and CancelSessionResponseEs9 share the exact same definition, so we may convert
% without an extra case statement.
{cancelSessionResponseEsipa, Es9Resp};
%GSMA SGP.32, section 6.3.2.4
-handle_asn1(Pid, {handleNotificationEsipa, EsipaReq}) ->
+handle_asn1({handleNotificationEsipa, EsipaReq}) ->
case EsipaReq of
{pendingNotification, PendingNotif} ->
case PendingNotif of
@@ -233,18 +233,9 @@
% notification receivers (see also GSMA SGP.32, section 3.7) procedure. By then the context in the
% eIM may be long gone. The eIM will be unable to match the ProfileInstallationResult to any
% context but it will foward it to the SMDP+ anyway.
- case mnesia_db_work:bind(Pid, TransactionId) of
- ok ->
- % A related work item exists, make the notification contents available to the REST API user
- Outcome = esipa_rest_utils:profileInstallationResult_to_outcome(
- PrfleInstRslt
- ),
- ok = mnesia_db_work:finish(Pid, Outcome, EsipaReq);
- _ ->
- % No related work item exists, so we cannot do anything useful with the notification
- % contents.
- ok
- end,
+ Outcome = esipa_rest_utils:profileInstallationResult_to_outcome(PrfleInstRslt),
+ mnesia_db_work:finish(transactionId, TransactionId, Outcome, EsipaReq),
+
% foward the ProfileInstallationResult
{} = es9p_client:request_json(Es9Req, BaseUrl);
{otherSignedNotification, OtherSignNotif} ->
@@ -265,14 +256,14 @@
{provideEimPackageResult, _PrvdeEimPkgRslt} ->
%Use the already existing handle_asn1 function to prcess the provideEimPackageResult we got here
%(provideEimPackageResult is directed to the eIM itsself, so there will be no ES9+ request)
- handle_asn1(Pid, {provideEimPackageResult, EsipaReq})
+ handle_asn1({provideEimPackageResult, EsipaReq})
end,
% There is no response defined for this function (see also SGP.32, section 6.3.2.4), so we send just an empty
% response (0 bytes of data)
emptyResponse;
%GSMA SGP.32, section 6.3.2.6
-handle_asn1(Pid, {getEimPackageRequest, EsipaReq}) ->
+handle_asn1({getEimPackageRequest, EsipaReq}) ->
EidValue = maps:get(eidValue, EsipaReq),
% Store stateChangeCause, but only in case the EID is already known to this eIM as we do not want to record any
@@ -300,16 +291,10 @@
end,
% Continue with the processing of the getEimPackageRequest
- Work = mnesia_db_work:fetch(utils:binary_to_hex(EidValue), Pid),
+ Work = mnesia_db_work:fetch(utils:binary_to_hex(EidValue)),
EsipaResp =
case Work of
- {download, Order} ->
- % The first time we see a transactionId from the SM-DP+ is in the SM-DP+ response to the
- % initiateAuthenticationRequest. Until this point we will use an eimTransactionId as a
- % temporary identifier.
- EimTransactionId = rand:bytes(16),
- mnesia_db_work:bind(Pid, EimTransactionId),
- mnesia_db_work:update(Pid, #{}),
+ {download, EimTransactionId, Order} ->
{[{<<"download">>, {Download}}]} = Order,
% TODO: Add missing download options: This eIM currently only allows to trigger a profile download using
% an activationCode (option a) It still lacks download triggers via SM-DS (option b) and downloads from
@@ -324,9 +309,7 @@
profileDownloadData => {activationCode, ActivationCode},
eimTransactionId => EimTransactionId
}};
- {psmo, Order} ->
- EimTransactionId = rand:bytes(16),
- mnesia_db_work:bind(Pid, EimTransactionId),
+ {psmo, EimTransactionId, Order} ->
EuiccPackageSigned = esipa_rest_utils:psmo_order_to_euiccPackageSigned(
Order,
EidValue,
@@ -335,7 +318,9 @@
case EuiccPackageSigned of
error ->
Outcome = [{[{eimProcedureError, badOrder}]}],
- ok = mnesia_db_work:finish(Pid, Outcome, EsipaReq),
+ ok = mnesia_db_work:finish(
+ eimTransactionId, EimTransactionId, Outcome, EsipaReq
+ ),
{eimPackageError, undefinedError};
_ ->
EimSignature = crypto_utils:sign_euiccPackageSigned(
@@ -347,9 +332,7 @@
eimSignature => EimSignature
}}
end;
- {eco, Order} ->
- EimTransactionId = rand:bytes(16),
- mnesia_db_work:bind(Pid, EimTransactionId),
+ {eco, EimTransactionId, Order} ->
EuiccPackageSigned = esipa_rest_utils:eco_order_to_euiccPackageSigned(
Order,
EidValue,
@@ -358,7 +341,9 @@
case EuiccPackageSigned of
error ->
Outcome = [{[{eimProcedureError, badOrder}]}],
- ok = mnesia_db_work:finish(Pid, Outcome, EsipaReq),
+ ok = mnesia_db_work:finish(
+ eimTransactionId, EimTransactionId, Outcome, EsipaReq
+ ),
{eimPackageError, undefinedError};
_ ->
EimSignature = crypto_utils:sign_euiccPackageSigned(
@@ -370,52 +355,62 @@
eimSignature => EimSignature
}}
end;
- {edr, Order} ->
- EimTransactionId = rand:bytes(16),
- mnesia_db_work:bind(Pid, EimTransactionId),
+ {edr, EimTransactionId, Order} ->
IpaEuiccDataRequest = esipa_rest_utils:edr_order_to_ipaEuiccDataRequest(
Order, EimTransactionId
),
case IpaEuiccDataRequest of
error ->
Outcome = [{[{eimProcedureError, badOrder}]}],
- ok = mnesia_db_work:finish(Pid, Outcome, EsipaReq),
+ ok = mnesia_db_work:finish(
+ eimTransactionId, EimTransactionId, Outcome, EsipaReq
+ ),
{eimPackageError, undefinedError};
_ ->
IpaEuiccDataRequest
end;
+ {Facility, EimTransactionId, _} ->
+ logger:error(
+ "Cannot handle request, facility unknown,~nFacility=~p,~nEimTransactionId=~p~n",
+ [Facility, EimTransactionId]
+ ),
+ ok = mnesia_db_work:finish(
+ eimTransactionId,
+ EimTransactionId,
+ [{[{eimProcedureError, badOrder}]}],
+ EsipaReq
+ ),
+ {eimPackageError, undefinedError};
none ->
+ % Technically not an error, just means that there is currently nothing to do.
{eimPackageError, noEimPackageAvailable};
_ ->
- ok = mnesia_db_work:finish(Pid, [{[{eimProcedureError, badOrder}]}], EsipaReq),
{eimPackageError, undefinedError}
end,
{getEimPackageResponse, EsipaResp};
%GSMA SGP.32, section 6.3.2.7
-handle_asn1(Pid, {provideEimPackageResult, EsipaReq}) ->
+handle_asn1({provideEimPackageResult, EsipaReq}) ->
EimPackageResult = maps:get(eimPackageResult, EsipaReq),
case EimPackageResult of
{euiccPackageResult, EuiccPackageResult} ->
ok = esipa_asn1_handler_utils:handle_euiccPackageResult(
- Pid, EuiccPackageResult, EsipaReq
+ EuiccPackageResult, EsipaReq
);
{ePRAndNotifications, EPRAndNotifications} ->
% Handle the euiccPackageResult first,
EuiccPackageResult = maps:get(euiccPackageResult, EPRAndNotifications),
ok = esipa_asn1_handler_utils:handle_euiccPackageResult(
- Pid, EuiccPackageResult, EsipaReq
+ EuiccPackageResult, EsipaReq
),
% then forward the notifications in the included notification list
NotificationList = maps:get(notificationList, EPRAndNotifications),
[
- handle_asn1(
- Pid, {handleNotificationEsipa, {pendingNotification, PendingNotification}}
- )
+ handle_asn1({handleNotificationEsipa, {pendingNotification, PendingNotification}})
|| PendingNotification <- NotificationList
];
{ipaEuiccDataResponse, IpaEuiccDataResponse} ->
ok = esipa_asn1_handler_utils:handle_ipaEuiccDataResponse(
- Pid, IpaEuiccDataResponse, EsipaReq
+ IpaEuiccDataResponse, EsipaReq
);
{profileDownloadTriggerResult, _} ->
% The profileDownloadTriggerResult is sent by the IPAd in case a profile was downloaded directly from an
@@ -424,16 +419,14 @@
throw("unsuppported message type \"profileDownloadTriggerResult\"");
{eimPackageResultResponseError, EimPackageResultResponseError} ->
ok = esipa_asn1_handler_utils:handle_eimPackageResultResponseError(
- Pid, EimPackageResultResponseError, EsipaReq
+ EimPackageResultResponseError, EsipaReq
)
end,
{provideEimPackageResultResponse, {emptyResponse, #{}}};
%Unsupported request
-handle_asn1(Pid, Request) ->
- Outcome = [{[{eimProcedureError, abortedOrder}]}],
- mnesia_db_work:finish(Pid, Outcome, unsupported),
+handle_asn1(Request) ->
logger:info(
- "Handling of IPAd request failed, the request type is unsupported,~nRequest=~p,~nPid=~p~n",
- [Request, Pid]
+ "Handling of IPAd request failed, the request type is unsupported,~nRequest=~p~n",
+ [Request]
),
{error, unsupported_request}.
diff --git a/src/esipa_asn1_handler_utils.erl b/src/esipa_asn1_handler_utils.erl
index ebff01b..844fdc4 100644
--- a/src/esipa_asn1_handler_utils.erl
+++ b/src/esipa_asn1_handler_utils.erl
@@ -7,9 +7,9 @@
-module(esipa_asn1_handler_utils).
-export([
- handle_euiccPackageResult/3,
- handle_ipaEuiccDataResponse/3,
- handle_eimPackageResultResponseError/3
+ handle_euiccPackageResult/2,
+ handle_ipaEuiccDataResponse/2,
+ handle_eimPackageResultResponseError/2
]).
eimTransactionId_from_euiccPackageResult(EuiccPackageResult) ->
@@ -42,9 +42,9 @@
% Handle an EuiccPackageResult, this includes everything from the handling of the work items in mnesia_db, down to
% signature checks and the generation of an appropriate outcome for the REST API.
-handle_euiccPackageResult(Pid, EuiccPackageResult, Debuginfo) ->
+handle_euiccPackageResult(EuiccPackageResult, Debuginfo) ->
EimTransactionId = eimTransactionId_from_euiccPackageResult(EuiccPackageResult),
- {EidValue, _, _} = mnesia_db_work:pickup(Pid, EimTransactionId),
+ {EidValue, _, _} = mnesia_db_work:pickup(eimTransactionId, EimTransactionId),
CheckCounterValue = fun(Map) ->
CounterValueIpad = maps:get(counterValue, Map),
@@ -108,26 +108,26 @@
[{[{eimProcedureError, badEuiccResult}]}]
end,
- mnesia_db_work:finish(Pid, Outcome, Debuginfo).
+ mnesia_db_work:finish(eimTransactionId, EimTransactionId, Outcome, Debuginfo).
% Handle an IpaEuiccDataResponse, this includes everything from the handling of the work items in mnesia_db as well
% as the generation of an appropriate outcome for the REST API. In case IpaEuiccDataResponse contains an eUICC public
% key, we will automatically store it so that we can use it to check the signatures of PSMOs and eCOs.
-handle_ipaEuiccDataResponse(Pid, IpaEuiccDataResponse, Debuginfo) ->
+handle_ipaEuiccDataResponse(IpaEuiccDataResponse, Debuginfo) ->
EimTransactionId = eimTransactionId_from_ipaEuiccDataResponse(IpaEuiccDataResponse),
- {EidValue, _, _} = mnesia_db_work:pickup(Pid, EimTransactionId),
+ {EidValue, _, _} = mnesia_db_work:pickup(eimTransactionId, EimTransactionId),
% drive-by store the eUICC public key so that we can use it later to check the signatures of PSMOs or eCOs
crypto_utils:store_euicc_pubkey_from_ipaEuiccDataResponse(IpaEuiccDataResponse, EidValue),
Outcome = esipa_rest_utils:ipaEuiccDataResponse_to_outcome(IpaEuiccDataResponse),
- mnesia_db_work:finish(Pid, Outcome, Debuginfo).
+ mnesia_db_work:finish(eimTransactionId, EimTransactionId, Outcome, Debuginfo).
% Handle an EimPackageResultResponseError, this includes handling of the work items in mnesia_db and the generation of
% an appropriate REST outcome for the REST API.
-handle_eimPackageResultResponseError(Pid, EimPackageResultResponseError, Debuginfo) ->
+handle_eimPackageResultResponseError(EimPackageResultResponseError, Debuginfo) ->
EimTransactionId = maps:get(eimTransactionId, EimPackageResultResponseError),
- {_, _, _} = mnesia_db_work:pickup(Pid, EimTransactionId),
+ {_, _, _} = mnesia_db_work:pickup(eimTransactionId, EimTransactionId),
EimPackageResultErrorCode = maps:get(eimPackageResultErrorCode, EimPackageResultResponseError),
Outcome = [{[{eimPackageResultError, EimPackageResultErrorCode}]}],
- mnesia_db_work:finish(Pid, Outcome, Debuginfo).
+ mnesia_db_work:finish(eimTransactionId, EimTransactionId, Outcome, Debuginfo).
diff --git a/src/esipa_asn1_http_handler.erl b/src/esipa_asn1_http_handler.erl
index fdb5706..331f7d5 100644
--- a/src/esipa_asn1_http_handler.erl
+++ b/src/esipa_asn1_http_handler.erl
@@ -25,17 +25,17 @@
{ok, IpaToEim} = esipa_asn1_codec:decode_ipa_to_eim(Data),
{EsipaMsgType, _} = IpaToEim,
logger:info(
- "Handling incoming IPAd request (ASN.1): ~p,~nPeer=~p, Pid=~p~n",
- [EsipaMsgType, maps:get(peer, Req0), maps:get(pid, Req0)]
+ "Handling incoming IPAd request (ASN.1): ~p,~nPeer=~p~n",
+ [EsipaMsgType, maps:get(peer, Req0)]
),
logger:debug(
- "Rx ESipa ASN.1,~nPeer=~p, Pid=~p,~nIpaToEim=~p~n",
- [maps:get(peer, Req0), maps:get(pid, Req0), IpaToEim]
+ "Rx ESipa ASN.1,~nPeer=~p,~nIpaToEim=~p~n",
+ [maps:get(peer, Req0), IpaToEim]
),
- EimToIpa = esipa_asn1_handler:handle_asn1(maps:get(pid, Req0), IpaToEim),
+ EimToIpa = esipa_asn1_handler:handle_asn1(IpaToEim),
logger:debug(
- "Tx ESipa ASN.1,~nPeer=~p,Pid=~p,~nEimToIpa=~p~n",
- [maps:get(peer, Req0), maps:get(pid, Req0), EimToIpa]
+ "Tx ESipa ASN.1,~nPeer=~p,~nEimToIpa=~p~n",
+ [maps:get(peer, Req0), EimToIpa]
),
case EimToIpa of
{error, unsupported_request} ->
@@ -60,12 +60,9 @@
normal ->
ok;
_ ->
- mnesia_db_work:finish(
- maps:get(pid, Req0), [{[{eimProcedureError, abortedOrder}]}], Reason
- ),
logger:info(
- "Handling of IPAd request (ASN.1) terminated unexpectedly, Reason=~p Pid=~p~n",
- [Reason, maps:get(pid, Req0)]
+ "Handling of IPAd request (ASN.1) terminated unexpectedly, Reason=~p~n",
+ [Reason]
),
cowboy_req:reply(500, ?RESPONSE_HEADERS, <<"Internal Server Error">>, Req0)
end.
diff --git a/src/esipa_json_handler.erl b/src/esipa_json_handler.erl
index f5fc3e3..6e55675 100644
--- a/src/esipa_json_handler.erl
+++ b/src/esipa_json_handler.erl
@@ -6,7 +6,7 @@
-module(esipa_json_handler).
--export([handle_json/2]).
+-export([handle_json/1]).
% Decode hex-string to binary
to_binary(absent) ->
@@ -74,7 +74,7 @@
end.
%GSMA SGP.32, section 6.4.1.1
-handle_json(Pid, {<<"/gsma/rsp2/esipa/initiateAuthentication">>, EsipaReq}) ->
+handle_json({<<"/gsma/rsp2/esipa/initiateAuthentication">>, EsipaReq}) ->
Req = join([
{euiccChallenge, from_base64(maps:get(<<"euiccChallenge">>, EsipaReq, absent))},
{euiccInfo1,
@@ -86,7 +86,7 @@
]),
EsipaReqAsn = {initiateAuthenticationRequestEsipa, Req},
- EimToIpaAsn = esipa_asn1_handler:handle_asn1(Pid, EsipaReqAsn),
+ EimToIpaAsn = esipa_asn1_handler:handle_asn1(EsipaReqAsn),
case EimToIpaAsn of
{initiateAuthenticationResponseEsipa,
@@ -127,7 +127,7 @@
join([{header, #{<<"functionExecutionStatus">> => #{<<"status">> => <<"Failed">>}}}])
end;
%GSMA SGP.32, section 6.4.1.2
-handle_json(Pid, {<<"/gsma/rsp2/esipa/authenticateClient">>, EsipaReq}) ->
+handle_json({<<"/gsma/rsp2/esipa/authenticateClient">>, EsipaReq}) ->
Req = join([
{transactionId, to_binary(maps:get(<<"transactionId">>, EsipaReq))},
{authenticateServerResponse,
@@ -139,7 +139,7 @@
]),
EsipaReqAsn = {authenticateClientRequestEsipa, Req},
- EimToIpaAsn = esipa_asn1_handler:handle_asn1(Pid, EsipaReqAsn),
+ EimToIpaAsn = esipa_asn1_handler:handle_asn1(EsipaReqAsn),
case EimToIpaAsn of
{authenticateClientResponseEsipa,
@@ -182,7 +182,7 @@
join([{header, #{<<"functionExecutionStatus">> => #{<<"status">> => <<"Failed">>}}}])
end;
%GSMA SGP.32, section 6.4.1.3
-handle_json(Pid, {<<"/gsma/rsp2/esipa/getBoundProfilePackage">>, EsipaReq}) ->
+handle_json({<<"/gsma/rsp2/esipa/getBoundProfilePackage">>, EsipaReq}) ->
Req = join([
{transactionId, to_binary(maps:get(<<"transactionId">>, EsipaReq))},
{prepareDownloadResponse,
@@ -194,7 +194,7 @@
]),
EsipaReqAsn = {getBoundProfilePackageRequestEsipa, Req},
- EimToIpaAsn = esipa_asn1_handler:handle_asn1(Pid, EsipaReqAsn),
+ EimToIpaAsn = esipa_asn1_handler:handle_asn1(EsipaReqAsn),
case EimToIpaAsn of
{getBoundProfilePackageResponseEsipa,
@@ -219,7 +219,7 @@
join([{header, #{<<"functionExecutionStatus">> => #{<<"status">> => <<"Failed">>}}}])
end;
%GSMA SGP.32, section 6.4.1.5
-handle_json(Pid, {<<"/gsma/rsp2/esipa/getEimPackage">>, EsipaReq}) ->
+handle_json({<<"/gsma/rsp2/esipa/getEimPackage">>, EsipaReq}) ->
NotifyStateChange =
case maps:get(<<"notifyStateChange">>, EsipaReq, false) of
true ->
@@ -259,7 +259,7 @@
]),
EsipaReqAsn = {getEimPackageRequest, Req},
- EimToIpaAsn = esipa_asn1_handler:handle_asn1(Pid, EsipaReqAsn),
+ EimToIpaAsn = esipa_asn1_handler:handle_asn1(EsipaReqAsn),
case EimToIpaAsn of
{getEimPackageResponse, {euiccPackageRequest, EuiccPackageRequest}} ->
@@ -318,7 +318,7 @@
join([{header, #{<<"functionExecutionStatus">> => #{<<"status">> => <<"Failed">>}}}])
end;
%GSMA SGP.32, section 6.4.1.6
-handle_json(Pid, {<<"/gsma/rsp2/esipa/provideEimPackageResult">>, EsipaReq}) ->
+handle_json({<<"/gsma/rsp2/esipa/provideEimPackageResult">>, EsipaReq}) ->
Req = join([
{eidValue, to_binary(maps:get(<<"eidValue">>, EsipaReq, absent))},
{eimPackageResult,
@@ -328,7 +328,7 @@
]),
EsipaReqAsn = {provideEimPackageResult, Req},
- EimToIpaAsn = esipa_asn1_handler:handle_asn1(Pid, EsipaReqAsn),
+ EimToIpaAsn = esipa_asn1_handler:handle_asn1(EsipaReqAsn),
case EimToIpaAsn of
{provideEimPackageResultResponse, {eimAcknowledgements, EimAcknowledgements}} ->
@@ -354,7 +354,7 @@
join([{header, #{<<"functionExecutionStatus">> => #{<<"status">> => <<"Failed">>}}}])
end;
%GSMA SGP.32, section 6.4.1.7
-handle_json(Pid, {<<"/gsma/rsp2/esipa/handleNotification">>, EsipaReq}) ->
+handle_json({<<"/gsma/rsp2/esipa/handleNotification">>, EsipaReq}) ->
Req = choose([
{pendingNotification,
from_base64asn1(
@@ -371,7 +371,7 @@
]),
EsipaReqAsn = {handleNotificationEsipa, Req},
- EimToIpaAsn = esipa_asn1_handler:handle_asn1(Pid, EsipaReqAsn),
+ EimToIpaAsn = esipa_asn1_handler:handle_asn1(EsipaReqAsn),
case EimToIpaAsn of
emptyResponse ->
@@ -384,7 +384,7 @@
join([{header, #{<<"functionExecutionStatus">> => #{<<"status">> => <<"Failed">>}}}])
end;
%GSMA SGP.32, section 6.4.1.8
-handle_json(Pid, {<<"/gsma/rsp2/esipa/cancelSession">>, EsipaReq}) ->
+handle_json({<<"/gsma/rsp2/esipa/cancelSession">>, EsipaReq}) ->
Req = join([
{transactionId, to_binary(maps:get(<<"transactionId">>, EsipaReq))},
{cancelSessionResponse,
@@ -396,7 +396,7 @@
]),
EsipaReqAsn = {cancelSessionRequestEsipa, Req},
- EimToIpaAsn = esipa_asn1_handler:handle_asn1(Pid, EsipaReqAsn),
+ EimToIpaAsn = esipa_asn1_handler:handle_asn1(EsipaReqAsn),
case EimToIpaAsn of
{cancelSessionResponseEsipa, {cancelSessionOk, _CancelSessionOk}} ->
@@ -411,10 +411,9 @@
join([{header, #{<<"functionExecutionStatus">> => #{<<"status">> => <<"Failed">>}}}])
end;
%Unsupported request
-handle_json(Pid, Request) ->
- mnesia_db_work:finish(Pid, [{[{eimProcedureError, abortedOrder}]}], unsupported),
+handle_json(Request) ->
logger:info(
- "Handling of IPAd request failed, the request type is unsupported,~nRequest=~p,~nPid=~p~n",
- [Request, Pid]
+ "Handling of IPAd request failed, the request type is unsupported,~nRequest=~p~n",
+ [Request]
),
{error, unsupported_request}.
diff --git a/src/esipa_json_http_handler.erl b/src/esipa_json_http_handler.erl
index 20fb61a..026d342 100644
--- a/src/esipa_json_http_handler.erl
+++ b/src/esipa_json_http_handler.erl
@@ -20,17 +20,17 @@
IpaToEim = jiffy:decode(Data, [return_maps]),
Path = cowboy_req:path(Req0),
logger:info(
- "Handling incoming IPAd request (JSON): ~p,~nPeer=~p, Pid=~p~n",
- [Path, maps:get(peer, Req0), maps:get(pid, Req0)]
+ "Handling incoming IPAd request (JSON): ~p,~nPeer=~p~n",
+ [Path, maps:get(peer, Req0)]
),
logger:debug(
- "Rx ESipa JSON,~nPeer=~p, Pid=~p,~nIpaToEim=~p~n",
- [maps:get(peer, Req0), maps:get(pid, Req0), IpaToEim]
+ "Rx ESipa JSON,~nPeer=~p,~nIpaToEim=~p~n",
+ [maps:get(peer, Req0), IpaToEim]
),
- EimToIpa = esipa_json_handler:handle_json(maps:get(pid, Req0), {Path, IpaToEim}),
+ EimToIpa = esipa_json_handler:handle_json({Path, IpaToEim}),
logger:debug(
- "Tx ESipa JSON,~nPeer=~p,Pid=~p,~nEimToIpa=~p~n",
- [maps:get(peer, Req0), maps:get(pid, Req0), EimToIpa]
+ "Tx ESipa JSON,~nPeer=~p,~nEimToIpa=~p~n",
+ [maps:get(peer, Req0), EimToIpa]
),
case EimToIpa of
{error, unsupported_request} ->
@@ -55,12 +55,9 @@
normal ->
ok;
_ ->
- mnesia_db_work:finish(
- maps:get(pid, Req0), [{[{eimProcedureError, abortedOrder}]}], Reason
- ),
logger:info(
- "Handling of IPAd request (JSON) terminated unexpectedly, Reason=~p Pid=~p~n",
- [Reason, maps:get(pid, Req0)]
+ "Handling of IPAd request (JSON) terminated unexpectedly, Reason=~p~n",
+ [Reason]
),
cowboy_req:reply(500, ?RESPONSE_HEADERS, <<"Internal Server Error">>, Req0)
end.
diff --git a/src/mnesia_db.erl b/src/mnesia_db.erl
index 62cd861..d44de1c 100644
--- a/src/mnesia_db.erl
+++ b/src/mnesia_db.erl
@@ -51,6 +51,7 @@
work,
[
{attributes, record_info(fields, work)},
+ {index, [transactionId, eimTransactionId]},
{type, set}
]
)
diff --git a/src/mnesia_db_rest.erl b/src/mnesia_db_rest.erl
index cef68c9..bdf66de 100644
--- a/src/mnesia_db_rest.erl
+++ b/src/mnesia_db_rest.erl
@@ -115,25 +115,9 @@
[] ->
none;
_ ->
+ ok = mnesia_db_work:trans_delete_work(ResourceId),
OidRest = {rest, ResourceId},
- ok = mnesia:delete(OidRest),
-
- % There may be an orphaned work item now, which we must also remove. This will also kill
- % the order in case it is currently in progress.
- QWork = qlc:q([
- X#work.pid
- || X <- mnesia:table(work), X#work.resourceId == ResourceId
- ]),
- WorkPresent = qlc:e(QWork),
- case WorkPresent of
- [] ->
- ok;
- [Pid] ->
- OidWork = {work, Pid},
- mnesia:delete(OidWork);
- _ ->
- error
- end
+ mnesia:delete(OidRest)
end
end,
{atomic, Result} = mnesia:transaction(Trans),
@@ -157,18 +141,7 @@
% Remove Resource from work table and set an appropriate status in the rest table
HandleResource = fun(ResourceId) ->
- % find the pid of the work item that is stuck and then delete it
- Q = qlc:q([X#work.pid || X <- mnesia:table(work), X#work.resourceId == ResourceId]),
- WorkPresent = qlc:e(Q),
- case WorkPresent of
- [Pid] ->
- Oid = {work, Pid},
- ok = mnesia:delete(Oid);
- _ ->
- ok
- end,
-
- % set status in the rest table
+ mnesia_db_work:trans_delete_work(ResourceId),
trans_set_status(ResourceId, done, [{[{eimProcedureError, stuckOrder}]}], none)
end,
diff --git a/src/mnesia_db_work.erl b/src/mnesia_db_work.erl
index a620ffa..69b15bf 100644
--- a/src/mnesia_db_work.erl
+++ b/src/mnesia_db_work.erl
@@ -10,35 +10,41 @@
-include("mnesia_db_work.hrl").
% work functions, to be called by the eIM code (from inside)
--export([fetch/2, pickup/2, update/2, bind/2, finish/3]).
+-export([fetch/1, pickup/2, update/3, bind/2, finish/4]).
% debugging
-export([dump/0]).
-% Start working on an order by creating a an entry in the work table and marking it's status as "work". After calling
-% this it is the callers responsibility to handle the work item and call rest_finish_order when the work is done.
-fetch(EidValue, Pid) ->
- % One process can only work on one work item at a time. The API user must call finish before the next work
- % item can be processed. If there is already a pending work item under the given PID, forcefully finish this work
- % item.
- TransPidExists = fun() ->
- Q = qlc:q([X || X <- mnesia:table(work), X#work.pid == Pid]),
- WorkPresent = qlc:e(Q),
- case WorkPresent of
- [] ->
- false;
- _ ->
- true
- end
- end,
+% transaction functions (to be called from a transaction)
+-export([trans_delete_work/1]).
- {atomic, PidExists} = mnesia:transaction(TransPidExists),
- case PidExists of
- true ->
- finish(Pid, [{[{eimProcedureError, stuckOrder}]}], none);
- false ->
- ok
- end,
+trans_delete_work(ResourceId) ->
+ % Run a query to check if the work item is still present
+ QWork = qlc:q([X || X <- mnesia:table(work), X#work.resourceId == ResourceId]),
+ WorkPresent = qlc:e(QWork),
+
+ % Delete work item if present
+ case WorkPresent of
+ [] ->
+ % No work item present, everything ok, nothing to delete
+ ok;
+ [_] ->
+ % Work item is present, delete it
+ OidWork = {work, ResourceId},
+ mnesia:delete(OidWork);
+ _ ->
+ error
+ end.
+
+% Start working on an order by creating a an entry in the work table and marking it's status as "work". After calling
+% this function (once), the caller may use the functions (pickup, update, bind, finish) while processing the order.
+fetch(EidValue) ->
+ % All transactons begin with an eimTransactionId, which is generated by the eIM. When the transaction is a profile
+ % download, the SM-DP+ will generate a TransactionId, which will be used as the primary identifier when the profile
+ % download commences. The API user may use the bind function to associate the current work item with the
+ % TransactionId. (Even though the eimTransactionId is no longer used in this scenario, it is not overwritten and
+ % remains valid).
+ EimTransactionId = uuid:get_v4_urandom(),
% Read the next pending REST resource from the rest table and create a related work item. The work item is then
% in progress.
@@ -58,16 +64,17 @@
[Row | _] ->
% Create an entry in the work table
WorkRow = #work{
- pid = Pid,
resourceId = Row#rest.resourceId,
+ eimTransactionId = EimTransactionId,
transactionId = none,
eidValue = Row#rest.eidValue,
order = Row#rest.order,
- state = none
+ state = #{}
},
case mnesia:write(WorkRow) of
ok ->
- % We are now working on this order
+ % Mark the order as being worked on, so that the REST API can know that the order is now
+ % in progress.
ok = mnesia_db_rest:trans_set_status(Row#rest.resourceId, work, [], none),
Row;
_ ->
@@ -82,141 +89,136 @@
{atomic, Result} = mnesia:transaction(Trans),
case Result of
- {rest, _, Facility, _, Order, _, _, _, _} ->
+ {rest, ResourceId, Facility, _, Order, _, _, _, _} ->
logger:info(
- "Work: fetching new work item,~nEidValue=~p, Pid=~p, Facility=~p,~nOrder=~p~n",
- [EidValue, Pid, Facility, Order]
+ "Work: fetching new work item,~nEimTransactionId=~p,~nEidValue=~p,~nResourceId=~p,~nFacility=~p,~nOrder=~p~n",
+ [EimTransactionId, EidValue, ResourceId, Facility, Order]
),
- {Facility, Order};
+ {Facility, EimTransactionId, Order};
none ->
- logger:info("Work: no work item in database,~nEidValue=~p, Pid=~p~n", [EidValue, Pid]),
+ logger:debug(
+ "Work: no work item in database,~nEimTransactionId=~p,~nEidValue=~p~n",
+ [EimTransactionId, EidValue]
+ ),
none;
_ ->
- logger:error("Work: cannot fetch work item, database error,~nEidValue=~p, Pid=~p~n", [
- EidValue, Pid
- ]),
- error
- end.
-
-% Bind a work item to a TransactionId. The transactionId has to be a unique identifier that can be used as a secondary
-% key to find a work item in the databse. The binding works in two directions. The work item is first searched by its
-% pid, when found, the transactionId is updated. In case the pid has become invalid, then the work item is searched
-% again by the transactionId and when found, the pid is updated. This function can be called any time after fetch
-% was called before. It can also be called multiple times.
-bind(Pid, TransactionId) ->
- % Transaction to update the TransactionId. This is the normal case. A work item starts without having a
- % TransactionId assigned. As soon as a (new) TransactionId becomes known, it is updated using this Transaction.
- TransUpdateTrnsId = fun() ->
- Q = qlc:q([X || X <- mnesia:table(work), X#work.pid == Pid]),
- Rows = qlc:e(Q),
- case Rows of
- [Row | _] ->
- mnesia:write(Row#work{transactionId = TransactionId});
- [] ->
- none;
- _ ->
- error
- end
- end,
-
- % Transaction to update the PID. This is a corner case that comes into play in case the PID is lost (the
- % process/connection handling this work item has died). We then try to find the work item by the TransactionId
- % and update its PID.
- TransUpdatePid = fun() ->
- Q = qlc:q([X || X <- mnesia:table(work), X#work.transactionId == TransactionId]),
- Rows = qlc:e(Q),
- case Rows of
- [Row | _] ->
- mnesia:write(Row#work{pid = Pid});
- [] ->
- none;
- _ ->
- error
- end
- end,
-
- {atomic, Result} = mnesia:transaction(TransUpdateTrnsId),
- case Result of
- ok ->
- logger:info("Work: bound work item to transactionId,~nPid=~p, TransactionId=~p~n", [
- Pid, TransactionId
- ]),
- ok;
- none ->
- {atomic, UpdatePidResult} = mnesia:transaction(TransUpdatePid),
- case UpdatePidResult of
- ok ->
- logger:info("Work: bound work item to PID,~nPid=~p, TransactionId=~p~n", [
- Pid, TransactionId
- ]),
- ok;
- none ->
- logger:error(
- "Work: cannot bind work item, transactionId nor PID found,~nPid=~p, TransactionId=~p~n",
- [Pid, TransactionId]
- ),
- error;
- _ ->
- logger:error(
- "Work: cannot bind work item, database error,~nPid=~p, TransactionId=~p, TransUpdatePid~n",
- [Pid, TransactionId]
- ),
- error
- end;
- _ ->
logger:error(
- "Work: cannot bind work item, database error,~nPid=~p, TransactionId=~p, TransUpdateTrnsId~n",
- [Pid, TransactionId]
+ "Work: cannot fetch work item, database error,~nEimTransactionId=~p,~nEidValue=~p~n",
+ [EimTransactionId, EidValue]
),
error
end.
-% Pickup a work item that is in progress. This function can be called any time after fetch was called
-% before. It can also be called multiple times.
-pickup(Pid, TransactionId) ->
- % In case a TransactionId is provied, bind the PID to this TransactionId,
- WorkBound =
- case TransactionId of
- none ->
- ok;
- _ ->
- bind(Pid, TransactionId)
- end,
-
- % Lookup the work state by the given PID
- case WorkBound of
- ok ->
- Trans = fun() ->
- Q = qlc:q([
- {X#work.eidValue, X#work.order, X#work.state}
- || X <- mnesia:table(work), X#work.pid == Pid
+% Bind a work item that is already known by an eimTransactionId to a transactionId (generated by the SM-DP+). After
+% calling this function, the work item is associated with that transactionId and the API user may use the transactionId
+% as identifier with the pickup, update and finish functions. The eimTransactionId remains valid.
+bind(EimTransactionId, TransactionId) ->
+ Trans = fun() ->
+ Q1 = qlc:q([X || X <- mnesia:table(work), X#work.transactionId == TransactionId]),
+ RowsAlreadyPresent = qlc:e(Q1),
+ case RowsAlreadyPresent of
+ [] ->
+ Q2 = qlc:q([
+ X
+ || X <- mnesia:table(work), X#work.eimTransactionId == EimTransactionId
]),
- qlc:e(Q)
- end,
- {atomic, Result} = mnesia:transaction(Trans),
- case Result of
- [{EidValue, Order, State} | _] ->
- {EidValue, Order, State};
- [] ->
- logger:error(
- "Work: no work item found under specified Pid, already finished?, not fetched?,~nPid=~p~n",
- [Pid]
- ),
- none;
- _ ->
- logger:error("Work: cannot pick up work item, database error,~nPid=~p~n", [Pid]),
- error
- end;
+ Rows = qlc:e(Q2),
+ case Rows of
+ [Row | _] ->
+ mnesia:write(Row#work{transactionId = TransactionId});
+ _ ->
+ error
+ end;
+ _ ->
+ inuse
+ end
+ end,
+
+ {atomic, Result} = mnesia:transaction(Trans),
+ case Result of
+ ok ->
+ logger:info(
+ "Work: bound work item to transactionId,~nEimTransactionId=~p,~nTransactionId=~p~n",
+ [
+ EimTransactionId, TransactionId
+ ]
+ ),
+ ok;
+ inuse ->
+ logger:error(
+ "Work: cannot bind work item, TransactionId already in use by other transaction,~nEimTransactionId=~p,~nTransactionId=~p~n",
+ [EimTransactionId, TransactionId]
+ ),
+ error;
_ ->
- WorkBound
+ logger:error(
+ "Work: cannot bind work item, database error,~nEimTransactionId=~p,~nTransactionId=~p~n",
+ [EimTransactionId, TransactionId]
+ ),
+ error
end.
-% Update a work item that is in progress. This function updates the state (any user defined term) of the work item.
-% This function can be called any time after fetch was called before. It can also be called multiple times.
-update(Pid, State) ->
+% Pickup a work item that is in progress. This function may be called any time after the fetch function has been
+% called. It can also be called multiple times.
+pickup(TransactionIdType, TransactionId) ->
Trans = fun() ->
- Q = qlc:q([X || X <- mnesia:table(work), X#work.pid == Pid]),
- Rows = qlc:e(Q),
+ case TransactionIdType of
+ transactionId ->
+ Q = qlc:q([
+ {X#work.eidValue, X#work.order, X#work.state}
+ || X <- mnesia:table(work), X#work.transactionId == TransactionId
+ ]),
+ qlc:e(Q);
+ eimTransactionId ->
+ Q = qlc:q([
+ {X#work.eidValue, X#work.order, X#work.state}
+ || X <- mnesia:table(work), X#work.eimTransactionId == TransactionId
+ ]),
+ qlc:e(Q);
+ _ ->
+ error
+ end
+ end,
+ {atomic, Result} = mnesia:transaction(Trans),
+ case Result of
+ [{EidValue, Order, State} | _] ->
+ logger:info(
+ "Work: picking up work item,~nTransactionIdType=~p,~nTransactionId=~p,~nState=~p~n",
+ [TransactionIdType, TransactionId, State]
+ ),
+ {EidValue, Order, State};
+ [] ->
+ logger:error(
+ "Work: no work item found under specified Pid, already finished?, not fetched?,~nTransactionIdType=~p,~nTransactionId=~p~n",
+ [TransactionIdType, TransactionId]
+ ),
+ none;
+ _ ->
+ logger:error(
+ "Work: cannot pick up work item, database error,~nTransactionIdType=~p,~nTransactionId=~p~n",
+ [TransactionIdType, TransactionId]
+ ),
+ error
+ end.
+
+% Update a work item that is in progress. This function updates the state (map) of the work item. This function may be
+% called any time after the fetch function has been called. It can also be called multiple times.
+update(TransactionIdType, TransactionId, State) ->
+ Trans = fun() ->
+ Rows =
+ case TransactionIdType of
+ transactionId ->
+ Q = qlc:q([X || X <- mnesia:table(work), X#work.transactionId == TransactionId]),
+ qlc:e(Q);
+ eimTransactionId ->
+ Q = qlc:q([
+ X
+ || X <- mnesia:table(work), X#work.eimTransactionId == TransactionId
+ ]),
+ qlc:e(Q);
+ _ ->
+ error
+ end,
case Rows of
[Row | _] ->
mnesia:write(Row#work{state = State});
@@ -230,25 +232,46 @@
{atomic, Result} = mnesia:transaction(Trans),
case Result of
ok ->
- logger:info("Work: updating work item,~nPid=~p, State=~p~n", [Pid, State]),
+ logger:info(
+ "Work: updating work item,~nTransactionIdType=~p,~nTransactionId=~p,~nState=~p~n",
+ [TransactionIdType, TransactionId, State]
+ ),
ok;
_ ->
- logger:error("Work: cannot update, database error,~nPid=~p, State=~p~n", [Pid, State]),
+ logger:error(
+ "Work: cannot update, database error,~nTransactionIdType=~p,~nTransactionId=~p,~nState=~p~n",
+ [TransactionIdType, TransactionId, State]
+ ),
error
end.
-% Finish an order that has been worked on. This removes the related entry from the work table and sets the status in
-% the rest table to "done".
-finish(Pid, Outcome, Debuginfo) ->
+% Finish an order that has been worked on. This function removes the related entry from the work table and sets the
+% status in the rest table to "done". This function may be called any time after the fetch function has been called.
+% It must not be called multiple times.
+finish(TransactionIdType, TransactionId, Outcome, Debuginfo) ->
Trans = fun() ->
- Q = qlc:q([X#work.resourceId || X <- mnesia:table(work), X#work.pid == Pid]),
- Rows = qlc:e(Q),
+ Rows =
+ case TransactionIdType of
+ transactionId ->
+ Q = qlc:q([
+ X#work.resourceId
+ || X <- mnesia:table(work), X#work.transactionId == TransactionId
+ ]),
+ qlc:e(Q);
+ eimTransactionId ->
+ Q = qlc:q([
+ X#work.resourceId
+ || X <- mnesia:table(work), X#work.eimTransactionId == TransactionId
+ ]),
+ qlc:e(Q);
+ _ ->
+ error
+ end,
case Rows of
[] ->
error;
[ResourceId | _] ->
- Oid = {work, Pid},
- ok = mnesia:delete(Oid),
+ ok = trans_delete_work(ResourceId),
ok = mnesia_db_rest:trans_set_status(ResourceId, done, Outcome, Debuginfo)
end
end,
@@ -256,12 +279,15 @@
{atomic, Result} = mnesia:transaction(Trans),
case Result of
ok ->
- logger:info("Work: finishing work item,~nPid=~p, Outcome=~p~n", [Pid, Outcome]),
+ logger:info(
+ "Work: finishing work item,~nTransactionIdType=~p,~nTransactionId=~p,~nOutcome=~p~n",
+ [TransactionIdType, TransactionId, Outcome]
+ ),
ok;
_ ->
logger:error(
- "Work: cannot finish work item, database error,~nPid=~p, Outcome=~p~n",
- [Pid, Outcome]
+ "Work: cannot finish work item, database error,~nTransactionIdType=~p,~nTransactionId=~p,~nOutcome=~p~n",
+ [TransactionIdType, TransactionId, Outcome]
),
error
end.
--
To view, visit https://gerrit.osmocom.org/c/onomondo-eim/+/43659?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: onomondo-eim
Gerrit-Branch: master
Gerrit-Change-Id: Idbf2604594627ab610cd5d65c91ae1705c3a72f4
Gerrit-Change-Number: 43659
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Attention is currently required from: fixeria, osmith.
pespin has posted comments on this change by pespin. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/43651?usp=email )
Change subject: smf: Initial HTTP2/SBI support
......................................................................
Patch Set 2:
(1 comment)
File library/HTTP2_Functions.ttcn:
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/43651/comment/0117a39a_4003… :
PS2, Line 51: //var charstring regexpString := "([A-Za-z][A-Za-z0-9-]*):\s*(.+?)\s*";
@osmith@sysmocom.de @axilirator@gmail.com I need some help with somebody better at regexps than me here to obtain header name and value from string of type:
"Content-Type: application/octetstream"
log commented out shows empty strings when printed, but regexp indeed tells there's 2 groups if I try to access any more...
--
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/43651?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: comment
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: I377b748d8da6e9e53a96a85f1c730505793ecea8
Gerrit-Change-Number: 43651
Gerrit-PatchSet: 2
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-CC: fixeria <axilirator(a)gmail.com>
Gerrit-CC: osmith <osmith(a)sysmocom.de>
Gerrit-Attention: osmith <osmith(a)sysmocom.de>
Gerrit-Attention: fixeria <axilirator(a)gmail.com>
Gerrit-Comment-Date: Wed, 16 Sep 2026 15:39:09 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Hello Jenkins Builder,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/43651?usp=email
to look at the new patch set (#2).
The following approvals got outdated and were removed:
Verified+1 by Jenkins Builder
Change subject: smf: Initial HTTP2/SBI support
......................................................................
smf: Initial HTTP2/SBI support
* New library/TS*_Templates.ttcn files are added providing several
templates for SBI interface types available from
osmo-ttcn3-openapi-generator.git.
* Split SMF_Session_CT parts which are only used during 4G tests
(Diameter interfaces, S5/S8/S2b GTPv2C interfaces) into its own file
SMF_Session_CT_4G. There's usually no need to look at both 4G and 5G
specific code at the same time, since usually tests validate one or
the other. SMF_Session_CT is left with common stuff, like lifecycle
of component and PFCP interface.
* Add a new SMF_Session_CT_5G file containing all 5G specific logic, ie.
HTTP2 SBI interface handling.
* Add a new test in SMF_Tests which makes use of the new
SMF_Session_CT_5G logic to emulate a PDU Session request from a 5G UE.
Test and infra only validates so far until UE receives the PDU session
request after UDM/PCF validation & setup. Further work will be done in
follow-up commits.
* Adapt open5gs config to use an SCP to route all HTTP2 traffic. This
way we can emulate all nodes through a single HTTP2 server, and we
emulate the SCP forwarding the messages to the proper destination.
Hence, the NRF is disabled.
Related: SYS#7073
Change-Id: I377b748d8da6e9e53a96a85f1c730505793ecea8
---
M library/HTTP2_Functions.ttcn
A library/TS29502_Nsmf_PDUSession_Templates.ttcn
A library/TS29503_Nudm_SDM_Templates.ttcn
A library/TS29512_Npcf_SMPolicyControl_Templates.ttcn
A library/TS29518_Namf_Communication_Templates.ttcn
A library/TS29571_CommonData_Templates.ttcn
M smf/README.md
M smf/SMF_Session_CT.ttcn
A smf/SMF_Session_CT_4G.ttcn
A smf/SMF_Session_CT_5G.ttcn
M smf/SMF_Tests.ttcn
M smf/expected-results.xml
M smf/gen_links.sh
M smf/open5gs-nrf.yaml
M smf/open5gs-smf.yaml
M smf/regen_makefile.sh
M smf/testenv.cfg
17 files changed, 2,008 insertions(+), 396 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/51/43651/2
--
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/43651?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newpatchset
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: I377b748d8da6e9e53a96a85f1c730505793ecea8
Gerrit-Change-Number: 43651
Gerrit-PatchSet: 2
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder