Added NRF

This commit is contained in:
Sukchan Lee 2020-05-18 17:00:37 -04:00
parent 46f20cc979
commit d0673e3066
397 changed files with 85455 additions and 209 deletions

View File

@ -66,6 +66,23 @@ sgw:
addr: 127.0.0.2
smf:
sbi:
- addr: 127.0.0.3
port: 7777
gtpc:
- addr: 127.0.0.3
- addr: ::1
pfcp:
- addr: 127.0.0.3
pdn:
- addr: 10.45.0.1/16
- addr: cafe::1/64
dns:
- 8.8.8.8
- 8.8.4.4
- 2001:4860:4860::8888
- 2001:4860:4860::8844
mtu: 1400
freeDiameter:
identity: pgw.open-ims.test
realm: open-ims.test
@ -82,28 +99,19 @@ smf:
connect:
- identity: pcrf.open-ims.test
addr: 127.0.0.5
gtpc:
- addr: 127.0.0.3
- addr: ::1
pfcp:
- addr: 127.0.0.3
pdn:
- addr: 10.45.0.1/16
- addr: cafe::1/64
dns:
- 8.8.8.8
- 8.8.4.4
- 2001:4860:4860::8888
- 2001:4860:4860::8844
mtu: 1400
nrf:
sbi:
addr:
- 127.0.0.1
- ::1
port: 7777
upf:
pfcp:
addr: 127.0.0.2
addr: 127.0.0.4
gtpu:
- addr:
- 127.0.0.3
- 127.0.0.4
- ::1
pdn:

View File

@ -47,7 +47,6 @@ hss:
# o Disable Stateless Address Autoconfiguration for IPv6
# no_slaac: true
#
#
parameter:
#
@ -92,4 +91,5 @@ max:
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#
pool:

View File

@ -26,6 +26,7 @@ open5gs_conf = '''
pgw.yaml
pcrf.yaml
nrf.yaml
smf.yaml
upf.yaml
'''.split()

View File

@ -336,7 +336,6 @@ pgw:
# o Disable Stateless Address Autoconfiguration for IPv6
# no_slaac: true
#
#
parameter:
#
@ -381,6 +380,7 @@ max:
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#
pool:
#
@ -395,4 +395,5 @@ pool:
# o max_attempts : 4
# o max_initial_timeout : 8000(8secs)
# o usrsctp_udp_port : 9899
#
sctp:

162
configs/open5gs/nrf.yaml.in Normal file
View File

@ -0,0 +1,162 @@
db_uri: mongodb://localhost/open5gs
#
# logger:
#
# o Set OGS_LOG_INFO to all domain level
# - If `level` is omitted, the default level is OGS_LOG_INFO)
# - If `domain` is omitted, the all domain level is set from 'level'
# (Nothing is needed)
#
# o Set OGS_LOG_ERROR to all domain level
# - `level` can be set with none, fatal, error, warn, info, debug, trace
# level: error
#
# o Set OGS_LOG_DEBUG to mme/emm domain level
# level: debug
# domain: mme,emm
#
# o Set OGS_LOG_TRACE to all domain level
# level: trace
# domain: core,fd,nrf,event,mem,sock
#
logger:
file: @localstatedir@/log/open5gs/nrf.log
#
# nrf:
#
# <SBI Server>
#
# o SBI Server(http://<all address available>:80)
# sbi:
#
# o SBI Server(http://<any address>:7777)
# sbi:
# - addr:
# - 0.0.0.0
# - ::0
# port: 7777
#
# o SBI Server(https://<all address avaiable>:443)
# sbi:
# tls:
# key: nrf.key
# pem: nrf.pem
#
# o SBI Server(https://127.0.0.1:443, http://[::1]:80)
# sbi:
# - addr: 127.0.0.1
# tls:
# key: nrf.key
# pem: nrf.pem
# - addr: ::1
#
# o SBI Server(http://nrf.open5gs.org:80)
# sbi:
# name: nrf.open5gs.org
#
# o SBI Server(http://127.0.0.1:7777)
# sbi:
# - addr: 127.0.0.1
# port: 7777
#
# o SBI Server(http://<eth0 IP address>:80)
# sbi:
# dev: eth0
#
nrf:
sbi:
addr:
- 127.0.0.1
- ::1
port: 7777
#
# parameter:
#
# o Number of output streams per SCTP associations.
# sctp_streams: 30
#
# o Disable use of IPv4 addresses (only IPv6)
# no_ipv4: true
#
# o Disable use of IPv6 addresses (only IPv4)
# no_ipv6: true
#
# o Prefer IPv4 instead of IPv6 for estabishing new GTP connections.
# prefer_ipv4: true
#
# o Enable Multicast traffic to the UE
# multicast: true
#
# o Disable Stateless Address Autoconfiguration for IPv6
# no_slaac: true
#
parameter:
#
# max:
#
# o Maximum Number of SGW per MME
# sgw: 32
# o Maximum Number of PGW per MME
# pgw: 32
# o Maximum Number of VLR per MME
# vlr: 32
# o Maximum Number of eNodeB per MME
# enb: 32
# o Maximum Number of UE per eNodeB
# ue: 128
#
max:
#
# pool:
#
# o The Number of Default Memory Pool Size
#
# - Pool-size 128 => 8192 Number
# - Pool-size 256 => 4096 Number
# - Pool-size 512 => 2048 Number
# - Pool-size 1024 => 1024 Number
# - Pool-size 2048 => 512 Number
# - Pool-size 8192 => 128 Number
# - Pool-size 1024*1024 => 8 Number
#
# 128: 8192
# 256: 4096
# 512: 2048
# 1024: 1024
# 2048: 512
# 8192: 128
# big: 8
#
# o Memory of Packet Buffering in SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in SGW
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#
pool:
#
# time:
#
# o NF Instance Validity (Default : 3600 seconds = 1 hour)
#
# o NF Instance Validity (10 seconds)
# nf_instance:
# validity: 10
#
# o Subscription Validity (Default : 86400 seconds = 1 day)
#
# o Subscription Validity (Disabled)
# subscription:
# validity: 0
#
# o Subscription Validity (3600 seconds = 1 hour)
# subscription:
# validity: 3600
#
time:

View File

@ -46,7 +46,6 @@ pcrf:
# o Disable Stateless Address Autoconfiguration for IPv6
# no_slaac: true
#
#
parameter:
#
@ -91,4 +90,5 @@ max:
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#
pool:

View File

@ -186,7 +186,6 @@ pgw:
# o Disable Stateless Address Autoconfiguration for IPv6
# no_slaac: true
#
#
parameter:
#
@ -231,4 +230,5 @@ max:
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#
pool:

View File

@ -82,7 +82,6 @@ sgw:
# o Disable Stateless Address Autoconfiguration for IPv6
# no_slaac: true
#
#
parameter:
no_ipv6: true
@ -128,4 +127,5 @@ max:
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#
pool:

View File

@ -23,6 +23,45 @@ logger:
#
# smf:
#
# <SBI Server>
#
# o SBI Server(http://<all address available>:80)
# sbi:
#
# o SBI Server(http://<any address>:80)
# sbi:
# - addr:
# - 0.0.0.0
# - ::0
# port: 7777
#
# o SBI Server(https://<all address avaiable>:443)
# sbi:
# tls:
# key: smf.key
# pem: smf.pem
#
# o SBI Server(https://127.0.0.3:443, http://[::1]:80)
# sbi:
# - addr: 127.0.0.3
# tls:
# key: smf.key
# pem: smf.pem
# - addr: ::1
#
# o SBI Server(http://smf.open5gs.org:80)
# sbi:
# name: smf.open5gs.org
#
# o SBI Server(http://127.0.0.3:7777)
# sbi:
# - addr: 127.0.0.3
# port: 7777
#
# o SBI Server(http://<eth0 IP address>:80)
# sbi:
# dev: eth0
#
# <PFCP Server>
#
# o PFCP Server(127.0.0.3:8805, ::1:8805)
@ -141,7 +180,9 @@ logger:
# - ::1
#
smf:
freeDiameter: @sysconfdir@/freeDiameter/pgw.conf
sbi:
- addr: 127.0.0.3
port: 7777
gtpc:
- addr: 127.0.0.3
- addr: ::1
@ -157,20 +198,54 @@ smf:
- 2001:4860:4860::8888
- 2001:4860:4860::8844
mtu: 1400
freeDiameter: @sysconfdir@/freeDiameter/pgw.conf
#
# nrf:
#
# <SBI Client>>
#
# o SBI Client(http://127.0.0.1:7777)
# sbi:
# addr: 127.0.0.1
# port: 7777
#
# o SBI Client(https://127.0.0.1:443, http://nrf.open5gs.org:80)
# sbi:
# - addr: 127.0.0.1
# tls:
# key: nrf.key
# pem: nrf.pem
# - name: nrf.open5gs.org
#
# o SBI Client(http://[fe80::1%@loopback_devname@]:80)
# If prefer_ipv4 is true, http://127.0.0.1:80 is selected.
#
# sbi:
# addr:
# - 127.0.0.1
# - fe80::1%@loopback_devname@
#
nrf:
sbi:
addr:
- 127.0.0.1
- ::1
port: 7777
#
# upf:
#
# <PFCP Client>>
#
# o PFCP Client(127.0.0.2:8805)
# o PFCP Client(127.0.0.4:8805)
#
# pfcp:
# addr: 127.0.0.2
# addr: 127.0.0.4
#
upf:
pfcp:
addr: 127.0.0.2
addr: 127.0.0.4
#
# parameter:
@ -193,7 +268,6 @@ upf:
# o Disable Stateless Address Autoconfiguration for IPv6
# no_slaac: true
#
#
parameter:
#
@ -238,4 +312,19 @@ max:
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#
pool:
#
# time:
#
# o NF Instance Heartbeat (Default : 3 seconds)
#
# o NF Instance Heartbeat (Disabled)
# nf_instance:
# heartbeat: 0
#
# o NF Instance Heartbeat (5 seconds)
# nf_instance:
# heartbeat: 5
time:

View File

@ -26,32 +26,32 @@ logger:
#
# <PFCP Server>
#
# o PFCP Server(127.0.0.2:8805)
# o PFCP Server(127.0.0.4:8805)
# pfcp:
# addr: 127.0.0.2
# addr: 127.0.0.4
#
# <GTP-U Server>>
#
# o GTP-U Server(127.0.0.3:2152, [::1]:2152)
# o GTP-U Server(127.0.0.4:2152, [::1]:2152)
# gtpu:
# - addr:
# - 127.0.0.3
# - 127.0.0.4
# - ::1
#
# o Same configuration(127.0.0.3:2152, [::1]:2152) as below.
# o Same configuration(127.0.0.4:2152, [::1]:2152) as below.
# gtpu:
# name: localhost
#
# o User Plane IP Resource information
# gtpu:
# - addr:
# - 127.0.0.3
# - 127.0.0.4
# - ::1
# teid_range_indication: 4
# teid_range: 10
# network_instance: internet
# source_interface: 0
# - addr: 127.0.0.4
# - addr: 127.0.10.4
# teid_range_indication: 4
# teid_range: 5
# network_instance: ims
@ -59,10 +59,10 @@ logger:
#
upf:
pfcp:
addr: 127.0.0.2
addr: 127.0.0.4
gtpu:
- addr:
- 127.0.0.3
- 127.0.0.4
- ::1
pdn:

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
open5gs (1.2.5) unstable; urgency=medium
* NRF is added
-- Sukchan Lee <acetcom@gmail.com> Mon, 18 May 2020 13:14:54 -0400
open5gs (1.2.4~eoan) eoan; urgency=medium
* Bug Fixed

2
debian/control vendored
View File

@ -17,6 +17,8 @@ Build-Depends: debhelper (>= 11),
libbson-dev,
libsctp-dev,
libyaml-dev,
libmicrohttpd-dev,
libcurl4-gnutls-dev,
Standards-Version: 4.3.0
Rules-Requires-Root: no
Homepage: https://open5gs.org

View File

@ -15,6 +15,7 @@ RUN yum -y install \
flex \
bison \
git \
meson \
lksctp-tools-devel \
libidn-devel \
gnutls-devel \
@ -22,7 +23,7 @@ RUN yum -y install \
openssl-devel \
cyrus-sasl-devel \
libyaml-devel \
iproute \
mongo-c-driver-devel
RUN pip3 install --upgrade pip && pip install meson
mongo-c-driver-devel \
libmicrohttpd-devel \
libcurl-devel \
iproute

View File

@ -9,6 +9,11 @@ RUN dnf -y install epel-release && \
dnf config-manager --set-enabled PowerTools && \
dnf -y update
RUN dnf -y install \
https://www.elrepo.org/elrepo-release-8.el8.elrepo.noarch.rpm && \
dnf config-manager --set-enabled elrepo-testing && \
dnf -y update
RUN dnf -y install \
python3 \
ninja-build \
@ -23,7 +28,9 @@ RUN dnf -y install \
openssl-devel \
cyrus-sasl-devel \
libyaml-devel \
iproute \
mongo-c-driver-devel
mongo-c-driver-devel \
libmicrohttpd-devel \
libcurl-devel \
iproute
RUN pip3 install --upgrade pip && pip install meson
RUN dnf -y install meson

1
docker/fedora/31 Symbolic link
View File

@ -0,0 +1 @@
latest

View File

@ -18,7 +18,9 @@ RUN dnf -y install \
openssl-devel \
cyrus-sasl-devel \
libyaml-devel \
iproute \
mongo-c-driver-devel
mongo-c-driver-devel \
libmicrohttpd-devel \
libcurl-devel \
iproute
RUN pip3 install --upgrade pip && pip install meson
RUN dnf -y install meson

View File

@ -6,6 +6,7 @@ FROM ${username}/${dist}-${tag}-open5gs-base
MAINTAINER Sukchan Lee <acetcom@gmail.com>
RUN dnf -y install \
findutils \
cscope \
vim \
sudo \

View File

@ -25,6 +25,8 @@ RUN apt-get update && \
libmongoc-dev \
libbson-dev \
libyaml-dev \
libmicrohttpd-dev \
libcurl4-gnutls-dev \
iproute2 \
ca-certificates \
netbase \

View File

@ -40,7 +40,7 @@ $ sudo ip link set ogstun up
Install the dependencies for building the source code.
```bash
$ sudo apt install python3-pip python3-setuptools python3-wheel ninja-build build-essential flex bison git libsctp-dev libgnutls28-dev libgcrypt-dev libssl-dev libidn11-dev libmongoc-dev libbson-dev libyaml-dev meson
$ sudo apt install python3-pip python3-setuptools python3-wheel ninja-build build-essential flex bison git libsctp-dev libgnutls28-dev libgcrypt-dev libssl-dev libidn11-dev libmongoc-dev libbson-dev libyaml-dev libmicrohttpd-dev libcurl4-gnutls-dev meson
```
Git clone.

View File

@ -23,8 +23,13 @@ EOF'
Install MongoDB with Package Manager.
```bash
sudo yum -y install mongodb-org
sudo systemctl start mongod (if '/usr/bin/mongod' is not running)
sudo dnf -y install mongodb-org
```
Run MongoDB server.
```bash
$ mkdir -p ./data/db
$ mongod --dbpath ./data/db
```
### Setting up TUN device (No persistent after rebooting)
@ -85,15 +90,21 @@ $ sudo dnf config-manager --set-enabled PowerTools
$ sudo update
```
Install the depedencies for building the source code.
Configure ELRepo(with testing) package.
```bash
$ sudo dnf install python3 ninja-build gcc flex bison git lksctp-tools-devel libidn-devel gnutls-devel libgcrypt-devel openssl-devel cyrus-sasl-devel libyaml-devel iproute mongo-c-driver-devel
$ sudo dnf install https://www.elrepo.org/elrepo-release-8.el8.elrepo.noarch.rpm
$ sudo dnf config-manager --set-enabled elrepo-testing
$ sudo dnf update
```
Install Meson using Python.
Install the depedencies for building the source code.
```bash
$ sudo pip3 install --upgrade pip
$ sudo pip install meson
$ sudo dnf install python3 ninja-build gcc flex bison git lksctp-tools-devel libidn-devel gnutls-devel libgcrypt-devel openssl-devel cyrus-sasl-devel libyaml-devel mongo-c-driver-devel libmicrohttpd-devel libcurl-devel iproute
```
Install Meson
```bash
$ sudo dnf install meson
```
Git clone.

View File

@ -67,13 +67,12 @@ $ ip link show
Install the depedencies for building the source code.
```bash
$ sudo dnf install python3 ninja-build gcc flex bison git lksctp-tools-devel libidn-devel gnutls-devel libgcrypt-devel openssl-devel cyrus-sasl-devel libyaml-devel iproute mongo-c-driver-devel
$ sudo dnf install python3 ninja-build gcc flex bison git lksctp-tools-devel libidn-devel gnutls-devel libgcrypt-devel openssl-devel cyrus-sasl-devel libyaml-devel mongo-c-driver-devel libmicrohttpd-devel libcurl-devel iproute
```
Install Meson using Python.
Install Meson
```bash
$ sudo pip3 install --upgrade pip
$ sudo pip install meson
$ sudo dnf install meson
```
Git clone.

View File

@ -45,7 +45,7 @@ $ sudo sysctl -w net.inet.ip.forwarding=1
Install the depedencies for building the source code.
```bash
$ sudo pkg install py36-pip ninja gcc bison gsed pkgconf git mongo-c-driver gnutls libgcrypt libidn libyaml
$ sudo pkg install py36-pip ninja gcc bison gsed pkgconf git mongo-c-driver gnutls libgcrypt libidn libyaml libmicrohttpd curl
```
Install Meson using Python.

View File

@ -63,7 +63,7 @@ $ sudo pfctl -e -f /etc/pf.anchors/org.open5gs
Install the depedencies for building the source code.
```bash
$ brew install mongo-c-driver gnutls libgcrypt libidn libyaml pkg-config
$ brew install mongo-c-driver gnutls libgcrypt libidn libyaml libmicrohttpd curl pkg-config
```
Install Meson using Homebrew.

View File

@ -57,6 +57,9 @@ void pgw_terminate(void);
int pcrf_initialize(void);
void pcrf_terminate(void);
int nrf_initialize(void);
void nrf_terminate(void);
int smf_initialize(void);
void smf_terminate(void);

View File

@ -140,6 +140,7 @@ static void recalculate_pool_size(void)
self.pool.ue = self.max.ue * self.max.enb;
self.pool.pfcp = ogs_max(self.max.smf, self.max.upf);
self.pool.sbi = self.pool.pfcp;
self.pool.sess = self.pool.ue * OGS_MAX_NUM_OF_SESS;
self.pool.bearer = self.pool.sess * MAX_NUM_OF_BEARER;
self.pool.tunnel = self.pool.bearer * MAX_NUM_OF_TUNNEL;
@ -175,6 +176,10 @@ static int config_prepare(void)
recalculate_pool_size();
self.time.nf_instance.heartbeat = 3; /* 3 second */
self.time.nf_instance.validity = 3600; /* 3600 seconds = 1 hour */
self.time.subscription.validity = 86400; /* 86400 seconds = 1 day */
return OGS_OK;
}
@ -187,6 +192,15 @@ static int ogs_app_ctx_validation(void)
return OGS_ERROR;
}
if (self.time.nf_instance.validity == 0) {
ogs_error("NF Instance validity-time should not 0");
ogs_error("time:");
ogs_error(" nf_instance:");
ogs_error(" validity: 0");
return OGS_ERROR;
}
return OGS_OK;
}
int ogs_config_parse()
@ -358,8 +372,49 @@ int ogs_config_parse()
} else
ogs_warn("unknown key `%s`", pool_key);
}
} else if (!strcmp(root_key, "time")) {
ogs_yaml_iter_t time_iter;
ogs_yaml_iter_recurse(&root_iter, &time_iter);
while (ogs_yaml_iter_next(&time_iter)) {
const char *time_key = ogs_yaml_iter_key(&time_iter);
ogs_assert(time_key);
if (!strcmp(time_key, "nf_instance")) {
ogs_yaml_iter_t sbi_iter;
ogs_yaml_iter_recurse(&time_iter, &sbi_iter);
while (ogs_yaml_iter_next(&sbi_iter)) {
const char *sbi_key =
ogs_yaml_iter_key(&sbi_iter);
ogs_assert(sbi_key);
if (!strcmp(sbi_key, "heartbeat")) {
const char *v = ogs_yaml_iter_value(&sbi_iter);
if (v) self.time.nf_instance.heartbeat = atoi(v);
} else if (!strcmp(sbi_key, "validity")) {
const char *v = ogs_yaml_iter_value(&sbi_iter);
if (v) self.time.nf_instance.validity = atoi(v);
} else
ogs_warn("unknown key `%s`", sbi_key);
}
} else if (!strcmp(time_key, "subscription")) {
ogs_yaml_iter_t sbi_iter;
ogs_yaml_iter_recurse(&time_iter, &sbi_iter);
while (ogs_yaml_iter_next(&sbi_iter)) {
const char *sbi_key =
ogs_yaml_iter_key(&sbi_iter);
ogs_assert(sbi_key);
if (!strcmp(sbi_key, "validity")) {
const char *v = ogs_yaml_iter_value(&sbi_iter);
if (v) self.time.subscription.validity = atoi(v);
} else
ogs_warn("unknown key `%s`", sbi_key);
}
} else
ogs_warn("unknown key `%s`", time_key);
}
}
}
rv = ogs_app_ctx_validation();

View File

@ -78,11 +78,22 @@ typedef struct ogs_config_s {
int ue;
int pfcp;
int sbi;
int sess;
int bearer;
int tunnel;
int pf;
} pool;
struct {
struct {
int heartbeat;
int validity;
} nf_instance;
struct {
int validity;
} subscription;
} time;
} ogs_config_t;
int ogs_config_init(void);

View File

@ -202,9 +202,9 @@ ogs_libcore_conf.set('OGS_BIG_ENDIAN', 4321)
ogs_libcore_conf.set('OGS_LITTLE_ENDIAN', 1234)
if host_machine.endian() == 'big'
ogs_libcore_conf.set('OGS_BYTE_ORDER', 'OGS_BIG_ENDIAN')
ogs_libcore_conf.set('OGS_BYTE_ORDER', 'OGS_BIG_ENDIAN')
else
ogs_libcore_conf.set('OGS_BYTE_ORDER', 'OGS_LITTLE_ENDIAN')
ogs_libcore_conf.set('OGS_BYTE_ORDER', 'OGS_LITTLE_ENDIAN')
endif
if host_system == 'windows'
@ -235,6 +235,7 @@ libcore_sources = files('''
ogs-rbtree.h
ogs-timer.h
ogs-rand.h
ogs-uuid.h
ogs-thread.h
ogs-signal.h
ogs-process.h
@ -269,6 +270,7 @@ libcore_sources = files('''
ogs-rbtree.c
ogs-timer.c
ogs-rand.c
ogs-uuid.c
ogs-thread.c
ogs-signal.c
ogs-process.c
@ -295,6 +297,13 @@ libcore_sources = files('''
abts.c
'''.split())
if have_func_epoll_ctl
libcore_sources += files('ogs-epoll.c')
endif
if have_func_kqueue
libcore_sources += files('ogs-kqueue.c')
endif
libcore_inc = include_directories('.')
libcore = library('ogscore',

View File

@ -131,3 +131,7 @@ void *ogs_buffer_to_bcd(uint8_t *in, int in_len, void *out)
return out;
}
char ogs_from_hex(char ch)
{
return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
}

View File

@ -36,6 +36,8 @@ uint64_t ogs_buffer_to_uint64(void *buffer, int size);
void *ogs_bcd_to_buffer(const char *in, void *out, int *out_len);
void *ogs_buffer_to_bcd(uint8_t *in, int in_len, void *out);
char ogs_from_hex(char ch);
#ifdef __cplusplus
}
#endif

View File

@ -37,6 +37,7 @@
#include "core/ogs-pkbuf.h"
#include "core/ogs-memory.h"
#include "core/ogs-rand.h"
#include "core/ogs-uuid.h"
#include "core/ogs-rbtree.h"
#include "core/ogs-timer.h"
#include "core/ogs-thread.h"

View File

@ -30,7 +30,7 @@
static void epoll_init(ogs_pollset_t *pollset);
static void epoll_cleanup(ogs_pollset_t *pollset);
static int epoll_add(ogs_poll_t *poll, short when);
static int epoll_add(ogs_poll_t *poll);
static int epoll_remove(ogs_poll_t *poll);
static int epoll_process(ogs_pollset_t *pollset, ogs_time_t timeout);
@ -45,9 +45,15 @@ const ogs_pollset_actions_t ogs_epoll_actions = {
ogs_notify_pollset,
};
struct epoll_map_s {
ogs_poll_t *read;
ogs_poll_t *write;
};
struct epoll_context_s {
int epfd;
ogs_hash_t *map_hash;
struct epoll_event *event_list;
};
@ -64,6 +70,9 @@ static void epoll_init(ogs_pollset_t *pollset)
ogs_core()->socket.pool, sizeof(struct epoll_event));
ogs_assert(context->event_list);
context->map_hash = ogs_hash_make();
ogs_assert(context->map_hash);
context->epfd = epoll_create(ogs_core()->socket.pool);
ogs_assert(context->epfd >= 0);
@ -81,15 +90,17 @@ static void epoll_cleanup(ogs_pollset_t *pollset)
ogs_notify_final(pollset);
close(context->epfd);
ogs_free(context->event_list);
ogs_hash_destroy(context->map_hash);
ogs_free(context);
}
static int epoll_add(ogs_poll_t *poll, short when)
static int epoll_add(ogs_poll_t *poll)
{
int rv, op;
ogs_pollset_t *pollset = NULL;
struct epoll_context_s *context = NULL;
int rv;
struct epoll_map_s *map = NULL;
struct epoll_event ee;
ogs_assert(poll);
@ -98,17 +109,33 @@ static int epoll_add(ogs_poll_t *poll, short when)
context = pollset->context;
ogs_assert(context);
map = ogs_hash_get(context->map_hash, &poll->fd, sizeof(poll->fd));
if (!map) {
map = ogs_calloc(1, sizeof(*map));
ogs_assert(map);
op = EPOLL_CTL_ADD;
ogs_hash_set(context->map_hash, &poll->fd, sizeof(poll->fd), map);
} else {
op = EPOLL_CTL_MOD;
}
if (poll->when & OGS_POLLIN)
map->read = poll;
if (poll->when & OGS_POLLOUT)
map->write = poll;
ee.events = 0;
if (when == OGS_POLLIN)
if (map->read)
ee.events |= (EPOLLIN|EPOLLRDHUP);
if (when == OGS_POLLOUT)
if (map->write)
ee.events |= EPOLLOUT;
ee.data.ptr = map;
ee.data.ptr = poll;
rv = epoll_ctl(context->epfd, EPOLL_CTL_ADD, poll->fd, &ee);
rv = epoll_ctl(context->epfd, op, poll->fd, &ee);
if (rv < 0) {
ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "epoll_ctl failed");
ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
"epoll_ctl[%d] failed", op);
return OGS_ERROR;
}
@ -117,9 +144,10 @@ static int epoll_add(ogs_poll_t *poll, short when)
static int epoll_remove(ogs_poll_t *poll)
{
int rv;
int rv, op;
ogs_pollset_t *pollset = NULL;
struct epoll_context_s *context = NULL;
struct epoll_map_s *map = NULL;
struct epoll_event ee;
ogs_assert(poll);
@ -128,13 +156,35 @@ static int epoll_remove(ogs_poll_t *poll)
context = pollset->context;
ogs_assert(context);
ee.events = 0;
ee.data.ptr = NULL;
map = ogs_hash_get(context->map_hash, &poll->fd, sizeof(poll->fd));
ogs_assert(map);
rv = epoll_ctl(context->epfd, EPOLL_CTL_DEL, poll->fd, &ee);
if (poll->when & OGS_POLLIN)
map->read = NULL;
if (poll->when & OGS_POLLOUT)
map->write = NULL;
ee.events = 0;
if (map->read)
ee.events |= (EPOLLIN|EPOLLRDHUP);
if (map->write)
ee.events |= EPOLLOUT;
if (map->read || map->write) {
op = EPOLL_CTL_MOD;
ee.data.ptr = map;
} else {
op = EPOLL_CTL_DEL;
ee.data.ptr = NULL;
ogs_free(map);
ogs_hash_set(context->map_hash, &poll->fd, sizeof(poll->fd), NULL);
}
rv = epoll_ctl(context->epfd, op, poll->fd, &ee);
if (rv < 0) {
ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
"epoll_remove failed");
"epoll_remove[%d] failed", op);
return OGS_ERROR;
}
@ -163,7 +213,7 @@ static int epoll_process(ogs_pollset_t *pollset, ogs_time_t timeout)
}
for (i = 0; i < num_of_poll; i++) {
ogs_poll_t *poll = NULL;
struct epoll_map_s *map = NULL;
uint32_t received;
short when = 0;
@ -182,11 +232,16 @@ static int epoll_process(ogs_pollset_t *pollset, ogs_time_t timeout)
if (!when)
continue;
poll = context->event_list[i].data.ptr;
ogs_assert(poll);
map = context->event_list[i].data.ptr;
ogs_assert(map);
if (poll->handler) {
poll->handler(when, poll->fd, poll->data);
if (map->read && map->write && map->read == map->write) {
map->read->handler(when, map->read->fd, map->read->data);
} else {
if (map->read && (when & OGS_POLLIN))
map->read->handler(when, map->read->fd, map->read->data);
if (map->write && (when & OGS_POLLOUT))
map->write->handler(when, map->write->fd, map->write->data);
}
}

View File

@ -31,7 +31,7 @@
static void kqueue_init(ogs_pollset_t *pollset);
static void kqueue_cleanup(ogs_pollset_t *pollset);
static int kqueue_add(ogs_poll_t *poll, short when);
static int kqueue_add(ogs_poll_t *poll);
static int kqueue_remove(ogs_poll_t *poll);
static int kqueue_process(ogs_pollset_t *pollset, ogs_time_t timeout);
@ -123,14 +123,14 @@ static int kqueue_set(ogs_poll_t *poll, int filter, int flags)
return OGS_OK;
}
static int kqueue_add(ogs_poll_t *poll, short when)
static int kqueue_add(ogs_poll_t *poll)
{
int filter = 0;
if (when & OGS_POLLIN) {
if (poll->when & OGS_POLLIN) {
filter = EVFILT_READ;
}
if (when & OGS_POLLOUT) {
if (poll->when & OGS_POLLOUT) {
filter = EVFILT_WRITE;
}

View File

@ -164,6 +164,19 @@ extern "C" {
#define ogs_container_of(ptr, type, member) \
(type *)((u_char *)ptr - offsetof(type, member))
#ifndef SWITCH_CASE_INIT
#define SWITCH_CASE_INIT
#define SWITCH(X) {char *__switch_p__, __switch_next__; \
for (__switch_p__ = (char *)X, __switch_next__ = 1; \
__switch_p__; \
__switch_p__ = 0, __switch_next__ = 1) { {
#define CASE(X) } if (!__switch_next__ || \
!(__switch_next__ = \
strcmp(__switch_p__, X))) {
#define DEFAULT } {
#define END }}}
#endif
#ifdef __cplusplus
}
#endif

View File

@ -32,6 +32,7 @@ typedef struct ogs_poll_s {
ogs_lnode_t node;
int index;
short when;
ogs_socket_t fd;
ogs_poll_handler_f handler;
void *data;

View File

@ -17,6 +17,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "core-config-private.h"
#include "ogs-core.h"
#include "ogs-poll-private.h"
@ -80,13 +82,14 @@ ogs_poll_t *ogs_pollset_add(ogs_pollset_t *pollset, short when,
rc = ogs_closeonexec(fd);
ogs_assert(rc == OGS_OK);
poll->when = when;
poll->fd = fd;
poll->handler = handler;
poll->data = data;
poll->pollset = pollset;
rc = ogs_pollset_actions.add(poll, when);
rc = ogs_pollset_actions.add(poll);
if (rc != OGS_OK) {
ogs_error("cannot add poll");
ogs_pool_free(&pollset->pool, poll);

View File

@ -44,7 +44,7 @@ typedef struct ogs_pollset_actions_s {
void (*init)(ogs_pollset_t *pollset);
void (*cleanup)(ogs_pollset_t *pollset);
int (*add)(ogs_poll_t *poll, short when);
int (*add)(ogs_poll_t *poll);
int (*remove)(ogs_poll_t *poll);
int (*poll)(ogs_pollset_t *pollset, ogs_time_t timeout);

View File

@ -28,7 +28,7 @@
static void select_init(ogs_pollset_t *pollset);
static void select_cleanup(ogs_pollset_t *pollset);
static int select_add(ogs_poll_t *poll, short when);
static int select_add(ogs_poll_t *poll);
static int select_remove(ogs_poll_t *poll);
static int select_process(ogs_pollset_t *pollset, ogs_time_t timeout);
@ -83,7 +83,7 @@ static void select_cleanup(ogs_pollset_t *pollset)
ogs_free(context);
}
static int select_add(ogs_poll_t *poll, short when)
static int select_add(ogs_poll_t *poll)
{
ogs_pollset_t *pollset = NULL;
struct select_context_s *context = NULL;
@ -94,11 +94,11 @@ static int select_add(ogs_poll_t *poll, short when)
context = pollset->context;
ogs_assert(context);
if (when & OGS_POLLIN) {
if (poll->when & OGS_POLLIN) {
FD_SET(poll->fd, &context->master_read_fd_set);
}
if (when & OGS_POLLOUT) {
if (poll->when & OGS_POLLOUT) {
FD_SET(poll->fd, &context->master_write_fd_set);
}
@ -121,8 +121,11 @@ static int select_remove(ogs_poll_t *poll)
context = pollset->context;
ogs_assert(context);
FD_CLR(poll->fd, &context->master_read_fd_set);
FD_CLR(poll->fd, &context->master_write_fd_set);
if (poll->when & OGS_POLLIN)
FD_CLR(poll->fd, &context->master_read_fd_set);
if (poll->when & OGS_POLLOUT)
FD_CLR(poll->fd, &context->master_write_fd_set);
if (context->max_fd == poll->fd) {
context->max_fd = -1;

View File

@ -579,3 +579,32 @@ int ogs_ipsubnet(ogs_ipsubnet_t *ipsub,
return OGS_OK;
}
char *ogs_gethostname(ogs_sockaddr_t *addr)
{
int rv;
char hostname[OGS_MAX_FQDN_LEN];
ogs_assert(addr);
if (!addr->hostname)
return NULL;
rv = ogs_getnameinfo(hostname, OGS_MAX_FQDN_LEN, addr, 0);
if (rv == OGS_OK && strcmp(addr->hostname, hostname) == 0)
return addr->hostname;
return NULL;
}
char *ogs_ipstrdup(ogs_sockaddr_t *addr)
{
char buf[OGS_ADDRSTRLEN + 1];
ogs_assert(addr);
memset(buf, 0, sizeof(buf));
OGS_ADDR(addr, buf);
return ogs_strdup(buf);
}

View File

@ -94,6 +94,9 @@ bool ogs_sockaddr_is_equal(void *p, void *q);
int ogs_ipsubnet(ogs_ipsubnet_t *ipsub,
const char *ipstr, const char *mask_or_numbits);
char *ogs_gethostname(ogs_sockaddr_t *addr);
char *ogs_ipstrdup(ogs_sockaddr_t *addr);
#ifdef __cplusplus
}
#endif

View File

@ -154,3 +154,77 @@ char *ogs_cpystrn(char *dst, const char *src, size_t dst_size)
return (d);
}
/*
* char *ogs_msprintf(const char *message, ...)
* char *mstrcatf(char *source, const char *message, ...)
*
* Orcania library
* Copyright 2015-2018 Nicolas Mora <mail@babelouest.org>
* License: LGPL-2.1
*
* https://github.com/babelouest/orcania.git
*/
char *ogs_msprintf(const char *message, ...)
{
va_list argp, argp_cpy;
size_t out_len = 0;
char *out = NULL;
if (message != NULL) {
va_start(argp, message);
va_copy(argp_cpy, argp); /* We make a copy because
in some architectures,
vsnprintf can modify argp */
out_len = vsnprintf(NULL, 0, message, argp);
out = ogs_malloc(out_len + sizeof(char));
if (out == NULL) {
va_end(argp);
va_end(argp_cpy);
return NULL;
}
vsnprintf(out, (out_len + sizeof(char)), message, argp_cpy);
va_end(argp);
va_end(argp_cpy);
}
return out;
}
char *ogs_mstrcatf(char *source, const char *message, ...)
{
va_list argp, argp_cpy;
char *out = NULL, *message_formatted = NULL;
size_t message_formatted_len = 0, out_len = 0;
if (message != NULL) {
if (source != NULL) {
va_start(argp, message);
va_copy(argp_cpy, argp); /* We make a copy because
in some architectures,
vsnprintf can modify argp */
message_formatted_len = vsnprintf(NULL, 0, message, argp);
message_formatted = ogs_malloc(message_formatted_len+sizeof(char));
if (message_formatted != NULL) {
vsnprintf(message_formatted,
(message_formatted_len+sizeof(char)), message, argp_cpy);
out = ogs_msprintf("%s%s", source, message_formatted);
ogs_free(message_formatted);
ogs_free(source);
}
va_end(argp);
va_end(argp_cpy);
} else {
va_start(argp, message);
va_copy(argp_cpy, argp); /* We make a copy because
in some architectures,
vsnprintf can modify argp */
out_len = vsnprintf(NULL, 0, message, argp);
out = ogs_malloc(out_len+sizeof(char));
if (out != NULL) {
vsnprintf(out, (out_len+sizeof(char)), message, argp_cpy);
}
va_end(argp);
va_end(argp_cpy);
}
}
return out;
}

View File

@ -55,6 +55,11 @@ void *ogs_memdup(const void *m, size_t n);
char *ogs_cpystrn(char *dst, const char *src, size_t dst_size);
char *ogs_msprintf(const char *message, ...)
OGS_GNUC_PRINTF(1, 2);
char *ogs_mstrcatf(char *source, const char *message, ...)
OGS_GNUC_PRINTF(2, 3);
#ifdef __cplusplus
}
#endif

View File

@ -67,6 +67,13 @@ void ogs_gmtime(time_t s, struct tm *tm);
void ogs_msleep(time_t msec);
void ogs_usleep(time_t usec);
#define OGS_TIME_ISO8601_FORMATTED_LENGTH 128
#define OGS_TIME_ISO8601_FORMAT "%Y-%m-%dT%H:%M:%S%z"
#define ogs_mktime mktime
#define ogs_strptime strptime
#define ogs_strftime strftime
#ifdef __cplusplus
}
#endif

View File

@ -87,7 +87,6 @@ ogs_timer_t *ogs_timer_add(
{
ogs_timer_t *timer = NULL;
ogs_assert(manager);
ogs_assert(cb);
ogs_pool_alloc(&manager->pool, &timer);
ogs_assert(timer);
@ -117,7 +116,7 @@ void ogs_timer_start(ogs_timer_t *timer, ogs_time_t duration)
{
ogs_timer_mgr_t *manager = NULL;
ogs_assert(timer);
ogs_assert(duration > 0);
ogs_assert(duration);
manager = timer->manager;
ogs_assert(manager);

250
lib/core/ogs-uuid.c Normal file
View File

@ -0,0 +1,250 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "core-config-private.h"
#if HAVE_CTYPE_H
#include <ctype.h>
#endif
#include "ogs-core.h"
#define NODE_LENGTH 6
static int uuid_state_seqnum;
static unsigned char uuid_state_node[NODE_LENGTH] = { 0 };
static void get_random_info(unsigned char node[NODE_LENGTH])
{
ogs_random(node, NODE_LENGTH);
}
/* This implementation generates a random node ID instead of a
system-dependent call to get IEEE node ID. This is also more secure:
we aren't passing out our MAC address. */
static void get_pseudo_node_identifier(unsigned char *node)
{
get_random_info(node);
node[0] |= 0x01; /* this designates a random multicast node ID */
}
/* true_random -- generate a crypto-quality random number. */
static int true_random(void)
{
unsigned char buf[2];
ogs_random(buf, 2);
return (buf[0] << 8) | buf[1];
}
static void init_state(void)
{
uuid_state_seqnum = true_random();
get_pseudo_node_identifier(uuid_state_node);
}
static void get_system_time(uint64_t *uuid_time)
{
struct timeval tv;
/* ### fix this call to be more portable? */
ogs_gettimeofday(&tv);
*uuid_time = tv.tv_sec * OGS_USEC_PER_SEC + tv.tv_usec;
/* Offset between UUID formatted times and Unix formatted times.
UUID UTC base time is October 15, 1582.
Unix base time is January 1, 1970. */
*uuid_time = (*uuid_time * 10) + 0x01B21DD213814000;
}
static void get_current_time(uint64_t *timestamp)
{
/* ### this needs to be made thread-safe! */
uint64_t time_now;
static uint64_t time_last = 0;
static uint64_t fudge = 0;
get_system_time(&time_now);
/* if clock reading changed since last UUID generated... */
if (time_last != time_now) {
/* The clock reading has changed since the last UUID was generated.
Reset the fudge factor. if we are generating them too fast, then
the fudge may need to be reset to something greater than zero. */
if (time_last + fudge > time_now)
fudge = time_last + fudge - time_now + 1;
else
fudge = 0;
time_last = time_now;
}
else {
/* We generated two really fast. Bump the fudge factor. */
++fudge;
}
*timestamp = time_now + fudge;
}
void ogs_uuid_get(ogs_uuid_t *uuid)
{
uint64_t timestamp;
unsigned char *d = NULL;
int version = 4;
ogs_assert(uuid);
d = uuid->data;
if (!uuid_state_node[0])
init_state();
get_current_time(&timestamp);
/* time_low, uint32 */
d[3] = (unsigned char)timestamp;
d[2] = (unsigned char)(timestamp >> 8);
d[1] = (unsigned char)(timestamp >> 16);
d[0] = (unsigned char)(timestamp >> 24);
/* time_mid, uint16 */
d[5] = (unsigned char)(timestamp >> 32);
d[4] = (unsigned char)(timestamp >> 40);
/* Set the four most significant bits (bits 12 through 15) of the
* time_hi_and_version field to the 4-bit version number from
* Section 4.1.3. */
d[7] = (unsigned char)(timestamp >> 48);
d[6] = (unsigned char)(((timestamp >> 56) & 0x0F) | (version << 4));
/* Set the two most significant bits (bits 6 and 7) of the
* clock_seq_hi_and_reserved to zero and one, respectively. */
d[8] = (unsigned char)(((uuid_state_seqnum >> 8) & 0x3F) | 0x80);
/* clock_seq_low, uint8 */
d[9] = (unsigned char)uuid_state_seqnum;
/* node, byte[6] */
memcpy(&d[10], uuid_state_node, NODE_LENGTH);
}
void ogs_uuid_format(char *buffer, const ogs_uuid_t *uuid)
{
const unsigned char *d = uuid->data;
sprintf(buffer, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
"%02x%02x%02x%02x%02x%02x",
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
}
/* convert a pair of hex digits to an integer value [0,255] */
#if 'A' == 65
static unsigned char parse_hexpair(const char *s)
{
int result;
int temp;
result = s[0] - '0';
if (result > 48)
result = (result - 39) << 4;
else if (result > 16)
result = (result - 7) << 4;
else
result = result << 4;
temp = s[1] - '0';
if (temp > 48)
result |= temp - 39;
else if (temp > 16)
result |= temp - 7;
else
result |= temp;
return (unsigned char)result;
}
#else
static unsigned char parse_hexpair(const char *s)
{
int result;
if (isdigit(*s)) {
result = (*s - '0') << 4;
}
else {
if (isupper(*s)) {
result = (*s - 'A' + 10) << 4;
}
else {
result = (*s - 'a' + 10) << 4;
}
}
++s;
if (isdigit(*s)) {
result |= (*s - '0');
}
else {
if (isupper(*s)) {
result |= (*s - 'A' + 10);
}
else {
result |= (*s - 'a' + 10);
}
}
return (unsigned char)result;
}
#endif
int ogs_uuid_parse(ogs_uuid_t *uuid, const char *uuid_str)
{
int i;
unsigned char *d = uuid->data;
for (i = 0; i < 36; ++i) {
char c = uuid_str[i];
if (!isxdigit(c) &&
!(c == '-' && (i == 8 || i == 13 || i == 18 || i == 23)))
/* ### need a better value */
return OGS_ERROR;
}
if (uuid_str[36] != '\0') {
/* ### need a better value */
return OGS_ERROR;
}
d[0] = parse_hexpair(&uuid_str[0]);
d[1] = parse_hexpair(&uuid_str[2]);
d[2] = parse_hexpair(&uuid_str[4]);
d[3] = parse_hexpair(&uuid_str[6]);
d[4] = parse_hexpair(&uuid_str[9]);
d[5] = parse_hexpair(&uuid_str[11]);
d[6] = parse_hexpair(&uuid_str[14]);
d[7] = parse_hexpair(&uuid_str[16]);
d[8] = parse_hexpair(&uuid_str[19]);
d[9] = parse_hexpair(&uuid_str[21]);
for (i = 6; i--;)
d[10 + i] = parse_hexpair(&uuid_str[i*2+24]);
return OGS_OK;
}

45
lib/core/ogs-uuid.h Normal file
View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#if !defined(OGS_CORE_INSIDE) && !defined(OGS_CORE_COMPILATION)
#error "This header cannot be included directly."
#endif
#ifndef OGS_UUID_H
#define OGS_UUID_H
#ifdef __cplusplus
extern "C" {
#endif
#define OGS_UUID_FORMATTED_LENGTH 36
typedef struct {
unsigned char data[16]; /**< the actual UUID */
} ogs_uuid_t;
void ogs_uuid_get(ogs_uuid_t *uuid);
void ogs_uuid_format(char *buffer, const ogs_uuid_t *uuid);
int ogs_uuid_parse(ogs_uuid_t *uuid, const char *uuid_str);
#ifdef __cplusplus
}
#endif
#endif /* OGS_UUID_H */

View File

@ -29,3 +29,4 @@ subdir('s1ap')
subdir('nas')
subdir('gtp')
subdir('pfcp')
subdir('sbi')

View File

@ -35,12 +35,12 @@ static OGS_POOL(ogs_pfcp_bar_pool, ogs_pfcp_bar_t);
static OGS_POOL(ogs_pfcp_dev_pool, ogs_pfcp_dev_t);
static OGS_POOL(ogs_pfcp_subnet_pool, ogs_pfcp_subnet_t);
static int context_initiaized = 0;
static int context_initialized = 0;
void ogs_pfcp_context_init(int num_of_gtpu_resource)
{
struct timeval tv;
ogs_assert(context_initiaized == 0);
ogs_assert(context_initialized == 0);
/* Initialize SMF context */
memset(&self, 0, sizeof(ogs_pfcp_context_t));
@ -88,12 +88,12 @@ void ogs_pfcp_context_init(int num_of_gtpu_resource)
self.pdr_hash = ogs_hash_make();
context_initiaized = 1;
context_initialized = 1;
}
void ogs_pfcp_context_final(void)
{
ogs_assert(context_initiaized == 1);
ogs_assert(context_initialized == 1);
ogs_assert(self.pdr_hash);
ogs_hash_destroy(self.pdr_hash);
@ -116,7 +116,7 @@ void ogs_pfcp_context_final(void)
ogs_pool_final(&ogs_pfcp_node_pool);
ogs_pool_final(&ogs_pfcp_gtpu_resource_pool);
context_initiaized = 0;
context_initialized = 0;
}
ogs_pfcp_context_t *ogs_pfcp_self(void)

View File

@ -24,30 +24,29 @@ int ogs_pfcp_sockaddr_to_node_id(
ogs_pfcp_node_id_t *node_id, int *len)
{
const int hdr_len = 1;
int rv;
char hostname[OGS_MAX_FQDN_LEN];
char *hostname = NULL;
ogs_assert(node_id);
memset(node_id, 0, sizeof *node_id);
if (addr && addr->hostname) {
rv = ogs_getnameinfo(hostname, OGS_MAX_FQDN_LEN, addr, 0);
if (rv == OGS_OK && strcmp(addr->hostname, hostname) == 0) {
if (addr) {
hostname = ogs_gethostname(addr);
if (hostname) {
node_id->type = OGS_PFCP_NODE_ID_FQDN;
*len = ogs_fqdn_build(node_id->fqdn,
addr->hostname, strlen(addr->hostname)) + hdr_len;
hostname, strlen(hostname)) + hdr_len;
return OGS_OK;
}
}
if (addr6 && addr6->hostname) {
rv = ogs_getnameinfo(hostname, OGS_MAX_FQDN_LEN, addr6, 0);
if (rv == OGS_OK && strcmp(addr6->hostname, hostname) == 0) {
if (addr6) {
hostname = ogs_gethostname(addr6);
if (hostname) {
node_id->type = OGS_PFCP_NODE_ID_FQDN;
*len = ogs_fqdn_build(node_id->fqdn,
addr6->hostname, strlen(addr6->hostname)) + hdr_len;
hostname, strlen(hostname)) + hdr_len;
return OGS_OK;
}

674
lib/sbi/client.c Normal file
View File

@ -0,0 +1,674 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "ogs-app.h"
#include "ogs-sbi.h"
#include "sbi-private.h"
#include "curl/curl.h"
typedef struct sockinfo_s {
ogs_poll_t *poll;
curl_socket_t sockfd;
int action;
CURL *easy;
ogs_sbi_client_t *client;
} sockinfo_t;
typedef struct connection_s {
ogs_lnode_t lnode;
void *data;
char *method;
int num_of_header;
char **headers;
struct curl_slist *header_list;
char *memory;
size_t size;
ogs_timer_t *timer;
CURL *easy;
char error[CURL_ERROR_SIZE];
ogs_sbi_client_t *client;
} connection_t;
static OGS_POOL(client_pool, ogs_sbi_client_t);
static OGS_POOL(sockinfo_pool, sockinfo_t);
static OGS_POOL(connection_pool, connection_t);
static size_t write_cb(void *contents, size_t size, size_t nmemb, void *data);
static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp);
static int multi_timer_cb(CURLM *multi, long timeout_ms, void *cbp);
static void multi_timer_expired(void *data);
static void connection_timer_expired(void *data);
static void connection_remove_all(ogs_sbi_client_t *client);
void ogs_sbi_client_init(int num_of_sockinfo_pool, int num_of_connection_pool)
{
curl_global_init(CURL_GLOBAL_DEFAULT);
ogs_list_init(&ogs_sbi_self()->client_list);
ogs_pool_init(&client_pool, ogs_config()->pool.sbi);
ogs_pool_init(&sockinfo_pool, num_of_sockinfo_pool);
ogs_pool_init(&connection_pool, num_of_connection_pool);
}
void ogs_sbi_client_final(void)
{
ogs_sbi_client_remove_all();
ogs_pool_final(&client_pool);
ogs_pool_final(&sockinfo_pool);
ogs_pool_final(&connection_pool);
curl_global_cleanup();
}
ogs_sbi_client_t *ogs_sbi_client_add(ogs_sockaddr_t *addr)
{
ogs_sbi_client_t *client = NULL;
CURLM *multi = NULL;
ogs_assert(addr);
ogs_pool_alloc(&client_pool, &client);
ogs_assert(client);
memset(client, 0, sizeof(ogs_sbi_client_t));
ogs_copyaddrinfo(&client->addr, addr);
ogs_list_init(&client->connection_list);
client->t_curl = ogs_timer_add(
ogs_sbi_self()->timer_mgr, multi_timer_expired, client);
multi = client->multi = curl_multi_init();
ogs_assert(multi);
curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, sock_cb);
curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, client);
curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, multi_timer_cb);
curl_multi_setopt(multi, CURLMOPT_TIMERDATA, client);
ogs_list_add(&ogs_sbi_self()->client_list, client);
return client;
}
ogs_sbi_client_t *ogs_sbi_client_find_or_add(char *url)
{
int rv;
ogs_sbi_client_t *client = NULL;
struct yuarel yuarel;
char *p = ogs_strdup(url);
int port;
ogs_sockaddr_t *addr = NULL;
rv = yuarel_parse(&yuarel, p);
if (rv != OGS_OK) {
ogs_free(p);
ogs_error("yuarel_parse() failed [%s]", url);
return NULL;
}
if (!yuarel.scheme) {
ogs_error("No http.scheme found [%s]", url);
ogs_free(p);
return NULL;
}
if (strcmp(yuarel.scheme, "https") == 0) {
port = OGS_SBI_HTTPS_PORT;
} else if (strcmp(yuarel.scheme, "http") == 0) {
port = OGS_SBI_HTTP_PORT;
} else {
ogs_error("Invalid http.scheme [%s:%s]", yuarel.scheme, url);
ogs_free(p);
return NULL;
}
if (!yuarel.host) {
ogs_error("No http.host found [%s]", url);
ogs_free(p);
return NULL;
}
if (yuarel.port) port = yuarel.port;
rv = ogs_getaddrinfo(&addr, AF_UNSPEC, yuarel.host, port, 0);
if (rv != OGS_OK) {
ogs_error("ogs_getaddrinfo() failed [%s]", url);
ogs_free(p);
}
client = ogs_sbi_client_find(addr);
if (!client) {
client = ogs_sbi_client_add(addr);
ogs_assert(client);
}
ogs_freeaddrinfo(addr);
ogs_free(p);
return client;
}
void ogs_sbi_client_remove(ogs_sbi_client_t *client)
{
ogs_assert(client);
ogs_list_remove(&ogs_sbi_self()->client_list, client);
connection_remove_all(client);
ogs_assert(client->t_curl);
ogs_timer_delete(client->t_curl);
ogs_assert(client->multi);
curl_multi_cleanup(client->multi);
ogs_assert(client->addr);
ogs_freeaddrinfo(client->addr);
ogs_pool_free(&client_pool, client);
}
void ogs_sbi_client_remove_all(void)
{
ogs_sbi_client_t *client = NULL, *next_client = NULL;
ogs_list_for_each_safe(&ogs_sbi_self()->client_list, next_client, client)
ogs_sbi_client_remove(client);
}
ogs_sbi_client_t *ogs_sbi_client_find(ogs_sockaddr_t *addr)
{
ogs_sbi_client_t *client = NULL;
ogs_assert(addr);
ogs_list_for_each(&ogs_sbi_self()->client_list, client) {
if (ogs_sockaddr_is_equal(client->addr, addr) == true)
break;
}
return client;
}
#define mycase(code) \
case code: s = __STRING(code)
static void mcode_or_die(const char *where, CURLMcode code)
{
if(CURLM_OK != code) {
const char *s;
switch(code) {
mycase(CURLM_BAD_HANDLE); break;
mycase(CURLM_BAD_EASY_HANDLE); break;
mycase(CURLM_OUT_OF_MEMORY); break;
mycase(CURLM_INTERNAL_ERROR); break;
mycase(CURLM_UNKNOWN_OPTION); break;
mycase(CURLM_LAST); break;
default: s = "CURLM_unknown"; break;
mycase(CURLM_BAD_SOCKET);
ogs_error("ERROR: %s returns %s", where, s);
/* ignore this error */
return;
}
ogs_fatal("ERROR: %s returns %s", where, s);
ogs_assert_if_reached();
}
}
static char *add_params_to_url(CURL *easy, char *url, ogs_hash_t *params)
{
ogs_hash_index_t *hi;
int has_params = 0;
const char *fp = "?", *np = "&";
ogs_assert(easy);
ogs_assert(url);
ogs_assert(params);
ogs_assert(ogs_hash_count(params));
has_params = (strchr(url, '?') != NULL);
for (hi = ogs_hash_first(params); hi; hi = ogs_hash_next(hi)) {
const char *key = NULL;
char *key_esc = NULL;
char *val = NULL;
char *val_esc = NULL;
key = ogs_hash_this_key(hi);
ogs_assert(key);
val = ogs_hash_this_val(hi);
ogs_assert(val);
key_esc = curl_easy_escape(easy, key, 0);
ogs_assert(key_esc);
val_esc = curl_easy_escape(easy, val, 0);
ogs_assert(val_esc);
if (!has_params) {
url = ogs_mstrcatf(url, "%s%s=%s", fp, key_esc, val_esc);
has_params = 1;
} else {
url = ogs_mstrcatf(url, "%s%s=%s", np, key_esc, val_esc);
}
curl_free(val_esc);
curl_free(key_esc);
}
return url;
}
static connection_t *connection_add(ogs_sbi_client_t *client,
ogs_sbi_request_t *request, void *data)
{
ogs_hash_index_t *hi;
int i;
connection_t *conn = NULL;
CURLMcode rc;
ogs_assert(client);
ogs_assert(request);
ogs_pool_alloc(&connection_pool, &conn);
ogs_assert(conn);
memset(conn, 0, sizeof(connection_t));
ogs_assert(request->h.method);
conn->method = ogs_strdup(request->h.method);
conn->num_of_header = ogs_hash_count(request->http.headers);
if (conn->num_of_header) {
conn->headers = ogs_calloc(conn->num_of_header, sizeof(char *));
ogs_assert(conn->headers);
for (hi = ogs_hash_first(request->http.headers), i = 0;
hi && i < conn->num_of_header; hi = ogs_hash_next(hi), i++) {
const char *key = ogs_hash_this_key(hi);
char *val = ogs_hash_this_val(hi);
conn->headers[i] = ogs_msprintf("%s: %s", key, val);
ogs_assert(conn->headers[i]);
conn->header_list = curl_slist_append(
conn->header_list, conn->headers[i]);
}
}
conn->timer = ogs_timer_add(
ogs_sbi_self()->timer_mgr, connection_timer_expired, conn);
ogs_assert(conn->timer);
/* If http response is not received within 1 second,
* we will discard this request. */
ogs_timer_start(conn->timer, ogs_time_from_sec(1));
conn->easy = curl_easy_init();
ogs_assert(conn->easy);
/* HTTP Method */
if (strcmp(request->h.method, OGS_SBI_HTTP_METHOD_PUT) == 0 ||
strcmp(request->h.method, OGS_SBI_HTTP_METHOD_PATCH) == 0 ||
strcmp(request->h.method, OGS_SBI_HTTP_METHOD_DELETE) == 0 ||
strcmp(request->h.method, OGS_SBI_HTTP_METHOD_POST) == 0) {
curl_easy_setopt(conn->easy, CURLOPT_CUSTOMREQUEST, request->h.method);
if (request->http.content) {
curl_easy_setopt(conn->easy, CURLOPT_HTTPHEADER, conn->header_list);
curl_easy_setopt(conn->easy, CURLOPT_POSTFIELDS,
request->http.content);
}
}
if (ogs_hash_count(request->http.params)) {
request->h.url = add_params_to_url(conn->easy,
request->h.url, request->http.params);
}
curl_easy_setopt(conn->easy, CURLOPT_URL, request->h.url);
curl_easy_setopt(conn->easy, CURLOPT_PRIVATE, conn);
curl_easy_setopt(conn->easy, CURLOPT_WRITEFUNCTION, write_cb);
curl_easy_setopt(conn->easy, CURLOPT_WRITEDATA, conn);
curl_easy_setopt(conn->easy, CURLOPT_ERRORBUFFER, conn->error);
ogs_assert(client->multi);
rc = curl_multi_add_handle(client->multi, conn->easy);
mcode_or_die("connection_add: curl_multi_add_handle", rc);
conn->client = client;
conn->data = data;
ogs_list_add(&client->connection_list, conn);
return conn;
}
static void connection_remove(connection_t *conn)
{
ogs_sbi_client_t *client = NULL;
int i;
ogs_assert(conn);
client = conn->client;
ogs_assert(client);
ogs_list_remove(&client->connection_list, conn);
ogs_assert(conn->timer);
ogs_timer_delete(conn->timer);
ogs_assert(conn->easy);
ogs_assert(client->multi);
curl_multi_remove_handle(client->multi, conn->easy);
curl_easy_cleanup(conn->easy);
ogs_assert(conn->method);
ogs_free(conn->method);
if (conn->num_of_header) {
for (i = 0; i < conn->num_of_header; i++)
ogs_free(conn->headers[i]);
ogs_free(conn->headers);
}
curl_slist_free_all(conn->header_list);
if (conn->memory)
ogs_free(conn->memory);
ogs_pool_free(&connection_pool, conn);
}
static void connection_remove_all(ogs_sbi_client_t *client)
{
connection_t *conn = NULL, *next_conn = NULL;
ogs_assert(client);
ogs_list_for_each_safe(&client->connection_list, next_conn, conn)
connection_remove(conn);
}
static void connection_timer_expired(void *data)
{
connection_t *conn = NULL;
conn = data;
ogs_assert(conn);
connection_remove(conn);
}
static void check_multi_info(ogs_sbi_client_t *client)
{
CURLM *multi = NULL;
CURLMsg *resource;
int pending;
CURL *easy = NULL;
CURLcode res;
connection_t *conn = NULL;
ogs_sbi_response_t *response = NULL;
ogs_assert(client);
multi = client->multi;
ogs_assert(multi);
while ((resource = curl_multi_info_read(multi, &pending))) {
char *url;
char *content_type = NULL;
long res_status;
ogs_assert(resource);
switch (resource->msg) {
case CURLMSG_DONE:
easy = resource->easy_handle;
ogs_assert(easy);
curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn);
ogs_assert(conn);
curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &url);
curl_easy_getinfo(easy, CURLINFO_RESPONSE_CODE, &res_status);
curl_easy_getinfo(easy, CURLINFO_CONTENT_TYPE, &content_type);
res = resource->data.result;
if (res == CURLE_OK) {
response = ogs_sbi_response_new();
ogs_assert(response);
response->status = res_status;
ogs_assert(conn->method);
response->h.method = ogs_strdup(conn->method);
/* remove https://localhost:8000 */
response->h.url = ogs_strdup(url);
response->http.content = ogs_strdup(conn->memory);
response->http.content_length = conn->size;
if (content_type)
ogs_sbi_header_set(response->http.headers,
"Content-Type", content_type);
if (client->cb)
client->cb(response, conn->data);
else {
ogs_fatal("client callback is not registered");
ogs_sbi_response_free(response);
ogs_assert_if_reached();
}
} else
ogs_warn("[%d] %s", res, conn->error);
connection_remove(conn);
break;
default:
ogs_error("Unknown CURL resource[%d]", resource->msg);
break;
}
}
}
void ogs_sbi_client_send_request(
ogs_sbi_client_t *client, ogs_sbi_request_t *request, void *data)
{
connection_t *conn = NULL;
ogs_assert(client);
ogs_assert(request);
if (request->h.url == NULL) {
request->h.url = ogs_sbi_client_uri(client,
request->h.service.name, request->h.api.version,
request->h.resource.name, request->h.resource.id);
}
conn = connection_add(client, request, data);
ogs_assert(conn);
ogs_sbi_request_free(request);
}
static size_t write_cb(void *contents, size_t size, size_t nmemb, void *data)
{
size_t realsize = 0;
connection_t *conn = NULL;
char *ptr = NULL;
conn = data;
ogs_assert(conn);
realsize = size * nmemb;
ptr = ogs_realloc(conn->memory, conn->size + realsize + 1);
if(!ptr) {
ogs_fatal("not enough memory (realloc returned NULL)");
return 0;
}
conn->memory = ptr;
memcpy(&(conn->memory[conn->size]), contents, realsize);
conn->size += realsize;
conn->memory[conn->size] = 0;
return realsize;
}
static void event_cb(short when, ogs_socket_t fd, void *data)
{
sockinfo_t *sockinfo = NULL;
ogs_sbi_client_t *client = NULL;
CURLM *multi = NULL;
CURLMcode rc;
int action = ((when & OGS_POLLIN) ? CURL_CSELECT_IN : 0) |
((when & OGS_POLLOUT) ? CURL_CSELECT_OUT : 0);
sockinfo = data;
ogs_assert(sockinfo);
client = sockinfo->client;
ogs_assert(client);
multi = client->multi;
ogs_assert(multi);
rc = curl_multi_socket_action(multi, fd, action, &client->still_running);
mcode_or_die("event_cb: curl_multi_socket_action", rc);
check_multi_info(client);
if (client->still_running <= 0) {
ogs_timer_t *timer;
timer = client->t_curl;
ogs_assert(timer);
ogs_timer_stop(timer);
}
}
/* Assign information to a sockinfo_t structure */
static void sock_set(sockinfo_t *sockinfo, curl_socket_t s,
CURL *e, int act, ogs_sbi_client_t *client)
{
int kind = ((act & CURL_POLL_IN) ? OGS_POLLIN : 0) |
((act & CURL_POLL_OUT) ? OGS_POLLOUT : 0);
if (sockinfo->sockfd)
ogs_pollset_remove(sockinfo->poll);
sockinfo->sockfd = s;
sockinfo->action = act;
sockinfo->easy = e;
sockinfo->poll = ogs_pollset_add(
ogs_sbi_self()->pollset, kind, s, event_cb, sockinfo);
}
/* Initialize a new sockinfo_t structure */
static void sock_new(curl_socket_t s,
CURL *easy, int action, ogs_sbi_client_t *client)
{
sockinfo_t *sockinfo = NULL;
CURLM *multi = NULL;
ogs_assert(client);
multi = client->multi;
ogs_assert(multi);
ogs_pool_alloc(&sockinfo_pool, &sockinfo);
ogs_assert(sockinfo);
memset(sockinfo, 0, sizeof(sockinfo_t));
sockinfo->client = client;
sock_set(sockinfo, s, easy, action, client);
curl_multi_assign(multi, s, sockinfo);
}
/* Clean up the sockinfo_t structure */
static void sock_free(sockinfo_t *sockinfo, ogs_sbi_client_t *client)
{
ogs_assert(sockinfo);
ogs_assert(sockinfo->poll);
ogs_pollset_remove(sockinfo->poll);
ogs_pool_free(&sockinfo_pool, sockinfo);
}
/* CURLMOPT_SOCKETFUNCTION */
static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp)
{
ogs_sbi_client_t *client = (ogs_sbi_client_t *)cbp;
sockinfo_t *sockinfo = (sockinfo_t *) sockp;
if (what == CURL_POLL_REMOVE) {
sock_free(sockinfo, client);
} else {
if (!sockinfo) {
sock_new(s, e, what, client);
} else {
sock_set(sockinfo, s, e, what, client);
}
}
return 0;
}
static void multi_timer_expired(void *data)
{
CURLMcode rc;
ogs_sbi_client_t *client = NULL;
CURLM *multi = NULL;
client = data;
ogs_assert(client);
multi = client->multi;
ogs_assert(multi);
rc = curl_multi_socket_action(
multi, CURL_SOCKET_TIMEOUT, 0, &client->still_running);
mcode_or_die("multi_timer_expired: curl_multi_socket_action", rc);
check_multi_info(client);
}
static int multi_timer_cb(CURLM *multi, long timeout_ms, void *cbp)
{
ogs_sbi_client_t *client = NULL;
ogs_timer_t *timer = NULL;
client = cbp;
ogs_assert(client);
timer = client->t_curl;
ogs_assert(timer);
if (timeout_ms > 0) {
ogs_timer_start(timer, ogs_time_from_msec(timeout_ms));
} else if (timeout_ms == 0) {
/* libcurl wants us to timeout now.
* The closest we can do is to schedule the timer to fire in 1 us. */
ogs_timer_start(timer, 1);
} else {
ogs_timer_stop(timer);
}
return 0;
}

72
lib/sbi/client.h Normal file
View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#if !defined(OGS_SBI_INSIDE) && !defined(OGS_SBI_COMPILATION)
#error "This header cannot be included directly."
#endif
#ifndef OGS_SBI_CLIENT_H
#define OGS_SBI_CLIENT_H
#ifdef __cplusplus
extern "C" {
#endif
#define OGS_SETUP_SBI_CLIENT(__cTX, __pCLIENT) \
do { \
ogs_assert((__cTX)); \
ogs_assert((__pCLIENT)); \
(__cTX)->client = __pCLIENT; \
} while(0)
typedef struct ogs_sbi_client_s {
ogs_lnode_t lnode;
ogs_sockaddr_t *addr;
struct {
const char *key;
const char *pem;
} tls;
int (*cb)(ogs_sbi_response_t *response, void *data);
ogs_timer_t *t_curl; /* timer for CURL */
ogs_list_t connection_list; /* CURL connection list */
void *multi; /* CURL multi handle */
int still_running; /* number of running CURL handle */
} ogs_sbi_client_t;
void ogs_sbi_client_init(int num_of_sockinfo_pool, int num_of_connection_pool);
void ogs_sbi_client_final(void);
ogs_sbi_client_t *ogs_sbi_client_add(ogs_sockaddr_t *addr);
ogs_sbi_client_t *ogs_sbi_client_find_or_add(char *uri);
void ogs_sbi_client_remove(ogs_sbi_client_t *client);
void ogs_sbi_client_remove_all(void);
ogs_sbi_client_t *ogs_sbi_client_find(ogs_sockaddr_t *addr);
void ogs_sbi_client_send_request(
ogs_sbi_client_t *client, ogs_sbi_request_t *request, void *data);
#ifdef __cplusplus
}
#endif
#endif /* OGS_SBI_CLIENT_H */

903
lib/sbi/context.c Normal file
View File

@ -0,0 +1,903 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "app/ogs-app.h"
#include "ogs-sbi.h"
int __ogs_sbi_domain;
static OGS_POOL(nf_instance_pool, ogs_sbi_nf_instance_t);
static OGS_POOL(nf_service_pool, ogs_sbi_nf_service_t);
static OGS_POOL(subscription_pool, ogs_sbi_subscription_t);
static ogs_sbi_context_t self;
static int context_initialized = 0;
void ogs_sbi_context_init(ogs_pollset_t *pollset, ogs_timer_mgr_t *timer_mgr)
{
ogs_assert(context_initialized == 0);
/* Initialize SMF context */
memset(&self, 0, sizeof(ogs_sbi_context_t));
ogs_assert(pollset);
self.pollset = pollset;
ogs_assert(timer_mgr);
self.timer_mgr = timer_mgr;
ogs_log_install_domain(&__ogs_sbi_domain, "sbi", ogs_core()->log.level);
/* FIXME : number of pool size */
ogs_sbi_message_init(32, 32);
ogs_sbi_server_init(32);
ogs_sbi_client_init(512, 512);
ogs_list_init(&self.nf_instance_list);
ogs_pool_init(&nf_instance_pool, ogs_config()->pool.sbi);
ogs_pool_init(&nf_service_pool, ogs_config()->pool.sbi);
ogs_list_init(&self.subscription_list);
ogs_pool_init(&subscription_pool, ogs_config()->pool.sbi);
ogs_uuid_get(&self.uuid);
ogs_uuid_format(self.nf_instance_id, &self.uuid);
context_initialized = 1;
}
void ogs_sbi_context_final(void)
{
ogs_assert(context_initialized == 1);
ogs_sbi_subscription_remove_all();
ogs_pool_final(&subscription_pool);
ogs_sbi_nf_instance_remove_all();
ogs_pool_final(&nf_instance_pool);
ogs_pool_final(&nf_service_pool);
ogs_sbi_client_final();
ogs_sbi_server_final();
ogs_sbi_message_final();
context_initialized = 0;
}
ogs_sbi_context_t *ogs_sbi_self(void)
{
return &self;
}
static int ogs_sbi_context_prepare(void)
{
self.http_port = OGS_SBI_HTTP_PORT;
self.https_port = OGS_SBI_HTTPS_PORT;
self.content_encoding = "gzip";
return OGS_OK;
}
static int ogs_sbi_context_validation(const char *local)
{
if (ogs_list_first(&self.server_list) == NULL) {
ogs_error("No %s.sbi: in '%s'", local, ogs_config()->file);
return OGS_ERROR;
}
return OGS_OK;
}
int ogs_sbi_context_parse_config(const char *local, const char *remote)
{
int rv;
yaml_document_t *document = NULL;
ogs_yaml_iter_t root_iter;
document = ogs_config()->document;
ogs_assert(document);
rv = ogs_sbi_context_prepare();
if (rv != OGS_OK) return rv;
ogs_yaml_iter_init(&root_iter, document);
while (ogs_yaml_iter_next(&root_iter)) {
const char *root_key = ogs_yaml_iter_key(&root_iter);
ogs_assert(root_key);
if (local && !strcmp(root_key, local)) {
ogs_yaml_iter_t local_iter;
ogs_yaml_iter_recurse(&root_iter, &local_iter);
while (ogs_yaml_iter_next(&local_iter)) {
const char *local_key = ogs_yaml_iter_key(&local_iter);
ogs_assert(local_key);
if (!strcmp(local_key, "sbi")) {
ogs_list_t list, list6;
ogs_socknode_t *node = NULL, *node6 = NULL;
ogs_yaml_iter_t sbi_array, sbi_iter;
ogs_yaml_iter_recurse(&local_iter, &sbi_array);
do {
int family = AF_UNSPEC;
int i, num = 0;
const char *hostname[OGS_MAX_NUM_OF_HOSTNAME];
uint16_t port = self.http_port;
const char *dev = NULL;
ogs_sockaddr_t *addr = NULL;
const char *key = NULL;
const char *pem = NULL;
if (ogs_yaml_iter_type(&sbi_array) ==
YAML_MAPPING_NODE) {
memcpy(&sbi_iter, &sbi_array,
sizeof(ogs_yaml_iter_t));
} else if (ogs_yaml_iter_type(&sbi_array) ==
YAML_SEQUENCE_NODE) {
if (!ogs_yaml_iter_next(&sbi_array))
break;
ogs_yaml_iter_recurse(&sbi_array, &sbi_iter);
} else if (ogs_yaml_iter_type(&sbi_array) ==
YAML_SCALAR_NODE) {
break;
} else
ogs_assert_if_reached();
while (ogs_yaml_iter_next(&sbi_iter)) {
const char *sbi_key =
ogs_yaml_iter_key(&sbi_iter);
ogs_assert(sbi_key);
if (!strcmp(sbi_key, "family")) {
const char *v = ogs_yaml_iter_value(&sbi_iter);
if (v) family = atoi(v);
if (family != AF_UNSPEC &&
family != AF_INET && family != AF_INET6) {
ogs_warn("Ignore family(%d) : "
"AF_UNSPEC(%d), "
"AF_INET(%d), AF_INET6(%d) ",
family, AF_UNSPEC, AF_INET, AF_INET6);
family = AF_UNSPEC;
}
} else if (!strcmp(sbi_key, "addr") ||
!strcmp(sbi_key, "name")) {
ogs_yaml_iter_t hostname_iter;
ogs_yaml_iter_recurse(&sbi_iter,
&hostname_iter);
ogs_assert(ogs_yaml_iter_type(&hostname_iter) !=
YAML_MAPPING_NODE);
do {
if (ogs_yaml_iter_type(&hostname_iter) ==
YAML_SEQUENCE_NODE) {
if (!ogs_yaml_iter_next(
&hostname_iter))
break;
}
ogs_assert(num <= OGS_MAX_NUM_OF_HOSTNAME);
hostname[num++] =
ogs_yaml_iter_value(&hostname_iter);
} while (
ogs_yaml_iter_type(&hostname_iter) ==
YAML_SEQUENCE_NODE);
} else if (!strcmp(sbi_key, "port")) {
const char *v = ogs_yaml_iter_value(&sbi_iter);
if (v) {
port = atoi(v);
self.http_port = port;
}
} else if (!strcmp(sbi_key, "dev")) {
dev = ogs_yaml_iter_value(&sbi_iter);
} else if (!strcmp(sbi_key, "tls")) {
ogs_yaml_iter_t tls_iter;
ogs_yaml_iter_recurse(&sbi_iter, &tls_iter);
while (ogs_yaml_iter_next(&tls_iter)) {
const char *tls_key =
ogs_yaml_iter_key(&tls_iter);
ogs_assert(tls_key);
if (!strcmp(tls_key, "key")) {
key = ogs_yaml_iter_value(&tls_iter);
} else if (!strcmp(tls_key, "pem")) {
pem = ogs_yaml_iter_value(&tls_iter);
} else
ogs_warn("unknown key `%s`", tls_key);
}
} else
ogs_warn("unknown key `%s`", sbi_key);
}
addr = NULL;
for (i = 0; i < num; i++) {
rv = ogs_addaddrinfo(&addr,
family, hostname[i], port, 0);
ogs_assert(rv == OGS_OK);
}
ogs_list_init(&list);
ogs_list_init(&list6);
if (addr) {
if (ogs_config()->parameter.no_ipv4 == 0)
ogs_socknode_add(&list, AF_INET, addr);
if (ogs_config()->parameter.no_ipv6 == 0)
ogs_socknode_add(&list6, AF_INET6, addr);
ogs_freeaddrinfo(addr);
}
if (dev) {
rv = ogs_socknode_probe(
ogs_config()->parameter.no_ipv4 ? NULL : &list,
ogs_config()->parameter.no_ipv6 ? NULL : &list6,
dev, port);
ogs_assert(rv == OGS_OK);
}
node = ogs_list_first(&list);
if (node) {
ogs_sbi_server_t *server =
ogs_sbi_server_add(node->addr);
ogs_assert(server);
if (key) server->tls.key = key;
if (pem) server->tls.pem = pem;
}
node6 = ogs_list_first(&list6);
if (node6) {
ogs_sbi_server_t *server =
ogs_sbi_server_add(node6->addr);
ogs_assert(server);
if (key) server->tls.key = key;
if (pem) server->tls.pem = pem;
}
ogs_socknode_remove_all(&list);
ogs_socknode_remove_all(&list6);
} while (ogs_yaml_iter_type(&sbi_array) ==
YAML_SEQUENCE_NODE);
if (ogs_list_first(&self.server_list) == 0) {
ogs_list_init(&list);
ogs_list_init(&list6);
rv = ogs_socknode_probe(
ogs_config()->parameter.no_ipv4 ? NULL : &list,
ogs_config()->parameter.no_ipv6 ? NULL : &list6,
NULL, self.http_port);
ogs_assert(rv == OGS_OK);
node = ogs_list_first(&list);
if (node) ogs_sbi_server_add(node->addr);
node6 = ogs_list_first(&list6);
if (node6) ogs_sbi_server_add(node6->addr);
ogs_socknode_remove_all(&list);
ogs_socknode_remove_all(&list6);
}
}
}
} else if (remote && !strcmp(root_key, remote)) {
ogs_yaml_iter_t remote_iter;
ogs_yaml_iter_recurse(&root_iter, &remote_iter);
while (ogs_yaml_iter_next(&remote_iter)) {
const char *remote_key = ogs_yaml_iter_key(&remote_iter);
ogs_assert(remote_key);
if (!strcmp(remote_key, "sbi")) {
ogs_yaml_iter_t sbi_array, sbi_iter;
ogs_yaml_iter_recurse(&remote_iter, &sbi_array);
do {
ogs_sbi_client_t *client = NULL;
ogs_sockaddr_t *addr = NULL;
int family = AF_UNSPEC;
int i, num = 0;
const char *hostname[OGS_MAX_NUM_OF_HOSTNAME];
uint16_t port = self.http_port;
const char *key = NULL;
const char *pem = NULL;
if (ogs_yaml_iter_type(&sbi_array) ==
YAML_MAPPING_NODE) {
memcpy(&sbi_iter, &sbi_array,
sizeof(ogs_yaml_iter_t));
} else if (ogs_yaml_iter_type(&sbi_array) ==
YAML_SEQUENCE_NODE) {
if (!ogs_yaml_iter_next(&sbi_array))
break;
ogs_yaml_iter_recurse(&sbi_array, &sbi_iter);
} else if (ogs_yaml_iter_type(&sbi_array) ==
YAML_SCALAR_NODE) {
break;
} else
ogs_assert_if_reached();
while (ogs_yaml_iter_next(&sbi_iter)) {
const char *sbi_key =
ogs_yaml_iter_key(&sbi_iter);
ogs_assert(sbi_key);
if (!strcmp(sbi_key, "family")) {
const char *v = ogs_yaml_iter_value(&sbi_iter);
if (v) family = atoi(v);
if (family != AF_UNSPEC &&
family != AF_INET && family != AF_INET6) {
ogs_warn("Ignore family(%d) : "
"AF_UNSPEC(%d), "
"AF_INET(%d), AF_INET6(%d) ",
family, AF_UNSPEC, AF_INET, AF_INET6);
family = AF_UNSPEC;
}
} else if (!strcmp(sbi_key, "addr") ||
!strcmp(sbi_key, "name")) {
ogs_yaml_iter_t hostname_iter;
ogs_yaml_iter_recurse(&sbi_iter,
&hostname_iter);
ogs_assert(ogs_yaml_iter_type(&hostname_iter) !=
YAML_MAPPING_NODE);
do {
if (ogs_yaml_iter_type(&hostname_iter) ==
YAML_SEQUENCE_NODE) {
if (!ogs_yaml_iter_next(&hostname_iter))
break;
}
ogs_assert(num <= OGS_MAX_NUM_OF_HOSTNAME);
hostname[num++] =
ogs_yaml_iter_value(&hostname_iter);
} while (
ogs_yaml_iter_type(&hostname_iter) ==
YAML_SEQUENCE_NODE);
} else if (!strcmp(sbi_key, "port")) {
const char *v = ogs_yaml_iter_value(&sbi_iter);
if (v) port = atoi(v);
} else if (!strcmp(sbi_key, "tls")) {
ogs_yaml_iter_t tls_iter;
ogs_yaml_iter_recurse(&sbi_iter, &tls_iter);
while (ogs_yaml_iter_next(&tls_iter)) {
const char *tls_key =
ogs_yaml_iter_key(&tls_iter);
ogs_assert(tls_key);
if (!strcmp(tls_key, "key")) {
key = ogs_yaml_iter_value(&tls_iter);
} else if (!strcmp(tls_key, "pem")) {
pem = ogs_yaml_iter_value(&tls_iter);
} else
ogs_warn("unknown key `%s`", tls_key);
}
} else
ogs_warn("unknown key `%s`", sbi_key);
}
addr = NULL;
for (i = 0; i < num; i++) {
rv = ogs_addaddrinfo(&addr,
family, hostname[i], port, 0);
ogs_assert(rv == OGS_OK);
}
ogs_filter_ip_version(&addr,
ogs_config()->parameter.no_ipv4,
ogs_config()->parameter.no_ipv6,
ogs_config()->parameter.prefer_ipv4);
client = ogs_sbi_client_add(addr);
ogs_assert(client);
if (key) client->tls.key = key;
if (pem) client->tls.pem = pem;
ogs_freeaddrinfo(addr);
} while (ogs_yaml_iter_type(&sbi_array) ==
YAML_SEQUENCE_NODE);
}
}
}
}
rv = ogs_sbi_context_validation(local);
if (rv != OGS_OK) return rv;
return OGS_OK;
}
ogs_sbi_nf_instance_t *ogs_sbi_nf_instance_add(char *id)
{
ogs_sbi_nf_instance_t *nf_instance = NULL;
ogs_assert(id);
ogs_pool_alloc(&nf_instance_pool, &nf_instance);
ogs_assert(nf_instance);
memset(nf_instance, 0, sizeof(ogs_sbi_nf_instance_t));
nf_instance->id = ogs_strdup(id);
ogs_assert(nf_instance->id);
nf_instance->time.heartbeat = ogs_config()->time.nf_instance.heartbeat;
ogs_list_add(&ogs_sbi_self()->nf_instance_list, nf_instance);
return nf_instance;
}
void ogs_sbi_nf_instance_clear(ogs_sbi_nf_instance_t *nf_instance)
{
int i;
ogs_assert(nf_instance);
for (i = 0; i < nf_instance->num_of_ipv4; i++) {
if (nf_instance->ipv4[i])
ogs_freeaddrinfo(nf_instance->ipv4[i]);
}
for (i = 0; i < nf_instance->num_of_ipv6; i++) {
if (nf_instance->ipv6[i])
ogs_freeaddrinfo(nf_instance->ipv6[i]);
}
ogs_sbi_nf_service_remove_all(nf_instance);
}
void ogs_sbi_nf_instance_remove(ogs_sbi_nf_instance_t *nf_instance)
{
ogs_assert(nf_instance);
ogs_list_remove(&ogs_sbi_self()->nf_instance_list, nf_instance);
ogs_sbi_subscription_remove_all_by_nf_instance_id(nf_instance->id);
ogs_assert(nf_instance->id);
ogs_free(nf_instance->id);
ogs_sbi_nf_instance_clear(nf_instance);
ogs_pool_free(&nf_instance_pool, nf_instance);
}
void ogs_sbi_nf_instance_remove_all(void)
{
ogs_sbi_nf_instance_t *nf_instance = NULL, *next_nf_instance = NULL;
ogs_list_for_each_safe(
&ogs_sbi_self()->nf_instance_list, next_nf_instance, nf_instance)
ogs_sbi_nf_instance_remove(nf_instance);
}
ogs_sbi_nf_instance_t *ogs_sbi_nf_instance_find(char *id)
{
ogs_sbi_nf_instance_t *nf_instance = NULL;
ogs_assert(id);
ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) {
ogs_assert(nf_instance->id);
if (strcmp(nf_instance->id, id) == 0)
break;
}
return nf_instance;
}
ogs_sbi_nf_instance_t *ogs_sbi_nf_instance_build_default(
OpenAPI_nf_type_e nf_type, ogs_sbi_client_t *client)
{
ogs_sbi_server_t *server = NULL;
ogs_sbi_nf_instance_t *nf_instance = NULL;
char *hostname = NULL;
nf_instance = ogs_sbi_nf_instance_add(ogs_sbi_self()->nf_instance_id);
ogs_assert(nf_instance);
nf_instance->nf_type = nf_type;
nf_instance->nf_status = OpenAPI_nf_status_REGISTERED;
OGS_SETUP_SBI_CLIENT(nf_instance, client);
hostname = NULL;
ogs_list_for_each(&ogs_sbi_self()->server_list, server) {
ogs_assert(server->addr);
/* First FQDN is selected */
if (!hostname) {
hostname = ogs_gethostname(server->addr);
if (hostname)
continue;
}
if (nf_instance->num_of_ipv4 < OGS_SBI_MAX_NUM_OF_IP_ADDRESS) {
ogs_sockaddr_t *addr = NULL;
ogs_copyaddrinfo(&addr, server->addr);
ogs_assert(addr);
if (addr->ogs_sa_family == AF_INET) {
nf_instance->ipv4[nf_instance->num_of_ipv4] = addr;
nf_instance->num_of_ipv4++;
} else if (addr->ogs_sa_family == AF_INET6) {
nf_instance->ipv6[nf_instance->num_of_ipv6] = addr;
nf_instance->num_of_ipv6++;
} else
ogs_assert_if_reached();
}
}
if (hostname)
strcpy(nf_instance->fqdn, hostname);
return nf_instance;
}
ogs_sbi_nf_service_t *ogs_sbi_nf_service_add(ogs_sbi_nf_instance_t *nf_instance,
char *id, char *name, OpenAPI_uri_scheme_e scheme)
{
ogs_sbi_nf_service_t *nf_service = NULL;
ogs_assert(nf_instance);
ogs_assert(id);
ogs_assert(name);
ogs_pool_alloc(&nf_service_pool, &nf_service);
ogs_assert(nf_service);
memset(nf_service, 0, sizeof(ogs_sbi_nf_service_t));
nf_service->id = ogs_strdup(id);
ogs_assert(nf_service->id);
nf_service->name = ogs_strdup(name);
ogs_assert(nf_service->name);
nf_service->scheme = scheme;
nf_service->status = OpenAPI_nf_service_status_REGISTERED;
nf_service->nf_instance = nf_instance;
ogs_list_add(&nf_instance->nf_service_list, nf_service);
return nf_service;
}
void ogs_sbi_nf_service_add_version(ogs_sbi_nf_service_t *nf_service,
char *in_uri, char *full, char *expiry)
{
ogs_assert(nf_service);
ogs_assert(in_uri);
ogs_assert(full);
if (nf_service->num_of_version < OGS_SBI_MAX_NUM_OF_SERVICE_VERSION) {
nf_service->versions[nf_service->num_of_version].in_uri =
ogs_strdup(in_uri);
nf_service->versions[nf_service->num_of_version].full =
ogs_strdup(full);
if (expiry)
nf_service->versions[nf_service->num_of_version].expiry =
ogs_strdup(expiry);
nf_service->num_of_version++;
}
}
void ogs_sbi_nf_service_remove(ogs_sbi_nf_instance_t *nf_instance,
ogs_sbi_nf_service_t *nf_service)
{
int i;
ogs_assert(nf_instance);
ogs_assert(nf_service);
ogs_list_remove(&nf_instance->nf_service_list, nf_service);
ogs_assert(nf_service->id);
ogs_free(nf_service->id);
ogs_assert(nf_service->name);
ogs_free(nf_service->name);
for (i = 0; i < nf_service->num_of_version; i++) {
if (nf_service->versions[i].in_uri)
ogs_free(nf_service->versions[i].in_uri);
if (nf_service->versions[i].full)
ogs_free(nf_service->versions[i].full);
if (nf_service->versions[i].expiry)
ogs_free(nf_service->versions[i].expiry);
}
for (i = 0; i < nf_service->num_of_addr; i++) {
if (nf_service->addr[i].ipv4)
ogs_freeaddrinfo(nf_service->addr[i].ipv4);
if (nf_service->addr[i].ipv6)
ogs_freeaddrinfo(nf_service->addr[i].ipv6);
}
ogs_pool_free(&nf_service_pool, nf_service);
}
void ogs_sbi_nf_service_remove_all(ogs_sbi_nf_instance_t *nf_instance)
{
ogs_sbi_nf_service_t *nf_service = NULL, *next_nf_service = NULL;
ogs_assert(nf_instance);
ogs_list_for_each_safe(&nf_instance->nf_service_list,
next_nf_service, nf_service)
ogs_sbi_nf_service_remove(nf_instance, nf_service);
}
ogs_sbi_nf_service_t *ogs_sbi_nf_service_find(
ogs_sbi_nf_instance_t *nf_instance, char *name)
{
ogs_sbi_nf_service_t *nf_service = NULL;
ogs_assert(nf_instance);
ogs_assert(name);
ogs_list_for_each(&nf_instance->nf_service_list, nf_service) {
ogs_assert(nf_service->name);
if (strcmp(nf_service->name, name) == 0)
break;
}
return nf_service;
}
ogs_sbi_nf_service_t *ogs_sbi_nf_service_build_default(
ogs_sbi_nf_instance_t *nf_instance,
char *name, ogs_sbi_client_t *client)
{
ogs_sbi_server_t *server = NULL;
ogs_sbi_nf_service_t *nf_service = NULL;
ogs_uuid_t uuid;
char id[OGS_UUID_FORMATTED_LENGTH + 1];
char *hostname = NULL;
ogs_assert(nf_instance);
ogs_assert(name);
ogs_assert(client);
ogs_uuid_get(&uuid);
ogs_uuid_format(id, &uuid);
nf_service = ogs_sbi_nf_service_add(nf_instance, id, name,
(client->tls.key && client->tls.pem) ?
OpenAPI_uri_scheme_https : OpenAPI_uri_scheme_http);
ogs_assert(nf_service);
OGS_SETUP_SBI_CLIENT(nf_service, client);
hostname = NULL;
ogs_list_for_each(&ogs_sbi_self()->server_list, server) {
ogs_assert(server->addr);
/* First FQDN is selected */
if (!hostname) {
hostname = ogs_gethostname(server->addr);
if (hostname)
continue;
}
if (nf_service->num_of_addr < OGS_SBI_MAX_NUM_OF_IP_ADDRESS) {
int port = 0;
ogs_sockaddr_t *addr = NULL;
ogs_copyaddrinfo(&addr, server->addr);
ogs_assert(addr);
port = OGS_PORT(addr);
if (nf_service->scheme == OpenAPI_uri_scheme_https) {
if (port == OGS_SBI_HTTPS_PORT) port = 0;
} else if (nf_service->scheme == OpenAPI_uri_scheme_http) {
if (port == OGS_SBI_HTTP_PORT) port = 0;
}
nf_service->addr[nf_service->num_of_addr].port = port;
if (addr->ogs_sa_family == AF_INET) {
nf_service->addr[nf_service->num_of_addr].ipv4 = addr;
} else if (addr->ogs_sa_family == AF_INET6) {
nf_service->addr[nf_service->num_of_addr].ipv6 = addr;
} else
ogs_assert_if_reached();
nf_service->num_of_addr++;
}
}
if (hostname)
strcpy(nf_service->fqdn, hostname);
return nf_service;
}
static ogs_sbi_client_t *find_client_by_fqdn(char *fqdn, int port)
{
int rv;
ogs_sockaddr_t *addr = NULL;
ogs_sbi_client_t *client = NULL;
rv = ogs_getaddrinfo(&addr, AF_UNSPEC, fqdn,
port ? port : OGS_SBI_HTTPS_PORT, 0);
if (rv != OGS_OK) {
ogs_error("Invalid NFProfile.fqdn");
return NULL;
}
client = ogs_sbi_client_find(addr);
if (!client) {
client = ogs_sbi_client_add(addr);
ogs_assert(client);
}
ogs_freeaddrinfo(addr);
return client;
}
ogs_sbi_client_t *ogs_sbi_nf_instance_find_client(
ogs_sbi_nf_instance_t *nf_instance)
{
ogs_sbi_client_t *client = NULL;
ogs_sockaddr_t *addr = NULL;
if (strlen(nf_instance->fqdn))
client = find_client_by_fqdn(nf_instance->fqdn, 0);
if (!client) {
/* At this point, CLIENT selection method is very simple. */
if (nf_instance->num_of_ipv4) addr = nf_instance->ipv4[0];
if (nf_instance->num_of_ipv6) addr = nf_instance->ipv6[0];
if (addr) {
client = ogs_sbi_client_find(addr);
if (!client) {
client = ogs_sbi_client_add(addr);
ogs_assert(client);
}
}
}
ogs_sbi_nf_service_find_client_all(nf_instance);
return client;
}
ogs_sbi_client_t *ogs_sbi_nf_service_find_client(
ogs_sbi_nf_service_t *nf_service)
{
ogs_sbi_client_t *client = NULL;
ogs_sockaddr_t *addr = NULL;
if (strlen(nf_service->fqdn))
client = find_client_by_fqdn(nf_service->fqdn, 0);
if (!client) {
/* At this point, CLIENT selection method is very simple. */
if (nf_service->num_of_addr) {
addr = nf_service->addr[0].ipv6;
if (!addr)
addr = nf_service->addr[0].ipv4;
}
if (addr) {
client = ogs_sbi_client_find(addr);
if (!client) {
client = ogs_sbi_client_add(addr);
ogs_assert(client);
}
}
}
if (!client) {
ogs_sbi_nf_instance_t *nf_instance = NULL;
nf_instance = nf_service->nf_instance;
ogs_assert(nf_instance);
client = nf_instance->client;
}
return client;
}
void ogs_sbi_nf_service_find_client_all(ogs_sbi_nf_instance_t *nf_instance)
{
ogs_sbi_nf_service_t *nf_service = NULL;
ogs_assert(nf_instance);
ogs_list_for_each(&nf_instance->nf_service_list, nf_service)
ogs_sbi_nf_service_find_client(nf_service);
}
ogs_sbi_subscription_t *ogs_sbi_subscription_add(void)
{
ogs_sbi_subscription_t *subscription = NULL;
ogs_pool_alloc(&subscription_pool, &subscription);
ogs_assert(subscription);
memset(subscription, 0, sizeof(ogs_sbi_subscription_t));
subscription->time.validity = ogs_config()->time.subscription.validity;
ogs_list_add(&ogs_sbi_self()->subscription_list, subscription);
return subscription;
}
void ogs_sbi_subscription_set_id(ogs_sbi_subscription_t *subscription, char *id)
{
ogs_assert(subscription);
ogs_assert(id);
subscription->id = ogs_strdup(id);
ogs_assert(subscription->id);
}
void ogs_sbi_subscription_remove(ogs_sbi_subscription_t *subscription)
{
ogs_assert(subscription);
ogs_list_remove(&ogs_sbi_self()->subscription_list, subscription);
if (subscription->id)
ogs_free(subscription->id);
if (subscription->notification_uri)
ogs_free(subscription->notification_uri);
if (subscription->nf_instance_id)
ogs_free(subscription->nf_instance_id);
if (subscription->t_validity)
ogs_timer_delete(subscription->t_validity);
ogs_pool_free(&subscription_pool, subscription);
}
void ogs_sbi_subscription_remove_all_by_nf_instance_id(char *nf_instance_id)
{
ogs_sbi_subscription_t *subscription = NULL, *next_subscription = NULL;
ogs_assert(nf_instance_id);
ogs_list_for_each_safe(&ogs_sbi_self()->subscription_list,
next_subscription, subscription) {
if (subscription->nf_instance_id &&
strcmp(subscription->nf_instance_id, nf_instance_id) == 0) {
ogs_sbi_subscription_remove(subscription);
}
}
}
void ogs_sbi_subscription_remove_all(void)
{
ogs_sbi_subscription_t *subscription = NULL, *next_subscription = NULL;
ogs_list_for_each_safe(&ogs_sbi_self()->subscription_list,
next_subscription, subscription)
ogs_sbi_subscription_remove(subscription);
}
ogs_sbi_subscription_t *ogs_sbi_subscription_find(char *id)
{
ogs_sbi_subscription_t *subscription = NULL;
ogs_assert(id);
ogs_list_for_each(&ogs_sbi_self()->subscription_list, subscription) {
ogs_assert(subscription->id);
if (strcmp(subscription->id, id) == 0)
break;
}
return subscription;
}

183
lib/sbi/context.h Normal file
View File

@ -0,0 +1,183 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#if !defined(OGS_SBI_INSIDE) && !defined(OGS_SBI_COMPILATION)
#error "This header cannot be included directly."
#endif
#ifndef OGS_SBI_CONTEXT_H
#define OGS_SBI_CONTEXT_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ogs_sbi_client_s ogs_sbi_client_t;
typedef struct ogs_sbi_context_s {
ogs_pollset_t *pollset; /* Poll Set for I/O Multiplexing */
ogs_timer_mgr_t *timer_mgr; /* Timer Manager */
uint32_t http_port; /* SBI HTTP local port */
uint32_t https_port; /* SBI HTTPS local port */
ogs_list_t server_list;
ogs_list_t client_list;
ogs_uuid_t uuid;
char nf_instance_id[OGS_UUID_FORMATTED_LENGTH + 1];
ogs_list_t nf_instance_list;
ogs_list_t subscription_list;
const char *content_encoding;
} ogs_sbi_context_t;
typedef struct ogs_sbi_nf_instance_s {
ogs_lnode_t lnode;
ogs_fsm_t sm; /* A state machine */
ogs_timer_t *t_registration_interval; /* timer to retry
to register peer node */
#define OGS_SBI_HEARTBEAT_RETRYCOUNT 4
struct {
int heartbeat;
int validity;
} time;
ogs_timer_t *t_heartbeat_interval; /* heartbeat interval */
ogs_timer_t *t_heartbeat; /* check heartbeat */
ogs_timer_t *t_validity; /* check validation */
#define NF_INSTANCE_IS_SELF(_iD) \
strcmp((_iD), ogs_sbi_self()->nf_instance_id) == 0
#define NF_INSTANCE_IS_OTHERS(_iD) \
strcmp((_iD), ogs_sbi_self()->nf_instance_id) != 0
char *id; /* NFInstanceId */
OpenAPI_nf_type_e nf_type;
OpenAPI_nf_status_e nf_status;
char fqdn[OGS_MAX_FQDN_LEN];
#define OGS_SBI_MAX_NUM_OF_IP_ADDRESS 8
int num_of_ipv4;
ogs_sockaddr_t *ipv4[OGS_SBI_MAX_NUM_OF_IP_ADDRESS];
int num_of_ipv6;
ogs_sockaddr_t *ipv6[OGS_SBI_MAX_NUM_OF_IP_ADDRESS];
ogs_list_t nf_service_list;
void *client; /* only used in CLIENT */
} ogs_sbi_nf_instance_t;
typedef struct ogs_sbi_nf_service_s {
ogs_lnode_t lnode;
char *id;
char *name;
OpenAPI_uri_scheme_e scheme;
OpenAPI_nf_service_status_e status;
#define OGS_SBI_MAX_NUM_OF_SERVICE_VERSION 8
int num_of_version;
struct {
char *in_uri;
char *full;
char *expiry;
} versions[OGS_SBI_MAX_NUM_OF_SERVICE_VERSION];
char fqdn[OGS_MAX_FQDN_LEN];
int num_of_addr;
struct {
ogs_sockaddr_t *ipv4;
ogs_sockaddr_t *ipv6;
int port;
} addr[OGS_SBI_MAX_NUM_OF_IP_ADDRESS];
/* Related Context */
ogs_sbi_nf_instance_t *nf_instance;
void *client;
} ogs_sbi_nf_service_t;
typedef struct ogs_sbi_subscription_s {
ogs_lnode_t lnode;
struct {
int validity;
} time;
ogs_timer_t *t_validity; /* check validation */
char *id; /* SubscriptionId */
char *nf_instance_id; /* NFInstanceId */
OpenAPI_nf_type_e nf_type;
OpenAPI_nf_status_e nf_status;
char *notification_uri;
void *client; /* only used in SERVER */
} ogs_sbi_subscription_t;
void ogs_sbi_context_init(ogs_pollset_t *pollset, ogs_timer_mgr_t *timer_mgr);
void ogs_sbi_context_final(void);
ogs_sbi_context_t *ogs_sbi_self(void);
int ogs_sbi_context_parse_config(const char *local, const char *remote);
ogs_sbi_nf_instance_t *ogs_sbi_nf_instance_add(char *id);
void ogs_sbi_nf_instance_clear(ogs_sbi_nf_instance_t *nf_instance);
void ogs_sbi_nf_instance_remove(ogs_sbi_nf_instance_t *nf_instance);
void ogs_sbi_nf_instance_remove_all(void);
ogs_sbi_nf_instance_t *ogs_sbi_nf_instance_find(char *id);
ogs_sbi_nf_instance_t *ogs_sbi_nf_instance_build_default(
OpenAPI_nf_type_e nf_type, ogs_sbi_client_t *client);
ogs_sbi_nf_service_t *ogs_sbi_nf_service_add(ogs_sbi_nf_instance_t *nf_instance,
char *id, char *name, OpenAPI_uri_scheme_e scheme);
void ogs_sbi_nf_service_add_version(ogs_sbi_nf_service_t *nf_service,
char *in_uri, char *full, char *expiry);
void ogs_sbi_nf_service_remove(ogs_sbi_nf_instance_t *nf_instance,
ogs_sbi_nf_service_t *nf_service);
void ogs_sbi_nf_service_remove_all(ogs_sbi_nf_instance_t *nf_instance);
ogs_sbi_nf_service_t *ogs_sbi_nf_service_find(
ogs_sbi_nf_instance_t *nf_instance, char *name);
ogs_sbi_nf_service_t *ogs_sbi_nf_service_build_default(
ogs_sbi_nf_instance_t *nf_instance,
char *name, ogs_sbi_client_t *client);
ogs_sbi_client_t *ogs_sbi_nf_instance_find_client(
ogs_sbi_nf_instance_t *nf_instance);
ogs_sbi_client_t *ogs_sbi_nf_service_find_client(
ogs_sbi_nf_service_t *nf_service);
void ogs_sbi_nf_service_find_client_all(ogs_sbi_nf_instance_t *nf_instance);
ogs_sbi_subscription_t *ogs_sbi_subscription_add(void);
void ogs_sbi_subscription_set_id(
ogs_sbi_subscription_t *subscription, char *id);
void ogs_sbi_subscription_remove(ogs_sbi_subscription_t *subscription);
void ogs_sbi_subscription_remove_all_by_nf_instance_id(char *nf_instance_id);
void ogs_sbi_subscription_remove_all(void);
ogs_sbi_subscription_t *ogs_sbi_subscription_find(char *id);
#ifdef __cplusplus
}
#endif
#endif /* OGS_SBI_CONTEXT_H */

192
lib/sbi/conv.c Normal file
View File

@ -0,0 +1,192 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "ogs-sbi.h"
#include "sbi-private.h"
static char *ogs_uridup(bool https, ogs_sockaddr_t *addr,
const char *service_name, const char *api_version,
const char *resource_name, const char *resource_id)
{
char buf[OGS_ADDRSTRLEN];
char url[OGS_HUGE_LEN];
char *p, *last;
ogs_assert(addr);
ogs_assert(service_name);
ogs_assert(api_version);
ogs_assert(resource_name);
p = url;
last = url + OGS_HUGE_LEN;
/* HTTP scheme is selected based on TLS information */
if (https == true)
p = ogs_slprintf(p, last, "https://");
else
p = ogs_slprintf(p, last, "http://");
/* IP address */
if (addr->ogs_sa_family == AF_INET6)
p = ogs_slprintf(p, last, "[%s]", OGS_ADDR(addr, buf));
else
p = ogs_slprintf(p, last, "%s", OGS_ADDR(addr, buf));
/* Port number */
if (OGS_PORT(addr) != OGS_SBI_HTTP_PORT) {
p = ogs_slprintf(p, last, ":%d", OGS_PORT(addr));
}
/* API */
ogs_assert(service_name);
p = ogs_slprintf(p, last, "/%s", service_name);
ogs_assert(api_version);
p = ogs_slprintf(p, last, "/%s", api_version);
/* Resource */
ogs_assert(resource_name);
p = ogs_slprintf(p, last, "/%s", resource_name);
if (resource_id)
p = ogs_slprintf(p, last, "/%s", resource_id);
return ogs_strdup(url);
}
char *ogs_sbi_server_uri(ogs_sbi_server_t *server,
const char *service_name, const char *api_version,
const char *resource_name, const char *resource_id)
{
bool https = false;
if (server->tls.key && server->tls.pem)
https = true;
return ogs_uridup(https, server->addr, service_name, api_version,
resource_name, resource_id);
}
char *ogs_sbi_client_uri(ogs_sbi_client_t *client,
const char *service_name, const char *api_version,
const char *resource_name, const char *resource_id)
{
bool https = false;
if (client->tls.key && client->tls.pem)
https = true;
return ogs_uridup(https, client->addr, service_name, api_version,
resource_name, resource_id);
}
/**
* Returns a url-decoded version of str
* IMPORTANT: be sure to free() the returned string after use
* Thanks Geek Hideout!
* http://www.geekhideout.com/urlcode.shtml
*/
static char *url_decode(const char *str)
{
if (str != NULL) {
char *pstr = (char*)str;
char *buf = ogs_malloc(strlen(str) + 1);
char *pbuf = buf;
while (*pstr) {
if (*pstr == '%') {
if (pstr[1] && pstr[2]) {
*pbuf++ = ogs_from_hex(pstr[1]) << 4 |
ogs_from_hex(pstr[2]);
pstr += 2;
}
} else if (*pstr == '+') {
*pbuf++ = ' ';
} else {
*pbuf++ = * pstr;
}
pstr++;
}
*pbuf = '\0';
return buf;
} else {
return NULL;
}
}
char *ogs_sbi_parse_url(char *url, const char *delim, char **saveptr)
{
char *item = NULL;
item = url_decode(strtok_r(url, delim, saveptr));
if (!item) {
return NULL;
}
return item;
}
ogs_sockaddr_t *ogs_sbi_getaddr_from_uri(char *uri)
{
int rv;
struct yuarel yuarel;
char *p = NULL;
int port;
ogs_sockaddr_t *addr = NULL;
p = ogs_strdup(uri);
rv = yuarel_parse(&yuarel, p);
if (rv != OGS_OK) {
ogs_free(p);
ogs_error("yuarel_parse() failed [%s]", uri);
return NULL;
}
if (!yuarel.scheme) {
ogs_error("No http.scheme found [%s]", uri);
ogs_free(p);
return NULL;
}
if (strcmp(yuarel.scheme, "https") == 0) {
port = OGS_SBI_HTTPS_PORT;
} else if (strcmp(yuarel.scheme, "http") == 0) {
port = OGS_SBI_HTTP_PORT;
} else {
ogs_error("Invalid http.scheme [%s:%s]", yuarel.scheme, uri);
ogs_free(p);
return NULL;
}
if (!yuarel.host) {
ogs_error("No http.host found [%s]", uri);
ogs_free(p);
return NULL;
}
if (yuarel.port) port = yuarel.port;
rv = ogs_getaddrinfo(&addr, AF_UNSPEC, yuarel.host, port, 0);
if (rv != OGS_OK) {
ogs_error("ogs_getaddrinfo() failed [%s]", uri);
ogs_free(p);
return NULL;
}
ogs_free(p);
return addr;
}

49
lib/sbi/conv.h Normal file
View File

@ -0,0 +1,49 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#if !defined(OGS_SBI_INSIDE) && !defined(OGS_SBI_COMPILATION)
#error "This header cannot be included directly."
#endif
#ifndef OGS_SBI_CONV_H
#define OGS_SBI_CONV_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ogs_sbi_server_s ogs_sbi_server_t;
typedef struct ogs_sbi_client_s ogs_sbi_client_t;
char *ogs_sbi_server_uri(ogs_sbi_server_t *server,
const char *service_name, const char *api_version,
const char *resource_name, const char *resource_id);
char *ogs_sbi_client_uri(ogs_sbi_client_t *client,
const char *service_name, const char *api_version,
const char *resource_name, const char *resource_id);
char *ogs_sbi_parse_url(char *url, const char *delim, char **saveptr);
ogs_sockaddr_t *ogs_sbi_getaddr_from_uri(char *uri);
#ifdef __cplusplus
}
#endif
#endif /* OGS_SBI_CONV_H */

37
lib/sbi/custom/links.c Normal file
View File

@ -0,0 +1,37 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "links.h"
cJSON *ogs_sbi_links_convertToJSON(ogs_sbi_links_t *links)
{
cJSON *rootJSON = NULL;
cJSON *linksJSON = NULL;
cJSON *itemsJSON = NULL;
cJSON *selfJSON = NULL;
OpenAPI_lnode_t *node;
ogs_assert(links);
ogs_assert(links->self);
rootJSON = cJSON_CreateObject();
ogs_assert(rootJSON);
linksJSON = cJSON_AddObjectToObject(rootJSON, "_links");
ogs_assert(linksJSON);
itemsJSON = cJSON_AddObjectToObject(linksJSON, "items");
ogs_assert(itemsJSON);
OpenAPI_list_for_each(links->items, node) {
if (!node->data) continue;
cJSON_AddStringToObject(itemsJSON, "href", node->data);
}
selfJSON = cJSON_AddObjectToObject(linksJSON, "self");
ogs_assert(selfJSON);
cJSON_AddStringToObject(selfJSON, "href", links->self);
return rootJSON;
}

32
lib/sbi/custom/links.h Normal file
View File

@ -0,0 +1,32 @@
/*
* search_result.h
*
*
*/
#ifndef _OpenAPILinksH_
#define _OpenAPILinksH_
#include <string.h>
#include "../openapi/external/cJSON.h"
#include "../openapi/include/list.h"
#include "../openapi/include/keyValuePair.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ogs_sbi_links_s ogs_sbi_links_t;
typedef struct ogs_sbi_links_s {
OpenAPI_list_t *items;
char *self;
} ogs_sbi_links_t;
cJSON *ogs_sbi_links_convertToJSON(ogs_sbi_links_t *links);
#ifdef __cplusplus
}
#endif
#endif /* _OpenAPILinksH_ */

64
lib/sbi/meson.build Normal file
View File

@ -0,0 +1,64 @@
# Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
# This file is part of Open5GS.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
subdir('openapi')
libsbi_sources = files('''
custom/links.c
yuarel.c
conv.c
message.c
server.c
client.c
context.c
nnrf-build.c
nnrf-handler.c
'''.split())
libsbi_inc = include_directories('.')
sbi_cc_flags = ['-DOGS_SBI_COMPILATION']
libgnutls_dep = cc.find_library('gnutls', required : true)
libmicrohttpd_dep = dependency('libmicrohttpd')
libcurl_dep = dependency('libcurl')
libsbi = library('ogssbi',
sources : libsbi_sources,
version : libogslib_version,
c_args : sbi_cc_flags,
include_directories : [libsbi_inc, libinc],
dependencies : [libcore_dep,
libapp_dep,
libsbi_openapi_dep,
libgnutls_dep,
libmicrohttpd_dep,
libcurl_dep],
install : true)
libsbi_dep = declare_dependency(
link_with : libsbi,
include_directories : [libsbi_inc, libinc],
dependencies : [libcore_dep,
libapp_dep,
libsbi_openapi_dep,
libgnutls_dep,
libmicrohttpd_dep,
libcurl_dep])

576
lib/sbi/message.c Normal file
View File

@ -0,0 +1,576 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "ogs-sbi.h"
#include "sbi-private.h"
static OGS_POOL(request_pool, ogs_sbi_request_t);
static OGS_POOL(response_pool, ogs_sbi_response_t);
void ogs_sbi_message_init(int num_of_request_pool, int num_of_response_pool)
{
ogs_pool_init(&request_pool, num_of_request_pool);
ogs_pool_init(&response_pool, num_of_response_pool);
}
void ogs_sbi_message_final(void)
{
ogs_pool_final(&request_pool);
ogs_pool_final(&response_pool);
}
void ogs_sbi_message_free(ogs_sbi_message_t *message)
{
ogs_assert(message);
if (message->NFProfile)
OpenAPI_nf_profile_free(message->NFProfile);
if (message->ProblemDetails)
OpenAPI_problem_details_free(message->ProblemDetails);
if (message->PatchItemList) {
OpenAPI_lnode_t *node = NULL;
OpenAPI_list_for_each(message->PatchItemList, node)
OpenAPI_patch_item_free(node->data);
OpenAPI_list_free(message->PatchItemList);
}
if (message->SubscriptionData)
OpenAPI_subscription_data_free(message->SubscriptionData);
if (message->NotificationData)
OpenAPI_notification_data_free(message->NotificationData);
if (message->SearchResult)
OpenAPI_search_result_free(message->SearchResult);
}
ogs_sbi_request_t *ogs_sbi_request_new(void)
{
ogs_sbi_request_t *request = NULL;
ogs_pool_alloc(&request_pool, &request);
ogs_assert(request);
memset(request, 0, sizeof(ogs_sbi_request_t));
request->http.params = ogs_hash_make();
request->http.headers = ogs_hash_make();
return request;
}
ogs_sbi_response_t *ogs_sbi_response_new(void)
{
ogs_sbi_response_t *response = NULL;
ogs_pool_alloc(&response_pool, &response);
ogs_assert(response);
memset(response, 0, sizeof(ogs_sbi_response_t));
response->http.params = ogs_hash_make();
response->http.headers = ogs_hash_make();
return response;
}
static void sbi_header_free(ogs_sbi_header_t *h);
static void http_message_free(http_message_t *http);
void ogs_sbi_request_free(ogs_sbi_request_t *request)
{
ogs_assert(request);
if (request->h.url)
ogs_free(request->h.url);
sbi_header_free(&request->h);
http_message_free(&request->http);
ogs_pool_free(&request_pool, request);
}
void ogs_sbi_response_free(ogs_sbi_response_t *response)
{
ogs_assert(response);
if (response->h.url)
ogs_free(response->h.url);
sbi_header_free(&response->h);
http_message_free(&response->http);
ogs_pool_free(&response_pool, response);
}
static void sbi_header_free(ogs_sbi_header_t *h)
{
ogs_assert(h);
if (h->method) ogs_free(h->method);
if (h->service.name) ogs_free(h->service.name);
if (h->api.version) ogs_free(h->api.version);
if (h->resource.name) ogs_free(h->resource.name);
if (h->resource.id) ogs_free(h->resource.id);
}
static void http_message_free(http_message_t *http)
{
ogs_assert(http);
if (http->params) {
ogs_hash_index_t *hi;
for (hi = ogs_hash_first(http->params); hi; hi = ogs_hash_next(hi)) {
char *val = ogs_hash_this_val(hi);
ogs_free(val);
}
ogs_hash_destroy(http->params);
}
if (http->headers) {
ogs_hash_index_t *hi;
for (hi = ogs_hash_first(http->headers); hi; hi = ogs_hash_next(hi)) {
char *val = ogs_hash_this_val(hi);
ogs_free(val);
}
ogs_hash_destroy(http->headers);
}
if (http->content) ogs_free(http->content);
}
static char *build_content(ogs_sbi_message_t *message);
ogs_sbi_request_t *ogs_sbi_build_request(ogs_sbi_message_t *message)
{
ogs_sbi_request_t *request = NULL;
ogs_assert(message);
request = ogs_sbi_request_new();
ogs_assert(request);
ogs_assert(message->h.method);
request->h.method = ogs_strdup(message->h.method);
if (message->h.url) {
request->h.url = ogs_strdup(message->h.url);
} else {
ogs_assert(message->h.service.name);
request->h.service.name = ogs_strdup(message->h.service.name);
ogs_assert(message->h.api.version);
request->h.api.version = ogs_strdup(message->h.api.version);
ogs_assert(message->h.resource.name);
request->h.resource.name = ogs_strdup(message->h.resource.name);
if (message->h.resource.id)
request->h.resource.id = ogs_strdup(message->h.resource.id);
}
/* URL Param */
if (message->param.nf_type) {
char *v = OpenAPI_nf_type_ToString(message->param.nf_type);
ogs_assert(v);
ogs_sbi_header_set(request->http.params, OGS_SBI_PARAM_NF_TYPE, v);
}
if (message->param.requester_nf_type) {
char *v = OpenAPI_nf_type_ToString(message->param.requester_nf_type);
ogs_assert(v);
ogs_sbi_header_set(request->http.params,
OGS_SBI_PARAM_REQUESTER_NF_TYPE, v);
}
if (message->param.target_nf_type) {
char *v = OpenAPI_nf_type_ToString(message->param.target_nf_type);
ogs_assert(v);
ogs_sbi_header_set(request->http.params,
OGS_SBI_PARAM_TARGET_NF_TYPE, v);
}
if (message->param.limit) {
char *v = ogs_msprintf("%d", message->param.limit);
ogs_assert(v);
ogs_sbi_header_set(request->http.params, OGS_SBI_PARAM_LIMIT, v);
}
/* HTTP Message */
request->http.content = build_content(message);
if (request->http.content) {
if (message->http.content_type)
ogs_sbi_header_set(request->http.headers,
OGS_SBI_CONTENT_TYPE, message->http.content_type);
else
ogs_sbi_header_set(request->http.headers,
OGS_SBI_CONTENT_TYPE, OGS_SBI_CONTENT_JSON_TYPE);
}
if (message->http.content_encoding)
ogs_sbi_header_set(request->http.headers,
OGS_SBI_ACCEPT_ENCODING, message->http.content_encoding);
return request;
}
ogs_sbi_response_t *ogs_sbi_build_response(ogs_sbi_message_t *message)
{
ogs_sbi_response_t *response = NULL;
ogs_assert(message);
response = ogs_sbi_response_new();
ogs_assert(response);
/* HTTP Message */
response->http.content = build_content(message);
if (response->http.content) {
if (message->http.content_type)
ogs_sbi_header_set(response->http.headers,
OGS_SBI_CONTENT_TYPE, message->http.content_type);
else
ogs_sbi_header_set(response->http.headers,
OGS_SBI_CONTENT_TYPE, OGS_SBI_CONTENT_JSON_TYPE);
}
if (message->http.location == true)
ogs_sbi_header_set(response->http.headers, "Location", message->h.url);
if (message->http.cache_control)
ogs_sbi_header_set(response->http.headers, "Cache-Control",
message->http.cache_control);
return response;
}
static char *build_content(ogs_sbi_message_t *message)
{
char *content = NULL;
cJSON *item = NULL;
ogs_assert(message);
if (message->ProblemDetails) {
item = OpenAPI_problem_details_convertToJSON(message->ProblemDetails);
ogs_assert(item);
} else if (message->NFProfile) {
item = OpenAPI_nf_profile_convertToJSON(message->NFProfile);
ogs_assert(item);
} else if (message->PatchItemList) {
OpenAPI_lnode_t *node = NULL;
item = cJSON_CreateArray();
ogs_assert(item);
OpenAPI_list_for_each(message->PatchItemList, node) {
cJSON *patchItem = OpenAPI_patch_item_convertToJSON(node->data);
ogs_assert(patchItem);
cJSON_AddItemToArray(item, patchItem);
}
} else if (message->SubscriptionData) {
item = OpenAPI_subscription_data_convertToJSON(
message->SubscriptionData);
ogs_assert(item);
} else if (message->NotificationData) {
item = OpenAPI_notification_data_convertToJSON(
message->NotificationData);
ogs_assert(item);
} else if (message->SearchResult) {
item = OpenAPI_search_result_convertToJSON(message->SearchResult);
ogs_assert(item);
} else if (message->links) {
item = ogs_sbi_links_convertToJSON(message->links);
ogs_assert(item);
}
if (item) {
content = cJSON_Print(item);
ogs_assert(content);
cJSON_Delete(item);
}
return content;
}
static int parse_sbi_header(
ogs_sbi_message_t *message, ogs_sbi_header_t *header);
static int parse_content(ogs_sbi_message_t *message, char *content);
int ogs_sbi_parse_request(
ogs_sbi_message_t *message, ogs_sbi_request_t *request)
{
int rv;
ogs_hash_index_t *hi;
ogs_assert(request);
ogs_assert(message);
rv = parse_sbi_header(message, &request->h);
if (rv != OGS_OK) {
ogs_error("sbi_parse_header() failed");
return OGS_ERROR;
}
for (hi = ogs_hash_first(request->http.params);
hi; hi = ogs_hash_next(hi)) {
if (!strcmp(ogs_hash_this_key(hi), OGS_SBI_PARAM_NF_TYPE)) {
message->param.nf_type =
OpenAPI_nf_type_FromString(ogs_hash_this_val(hi));
} else if (!strcmp(ogs_hash_this_key(hi),
OGS_SBI_PARAM_TARGET_NF_TYPE)) {
message->param.target_nf_type =
OpenAPI_nf_type_FromString(ogs_hash_this_val(hi));
} else if (!strcmp(ogs_hash_this_key(hi),
OGS_SBI_PARAM_REQUESTER_NF_TYPE)) {
message->param.requester_nf_type =
OpenAPI_nf_type_FromString(ogs_hash_this_val(hi));
} else if (!strcmp(ogs_hash_this_key(hi),
OGS_SBI_PARAM_LIMIT)) {
message->param.limit = atoi(ogs_hash_this_val(hi));
}
}
for (hi = ogs_hash_first(request->http.headers);
hi; hi = ogs_hash_next(hi)) {
if (!strcmp(ogs_hash_this_key(hi), OGS_SBI_ACCEPT_ENCODING)) {
message->http.content_encoding = ogs_hash_this_val(hi);
} else if (!strcmp(ogs_hash_this_key(hi), OGS_SBI_CONTENT_TYPE)) {
message->http.content_type = ogs_hash_this_val(hi);
}
}
if (parse_content(message, request->http.content) != OGS_OK) {
ogs_error("parse_content() failed");
return OGS_ERROR;
}
return OGS_OK;
}
int ogs_sbi_parse_response(
ogs_sbi_message_t *message, ogs_sbi_response_t *response)
{
int rv;
ogs_hash_index_t *hi;
ogs_assert(response);
ogs_assert(message);
rv = parse_sbi_header(message, &response->h);
if (rv != OGS_OK) {
ogs_error("sbi_parse_header() failed");
return OGS_ERROR;
}
for (hi = ogs_hash_first(response->http.headers);
hi; hi = ogs_hash_next(hi)) {
if (!strcmp(ogs_hash_this_key(hi), OGS_SBI_CONTENT_TYPE)) {
message->http.content_type = ogs_hash_this_val(hi);
}
}
if (parse_content(message, response->http.content) != OGS_OK) {
ogs_error("parse_content() failed");
return OGS_ERROR;
}
message->res_status = response->status;
return OGS_OK;
}
static int parse_sbi_header(
ogs_sbi_message_t *message, ogs_sbi_header_t *header)
{
struct yuarel yuarel;
char *saveptr = NULL;
char *url = NULL, *p = NULL;;
ogs_assert(message);
ogs_assert(header);
memset(message, 0, sizeof(*message));
message->h.method = header->method;
ogs_assert(message->h.method);
message->h.url = header->url;
ogs_assert(message->h.url);
url = ogs_strdup(header->url);
ogs_assert(url);
p = url;
if (p[0] != '/') {
int rv = yuarel_parse(&yuarel, p);
if (rv != OGS_OK) {
ogs_error("yuarel_parse() failed");
ogs_free(url);
return OGS_ERROR;
}
p = yuarel.path;
}
header->service.name = ogs_sbi_parse_url(p, "/", &saveptr);
if (!header->service.name) {
ogs_error("ogs_sbi_parse_url() failed");
ogs_free(url);
return OGS_ERROR;
}
message->h.service.name = header->service.name;
header->api.version = ogs_sbi_parse_url(NULL, "/", &saveptr);
if (!header->api.version) {
ogs_error("ogs_sbi_parse_url() failed");
ogs_free(url);
return OGS_ERROR;
}
message->h.api.version = header->api.version;
header->resource.name = ogs_sbi_parse_url(NULL, "/", &saveptr);
if (!header->resource.name) {
ogs_error("ogs_sbi_parse_url() failed");
ogs_free(url);
return OGS_ERROR;
}
message->h.resource.name = header->resource.name;
header->resource.id = ogs_sbi_parse_url(NULL, "/", &saveptr);
message->h.resource.id = header->resource.id;
ogs_free(url);
return OGS_OK;
}
static int parse_content(ogs_sbi_message_t *message, char *content)
{
int rv = OGS_OK;
cJSON *item = NULL;
ogs_assert(message);
if (!content)
return OGS_OK;
if (strcmp(message->h.api.version, OGS_SBI_API_VERSION) != 0) {
ogs_error("Not supported version - %s", message->h.api.version);
return OGS_ERROR;
}
item = cJSON_Parse(content);
if (!item) {
ogs_error("JSON parse error");
return OGS_ERROR;
}
if (message->http.content_type) {
if (!strncmp(message->http.content_type,
OGS_SBI_CONTENT_PROBLEM_TYPE,
strlen(OGS_SBI_CONTENT_PROBLEM_TYPE))) {
message->ProblemDetails =
OpenAPI_problem_details_parseFromJSON(item);
} else if (!strncmp(message->http.content_type,
OGS_SBI_CONTENT_PATCH_TYPE,
strlen(OGS_SBI_CONTENT_PATCH_TYPE))) {
if (item) {
OpenAPI_patch_item_t *patch_item = NULL;
cJSON *patchJSON = NULL;
message->PatchItemList = OpenAPI_list_create();
cJSON_ArrayForEach(patchJSON, item) {
if (!cJSON_IsObject(patchJSON)) {
rv = OGS_ERROR;
ogs_error("Unknown JSON");
goto cleanup;
}
patch_item = OpenAPI_patch_item_parseFromJSON(patchJSON);
OpenAPI_list_add(message->PatchItemList, patch_item);
}
}
} else {
SWITCH(message->h.service.name)
CASE(OGS_SBI_SERVICE_NAME_NRF_NFM)
SWITCH(message->h.resource.name)
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
message->NFProfile =
OpenAPI_nf_profile_parseFromJSON(item);
if (!message->NFProfile) {
rv = OGS_ERROR;
ogs_error("JSON parse error");
}
break;
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
message->SubscriptionData =
OpenAPI_subscription_data_parseFromJSON(item);
if (!message->SubscriptionData) {
rv = OGS_ERROR;
ogs_error("JSON parse error");
}
break;
CASE(OGS_SBI_RESOURCE_NAME_NF_STATUS_NOTIFY)
message->NotificationData =
OpenAPI_notification_data_parseFromJSON(item);
if (!message->NotificationData) {
rv = OGS_ERROR;
ogs_error("JSON parse error");
}
break;
DEFAULT
rv = OGS_ERROR;
ogs_error("Unknown resource name [%s]",
message->h.resource.name);
END
break;
CASE(OGS_SBI_SERVICE_NAME_NRF_DISC)
SWITCH(message->h.resource.name)
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
message->SearchResult =
OpenAPI_search_result_parseFromJSON(item);
if (!message->SearchResult) {
rv = OGS_ERROR;
ogs_error("JSON parse error");
}
break;
DEFAULT
rv = OGS_ERROR;
ogs_error("Unknown resource name [%s]",
message->h.resource.name);
END
break;
DEFAULT
rv = OGS_ERROR;
ogs_error("Not implemented API name [%s]",
message->h.service.name);
END
}
}
cleanup:
cJSON_Delete(item);
return rv;
}
void ogs_sbi_header_set(ogs_hash_t *ht, const void *key, const void *val)
{
ogs_hash_set(ht, key, strlen(key), ogs_strdup(val));
}
void *ogs_sbi_header_get(ogs_hash_t *ht, const void *key)
{
return ogs_hash_get(ht, key, strlen(key));
}

177
lib/sbi/message.h Normal file
View File

@ -0,0 +1,177 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#if !defined(OGS_SBI_INSIDE) && !defined(OGS_SBI_COMPILATION)
#error "This header cannot be included directly."
#endif
#ifndef OGS_SBI_MESSAGE_H
#define OGS_SBI_MESSAGE_H
#ifdef __cplusplus
extern "C" {
#endif
#define OGS_SBI_HTTP_PORT 80
#define OGS_SBI_HTTPS_PORT 443
#define OGS_SBI_HTTP_SCHEME "http"
#define OGS_SBI_HTTPS_SCHEME "https"
#define OGS_SBI_HTTP_STATUS_OK 200
#define OGS_SBI_HTTP_STATUS_CREATED 201 /* POST PUT */
#define OGS_SBI_HTTP_STATUS_ACCEPTED 202 /* DELETE PATCH
POST PUT */
#define OGS_SBI_HTTP_STATUS_NO_CONTENT 204 /* DELETE PATCH
POST PUT OPTIONS */
#define OGS_SBI_HTTP_STATUS_SEE_OTHER 303 /* DELETE GET
POST PUT */
#define OGS_SBI_HTTP_STATUS_TEMPORARY_REDIRECT 307 /* ALL */
#define OGS_SBI_HTTP_STATUS_PERMANENT_REDIRECT 308 /* ALL */
#define OGS_SBI_HTTP_STATUS_BAD_REQUEST 400 /* ALL */
#define OGS_SBI_HTTP_STATUS_UNAUTHORIZED 401 /* ALL */
#define OGS_SBI_HTTP_STATUS_FORBIDDEN 403 /* ALL */
#define OGS_SBI_HTTP_STATUS_NOT_FOUND 404 /* ALL */
#define OGS_SBI_HTTP_STATUS_MEHTOD_NOT_ALLOWED 405 /* ALL */
#define OGS_SBI_HTTP_STATUS_NOT_ACCEPTABLE 406 /* GET OPTIONS */
#define OGS_SBI_HTTP_STATUS_REQUEST_TIMEOUT 408 /* ALL */
#define OGS_SBI_HTTP_STATUS_CONFLICT 409 /* PATCH POST PUT */
#define OGS_SBI_HTTP_STATUS_GONE 410 /* ALL */
#define OGS_SBI_HTTP_STATUS_LENGTH_REQUIRED 411 /* PATCH POST
PUT OPTIONS */
#define OGS_SBI_HTTP_STATUS_PRECONDITION_FAILED 412 /* DELETE GET PATCH
POST PUT */
#define OGS_SBI_HTTP_STATUS_PAYLOAD_TOO_LARGE 413 /* PATCH POST
PUT OPTIONS */
#define OGS_SBI_HTTP_STATUS_URI_TOO_LONG 414 /* GET PUT */
#define OGS_SBI_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE 415 /* PATCH POST
PUT OPTIONS */
#define OGS_SBI_HTTP_STATUS_TOO_MANY_REQUESTS 429 /* ALL */
#define OGS_SBI_HTTP_STATUS_INTERNAL_SERVER_ERROR 500 /* ALL */
#define OGS_SBI_HTTP_STATUS_NOT_IMPLEMENTED 501 /* ALL */
#define OGS_SBI_HTTP_STATUS_SERVICE_UNAVAILABLE 503 /* ALL */
#define OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT 504 /* ALL */
#define OGS_SBI_HTTP_METHOD_DELETE "DELETE"
#define OGS_SBI_HTTP_METHOD_GET "GET"
#define OGS_SBI_HTTP_METHOD_PATCH "PATCH"
#define OGS_SBI_HTTP_METHOD_POST "POST"
#define OGS_SBI_HTTP_METHOD_PUT "PUT"
#define OGS_SBI_HTTP_METHOD_OPTIONS "OPTIONS"
#define OGS_SBI_API_VERSION "v1"
#define OGS_SBI_API_FULL_VERSION "1.0.0"
#define OGS_SBI_SERVICE_NAME_NRF_NFM "nnrf-nfm"
#define OGS_SBI_SERVICE_NAME_NRF_DISC "nnrf-disc"
#define OGS_SBI_SERVICE_NAME_SMF_PDUSESSION "nsmf-pdusession"
#define OGS_SBI_SERVICE_NAME_SMF_EVENT_EXPOSURE "nsmf-event-exposure"
#define OGS_SBI_RESOURCE_NAME_NF_INSTANCES "nf-instances"
#define OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS "subscriptions"
#define OGS_SBI_RESOURCE_NAME_NF_STATUS_NOTIFY "nf-status-notify"
#define OGS_SBI_PARAM_NF_TYPE "nf-type"
#define OGS_SBI_PARAM_TARGET_NF_TYPE "target-nf-type"
#define OGS_SBI_PARAM_REQUESTER_NF_TYPE "requester-nf-type"
#define OGS_SBI_PARAM_LIMIT "limit"
#define OGS_SBI_ACCEPT_ENCODING "Accept-Encoding"
#define OGS_SBI_CONTENT_TYPE "Content-Type"
#define OGS_SBI_CONTENT_JSON_TYPE "application/json"
#define OGS_SBI_CONTENT_PROBLEM_TYPE "application/problem+json"
#define OGS_SBI_CONTENT_PATCH_TYPE \
"application/json-patch+json"
#define OGS_SBI_CONTENT_3GPPHAL_TYPE "application/3gppHal+json"
typedef struct ogs_sbi_request_s ogs_sbi_request_t;
typedef struct ogs_sbi_response_s ogs_sbi_response_t;
typedef struct ogs_sbi_header_s {
char *method;
char *url;
struct {
char *name;
} service;
struct {
char *version;
} api;
struct {
char *name;
char *id;
} resource;
} ogs_sbi_header_t;
typedef struct ogs_sbi_message_s {
ogs_sbi_header_t h;
struct {
char *content_encoding;
char *content_type;
bool location;
char *cache_control;
} http;
struct {
OpenAPI_nf_type_e target_nf_type;
OpenAPI_nf_type_e requester_nf_type;
OpenAPI_nf_type_e nf_type;
int limit;
} param;
int res_status;
OpenAPI_nf_profile_t *NFProfile;
OpenAPI_problem_details_t *ProblemDetails;
OpenAPI_list_t *PatchItemList;
OpenAPI_subscription_data_t *SubscriptionData;
OpenAPI_notification_data_t *NotificationData;
OpenAPI_search_result_t *SearchResult;
ogs_sbi_links_t *links;
} ogs_sbi_message_t;
void ogs_sbi_message_init(int num_of_request_pool, int num_of_response_pool);
void ogs_sbi_message_final(void);
void ogs_sbi_message_free(ogs_sbi_message_t *message);
ogs_sbi_request_t *ogs_sbi_request_new(void);
void ogs_sbi_request_free(ogs_sbi_request_t *request);
ogs_sbi_request_t *ogs_sbi_build_request(ogs_sbi_message_t *message);
int ogs_sbi_parse_request(
ogs_sbi_message_t *message, ogs_sbi_request_t *request);
ogs_sbi_response_t *ogs_sbi_response_new(void);
void ogs_sbi_response_free(ogs_sbi_response_t *response);
ogs_sbi_response_t *ogs_sbi_build_response(ogs_sbi_message_t *message);
int ogs_sbi_parse_response(
ogs_sbi_message_t *message, ogs_sbi_response_t *response);
void ogs_sbi_header_set(ogs_hash_t *ht, const void *key, const void *val);
void *ogs_sbi_header_get(ogs_hash_t *ht, const void *key);
#ifdef __cplusplus
}
#endif
#endif /* OGS_SBI_MESSAGE_H */

214
lib/sbi/nnrf-build.c Normal file
View File

@ -0,0 +1,214 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "nnrf-build.h"
OpenAPI_nf_profile_t *ogs_sbi_nnrf_build_nf_profile(
ogs_sbi_nf_instance_t *nf_instance)
{
ogs_sbi_nf_service_t *nf_service = NULL;
OpenAPI_nf_profile_t *NFProfile = NULL;
OpenAPI_list_t *Ipv4AddrList = NULL;
OpenAPI_list_t *Ipv6AddrList = NULL;
OpenAPI_list_t *NFServiceList = NULL;
int i = 0;
int fqdn_len;
char fqdn[OGS_MAX_FQDN_LEN+1];
ogs_assert(nf_instance);
NFProfile = ogs_calloc(1, sizeof(*NFProfile));
ogs_assert(NFProfile);
NFProfile->nf_instance_id = nf_instance->id;
NFProfile->nf_type = nf_instance->nf_type;
NFProfile->nf_status = nf_instance->nf_status;
if (strlen(nf_instance->fqdn)) {
memset(fqdn, 0, sizeof(fqdn));
fqdn_len = ogs_fqdn_build(fqdn,
nf_instance->fqdn, strlen(nf_instance->fqdn));
NFProfile->fqdn = ogs_memdup(fqdn, fqdn_len);
}
Ipv4AddrList = OpenAPI_list_create();
ogs_assert(Ipv4AddrList);
Ipv6AddrList = OpenAPI_list_create();
ogs_assert(Ipv6AddrList);
for (i = 0; i < nf_instance->num_of_ipv4; i++) {
if (nf_instance->ipv4[i])
OpenAPI_list_add(Ipv4AddrList, ogs_ipstrdup(nf_instance->ipv4[i]));
}
for (i = 0; i < nf_instance->num_of_ipv6; i++) {
if (nf_instance->ipv6[i])
OpenAPI_list_add(Ipv6AddrList, ogs_ipstrdup(nf_instance->ipv6[i]));
}
if (Ipv4AddrList->count)
NFProfile->ipv4_addresses = Ipv4AddrList;
else
OpenAPI_list_free(Ipv4AddrList);
if (Ipv6AddrList->count)
NFProfile->ipv6_addresses = Ipv6AddrList;
else
OpenAPI_list_free(Ipv6AddrList);
NFServiceList = OpenAPI_list_create();
ogs_assert(NFServiceList);
ogs_list_for_each(&nf_instance->nf_service_list, nf_service) {
OpenAPI_nf_service_t *NFService = NULL;
OpenAPI_list_t *VersionList = NULL;
OpenAPI_list_t *IpEndPointList = NULL;
NFService = ogs_calloc(1, sizeof(*NFService));
ogs_assert(NFService);
NFService->service_instance_id = ogs_strdup(nf_service->id);
NFService->service_name = ogs_strdup(nf_service->name);
VersionList = OpenAPI_list_create();
ogs_assert(VersionList);
for (i = 0; i < nf_service->num_of_version; i++) {
OpenAPI_nf_service_version_t *NFServiceVersion = NULL;
NFServiceVersion = ogs_calloc(1, sizeof(*NFServiceVersion));
ogs_assert(NFServiceVersion);
if (nf_service->versions[i].in_uri)
NFServiceVersion->api_version_in_uri =
ogs_strdup(nf_service->versions[i].in_uri);
if (nf_service->versions[i].full)
NFServiceVersion->api_full_version =
ogs_strdup(nf_service->versions[i].full);
if (nf_service->versions[i].expiry)
NFServiceVersion->expiry =
ogs_strdup(nf_service->versions[i].expiry);
OpenAPI_list_add(VersionList, NFServiceVersion);
}
ogs_assert(VersionList->count);
NFService->versions = VersionList;
NFService->scheme = nf_service->scheme;
NFService->nf_service_status = nf_service->status;
if (strlen(nf_service->fqdn)) {
memset(fqdn, 0, sizeof(fqdn));
fqdn_len = ogs_fqdn_build(fqdn,
nf_service->fqdn, strlen(nf_service->fqdn));
NFService->fqdn = ogs_memdup(fqdn, fqdn_len);
}
IpEndPointList = OpenAPI_list_create();
ogs_assert(IpEndPointList);
for (i = 0; i < nf_service->num_of_addr; i++) {
ogs_sockaddr_t *ipv4 = NULL;
ogs_sockaddr_t *ipv6 = NULL;
OpenAPI_ip_end_point_t *IpEndPoint = NULL;
ipv4 = nf_service->addr[i].ipv4;
ipv6 = nf_service->addr[i].ipv6;
if (ipv4 || ipv6) {
IpEndPoint = ogs_calloc(1, sizeof(*IpEndPoint));
ogs_assert(IpEndPoint);
if (ipv4) IpEndPoint->ipv4_address = ogs_ipstrdup(ipv4);
if (ipv6) IpEndPoint->ipv6_address = ogs_ipstrdup(ipv6);
IpEndPoint->port = nf_service->addr[i].port;
OpenAPI_list_add(IpEndPointList, IpEndPoint);
}
}
if (IpEndPointList->count)
NFService->ip_end_points = IpEndPointList;
else
OpenAPI_list_free(IpEndPointList);
OpenAPI_list_add(NFServiceList, NFService);
}
if (NFServiceList->count)
NFProfile->nf_services = NFServiceList;
else
OpenAPI_list_free(NFServiceList);
return NFProfile;
}
void ogs_sbi_nnrf_free_nf_profile(OpenAPI_nf_profile_t *NFProfile)
{
OpenAPI_lnode_t *node = NULL;
ogs_assert(NFProfile);
OpenAPI_list_for_each(NFProfile->ipv4_addresses, node)
ogs_free(node->data);
OpenAPI_list_free(NFProfile->ipv4_addresses);
OpenAPI_list_for_each(NFProfile->ipv6_addresses, node)
ogs_free(node->data);
OpenAPI_list_free(NFProfile->ipv6_addresses);
OpenAPI_list_for_each(NFProfile->nf_services, node) {
OpenAPI_lnode_t *node2;
OpenAPI_nf_service_t *NFService = node->data;
ogs_assert(NFService);
ogs_free(NFService->service_instance_id);
ogs_free(NFService->service_name);
OpenAPI_list_for_each(NFService->versions, node2) {
OpenAPI_nf_service_version_t *NFServiceVersion = node2->data;
ogs_assert(NFServiceVersion);
ogs_free(NFServiceVersion->api_version_in_uri);
ogs_free(NFServiceVersion->api_full_version);
if (NFServiceVersion->expiry)
ogs_free(NFServiceVersion->expiry);
ogs_free(NFServiceVersion);
}
OpenAPI_list_free(NFService->versions);
OpenAPI_list_for_each(NFService->ip_end_points, node2) {
OpenAPI_ip_end_point_t *IpEndPoint = node2->data;
ogs_assert(IpEndPoint);
if (IpEndPoint->ipv4_address)
ogs_free(IpEndPoint->ipv4_address);
if (IpEndPoint->ipv6_address)
ogs_free(IpEndPoint->ipv6_address);
ogs_free(IpEndPoint);
}
OpenAPI_list_free(NFService->ip_end_points);
if (NFService->fqdn)
ogs_free(NFService->fqdn);
ogs_free(NFService);
}
OpenAPI_list_free(NFProfile->nf_services);
if (NFProfile->fqdn)
ogs_free(NFProfile->fqdn);
ogs_free(NFProfile);
}

38
lib/sbi/nnrf-build.h Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef OGS_NNRF_BUILD_H
#define OGS_NNRF_BUILD_H
#include "ogs-sbi.h"
#include "context.h"
#ifdef __cplusplus
extern "C" {
#endif
OpenAPI_nf_profile_t *ogs_sbi_nnrf_build_nf_profile(
ogs_sbi_nf_instance_t *nf_instance);
void ogs_sbi_nnrf_free_nf_profile(OpenAPI_nf_profile_t *NFProfile);
#ifdef __cplusplus
}
#endif
#endif /* OGS_NNRF_BUILD_H */

184
lib/sbi/nnrf-handler.c Normal file
View File

@ -0,0 +1,184 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "nnrf-handler.h"
bool ogs_sbi_nnrf_handle_nf_profile(ogs_sbi_nf_instance_t *nf_instance,
OpenAPI_nf_profile_t *NFProfile,
ogs_sbi_session_t *session, ogs_sbi_message_t *message)
{
int rv;
OpenAPI_lnode_t *node;
ogs_assert(nf_instance);
ogs_assert(NFProfile);
if (!NFProfile) {
ogs_error("No NFProfile");
if (session)
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
message, "No NFProfile", NULL);
return false;
}
if (!NFProfile->nf_instance_id) {
ogs_error("No NFProfile.NFInstanceId");
if (session)
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
message, "NFProfile", "No NFInstanceId");
return false;
}
if (!NFProfile->nf_type) {
ogs_error("No NFProfile.NFType");
if (session)
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
message, "NFProfile", "No NFType");
return false;
}
if (!NFProfile->nf_status) {
ogs_error("No NFProfile.NFStatus");
if (session)
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
message, "NFProfile", "No NFStatus");
return false;
}
ogs_sbi_nf_instance_clear(nf_instance);
nf_instance->nf_type = NFProfile->nf_type;
nf_instance->nf_status = NFProfile->nf_status;
nf_instance->time.heartbeat = NFProfile->heart_beat_timer;
if (NFProfile->fqdn)
ogs_fqdn_parse(nf_instance->fqdn,
NFProfile->fqdn, strlen(NFProfile->fqdn));
/* Only one time handles RegisterNFInstance operation */
OpenAPI_list_for_each(NFProfile->ipv4_addresses, node) {
ogs_sockaddr_t *addr = NULL;
if (!node->data) continue;
if (nf_instance->num_of_ipv4 < OGS_SBI_MAX_NUM_OF_IP_ADDRESS) {
rv = ogs_getaddrinfo(&addr, AF_UNSPEC,
node->data, OGS_SBI_HTTPS_PORT, 0);
if (rv != OGS_OK) continue;
nf_instance->ipv4[nf_instance->num_of_ipv4] = addr;
nf_instance->num_of_ipv4++;
}
}
OpenAPI_list_for_each(NFProfile->ipv6_addresses, node) {
ogs_sockaddr_t *addr = NULL;
if (!node->data) continue;
if (nf_instance->num_of_ipv6 < OGS_SBI_MAX_NUM_OF_IP_ADDRESS) {
rv = ogs_getaddrinfo(&addr, AF_UNSPEC,
node->data, OGS_SBI_HTTPS_PORT, 0);
if (rv != OGS_OK) continue;
nf_instance->ipv6[nf_instance->num_of_ipv6] = addr;
nf_instance->num_of_ipv6++;
}
}
OpenAPI_list_for_each(NFProfile->nf_services, node) {
OpenAPI_nf_service_t *NFService = node->data;
OpenAPI_list_t *VersionList = NULL;
OpenAPI_list_t *IpEndPointList = NULL;
OpenAPI_lnode_t *node2 = NULL;
ogs_sbi_nf_service_t *nf_service = NULL;
if (!NFService) continue;
VersionList = NFService->versions;
IpEndPointList = NFService->ip_end_points;
nf_service = ogs_sbi_nf_service_add(nf_instance,
NFService->service_instance_id,
NFService->service_name, NFService->scheme);
ogs_assert(nf_service);
OpenAPI_list_for_each(VersionList, node2) {
OpenAPI_nf_service_version_t *NFServiceVersion = node2->data;
if (!NFServiceVersion) continue;
ogs_sbi_nf_service_add_version(nf_service,
NFServiceVersion->api_version_in_uri,
NFServiceVersion->api_full_version,
NFServiceVersion->expiry);
}
if (NFService->fqdn)
ogs_fqdn_parse(nf_service->fqdn,
NFService->fqdn, strlen(NFService->fqdn));
nf_service->num_of_addr = 0;
OpenAPI_list_for_each(IpEndPointList, node2) {
OpenAPI_ip_end_point_t *IpEndPoint = node2->data;
ogs_sockaddr_t *addr = NULL, *addr6 = NULL;
int port = 0;
if (!IpEndPoint) continue;
if (nf_service->num_of_addr < OGS_SBI_MAX_NUM_OF_IP_ADDRESS) {
port = IpEndPoint->port;
if (!port) {
if (nf_service->scheme == OpenAPI_uri_scheme_http)
port = OGS_SBI_HTTP_PORT;
else if (nf_service->scheme == OpenAPI_uri_scheme_https)
port = OGS_SBI_HTTPS_PORT;
else
continue;
}
if (IpEndPoint->ipv4_address) {
rv = ogs_getaddrinfo(&addr, AF_UNSPEC,
IpEndPoint->ipv4_address, port, 0);
if (rv != OGS_OK) continue;
}
if (IpEndPoint->ipv6_address) {
rv = ogs_getaddrinfo(&addr6, AF_UNSPEC,
IpEndPoint->ipv6_address, port, 0);
if (rv != OGS_OK) continue;
}
if (addr || addr6) {
nf_service->addr[nf_service->num_of_addr].
port = port;
nf_service->addr[nf_service->num_of_addr].
ipv4 = addr;
nf_service->addr[nf_service->num_of_addr].
ipv6 = addr6;
}
nf_service->num_of_addr++;
}
}
}
return true;
}

38
lib/sbi/nnrf-handler.h Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef OGS_NNRF_HANDLER_H
#define OGS_NNRF_HANDLER_H
#include "ogs-sbi.h"
#include "context.h"
#ifdef __cplusplus
extern "C" {
#endif
bool ogs_sbi_nnrf_handle_nf_profile(ogs_sbi_nf_instance_t *nf_instance,
OpenAPI_nf_profile_t *NFProfile,
ogs_sbi_session_t *session, ogs_sbi_message_t *message);
#ifdef __cplusplus
}
#endif
#endif /* OGS_NNRF_HANDLER_H */

72
lib/sbi/ogs-sbi.h Normal file
View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef OGS_SBI_H
#define OGS_SBI_H
#include "ogs-core.h"
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
#endif
#include "model/nf_profile.h"
#include "model/nf_group_cond.h"
#include "model/smf_info.h"
#include "model/problem_details.h"
#include "model/patch_item.h"
#include "model/subscription_data.h"
#include "model/notification_data.h"
#include "model/search_result.h"
#include "custom/links.h"
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
#define OGS_SBI_INSIDE
#include "sbi/conv.h"
#include "sbi/message.h"
#include "sbi/server.h"
#include "sbi/client.h"
#include "sbi/context.h"
#include "sbi/nnrf-build.h"
#include "sbi/nnrf-handler.h"
#undef OGS_SBI_INSIDE
#ifdef __cplusplus
extern "C" {
#endif
extern int __ogs_sbi_domain;
#undef OGS_LOG_DOMAIN
#define OGS_LOG_DOMAIN __ogs_sbi_domain
#ifdef __cplusplus
}
#endif
#endif /* OGS_SBI_H */

View File

@ -0,0 +1,16 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
api/**
include/apiClient.h
src/apiClient.c
src/binary.c
unit-test/**
README.md
libcurl.licence
uncrustify-rules.cfg
CMakeLists.txt

View File

@ -0,0 +1 @@
4.3.1-SNAPSHOT

View File

@ -0,0 +1,6 @@
enablePostProcessFile: true
templateDir: "../openapi/.openapi-generator/templates"
reservedWordMappings:
3GPP_ACCESS: "3GPP_ACCESS"
5G_EIR: "5G_EIR"
5GMM: "5GMM"

View File

@ -0,0 +1,23 @@
#include <stdlib.h>
#include <string.h>
#include "../include/keyValuePair.h"
OpenAPI_map_t *OpenAPI_map_create(char *key, void *value)
{
OpenAPI_map_t *OpenAPI_map = ogs_malloc(sizeof(OpenAPI_map_t));
OpenAPI_map->key = key;
OpenAPI_map->value = value;
return OpenAPI_map;
}
OpenAPI_map_t *OpenAPI_map_create_allocate(char *key, double value)
{
double* boolpointer = ogs_malloc(sizeof(value));
memcpy(boolpointer, &value, sizeof(value));
return OpenAPI_map_create(key, boolpointer);
}
void OpenAPI_map_free(OpenAPI_map_t *OpenAPI_map)
{
ogs_free(OpenAPI_map);
}

View File

@ -0,0 +1,65 @@
#include <stdlib.h>
#include <string.h>
#include "../include/binary.h"
#ifdef OPENSSL
#include "openssl/pem.h"
#endif
OpenAPI_binary_t *OpenAPI_instantiate_binary_t(char *data, int len)
{
binary_t* ret = malloc(sizeof(struct binary_t));
ret->len=len;
ret->data = malloc(len);
memcpy(ret->data, data, len);
return ret;
}
char *OpenAPI_base64encode(const void *b64_encode_this,
int encode_this_many_bytes)
{
#ifdef OPENSSL
BIO *b64_bio, *mem_bio; //Declares two OpenSSL BIOs: a base64 filter and a memory BIO.
BUF_MEM *mem_bio_mem_ptr; //Pointer to a "memory BIO" structure holding our base64 data.
b64_bio = BIO_new(BIO_f_base64()); //Initialize our base64 filter BIO.
mem_bio = BIO_new(BIO_s_mem()); //Initialize our memory sink BIO.
BIO_push(b64_bio, mem_bio); //Link the BIOs by creating a filter-sink BIO chain.
BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL); //No newlines every 64 characters or less.
BIO_write(b64_bio, b64_encode_this, encode_this_many_bytes); //Records base64 encoded data.
BIO_flush(b64_bio); //Flush data. Necessary for b64 encoding, because of pad characters.
BIO_get_mem_ptr(mem_bio, &mem_bio_mem_ptr); //Store address of mem_bio's memory structure.
BIO_set_close(mem_bio, BIO_NOCLOSE); //Permit access to mem_ptr after BIOs are destroyed.
BIO_free_all(b64_bio); //Destroys all BIOs in chain, starting with b64 (i.e. the 1st one).
BUF_MEM_grow(mem_bio_mem_ptr, (*mem_bio_mem_ptr).length + 1); //Makes space for end null.
(*mem_bio_mem_ptr).data[(*mem_bio_mem_ptr).length] = '\0'; //Adds null-terminator to tail.
return (*mem_bio_mem_ptr).data; //Returns base-64 encoded data. (See: "buf_mem_st" struct).
#else // OPENSSL
#warning Data will not be encoded. If you want to use function "base64encode", please define "-DOPENSSL" when building the library.
return NULL;
#endif // OPENSSL
}
char *OpenAPI_base64decode(const void *b64_decode_this,
int decode_this_many_bytes, int *decoded_bytes)
{
#ifdef OPENSSL
BIO *b64_bio, *mem_bio; //Declares two OpenSSL BIOs: a base64 filter and a memory BIO.
char *base64_decoded = calloc( (decode_this_many_bytes*3)/4+1, sizeof(char) ); //+1 = null.
b64_bio = BIO_new(BIO_f_base64()); //Initialize our base64 filter BIO.
mem_bio = BIO_new(BIO_s_mem()); //Initialize our memory source BIO.
BIO_write(mem_bio, b64_decode_this, decode_this_many_bytes); //Base64 data saved in source.
BIO_push(b64_bio, mem_bio); //Link the BIOs by creating a filter-source BIO chain.
BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines.
int decoded_byte_index = 0; //Index where the next base64_decoded byte should be written.
while ( 0 < BIO_read(b64_bio, base64_decoded+decoded_byte_index, 1) ){ //Read byte-by-byte.
decoded_byte_index++; //Increment the index until read of BIO decoded data is complete.
} //Once we're done reading decoded data, BIO_read returns -1 even though there's no error.
BIO_free_all(b64_bio); //Destroys all BIOs in chain, starting with b64 (i.e. the 1st one).
*decoded_bytes = decoded_byte_index;
return base64_decoded; //Returns base-64 decoded data with trailing null terminator.
#else // OPENSSL
#warning Data will not be decoded. If you want to use function "base64decode", please define "-DOPENSSL" when building the library.
return NULL;
#endif // OPENSSL
}

View File

@ -0,0 +1,27 @@
#ifndef OGS_SBI_BINARY_H
#define OGS_SBI_BINARY_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OpenAPI_binary_s {
uint8_t* data;
unsigned int len;
} OpenAPI_binary_t;
OpenAPI_binary_t *OpenAPI_instantiate_binary_t(char *data, int len);
char *OpenAPI_base64encode(const void *b64_encode_this,
int encode_this_many_bytes);
char *OpenAPI_base64decode(const void *b64_decode_this,
int decode_this_many_bytes, int *decoded_bytes);
#ifdef __cplusplus
}
#endif
#endif // OGS_SBI_BINARY_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,277 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 7
#include <stddef.h>
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
typedef struct cJSON_Hooks
{
void *(*malloc_fn)(size_t sz);
void (*free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 2 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type __stdcall
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type __stdcall
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall
#endif
#else /* !WIN32 */
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
/* Supply malloc, realloc and free functions to cJSON */
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check if the item is a string and return its valuestring */
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/arrray that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items. */
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detatch items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
need to be released. With recurse!=0, it will duplicate any children connected to the item.
The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,25 @@
#ifndef OGS_SBI_MAP_H
#define OGS_SBI_MAP_H
#include "ogs-core.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OpenAPI_map_s {
char *key;
void *value;
} OpenAPI_map_t;
OpenAPI_map_t *OpenAPI_map_create(char *key, void *value);
OpenAPI_map_t *OpenAPI_map_create_allocate(char *key, double value);
void OpenAPI_map_free(OpenAPI_map_t *OpenAPI_map);
#ifdef __cplusplus
}
#endif
#endif /* OGS_SBI_MAP_H */

View File

@ -0,0 +1,169 @@
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include "../include/list.h"
static OpenAPI_lnode_t *listEntry_create(void *data)
{
OpenAPI_lnode_t *created = ogs_malloc(sizeof(OpenAPI_lnode_t));
if (created == NULL) {
// TODO Malloc Failure
return NULL;
}
created->data = data;
return created;
}
void OpenAPI_lnode_free(OpenAPI_lnode_t *listEntry, void *additionalData)
{
ogs_free(listEntry);
}
void OpenAPI_lnode_print(OpenAPI_lnode_t *listEntry, void *additionalData)
{
printf("%i\n", *((int *) (listEntry->data)));
}
OpenAPI_list_t *OpenAPI_list_create(void)
{
OpenAPI_list_t *createdList = ogs_malloc(sizeof(OpenAPI_list_t));
if (createdList == NULL) {
// TODO Malloc Failure
return NULL;
}
createdList->first = NULL;
createdList->last = NULL;
createdList->count = 0;
return createdList;
}
void OpenAPI_list_iterate_forward(OpenAPI_list_t *list,
void (*operationToPerform)(
OpenAPI_lnode_t *, void *callbackFunctionUsedData),
void *additionalDataNeededForCallbackFunction)
{
OpenAPI_lnode_t *current = list->first;
OpenAPI_lnode_t *next;
if (current == NULL) {
return;
}
next = current->next;
operationToPerform(current, additionalDataNeededForCallbackFunction);
current = next;
while (current != NULL) {
next = current->next;
operationToPerform(current, additionalDataNeededForCallbackFunction);
current = next;
}
}
void OpenAPI_list_iterate_backward(OpenAPI_list_t *list,
void (*operationToPerform)(
OpenAPI_lnode_t *, void *callbackFunctionUsedData),
void *additionalDataNeededForCallbackFunction)
{
OpenAPI_lnode_t *current = list->last;
OpenAPI_lnode_t *next = current->prev;
if (current == NULL) {
return;
}
operationToPerform(current, additionalDataNeededForCallbackFunction);
current = next;
while (current != NULL) {
next = current->prev;
operationToPerform(current, additionalDataNeededForCallbackFunction);
current = next;
}
}
void OpenAPI_list_free(OpenAPI_list_t *list)
{
if (list){
OpenAPI_list_iterate_forward(list, OpenAPI_lnode_free, NULL);
ogs_free(list);
}
}
void OpenAPI_list_add(OpenAPI_list_t *list, void *dataToAddInList)
{
OpenAPI_lnode_t *newListEntry = listEntry_create(dataToAddInList);
if (newListEntry == NULL) {
// TODO Malloc Failure
return;
}
if (list->first == NULL) {
list->first = newListEntry;
list->last = newListEntry;
newListEntry->prev = NULL;
newListEntry->next = NULL;
list->count++;
return;
}
list->last->next = newListEntry;
newListEntry->prev = list->last;
newListEntry->next = NULL;
list->last = newListEntry;
list->count++;
}
void OpenAPI_list_remove(OpenAPI_list_t *list, OpenAPI_lnode_t *elementToRemove)
{
OpenAPI_lnode_t *elementBeforeElementToRemove = elementToRemove->prev;
OpenAPI_lnode_t *elementAfterElementToRemove = elementToRemove->next;
if (elementBeforeElementToRemove != NULL) {
elementBeforeElementToRemove->next = elementAfterElementToRemove;
} else {
list->first = elementAfterElementToRemove;
}
if (elementAfterElementToRemove != NULL) {
elementAfterElementToRemove->prev = elementBeforeElementToRemove;
} else {
list->last = elementBeforeElementToRemove;
}
OpenAPI_lnode_free(elementToRemove, NULL);
list->count--;
}
OpenAPI_lnode_t *OpenAPI_list_find(OpenAPI_list_t *list, long indexOfElement)
{
OpenAPI_lnode_t *current;
int i;
if ((list->count / 2) > indexOfElement) {
current = list->first;
for(i = 0; i < indexOfElement; i++) {
current = current->next;
}
return current;
} else {
current = list->last;
for(i = 1; i < (list->count - indexOfElement); i++) {
current = current->prev;
}
return current;
}
}

View File

@ -0,0 +1,54 @@
#ifndef OGS_SBI_LIST_H
#define OGS_SBI_LIST_H
#include "../external/cJSON.h"
#include "ogs-core.h"
#ifdef __cplusplus
extern "C" {
#endif
#define OpenAPI_malloc(__sIZE) __sIZE == 0 ? NULL : ogs_malloc(__sIZE)
typedef struct OpenAPI_list_s OpenAPI_list_t;
typedef struct OpenAPI_lnode_s OpenAPI_lnode_t;
struct OpenAPI_lnode_s {
OpenAPI_lnode_t *next;
OpenAPI_lnode_t *prev;
void *data;
};
typedef struct OpenAPI_list_s {
OpenAPI_lnode_t *first;
OpenAPI_lnode_t *last;
long count;
} OpenAPI_list_t;
#define OpenAPI_list_for_each(list, element) for(element = (list != NULL) ? (list)->first : NULL; element != NULL; element = element->next)
OpenAPI_list_t *OpenAPI_list_create(void);
void OpenAPI_list_free(OpenAPI_list_t *listToFree);
void OpenAPI_list_add(OpenAPI_list_t *list, void *dataToAddInList);
OpenAPI_lnode_t *OpenAPI_list_find(OpenAPI_list_t *list, long indexOfElement);
void OpenAPI_list_remove(
OpenAPI_list_t *list, OpenAPI_lnode_t *elementToRemove);
void OpenAPI_list_iterate_forward(OpenAPI_list_t *list,
void (*operationToPerform)(OpenAPI_lnode_t*, void*),
void *additionalDataNeededForCallbackFunction);
void OpenAPI_list_iterate_backward(OpenAPI_list_t *list,
void (*operationToPerform)(OpenAPI_lnode_t*, void*),
void *additionalDataNeededForCallbackFunction);
void OpenAPI_lnode_print(OpenAPI_lnode_t *listEntry, void *additionalData);
void OpenAPI_lnode_free(OpenAPI_lnode_t *listEntry, void *additionalData);
#ifdef __cplusplus
}
#endif
#endif // OGS_SBI_LIST_H

View File

@ -0,0 +1,776 @@
{{#models}}{{#model}}
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "{{classname}}.h"
{{#isEnum}}
char* OpenAPI_{{classname}}_ToString(OpenAPI_{{classVarName}}_e {{classname}})
{
const char *{{classname}}Array[] = { "NULL"{{#allowableValues}}{{#enumVars}}, "{{{value}}}"{{/enumVars}}{{/allowableValues}} };
size_t sizeofArray = sizeof({{classname}}Array) / sizeof({{classname}}Array[0]);
if ({{classname}} < sizeofArray)
return (char *){{classname}}Array[{{classname}}];
else
return (char *)"Unknown";
}
OpenAPI_{{classVarName}}_e OpenAPI_{{classname}}_FromString(char* {{classname}})
{
int stringToReturn = 0;
const char *{{classname}}Array[] = { "NULL"{{#allowableValues}}{{#enumVars}}, "{{{value}}}"{{/enumVars}}{{/allowableValues}} };
size_t sizeofArray = sizeof({{classname}}Array) / sizeof({{classname}}Array[0]);
while (stringToReturn < sizeofArray) {
if (strcmp({{classname}}, {{classname}}Array[stringToReturn]) == 0) {
return stringToReturn;
}
stringToReturn++;
}
return 0;
}
{{/isEnum}}
{{^isEnum}}
{{#vars}}
{{^isContainer}}
{{#isPrimitiveType}}
{{#isEnum}}
char *OpenAPI_{{name}}{{classname}}_ToString(OpenAPI_{{classVarName}}_{{name}}_e {{name}})
{
const char *{{name}}Array[] = { "NULL"{{#allowableValues}}{{#enumVars}}, "{{{value}}}"{{/enumVars}}{{/allowableValues}} };
size_t sizeofArray = sizeof({{name}}Array) / sizeof({{name}}Array[0]);
if ({{name}} < sizeofArray)
return (char *){{name}}Array[{{name}}];
else
return (char *)"Unknown";
}
OpenAPI_{{classVarName}}_{{name}}_e OpenAPI_{{name}}{{classname}}_FromString(char* {{name}})
{
int stringToReturn = 0;
const char *{{name}}Array[] = { "NULL"{{#allowableValues}}{{#enumVars}}, "{{{value}}}"{{/enumVars}}{{/allowableValues}} };
size_t sizeofArray = sizeof({{name}}Array) / sizeof({{name}}Array[0]);
while (stringToReturn < sizeofArray) {
if (strcmp({{name}}, {{name}}Array[stringToReturn]) == 0) {
return stringToReturn;
}
stringToReturn++;
}
return 0;
}
{{/isEnum}}
{{/isPrimitiveType}}
{{/isContainer}}
{{/vars}}
OpenAPI_{{classname}}_t *OpenAPI_{{classname}}_create(
{{#vars}}
{{^isContainer}}
{{^isPrimitiveType}}
{{#isEnum}}
OpenAPI_{{datatype}}_e {{name}}{{#hasMore}},{{/hasMore}}
{{/isEnum}}
{{^isEnum}}
{{#isModel}}
OpenAPI_{{datatype}}_t *{{name}}{{#hasMore}},{{/hasMore}}
{{/isModel}}
{{#isUuid}}
{{datatype}} *{{name}}{{#hasMore}},{{/hasMore}}
{{/isUuid}}
{{#isEmail}}
{{datatype}} *{{name}}{{#hasMore}},{{/hasMore}}
{{/isEmail}}
{{#isFreeFormObject}}
OpenAPI_{{datatype}}_t *{{name}}{{#hasMore}},{{/hasMore}}
{{/isFreeFormObject}}
{{/isEnum}}
{{/isPrimitiveType}}
{{#isPrimitiveType}}
{{#isEnum}}
OpenAPI_{{classVarName}}_{{name}}_e {{name}}{{#hasMore}},{{/hasMore}}
{{/isEnum}}
{{^isEnum}}
{{#isNumeric}}
{{datatype}} {{name}}{{#hasMore}},{{/hasMore}}
{{/isNumeric}}
{{#isBoolean}}
{{datatype}} {{name}}{{#hasMore}},{{/hasMore}}
{{/isBoolean}}
{{#isString}}
{{datatype}} *{{name}}{{#hasMore}},{{/hasMore}}
{{/isString}}
{{/isEnum}}
{{#isByteArray}}
{{datatype}} {{name}}{{#hasMore}},{{/hasMore}}
{{/isByteArray}}
{{#isBinary}}
OpenAPI_{{datatype}} {{name}}{{#hasMore}},{{/hasMore}}
{{/isBinary}}
{{#isDate}}
{{datatype}} *{{name}}{{#hasMore}},{{/hasMore}}
{{/isDate}}
{{#isDateTime}}
{{datatype}} *{{name}}{{#hasMore}},{{/hasMore}}
{{/isDateTime}}
{{/isPrimitiveType}}
{{/isContainer}}
{{#isContainer}}
{{#isListContainer}}
OpenAPI_{{datatype}}_t *{{name}}{{#hasMore}},{{/hasMore}}
{{/isListContainer}}
{{#isMapContainer}}
OpenAPI_{{datatype}} {{name}}{{#hasMore}},{{/hasMore}}
{{/isMapContainer}}
{{/isContainer}}
{{/vars}})
{
OpenAPI_{{classname}}_t *{{classname}}_local_var = OpenAPI_malloc(sizeof(OpenAPI_{{classname}}_t));
if (!{{classname}}_local_var) {
return NULL;
}
{{#vars}}
{{classname}}_local_var->{{{name}}} = {{{name}}};
{{/vars}}
return {{classname}}_local_var;
}
void OpenAPI_{{classname}}_free(OpenAPI_{{classname}}_t *{{classname}})
{
if (NULL == {{classname}}) {
return ;
}
OpenAPI_lnode_t *node;
{{#vars}}
{{^isContainer}}
{{^isPrimitiveType}}
{{^isEnum}}
{{#isModel}}
OpenAPI_{{{complexType}}}_free({{{classname}}}->{{{name}}});
{{/isModel}}
{{#isUuid}}
ogs_free({{{classname}}}->{{{name}}});
{{/isUuid}}
{{#isEmail}}
ogs_free({{{classname}}}->{{{name}}});
{{/isEmail}}
{{#isFreeFormObject}}
OpenAPI_object_free({{{classname}}}->{{{name}}});
{{/isFreeFormObject}}
{{/isEnum}}
{{/isPrimitiveType}}
{{#isPrimitiveType}}
{{^isEnum}}
{{#isString}}
ogs_free({{{classname}}}->{{{name}}});
{{/isString}}
{{/isEnum}}
{{#isBinary}}
ogs_free({{{classname}}}->{{{name}}}->data);
{{/isBinary}}
{{#isDate}}
ogs_free({{{classname}}}->{{{name}}});
{{/isDate}}
{{#isDateTime}}
ogs_free({{{classname}}}->{{{name}}});
{{/isDateTime}}
{{/isPrimitiveType}}
{{/isContainer}}
{{#isContainer}}
{{#isListContainer}}
{{#isPrimitiveType}}
{{^isEnum}}
OpenAPI_list_for_each({{classname}}->{{name}}, node) {
ogs_free(node->data);
}
{{/isEnum}}
OpenAPI_list_free({{classname}}->{{name}});
{{/isPrimitiveType}}
{{^isPrimitiveType}}
{{^isEnum}}
OpenAPI_list_for_each({{classname}}->{{name}}, node) {
OpenAPI_{{complexType}}_free(node->data);
}
{{/isEnum}}
OpenAPI_list_free({{classname}}->{{name}});
{{/isPrimitiveType}}
{{/isListContainer}}
{{#isMapContainer}}
OpenAPI_list_for_each({{classname}}->{{name}}, node) {
OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)node->data;
OpenAPI_{{complexType}}_free(localKeyValue->value);
ogs_free(localKeyValue);
}
OpenAPI_list_free({{classname}}->{{name}});
{{/isMapContainer}}
{{/isContainer}}
{{/vars}}
ogs_free({{classname}});
}
cJSON *OpenAPI_{{classname}}_convertToJSON(OpenAPI_{{classname}}_t *{{classname}})
{
cJSON *item = NULL;
if ({{classname}} == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
return NULL;
}
item = cJSON_CreateObject();
{{#vars}}
{{#required}}
if (!{{{classname}}}->{{{name}}}) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/required}}
{{^required}}
if ({{{classname}}}->{{{name}}}) {
{{/required}}
{{^isContainer}}
{{#isPrimitiveType}}
{{#isEnum}}
if (cJSON_AddStringToObject(item, "{{{baseName}}}", OpenAPI_{{{name}}}{{classname}}_ToString({{{classname}}}->{{{name}}})) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isEnum}}
{{^isEnum}}
{{#isNumeric}}
if (cJSON_AddNumberToObject(item, "{{{baseName}}}", {{{classname}}}->{{{name}}}) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isNumeric}}
{{#isBoolean}}
if (cJSON_AddBoolToObject(item, "{{{baseName}}}", {{{classname}}}->{{{name}}}) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isBoolean}}
{{#isString}}
if (cJSON_AddStringToObject(item, "{{{baseName}}}", {{{classname}}}->{{{name}}}) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isString}}
{{/isEnum}}
{{#isByteArray}}
if (cJSON_AddNumberToObject(item, "{{{baseName}}}", {{{classname}}}->{{{name}}}) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isByteArray}}
{{#isBinary}}
char* encoded_str_{{{name}}} = OpenAPI_base64encode({{{classname}}}->{{{name}}}->data,{{{classname}}}->{{{name}}}->len);
if (cJSON_AddStringToObject(item, "{{{baseName}}}", encoded_str_{{{name}}}) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
ogs_free(encoded_str_{{{name}}});
{{/isBinary}}
{{#isDate}}
if (cJSON_AddStringToObject(item, "{{{baseName}}}", {{{classname}}}->{{{name}}}) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isDate}}
{{#isDateTime}}
if (cJSON_AddStringToObject(item, "{{{baseName}}}", {{{classname}}}->{{{name}}}) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isDateTime}}
{{/isPrimitiveType}}
{{^isPrimitiveType}}
{{#isEnum}}
if (cJSON_AddStringToObject(item, "{{{baseName}}}", OpenAPI_{{{complexType}}}_ToString({{{classname}}}->{{{name}}})) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isEnum}}
{{^isEnum}}
{{#isModel}}
cJSON *{{{name}}}_local_JSON = OpenAPI_{{complexType}}{{#isFreeFormObject}}object{{/isFreeFormObject}}_convertToJSON({{{classname}}}->{{{name}}});
if ({{{name}}}_local_JSON == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
cJSON_AddItemToObject(item, "{{{baseName}}}", {{{name}}}_local_JSON);
if (item->child == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isModel}}
{{#isUuid}}
if (cJSON_AddStringToObject(item, "{{{baseName}}}", {{{classname}}}->{{{name}}}) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isUuid}}
{{#isEmail}}
if (cJSON_AddStringToObject(item, "{{{baseName}}}", {{{classname}}}->{{{name}}}) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isEmail}}
{{#isFreeFormObject}}
cJSON *{{{name}}}_object = OpenAPI_object_convertToJSON({{{classname}}}->{{{name}}});
if ({{{name}}}_object == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
cJSON_AddItemToObject(item, "{{{baseName}}}", {{{name}}}_object);
if (item->child == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isFreeFormObject}}
{{/isEnum}}
{{/isPrimitiveType}}
{{/isContainer}}
{{#isContainer}}
{{#isListContainer}}
{{#isPrimitiveType}}
{{^isEnum}}
cJSON *{{{name}}} = cJSON_AddArrayToObject(item, "{{{baseName}}}");
if ({{{name}}} == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
OpenAPI_lnode_t *{{{name}}}_node;
OpenAPI_list_for_each({{{classname}}}->{{{name}}}, {{{name}}}_node) {
{{#items}}
{{#isString}}
if (cJSON_AddStringToObject({{{name}}}, "", (char*){{{name}}}_node->data) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isString}}
{{#isBoolean}}
if (cJSON_AddBoolToObject({{{name}}}, "", *(cJSON_bool *){{{name}}}_node->data) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isBoolean}}
{{#isNumeric}}
if (cJSON_AddNumberToObject({{{name}}}, "", *(double *){{{name}}}_node->data) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isNumeric}}
{{/items}}
}
{{/isEnum}}
{{/isPrimitiveType}}
{{^isPrimitiveType}}
{{^isEnum}}
cJSON *{{{name}}}List = cJSON_AddArrayToObject(item, "{{{baseName}}}");
if ({{{name}}}List == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
OpenAPI_lnode_t *{{{name}}}_node;
if ({{{classname}}}->{{{name}}}) {
OpenAPI_list_for_each({{classname}}->{{{name}}}, {{{name}}}_node) {
cJSON *itemLocal = OpenAPI_{{complexType}}_convertToJSON({{#isEnum}}{{#items}}(OpenAPI_{{classVarName}}_{{name}}_e){{/items}}{{/isEnum}}{{{name}}}_node->data);
if (itemLocal == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
cJSON_AddItemToArray({{{name}}}List, itemLocal);
}
}
{{/isEnum}}
{{#isEnum}}
cJSON *{{{name}}} = cJSON_AddArrayToObject(item, "{{{baseName}}}");
if ({{{name}}} == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
OpenAPI_lnode_t *{{{name}}}_node;
OpenAPI_list_for_each({{classname}}->{{{name}}}, {{{name}}}_node) {
if (cJSON_AddStringToObject({{{name}}}, "", OpenAPI_{{{complexType}}}_ToString((OpenAPI_{{{complexType}}}_e){{{name}}}_node->data)) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
}
{{/isEnum}}
{{/isPrimitiveType}}
{{/isListContainer}}
{{#isMapContainer}}
cJSON *{{{name}}} = cJSON_AddObjectToObject(item, "{{{baseName}}}");
if ({{{name}}} == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
cJSON *localMapObject = {{{name}}};
OpenAPI_lnode_t *{{{name}}}_node;
if ({{{classname}}}->{{{name}}}) {
OpenAPI_list_for_each({{{classname}}}->{{{name}}}, {{{name}}}_node) {
OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*){{{name}}}_node->data;
{{#isPrimitiveType}}
{{#isString}}
if (cJSON_AddStringToObject(localMapObject, localKeyValue->key, (char*)localKeyValue->value) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isString}}
{{#isNumeric}}
if (cJSON_AddNumberToObject(localMapObject, localKeyValue->key, *(double *)localKeyValue->value) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isNumeric}}
{{#isBoolean}}
if (cJSON_AddBoolToObject(localMapObject, localKeyValue->key, *(cJSON_bool *)localKeyValue->value) == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
{{/isBoolean}}
{{/isPrimitiveType}}
{{^isPrimitiveType}}
cJSON *itemLocal = OpenAPI_{{complexType}}_convertToJSON(localKeyValue->value);
if (itemLocal == NULL) {
ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]");
goto end;
}
cJSON_AddItemToObject({{{name}}}, localKeyValue->key, itemLocal);
{{/isPrimitiveType}}
}
}
{{/isMapContainer}}
{{/isContainer}}
{{^required}}
}
{{/required}}
{{/vars}}
end:
return item;
}
OpenAPI_{{classname}}_t *OpenAPI_{{classname}}_parseFromJSON(cJSON *{{classname}}JSON)
{
OpenAPI_{{classname}}_t *{{classname}}_local_var = NULL;
{{#vars}}
cJSON *{{{name}}} = cJSON_GetObjectItemCaseSensitive({{classname}}JSON, "{{{baseName}}}");
{{#required}}
if (!{{{name}}}) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{/required}}
{{^isContainer}}
{{#isPrimitiveType}}
{{#isEnum}}
OpenAPI_{{classVarName}}_{{name}}_e {{name}}Variable;
{{^required}}if ({{{name}}}) { {{/required}}
if (!cJSON_IsString({{{name}}})) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{name}}Variable = OpenAPI_{{name}}{{classname}}_FromString({{{name}}}->valuestring);
{{/isEnum}}
{{^isEnum}}
{{#isNumeric}}
{{^required}}if ({{{name}}}) { {{/required}}
if (!cJSON_IsNumber({{{name}}})) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{/isNumeric}}
{{#isBoolean}}
{{^required}}if ({{{name}}}) { {{/required}}
if (!cJSON_IsBool({{{name}}})) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{/isBoolean}}
{{#isString}}
{{^required}}if ({{{name}}}) { {{/required}}
if (!cJSON_IsString({{{name}}})) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{/isString}}
{{/isEnum}}
{{#isByteArray}}
{{^required}}if ({{{name}}}) { {{/required}}
if (!cJSON_IsNumber({{{name}}})) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{/isByteArray}}
{{#isBinary}}
OpenAPI_binary_t* decoded_str_{{{name}}} = OpenAPI_malloc(sizeof(struct binary_t));
{{^required}}if ({{{name}}}) { {{/required}}
if (!cJSON_IsString({{{name}}})) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
decoded_str_{{{name}}}->data = OpenAPI_base64decode({{{name}}}->valuestring, strlen({{{name}}}->valuestring), &decoded_str_{{{name}}}->len);
if (!decoded_str_{{{name}}}->data) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{/isBinary}}
{{#isDate}}
{{^required}}if ({{{name}}}) { {{/required}}
if (!cJSON_IsString({{{name}}})) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{/isDate}}
{{#isDateTime}}
{{^required}}if ({{{name}}}) { {{/required}}
if (!cJSON_IsString({{{name}}})) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{/isDateTime}}
{{/isPrimitiveType}}
{{^isPrimitiveType}}
{{#isEnum}}
OpenAPI_{{complexType}}_e {{name}}Variable;
{{^required}}if ({{{name}}}) { {{/required}}
if (!cJSON_IsString({{{name}}})) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{name}}Variable = OpenAPI_{{complexType}}_FromString({{{name}}}->valuestring);
{{/isEnum}}
{{^isEnum}}
{{#isModel}}
{{^isFreeFormObject}}OpenAPI_{{complexType}}{{/isFreeFormObject}}{{#isFreeFormObject}}OpenAPI_object{{/isFreeFormObject}}_t *{{name}}_local_nonprim = NULL;
{{^required}}if ({{{name}}}) { {{/required}}
{{{name}}}_local_nonprim = OpenAPI_{{complexType}}{{#isFreeFormObject}}object{{/isFreeFormObject}}_parseFromJSON({{{name}}});
{{/isModel}}
{{#isUuid}}
{{^required}}if ({{{name}}}) { {{/required}}
if (!cJSON_IsString({{{name}}})) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{/isUuid}}
{{#isEmail}}
{{^required}}if ({{{name}}}) { {{/required}}
if (!cJSON_IsString({{{name}}})) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{/isEmail}}
{{#isFreeFormObject}}
OpenAPI_object_t *{{name}}_local_object = NULL;
{{^required}}if ({{{name}}}) { {{/required}}
{{{name}}}_local_object = OpenAPI_object_parseFromJSON({{{name}}});
{{/isFreeFormObject}}
{{/isEnum}}
{{/isPrimitiveType}}
{{/isContainer}}
{{#isContainer}}
{{#isListContainer}}
{{#isPrimitiveType}}
{{^isEnum}}
OpenAPI_list_t *{{{name}}}List;
{{^required}}if ({{{name}}}) { {{/required}}
cJSON *{{{name}}}_local;
if (!cJSON_IsArray({{{name}}})) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{{name}}}List = OpenAPI_list_create();
cJSON_ArrayForEach({{{name}}}_local, {{{name}}}) {
{{#items}}
{{#isString}}
if (!cJSON_IsString({{{name}}}_local)) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
OpenAPI_list_add({{{name}}}List , ogs_strdup({{{name}}}_local->valuestring));
{{/isString}}
{{#isNumeric}}
if (!cJSON_IsNumber({{{name}}}_local)) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
OpenAPI_list_add({{{name}}}List , &{{{name}}}_local->valuedouble);
{{/isNumeric}}
{{#isBoolean}}
if (!cJSON_IsBool({{{name}}}_local)) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
OpenAPI_list_add({{{name}}}List , {{{name}}}_local->valueint);
{{/isBoolean}}
{{/items}}
}
{{/isEnum}}
{{/isPrimitiveType}}
{{^isPrimitiveType}}
{{^isEnum}}
OpenAPI_list_t *{{{name}}}List;
{{^required}}if ({{{name}}}) { {{/required}}
cJSON *{{{name}}}_local_nonprimitive;
if (!cJSON_IsArray({{{name}}})){
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{{name}}}List = OpenAPI_list_create();
cJSON_ArrayForEach({{{name}}}_local_nonprimitive, {{{name}}} ) {
if (!cJSON_IsObject({{{name}}}_local_nonprimitive)) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{#isEnum}}{{#items}}{{datatypeWithEnum}}_e {{/items}}{{/isEnum}}{{^isEnum}}OpenAPI_{{complexType}}_t *{{/isEnum}}{{{name}}}Item = OpenAPI_{{complexType}}_parseFromJSON({{{name}}}_local_nonprimitive);
OpenAPI_list_add({{{name}}}List, {{#isEnum}}{{#items}}(void *){{/items}}{{/isEnum}}{{{name}}}Item);
}
{{/isEnum}}
{{#isEnum}}
OpenAPI_list_t *{{{name}}}List;
{{^required}}if ({{{name}}}) { {{/required}}
cJSON *{{{name}}}_local_nonprimitive;
if (!cJSON_IsArray({{{name}}})) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{{name}}}List = OpenAPI_list_create();
cJSON_ArrayForEach({{{name}}}_local_nonprimitive, {{{name}}} ) {
if (!cJSON_IsString({{{name}}}_local_nonprimitive)){
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
OpenAPI_list_add({{{name}}}List, (void *)OpenAPI_{{{complexType}}}_FromString({{{name}}}_local_nonprimitive->valuestring));
}
{{/isEnum}}
{{/isPrimitiveType}}
{{/isListContainer}}
{{#isMapContainer}}
OpenAPI_list_t *{{{name}}}List;
{{^required}}if ({{{name}}}) { {{/required}}
cJSON *{{{name}}}_local_map;
if (!cJSON_IsObject({{{name}}})) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
{{{name}}}List = OpenAPI_list_create();
OpenAPI_map_t *localMapKeyPair = NULL;
cJSON_ArrayForEach({{{name}}}_local_map, {{{name}}}) {
cJSON *localMapObject = {{{name}}}_local_map;
{{#isPrimitiveType}}
{{#isString}}
if (!cJSON_IsString(localMapObject)) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
localMapKeyPair = OpenAPI_map_create(ogs_strdup(localMapObject->string),ogs_strdup(localMapObject->valuestring));
{{/isString}}
{{#isBoolean}}
if (!cJSON_IsBool(localMapObject)) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
localMapKeyPair = OpenAPI_map_create(ogs_strdup(localMapObject->string), &localMapObject->valueint);
{{/isBoolean}}
{{#isNumeric}}
if (!cJSON_IsNumber(localMapObject)) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
localMapKeyPair = OpenAPI_map_create(ogs_strdup(localMapObject->string),&localMapObject->valuedouble );
{{/isNumeric}}
{{/isPrimitiveType}}
{{^isPrimitiveType}}
if (!cJSON_IsObject({{{name}}}_local_map)) {
ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]");
goto end;
}
localMapKeyPair = OpenAPI_map_create(
localMapObject->string, OpenAPI_{{complexType}}_parseFromJSON(localMapObject));
{{/isPrimitiveType}}
OpenAPI_list_add({{{name}}}List , localMapKeyPair);
}
{{/isMapContainer}}
{{/isContainer}}
{{^required}}
}
{{/required}}
{{/vars}}
{{classname}}_local_var = OpenAPI_{{classname}}_create (
{{#vars}}
{{^isContainer}}
{{^isPrimitiveType}}
{{#isEnum}}
{{^required}}{{{name}}} ? {{/required}}{{{name}}}Variable{{^required}} : 0{{/required}}{{#hasMore}},{{/hasMore}}
{{/isEnum}}
{{^isEnum}}
{{#isModel}}
{{^required}}{{{name}}} ? {{/required}}{{{name}}}_local_nonprim{{^required}} : NULL{{/required}}{{#hasMore}},{{/hasMore}}
{{/isModel}}
{{#isUuid}}
{{^required}}{{{name}}} ? {{/required}}ogs_strdup({{{name}}}->valuestring){{^required}} : NULL{{/required}}{{#hasMore}},{{/hasMore}}
{{/isUuid}}
{{#isEmail}}
{{^required}}{{{name}}} ? {{/required}}ogs_strdup({{{name}}}->valuestring){{^required}} : NULL{{/required}}{{#hasMore}},{{/hasMore}}
{{/isEmail}}
{{#isFreeFormObject}}
{{^required}}{{{name}}} ? {{/required}}{{{name}}}_local_object{{^required}} : NULL{{/required}}{{#hasMore}},{{/hasMore}}
{{/isFreeFormObject}}
{{/isEnum}}
{{/isPrimitiveType}}
{{#isPrimitiveType}}
{{#isEnum}}
{{^required}}{{{name}}} ? {{/required}}{{name}}Variable{{^required}} : 0{{/required}}{{#hasMore}},{{/hasMore}}
{{/isEnum}}
{{^isEnum}}
{{#isNumeric}}
{{^required}}{{{name}}} ? {{/required}}{{{name}}}->valuedouble{{^required}} : 0{{/required}}{{#hasMore}},{{/hasMore}}
{{/isNumeric}}
{{#isBoolean}}
{{^required}}{{{name}}} ? {{/required}}{{{name}}}->valueint{{^required}} : 0{{/required}}{{#hasMore}},{{/hasMore}}
{{/isBoolean}}
{{#isString}}
{{^required}}{{{name}}} ? {{/required}}ogs_strdup({{{name}}}->valuestring){{^required}} : NULL{{/required}}{{#hasMore}},{{/hasMore}}
{{/isString}}
{{/isEnum}}
{{#isByteArray}}
{{^required}}{{{name}}} ? {{/required}}{{{name}}}->valueint{{^required}} : 0{{/required}}{{#hasMore}},{{/hasMore}}
{{/isByteArray}}
{{#isBinary}}
{{^required}}{{{name}}} ? {{/required}}decoded_str_{{{name}}}{{^required}} : NULL{{/required}}{{#hasMore}},{{/hasMore}}
{{/isBinary}}
{{#isDate}}
{{^required}}{{{name}}} ? {{/required}}ogs_strdup({{{name}}}->valuestring){{^required}} : NULL{{/required}}{{#hasMore}},{{/hasMore}}
{{/isDate}}
{{#isDateTime}}
{{^required}}{{{name}}} ? {{/required}}ogs_strdup({{{name}}}->valuestring){{^required}} : NULL{{/required}}{{#hasMore}},{{/hasMore}}
{{/isDateTime}}
{{/isPrimitiveType}}
{{/isContainer}}
{{#isContainer}}
{{#isListContainer}}
{{^required}}{{{name}}} ? {{/required}}{{{name}}}List{{^required}} : NULL{{/required}}{{#hasMore}},{{/hasMore}}
{{/isListContainer}}
{{#isMapContainer}}
{{^required}}{{{name}}} ? {{/required}}{{{name}}}List{{^required}} : NULL{{/required}}{{#hasMore}},{{/hasMore}}
{{/isMapContainer}}
{{/isContainer}}
{{/vars}}
);
return {{classname}}_local_var;
end:
return NULL;
}
{{/isEnum}}
{{/model}}{{/models}}

View File

@ -0,0 +1,181 @@
{{#models}}{{#model}}/*
* {{classname}}.h
*
* {{description}}
*/
#ifndef _OpenAPI_{{classname}}_H_
#define _OpenAPI_{{classname}}_H_
#include <string.h>
#include "../external/cJSON.h"
#include "../include/list.h"
#include "../include/keyValuePair.h"
#include "../include/binary.h"
{{#imports}}
#include "{{{.}}}.h"
{{/imports}}
#ifdef __cplusplus
extern "C" {
#endif
{{#isEnum}}
{{#allowableValues}}
typedef enum { OpenAPI_{{classVarName}}_NULL = 0{{#enumVars}}, OpenAPI_{{classVarName}}_{{{value}}}{{/enumVars}} } OpenAPI_{{classVarName}}_e;
{{/allowableValues}}
char* OpenAPI_{{classname}}_ToString(OpenAPI_{{classVarName}}_e {{classname}});
OpenAPI_{{classVarName}}_e OpenAPI_{{classname}}_FromString(char* {{classname}});
{{/isEnum}}
{{^isEnum}}
typedef struct OpenAPI_{{classname}}_s OpenAPI_{{classname}}_t;
{{#vars}}
{{^isContainer}}
{{#isPrimitiveType}}
{{#isEnum}}
{{#allowableValues}}
typedef enum { OpenAPI_{{classVarName}}_{{enumName}}_NULL = 0{{#enumVars}}, OpenAPI_{{classVarName}}_{{enumName}}_{{{value}}}{{/enumVars}} } OpenAPI_{{classVarName}}_{{name}}_e;
{{/allowableValues}}
char* OpenAPI_{{classVarName}}_{{name}}_ToString(OpenAPI_{{classVarName}}_{{name}}_e {{name}});
OpenAPI_{{classVarName}}_{{name}}_e OpenAPI_{{classVarName}}_{{name}}_FromString(char* {{name}});
{{/isEnum}}
{{/isPrimitiveType}}
{{/isContainer}}
{{/vars}}
typedef struct OpenAPI_{{classname}}_s {
{{#vars}}
{{^isContainer}}
{{^isPrimitiveType}}
{{#isEnum}}
OpenAPI_{{datatype}}_e {{name}};
{{/isEnum}}
{{^isEnum}}
{{#isModel}}
struct OpenAPI_{{datatype}}_s *{{name}};
{{/isModel}}
{{#isUuid}}
{{datatype}} *{{name}};
{{/isUuid}}
{{#isEmail}}
{{datatype}} *{{name}};
{{/isEmail}}
{{#isFreeFormObject}}
OpenAPI_{{datatype}}_t *{{name}};
{{/isFreeFormObject}}
{{/isEnum}}
{{/isPrimitiveType}}
{{#isPrimitiveType}}
{{#isEnum}}
OpenAPI_{{classVarName}}_{{name}}_e {{name}};
{{/isEnum}}
{{^isEnum}}
{{#isNumeric}}
{{datatype}} {{name}};
{{/isNumeric}}
{{#isBoolean}}
{{datatype}} {{name}};
{{/isBoolean}}
{{#isString}}
{{datatype}} *{{name}};
{{/isString}}
{{/isEnum}}
{{#isByteArray}}
{{datatype}} {{name}};
{{/isByteArray}}
{{#isBinary}}
OpenAPI_{{datatype}} {{name}};
{{/isBinary}}
{{#isDate}}
{{datatype}} *{{name}};
{{/isDate}}
{{#isDateTime}}
{{datatype}} *{{name}};
{{/isDateTime}}
{{/isPrimitiveType}}
{{/isContainer}}
{{#isContainer}}
{{#isListContainer}}
OpenAPI_{{datatype}}_t *{{name}};
{{/isListContainer}}
{{#isMapContainer}}
OpenAPI_{{datatype}} {{name}};
{{/isMapContainer}}
{{/isContainer}}
{{/vars}}
} OpenAPI_{{classname}}_t;
OpenAPI_{{classname}}_t *OpenAPI_{{classname}}_create(
{{#vars}}
{{^isContainer}}
{{^isPrimitiveType}}
{{#isEnum}}
OpenAPI_{{datatype}}_e {{name}}{{#hasMore}},{{/hasMore}}
{{/isEnum}}
{{^isEnum}}
{{#isModel}}
OpenAPI_{{datatype}}_t *{{name}}{{#hasMore}},{{/hasMore}}
{{/isModel}}
{{#isUuid}}
{{datatype}} *{{name}}{{#hasMore}},{{/hasMore}}
{{/isUuid}}
{{#isEmail}}
{{datatype}} *{{name}}{{#hasMore}},{{/hasMore}}
{{/isEmail}}
{{#isFreeFormObject}}
OpenAPI_{{datatype}}_t *{{name}}{{#hasMore}},{{/hasMore}}
{{/isFreeFormObject}}
{{/isEnum}}
{{/isPrimitiveType}}
{{#isPrimitiveType}}
{{#isEnum}}
OpenAPI_{{classVarName}}_{{name}}_e {{name}}{{#hasMore}},{{/hasMore}}
{{/isEnum}}
{{^isEnum}}
{{#isNumeric}}
{{datatype}} {{name}}{{#hasMore}},{{/hasMore}}
{{/isNumeric}}
{{#isBoolean}}
{{datatype}} {{name}}{{#hasMore}},{{/hasMore}}
{{/isBoolean}}
{{#isString}}
{{datatype}} *{{name}}{{#hasMore}},{{/hasMore}}
{{/isString}}
{{/isEnum}}
{{#isByteArray}}
{{datatype}} {{name}}{{#hasMore}},{{/hasMore}}
{{/isByteArray}}
{{#isBinary}}
OpenAPI_{{datatype}} {{name}}{{#hasMore}},{{/hasMore}}
{{/isBinary}}
{{#isDate}}
{{datatype}} *{{name}}{{#hasMore}},{{/hasMore}}
{{/isDate}}
{{#isDateTime}}
{{datatype}} *{{name}}{{#hasMore}},{{/hasMore}}
{{/isDateTime}}
{{/isPrimitiveType}}
{{/isContainer}}
{{#isContainer}}
{{#isListContainer}}
OpenAPI_{{datatype}}_t *{{name}}{{#hasMore}},{{/hasMore}}
{{/isListContainer}}
{{#isMapContainer}}
OpenAPI_{{datatype}} {{name}}{{#hasMore}},{{/hasMore}}
{{/isMapContainer}}
{{/isContainer}}
{{/vars}});
void OpenAPI_{{classname}}_free(OpenAPI_{{classname}}_t *{{classname}});
OpenAPI_{{classname}}_t *OpenAPI_{{classname}}_parseFromJSON(cJSON *{{classname}}JSON);
cJSON *OpenAPI_{{classname}}_convertToJSON(OpenAPI_{{classname}}_t *{{classname}});
{{/isEnum}}
#ifdef __cplusplus
}
#endif
#endif /* _OpenAPI_{{classname}}_H_ */
{{/model}}{{/models}}

View File

@ -0,0 +1,35 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "object.h"
OpenAPI_object_t *OpenAPI_object_create(void)
{
OpenAPI_object_t *object = ogs_malloc(sizeof(OpenAPI_object_t));
return object;
}
void OpenAPI_object_free(OpenAPI_object_t *object)
{
ogs_free (object);
}
cJSON *OpenAPI_object_convertToJSON(OpenAPI_object_t *object)
{
cJSON *item = cJSON_CreateObject();
return item;
fail:
cJSON_Delete(item);
return NULL;
}
OpenAPI_object_t *OpenAPI_object_parseFromJSON(cJSON *objectJSON)
{
OpenAPI_object_t *object = NULL;
return object;
end:
return NULL;
}

View File

@ -0,0 +1,30 @@
#ifndef OGS_SBI_OBJECT_H
#define OGS_SBI_OBJECT_H
#include <string.h>
#include "../external/cJSON.h"
#include "../include/list.h"
#include "../include/keyValuePair.h"
#include "../include/binary.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OpenAPI_object_s {
void *temporary;
} OpenAPI_object_t;
OpenAPI_object_t *OpenAPI_object_create(void);
void OpenAPI_object_free(OpenAPI_object_t *object);
OpenAPI_object_t *OpenAPI_object_parseFromJSON(cJSON *objectJSON);
cJSON *OpenAPI_object_convertToJSON(OpenAPI_object_t *object);
#ifdef __cplusplus
}
#endif
#endif /* OGS_SBI_OBJECT_H */

File diff suppressed because it is too large Load Diff

2939
lib/sbi/openapi/external/cJSON.c vendored Normal file

File diff suppressed because it is too large Load Diff

277
lib/sbi/openapi/external/cJSON.h vendored Normal file
View File

@ -0,0 +1,277 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 7
#include <stddef.h>
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
typedef struct cJSON_Hooks
{
void *(*malloc_fn)(size_t sz);
void (*free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 2 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type __stdcall
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type __stdcall
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall
#endif
#else /* !WIN32 */
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
/* Supply malloc, realloc and free functions to cJSON */
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check if the item is a string and return its valuestring */
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/arrray that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items. */
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detatch items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
need to be released. With recurse!=0, it will duplicate any children connected to the item.
The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
#ifdef __cplusplus
}
#endif
#endif

19
lib/sbi/openapi/external/cJSON.licence vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,27 @@
#ifndef OGS_SBI_BINARY_H
#define OGS_SBI_BINARY_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OpenAPI_binary_s {
uint8_t* data;
unsigned int len;
} OpenAPI_binary_t;
OpenAPI_binary_t *OpenAPI_instantiate_binary_t(char *data, int len);
char *OpenAPI_base64encode(const void *b64_encode_this,
int encode_this_many_bytes);
char *OpenAPI_base64decode(const void *b64_decode_this,
int decode_this_many_bytes, int *decoded_bytes);
#ifdef __cplusplus
}
#endif
#endif // OGS_SBI_BINARY_H

View File

@ -0,0 +1,25 @@
#ifndef OGS_SBI_MAP_H
#define OGS_SBI_MAP_H
#include "ogs-core.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OpenAPI_map_s {
char *key;
void *value;
} OpenAPI_map_t;
OpenAPI_map_t *OpenAPI_map_create(char *key, void *value);
OpenAPI_map_t *OpenAPI_map_create_allocate(char *key, double value);
void OpenAPI_map_free(OpenAPI_map_t *OpenAPI_map);
#ifdef __cplusplus
}
#endif
#endif /* OGS_SBI_MAP_H */

View File

@ -0,0 +1,54 @@
#ifndef OGS_SBI_LIST_H
#define OGS_SBI_LIST_H
#include "../external/cJSON.h"
#include "ogs-core.h"
#ifdef __cplusplus
extern "C" {
#endif
#define OpenAPI_malloc(__sIZE) __sIZE == 0 ? NULL : ogs_malloc(__sIZE)
typedef struct OpenAPI_list_s OpenAPI_list_t;
typedef struct OpenAPI_lnode_s OpenAPI_lnode_t;
struct OpenAPI_lnode_s {
OpenAPI_lnode_t *next;
OpenAPI_lnode_t *prev;
void *data;
};
typedef struct OpenAPI_list_s {
OpenAPI_lnode_t *first;
OpenAPI_lnode_t *last;
long count;
} OpenAPI_list_t;
#define OpenAPI_list_for_each(list, element) for(element = (list != NULL) ? (list)->first : NULL; element != NULL; element = element->next)
OpenAPI_list_t *OpenAPI_list_create(void);
void OpenAPI_list_free(OpenAPI_list_t *listToFree);
void OpenAPI_list_add(OpenAPI_list_t *list, void *dataToAddInList);
OpenAPI_lnode_t *OpenAPI_list_find(OpenAPI_list_t *list, long indexOfElement);
void OpenAPI_list_remove(
OpenAPI_list_t *list, OpenAPI_lnode_t *elementToRemove);
void OpenAPI_list_iterate_forward(OpenAPI_list_t *list,
void (*operationToPerform)(OpenAPI_lnode_t*, void*),
void *additionalDataNeededForCallbackFunction);
void OpenAPI_list_iterate_backward(OpenAPI_list_t *list,
void (*operationToPerform)(OpenAPI_lnode_t*, void*),
void *additionalDataNeededForCallbackFunction);
void OpenAPI_lnode_print(OpenAPI_lnode_t *listEntry, void *additionalData);
void OpenAPI_lnode_free(OpenAPI_lnode_t *listEntry, void *additionalData);
#ifdef __cplusplus
}
#endif
#endif // OGS_SBI_LIST_H

131
lib/sbi/openapi/meson.build Normal file
View File

@ -0,0 +1,131 @@
# Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
# This file is part of Open5GS.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
libsbi_openapi_sources = files('''
src/list.c
src/apiKey.c
external/cJSON.c
model/object.c
model/access_type.c
model/amf_cond.c
model/amf_info.c
model/atsss_capability.c
model/ausf_info.c
model/bsf_info.c
model/change_item.c
model/change_type.c
model/chf_info.c
model/chf_service_info.c
model/data_set_id.c
model/default_notification_subscription.c
model/dnn_smf_info_item.c
model/dnn_upf_info_item.c
model/event_id.c
model/guami.c
model/guami_list_cond.c
model/identity_range.c
model/inline_response_200.c
model/interface_upf_info_item.c
model/invalid_param.c
model/ip_end_point.c
model/ipv4_address_range.c
model/ipv6_prefix_range.c
model/link.c
model/links_value_schema.c
model/n1_message_class.c
model/n2_information_class.c
model/n2_interface_amf_info.c
model/network_slice_cond.c
model/nf_group_cond.c
model/nf_instance_id_cond.c
model/nf_profile.c
model/nf_service.c
model/nf_service_status.c
model/nf_service_version.c
model/nf_status.c
model/nf_type.c
model/nf_type_cond.c
model/notif_condition.c
model/notification_data.c
model/notification_event_type.c
model/notification_type.c
model/nrf_info.c
model/nwdaf_event.c
model/nwdaf_info.c
model/patch_item.c
model/patch_operation.c
model/pcf_info.c
model/pdu_session_type.c
model/plmn_id.c
model/plmn_range.c
model/plmn_snssai.c
model/problem_details.c
model/service_name_cond.c
model/smf_info.c
model/snssai.c
model/snssai_smf_info_item.c
model/snssai_upf_info_item.c
model/subscription_data.c
model/supi_range.c
model/tac_range.c
model/tai.c
model/tai_range.c
model/transport_protocol.c
model/udm_info.c
model/udr_info.c
model/up_interface_type.c
model/upf_info.c
model/uri_scheme.c
model/atom.c
model/cnf.c
model/cnf_unit.c
model/complex_query.c
model/dnf.c
model/dnf_unit.c
model/search_result.c
model/stored_search_result.c
'''.split())
libsbi_openapi_inc = include_directories('.')
sbi_openapi_cc_flags = ['-DOGS_SBI_COMPILATION']
if cc.get_id() == 'gcc' or cc.get_id() == 'clang'
sbi_openapi_cc_flags += cc.get_supported_arguments([
'-Wno-strict-prototypes',
'-Wno-missing-prototypes',
'-Wno-missing-declarations',
'-Wno-unused-variable',
'-Wno-unused-label',
'-Wno-float-equal',
])
endif
libsbi_openapi = library('ogssbi-openapi',
sources : libsbi_openapi_sources,
version : libogslib_version,
c_args : sbi_openapi_cc_flags,
include_directories : [libsbi_openapi_inc, libinc],
dependencies : libcore_dep,
install : true)
libsbi_openapi_dep = declare_dependency(
link_with : libsbi_openapi,
include_directories : [libsbi_openapi_inc, libinc],
dependencies : libcore_dep)

View File

@ -0,0 +1,30 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "access_type.h"
char* OpenAPI_access_type_ToString(OpenAPI_access_type_e access_type)
{
const char *access_typeArray[] = { "NULL", "3GPP_ACCESS", "NON_3GPP_ACCESS" };
size_t sizeofArray = sizeof(access_typeArray) / sizeof(access_typeArray[0]);
if (access_type < sizeofArray)
return (char *)access_typeArray[access_type];
else
return (char *)"Unknown";
}
OpenAPI_access_type_e OpenAPI_access_type_FromString(char* access_type)
{
int stringToReturn = 0;
const char *access_typeArray[] = { "NULL", "3GPP_ACCESS", "NON_3GPP_ACCESS" };
size_t sizeofArray = sizeof(access_typeArray) / sizeof(access_typeArray[0]);
while (stringToReturn < sizeofArray) {
if (strcmp(access_type, access_typeArray[stringToReturn]) == 0) {
return stringToReturn;
}
stringToReturn++;
}
return 0;
}

View File

@ -0,0 +1,31 @@
/*
* access_type.h
*
*
*/
#ifndef _OpenAPI_access_type_H_
#define _OpenAPI_access_type_H_
#include <string.h>
#include "../external/cJSON.h"
#include "../include/list.h"
#include "../include/keyValuePair.h"
#include "../include/binary.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum { OpenAPI_access_type_NULL = 0, OpenAPI_access_type_3GPP_ACCESS, OpenAPI_access_type_NON_3GPP_ACCESS } OpenAPI_access_type_e;
char* OpenAPI_access_type_ToString(OpenAPI_access_type_e access_type);
OpenAPI_access_type_e OpenAPI_access_type_FromString(char* access_type);
#ifdef __cplusplus
}
#endif
#endif /* _OpenAPI_access_type_H_ */

View File

@ -0,0 +1,91 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "amf_cond.h"
OpenAPI_amf_cond_t *OpenAPI_amf_cond_create(
char *amf_set_id,
char *amf_region_id
)
{
OpenAPI_amf_cond_t *amf_cond_local_var = OpenAPI_malloc(sizeof(OpenAPI_amf_cond_t));
if (!amf_cond_local_var) {
return NULL;
}
amf_cond_local_var->amf_set_id = amf_set_id;
amf_cond_local_var->amf_region_id = amf_region_id;
return amf_cond_local_var;
}
void OpenAPI_amf_cond_free(OpenAPI_amf_cond_t *amf_cond)
{
if (NULL == amf_cond) {
return;
}
OpenAPI_lnode_t *node;
ogs_free(amf_cond->amf_set_id);
ogs_free(amf_cond->amf_region_id);
ogs_free(amf_cond);
}
cJSON *OpenAPI_amf_cond_convertToJSON(OpenAPI_amf_cond_t *amf_cond)
{
cJSON *item = NULL;
if (amf_cond == NULL) {
ogs_error("OpenAPI_amf_cond_convertToJSON() failed [AmfCond]");
return NULL;
}
item = cJSON_CreateObject();
if (amf_cond->amf_set_id) {
if (cJSON_AddStringToObject(item, "amfSetId", amf_cond->amf_set_id) == NULL) {
ogs_error("OpenAPI_amf_cond_convertToJSON() failed [amf_set_id]");
goto end;
}
}
if (amf_cond->amf_region_id) {
if (cJSON_AddStringToObject(item, "amfRegionId", amf_cond->amf_region_id) == NULL) {
ogs_error("OpenAPI_amf_cond_convertToJSON() failed [amf_region_id]");
goto end;
}
}
end:
return item;
}
OpenAPI_amf_cond_t *OpenAPI_amf_cond_parseFromJSON(cJSON *amf_condJSON)
{
OpenAPI_amf_cond_t *amf_cond_local_var = NULL;
cJSON *amf_set_id = cJSON_GetObjectItemCaseSensitive(amf_condJSON, "amfSetId");
if (amf_set_id) {
if (!cJSON_IsString(amf_set_id)) {
ogs_error("OpenAPI_amf_cond_parseFromJSON() failed [amf_set_id]");
goto end;
}
}
cJSON *amf_region_id = cJSON_GetObjectItemCaseSensitive(amf_condJSON, "amfRegionId");
if (amf_region_id) {
if (!cJSON_IsString(amf_region_id)) {
ogs_error("OpenAPI_amf_cond_parseFromJSON() failed [amf_region_id]");
goto end;
}
}
amf_cond_local_var = OpenAPI_amf_cond_create (
amf_set_id ? ogs_strdup(amf_set_id->valuestring) : NULL,
amf_region_id ? ogs_strdup(amf_region_id->valuestring) : NULL
);
return amf_cond_local_var;
end:
return NULL;
}

View File

@ -0,0 +1,39 @@
/*
* amf_cond.h
*
*
*/
#ifndef _OpenAPI_amf_cond_H_
#define _OpenAPI_amf_cond_H_
#include <string.h>
#include "../external/cJSON.h"
#include "../include/list.h"
#include "../include/keyValuePair.h"
#include "../include/binary.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OpenAPI_amf_cond_s OpenAPI_amf_cond_t;
typedef struct OpenAPI_amf_cond_s {
char *amf_set_id;
char *amf_region_id;
} OpenAPI_amf_cond_t;
OpenAPI_amf_cond_t *OpenAPI_amf_cond_create(
char *amf_set_id,
char *amf_region_id
);
void OpenAPI_amf_cond_free(OpenAPI_amf_cond_t *amf_cond);
OpenAPI_amf_cond_t *OpenAPI_amf_cond_parseFromJSON(cJSON *amf_condJSON);
cJSON *OpenAPI_amf_cond_convertToJSON(OpenAPI_amf_cond_t *amf_cond);
#ifdef __cplusplus
}
#endif
#endif /* _OpenAPI_amf_cond_H_ */

View File

@ -0,0 +1,380 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "amf_info.h"
OpenAPI_amf_info_t *OpenAPI_amf_info_create(
char *amf_set_id,
char *amf_region_id,
OpenAPI_list_t *guami_list,
OpenAPI_list_t *tai_list,
OpenAPI_list_t *tai_range_list,
OpenAPI_list_t *backup_info_amf_failure,
OpenAPI_list_t *backup_info_amf_removal,
OpenAPI_n2_interface_amf_info_t *n2_interface_amf_info
)
{
OpenAPI_amf_info_t *amf_info_local_var = OpenAPI_malloc(sizeof(OpenAPI_amf_info_t));
if (!amf_info_local_var) {
return NULL;
}
amf_info_local_var->amf_set_id = amf_set_id;
amf_info_local_var->amf_region_id = amf_region_id;
amf_info_local_var->guami_list = guami_list;
amf_info_local_var->tai_list = tai_list;
amf_info_local_var->tai_range_list = tai_range_list;
amf_info_local_var->backup_info_amf_failure = backup_info_amf_failure;
amf_info_local_var->backup_info_amf_removal = backup_info_amf_removal;
amf_info_local_var->n2_interface_amf_info = n2_interface_amf_info;
return amf_info_local_var;
}
void OpenAPI_amf_info_free(OpenAPI_amf_info_t *amf_info)
{
if (NULL == amf_info) {
return;
}
OpenAPI_lnode_t *node;
ogs_free(amf_info->amf_set_id);
ogs_free(amf_info->amf_region_id);
OpenAPI_list_for_each(amf_info->guami_list, node) {
OpenAPI_guami_free(node->data);
}
OpenAPI_list_free(amf_info->guami_list);
OpenAPI_list_for_each(amf_info->tai_list, node) {
OpenAPI_tai_free(node->data);
}
OpenAPI_list_free(amf_info->tai_list);
OpenAPI_list_for_each(amf_info->tai_range_list, node) {
OpenAPI_tai_range_free(node->data);
}
OpenAPI_list_free(amf_info->tai_range_list);
OpenAPI_list_for_each(amf_info->backup_info_amf_failure, node) {
OpenAPI_guami_free(node->data);
}
OpenAPI_list_free(amf_info->backup_info_amf_failure);
OpenAPI_list_for_each(amf_info->backup_info_amf_removal, node) {
OpenAPI_guami_free(node->data);
}
OpenAPI_list_free(amf_info->backup_info_amf_removal);
OpenAPI_n2_interface_amf_info_free(amf_info->n2_interface_amf_info);
ogs_free(amf_info);
}
cJSON *OpenAPI_amf_info_convertToJSON(OpenAPI_amf_info_t *amf_info)
{
cJSON *item = NULL;
if (amf_info == NULL) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [AmfInfo]");
return NULL;
}
item = cJSON_CreateObject();
if (!amf_info->amf_set_id) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [amf_set_id]");
goto end;
}
if (cJSON_AddStringToObject(item, "amfSetId", amf_info->amf_set_id) == NULL) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [amf_set_id]");
goto end;
}
if (!amf_info->amf_region_id) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [amf_region_id]");
goto end;
}
if (cJSON_AddStringToObject(item, "amfRegionId", amf_info->amf_region_id) == NULL) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [amf_region_id]");
goto end;
}
if (!amf_info->guami_list) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [guami_list]");
goto end;
}
cJSON *guami_listList = cJSON_AddArrayToObject(item, "guamiList");
if (guami_listList == NULL) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [guami_list]");
goto end;
}
OpenAPI_lnode_t *guami_list_node;
if (amf_info->guami_list) {
OpenAPI_list_for_each(amf_info->guami_list, guami_list_node) {
cJSON *itemLocal = OpenAPI_guami_convertToJSON(guami_list_node->data);
if (itemLocal == NULL) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [guami_list]");
goto end;
}
cJSON_AddItemToArray(guami_listList, itemLocal);
}
}
if (amf_info->tai_list) {
cJSON *tai_listList = cJSON_AddArrayToObject(item, "taiList");
if (tai_listList == NULL) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [tai_list]");
goto end;
}
OpenAPI_lnode_t *tai_list_node;
if (amf_info->tai_list) {
OpenAPI_list_for_each(amf_info->tai_list, tai_list_node) {
cJSON *itemLocal = OpenAPI_tai_convertToJSON(tai_list_node->data);
if (itemLocal == NULL) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [tai_list]");
goto end;
}
cJSON_AddItemToArray(tai_listList, itemLocal);
}
}
}
if (amf_info->tai_range_list) {
cJSON *tai_range_listList = cJSON_AddArrayToObject(item, "taiRangeList");
if (tai_range_listList == NULL) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [tai_range_list]");
goto end;
}
OpenAPI_lnode_t *tai_range_list_node;
if (amf_info->tai_range_list) {
OpenAPI_list_for_each(amf_info->tai_range_list, tai_range_list_node) {
cJSON *itemLocal = OpenAPI_tai_range_convertToJSON(tai_range_list_node->data);
if (itemLocal == NULL) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [tai_range_list]");
goto end;
}
cJSON_AddItemToArray(tai_range_listList, itemLocal);
}
}
}
if (amf_info->backup_info_amf_failure) {
cJSON *backup_info_amf_failureList = cJSON_AddArrayToObject(item, "backupInfoAmfFailure");
if (backup_info_amf_failureList == NULL) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [backup_info_amf_failure]");
goto end;
}
OpenAPI_lnode_t *backup_info_amf_failure_node;
if (amf_info->backup_info_amf_failure) {
OpenAPI_list_for_each(amf_info->backup_info_amf_failure, backup_info_amf_failure_node) {
cJSON *itemLocal = OpenAPI_guami_convertToJSON(backup_info_amf_failure_node->data);
if (itemLocal == NULL) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [backup_info_amf_failure]");
goto end;
}
cJSON_AddItemToArray(backup_info_amf_failureList, itemLocal);
}
}
}
if (amf_info->backup_info_amf_removal) {
cJSON *backup_info_amf_removalList = cJSON_AddArrayToObject(item, "backupInfoAmfRemoval");
if (backup_info_amf_removalList == NULL) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [backup_info_amf_removal]");
goto end;
}
OpenAPI_lnode_t *backup_info_amf_removal_node;
if (amf_info->backup_info_amf_removal) {
OpenAPI_list_for_each(amf_info->backup_info_amf_removal, backup_info_amf_removal_node) {
cJSON *itemLocal = OpenAPI_guami_convertToJSON(backup_info_amf_removal_node->data);
if (itemLocal == NULL) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [backup_info_amf_removal]");
goto end;
}
cJSON_AddItemToArray(backup_info_amf_removalList, itemLocal);
}
}
}
if (amf_info->n2_interface_amf_info) {
cJSON *n2_interface_amf_info_local_JSON = OpenAPI_n2_interface_amf_info_convertToJSON(amf_info->n2_interface_amf_info);
if (n2_interface_amf_info_local_JSON == NULL) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [n2_interface_amf_info]");
goto end;
}
cJSON_AddItemToObject(item, "n2InterfaceAmfInfo", n2_interface_amf_info_local_JSON);
if (item->child == NULL) {
ogs_error("OpenAPI_amf_info_convertToJSON() failed [n2_interface_amf_info]");
goto end;
}
}
end:
return item;
}
OpenAPI_amf_info_t *OpenAPI_amf_info_parseFromJSON(cJSON *amf_infoJSON)
{
OpenAPI_amf_info_t *amf_info_local_var = NULL;
cJSON *amf_set_id = cJSON_GetObjectItemCaseSensitive(amf_infoJSON, "amfSetId");
if (!amf_set_id) {
ogs_error("OpenAPI_amf_info_parseFromJSON() failed [amf_set_id]");
goto end;
}
if (!cJSON_IsString(amf_set_id)) {
ogs_error("OpenAPI_amf_info_parseFromJSON() failed [amf_set_id]");
goto end;
}
cJSON *amf_region_id = cJSON_GetObjectItemCaseSensitive(amf_infoJSON, "amfRegionId");
if (!amf_region_id) {
ogs_error("OpenAPI_amf_info_parseFromJSON() failed [amf_region_id]");
goto end;
}
if (!cJSON_IsString(amf_region_id)) {
ogs_error("OpenAPI_amf_info_parseFromJSON() failed [amf_region_id]");
goto end;
}
cJSON *guami_list = cJSON_GetObjectItemCaseSensitive(amf_infoJSON, "guamiList");
if (!guami_list) {
ogs_error("OpenAPI_amf_info_parseFromJSON() failed [guami_list]");
goto end;
}
OpenAPI_list_t *guami_listList;
cJSON *guami_list_local_nonprimitive;
if (!cJSON_IsArray(guami_list)) {
ogs_error("OpenAPI_amf_info_parseFromJSON() failed [guami_list]");
goto end;
}
guami_listList = OpenAPI_list_create();
cJSON_ArrayForEach(guami_list_local_nonprimitive, guami_list ) {
if (!cJSON_IsObject(guami_list_local_nonprimitive)) {
ogs_error("OpenAPI_amf_info_parseFromJSON() failed [guami_list]");
goto end;
}
OpenAPI_guami_t *guami_listItem = OpenAPI_guami_parseFromJSON(guami_list_local_nonprimitive);
OpenAPI_list_add(guami_listList, guami_listItem);
}
cJSON *tai_list = cJSON_GetObjectItemCaseSensitive(amf_infoJSON, "taiList");
OpenAPI_list_t *tai_listList;
if (tai_list) {
cJSON *tai_list_local_nonprimitive;
if (!cJSON_IsArray(tai_list)) {
ogs_error("OpenAPI_amf_info_parseFromJSON() failed [tai_list]");
goto end;
}
tai_listList = OpenAPI_list_create();
cJSON_ArrayForEach(tai_list_local_nonprimitive, tai_list ) {
if (!cJSON_IsObject(tai_list_local_nonprimitive)) {
ogs_error("OpenAPI_amf_info_parseFromJSON() failed [tai_list]");
goto end;
}
OpenAPI_tai_t *tai_listItem = OpenAPI_tai_parseFromJSON(tai_list_local_nonprimitive);
OpenAPI_list_add(tai_listList, tai_listItem);
}
}
cJSON *tai_range_list = cJSON_GetObjectItemCaseSensitive(amf_infoJSON, "taiRangeList");
OpenAPI_list_t *tai_range_listList;
if (tai_range_list) {
cJSON *tai_range_list_local_nonprimitive;
if (!cJSON_IsArray(tai_range_list)) {
ogs_error("OpenAPI_amf_info_parseFromJSON() failed [tai_range_list]");
goto end;
}
tai_range_listList = OpenAPI_list_create();
cJSON_ArrayForEach(tai_range_list_local_nonprimitive, tai_range_list ) {
if (!cJSON_IsObject(tai_range_list_local_nonprimitive)) {
ogs_error("OpenAPI_amf_info_parseFromJSON() failed [tai_range_list]");
goto end;
}
OpenAPI_tai_range_t *tai_range_listItem = OpenAPI_tai_range_parseFromJSON(tai_range_list_local_nonprimitive);
OpenAPI_list_add(tai_range_listList, tai_range_listItem);
}
}
cJSON *backup_info_amf_failure = cJSON_GetObjectItemCaseSensitive(amf_infoJSON, "backupInfoAmfFailure");
OpenAPI_list_t *backup_info_amf_failureList;
if (backup_info_amf_failure) {
cJSON *backup_info_amf_failure_local_nonprimitive;
if (!cJSON_IsArray(backup_info_amf_failure)) {
ogs_error("OpenAPI_amf_info_parseFromJSON() failed [backup_info_amf_failure]");
goto end;
}
backup_info_amf_failureList = OpenAPI_list_create();
cJSON_ArrayForEach(backup_info_amf_failure_local_nonprimitive, backup_info_amf_failure ) {
if (!cJSON_IsObject(backup_info_amf_failure_local_nonprimitive)) {
ogs_error("OpenAPI_amf_info_parseFromJSON() failed [backup_info_amf_failure]");
goto end;
}
OpenAPI_guami_t *backup_info_amf_failureItem = OpenAPI_guami_parseFromJSON(backup_info_amf_failure_local_nonprimitive);
OpenAPI_list_add(backup_info_amf_failureList, backup_info_amf_failureItem);
}
}
cJSON *backup_info_amf_removal = cJSON_GetObjectItemCaseSensitive(amf_infoJSON, "backupInfoAmfRemoval");
OpenAPI_list_t *backup_info_amf_removalList;
if (backup_info_amf_removal) {
cJSON *backup_info_amf_removal_local_nonprimitive;
if (!cJSON_IsArray(backup_info_amf_removal)) {
ogs_error("OpenAPI_amf_info_parseFromJSON() failed [backup_info_amf_removal]");
goto end;
}
backup_info_amf_removalList = OpenAPI_list_create();
cJSON_ArrayForEach(backup_info_amf_removal_local_nonprimitive, backup_info_amf_removal ) {
if (!cJSON_IsObject(backup_info_amf_removal_local_nonprimitive)) {
ogs_error("OpenAPI_amf_info_parseFromJSON() failed [backup_info_amf_removal]");
goto end;
}
OpenAPI_guami_t *backup_info_amf_removalItem = OpenAPI_guami_parseFromJSON(backup_info_amf_removal_local_nonprimitive);
OpenAPI_list_add(backup_info_amf_removalList, backup_info_amf_removalItem);
}
}
cJSON *n2_interface_amf_info = cJSON_GetObjectItemCaseSensitive(amf_infoJSON, "n2InterfaceAmfInfo");
OpenAPI_n2_interface_amf_info_t *n2_interface_amf_info_local_nonprim = NULL;
if (n2_interface_amf_info) {
n2_interface_amf_info_local_nonprim = OpenAPI_n2_interface_amf_info_parseFromJSON(n2_interface_amf_info);
}
amf_info_local_var = OpenAPI_amf_info_create (
ogs_strdup(amf_set_id->valuestring),
ogs_strdup(amf_region_id->valuestring),
guami_listList,
tai_list ? tai_listList : NULL,
tai_range_list ? tai_range_listList : NULL,
backup_info_amf_failure ? backup_info_amf_failureList : NULL,
backup_info_amf_removal ? backup_info_amf_removalList : NULL,
n2_interface_amf_info ? n2_interface_amf_info_local_nonprim : NULL
);
return amf_info_local_var;
end:
return NULL;
}

View File

@ -0,0 +1,55 @@
/*
* amf_info.h
*
*
*/
#ifndef _OpenAPI_amf_info_H_
#define _OpenAPI_amf_info_H_
#include <string.h>
#include "../external/cJSON.h"
#include "../include/list.h"
#include "../include/keyValuePair.h"
#include "../include/binary.h"
#include "guami.h"
#include "n2_interface_amf_info.h"
#include "tai.h"
#include "tai_range.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OpenAPI_amf_info_s OpenAPI_amf_info_t;
typedef struct OpenAPI_amf_info_s {
char *amf_set_id;
char *amf_region_id;
OpenAPI_list_t *guami_list;
OpenAPI_list_t *tai_list;
OpenAPI_list_t *tai_range_list;
OpenAPI_list_t *backup_info_amf_failure;
OpenAPI_list_t *backup_info_amf_removal;
struct OpenAPI_n2_interface_amf_info_s *n2_interface_amf_info;
} OpenAPI_amf_info_t;
OpenAPI_amf_info_t *OpenAPI_amf_info_create(
char *amf_set_id,
char *amf_region_id,
OpenAPI_list_t *guami_list,
OpenAPI_list_t *tai_list,
OpenAPI_list_t *tai_range_list,
OpenAPI_list_t *backup_info_amf_failure,
OpenAPI_list_t *backup_info_amf_removal,
OpenAPI_n2_interface_amf_info_t *n2_interface_amf_info
);
void OpenAPI_amf_info_free(OpenAPI_amf_info_t *amf_info);
OpenAPI_amf_info_t *OpenAPI_amf_info_parseFromJSON(cJSON *amf_infoJSON);
cJSON *OpenAPI_amf_info_convertToJSON(OpenAPI_amf_info_t *amf_info);
#ifdef __cplusplus
}
#endif
#endif /* _OpenAPI_amf_info_H_ */

View File

@ -0,0 +1,120 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "atom.h"
OpenAPI_atom_t *OpenAPI_atom_create(
char *attr,
char *value,
int negative
)
{
OpenAPI_atom_t *atom_local_var = OpenAPI_malloc(sizeof(OpenAPI_atom_t));
if (!atom_local_var) {
return NULL;
}
atom_local_var->attr = attr;
atom_local_var->value = value;
atom_local_var->negative = negative;
return atom_local_var;
}
void OpenAPI_atom_free(OpenAPI_atom_t *atom)
{
if (NULL == atom) {
return;
}
OpenAPI_lnode_t *node;
ogs_free(atom->attr);
ogs_free(atom->value);
ogs_free(atom);
}
cJSON *OpenAPI_atom_convertToJSON(OpenAPI_atom_t *atom)
{
cJSON *item = NULL;
if (atom == NULL) {
ogs_error("OpenAPI_atom_convertToJSON() failed [Atom]");
return NULL;
}
item = cJSON_CreateObject();
if (!atom->attr) {
ogs_error("OpenAPI_atom_convertToJSON() failed [attr]");
goto end;
}
if (cJSON_AddStringToObject(item, "attr", atom->attr) == NULL) {
ogs_error("OpenAPI_atom_convertToJSON() failed [attr]");
goto end;
}
if (!atom->value) {
ogs_error("OpenAPI_atom_convertToJSON() failed [value]");
goto end;
}
if (cJSON_AddStringToObject(item, "value", atom->value) == NULL) {
ogs_error("OpenAPI_atom_convertToJSON() failed [value]");
goto end;
}
if (atom->negative) {
if (cJSON_AddBoolToObject(item, "negative", atom->negative) == NULL) {
ogs_error("OpenAPI_atom_convertToJSON() failed [negative]");
goto end;
}
}
end:
return item;
}
OpenAPI_atom_t *OpenAPI_atom_parseFromJSON(cJSON *atomJSON)
{
OpenAPI_atom_t *atom_local_var = NULL;
cJSON *attr = cJSON_GetObjectItemCaseSensitive(atomJSON, "attr");
if (!attr) {
ogs_error("OpenAPI_atom_parseFromJSON() failed [attr]");
goto end;
}
if (!cJSON_IsString(attr)) {
ogs_error("OpenAPI_atom_parseFromJSON() failed [attr]");
goto end;
}
cJSON *value = cJSON_GetObjectItemCaseSensitive(atomJSON, "value");
if (!value) {
ogs_error("OpenAPI_atom_parseFromJSON() failed [value]");
goto end;
}
if (!cJSON_IsString(value)) {
ogs_error("OpenAPI_atom_parseFromJSON() failed [value]");
goto end;
}
cJSON *negative = cJSON_GetObjectItemCaseSensitive(atomJSON, "negative");
if (negative) {
if (!cJSON_IsBool(negative)) {
ogs_error("OpenAPI_atom_parseFromJSON() failed [negative]");
goto end;
}
}
atom_local_var = OpenAPI_atom_create (
ogs_strdup(attr->valuestring),
ogs_strdup(value->valuestring),
negative ? negative->valueint : 0
);
return atom_local_var;
end:
return NULL;
}

View File

@ -0,0 +1,41 @@
/*
* atom.h
*
*
*/
#ifndef _OpenAPI_atom_H_
#define _OpenAPI_atom_H_
#include <string.h>
#include "../external/cJSON.h"
#include "../include/list.h"
#include "../include/keyValuePair.h"
#include "../include/binary.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OpenAPI_atom_s OpenAPI_atom_t;
typedef struct OpenAPI_atom_s {
char *attr;
char *value;
int negative;
} OpenAPI_atom_t;
OpenAPI_atom_t *OpenAPI_atom_create(
char *attr,
char *value,
int negative
);
void OpenAPI_atom_free(OpenAPI_atom_t *atom);
OpenAPI_atom_t *OpenAPI_atom_parseFromJSON(cJSON *atomJSON);
cJSON *OpenAPI_atom_convertToJSON(OpenAPI_atom_t *atom);
#ifdef __cplusplus
}
#endif
#endif /* _OpenAPI_atom_H_ */

View File

@ -0,0 +1,89 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "atsss_capability.h"
OpenAPI_atsss_capability_t *OpenAPI_atsss_capability_create(
int atsss_ll,
int mptcp
)
{
OpenAPI_atsss_capability_t *atsss_capability_local_var = OpenAPI_malloc(sizeof(OpenAPI_atsss_capability_t));
if (!atsss_capability_local_var) {
return NULL;
}
atsss_capability_local_var->atsss_ll = atsss_ll;
atsss_capability_local_var->mptcp = mptcp;
return atsss_capability_local_var;
}
void OpenAPI_atsss_capability_free(OpenAPI_atsss_capability_t *atsss_capability)
{
if (NULL == atsss_capability) {
return;
}
OpenAPI_lnode_t *node;
ogs_free(atsss_capability);
}
cJSON *OpenAPI_atsss_capability_convertToJSON(OpenAPI_atsss_capability_t *atsss_capability)
{
cJSON *item = NULL;
if (atsss_capability == NULL) {
ogs_error("OpenAPI_atsss_capability_convertToJSON() failed [AtsssCapability]");
return NULL;
}
item = cJSON_CreateObject();
if (atsss_capability->atsss_ll) {
if (cJSON_AddBoolToObject(item, "atsssLL", atsss_capability->atsss_ll) == NULL) {
ogs_error("OpenAPI_atsss_capability_convertToJSON() failed [atsss_ll]");
goto end;
}
}
if (atsss_capability->mptcp) {
if (cJSON_AddBoolToObject(item, "mptcp", atsss_capability->mptcp) == NULL) {
ogs_error("OpenAPI_atsss_capability_convertToJSON() failed [mptcp]");
goto end;
}
}
end:
return item;
}
OpenAPI_atsss_capability_t *OpenAPI_atsss_capability_parseFromJSON(cJSON *atsss_capabilityJSON)
{
OpenAPI_atsss_capability_t *atsss_capability_local_var = NULL;
cJSON *atsss_ll = cJSON_GetObjectItemCaseSensitive(atsss_capabilityJSON, "atsssLL");
if (atsss_ll) {
if (!cJSON_IsBool(atsss_ll)) {
ogs_error("OpenAPI_atsss_capability_parseFromJSON() failed [atsss_ll]");
goto end;
}
}
cJSON *mptcp = cJSON_GetObjectItemCaseSensitive(atsss_capabilityJSON, "mptcp");
if (mptcp) {
if (!cJSON_IsBool(mptcp)) {
ogs_error("OpenAPI_atsss_capability_parseFromJSON() failed [mptcp]");
goto end;
}
}
atsss_capability_local_var = OpenAPI_atsss_capability_create (
atsss_ll ? atsss_ll->valueint : 0,
mptcp ? mptcp->valueint : 0
);
return atsss_capability_local_var;
end:
return NULL;
}

View File

@ -0,0 +1,39 @@
/*
* atsss_capability.h
*
*
*/
#ifndef _OpenAPI_atsss_capability_H_
#define _OpenAPI_atsss_capability_H_
#include <string.h>
#include "../external/cJSON.h"
#include "../include/list.h"
#include "../include/keyValuePair.h"
#include "../include/binary.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OpenAPI_atsss_capability_s OpenAPI_atsss_capability_t;
typedef struct OpenAPI_atsss_capability_s {
int atsss_ll;
int mptcp;
} OpenAPI_atsss_capability_t;
OpenAPI_atsss_capability_t *OpenAPI_atsss_capability_create(
int atsss_ll,
int mptcp
);
void OpenAPI_atsss_capability_free(OpenAPI_atsss_capability_t *atsss_capability);
OpenAPI_atsss_capability_t *OpenAPI_atsss_capability_parseFromJSON(cJSON *atsss_capabilityJSON);
cJSON *OpenAPI_atsss_capability_convertToJSON(OpenAPI_atsss_capability_t *atsss_capability);
#ifdef __cplusplus
}
#endif
#endif /* _OpenAPI_atsss_capability_H_ */

View File

@ -0,0 +1,164 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "ausf_info.h"
OpenAPI_ausf_info_t *OpenAPI_ausf_info_create(
char *group_id,
OpenAPI_list_t *supi_ranges,
OpenAPI_list_t *routing_indicators
)
{
OpenAPI_ausf_info_t *ausf_info_local_var = OpenAPI_malloc(sizeof(OpenAPI_ausf_info_t));
if (!ausf_info_local_var) {
return NULL;
}
ausf_info_local_var->group_id = group_id;
ausf_info_local_var->supi_ranges = supi_ranges;
ausf_info_local_var->routing_indicators = routing_indicators;
return ausf_info_local_var;
}
void OpenAPI_ausf_info_free(OpenAPI_ausf_info_t *ausf_info)
{
if (NULL == ausf_info) {
return;
}
OpenAPI_lnode_t *node;
ogs_free(ausf_info->group_id);
OpenAPI_list_for_each(ausf_info->supi_ranges, node) {
OpenAPI_supi_range_free(node->data);
}
OpenAPI_list_free(ausf_info->supi_ranges);
OpenAPI_list_for_each(ausf_info->routing_indicators, node) {
ogs_free(node->data);
}
OpenAPI_list_free(ausf_info->routing_indicators);
ogs_free(ausf_info);
}
cJSON *OpenAPI_ausf_info_convertToJSON(OpenAPI_ausf_info_t *ausf_info)
{
cJSON *item = NULL;
if (ausf_info == NULL) {
ogs_error("OpenAPI_ausf_info_convertToJSON() failed [AusfInfo]");
return NULL;
}
item = cJSON_CreateObject();
if (ausf_info->group_id) {
if (cJSON_AddStringToObject(item, "groupId", ausf_info->group_id) == NULL) {
ogs_error("OpenAPI_ausf_info_convertToJSON() failed [group_id]");
goto end;
}
}
if (ausf_info->supi_ranges) {
cJSON *supi_rangesList = cJSON_AddArrayToObject(item, "supiRanges");
if (supi_rangesList == NULL) {
ogs_error("OpenAPI_ausf_info_convertToJSON() failed [supi_ranges]");
goto end;
}
OpenAPI_lnode_t *supi_ranges_node;
if (ausf_info->supi_ranges) {
OpenAPI_list_for_each(ausf_info->supi_ranges, supi_ranges_node) {
cJSON *itemLocal = OpenAPI_supi_range_convertToJSON(supi_ranges_node->data);
if (itemLocal == NULL) {
ogs_error("OpenAPI_ausf_info_convertToJSON() failed [supi_ranges]");
goto end;
}
cJSON_AddItemToArray(supi_rangesList, itemLocal);
}
}
}
if (ausf_info->routing_indicators) {
cJSON *routing_indicators = cJSON_AddArrayToObject(item, "routingIndicators");
if (routing_indicators == NULL) {
ogs_error("OpenAPI_ausf_info_convertToJSON() failed [routing_indicators]");
goto end;
}
OpenAPI_lnode_t *routing_indicators_node;
OpenAPI_list_for_each(ausf_info->routing_indicators, routing_indicators_node) {
if (cJSON_AddStringToObject(routing_indicators, "", (char*)routing_indicators_node->data) == NULL) {
ogs_error("OpenAPI_ausf_info_convertToJSON() failed [routing_indicators]");
goto end;
}
}
}
end:
return item;
}
OpenAPI_ausf_info_t *OpenAPI_ausf_info_parseFromJSON(cJSON *ausf_infoJSON)
{
OpenAPI_ausf_info_t *ausf_info_local_var = NULL;
cJSON *group_id = cJSON_GetObjectItemCaseSensitive(ausf_infoJSON, "groupId");
if (group_id) {
if (!cJSON_IsString(group_id)) {
ogs_error("OpenAPI_ausf_info_parseFromJSON() failed [group_id]");
goto end;
}
}
cJSON *supi_ranges = cJSON_GetObjectItemCaseSensitive(ausf_infoJSON, "supiRanges");
OpenAPI_list_t *supi_rangesList;
if (supi_ranges) {
cJSON *supi_ranges_local_nonprimitive;
if (!cJSON_IsArray(supi_ranges)) {
ogs_error("OpenAPI_ausf_info_parseFromJSON() failed [supi_ranges]");
goto end;
}
supi_rangesList = OpenAPI_list_create();
cJSON_ArrayForEach(supi_ranges_local_nonprimitive, supi_ranges ) {
if (!cJSON_IsObject(supi_ranges_local_nonprimitive)) {
ogs_error("OpenAPI_ausf_info_parseFromJSON() failed [supi_ranges]");
goto end;
}
OpenAPI_supi_range_t *supi_rangesItem = OpenAPI_supi_range_parseFromJSON(supi_ranges_local_nonprimitive);
OpenAPI_list_add(supi_rangesList, supi_rangesItem);
}
}
cJSON *routing_indicators = cJSON_GetObjectItemCaseSensitive(ausf_infoJSON, "routingIndicators");
OpenAPI_list_t *routing_indicatorsList;
if (routing_indicators) {
cJSON *routing_indicators_local;
if (!cJSON_IsArray(routing_indicators)) {
ogs_error("OpenAPI_ausf_info_parseFromJSON() failed [routing_indicators]");
goto end;
}
routing_indicatorsList = OpenAPI_list_create();
cJSON_ArrayForEach(routing_indicators_local, routing_indicators) {
if (!cJSON_IsString(routing_indicators_local)) {
ogs_error("OpenAPI_ausf_info_parseFromJSON() failed [routing_indicators]");
goto end;
}
OpenAPI_list_add(routing_indicatorsList, ogs_strdup(routing_indicators_local->valuestring));
}
}
ausf_info_local_var = OpenAPI_ausf_info_create (
group_id ? ogs_strdup(group_id->valuestring) : NULL,
supi_ranges ? supi_rangesList : NULL,
routing_indicators ? routing_indicatorsList : NULL
);
return ausf_info_local_var;
end:
return NULL;
}

View File

@ -0,0 +1,42 @@
/*
* ausf_info.h
*
*
*/
#ifndef _OpenAPI_ausf_info_H_
#define _OpenAPI_ausf_info_H_
#include <string.h>
#include "../external/cJSON.h"
#include "../include/list.h"
#include "../include/keyValuePair.h"
#include "../include/binary.h"
#include "supi_range.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OpenAPI_ausf_info_s OpenAPI_ausf_info_t;
typedef struct OpenAPI_ausf_info_s {
char *group_id;
OpenAPI_list_t *supi_ranges;
OpenAPI_list_t *routing_indicators;
} OpenAPI_ausf_info_t;
OpenAPI_ausf_info_t *OpenAPI_ausf_info_create(
char *group_id,
OpenAPI_list_t *supi_ranges,
OpenAPI_list_t *routing_indicators
);
void OpenAPI_ausf_info_free(OpenAPI_ausf_info_t *ausf_info);
OpenAPI_ausf_info_t *OpenAPI_ausf_info_parseFromJSON(cJSON *ausf_infoJSON);
cJSON *OpenAPI_ausf_info_convertToJSON(OpenAPI_ausf_info_t *ausf_info);
#ifdef __cplusplus
}
#endif
#endif /* _OpenAPI_ausf_info_H_ */

View File

@ -0,0 +1,237 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "bsf_info.h"
OpenAPI_bsf_info_t *OpenAPI_bsf_info_create(
OpenAPI_list_t *dnn_list,
OpenAPI_list_t *ip_domain_list,
OpenAPI_list_t *ipv4_address_ranges,
OpenAPI_list_t *ipv6_prefix_ranges
)
{
OpenAPI_bsf_info_t *bsf_info_local_var = OpenAPI_malloc(sizeof(OpenAPI_bsf_info_t));
if (!bsf_info_local_var) {
return NULL;
}
bsf_info_local_var->dnn_list = dnn_list;
bsf_info_local_var->ip_domain_list = ip_domain_list;
bsf_info_local_var->ipv4_address_ranges = ipv4_address_ranges;
bsf_info_local_var->ipv6_prefix_ranges = ipv6_prefix_ranges;
return bsf_info_local_var;
}
void OpenAPI_bsf_info_free(OpenAPI_bsf_info_t *bsf_info)
{
if (NULL == bsf_info) {
return;
}
OpenAPI_lnode_t *node;
OpenAPI_list_for_each(bsf_info->dnn_list, node) {
ogs_free(node->data);
}
OpenAPI_list_free(bsf_info->dnn_list);
OpenAPI_list_for_each(bsf_info->ip_domain_list, node) {
ogs_free(node->data);
}
OpenAPI_list_free(bsf_info->ip_domain_list);
OpenAPI_list_for_each(bsf_info->ipv4_address_ranges, node) {
OpenAPI_ipv4_address_range_free(node->data);
}
OpenAPI_list_free(bsf_info->ipv4_address_ranges);
OpenAPI_list_for_each(bsf_info->ipv6_prefix_ranges, node) {
OpenAPI_ipv6_prefix_range_free(node->data);
}
OpenAPI_list_free(bsf_info->ipv6_prefix_ranges);
ogs_free(bsf_info);
}
cJSON *OpenAPI_bsf_info_convertToJSON(OpenAPI_bsf_info_t *bsf_info)
{
cJSON *item = NULL;
if (bsf_info == NULL) {
ogs_error("OpenAPI_bsf_info_convertToJSON() failed [BsfInfo]");
return NULL;
}
item = cJSON_CreateObject();
if (bsf_info->dnn_list) {
cJSON *dnn_list = cJSON_AddArrayToObject(item, "dnnList");
if (dnn_list == NULL) {
ogs_error("OpenAPI_bsf_info_convertToJSON() failed [dnn_list]");
goto end;
}
OpenAPI_lnode_t *dnn_list_node;
OpenAPI_list_for_each(bsf_info->dnn_list, dnn_list_node) {
if (cJSON_AddStringToObject(dnn_list, "", (char*)dnn_list_node->data) == NULL) {
ogs_error("OpenAPI_bsf_info_convertToJSON() failed [dnn_list]");
goto end;
}
}
}
if (bsf_info->ip_domain_list) {
cJSON *ip_domain_list = cJSON_AddArrayToObject(item, "ipDomainList");
if (ip_domain_list == NULL) {
ogs_error("OpenAPI_bsf_info_convertToJSON() failed [ip_domain_list]");
goto end;
}
OpenAPI_lnode_t *ip_domain_list_node;
OpenAPI_list_for_each(bsf_info->ip_domain_list, ip_domain_list_node) {
if (cJSON_AddStringToObject(ip_domain_list, "", (char*)ip_domain_list_node->data) == NULL) {
ogs_error("OpenAPI_bsf_info_convertToJSON() failed [ip_domain_list]");
goto end;
}
}
}
if (bsf_info->ipv4_address_ranges) {
cJSON *ipv4_address_rangesList = cJSON_AddArrayToObject(item, "ipv4AddressRanges");
if (ipv4_address_rangesList == NULL) {
ogs_error("OpenAPI_bsf_info_convertToJSON() failed [ipv4_address_ranges]");
goto end;
}
OpenAPI_lnode_t *ipv4_address_ranges_node;
if (bsf_info->ipv4_address_ranges) {
OpenAPI_list_for_each(bsf_info->ipv4_address_ranges, ipv4_address_ranges_node) {
cJSON *itemLocal = OpenAPI_ipv4_address_range_convertToJSON(ipv4_address_ranges_node->data);
if (itemLocal == NULL) {
ogs_error("OpenAPI_bsf_info_convertToJSON() failed [ipv4_address_ranges]");
goto end;
}
cJSON_AddItemToArray(ipv4_address_rangesList, itemLocal);
}
}
}
if (bsf_info->ipv6_prefix_ranges) {
cJSON *ipv6_prefix_rangesList = cJSON_AddArrayToObject(item, "ipv6PrefixRanges");
if (ipv6_prefix_rangesList == NULL) {
ogs_error("OpenAPI_bsf_info_convertToJSON() failed [ipv6_prefix_ranges]");
goto end;
}
OpenAPI_lnode_t *ipv6_prefix_ranges_node;
if (bsf_info->ipv6_prefix_ranges) {
OpenAPI_list_for_each(bsf_info->ipv6_prefix_ranges, ipv6_prefix_ranges_node) {
cJSON *itemLocal = OpenAPI_ipv6_prefix_range_convertToJSON(ipv6_prefix_ranges_node->data);
if (itemLocal == NULL) {
ogs_error("OpenAPI_bsf_info_convertToJSON() failed [ipv6_prefix_ranges]");
goto end;
}
cJSON_AddItemToArray(ipv6_prefix_rangesList, itemLocal);
}
}
}
end:
return item;
}
OpenAPI_bsf_info_t *OpenAPI_bsf_info_parseFromJSON(cJSON *bsf_infoJSON)
{
OpenAPI_bsf_info_t *bsf_info_local_var = NULL;
cJSON *dnn_list = cJSON_GetObjectItemCaseSensitive(bsf_infoJSON, "dnnList");
OpenAPI_list_t *dnn_listList;
if (dnn_list) {
cJSON *dnn_list_local;
if (!cJSON_IsArray(dnn_list)) {
ogs_error("OpenAPI_bsf_info_parseFromJSON() failed [dnn_list]");
goto end;
}
dnn_listList = OpenAPI_list_create();
cJSON_ArrayForEach(dnn_list_local, dnn_list) {
if (!cJSON_IsString(dnn_list_local)) {
ogs_error("OpenAPI_bsf_info_parseFromJSON() failed [dnn_list]");
goto end;
}
OpenAPI_list_add(dnn_listList, ogs_strdup(dnn_list_local->valuestring));
}
}
cJSON *ip_domain_list = cJSON_GetObjectItemCaseSensitive(bsf_infoJSON, "ipDomainList");
OpenAPI_list_t *ip_domain_listList;
if (ip_domain_list) {
cJSON *ip_domain_list_local;
if (!cJSON_IsArray(ip_domain_list)) {
ogs_error("OpenAPI_bsf_info_parseFromJSON() failed [ip_domain_list]");
goto end;
}
ip_domain_listList = OpenAPI_list_create();
cJSON_ArrayForEach(ip_domain_list_local, ip_domain_list) {
if (!cJSON_IsString(ip_domain_list_local)) {
ogs_error("OpenAPI_bsf_info_parseFromJSON() failed [ip_domain_list]");
goto end;
}
OpenAPI_list_add(ip_domain_listList, ogs_strdup(ip_domain_list_local->valuestring));
}
}
cJSON *ipv4_address_ranges = cJSON_GetObjectItemCaseSensitive(bsf_infoJSON, "ipv4AddressRanges");
OpenAPI_list_t *ipv4_address_rangesList;
if (ipv4_address_ranges) {
cJSON *ipv4_address_ranges_local_nonprimitive;
if (!cJSON_IsArray(ipv4_address_ranges)) {
ogs_error("OpenAPI_bsf_info_parseFromJSON() failed [ipv4_address_ranges]");
goto end;
}
ipv4_address_rangesList = OpenAPI_list_create();
cJSON_ArrayForEach(ipv4_address_ranges_local_nonprimitive, ipv4_address_ranges ) {
if (!cJSON_IsObject(ipv4_address_ranges_local_nonprimitive)) {
ogs_error("OpenAPI_bsf_info_parseFromJSON() failed [ipv4_address_ranges]");
goto end;
}
OpenAPI_ipv4_address_range_t *ipv4_address_rangesItem = OpenAPI_ipv4_address_range_parseFromJSON(ipv4_address_ranges_local_nonprimitive);
OpenAPI_list_add(ipv4_address_rangesList, ipv4_address_rangesItem);
}
}
cJSON *ipv6_prefix_ranges = cJSON_GetObjectItemCaseSensitive(bsf_infoJSON, "ipv6PrefixRanges");
OpenAPI_list_t *ipv6_prefix_rangesList;
if (ipv6_prefix_ranges) {
cJSON *ipv6_prefix_ranges_local_nonprimitive;
if (!cJSON_IsArray(ipv6_prefix_ranges)) {
ogs_error("OpenAPI_bsf_info_parseFromJSON() failed [ipv6_prefix_ranges]");
goto end;
}
ipv6_prefix_rangesList = OpenAPI_list_create();
cJSON_ArrayForEach(ipv6_prefix_ranges_local_nonprimitive, ipv6_prefix_ranges ) {
if (!cJSON_IsObject(ipv6_prefix_ranges_local_nonprimitive)) {
ogs_error("OpenAPI_bsf_info_parseFromJSON() failed [ipv6_prefix_ranges]");
goto end;
}
OpenAPI_ipv6_prefix_range_t *ipv6_prefix_rangesItem = OpenAPI_ipv6_prefix_range_parseFromJSON(ipv6_prefix_ranges_local_nonprimitive);
OpenAPI_list_add(ipv6_prefix_rangesList, ipv6_prefix_rangesItem);
}
}
bsf_info_local_var = OpenAPI_bsf_info_create (
dnn_list ? dnn_listList : NULL,
ip_domain_list ? ip_domain_listList : NULL,
ipv4_address_ranges ? ipv4_address_rangesList : NULL,
ipv6_prefix_ranges ? ipv6_prefix_rangesList : NULL
);
return bsf_info_local_var;
end:
return NULL;
}

Some files were not shown because too many files have changed in this diff Show More