Commit 68867733 authored by Elian Kraja's avatar Elian Kraja

Merging jsonMessageBodyTypes and JsonTemplates

parents 30d3f8ad b55fa194
ETSI Software License
As long as the hereunder conditions are respected, non-exclusive permission is
hereby granted, free of charge, to use, reproduce and modify this software
source code, under the following conditions:
- This source code is provided “AS IS” with no warranties, express or implied,
including but not limited to, the warranties of merchantability, fitness for
a particular purpose and warranties for non-infringement of intellectual
property rights. ETSI shall not be held liable in any event for any direct or
indirect damages whatsoever (including, without limitation, damages for loss
of profits, business interruption, loss of information, or any other pecuniary
loss) arising out of or related to the use of or inability to use the
source code.
- This permission is granted to facilitate the implementation of the related
ETSI standard, provided that ETSI is given the right to use, reproduce and
amend the modified source code under the same conditions as the
present permission.
- This permission does not apply to any documentation associated with this
source code for which ETSI keeps all rights reserved.
The present ETSI Source Code license shall be included in all copies of whole
or part of this source code and shall not imply any sub-license right.
......@@ -21,6 +21,14 @@ This file provides the list of the TODOs related to the STF 569.
### RNIS
Draft ETSI GS MEC 012 2.0.4
https://forge.etsi.org/gitlab/mec/gs032p2-test-purposes/blob/master/Test%20Purposes/SRV/RNIS/RnisSpecificSubscription_BV.tplan2
https://forge.etsi.org/gitlab/mec/gs032p2-test-purposes/blob/master/Test%20Purposes/SRV/RNIS/RnisSpecificSubscription_BV.tplan2
- TC_MEC_SRV_RNIS_011_OK <font color="color:green">To be tested</font>
- TC_MEC_SRV_RNIS_012_OK <font color="color:green">To be tested</font>
### SAQ
### SRVSUB
......@@ -29,18 +37,39 @@ This file provides the list of the TODOs related to the STF 569.
### TRAF
Draft ETSI GS MEC 011 V2.0.9 (2018-10)
https://forge.etsi.org/gitlab/mec/gs032p2-test-purposes/blob/remove-401s/Test%20Purposes/SRV/TRAF/PlatTrafficRules.tplan2
- TC_MEC_SRV_TRANS_001_OK <font color="color:green">To be tested</font>
- TC_MEC_SRV_TRAF_001_OK <font color="color:green">To be tested</font>
- TC_MEC_SRV_TRAF_002_OK <font color="color:green">To be tested</font>
- TC_MEC_SRV_TRAF_003_OK <font color="color:green">To be tested</font>
- TC_MEC_SRV_TRAF_001_NF <font color="color:green">To be tested</font>
### TRANS
Draft ETSI GS MEC 011 V2.0.9 (2018-10)
https://forge.etsi.org/gitlab/mec/gs032p2-test-purposes/blob/remove-401s/Test%20Purposes/SRV/TRANS/PlatTransport.tplan2
- TP_MEC_SRV_TRAF_001_OK <font color="color:green">To be tested</font>
### UEAREASUB
Draft ETSI GS MEC 013 V2.0.3 (2018-10)
https://forge.etsi.org/gitlab/mec/gs032p2-test-purposes/blob/remove-401s/Test%20Purposes/SRV/UEDISTSUB/PlatUeAreaSubscription.tplan2
TODO CircleNotificationSubscription data structure not found
### UEDISTLOOK
Draft ETSI GS MEC 013 V2.0.3 (2018-10)
https://forge.etsi.org/gitlab/mec/gs032p2-test-purposes/blob/remove-401s/Test%20Purposes/SRV/UEDISTSUB/PlatUeDistanceSubscription.tplan2
TODO TerminalDistance data structure not found
https://forge.etsi.org/gitlab/mec/gs032p2-test-purposes/blob/remove-401s/Test%20Purposes/SRV/UEDISTLOOK/PlatUeDistanceSubscription.tplan2
TODO TerminalDistance data structure not found
### UEDISTSUB
......@@ -50,7 +79,6 @@ https://forge.etsi.org/gitlab/mec/gs032p2-test-purposes/blob/remove-401s/Test%20
TODO DistanceNotificationSubscription data structure not found
### UEINFLOOK
Draft ETSI GS MEC 013 V2.0.3 (2018-10)
......
......@@ -24,6 +24,10 @@ int json_codec::encode (const LibItsHttp__JsonMessageBodyTypes::JsonBody& msg, O
const LocationAPI__TypesAndValues::UserTrackingSubscription& user_tracking_subscription = msg.userTrackingSubscription();
user_tracking_subscription.encode(LocationAPI__TypesAndValues::UserTrackingSubscription_descr_, encoding_buffer, TTCN_EncDec::CT_JSON);
data = char2oct(CHARSTRING("{\"userTrackingSubscription\": ")) + OCTETSTRING(encoding_buffer.get_len(), encoding_buffer.get_data()) + char2oct(CHARSTRING("}"));
} else if (msg.ischosen(LibItsHttp__JsonMessageBodyTypes::JsonBody::ALT_cellChangeSubscription)) {
const RnisAPI__TypesAndValues::CellChangeSubscription& cell_change_subscription = msg.cellChangeSubscription();
cell_change_subscription.encode(RnisAPI__TypesAndValues::CellChangeSubscription_descr_, encoding_buffer, TTCN_EncDec::CT_JSON);
data = char2oct(CHARSTRING("{\"CellChangeSubscription\": ")) + OCTETSTRING(encoding_buffer.get_len(), encoding_buffer.get_data()) + char2oct(CHARSTRING("}"));
} else {
loggers::get_instance().error("json_codec::encode: Not supported");
}
......@@ -58,21 +62,26 @@ int json_codec::decode (const OCTETSTRING& p_data, LibItsHttp__JsonMessageBodyTy
// ..and create the decoding buffer
TTCN_Buffer decoding_buffer(OCTETSTRING(str.length(), (const unsigned char*)str.c_str()));
if (it->second.find("\"userList\"") != std::string::npos) { // Be carefull to the order
// TODO To be refined, find("\"userList\"") is not optimal
if (it->second.find("\"userList\"") != std::string::npos) { // Be careful to the order
// TODO To be refined, find("\"userList\"") is not optimal
LocationAPI__TypesAndValues::UserList user_list;
user_list.decode(LocationAPI__TypesAndValues::UserList_descr_, decoding_buffer, TTCN_EncDec::CT_JSON);
msg.userList() = user_list;
} else if (it->second.find("\"accessPointList\"") != std::string::npos) { // Be carefull to the order
// TODO To be refined, find("\"accessPointList\"") is not optimal
} else if (it->second.find("\"accessPointList\"") != std::string::npos) { // Be careful to the order
// TODO To be refined, find("\"accessPointList\"") is not optimal
LocationAPI__TypesAndValues::AccessPointList access_point_list;
access_point_list.decode(LocationAPI__TypesAndValues::AccessPointList_descr_, decoding_buffer, TTCN_EncDec::CT_JSON);
msg.accessPointList() = access_point_list;
} else if (it->second.find("\"SubscriptionLinkList\"") != std::string::npos) { // Be carefull to the order
// TODO To be refined, find("\"accessPointList\"") is not optimal
} else if (it->second.find("\"SubscriptionLinkList\"") != std::string::npos) { // Be careful to the order
// TODO To be refined, find("\"accessPointList\"") is not optimal
RnisAPI__TypesAndValues::SubscriptionLinkList subscription_link_list;
subscription_link_list.decode(RnisAPI__TypesAndValues::SubscriptionLinkList_descr_, decoding_buffer, TTCN_EncDec::CT_JSON);
msg.subscriptionLinkList() = subscription_link_list;
} else if (it->second.find("\"transportInfoList\"") != std::string::npos) { // Be careful to the order
// TODO To be refined, find("\"accessPointList\"") is not optimal
AppEnablementAPI__TypesAndValues::TransportInfoList transport_info_list;
transport_info_list.decode(AppEnablementAPI__TypesAndValues::TransportInfoList_descr_, decoding_buffer, TTCN_EncDec::CT_JSON);
msg.transportInfoList() = transport_info_list;
} else if (it->second.find("\"userTrackingSubscription\"") != std::string::npos) {
LocationAPI__TypesAndValues::UserTrackingSubscription user_tracking_subscription;
user_tracking_subscription.decode(LocationAPI__TypesAndValues::UserTrackingSubscription_descr_, decoding_buffer, TTCN_EncDec::CT_JSON);
......@@ -85,6 +94,23 @@ int json_codec::decode (const OCTETSTRING& p_data, LibItsHttp__JsonMessageBodyTy
UEidentityAPI__TypesAndValues::UeIdentityTagInfo ue_identity_tag_info;
ue_identity_tag_info.decode(UEidentityAPI__TypesAndValues::UeIdentityTagInfo_descr_, decoding_buffer, TTCN_EncDec::CT_JSON);
msg.ueIdentityTagInfo() = ue_identity_tag_info;
} else if (it->second.find("\"trafficRule\"") != std::string::npos) {
AppEnablementAPI__TypesAndValues::TrafficRule traffic_rule;
traffic_rule.decode(AppEnablementAPI__TypesAndValues::TrafficRule_descr_, decoding_buffer, TTCN_EncDec::CT_JSON);
msg.trafficRule() = traffic_rule;
} else if (it->second.find("\"CellChangeSubscription\"") != std::string::npos) {
RnisAPI__TypesAndValues::CellChangeSubscription cell_change_subscription;
cell_change_subscription.decode(RnisAPI__TypesAndValues::CellChangeSubscription_descr_, decoding_buffer, TTCN_EncDec::CT_JSON);
msg.cellChangeSubscription() = cell_change_subscription;
//TODO Continue with other ChangeSubscription
} else if (it->second.find("\"RabInfo\"") != std::string::npos) {
RnisAPI__TypesAndValues::RabInfo rab_info;
rab_info.decode(RnisAPI__TypesAndValues::RabInfo_descr_, decoding_buffer, TTCN_EncDec::CT_JSON);
msg.rabInfo() = rab_info;
} else if (it->second.find("\"PlmnInfo\"") != std::string::npos) {
RnisAPI__TypesAndValues::PlmnInfo plmn_info;
plmn_info.decode(RnisAPI__TypesAndValues::PlmnInfo_descr_, decoding_buffer, TTCN_EncDec::CT_JSON);
msg.plmnInfo() = plmn_info;
} else if (it->second.find("\"bwInfo\"") != std::string::npos) {
BwManagementAPI__TypesAndValues::BwInfo bw_info;
......@@ -105,9 +131,17 @@ int json_codec::decode (const OCTETSTRING& p_data, LibItsHttp__JsonMessageBodyTy
bw_info.decode(BwManagementAPI__TypesAndValues::BwInfo_descr_, decoding_buffer_, TTCN_EncDec::CT_JSON);
msg.bwInfo() = bw_info;
} else if (it->second.find("\"problemDetails\"") != std::string::npos) { // TODO To be refined, problemDetails in different modules
UEidentityAPI__TypesAndValues::ProblemDetails problem_details;
problem_details.decode(UEidentityAPI__TypesAndValues::ProblemDetails_descr_, decoding_buffer, TTCN_EncDec::CT_JSON);
msg.problemDetails__ue__identity() = problem_details;
// UEidentityAPI__TypesAndValues::ProblemDetails problem_details;
// problem_details.decode(UEidentityAPI__TypesAndValues::ProblemDetails_descr_, decoding_buffer, TTCN_EncDec::CT_JSON);
// msg.problemDetails__ue__identity() = problem_details;
RnisAPI__TypesAndValues::ProblemDetails problem_details;
problem_details.decode(RnisAPI__TypesAndValues::ProblemDetails_descr_, decoding_buffer, TTCN_EncDec::CT_JSON);
msg.problemDetails__rni() = problem_details;
} else {
loggers::get_instance().warning("json_codec::decode: Unsupported variant");
return -1;
......
......@@ -37,6 +37,7 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update \
libssl-dev \
libtool-bin \
libtool \
libwebsockets-dev \
libwireshark-dev \
libxml2-dev \
lsof \
......@@ -87,9 +88,9 @@ RUN cd /home/etsi \
# Seems that COPY does not work as expected, to be investaged
#==> Fallback to more secured solution
#COPY [^.]* /home/etsi/dev/STF569_Mec/
ADD . /home/etsi/dev/STF569_Mec
#COPY home home/etsi
RUN git clone https://forge.etsi.org/gitlab/mec/gs032p3-ttcn-test-suite.git /home/etsi/dev/STF569_Mec
# RUN git clone https://forge.etsi.org/gitlab/mec/gs032p3-ttcn-test-suite.git /home/etsi/dev/STF569_Mec
RUN chown -R etsi /home/etsi/dev/STF569_Mec/ && cd /home/etsi/dev/STF569_Mec
USER etsi
......@@ -107,8 +108,6 @@ RUN cd /home/etsi/frameworks \
&& rm -f ./eclipse-cpp-photon-R-linux-gtk-x86_64.tar.gz \
&& cd /home/etsi/dev/STF569_Mec \
&& cd /home/etsi/dev/STF569_Mec/ttcn \
&& git clone https://forge.etsi.org/gitlab/LIBS/LibSip.git ./LibSip \
&& git clone https://forge.etsi.org/gitlab/LIBS/LibIms.git ./LibIms \
&& git clone https://forge.etsi.org/gitlab/LIBS/LibCommon.git ./LibCommon \
&& git clone -bSTF525 https://forge.etsi.org/gitlab/LIBS/LibIts ./LibIts \
&& cd /home/etsi/dev/STF569_Mec/ttcn/LibIts \
......
......@@ -3,20 +3,25 @@
# See: https://forge.etsi.org/etsi-forge-copyright-statement.txt
#set -e
#set -vx
set -vx
DOCKER_FILE=./docker/Dockerfile
if [ -f ${DOCKER_FILE} ]
then
docker rm --force stf569_Mec
docker build --tag stf569_Mec --force-rm -f ${DOCKER_FILE} .
#check and build stf569_mec image
DOCKER_ID=`docker ps -a | grep -e stf569_mec | awk '{ print $1 }'`
if [ ! -z "${DOCKER_ID}" ]
then
docker rm --force stf569_mec
fi
docker build --tag stf569_mec --force-rm -f ${DOCKER_FILE} .
if [ "$?" != "0" ]
then
echo "Docker build failed: $?"
exit -1
fi
docker image ls -a
docker inspect stf569_Mec:latest
docker inspect stf569_mec:latest
if [ "$?" != "0" ]
then
echo "Docker inspect failed: $?"
......
......@@ -5,9 +5,9 @@
#set -e
#set -vx
docker run stf569_Mec:latest "/bin/bash" \
docker run stf569_mec:latest "/bin/bash" \
-c "source /home/etsi/devenv.bash \
&& cd /home/etsi/dev/etsi_emcom/src/AtsMec/objs \
&& cd /home/etsi/dev/etsi_mec/src/AtsMec/objs \
&& ../bin/run_all.bash \
&& ls -ltr ../logs"
......
......@@ -7,21 +7,27 @@ LibCommon_Time.PX_TAC := 30.0
LibCommon_Sync.PX_TSYNC_TIME_LIMIT := 30.0;
LibCommon_Sync.PX_TSHUT_DOWN_TIME_LIMIT := 30.0;
LibItsHttp_Pics.PICS_HEADER_HOST := "172.28.4.87"
LibItsHttp_Pics.PICS_HEADER_HOST := "192.168.56.1"
#LibItsHttp_Pics.PICS_HEADER_HOST := "172.28.4.87"
#LibItsHttp_Pics.PICS_HEADER_HOST := "192.168.0.17"
LibItsHttp_Pics.PICS_HEADER_CONTENT_TYPE := "application/json"
LibMec_Pics.PICS_MEC_PLAT := true
LibMec_Pics.PICS_SERVICES := true
LibMec_Pics.PICS_RNIS := false
LibMec_Pics.PICS_MEC_PLAT := true
LibMec_Pics.PICS_SERVICES := true
LibMec_Pics.PICS_RNIS := true
LibMec_Pics.PICS_RNIS_QUERY := true
LibMec_Pics.PICS_RNIS_ALL_SUBSCRIPTIONS := true
LocationAPI_Pics.PICS_LOCATION_API_SUPPORTED := false
UEidentityAPI_Pics.PICS_UE_IDENTITY_API_SUPPORTED := true
UEidentityAPI_Pics.PICS_UE_IDENTITY_API_SUPPORTED := false
BwManagementAPI_Pics.PICS_BWMANAGEMENT_API_SUPPORTED := false
AppEnablementAPI_Pics.PICS_ENABLE_APP_API_SUPPORTED := true
[LOGGING]
# In this section you can specify the name of the log file and the classes of events
# you want to log into the file or display on console (standard error).
......@@ -38,7 +44,7 @@ LogEventTypes:= Yes
[TESTPORT_PARAMETERS]
# In this section you can specify parameters that are passed to Test Ports.
system.httpPort.params := "HTTP(codecs=json:json_codec)/TCP(debug=1,server=172.28.4.87,port=8081,use_ssl=0)"
system.httpPort.params := "HTTP(codecs=json:json_codec)/TCP(debug=1,server=192.168.56.1,port=8081,use_ssl=0)"
[DEFINE]
# In this section you can create macro definitions,
......@@ -69,7 +75,7 @@ system.httpPort.params := "HTTP(codecs=json:json_codec)/TCP(debug=1,server=172.2
#AtsMec_UEidentityAPI_TestCases.TC_MEC_SRV_UETAG_001_NF
#AtsMec_UEidentityAPI_TestCases.TC_MEC_SRV_UETAG_002_OK
#AtsMec_UEidentityAPI_TestCases.TC_MEC_SRV_UETAG_002_BR
AtsMec_UEidentityAPI_TestCases.TC_MEC_SRV_UETAG_002_PF
#AtsMec_UEidentityAPI_TestCases.TC_MEC_SRV_UETAG_002_PF
#AtsMec_UEidentityAPI_TestCases.TC_MEC_SRV_UELOC_001_OK
#AtsMec_UEidentityAPI_TestCases.TC_MEC_SRV_UELOC_001_BR
......@@ -94,6 +100,17 @@ AtsMec_UEidentityAPI_TestCases.TC_MEC_SRV_UETAG_002_PF
#AtsMec_LocationAPI_TestCases.TC_MEC_SRV_UEINFSUB_002_OK
#AtsMec_LocationAPI_TestCases.TC_MEC_SRV_UEINFSUB_002_NF
#AtsMec_RnisAPI_TestCases.TC_MEC_SRV_RNIS_011_OK
#AtsMec_RnisAPI_TestCases.TC_MEC_SRV_RNIS_012_OK
#AtsMec_RnisAPI_TestCases.TC_MEC_SRV_RNIS_011_BR
#AtsMec_RnisAPI_TestCases.TC_MEC_SRV_RNIS_012_BR
AtsMec_RnisAPI_TestCases.TC_MEC_SRV_RNIS_016_OK
#AtsMec_AppEnablementAPI_TestCases.TC_MEC_SRV_TRANS_001_OK
#AtsMec_AppEnablementAPI_TestCases.TC_MEC_SRV_TRAF_001_OK
#AtsMec_AppEnablementAPI_TestCases.TC_MEC_SRV_TRAF_002_OK
#AtsMec_AppEnablementAPI_TestCases.TC_MEC_SRV_TRAF_001_NF
[GROUPS]
# In this section you can specify groups of hosts. These groups can be used inside the
# [COMPONENTS] section to restrict the creation of certain PTCs to a given set of hosts.
......
id,grantTypes,tokenEndpoint
security0,OAUTH2_CLIENT_CREDENTIALS,/meMp1/security/TokenEndPoint
trafficRuleId,filterType,priority,trafficFilter,action,dstInterface,state
transportId,name,description,type,protocol,version,endpoint,security,implSpecificInfo
TransId12345,REST,REST API,REST_HTTP,HTTP,2.0,{},security0,{}
appInst,ueTag,address,state
appInst01,UeTagA,acr:192.0.0.1,UNREGISTERED
appInst01,UeTagC,acr:192.0.0.3,UNREGISTERED
appInst01,UeTagC,acr:192.0.0.3,INVALID_STATE
appInst02,UeTagB,acr:192.0.0.2,UNREGISTERED
appInst03,UeTagD,acr:192.0.0.4,UNREGISTERED
appInst03,UeTagE,acr:192.0.0.5,UNREGISTERED
......@@ -15,6 +15,9 @@ class mec_database:
__cells__ = None
__associated__ = None
__subscribions__ = None
__transport_info__ = None
__security__ = None
__traffic_rules__ = None
def __init__(self):
""" Default ctor: Open Pandas database. """
......@@ -26,7 +29,10 @@ class mec_database:
self.__cells__ = pd.DataFrame(pd.read_csv(self.__path__ + 'cells.csv', encoding = 'utf-8', index_col = 'cellId'))
self.__associated__ = pd.DataFrame(pd.read_csv(self.__path__ + 'associated.csv', encoding = 'utf-8', index_col = 'cellId'))
self.__subscriptions__ = pd.DataFrame(pd.read_csv(self.__path__ + 'subscriptions.csv', encoding = 'utf-8', index_col = 'subscription_id'))
#self.dump()
self.__transport_info__ = pd.DataFrame(pd.read_csv(self.__path__ + 'transport_info.csv', encoding = 'utf-8', index_col = 'transportId'))
self.__security__ = pd.DataFrame(pd.read_csv(self.__path__ + 'security.csv', encoding = 'utf-8', index_col = 'id'))
self.__traffic_rules__ = pd.DataFrame(pd.read_csv(self.__path__ + 'traffic_rules.csv', encoding = 'utf-8', index_col = 'trafficRuleId'))
# self.dump()
# End of __init__
def dump(self):
......@@ -38,7 +44,10 @@ class mec_database:
print("LocationInfo: ", self.__location_info__.head())
print("Cells: ", self.__cells__.head())
print("Associated: ", self.__associated__.head())
print("subscriptions: ", self.__subscribions__.head())
print("subscriptions: ", self.__subscriptions__.head())
print("transport_info: ", self.__transport_info__.head())
print("security: ", self.__security__.head())
print("traffic_rules: ", self.__traffic_rules__.head())
# End of dump
def __to_accessPoint__(self, p_access_point, p_location):
......@@ -106,6 +115,53 @@ class mec_database:
return resp
# End of __to_subscriptions__
def __to_transport_info__(self, p_transport_info):
"""
Build a TransportInfo Json message.
Keyword arguments:
-- p_transport_info: TransportInfo description
"""
print(">>> __to_transport_info__: ", p_transport_info)
# print("__to_transport_info__: security id: ", p_transport_info[7])
resp = "{{\t\"id\": \"TransId12345\",\"name\": \"REST\",\"description\": \"REST API\",\"type\": \"REST_HTTP\",\"protocol\": \"HTTP\",\"version\": \"2.0\",\"endpoint\": {},\"security\": {\"oAuth2Info\": {\"grantTypes\": [\"OAUTH2_CLIENT_CREDENTIALS\"],\"tokenEndpoint\": \"/meMp1/security/TokenEndPoint\"}\"},\"implSpecificInfo\": {}}"
# resp = None
# try:
# security = self.__security__.loc[self.__security__['id'] == p_transport_info[7]]
# print("__to_transport_info__: security= ", security)
#
# resp = "{\t\"id\": \"" + p_transport_info[0] + "\",\t\"name\": \"" + p_transport_info[1] + "\",\t\"description\": \"" + p_transport_info[2] + "\",\t\"type\": \"" + p_transport_info[3] + "\",\t\"protocol\": \"" + p_transport_info[4] + "\",\t\"version\": \"" + str(p_transport_info[5]) + "\",\t\"endpoint\": \"" + p_transport_info[6] + "\",\t\"security\": \"" + security + "\",\t\"implSpecificInfo\": \"" + p_transport_info[8] + "\"}"
# print("__to_transport_info__: ", resp)
# except KeyError:
# print("__to_transport_info__: No security entry")
return resp
# End of method __to_transport_info__
def __to_traffic_rule__(self, p_traffic_rule):
"""
Build a TrafficRule Json message.
Keyword arguments:
-- p_traffic_rule: TrafficRule description
"""
print(">>> __to_traffic_rule__: ", p_traffic_rule)
resp = "{\"trafficRuleId\": \"TrafficRule1\",\"filterType\": \"FLOW\",\"priority\": 1,\"trafficFilter\": [{\"srcAddress\": [\"192.168.1.1\"],\"dstAddress\": [\"192.168.1.1\"],\"srcPort\": [\"8080\"],\"dstPort\": [\"8080\"],\"protocol\": [ \"?\"],\"token\": [\"?\"],\"srcTunnelAddress\": [\"?\"],\"tgtTunnelAddress\": [\"?\"],\"srcTunnelPort\": [\"?\"],\"dstTunnelPort\": [\"?\"],\"qCI\": 1,\"dSCP\": 0,\"tC\": 1}],\"action\": \"DROP\",\"dstInterface\": {\"interfaceType\": \"TUNNEL\",\"tunnelInfo\": {\"tunnelType\": \"GTP_U\",\"tunnelDstAddress\": \"?\",\"tunnelSrcAddress\": \"?\"},\"srcMacAddress\": \"02-00-00-00-00-00\",\"dstMacAddress\": \"02-00-00-00-00-00\",\"dstIpAddress\":\"192.0.2.0\"},\"state\":\"ACTIVE\"}"
# resp = None
# try:
# resp = "{\t\"id\": \"" + p_transport_info[0] + "\",\t\"name\": \"" + p_transport_info[1] + "\",\t\"description\": \"" + p_transport_info[2] + "\",\t\"type\": \"" + p_transport_info[3] + "\",\t\"protocol\": \"" + p_transport_info[4] + "\",\t\"version\": \"" + str(p_transport_info[5]) + "\",\t\"endpoint\": \"" + p_transport_info[6] + "\",\t\"security\": \"" + security + "\",\t\"implSpecificInfo\": \"" + p_transport_info[8] + "\"}"
# print("__to_transport_info__: ", resp)
# except KeyError:
# print("__to_transport_info__: No security entry")
return resp
# End of method __to_transport_info__
def __to_rni_subscriptions__(self, p_subscription, p_subscription_type):
""" Build a RNI subscription Json message. """
print(">>> __to_rni_subscriptions__")
resp = "{\"CellChangeSubscription\": {\"subscriptionType\": \"" + p_subscription_type + "\",\"callbackReference\": \"http://meAppClient.example.com/rni/v2/notifications/cell_change/77777\", \"_links\": {\"self\": \"http://example.com/exampleAPI/rni/v2/subscriptions\"}, \"filterCriteria\": {\"appInsId\": \"01\", \"associateId\": [{\"type\": \"UE_IPV4_ADDRESS\", \"value\": 1}], \"plmn\": {\"mcc\": \"01\", \"mnc\": \"001\"}, \"cellId\": [\"0x800000A\"], \"hoStatus\": \"COMPLETED\"}, \"expiryDeadline\": {\"seconds\": 1577836800, \"nanoSeconds\": 0}}}"
# resp = "{\"CellChangeSubscription\": {\"callbackReference\": " + p_subscription['callbackReference'] + ", \"_links\": {\"self\": " + p_subscription['_links'] + "}, \"filterCriteria\": {\"appInsId\": " + p_subscription['filterCriteria']['appInsId'] + ", \"associateId\": [{\"type\": " + p_subscription['filterCriteria']['associateId']['type'] + ", \"value\": " + p_subscription['filterCriteria']['associateId']['value'] + "}], \"plmn\": {\"mcc\": " + p_subscription['filterCriteria']['plmn']['mcc'] + ", \"mnc\": " + p_subscription['filterCriteria']['plmn']['mnc'] + "}, \"cellId\": [" + p_subscription['filterCriteria']['cellId'] + "], 'hoStatus': " + p_subscription['filterCriteria']['hoStatus'] + "}, \"expiryDeadline\": {\"seconds\": " + p_subscription['expiryDeadline']['seconds'] + ", \"nanoSeconds\": \"" + p_subscription['expiryDeadline']['nanoSeconds'] + "}}"
print("__to_rni_subscriptions__: ", resp)
return resp
# end of __to_rni_subscriptions__
def getSubscriberList(self, p_uri):
""" Build a SubscriberList Json message. """
print(">>> getSubscriberList")
......@@ -145,7 +201,6 @@ class mec_database:
print(">>> getAccessPointList")
resp = None
try:
r = self.__access_point_list__.loc[self.__access_point_list__['zoneId'] == p_zone_id]
print("getAccessPointList: r= ", r)
resp = "{\"accessPointList\": {\t\"zoneId\": \"" + p_zone_id + "\",\t\"accessPoint\": [\t"
......@@ -163,9 +218,61 @@ class mec_database:
# End of method getAccessPointList
def getSubscriptionLinkList(self, p_uri):
return "{\"SubscriptionLinkList\": {\"_links\": {\"self\": \"http://example.com" + p_uri + "\"},\"subscription\": [{\"href\": \"http://meAppClient.example.com/rni/v1/notifications/cell_change/77777\",\"subscriptionType\": \"CELL_CHANGE\"},{\"href\": \"http://meAppClient.example.com/rni/v1/notifications/MeasTa/77777\",\"subscriptionType\": \"MEAS_TIMING_ADVANCE\"}]}}"
s = p_uri.split('?')
return "{\"SubscriptionLinkList\": {\"_links\": {\"self\": \"http://example.com" + s[0] + "\"},\"subscription\": [{\"href\": \"http://meAppClient.example.com/rni/v1/notifications/cell_change/77777\",\"subscriptionType\": \"CELL_CHANGE\"},{\"href\": \"http://meAppClient.example.com/rni/v1/notifications/MeasTa/77777\",\"subscriptionType\": \"MEAS_TIMING_ADVANCE\"}]}}"
# End of method getSubscriptionLinkList
def getMp1TransportInfoList(self):
print(">>> getMp1TransportInfoList")
resp = None
try:
resp = "{\"transportInfoList\": [\t"
for r in self.__transport_info__.itertuples():
t = tuple(r)
resp += self.__to_transport_info__(t) + ","
# En of 'for' statement
resp = resp[: len(resp) - 1]
resp += "\t]}"
print("getMp1TransportInfoList: ", resp)
except KeyError:
print("getMp1TransportInfoList: No transportInfo list")
return resp
# End of method getMp1TransportInfo
def getMp1TrafficRulesList(self):
print(">>> getMp1TrafficRulesList")
resp = None
try:
resp = "{\"TrafficRulesList\": [\t"
for r in self.__traffic_rules__.itertuples():
t = tuple(r)
resp += self.__to_traffic_rule__(t) + ","
# En of 'for' statement
resp = resp[: len(resp) - 1]
resp += "\t]}"
print("getMp1TrafficRulesList: ", resp)
except KeyError:
print("getMp1TrafficRulesList: No TrafficRules list")
return resp
# End of method getMp1TrafficRules
def getMp1TrafficRule(self):
print(">>> getMp1TrafficRule")
resp = None
try:
resp = "{\"TrafficRule\": [\t"
for r in self.__traffic_rule__.itertuples():
t = tuple(r)
resp += self.__to_traffic_rule__(t) + ","
# En of 'for' statement
resp = resp[: len(resp) - 1]
resp += "\t]}"
print("getMp1TrafficRule: ", resp)
except KeyError:
print("getMp1TrafficRule: No TrafficRules list")
return resp
# End of method getMp1TrafficRules
def getSubscriberFromAddress(self, p_ue_address):
print(">>> getSubscriberFromAddress: ", p_ue_address)
result = None
......@@ -209,16 +316,26 @@ class mec_database:
return resp
# End of method getUEidentityTagInfo
def getBwAllocationAppInst(self, p_app_inst, p_ue_identity_tag):
print(">>> getBwAllocationAppInst: ", p_app_inst, ", ", p_ue_identity_tag)
resp = None
resp = "{\"bwInfo\": {\"timeStamp\": {\"seconds\": 0,\"nanoSeconds\": 0},\"appInsId\": \"string\",\"requestType\": \"APPLICATION_SPECIFIC_BW_ALLOCATION\",\"sessionFilter\": [{\"sourceIp\": \"string\",\"sourcePort\": [\"string\"],\"dstAddress\": \"string\",\"dstPort\": [\"string\"],\"protocol\": \"string\"}],\"fixedBWPriority\": \"not defined in the present document\",\"fixedAllocation\": \"string\",\"allocationDirection\": \"00 = Downlink (towards the UE)\"}}"
print("getBwAllocationAppInst: ", resp)
return resp
# End of method getBwAllocationAppInst
def registerUEidentity(self, p_app_inst, p_json_msg):
print(">>> registerUEidentity", p_json_msg)
if p_json_msg["state"] != "REGISTERED" and p_json_msg["state"] != "UNREGISTERED":
return None
return '400 Bad Request'
resp = None
try:
# Check the record exists
r = tuple(self.__ue_information_list__.loc[p_app_inst, p_json_msg["ueIdentityTag"]])
print("registerUEidentity: Find zoneId for appInst: ", p_app_inst, ", r= ", r)
self.__ue_information_list__.loc[p_app_inst, p_json_msg["ueIdentityTag"]]['state'] = p_json_msg["state"]
if self.__ue_information_list__.loc[p_app_inst, p_json_msg["ueIdentityTag"]]['state'] == 'INVALID_STATE':
return '412 Precondition Failed'
self.__ue_information_list__.loc[p_app_inst, p_json_msg["ueIdentityTag"]]['state'] = p_json_msg["state"]
l = (p_json_msg["ueIdentityTag"], p_json_msg["state"])
resp = self.__to_ueIdentityTagInfo__(p_json_msg["ueIdentityTag"], l)
except KeyError:
......@@ -263,12 +380,32 @@ class mec_database:
return resp
# End of unregisterSubscription
def getBwAllocationAppInst(self, p_app_inst, p_ue_identity_tag):
print(">>> getBwAllocationAppInst: ", p_app_inst, ", ", p_ue_identity_tag)
def registerRniSubscription(self, p_json_msg):
print(">>> registerRniSubscription: ", p_json_msg)
resp = None
resp = "{\"bwInfo\": {\"timeStamp\": {\"seconds\": 0,\"nanoSeconds\": 0},\"appInsId\": \"string\",\"requestType\": \"APPLICATION_SPECIFIC_BW_ALLOCATION\",\"sessionFilter\": [{\"sourceIp\": \"string\",\"sourcePort\": [\"string\"],\"dstAddress\": \"string\",\"dstPort\": [\"string\"],\"protocol\": \"string\"}],\"fixedBWPriority\": \"not defined in the present document\",\"fixedAllocation\": \"string\",\"allocationDirection\": \"00 = Downlink (towards the UE)\"}}"
print("getBwAllocationAppInst: ", resp)
if p_json_msg['subscriptionType'] == 'CELL_CHANGE':
resp = self.__to_rni_subscriptions__(p_json_msg, 'CELL_CHANGE')
return resp
# End of method getBwAllocationAppInst
# End of registerRniSubscription
def getRabInfo(self, p_cell_id):
print(">>> getRabInfo: ", p_cell_id)
resp = None
if p_cell_id == '0xFFFFFFFF':
resp = "{\"problemDetails\": {\t\"type\": \"Bad Request\",\t\"title\": \"RnisAPI\",\t\"status\": 400,\t\"detail\": \"Wrong parameters\",\t\"instance\": \"string\"}}"
else:
resp = "{ \"RabInfo\": { \"timeStamp\": { \"seconds\": 1577836800, \"nanoSeconds\": 0 }, \"appInsId\": \"01\", \"requestId\": \"01\", \"cellUserInfo\": { \"ecgi\": { \"plmn\": { \"mcc\": \"001\", \"mnc\": \"01\" }, \"cellId\": \"" + p_cell_id + "\" }, \"ueInfo\": { \"associateId\": null, \"type\": \"1\", \"value\": \"192.0.2.0\", \"erabInfo\": { \"erabId\": 10 }, \"erabQosParameters\": { \"qci\": 7, \"qosInformation\": { \"erabMbrDl\": 10, \"erabMbrUl\": 10, \"erabGbrDl\": 10, \"erabGbrUl\": 10 } } } } } }"
return resp
# End of getRabInfo
def getPlmnInfo(self, p_app_inst):
print(">>> getPlmnInfo: ", p_app_inst)
resp = None
if p_app_inst == '99':
resp = "{\"problemDetails\": {\t\"type\": \"Bad Request\",\t\"title\": \"RnisAPI\",\t\"status\": 400,\t\"detail\": \"Wrong parameters\",\t\"instance\": \"string\"}}"
else:
resp = "{ \"PlmnInfo\": { \"timeStamp\": { \"seconds\": 1577836800, \"nanoSeconds\": 0 }, \"appInsId\": \"" + p_app_inst + "\", \"ecgi\": { \"plmn\": { \"mcc\": \"001\", \"mnc\": \"01\" }, \"cellId\": \"0x800000A\" } } }"
return resp
# End of getPlmnInfo
# End of class mec_database
......@@ -96,12 +96,21 @@ class myHandler(http.server.BaseHTTPRequestHandler):
else:
if resp.find('Not Found') != -1:
self.send_response(404, 'Not Found')
resp = ""
elif resp.find('Forbidden') != -1:
self.send_response(403, 'Forbidden')
elif resp.find('Bad Request') != -1:
resp = ""
elif resp.find('Bad Request') != -1 or resp.find('Wrong parameters') != -1:
self.send_response(400, 'Bad Request')
elif resp.find('Precondition Failed') != -1:
self.send_response(412, 'Precondition Failed')
resp = "{\"problemDetails\": {\t\"type\": \"Precondition Failed\",\t\"title\": \"N/A\",\t\"status\": 412,\t\"detail\": \"Wrong preconditions\",\t\"instance\": \"N/A\"}}"
content_type = 'application/problem+json'
elif resp.find('userTrackingSubscription') != -1:
self.send_response(201, 'Created')
resp = ""
elif resp.find('CellChangeSubscription') != -1:
self.send_response(201, 'Created')
else:
self.send_response(200, 'OK')
self.send_header('Host', self.headers.get('Host')) # send_header() shall be after send_response()
......@@ -121,6 +130,68 @@ class myHandler(http.server.BaseHTTPRequestHandler):
return
# End of do_POST
# Handler for the PUT requests
def do_PUT(self):
print(">>> do_PUT: ", self.path)
self.protocol_version = self.request_version
# Check HTTP end_headers
if self.__check_http_headers__() == False:
resp = "{\"problemDetails\": {\t\"type\": \"Bad Request\",\t\"title\": \"N/A\",\t\"status\": 400,\t\"detail\": \"Wrong headers\",\t\"instance\": \"N/A\"}}"
self.protocol_version = self.request_version
self.send_response(400, 'Bad Request')
self.send_header('Host', self.headers.get('Host'))
self.send_header('Authorization', self.headers.get('Authorization'))
self.send_header('Connection', 'keep-alive')
self.send_header('Content-Type', 'application/problem+json')
l = len(resp)
self.send_header('Content-Length', str(l))
self.end_headers()
self.wfile.write(bytes(resp, 'utf-8'))
return
resp, content_type = self.__process__()
print('do_PUT: resp= ', resp, ', Content_Type= ', content_type)
if (resp == None):
self.send_response(404, 'Not Found')
self.send_header('Host', self.headers.get('Host')) # send_header() shall be after send_response()
self.send_header('Authorization', self.headers.get('Authorization'))
self.send_header('Connection', 'keep-alive')
self.send_header('Content-Type', content_type)
self.send_header('Content-Length', '0')
self.end_headers()
else:
if resp.find('Not Found') != -1:
self.send_response(404, 'Not Found')
resp = ""
elif resp.find('Forbidden') != -1:
self.send_response(403, 'Forbidden')
resp = ""
elif resp.find('Bad Request') != -1:
self.send_response(400, 'Bad Request')
resp = ""
elif resp.find('Precondition Failed') != -1:
self.send_response(412, 'Precondition Failed')
resp = "{\"problemDetails\": {\t\"type\": \"Precondition Failed\",\t\"title\": \"N/A\",\t\"status\": 412,\t\"detail\": \"Wrong preconditions\",\t\"instance\": \"N/A\"}}"
content_type = 'application/problem+json'
else:
self.send_response(200, 'OK')
self.send_header('Host', self.headers.get('Host')) # send_header() shall be after send_response()
self.send_header('Authorization', self.headers.get('Authorization'))
self.send_header('Connection', 'keep-alive')
self.send_header('Content-Type', content_type)
l = len(resp)
self.send_header('Content-Length', str(l))
#self.end_headers() # Unable to bufferize wfile, so calling end_headers() headers and body are sent in 2 different TCP packets
self._headers_buffer.append(b"\r\n")
self._headers_buffer.append(bytes(resp, 'utf-8'))
self.wfile.write(b"".join(self._headers_buffer))
self._headers_buffer = []
#self.wfile.write(bytes(resp, 'utf-8'))
#self.wfile.flush()
print("<<< do_PUT")
return
# End of do_POST
# Handler for the DELETE requests
def do_DELETE(self):
print('>>> do_DELETE: ', self.path)
......@@ -209,6 +280,8 @@ class myHandler(http.server.BaseHTTPRequestHandler):
return self.__process__rnis__api__(s)
elif s[2] == 'bwm' and ((s[3] == 'v1') or (s[3] == 'v2')):
return self.__process__bwm__api__(s)
elif s[2] == 'mec_app_support' and ((s[3] == 'v1') or (s[3] == 'v2')):
return self.__process__mp1__api__(s)
else:
return None, 'application/json'
# End of __process__
......@@ -302,8 +375,7 @@ class myHandler(http.server.BaseHTTPRequestHandler):
content_type = 'application/problem+json'
if (resp == None):
resp = "{\"problemDetails\": {\t\"type\": \"Bad Request\",\t\"title\": \"UEidentityAPI\",\t\"status\": 400,\t\"detail\": \"Wrong parameters\",\t\"instance\": \"string\"}}"
content_type = 'application/problem+json'
elif resp.find('problemDetails') != -1:
if resp.find('problemDetails') != -1:
content_type = 'application/problem+json'
print ("<<< __process__ue__identity__api__: ", resp, ", ", content_type)
......@@ -316,11 +388,65 @@ class myHandler(http.server.BaseHTTPRequestHandler):
resp = None
content_type = 'application/json'
if p_split[4].startswith('subscriptions'):
if p_split.__len__() == 6:
if p_split.__len__() == 5:
s = p_split[4].split('?')
if s.__len__() == 1: # Chek message body
# Register/Unregister operation
body = None
# Extract the body if any
content_len = int(self.headers.get('Content-Length'))
if (content_len != 0):
body = self.rfile.read(content_len)
json_msg = self.__decode__json__body__(body)
if (json_msg == None):
resp = "{\"problemDetails\": {\t\"type\": \"Body processing not supported\",\t\"title\": \"UEidentityAPI\",\t\"status\": 400,\t\"detail\": \"Unknown request