diff --git a/configs/open5gs/amf.yaml.in b/configs/open5gs/amf.yaml.in index e7b4ff130..eebd45a93 100644 --- a/configs/open5gs/amf.yaml.in +++ b/configs/open5gs/amf.yaml.in @@ -73,6 +73,18 @@ logger: # - 127.0.0.99 # - ::1 # +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.5 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# # > # # o NGAP Server(all address avaiable) @@ -96,6 +108,43 @@ logger: # ngap: # dev: eth0 # +# o NGAP Option (Default) +# - sctp_nodelay : true +# - so_linger.l_onoff : false +# +# ngap: +# addr: 127.0.0.5 +# option: +# stcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# +# o NGAP SCTP Option (Default) +# - spp_hbinterval : 5000 (5secs) +# - spp_sackdelay : 200 (200ms) +# - srto_initial : 3000 (3secs) +# - srto_min : 1000 (1sec) +# - srto_max : 5000 (5secs) +# - sinit_num_ostreams : 30 +# - sinit_max_instreams : 65535 +# - sinit_max_attempts : 4 +# - sinit_max_init_timeo : 8000(8secs) +# +# ngap: +# addr: 127.0.0.5 +# option: +# sctp: +# spp_hbinterval : 5000 +# spp_sackdelay : 200 +# srto_initial : 3000 +# srto_min : 1000 +# srto_max : 5000 +# sinit_num_ostreams : 30 +# sinit_max_instreams : 65535 +# sinit_max_attempts : 4 +# sinit_max_init_timeo : 8000 +# # # # o Multiple GUAMI @@ -232,6 +281,18 @@ amf: # - 127.0.0.10 # - fd69:f21d:873c:fa::1 # +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.10 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# nrf: sbi: - addr: @@ -288,26 +349,10 @@ max: pool: # -# sockopt: -# no_delay : true -# bindtodevice : false +# usrsctp: +# udp_port : 9899 # -sockopt: - -# -# sctp: -# heartbit_interval : 5000 (5secs) -# sack_delay : 200 (200ms) -# rto_initial : 3000 (3secs) -# rto_min : 1000 (1sec) -# rto_max : 5000 (5secs) -# max_num_of_ostreams : 30 -# max_num_of_istreams : 65535 -# max_attempts : 4 -# max_initial_timeout : 8000(8secs) -# usrsctp_udp_port : 9899 -# -sctp: +usrsctp: # # time: diff --git a/configs/open5gs/ausf.yaml.in b/configs/open5gs/ausf.yaml.in index 214c53aca..053824bb8 100644 --- a/configs/open5gs/ausf.yaml.in +++ b/configs/open5gs/ausf.yaml.in @@ -73,6 +73,18 @@ logger: # - 127.0.0.99 # - ::1 # +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.11 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# ausf: sbi: - addr: 127.0.0.11 @@ -104,6 +116,18 @@ ausf: # - 127.0.0.10 # - fd69:f21d:873c:fa::1 # +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.10 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# nrf: sbi: - addr: diff --git a/configs/open5gs/bsf.yaml.in b/configs/open5gs/bsf.yaml.in index b4e0b6eb8..63584e416 100644 --- a/configs/open5gs/bsf.yaml.in +++ b/configs/open5gs/bsf.yaml.in @@ -75,6 +75,18 @@ logger: # - 127.0.0.99 # - ::1 # +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.15 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# bsf: sbi: - addr: 127.0.0.15 @@ -106,6 +118,18 @@ bsf: # - 127.0.0.10 # - fd69:f21d:873c:fa::1 # +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.10 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# nrf: sbi: - addr: diff --git a/configs/open5gs/mme.yaml.in b/configs/open5gs/mme.yaml.in index 5004402f0..0345bbbaf 100644 --- a/configs/open5gs/mme.yaml.in +++ b/configs/open5gs/mme.yaml.in @@ -47,6 +47,43 @@ logger: # s1ap: # dev: eth0 # +# o S1AP Option (Default) +# - sctp_nodelay : true +# - so_linger.l_onoff : false +# +# s1ap: +# addr: 127.0.0.2 +# option: +# stcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# +# o S1AP SCTP Option (Default) +# - spp_hbinterval : 5000 (5secs) +# - spp_sackdelay : 200 (200ms) +# - srto_initial : 3000 (3secs) +# - srto_min : 1000 (1sec) +# - srto_max : 5000 (5secs) +# - sinit_num_ostreams : 30 +# - sinit_max_instreams : 65535 +# - sinit_max_attempts : 4 +# - sinit_max_init_timeo : 8000(8secs) +# +# s1ap: +# addr: 127.0.0.2 +# option: +# sctp: +# spp_hbinterval : 5000 +# spp_sackdelay : 200 +# srto_initial : 3000 +# srto_min : 1000 +# srto_max : 5000 +# sinit_num_ostreams : 30 +# sinit_max_instreams : 65535 +# sinit_max_attempts : 4 +# sinit_max_init_timeo : 8000 +# # > # # o GTP-C Server(all address avaiable) @@ -386,26 +423,10 @@ max: pool: # -# sockopt: -# no_delay : true -# bindtodevice : false +# usrsctp: +# udp_port : 9899 # -sockopt: - -# -# sctp: -# heartbit_interval : 5000 (5secs) -# sack_delay : 200 (200ms) -# rto_initial : 3000 (3secs) -# rto_min : 1000 (1sec) -# rto_max : 5000 (5secs) -# max_num_of_ostreams : 30 -# max_num_of_istreams : 65535 -# max_attempts : 4 -# max_initial_timeout : 8000(8secs) -# usrsctp_udp_port : 9899 -# -sctp: +usrsctp: # # time: diff --git a/configs/open5gs/nrf.yaml.in b/configs/open5gs/nrf.yaml.in index e9db8ab8f..86ac5716e 100644 --- a/configs/open5gs/nrf.yaml.in +++ b/configs/open5gs/nrf.yaml.in @@ -65,6 +65,18 @@ logger: # sbi: # dev: eth0 # +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.10 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# nrf: sbi: addr: diff --git a/configs/open5gs/nssf.yaml.in b/configs/open5gs/nssf.yaml.in index a02871293..c581304b4 100644 --- a/configs/open5gs/nssf.yaml.in +++ b/configs/open5gs/nssf.yaml.in @@ -73,6 +73,18 @@ logger: # - 127.0.0.99 # - ::1 # +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.14 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# # # # o One NSI @@ -110,6 +122,18 @@ logger: # s_nssai: # sst: 1 # sd: 009000 +# +# o NSI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# nsi: +# addr: ::1 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 nssf: sbi: - addr: 127.0.0.14 diff --git a/configs/open5gs/pcf.yaml.in b/configs/open5gs/pcf.yaml.in index 3d12e97ea..aa0efb389 100644 --- a/configs/open5gs/pcf.yaml.in +++ b/configs/open5gs/pcf.yaml.in @@ -75,6 +75,18 @@ logger: # - 127.0.0.99 # - ::1 # +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.13 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# pcf: sbi: - addr: 127.0.0.13 @@ -106,6 +118,18 @@ pcf: # - 127.0.0.10 # - fd69:f21d:873c:fa::1 # +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.10 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# nrf: sbi: - addr: diff --git a/configs/open5gs/sgwc.yaml.in b/configs/open5gs/sgwc.yaml.in index 3306273c7..750e66c7d 100644 --- a/configs/open5gs/sgwc.yaml.in +++ b/configs/open5gs/sgwc.yaml.in @@ -38,6 +38,14 @@ logger: # - addr: 127.0.0.3 # - addr: fd69:f21d:873c:fa::2 # +# o GTP-C Option (Default) +# - so_bindtodevice : NULL +# +# gtpc: +# addr: 127.0.0.3 +# option: +# so_bindtodevice: vrf-blue +# # # # o PFCP Server(127.0.0.3:8805, ::1:8805) @@ -49,6 +57,14 @@ logger: # pfcp: # name: localhost # +# o PFCP Option (Default) +# - so_bindtodevice : NULL +# +# pfcp: +# addr: 127.0.0.3 +# option: +# so_bindtodevice: vrf-blue +# sgwc: gtpc: - addr: 127.0.0.3 @@ -160,12 +176,6 @@ max: # pool: -# -# sockopt: -# bindtodevice : false -# -sockopt: - # # time: # diff --git a/configs/open5gs/sgwu.yaml.in b/configs/open5gs/sgwu.yaml.in index 4f7fd84e5..e87d27885 100644 --- a/configs/open5gs/sgwu.yaml.in +++ b/configs/open5gs/sgwu.yaml.in @@ -35,6 +35,14 @@ logger: # pfcp: # - name: localhost # +# o PFCP Option (Default) +# - so_bindtodevice : NULL +# +# pfcp: +# addr: 127.0.0.6 +# option: +# so_bindtodevice: vrf-blue +# # # # o GTP-U Server(127.0.0.6:2152, [::1]:2152) @@ -80,6 +88,14 @@ logger: # - dev: ens3 # advertise: sgw1.epc.mnc001.mcc001.3gppnetwork.org # +# o GTP-U Option (Default) +# - so_bindtodevice : NULL +# +# gtpu: +# addr: 127.0.0.6 +# option: +# so_bindtodevice: vrf-blue +# sgwu: pfcp: - addr: 127.0.0.6 @@ -149,13 +165,6 @@ max: # pool: -# -# sockopt: -# no_delay : true -# bindtodevice : false -# -sockopt: - # # time: # diff --git a/configs/open5gs/smf.yaml.in b/configs/open5gs/smf.yaml.in index 2015f7213..f9fce1dc3 100644 --- a/configs/open5gs/smf.yaml.in +++ b/configs/open5gs/smf.yaml.in @@ -73,6 +73,18 @@ logger: # - 127.0.0.99 # - ::1 # +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.4 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# # # # o PFCP Server(127.0.0.4:8805, ::1:8805) @@ -84,6 +96,14 @@ logger: # pfcp: # name: localhost # +# o PFCP Option (Default) +# - so_bindtodevice : NULL +# +# pfcp: +# addr: 127.0.0.4 +# option: +# so_bindtodevice: vrf-blue +# # # # o GTP-C Server(127.0.0.4:2123, [fd69:f21d:873c:fa::3]:2123) @@ -98,6 +118,14 @@ logger: # - addr: 127.0.0.4 # - addr: fd69:f21d:873c:fa::3 # +# o GTP-C Option (Default) +# - so_bindtodevice : NULL +# +# gtpc: +# addr: 127.0.0.4 +# option: +# so_bindtodevice: vrf-blue +# # > # # o GTP-U Server(127.0.0.4:2152, [::1]:2152) @@ -109,6 +137,14 @@ logger: # gtpu: # name: localhost # +# o GTP-U Option (Default) +# - so_bindtodevice : NULL +# +# gtpu: +# addr: 127.0.0.4 +# option: +# so_bindtodevice: vrf-blue +# # # # o IPv4 Pool @@ -377,6 +413,18 @@ smf: # - 127.0.0.10 # - fd69:f21d:873c:fa::1 # +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.10 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# nrf: sbi: - addr: @@ -498,12 +546,6 @@ max: # pool: -# -# sockopt: -# bindtodevice : false -# -sockopt: - # # time: # diff --git a/configs/open5gs/udm.yaml.in b/configs/open5gs/udm.yaml.in index d99b340c5..bb7a5b580 100644 --- a/configs/open5gs/udm.yaml.in +++ b/configs/open5gs/udm.yaml.in @@ -73,6 +73,18 @@ logger: # - 127.0.0.99 # - ::1 # +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.12 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# udm: sbi: - addr: 127.0.0.12 @@ -104,6 +116,18 @@ udm: # - 127.0.0.10 # - fd69:f21d:873c:fa::1 # +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.10 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# nrf: sbi: - addr: diff --git a/configs/open5gs/udr.yaml.in b/configs/open5gs/udr.yaml.in index 230c5fa7f..bf3a250e3 100644 --- a/configs/open5gs/udr.yaml.in +++ b/configs/open5gs/udr.yaml.in @@ -75,6 +75,18 @@ logger: # - 127.0.0.99 # - ::1 # +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.20 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# udr: sbi: - addr: 127.0.0.20 @@ -106,6 +118,18 @@ udr: # - 127.0.0.10 # - fd69:f21d:873c:fa::1 # +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.10 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# nrf: sbi: - addr: diff --git a/configs/open5gs/upf.yaml.in b/configs/open5gs/upf.yaml.in index 450df41b5..db520cf0d 100644 --- a/configs/open5gs/upf.yaml.in +++ b/configs/open5gs/upf.yaml.in @@ -35,6 +35,14 @@ logger: # pfcp: # name: localhost # +# o PFCP Option (Default) +# - so_bindtodevice : NULL +# +# pfcp: +# addr: 127.0.0.7 +# option: +# so_bindtodevice: vrf-blue +# # > # # o GTP-U Server(127.0.0.7:2152, [::1]:2152) @@ -80,6 +88,14 @@ logger: # - dev: ens3 # advertise: upf1.5gc.mnc001.mcc001.3gppnetwork.org # +# o GTP-U Option (Default) +# - so_bindtodevice : NULL +# +# gtpu: +# addr: 127.0.0.7 +# option: +# so_bindtodevice: vrf-blue +# # # # Note that you need to setup your UE network using TUN device. @@ -220,12 +236,6 @@ max: # pool: -# -# sockopt: -# bindtodevice : false -# -sockopt: - # # time: # diff --git a/lib/app/meson.build b/lib/app/meson.build index 828f1146f..0a23d713e 100644 --- a/lib/app/meson.build +++ b/lib/app/meson.build @@ -20,10 +20,12 @@ libapp_sources = files(''' ogs-yaml.h ogs-context.h + ogs-config.h ogs-init.h ogs-yaml.c ogs-context.c + ogs-config.c ogs-init.c '''.split()) diff --git a/lib/app/ogs-app.h b/lib/app/ogs-app.h index 019450c32..78a446c29 100644 --- a/lib/app/ogs-app.h +++ b/lib/app/ogs-app.h @@ -28,6 +28,7 @@ extern int __ogs_app_domain; #include "app/ogs-yaml.h" #include "app/ogs-context.h" +#include "app/ogs-config.h" #include "app/ogs-init.h" #undef OGS_APP_INSIDE diff --git a/lib/app/ogs-config.c b/lib/app/ogs-config.c new file mode 100644 index 000000000..244847c5d --- /dev/null +++ b/lib/app/ogs-config.c @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * 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 . + */ + +#include "ogs-app.h" + +int ogs_app_config_parse_sockopt( + ogs_yaml_iter_t *parent, ogs_sockopt_t *option) +{ + ogs_yaml_iter_t sockopt_iter; + + ogs_assert(parent); + ogs_assert(option); + + ogs_sockopt_init(option); + + ogs_yaml_iter_recurse(parent, &sockopt_iter); + while (ogs_yaml_iter_next(&sockopt_iter)) { + const char *sockopt_key = ogs_yaml_iter_key(&sockopt_iter); + ogs_assert(sockopt_key); + + if (!strcmp(sockopt_key, "sctp")) { + ogs_yaml_iter_t sctp_iter; + ogs_yaml_iter_recurse(&sockopt_iter, &sctp_iter); + + while (ogs_yaml_iter_next(&sctp_iter)) { + const char *sctp_key = ogs_yaml_iter_key(&sctp_iter); + ogs_assert(sctp_key); + if (!strcmp(sctp_key, "spp_hbinterval")) { + const char *v = ogs_yaml_iter_value(&sctp_iter); + if (v) option->sctp.spp_hbinterval = atoi(v); + } else if (!strcmp(sctp_key, "spp_sackdelay")) { + const char *v = ogs_yaml_iter_value(&sctp_iter); + if (v) option->sctp.spp_sackdelay = atoi(v); + } else if (!strcmp(sctp_key, "srto_initial")) { + const char *v = ogs_yaml_iter_value(&sctp_iter); + if (v) option->sctp.srto_initial = atoi(v); + } else if (!strcmp(sctp_key, "srto_min")) { + const char *v = ogs_yaml_iter_value(&sctp_iter); + if (v) option->sctp.srto_min = atoi(v); + } else if (!strcmp(sctp_key, "srto_max")) { + const char *v = ogs_yaml_iter_value(&sctp_iter); + if (v) option->sctp.srto_max = atoi(v); + } else if (!strcmp(sctp_key, "sinit_num_ostreams")) { + const char *v = ogs_yaml_iter_value(&sctp_iter); + if (v) option->sctp.sinit_num_ostreams = atoi(v); + } else if (!strcmp(sctp_key, "sinit_max_instreams")) { + const char *v = ogs_yaml_iter_value(&sctp_iter); + if (v) option->sctp.sinit_max_instreams = atoi(v); + } else if (!strcmp(sctp_key, "sinit_max_attempts")) { + const char *v = ogs_yaml_iter_value(&sctp_iter); + if (v) option->sctp.sinit_max_attempts = atoi(v); + } else if (!strcmp(sctp_key, "sinit_max_init_timeo")) { + const char *v = ogs_yaml_iter_value(&sctp_iter); + if (v) option->sctp.sinit_max_init_timeo = atoi(v); + } else { + ogs_error("unknown key `%s`", sctp_key); + return OGS_ERROR; + } + } + } else if (!strcmp(sockopt_key, "sctp_nodelay")) { + option->sctp_nodelay = ogs_yaml_iter_bool(&sockopt_iter); + } else if (!strcmp(sockopt_key, "tcp_nodelay")) { + option->tcp_nodelay = ogs_yaml_iter_bool(&sockopt_iter); + + } else if (!strcmp(sockopt_key, "so_linger")) { + ogs_yaml_iter_t so_linger_iter; + ogs_yaml_iter_recurse(&sockopt_iter, &so_linger_iter); + + while (ogs_yaml_iter_next(&so_linger_iter)) { + const char *so_linger_key = ogs_yaml_iter_key(&so_linger_iter); + ogs_assert(so_linger_key); + if (!strcmp(so_linger_key, "l_onoff")) { + option->so_linger.l_onoff = + ogs_yaml_iter_bool(&so_linger_iter); + } else if (!strcmp(so_linger_key, "l_linger")) { + const char *v = ogs_yaml_iter_value(&so_linger_iter); + if (v) option->so_linger.l_linger = atoi(v); + } else { + ogs_error("unknown key `%s`", so_linger_key); + return OGS_ERROR; + } + } + + } else if (!strcmp(sockopt_key, "so_bindtodevice")) { + option->so_bindtodevice = ogs_yaml_iter_value(&sockopt_iter); + + } else { + ogs_error("unknown key `%s`", sockopt_key); + return OGS_ERROR; + } + } + + return OGS_OK; +} diff --git a/lib/app/ogs-config.h b/lib/app/ogs-config.h new file mode 100644 index 000000000..ce681edbb --- /dev/null +++ b/lib/app/ogs-config.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * 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 . + */ + +#if !defined(OGS_APP_INSIDE) && !defined(OGS_APP_COMPILATION) +#error "This header cannot be included directly." +#endif + +#ifndef OGS_APP_CONFIG_H +#define OGS_APP_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +int ogs_app_config_parse_sockopt( + ogs_yaml_iter_t *parent, ogs_sockopt_t *sockopt); + +#ifdef __cplusplus +} +#endif + +#endif /* OGS_APP_CONFIG_H */ diff --git a/lib/app/ogs-context.c b/lib/app/ogs-context.c index cd1937bd5..a76d02f28 100644 --- a/lib/app/ogs-context.c +++ b/lib/app/ogs-context.c @@ -187,7 +187,6 @@ static void app_context_prepare(void) self.sctp.max_initial_timeout = 8000; /* 8 seconds */ self.sockopt.no_delay = true; - self.sockopt.bindtodevice = false; #define MAX_NUM_OF_UE 1024 /* Num of UE per AMF/MME */ #define MAX_NUM_OF_GNB 64 /* Num of gNB per AMF/MME */ @@ -377,9 +376,6 @@ int ogs_app_context_parse_config(void) const char *v = ogs_yaml_iter_value(&sockopt_iter); if (v) self.sockopt.l_linger = atoi(v); self.sockopt.l_onoff = true; - } else if (!strcmp(sockopt_key, "bindtodevice")) { - self.sockopt.bindtodevice = - ogs_yaml_iter_bool(&sockopt_iter); } else ogs_warn("unknown key `%s`", sockopt_key); } diff --git a/lib/app/ogs-context.h b/lib/app/ogs-context.h index f82a14134..d0db2cd16 100644 --- a/lib/app/ogs-context.h +++ b/lib/app/ogs-context.h @@ -24,8 +24,6 @@ #ifndef OGS_APP_CONTEXT_H #define OGS_APP_CONTEXT_H -#include "ogs-app.h" - #ifdef __cplusplus extern "C" { #endif @@ -84,7 +82,6 @@ typedef struct ogs_app_context_s { int no_delay; int l_onoff; int l_linger; - int bindtodevice; } sockopt; struct { diff --git a/lib/app/ogs-yaml.c b/lib/app/ogs-yaml.c index b8b238f72..bffb531b5 100644 --- a/lib/app/ogs-yaml.c +++ b/lib/app/ogs-yaml.c @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -#include "ogs-yaml.h" +#include "ogs-app.h" void ogs_yaml_iter_init(ogs_yaml_iter_t *iter, yaml_document_t *document) { diff --git a/lib/app/ogs-yaml.h b/lib/app/ogs-yaml.h index be4c69bcd..5a3e9752a 100644 --- a/lib/app/ogs-yaml.h +++ b/lib/app/ogs-yaml.h @@ -26,8 +26,6 @@ #include -#include "ogs-app.h" - #ifdef __cplusplus extern "C" { #endif diff --git a/lib/core/meson.build b/lib/core/meson.build index 2b6b4cd9c..ddc0e9dbc 100644 --- a/lib/core/meson.build +++ b/lib/core/meson.build @@ -241,6 +241,7 @@ libcore_sources = files(''' ogs-process.h ogs-sockaddr.h ogs-socket.h + ogs-sockopt.h ogs-sockpair.h ogs-socknode.h ogs-udp.h @@ -275,6 +276,7 @@ libcore_sources = files(''' ogs-process.c ogs-sockaddr.c ogs-socket.c + ogs-sockopt.c ogs-sockpair.c ogs-socknode.c ogs-udp.c diff --git a/lib/core/ogs-core.h b/lib/core/ogs-core.h index f4e1dbb51..ca4a523bc 100644 --- a/lib/core/ogs-core.h +++ b/lib/core/ogs-core.h @@ -47,6 +47,7 @@ #include "core/ogs-signal.h" #include "core/ogs-sockaddr.h" #include "core/ogs-socket.h" +#include "core/ogs-sockopt.h" #include "core/ogs-sockpair.h" #include "core/ogs-socknode.h" #include "core/ogs-udp.h" diff --git a/lib/core/ogs-socket.c b/lib/core/ogs-socket.c index e5e4a199a..f7299c73a 100644 --- a/lib/core/ogs-socket.c +++ b/lib/core/ogs-socket.c @@ -255,102 +255,3 @@ int ogs_closesocket(ogs_socket_t fd) return OGS_OK; } - -int ogs_nonblocking(ogs_socket_t fd) -{ -#ifdef _WIN32 - int rc; - ogs_assert(fd != INVALID_SOCKET); - - u_long io_mode = 1; - rc = ioctlsocket(fd, FIONBIO, &io_mode); - if (rc != OGS_OK) { - ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "ioctlsocket failed"); - return OGS_ERROR; - } -#else - int rc; - int flags; - ogs_assert(fd != INVALID_SOCKET); - - flags = fcntl(fd, F_GETFL, NULL); - if (flags < 0) { - ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "F_GETFL failed"); - return OGS_ERROR; - } - if (!(flags & O_NONBLOCK)) { - rc = fcntl(fd, F_SETFL, (flags | O_NONBLOCK)); - if (rc != OGS_OK) { - ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "F_SETFL failed"); - return OGS_ERROR; - } - } -#endif - - return OGS_OK; -} - -int ogs_closeonexec(ogs_socket_t fd) -{ -#ifndef _WIN32 - int rc; - int flags; - - ogs_assert(fd != INVALID_SOCKET); - flags = fcntl(fd, F_GETFD, NULL); - if (flags < 0) { - ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "F_GETFD failed"); - return OGS_ERROR; - } - if (!(flags & FD_CLOEXEC)) { - rc = fcntl(fd, F_SETFD, (flags | FD_CLOEXEC)); - if (rc != OGS_OK) { - ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "F_SETFD failed"); - return OGS_ERROR; - } - } -#endif - - return OGS_OK; -} - -int ogs_listen_reusable(ogs_socket_t fd) -{ -#if defined(SO_REUSEADDR) && !defined(_WIN32) - int rc; - int on = 1; - - ogs_assert(fd != INVALID_SOCKET); - rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(int)); - if (rc != OGS_OK) { - ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, - "setsockopt(SOL_SOCKET, SO_REUSEADDR) failed"); - return OGS_ERROR; - } -#endif - - return OGS_OK; -} - -int ogs_bind_to_device(ogs_socket_t fd, const char *device) -{ -#if defined(SO_BINDTODEVICE) && !defined(_WIN32) - int rc; - - ogs_assert(fd != INVALID_SOCKET); - ogs_assert(device); - rc = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)+1); - if (rc != OGS_OK) { - ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, - "setsockopt(SOL_SOCKET, SO_BINDTODEVICE, %s) failed", device); - ogs_error("You need to grant privileges to use SO_BINDTODEVICE."); - ogs_error("OR disable SO_BINDTODEVICE " - "in the configuration file as below."); - ogs_log_print(OGS_LOG_ERROR, "\nsockopt:\n"); - ogs_log_print(OGS_LOG_ERROR, " bindtodevice : false\n\n"); - return OGS_ERROR; - } -#endif - - return OGS_OK; -} diff --git a/lib/core/ogs-socket.h b/lib/core/ogs-socket.h index bd1e6f202..360bf00b8 100644 --- a/lib/core/ogs-socket.h +++ b/lib/core/ogs-socket.h @@ -71,11 +71,6 @@ ssize_t ogs_recvfrom(ogs_socket_t fd, int ogs_closesocket(ogs_socket_t fd); -int ogs_nonblocking(ogs_socket_t fd); -int ogs_closeonexec(ogs_socket_t fd); -int ogs_listen_reusable(ogs_socket_t fd); -int ogs_bind_to_device(ogs_socket_t fd, const char *device); - #ifdef __cplusplus } #endif diff --git a/lib/core/ogs-socknode.c b/lib/core/ogs-socknode.c index cb566f77b..391d67391 100644 --- a/lib/core/ogs-socknode.c +++ b/lib/core/ogs-socknode.c @@ -61,11 +61,13 @@ void ogs_socknode_free(ogs_socknode_t *node) else ogs_sock_destroy(node->sock); } + if (node->option) + ogs_free(node->option); ogs_free(node); } -ogs_socknode_t *ogs_socknode_add( - ogs_list_t *list, int family, ogs_sockaddr_t *addr) +ogs_socknode_t *ogs_socknode_add(ogs_list_t *list, + int family, ogs_sockaddr_t *addr, ogs_sockopt_t *option) { ogs_socknode_t *node = NULL; ogs_sockaddr_t *dup = NULL; @@ -81,6 +83,9 @@ ogs_socknode_t *ogs_socknode_add( node = ogs_socknode_new(dup); ogs_assert(node); ogs_list_add(list, node); + + if (option) + node->option = ogs_memdup(option, sizeof *option); } return node; @@ -102,8 +107,8 @@ void ogs_socknode_remove_all(ogs_list_t *list) ogs_socknode_remove(list, node); } -int ogs_socknode_probe( - ogs_list_t *list, ogs_list_t *list6, const char *dev, uint16_t port) +int ogs_socknode_probe(ogs_list_t *list, ogs_list_t *list6, + const char *dev, uint16_t port, ogs_sockopt_t *option) { #if defined(HAVE_GETIFADDRS) ogs_socknode_t *node = NULL; @@ -177,6 +182,9 @@ int ogs_socknode_probe( ogs_list_add(list6, node); } else ogs_assert_if_reached(); + + if (option) + node->option = ogs_memdup(option, sizeof *option); } freeifaddrs(iflist); @@ -190,6 +198,7 @@ int ogs_socknode_probe( } +#if 0 /* deprecated */ int ogs_socknode_fill_scope_id_in_local(ogs_sockaddr_t *sa_list) { #if defined(HAVE_GETIFADDRS) @@ -247,6 +256,7 @@ int ogs_socknode_fill_scope_id_in_local(ogs_sockaddr_t *sa_list) return OGS_ERROR; #endif } +#endif void ogs_socknode_set_cleanup( ogs_socknode_t *node, void (*cleanup)(ogs_sock_t *)) diff --git a/lib/core/ogs-socknode.h b/lib/core/ogs-socknode.h index 2158e061b..47de859f7 100644 --- a/lib/core/ogs-socknode.h +++ b/lib/core/ogs-socknode.h @@ -35,24 +35,28 @@ typedef struct ogs_socknode_s { ogs_lnode_t node; ogs_sockaddr_t *addr; - char *dev; /* !NULL: used with SO_BINDTODEVICE */ + char *dev; ogs_sock_t *sock; void (*cleanup)(ogs_sock_t *sock); ogs_poll_t *poll; + + ogs_sockopt_t *option; } ogs_socknode_t; ogs_socknode_t *ogs_socknode_new(ogs_sockaddr_t *addr); void ogs_socknode_free(ogs_socknode_t *node); -ogs_socknode_t *ogs_socknode_add( - ogs_list_t *list, int family, ogs_sockaddr_t *sa_list); +ogs_socknode_t *ogs_socknode_add(ogs_list_t *list, + int family, ogs_sockaddr_t *addr, ogs_sockopt_t *option); void ogs_socknode_remove(ogs_list_t *list, ogs_socknode_t *node); void ogs_socknode_remove_all(ogs_list_t *list); -int ogs_socknode_probe( - ogs_list_t *list, ogs_list_t *list6, const char *dev, uint16_t port); +int ogs_socknode_probe(ogs_list_t *list, ogs_list_t *list6, + const char *dev, uint16_t port, ogs_sockopt_t *option); +#if 0 /* deprecated */ int ogs_socknode_fill_scope_id_in_local(ogs_sockaddr_t *sa_list); +#endif void ogs_socknode_set_cleanup( ogs_socknode_t *node, void (*cleanup)(ogs_sock_t *)); diff --git a/lib/core/ogs-sockopt.c b/lib/core/ogs-sockopt.c new file mode 100644 index 000000000..5caeeb12c --- /dev/null +++ b/lib/core/ogs-sockopt.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * 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 . + */ + +#include "core-config-private.h" + +#if HAVE_FCNTL_H +#include +#endif + +#if HAVE_NETINET_TCP_H +#include +#endif + +#include "ogs-core.h" + +#undef OGS_LOG_DOMAIN +#define OGS_LOG_DOMAIN __ogs_sock_domain + +void ogs_sockopt_init(ogs_sockopt_t *option) +{ + ogs_assert(option); + + memset(option, 0, sizeof *option); + + option->sctp.spp_hbinterval = 5000; /* 5 seconds */ + option->sctp.spp_sackdelay = 200; /* 200 ms */ + option->sctp.srto_initial = 3000; /* 3 seconds */ + option->sctp.srto_min = 1000; /* 1 seconds */ + option->sctp.srto_max = 5000; /* 5 seconds */ + option->sctp.sinit_num_ostreams = OGS_DEFAULT_SCTP_MAX_NUM_OF_OSTREAMS; + option->sctp.sinit_max_instreams = 65535; + option->sctp.sinit_max_attempts = 4; + option->sctp.sinit_max_init_timeo = 8000; /* 8 seconds */ + + option->sctp_nodelay = true; + option->tcp_nodelay = true; +} + +int ogs_nonblocking(ogs_socket_t fd) +{ +#ifdef _WIN32 + int rc; + ogs_assert(fd != INVALID_SOCKET); + + u_long io_mode = 1; + rc = ioctlsocket(fd, FIONBIO, &io_mode); + if (rc != OGS_OK) { + ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "ioctlsocket failed"); + return OGS_ERROR; + } +#else + int rc; + int flags; + ogs_assert(fd != INVALID_SOCKET); + + flags = fcntl(fd, F_GETFL, NULL); + if (flags < 0) { + ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "F_GETFL failed"); + return OGS_ERROR; + } + if (!(flags & O_NONBLOCK)) { + rc = fcntl(fd, F_SETFL, (flags | O_NONBLOCK)); + if (rc != OGS_OK) { + ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "F_SETFL failed"); + return OGS_ERROR; + } + } +#endif + + return OGS_OK; +} + +int ogs_closeonexec(ogs_socket_t fd) +{ +#ifndef _WIN32 + int rc; + int flags; + + ogs_assert(fd != INVALID_SOCKET); + flags = fcntl(fd, F_GETFD, NULL); + if (flags < 0) { + ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "F_GETFD failed"); + return OGS_ERROR; + } + if (!(flags & FD_CLOEXEC)) { + rc = fcntl(fd, F_SETFD, (flags | FD_CLOEXEC)); + if (rc != OGS_OK) { + ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "F_SETFD failed"); + return OGS_ERROR; + } + } +#endif + + return OGS_OK; +} + +int ogs_listen_reusable(ogs_socket_t fd, int on) +{ +#if defined(SO_REUSEADDR) && !defined(_WIN32) + int rc; + + ogs_assert(fd != INVALID_SOCKET); + + ogs_debug("Turn on SO_REUSEADDR"); + rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(int)); + if (rc != OGS_OK) { + ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, + "setsockopt(SOL_SOCKET, SO_REUSEADDR) failed"); + return OGS_ERROR; + } +#endif + + return OGS_OK; +} + +int ogs_tcp_nodelay(ogs_socket_t fd, int on) +{ +#if defined(TCP_NODELAY) && !defined(_WIN32) + int rc; + + ogs_assert(fd != INVALID_SOCKET); + + ogs_debug("Turn on TCP_NODELAY"); + rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(int)); + if (rc != OGS_OK) { + ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, + "setsockopt(IPPROTO_TCP, TCP_NODELAY) failed"); + return OGS_ERROR; + } +#endif + + return OGS_OK; +} + +int ogs_so_linger(ogs_socket_t fd, int l_linger) +{ +#if defined(SO_LINGER) && !defined(_WIN32) + struct linger l; + int rc; + + ogs_assert(fd != INVALID_SOCKET); + + memset(&l, 0, sizeof(l)); + l.l_onoff = 1; + l.l_linger = l_linger; + + ogs_debug("SO_LINGER:[%d]", l_linger); + rc = setsockopt(fd, SOL_SOCKET, SO_LINGER, + (void *)&l, sizeof(struct linger)); + if (rc != OGS_OK) { + ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, + "setsockopt(SOL_SOCKET, SO_LINGER) failed"); + return OGS_ERROR; + } +#endif + + return OGS_OK; +} + +int ogs_bind_to_device(ogs_socket_t fd, const char *device) +{ +#if defined(SO_BINDTODEVICE) && !defined(_WIN32) + int rc; + + ogs_assert(fd != INVALID_SOCKET); + ogs_assert(device); + + ogs_debug("SO_BINDTODEVICE:[%s]", device); + rc = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)+1); + if (rc != OGS_OK) { + ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, + "setsockopt(SOL_SOCKET, SO_BINDTODEVICE, %s) failed", device); + ogs_error("You need to grant privileges to use SO_BINDTODEVICE."); + return OGS_ERROR; + } +#endif + + return OGS_OK; +} diff --git a/lib/core/ogs-sockopt.h b/lib/core/ogs-sockopt.h new file mode 100644 index 000000000..49d767469 --- /dev/null +++ b/lib/core/ogs-sockopt.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * 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 . + */ + +#if !defined(OGS_CORE_INSIDE) && !defined(OGS_CORE_COMPILATION) +#error "This header cannot be included directly." +#endif + +#ifndef OGS_SOCKOPT_H +#define OGS_SOCKOPT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ogs_sockopt_s { + struct { + uint32_t spp_hbinterval; + uint32_t spp_sackdelay; + uint32_t srto_initial; + uint32_t srto_min; + uint32_t srto_max; + uint16_t sinit_num_ostreams; + uint16_t sinit_max_instreams; + uint16_t sinit_max_attempts; + uint16_t sinit_max_init_timeo; + } sctp; + + bool sctp_nodelay; + bool tcp_nodelay; + + struct { + bool l_onoff; + int l_linger; + } so_linger; + + const char *so_bindtodevice; +} ogs_sockopt_t; + +void ogs_sockopt_init(ogs_sockopt_t *option); + +int ogs_nonblocking(ogs_socket_t fd); +int ogs_closeonexec(ogs_socket_t fd); +int ogs_listen_reusable(ogs_socket_t fd, int on); +int ogs_tcp_nodelay(ogs_socket_t fd, int on); +int ogs_so_linger(ogs_socket_t fd, int l_linger); +int ogs_bind_to_device(ogs_socket_t fd, const char *device); + +#ifdef __cplusplus +} +#endif + +#endif /* OGS_SOCKOPT_H */ diff --git a/lib/core/ogs-tcp.c b/lib/core/ogs-tcp.c index d757b4c30..136a46b52 100644 --- a/lib/core/ogs-tcp.c +++ b/lib/core/ogs-tcp.c @@ -22,21 +22,38 @@ #undef OGS_LOG_DOMAIN #define OGS_LOG_DOMAIN __ogs_sock_domain -ogs_sock_t *ogs_tcp_server(ogs_socknode_t *node) +ogs_sock_t *ogs_tcp_server( + ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option) { int rv; - ogs_sock_t *new = NULL; - ogs_sockaddr_t *addr; char buf[OGS_ADDRSTRLEN]; - ogs_assert(node); - ogs_assert(node->addr); + ogs_sock_t *new = NULL; + ogs_sockaddr_t *addr; + ogs_sockopt_t option; - addr = node->addr; + ogs_assert(sa_list); + + ogs_sockopt_init(&option); + if (socket_option) + memcpy(&option, socket_option, sizeof option); + + addr = sa_list; while(addr) { new = ogs_sock_socket(addr->ogs_sa_family, SOCK_STREAM, IPPROTO_TCP); if (new) { - rv = ogs_listen_reusable(new->fd); + if (option.tcp_nodelay == true) { + rv = ogs_tcp_nodelay(new->fd, true); + ogs_assert(rv == OGS_OK); + } else + ogs_warn("TCP NO_DELAY Disabled"); + + if (option.so_linger.l_onoff == true) { + rv = ogs_so_linger(new->fd, option.so_linger.l_linger); + ogs_assert(rv == OGS_OK); + } + + rv = ogs_listen_reusable(new->fd, true); ogs_assert(rv == OGS_OK); if (ogs_sock_bind(new, addr) == OGS_OK) { @@ -54,31 +71,47 @@ ogs_sock_t *ogs_tcp_server(ogs_socknode_t *node) if (addr == NULL) { ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "tcp_server() [%s]:%d failed", - OGS_ADDR(node->addr, buf), OGS_PORT(node->addr)); + OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); return NULL; } rv = ogs_sock_listen(new); ogs_assert(rv == OGS_OK); - node->sock = new; - return new; } -ogs_sock_t *ogs_tcp_client(ogs_socknode_t *node) +ogs_sock_t *ogs_tcp_client( + ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option) { - ogs_sock_t *new = NULL; - ogs_sockaddr_t *addr; + int rv; char buf[OGS_ADDRSTRLEN]; - ogs_assert(node); - ogs_assert(node->addr); + ogs_sock_t *new = NULL; + ogs_sockaddr_t *addr; + ogs_sockopt_t option; - addr = node->addr; + ogs_assert(sa_list); + + ogs_sockopt_init(&option); + if (socket_option) + memcpy(&option, socket_option, sizeof option); + + addr = sa_list; while (addr) { new = ogs_sock_socket(addr->ogs_sa_family, SOCK_STREAM, IPPROTO_TCP); if (new) { + if (option.sctp_nodelay == true) { + rv = ogs_tcp_nodelay(new->fd, true); + ogs_assert(rv == OGS_OK); + } else + ogs_warn("TCP NO_DELAY Disabled"); + + if (option.so_linger.l_onoff == true) { + rv = ogs_so_linger(new->fd, option.so_linger.l_linger); + ogs_assert(rv == OGS_OK); + } + if (ogs_sock_connect(new, addr) == OGS_OK) { ogs_debug("tcp_client() [%s]:%d", OGS_ADDR(addr, buf), OGS_PORT(addr)); @@ -94,11 +127,9 @@ ogs_sock_t *ogs_tcp_client(ogs_socknode_t *node) if (addr == NULL) { ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "tcp_client() [%s]:%d failed", - OGS_ADDR(node->addr, buf), OGS_PORT(node->addr)); + OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); return NULL; } - node->sock = new; - return new; } diff --git a/lib/core/ogs-tcp.h b/lib/core/ogs-tcp.h index bb646b93b..2fc39d95e 100644 --- a/lib/core/ogs-tcp.h +++ b/lib/core/ogs-tcp.h @@ -28,8 +28,10 @@ extern "C" { #endif -ogs_sock_t *ogs_tcp_server(ogs_socknode_t *node); -ogs_sock_t *ogs_tcp_client(ogs_socknode_t *node); +ogs_sock_t *ogs_tcp_server( + ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option); +ogs_sock_t *ogs_tcp_client( + ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option); #ifdef __cplusplus } diff --git a/lib/core/ogs-udp.c b/lib/core/ogs-udp.c index 486a5f9a3..45b58e952 100644 --- a/lib/core/ogs-udp.c +++ b/lib/core/ogs-udp.c @@ -22,29 +22,24 @@ #undef OGS_LOG_DOMAIN #define OGS_LOG_DOMAIN __ogs_sock_domain -ogs_sock_t *ogs_udp_socket(int family, ogs_socknode_t *node) +ogs_sock_t *ogs_udp_server( + ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option) { - ogs_sock_t *sock = NULL; - sock = ogs_sock_socket(family, SOCK_DGRAM, IPPROTO_UDP); - ogs_assert(sock); - - ogs_debug("udp_socket() family:%d", family); - - return sock; -} - -ogs_sock_t *ogs_udp_server(ogs_socknode_t *node, bool bindtodevice) -{ - ogs_sock_t *new = NULL; - ogs_sockaddr_t *addr; char buf[OGS_ADDRSTRLEN]; - ogs_assert(node); - ogs_assert(node->addr); + ogs_sock_t *new = NULL; + ogs_sockaddr_t *addr; + ogs_sockopt_t option; - addr = node->addr; + ogs_assert(sa_list); + + ogs_sockopt_init(&option); + if (socket_option) + memcpy(&option, socket_option, sizeof option); + + addr = sa_list; while (addr) { - new = ogs_udp_socket(addr->ogs_sa_family, node); + new = ogs_sock_socket(addr->ogs_sa_family, SOCK_DGRAM, IPPROTO_UDP); if (!new) { addr = addr->next; continue; @@ -55,14 +50,15 @@ ogs_sock_t *ogs_udp_server(ogs_socknode_t *node, bool bindtodevice) continue; } ogs_debug("udp_server() [%s]:%d", OGS_ADDR(addr, buf), OGS_PORT(addr)); - if (bindtodevice == true && node->dev) { - if (ogs_bind_to_device(new->fd, node->dev) != OGS_OK) { + if (option.so_bindtodevice) { + if (ogs_bind_to_device(new->fd, option.so_bindtodevice) != OGS_OK) { ogs_sock_destroy(new); addr = addr->next; continue; } - ogs_debug("udp_server() [%s]:%d bound to device %s", - OGS_ADDR(addr, buf), OGS_PORT(addr), node->dev); + ogs_info("udp_server() [%s]:%d bound to device `%s`", + OGS_ADDR(addr, buf), OGS_PORT(addr), + option.so_bindtodevice); } break; } @@ -70,27 +66,32 @@ ogs_sock_t *ogs_udp_server(ogs_socknode_t *node, bool bindtodevice) if (addr == NULL) { ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "udp_server() [%s]:%d failed", - OGS_ADDR(node->addr, buf), OGS_PORT(node->addr)); + OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); return NULL; } - node->sock = new; - return new; } -ogs_sock_t *ogs_udp_client(ogs_socknode_t *node) +ogs_sock_t *ogs_udp_client( + ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option) { - ogs_sock_t *new = NULL; - ogs_sockaddr_t *addr; char buf[OGS_ADDRSTRLEN]; - ogs_assert(node); - ogs_assert(node->addr); + ogs_sock_t *new = NULL; + ogs_sockaddr_t *addr; - addr = node->addr; + ogs_sockopt_t option; + + ogs_assert(sa_list); + + ogs_sockopt_init(&option); + if (socket_option) + memcpy(&option, socket_option, sizeof option); + + addr = sa_list; while (addr) { - new = ogs_udp_socket(addr->ogs_sa_family, node); + new = ogs_sock_socket(addr->ogs_sa_family, SOCK_DGRAM, IPPROTO_UDP); if (new) { if (ogs_sock_connect(new, addr) == OGS_OK) { ogs_debug("udp_client() [%s]:%d", @@ -107,12 +108,10 @@ ogs_sock_t *ogs_udp_client(ogs_socknode_t *node) if (addr == NULL) { ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "udp_client() [%s]:%d failed", - OGS_ADDR(node->addr, buf), OGS_PORT(node->addr)); + OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); return NULL;; } - node->sock = new; - return new; } diff --git a/lib/core/ogs-udp.h b/lib/core/ogs-udp.h index 1b596a137..4a2ac96b1 100644 --- a/lib/core/ogs-udp.h +++ b/lib/core/ogs-udp.h @@ -28,9 +28,10 @@ extern "C" { #endif -ogs_sock_t *ogs_udp_socket(int family, ogs_socknode_t *node); -ogs_sock_t *ogs_udp_server(ogs_socknode_t *node, bool bindtodevice); -ogs_sock_t *ogs_udp_client(ogs_socknode_t *node); +ogs_sock_t *ogs_udp_server( + ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option); +ogs_sock_t *ogs_udp_client( + ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option); int ogs_udp_connect(ogs_sock_t *sock, ogs_sockaddr_t *sa_list); #ifdef __cplusplus diff --git a/lib/gtp/context.c b/lib/gtp/context.c index a90c255dd..aa5517b34 100644 --- a/lib/gtp/context.c +++ b/lib/gtp/context.c @@ -105,6 +105,9 @@ int ogs_gtp_context_parse_config(const char *local, const char *remote) const char *dev = NULL; ogs_sockaddr_t *addr = NULL; + ogs_sockopt_t option; + bool is_option = false; + if (ogs_yaml_iter_type(>pc_array) == YAML_MAPPING_NODE) { memcpy(>pc_iter, >pc_array, @@ -161,6 +164,11 @@ int ogs_gtp_context_parse_config(const char *local, const char *remote) if (v) port = atoi(v); } else if (!strcmp(gtpc_key, "dev")) { dev = ogs_yaml_iter_value(>pc_iter); + } else if (!strcmp(gtpc_key, "option")) { + rv = ogs_app_config_parse_sockopt( + >pc_iter, &option); + if (rv != OGS_OK) return rv; + is_option = true; } else ogs_warn("unknown key `%s`", gtpc_key); } @@ -175,10 +183,12 @@ int ogs_gtp_context_parse_config(const char *local, const char *remote) if (addr) { if (ogs_app()->parameter.no_ipv4 == 0) ogs_socknode_add( - &self.gtpc_list, AF_INET, addr); + &self.gtpc_list, AF_INET, addr, + is_option ? &option : NULL); if (ogs_app()->parameter.no_ipv6 == 0) ogs_socknode_add( - &self.gtpc_list6, AF_INET6, addr); + &self.gtpc_list6, AF_INET6, addr, + is_option ? &option : NULL); ogs_freeaddrinfo(addr); } @@ -188,7 +198,8 @@ int ogs_gtp_context_parse_config(const char *local, const char *remote) NULL : &self.gtpc_list, ogs_app()->parameter.no_ipv6 ? NULL : &self.gtpc_list6, - dev, port); + dev, port, + is_option ? &option : NULL); ogs_assert(rv == OGS_OK); } @@ -202,7 +213,7 @@ int ogs_gtp_context_parse_config(const char *local, const char *remote) NULL : &self.gtpc_list, ogs_app()->parameter.no_ipv6 ? NULL : &self.gtpc_list6, - NULL, self.gtpc_port); + NULL, self.gtpc_port, NULL); ogs_assert(rv == OGS_OK); } } else if (!strcmp(local_key, "gtpu")) { @@ -229,6 +240,9 @@ int ogs_gtp_context_parse_config(const char *local, const char *remote) const char *network_instance = NULL; const char *source_interface = NULL; + ogs_sockopt_t option; + bool is_option = false; + if (ogs_yaml_iter_type(>pu_array) == YAML_MAPPING_NODE) { memcpy(>pu_iter, >pu_array, @@ -317,6 +331,11 @@ int ogs_gtp_context_parse_config(const char *local, const char *remote) if (v) port = atoi(v); } else if (!strcmp(gtpu_key, "dev")) { dev = ogs_yaml_iter_value(>pu_iter); + } else if (!strcmp(gtpu_key, "option")) { + rv = ogs_app_config_parse_sockopt( + >pu_iter, &option); + if (rv != OGS_OK) return rv; + is_option = true; } else if (!strcmp(gtpu_key, "teid_range_indication")) { teid_range_indication = @@ -348,9 +367,13 @@ int ogs_gtp_context_parse_config(const char *local, const char *remote) if (addr) { if (ogs_app()->parameter.no_ipv4 == 0) - ogs_socknode_add(&list, AF_INET, addr); + ogs_socknode_add( + &list, AF_INET, addr, + is_option ? &option : NULL); if (ogs_app()->parameter.no_ipv6 == 0) - ogs_socknode_add(&list6, AF_INET6, addr); + ogs_socknode_add( + &list6, AF_INET6, addr, + is_option ? &option : NULL); ogs_freeaddrinfo(addr); } @@ -358,7 +381,8 @@ int ogs_gtp_context_parse_config(const char *local, const char *remote) rv = ogs_socknode_probe( ogs_app()->parameter.no_ipv4 ? NULL : &list, ogs_app()->parameter.no_ipv6 ? NULL : &list6, - dev, port); + dev, port, + is_option ? &option : NULL); ogs_assert(rv == OGS_OK); } @@ -452,9 +476,9 @@ int ogs_gtp_context_parse_config(const char *local, const char *remote) ogs_list_init(&list6); rv = ogs_socknode_probe( - ogs_app()->parameter.no_ipv4 ? NULL : &list, - ogs_app()->parameter.no_ipv6 ? NULL : &list6, - NULL, self.gtpu_port); + ogs_app()->parameter.no_ipv4 ? NULL : &list, + ogs_app()->parameter.no_ipv6 ? NULL : &list6, + NULL, self.gtpu_port, NULL); ogs_assert(rv == OGS_OK); /* @@ -544,8 +568,10 @@ ogs_gtp_node_t *ogs_gtp_node_add_by_f_teid( ogs_app()->parameter.prefer_ipv4); ogs_assert(addr); +#if 0 /* deprecated */ rv = ogs_socknode_fill_scope_id_in_local(addr); ogs_assert(rv == OGS_OK); +#endif node = ogs_gtp_node_new(addr); ogs_assert(node); @@ -652,8 +678,10 @@ ogs_gtp_node_t *ogs_gtp_node_add_by_ip( ogs_app()->parameter.prefer_ipv4); ogs_expect_or_return_val(addr, NULL); +#if 0 /* deprecated */ rv = ogs_socknode_fill_scope_id_in_local(addr); ogs_expect_or_return_val(rv == OGS_OK, NULL); +#endif node = ogs_gtp_node_new(addr); ogs_expect_or_return_val(node, NULL); diff --git a/lib/gtp/path.c b/lib/gtp/path.c index ceaf40d83..fcd0df80d 100644 --- a/lib/gtp/path.c +++ b/lib/gtp/path.c @@ -25,10 +25,12 @@ ogs_sock_t *ogs_gtp_server(ogs_socknode_t *node) ogs_sock_t *gtp; ogs_assert(node); - gtp = ogs_udp_server(node, ogs_app()->sockopt.bindtodevice); + gtp = ogs_udp_server(node->addr, node->option); if (gtp) { ogs_info("gtp_server() [%s]:%d", OGS_ADDR(node->addr, buf), OGS_PORT(node->addr)); + + node->sock = gtp; } return gtp; diff --git a/lib/pfcp/context.c b/lib/pfcp/context.c index 9fbc6ab4f..661f1d28e 100644 --- a/lib/pfcp/context.c +++ b/lib/pfcp/context.c @@ -184,6 +184,9 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote) const char *dev = NULL; ogs_sockaddr_t *addr = NULL; + ogs_sockopt_t option; + bool is_option = false; + if (ogs_yaml_iter_type(&pfcp_array) == YAML_MAPPING_NODE) { memcpy(&pfcp_iter, &pfcp_array, @@ -244,6 +247,11 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote) } } else if (!strcmp(pfcp_key, "dev")) { dev = ogs_yaml_iter_value(&pfcp_iter); + } else if (!strcmp(pfcp_key, "option")) { + rv = ogs_app_config_parse_sockopt( + &pfcp_iter, &option); + if (rv != OGS_OK) return rv; + is_option = true; } else if (!strcmp(pfcp_key, "apn") || !strcmp(pfcp_key, "dnn")) { /* Skip */ @@ -261,10 +269,12 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote) if (addr) { if (ogs_app()->parameter.no_ipv4 == 0) ogs_socknode_add( - &self.pfcp_list, AF_INET, addr); + &self.pfcp_list, AF_INET, addr, + is_option ? &option : NULL); if (ogs_app()->parameter.no_ipv6 == 0) ogs_socknode_add( - &self.pfcp_list6, AF_INET6, addr); + &self.pfcp_list6, AF_INET6, addr, + is_option ? &option : NULL); ogs_freeaddrinfo(addr); } @@ -274,7 +284,8 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote) NULL : &self.pfcp_list, ogs_app()->parameter.no_ipv6 ? NULL : &self.pfcp_list6, - dev, self.pfcp_port); + dev, self.pfcp_port, + is_option ? &option : NULL); ogs_assert(rv == OGS_OK); } @@ -288,7 +299,7 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote) NULL : &self.pfcp_list, ogs_app()->parameter.no_ipv6 ? NULL : &self.pfcp_list6, - NULL, self.pfcp_port); + NULL, self.pfcp_port, NULL); ogs_assert(rv == OGS_OK); } } else if (!strcmp(local_key, "subnet")) { diff --git a/lib/pfcp/path.c b/lib/pfcp/path.c index fbfde0722..d098c7105 100644 --- a/lib/pfcp/path.c +++ b/lib/pfcp/path.c @@ -25,10 +25,12 @@ ogs_sock_t *ogs_pfcp_server(ogs_socknode_t *node) ogs_sock_t *pfcp; ogs_assert(node); - pfcp = ogs_udp_server(node, ogs_app()->sockopt.bindtodevice); + pfcp = ogs_udp_server(node->addr, node->option); if (pfcp) { ogs_info("pfcp_server() [%s]:%d", OGS_ADDR(node->addr, buf), OGS_PORT(node->addr)); + + node->sock = pfcp; } return pfcp; diff --git a/lib/sbi/context.c b/lib/sbi/context.c index 16d20d0ea..81ef661c9 100644 --- a/lib/sbi/context.c +++ b/lib/sbi/context.c @@ -158,6 +158,9 @@ int ogs_sbi_context_parse_config(const char *local, const char *remote) const char *dev = NULL; ogs_sockaddr_t *addr = NULL; + ogs_sockopt_t option; + bool is_option = false; + if (ogs_yaml_iter_type(&sbi_array) == YAML_MAPPING_NODE) { memcpy(&sbi_iter, &sbi_array, @@ -238,6 +241,11 @@ int ogs_sbi_context_parse_config(const char *local, const char *remote) port = atoi(v); } else if (!strcmp(sbi_key, "dev")) { dev = ogs_yaml_iter_value(&sbi_iter); + } else if (!strcmp(sbi_key, "option")) { + rv = ogs_app_config_parse_sockopt( + &sbi_iter, &option); + if (rv != OGS_OK) return rv; + is_option = true; } else if (!strcmp(sbi_key, "tls")) { ogs_yaml_iter_t tls_iter; ogs_yaml_iter_recurse(&sbi_iter, &tls_iter); @@ -270,9 +278,11 @@ int ogs_sbi_context_parse_config(const char *local, const char *remote) if (addr) { if (ogs_app()->parameter.no_ipv4 == 0) - ogs_socknode_add(&list, AF_INET, addr); + ogs_socknode_add( + &list, AF_INET, addr, NULL); if (ogs_app()->parameter.no_ipv6 == 0) - ogs_socknode_add(&list6, AF_INET6, addr); + ogs_socknode_add( + &list6, AF_INET6, addr, NULL); ogs_freeaddrinfo(addr); } @@ -280,7 +290,7 @@ int ogs_sbi_context_parse_config(const char *local, const char *remote) rv = ogs_socknode_probe( ogs_app()->parameter.no_ipv4 ? NULL : &list, ogs_app()->parameter.no_ipv6 ? NULL : &list6, - dev, port); + dev, port, NULL); ogs_assert(rv == OGS_OK); } @@ -293,8 +303,8 @@ int ogs_sbi_context_parse_config(const char *local, const char *remote) node = ogs_list_first(&list); if (node) { - ogs_sbi_server_t *server = - ogs_sbi_server_add(node->addr); + ogs_sbi_server_t *server = ogs_sbi_server_add( + node->addr, is_option ? &option : NULL); ogs_assert(server); if (addr && ogs_app()->parameter.no_ipv4 == 0) @@ -306,8 +316,8 @@ int ogs_sbi_context_parse_config(const char *local, const char *remote) } node6 = ogs_list_first(&list6); if (node6) { - ogs_sbi_server_t *server = - ogs_sbi_server_add(node6->addr); + ogs_sbi_server_t *server = ogs_sbi_server_add( + node6->addr, is_option ? &option : NULL); ogs_assert(server); if (addr && ogs_app()->parameter.no_ipv6 == 0) @@ -334,13 +344,13 @@ int ogs_sbi_context_parse_config(const char *local, const char *remote) rv = ogs_socknode_probe( ogs_app()->parameter.no_ipv4 ? NULL : &list, ogs_app()->parameter.no_ipv6 ? NULL : &list6, - NULL, self.sbi_port); + NULL, self.sbi_port, NULL); ogs_assert(rv == OGS_OK); node = ogs_list_first(&list); - if (node) ogs_sbi_server_add(node->addr); + if (node) ogs_sbi_server_add(node->addr, NULL); node6 = ogs_list_first(&list6); - if (node6) ogs_sbi_server_add(node6->addr); + if (node6) ogs_sbi_server_add(node6->addr, NULL); ogs_socknode_remove_all(&list); ogs_socknode_remove_all(&list6); diff --git a/lib/sbi/nghttp2-server.c b/lib/sbi/nghttp2-server.c index 75eca267b..c0b448796 100644 --- a/lib/sbi/nghttp2-server.c +++ b/lib/sbi/nghttp2-server.c @@ -123,12 +123,14 @@ static int server_start(ogs_sbi_server_t *server, addr = server->node.addr; ogs_assert(addr); - sock = ogs_tcp_server(&server->node); + sock = ogs_tcp_server(addr, server->node.option); if (!sock) { ogs_error("Cannot start SBI server"); return OGS_ERROR; } + server->node.sock = sock; + /* Setup callback function */ server->cb = cb; diff --git a/lib/sbi/server.c b/lib/sbi/server.c index d8f4ebaef..c52225bff 100644 --- a/lib/sbi/server.c +++ b/lib/sbi/server.c @@ -53,7 +53,8 @@ void ogs_sbi_server_final(void) ogs_sbi_server_actions.cleanup(); } -ogs_sbi_server_t *ogs_sbi_server_add(ogs_sockaddr_t *addr) +ogs_sbi_server_t *ogs_sbi_server_add( + ogs_sockaddr_t *addr, ogs_sockopt_t *option) { ogs_sbi_server_t *server = NULL; @@ -64,6 +65,8 @@ ogs_sbi_server_t *ogs_sbi_server_add(ogs_sockaddr_t *addr) memset(server, 0, sizeof(ogs_sbi_server_t)); ogs_assert(OGS_OK == ogs_copyaddrinfo(&server->node.addr, addr)); + if (option) + server->node.option = ogs_memdup(option, sizeof *option); ogs_list_add(&ogs_sbi_self()->server_list, server); @@ -78,6 +81,8 @@ void ogs_sbi_server_remove(ogs_sbi_server_t *server) ogs_assert(server->node.addr); ogs_freeaddrinfo(server->node.addr); + if (server->node.option) + ogs_free(server->node.option); if (server->advertise) ogs_freeaddrinfo(server->advertise); diff --git a/lib/sbi/server.h b/lib/sbi/server.h index 81a97919f..28f27c5d7 100644 --- a/lib/sbi/server.h +++ b/lib/sbi/server.h @@ -62,7 +62,8 @@ typedef struct ogs_sbi_server_actions_s { void ogs_sbi_server_init(int num_of_session_pool, int num_of_stream_pool); void ogs_sbi_server_final(void); -ogs_sbi_server_t *ogs_sbi_server_add(ogs_sockaddr_t *addr); +ogs_sbi_server_t *ogs_sbi_server_add( + ogs_sockaddr_t *addr, ogs_sockopt_t *option); void ogs_sbi_server_remove(ogs_sbi_server_t *server); void ogs_sbi_server_remove_all(void); diff --git a/lib/sctp/ogs-lksctp.c b/lib/sctp/ogs-lksctp.c index 4e0aa5f63..e069a266e 100644 --- a/lib/sctp/ogs-lksctp.c +++ b/lib/sctp/ogs-lksctp.c @@ -23,10 +23,6 @@ #define OGS_LOG_DOMAIN __ogs_sock_domain static int subscribe_to_events(ogs_sock_t *sock); -static int set_paddrparams(ogs_sock_t *sock); -static int set_rtoinfo(ogs_sock_t *sock); -static int set_initmsg(ogs_sock_t *sock); -static int set_nodelay(ogs_sock_t *sock, int on); void ogs_sctp_init(uint16_t port) { @@ -36,51 +32,68 @@ void ogs_sctp_final(void) { } -ogs_sock_t *ogs_sctp_socket(int family, int type, ogs_socknode_t *node) +ogs_sock_t *ogs_sctp_socket(int family, int type) { ogs_sock_t *new = NULL; int rv; new = ogs_sock_socket(family, type, IPPROTO_SCTP); - ogs_assert(new); + if (!new) { + ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, + "ogs_sock_socket(faimly:%d type:%d) failed", family, type); + return NULL; + } rv = subscribe_to_events(new); - ogs_assert(rv == OGS_OK); - - rv = set_paddrparams(new); - ogs_assert(rv == OGS_OK); - - rv = set_rtoinfo(new); - ogs_assert(rv == OGS_OK); - - rv = set_initmsg(new); - ogs_assert(rv == OGS_OK); - - if (ogs_app()->sockopt.no_delay == true) { - rv = set_nodelay(new, true); - ogs_assert(rv == OGS_OK); - } else { - ogs_warn("SCTP NO_DELAY Disabled"); + if (rv != OGS_OK) { + ogs_sock_destroy(new); + return NULL; } return new; } -ogs_sock_t *ogs_sctp_server(int type, ogs_socknode_t *node) +ogs_sock_t *ogs_sctp_server( + int type, ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option) { int rv; - ogs_sock_t *new; - ogs_sockaddr_t *addr; char buf[OGS_ADDRSTRLEN]; - ogs_assert(node); - ogs_assert(node->addr); + ogs_sock_t *new = NULL; + ogs_sockaddr_t *addr; + ogs_sockopt_t option; - addr = node->addr; + ogs_assert(sa_list); + + ogs_sockopt_init(&option); + if (socket_option) + memcpy(&option, socket_option, sizeof option); + + addr = sa_list; while (addr) { - new = ogs_sctp_socket(addr->ogs_sa_family, type, node); + new = ogs_sctp_socket(addr->ogs_sa_family, type); if (new) { - rv = ogs_listen_reusable(new->fd); + rv = ogs_sctp_peer_addr_params(new, &option); + ogs_assert(rv == OGS_OK); + + rv = ogs_sctp_rto_info(new, &option); + ogs_assert(rv == OGS_OK); + + rv = ogs_sctp_initmsg(new, &option); + ogs_assert(rv == OGS_OK); + + if (option.sctp_nodelay == true) { + rv = ogs_sctp_nodelay(new, true); + ogs_assert(rv == OGS_OK); + } else + ogs_warn("SCTP NO_DELAY Disabled"); + + if (option.so_linger.l_onoff == true) { + rv = ogs_sctp_so_linger(new, option.so_linger.l_linger); + ogs_assert(rv == OGS_OK); + } + + rv = ogs_listen_reusable(new->fd, true); ogs_assert(rv == OGS_OK); if (ogs_sock_bind(new, addr) == OGS_OK) { @@ -98,31 +111,58 @@ ogs_sock_t *ogs_sctp_server(int type, ogs_socknode_t *node) if (addr == NULL) { ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "sctp_server() [%s]:%d failed", - OGS_ADDR(node->addr, buf), OGS_PORT(node->addr)); + OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); return NULL; } + ogs_assert(new); + rv = ogs_sock_listen(new); ogs_assert(rv == OGS_OK); - node->sock = new; - return new; } -ogs_sock_t *ogs_sctp_client(int type, ogs_socknode_t *node) +ogs_sock_t *ogs_sctp_client( + int type, ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option) { - ogs_sock_t *new = NULL; - ogs_sockaddr_t *addr; + int rv; char buf[OGS_ADDRSTRLEN]; - ogs_assert(node); - ogs_assert(node->addr); + ogs_sock_t *new = NULL; + ogs_sockaddr_t *addr; + ogs_sockopt_t option; - addr = node->addr; + ogs_assert(sa_list); + + ogs_sockopt_init(&option); + if (socket_option) + memcpy(&option, socket_option, sizeof option); + + addr = sa_list; while (addr) { - new = ogs_sctp_socket(addr->ogs_sa_family, type, node); + new = ogs_sctp_socket(addr->ogs_sa_family, type); if (new) { + rv = ogs_sctp_peer_addr_params(new, &option); + ogs_assert(rv == OGS_OK); + + rv = ogs_sctp_rto_info(new, &option); + ogs_assert(rv == OGS_OK); + + rv = ogs_sctp_initmsg(new, &option); + ogs_assert(rv == OGS_OK); + + if (option.sctp_nodelay == true) { + rv = ogs_sctp_nodelay(new, true); + ogs_assert(rv == OGS_OK); + } else + ogs_warn("SCTP NO_DELAY Disabled"); + + if (option.so_linger.l_onoff == true) { + rv = ogs_sctp_so_linger(new, option.so_linger.l_linger); + ogs_assert(rv == OGS_OK); + } + if (ogs_sock_connect(new, addr) == OGS_OK) { ogs_debug("sctp_client() [%s]:%d", OGS_ADDR(addr, buf), OGS_PORT(addr)); @@ -138,11 +178,11 @@ ogs_sock_t *ogs_sctp_client(int type, ogs_socknode_t *node) if (addr == NULL) { ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "sctp_client() [%s]:%d failed", - OGS_ADDR(node->addr, buf), OGS_PORT(node->addr)); + OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); return NULL; } - node->sock = new; + ogs_assert(new); return new; } @@ -452,12 +492,13 @@ static int sctp_setsockopt_paddrparams_workaround( } } -static int set_paddrparams(ogs_sock_t *sock) +int ogs_sctp_peer_addr_params(ogs_sock_t *sock, ogs_sockopt_t *option) { struct sctp_paddrparams paddrparams; socklen_t socklen; ogs_assert(sock); + ogs_assert(option); memset(&paddrparams, 0, sizeof(paddrparams)); socklen = sizeof(paddrparams); @@ -481,9 +522,9 @@ static int set_paddrparams(ogs_sock_t *sock) paddrparams.spp_pathmaxrxt); #endif - paddrparams.spp_hbinterval = ogs_app()->sctp.heartbit_interval; + paddrparams.spp_hbinterval = option->sctp.spp_hbinterval; #if !defined(__FreeBSD__) - paddrparams.spp_sackdelay = ogs_app()->sctp.sack_delay; + paddrparams.spp_sackdelay = option->sctp.spp_sackdelay; #endif #ifdef DISABLE_SCTP_EVENT_WORKAROUND @@ -516,12 +557,13 @@ static int set_paddrparams(ogs_sock_t *sock) return OGS_OK; } -static int set_rtoinfo(ogs_sock_t *sock) +int ogs_sctp_rto_info(ogs_sock_t *sock, ogs_sockopt_t *option) { struct sctp_rtoinfo rtoinfo; socklen_t socklen; ogs_assert(sock); + ogs_assert(option); memset(&rtoinfo, 0, sizeof(rtoinfo)); socklen = sizeof(rtoinfo); @@ -537,9 +579,9 @@ static int set_rtoinfo(ogs_sock_t *sock) rtoinfo.srto_max, rtoinfo.srto_min); - rtoinfo.srto_initial = ogs_app()->sctp.rto_initial; - rtoinfo.srto_min = ogs_app()->sctp.rto_min; - rtoinfo.srto_max = ogs_app()->sctp.rto_max; + rtoinfo.srto_initial = option->sctp.srto_initial; + rtoinfo.srto_min = option->sctp.srto_min; + rtoinfo.srto_max = option->sctp.srto_max; if (setsockopt(sock->fd, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, sizeof(rtoinfo)) != 0) { @@ -547,6 +589,7 @@ static int set_rtoinfo(ogs_sock_t *sock) "setsockopt for SCTP_RTOINFO failed"); return OGS_ERROR; } + ogs_debug("New RTO (initial:%d max:%d min:%d)", rtoinfo.srto_initial, rtoinfo.srto_max, @@ -555,13 +598,14 @@ static int set_rtoinfo(ogs_sock_t *sock) return OGS_OK; } -static int set_initmsg(ogs_sock_t *sock) +int ogs_sctp_initmsg(ogs_sock_t *sock, ogs_sockopt_t *option) { struct sctp_initmsg initmsg; socklen_t socklen; ogs_assert(sock); - ogs_assert(ogs_app()->sctp.max_num_of_ostreams > 1); + ogs_assert(option); + ogs_assert(option->sctp.sinit_num_ostreams > 1); memset(&initmsg, 0, sizeof(initmsg)); socklen = sizeof(initmsg); @@ -578,10 +622,10 @@ static int set_initmsg(ogs_sock_t *sock) initmsg.sinit_max_attempts, initmsg.sinit_max_init_timeo); - initmsg.sinit_num_ostreams = ogs_app()->sctp.max_num_of_ostreams; - initmsg.sinit_max_instreams = ogs_app()->sctp.max_num_of_istreams; - initmsg.sinit_max_attempts = ogs_app()->sctp.max_attempts; - initmsg.sinit_max_init_timeo = ogs_app()->sctp.max_initial_timeout; + initmsg.sinit_num_ostreams = option->sctp.sinit_num_ostreams; + initmsg.sinit_max_instreams = option->sctp.sinit_max_instreams; + initmsg.sinit_max_attempts = option->sctp.sinit_max_attempts; + initmsg.sinit_max_init_timeo = option->sctp.sinit_max_init_timeo; if (setsockopt(sock->fd, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg)) != 0) { @@ -599,7 +643,7 @@ static int set_initmsg(ogs_sock_t *sock) return OGS_OK; } -static int set_nodelay(ogs_sock_t *sock, int on) +int ogs_sctp_nodelay(ogs_sock_t *sock, int on) { ogs_assert(sock); @@ -607,9 +651,15 @@ static int set_nodelay(ogs_sock_t *sock, int on) if (setsockopt(sock->fd, IPPROTO_SCTP, SCTP_NODELAY, &on, sizeof(on)) != 0) { ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, - "setsockopt for SCTP_NODELAY failed"); + "setsockopt(IPPROTO_SCTP, SCTP_NODELAY) failed"); return OGS_ERROR; } return OGS_OK; } + +int ogs_sctp_so_linger(ogs_sock_t *sock, int l_linger) +{ + ogs_assert(sock); + return ogs_so_linger(sock->fd, l_linger); +} diff --git a/lib/sctp/ogs-sctp.h b/lib/sctp/ogs-sctp.h index 79d46937b..d34d519b4 100644 --- a/lib/sctp/ogs-sctp.h +++ b/lib/sctp/ogs-sctp.h @@ -104,15 +104,23 @@ typedef struct ogs_sctp_info_s { void ogs_sctp_init(uint16_t port); void ogs_sctp_final(void); -ogs_sock_t *ogs_sctp_socket(int family, int type, ogs_socknode_t *node); +ogs_sock_t *ogs_sctp_socket(int family, int type); -ogs_sock_t *ogs_sctp_server(int type, ogs_socknode_t *node); -ogs_sock_t *ogs_sctp_client(int type, ogs_socknode_t *node); +ogs_sock_t *ogs_sctp_server( + int type, ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option); +ogs_sock_t *ogs_sctp_client( + int type, ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option); int ogs_sctp_bind(ogs_sock_t *sock, ogs_sockaddr_t *sa_list); int ogs_sctp_connect(ogs_sock_t *sock, ogs_sockaddr_t *sa_list); int ogs_sctp_listen(ogs_sock_t *sock); +int ogs_sctp_peer_addr_params(ogs_sock_t *sock, ogs_sockopt_t *option); +int ogs_sctp_rto_info(ogs_sock_t *sock, ogs_sockopt_t *option); +int ogs_sctp_initmsg(ogs_sock_t *sock, ogs_sockopt_t *option); +int ogs_sctp_nodelay(ogs_sock_t *sock, int on); +int ogs_sctp_so_linger(ogs_sock_t *sock, int l_linger); + int ogs_sctp_sendmsg(ogs_sock_t *sock, const void *msg, size_t len, ogs_sockaddr_t *to, uint32_t ppid, uint16_t stream_no); int ogs_sctp_recvmsg(ogs_sock_t *sock, void *msg, size_t len, diff --git a/lib/sctp/ogs-usrsctp.c b/lib/sctp/ogs-usrsctp.c index 094ab1126..7b49f5d03 100644 --- a/lib/sctp/ogs-usrsctp.c +++ b/lib/sctp/ogs-usrsctp.c @@ -41,10 +41,9 @@ void ogs_sctp_final() } } -ogs_sock_t *ogs_sctp_socket(int family, int type, ogs_socknode_t *node) +ogs_sock_t *ogs_sctp_socket(int family, int type) { struct socket *socket = NULL; - struct linger l; const int on = 1; struct sctp_event event; uint16_t event_types[] = { @@ -55,8 +54,6 @@ ogs_sock_t *ogs_sctp_socket(int family, int type, ogs_socknode_t *node) SCTP_ADAPTATION_INDICATION, SCTP_PARTIAL_DELIVERY_EVENT }; - struct sctp_initmsg initmsg; - socklen_t socklen; int i; if (!(socket = usrsctp_socket(family, type, IPPROTO_SCTP, @@ -65,27 +62,6 @@ ogs_sock_t *ogs_sctp_socket(int family, int type, ogs_socknode_t *node) return NULL; } - if (ogs_app()->sockopt.no_delay == true) { - if (usrsctp_setsockopt(socket, IPPROTO_SCTP, SCTP_NODELAY, - &on, sizeof(int)) < 0) { - ogs_error("usrsctp_setsockopt SCTP_NODELAY failed"); - return NULL; - } - } else { - ogs_warn("SCTP NO_DELAY Disabled"); - } - - if (ogs_app()->sockopt.l_onoff == true) { - memset(&l, 0, sizeof(l)); - l.l_onoff = 1; - l.l_linger = ogs_app()->sockopt.l_linger; - if (usrsctp_setsockopt(socket, SOL_SOCKET, SO_LINGER, - (const void *)&l, (socklen_t) sizeof(struct linger)) < 0) { - ogs_error("Could not set SO_LINGER on SCTP socket"); - return NULL; - } - } - if (usrsctp_setsockopt(socket, IPPROTO_SCTP, SCTP_RECVRCVINFO, &on, sizeof(int)) < 0) { ogs_error("usrsctp_setsockopt SCTP_RECVRCVINFO failed"); @@ -104,42 +80,7 @@ ogs_sock_t *ogs_sctp_socket(int family, int type, ogs_socknode_t *node) } } - memset(&initmsg, 0, sizeof(struct sctp_initmsg)); - socklen = sizeof(struct sctp_initmsg); - if (usrsctp_getsockopt(socket, IPPROTO_SCTP, SCTP_INITMSG, - &initmsg, &socklen) != 0) { - ogs_error("getsockopt for SCTP_INITMSG failed(%d:%s)", - errno, strerror( errno )); - return NULL; - } - - ogs_debug("Old INITMSG (numout:%d maxin:%d maxattempt:%d maxinit_to:%d)", - initmsg.sinit_num_ostreams, - initmsg.sinit_max_instreams, - initmsg.sinit_max_attempts, - initmsg.sinit_max_init_timeo); - - ogs_assert(ogs_app()->sctp.max_num_of_ostreams > 1); - - initmsg.sinit_num_ostreams = ogs_app()->sctp.max_num_of_ostreams; - initmsg.sinit_max_instreams = ogs_app()->sctp.max_num_of_istreams; - initmsg.sinit_max_attempts = ogs_app()->sctp.max_attempts; - initmsg.sinit_max_init_timeo = ogs_app()->sctp.max_initial_timeout; - - if (usrsctp_setsockopt(socket, IPPROTO_SCTP, SCTP_INITMSG, - &initmsg, sizeof(initmsg)) != 0) { - ogs_error("setsockopt for SCTP_INITMSG failed(%d:%s)", - errno, strerror( errno )); - return NULL; - } - - ogs_debug("New INITMSG (numout:%d maxin:%d maxattempt:%d maxinit_to:%d)", - initmsg.sinit_num_ostreams, - initmsg.sinit_max_instreams, - initmsg.sinit_max_attempts, - initmsg.sinit_max_init_timeo); - - return (ogs_sock_t *)socket;; + return (ogs_sock_t *)socket; } void ogs_sctp_destroy(ogs_sock_t *sock) @@ -148,27 +89,53 @@ void ogs_sctp_destroy(ogs_sock_t *sock) usrsctp_close((struct socket *)sock); } -ogs_sock_t *ogs_sctp_server(int type, ogs_socknode_t *node) +ogs_sock_t *ogs_sctp_server( + int type, ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option) { int rv; char buf[OGS_ADDRSTRLEN]; - ogs_sock_t *sock = NULL; - ogs_sockaddr_t *addr = NULL; - ogs_assert(node); - ogs_assert(node->addr); + ogs_sock_t *new = NULL; + ogs_sockaddr_t *addr; + ogs_sockopt_t option; - addr = node->addr; + ogs_assert(sa_list); + + ogs_sockopt_init(&option); + if (socket_option) + memcpy(&option, socket_option, sizeof option); + + addr = sa_list; while (addr) { - sock = ogs_sctp_socket(addr->ogs_sa_family, type, node); - if (sock) { - if (ogs_sctp_bind(sock, addr) == OGS_OK) { + new = ogs_sctp_socket(addr->ogs_sa_family, type); + if (new) { + rv = ogs_sctp_peer_addr_params(new, &option); + ogs_assert(rv == OGS_OK); + + rv = ogs_sctp_rto_info(new, &option); + ogs_assert(rv == OGS_OK); + + rv = ogs_sctp_initmsg(new, &option); + ogs_assert(rv == OGS_OK); + + if (option.sctp_nodelay == true) { + rv = ogs_sctp_nodelay(new, true); + ogs_assert(rv == OGS_OK); + } else + ogs_warn("SCTP NO_DELAY Disabled"); + + if (option.so_linger.l_onoff == true) { + rv = ogs_sctp_so_linger(new, option.so_linger.l_linger); + ogs_assert(rv == OGS_OK); + } + + if (ogs_sctp_bind(new, addr) == OGS_OK) { ogs_trace("sctp_server [%s]:%d", OGS_ADDR(addr, buf), OGS_PORT(addr)); break; } - ogs_sctp_destroy(sock); + ogs_sctp_destroy(new); } addr = addr->next; @@ -176,39 +143,65 @@ ogs_sock_t *ogs_sctp_server(int type, ogs_socknode_t *node) if (addr == NULL) { ogs_error("sctp_server [%s]:%d failed", - OGS_ADDR(node->addr, buf), OGS_PORT(node->addr)); + OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); return NULL; } - rv = ogs_sctp_listen(sock); + ogs_assert(new); + + rv = ogs_sctp_listen(new); ogs_assert(rv == OGS_OK); - node->sock = sock; - node->cleanup = ogs_sctp_destroy; - - return sock; + return new; } -ogs_sock_t *ogs_sctp_client(int type, ogs_socknode_t *node) +ogs_sock_t *ogs_sctp_client( + int type, ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option) { - ogs_sock_t *sock = NULL; - ogs_sockaddr_t *addr = NULL; + int rv; char buf[OGS_ADDRSTRLEN]; - ogs_assert(node); - ogs_assert(node->addr); + ogs_sock_t *new = NULL; + ogs_sockaddr_t *addr; + ogs_sockopt_t option; - addr = node->addr; + ogs_assert(sa_list); + + ogs_sockopt_init(&option); + if (socket_option) + memcpy(&option, socket_option, sizeof option); + + addr = sa_list; while (addr) { - sock = ogs_sctp_socket(addr->ogs_sa_family, type, node); - if (sock) { - if (ogs_sctp_connect(sock, addr) == OGS_OK) { + new = ogs_sctp_socket(addr->ogs_sa_family, type); + if (new) { + rv = ogs_sctp_peer_addr_params(new, &option); + ogs_assert(rv == OGS_OK); + + rv = ogs_sctp_rto_info(new, &option); + ogs_assert(rv == OGS_OK); + + rv = ogs_sctp_initmsg(new, &option); + ogs_assert(rv == OGS_OK); + + if (option.sctp_nodelay == true) { + rv = ogs_sctp_nodelay(new, true); + ogs_assert(rv == OGS_OK); + } else + ogs_warn("SCTP NO_DELAY Disabled"); + + if (option.so_linger.l_onoff == true) { + rv = ogs_sctp_so_linger(new, option.so_linger.l_linger); + ogs_assert(rv == OGS_OK); + } + + if (ogs_sctp_connect(new, addr) == OGS_OK) { ogs_trace("sctp_client [%s]:%d", OGS_ADDR(addr, buf), OGS_PORT(addr)); break; } - ogs_sctp_destroy(sock); + ogs_sctp_destroy(new); } addr = addr->next; @@ -216,17 +209,13 @@ ogs_sock_t *ogs_sctp_client(int type, ogs_socknode_t *node) if (addr == NULL) { ogs_error("sctp_client [%s]:%d failed", - OGS_ADDR(node->addr, buf), OGS_PORT(node->addr)); + OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); return NULL; } - node->sock = sock; - node->cleanup = ogs_sctp_destroy; - - return sock; + return new; } - int ogs_sctp_bind(ogs_sock_t *sock, ogs_sockaddr_t *sa_list) { struct socket *socket = (struct socket *)sock; @@ -407,3 +396,169 @@ static void ogs_debug_printf(const char *format, ...) va_end(ap); } +int ogs_sctp_peer_addr_params(ogs_sock_t *sock, ogs_sockopt_t *option) +{ + struct socket *socket = (struct socket *)sock; + + struct sctp_paddrparams paddrparams; + socklen_t socklen; + + ogs_assert(socket); + ogs_assert(option); + + memset(&paddrparams, 0, sizeof(paddrparams)); + socklen = sizeof(paddrparams); + if (usrsctp_getsockopt(socket, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, + &paddrparams, &socklen) != 0) { + ogs_error("getsockopt for SCTP_PEER_ADDR failed(%d:%s)", + errno, strerror( errno )); + return OGS_ERROR; + } + + ogs_debug("OLD spp_flags = 0x%x hbinter = %d pathmax = %d", + paddrparams.spp_flags, + paddrparams.spp_hbinterval, + paddrparams.spp_pathmaxrxt); + + paddrparams.spp_hbinterval = option->sctp.spp_hbinterval; + + if (usrsctp_setsockopt(socket, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, + &paddrparams, sizeof(paddrparams)) != 0) { + ogs_error("setsockopt for SCTP_PEER_ADDR_PARAMS failed(%d:%s)", + errno, strerror( errno )); + return OGS_ERROR; + } + + ogs_debug("NEW spp_flags = 0x%x hbinter = %d pathmax = %d", + paddrparams.spp_flags, + paddrparams.spp_hbinterval, + paddrparams.spp_pathmaxrxt); + + return OGS_OK; +} + +int ogs_sctp_rto_info(ogs_sock_t *sock, ogs_sockopt_t *option) +{ + struct socket *socket = (struct socket *)sock; + + struct sctp_rtoinfo rtoinfo; + socklen_t socklen; + + ogs_assert(sock); + ogs_assert(option); + + memset(&rtoinfo, 0, sizeof(rtoinfo)); + socklen = sizeof(rtoinfo); + if (usrsctp_getsockopt(socket, IPPROTO_SCTP, SCTP_RTOINFO, + &rtoinfo, &socklen) != 0) { + ogs_error("getsockopt for SCTP_RTOINFO failed(%d:%s)", + errno, strerror( errno )); + return OGS_ERROR; + } + + ogs_debug("OLD RTO (initial:%d max:%d min:%d)", + rtoinfo.srto_initial, + rtoinfo.srto_max, + rtoinfo.srto_min); + + rtoinfo.srto_initial = option->sctp.srto_initial; + rtoinfo.srto_min = option->sctp.srto_min; + rtoinfo.srto_max = option->sctp.srto_max; + + if (usrsctp_setsockopt(socket, IPPROTO_SCTP, SCTP_RTOINFO, + &rtoinfo, sizeof(rtoinfo)) != 0) { + ogs_error("setsockopt for SCTP_RTOINFO failed(%d:%s)", + errno, strerror( errno )); + return OGS_ERROR; + } + + ogs_debug("New RTO (initial:%d max:%d min:%d)", + rtoinfo.srto_initial, + rtoinfo.srto_max, + rtoinfo.srto_min); + + return OGS_OK; +} + +int ogs_sctp_initmsg(ogs_sock_t *sock, ogs_sockopt_t *option) +{ + struct socket *socket = (struct socket *)sock; + + struct sctp_initmsg initmsg; + socklen_t socklen; + + ogs_assert(socket); + ogs_assert(option); + ogs_assert(option->sctp.sinit_num_ostreams > 1); + + memset(&initmsg, 0, sizeof(struct sctp_initmsg)); + socklen = sizeof(struct sctp_initmsg); + if (usrsctp_getsockopt(socket, IPPROTO_SCTP, SCTP_INITMSG, + &initmsg, &socklen) != 0) { + ogs_error("getsockopt for SCTP_INITMSG failed(%d:%s)", + errno, strerror( errno )); + return OGS_ERROR; + } + + ogs_debug("Old INITMSG (numout:%d maxin:%d maxattempt:%d maxinit_to:%d)", + initmsg.sinit_num_ostreams, + initmsg.sinit_max_instreams, + initmsg.sinit_max_attempts, + initmsg.sinit_max_init_timeo); + + initmsg.sinit_num_ostreams = option->sctp.sinit_num_ostreams; + initmsg.sinit_max_instreams = option->sctp.sinit_max_instreams; + initmsg.sinit_max_attempts = option->sctp.sinit_max_attempts; + initmsg.sinit_max_init_timeo = option->sctp.sinit_max_init_timeo; + + if (usrsctp_setsockopt(socket, IPPROTO_SCTP, SCTP_INITMSG, + &initmsg, sizeof(initmsg)) != 0) { + ogs_error("setsockopt for SCTP_INITMSG failed(%d:%s)", + errno, strerror( errno )); + return OGS_ERROR; + } + + ogs_debug("New INITMSG (numout:%d maxin:%d maxattempt:%d maxinit_to:%d)", + initmsg.sinit_num_ostreams, + initmsg.sinit_max_instreams, + initmsg.sinit_max_attempts, + initmsg.sinit_max_init_timeo); + + return OGS_OK; +} + +int ogs_sctp_nodelay(ogs_sock_t *sock, int on) +{ + struct socket *socket = (struct socket *)sock; + + ogs_assert(socket); + + ogs_debug("Turn on SCTP_NODELAY"); + if (usrsctp_setsockopt(socket, IPPROTO_SCTP, SCTP_NODELAY, + &on, sizeof(int)) < 0) { + ogs_error("usrsctp_setsockopt(IPPROTO_SCTP, SCTP_NODELAY) failed"); + return OGS_ERROR; + } + + return OGS_OK; +} + +int ogs_sctp_so_linger(ogs_sock_t *sock, int l_linger) +{ + struct socket *socket = (struct socket *)sock; + struct linger l; + + ogs_assert(socket); + ogs_assert(l_linger); + + memset(&l, 0, sizeof(l)); + l.l_onoff = 1; + l.l_linger = l_linger; + if (usrsctp_setsockopt(socket, SOL_SOCKET, SO_LINGER, + (const void *)&l, (socklen_t) sizeof(struct linger)) < 0) { + ogs_error("Could not set SO_LINGER on SCTP socket"); + return OGS_ERROR; + } + + return OGS_OK; +} diff --git a/src/amf/amf-sm.c b/src/amf/amf-sm.c index c76e88d15..164f46057 100644 --- a/src/amf/amf-sm.c +++ b/src/amf/amf-sm.c @@ -649,10 +649,13 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e) ogs_free(addr); } - gnb->max_num_of_ostreams = - ogs_min(max_num_of_ostreams, gnb->max_num_of_ostreams); + if (gnb->max_num_of_ostreams) + gnb->max_num_of_ostreams = + ogs_min(max_num_of_ostreams, gnb->max_num_of_ostreams); + else + gnb->max_num_of_ostreams = max_num_of_ostreams; - ogs_debug("gNB-N2 SCTP_COMM_UP[%s] Max Num of Outbound Streams[%d]", + ogs_info("gNB-N2[%s] max_num_of_ostreams : %d", OGS_ADDR(gnb->sctp.addr, buf), gnb->max_num_of_ostreams); break; diff --git a/src/amf/context.c b/src/amf/context.c index a4f982c3d..bd70a4a32 100644 --- a/src/amf/context.c +++ b/src/amf/context.c @@ -213,6 +213,9 @@ int amf_context_parse_config(void) const char *dev = NULL; ogs_sockaddr_t *addr = NULL; + ogs_sockopt_t option; + bool is_option = false; + if (ogs_yaml_iter_type(&ngap_array) == YAML_MAPPING_NODE) { memcpy(&ngap_iter, &ngap_array, @@ -269,6 +272,11 @@ int amf_context_parse_config(void) if (v) port = atoi(v); } else if (!strcmp(ngap_key, "dev")) { dev = ogs_yaml_iter_value(&ngap_iter); + } else if (!strcmp(ngap_key, "option")) { + rv = ogs_app_config_parse_sockopt( + &ngap_iter, &option); + if (rv != OGS_OK) return rv; + is_option = true; } else ogs_warn("unknown key `%s`", ngap_key); } @@ -283,10 +291,12 @@ int amf_context_parse_config(void) if (addr) { if (ogs_app()->parameter.no_ipv4 == 0) ogs_socknode_add( - &self.ngap_list, AF_INET, addr); + &self.ngap_list, AF_INET, addr, + is_option ? &option : NULL); if (ogs_app()->parameter.no_ipv6 == 0) ogs_socknode_add( - &self.ngap_list6, AF_INET6, addr); + &self.ngap_list6, AF_INET6, addr, + is_option ? &option : NULL); ogs_freeaddrinfo(addr); } @@ -296,7 +306,8 @@ int amf_context_parse_config(void) NULL : &self.ngap_list, ogs_app()->parameter.no_ipv6 ? NULL : &self.ngap_list6, - dev, port); + dev, port, + is_option ? &option : NULL); ogs_assert(rv == OGS_OK); } @@ -310,7 +321,7 @@ int amf_context_parse_config(void) NULL : &self.ngap_list, ogs_app()->parameter.no_ipv6 ? NULL : &self.ngap_list6, - NULL, self.ngap_port); + NULL, self.ngap_port, NULL); ogs_assert(rv == OGS_OK); } } else if (!strcmp(amf_key, "guami")) { @@ -847,12 +858,8 @@ amf_gnb_t *amf_gnb_add(ogs_sock_t *sock, ogs_sockaddr_t *addr) ogs_assert(gnb->sctp.poll.read); } - gnb->max_num_of_ostreams = OGS_DEFAULT_SCTP_MAX_NUM_OF_OSTREAMS; + gnb->max_num_of_ostreams = 0; gnb->ostream_id = 0; - if (ogs_app()->sctp.max_num_of_ostreams) { - gnb->max_num_of_ostreams = ogs_app()->sctp.max_num_of_ostreams; - ogs_info("[GNB] max_num_of_ostreams : %d", gnb->max_num_of_ostreams); - } ogs_list_init(&gnb->ran_ue_list); @@ -970,6 +977,7 @@ ran_ue_t *ran_ue_add(amf_gnb_t *gnb, uint32_t ran_ue_ngap_id) * 0 : Non UE signalling * 1-29 : UE specific association */ + ogs_assert((gnb->max_num_of_ostreams-1) >= 1); /* NEXT_ID(MAX >= MIN) */ ran_ue->gnb_ostream_id = OGS_NEXT_ID(gnb->ostream_id, 1, gnb->max_num_of_ostreams-1); diff --git a/src/amf/ngap-sctp.c b/src/amf/ngap-sctp.c index b96e907b4..d5bde44a5 100644 --- a/src/amf/ngap-sctp.c +++ b/src/amf/ngap-sctp.c @@ -34,22 +34,30 @@ ogs_sock_t *ngap_server(ogs_socknode_t *node) { char buf[OGS_ADDRSTRLEN]; ogs_sock_t *sock = NULL; +#if !HAVE_USRSCTP + ogs_poll_t *poll = NULL; +#endif ogs_assert(node); #if HAVE_USRSCTP - sock = ogs_sctp_server(SOCK_SEQPACKET, node); + sock = ogs_sctp_server(SOCK_SEQPACKET, node->addr, node->option); if (!sock) return NULL; usrsctp_set_non_blocking((struct socket *)sock, 1); usrsctp_set_upcall((struct socket *)sock, usrsctp_recv_handler, NULL); #else - sock = ogs_sctp_server(SOCK_STREAM, node); + sock = ogs_sctp_server(SOCK_STREAM, node->addr, node->option); if (!sock) return NULL; - node->poll = ogs_pollset_add(ogs_app()->pollset, + poll = ogs_pollset_add(ogs_app()->pollset, OGS_POLLIN, sock->fd, lksctp_accept_handler, sock); - ogs_assert(node->poll); + ogs_assert(node); + + node->poll = poll; #endif + node->sock = sock; + node->cleanup = ogs_sctp_destroy; + ogs_info("ngap_server() [%s]:%d", OGS_ADDR(node->addr, buf), OGS_PORT(node->addr)); diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index 6be71cd24..29e51eef3 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -423,6 +423,9 @@ int mme_context_parse_config() const char *dev = NULL; ogs_sockaddr_t *addr = NULL; + ogs_sockopt_t option; + bool is_option = false; + if (ogs_yaml_iter_type(&s1ap_array) == YAML_MAPPING_NODE) { memcpy(&s1ap_iter, &s1ap_array, @@ -479,6 +482,11 @@ int mme_context_parse_config() if (v) port = atoi(v); } else if (!strcmp(s1ap_key, "dev")) { dev = ogs_yaml_iter_value(&s1ap_iter); + } else if (!strcmp(s1ap_key, "option")) { + rv = ogs_app_config_parse_sockopt( + &s1ap_iter, &option); + if (rv != OGS_OK) return rv; + is_option = true; } else ogs_warn("unknown key `%s`", s1ap_key); } @@ -493,10 +501,12 @@ int mme_context_parse_config() if (addr) { if (ogs_app()->parameter.no_ipv4 == 0) ogs_socknode_add( - &self.s1ap_list, AF_INET, addr); + &self.s1ap_list, AF_INET, addr, + is_option ? &option : NULL); if (ogs_app()->parameter.no_ipv6 == 0) ogs_socknode_add( - &self.s1ap_list6, AF_INET6, addr); + &self.s1ap_list6, AF_INET6, addr, + is_option ? &option : NULL); ogs_freeaddrinfo(addr); } @@ -506,7 +516,8 @@ int mme_context_parse_config() NULL : &self.s1ap_list, ogs_app()->parameter.no_ipv6 ? NULL : &self.s1ap_list6, - dev, port); + dev, port, + is_option ? &option : NULL); ogs_assert(rv == OGS_OK); } @@ -520,7 +531,7 @@ int mme_context_parse_config() NULL : &self.s1ap_list, ogs_app()->parameter.no_ipv6 ? NULL : &self.s1ap_list6, - NULL, self.s1ap_port); + NULL, self.s1ap_port, NULL); ogs_assert(rv == OGS_OK); } } else if (!strcmp(mme_key, "gtpc")) { @@ -965,6 +976,9 @@ int mme_context_parse_config() const char *hostname[OGS_MAX_NUM_OF_HOSTNAME]; uint16_t port = self.sgsap_port; + ogs_sockopt_t option; + bool is_option = false; + if (ogs_yaml_iter_type(&sgsap_array) == YAML_MAPPING_NODE) { memcpy(&sgsap_iter, &sgsap_array, @@ -1025,6 +1039,11 @@ int mme_context_parse_config() port = atoi(v); self.sgsap_port = port; } + } else if (!strcmp(sgsap_key, "option")) { + rv = ogs_app_config_parse_sockopt( + &sgsap_iter, &option); + if (rv != OGS_OK) return rv; + is_option = true; } else if (!strcmp(sgsap_key, "map")) { ogs_yaml_iter_t map_iter; ogs_yaml_iter_recurse(&sgsap_iter, &map_iter); @@ -1227,7 +1246,7 @@ int mme_context_parse_config() if (addr == NULL) continue; - vlr = mme_vlr_add(addr); + vlr = mme_vlr_add(addr, is_option ? &option : NULL); ogs_assert(vlr); for (i = 0; i < map_num; i++) { @@ -1632,7 +1651,7 @@ ogs_sockaddr_t *mme_pgw_addr_find_by_apn( return NULL; } -mme_vlr_t *mme_vlr_add(ogs_sockaddr_t *sa_list) +mme_vlr_t *mme_vlr_add(ogs_sockaddr_t *sa_list, ogs_sockopt_t *option) { mme_vlr_t *vlr = NULL; @@ -1646,6 +1665,10 @@ mme_vlr_t *mme_vlr_add(ogs_sockaddr_t *sa_list) vlr->ostream_id = 0; vlr->sa_list = sa_list; + if (option) { + vlr->max_num_of_ostreams = option->sctp.sinit_num_ostreams; + vlr->option = ogs_memdup(option, sizeof *option); + } ogs_list_add(&self.vlr_list, vlr); @@ -1661,6 +1684,8 @@ void mme_vlr_remove(mme_vlr_t *vlr) mme_vlr_close(vlr); ogs_freeaddrinfo(vlr->sa_list); + if (vlr->option) + ogs_free(vlr->option); ogs_pool_free(&mme_vlr_pool, vlr); } @@ -1783,12 +1808,8 @@ mme_enb_t *mme_enb_add(ogs_sock_t *sock, ogs_sockaddr_t *addr) ogs_list_init(&enb->sctp.write_queue); } - enb->max_num_of_ostreams = OGS_DEFAULT_SCTP_MAX_NUM_OF_OSTREAMS; + enb->max_num_of_ostreams = 0; enb->ostream_id = 0; - if (ogs_app()->sctp.max_num_of_ostreams) { - enb->max_num_of_ostreams = ogs_app()->sctp.max_num_of_ostreams; - ogs_info("[ENB] max_num_of_ostreams : %d", enb->max_num_of_ostreams); - } ogs_list_init(&enb->enb_ue_list); @@ -1917,6 +1938,7 @@ enb_ue_t *enb_ue_add(mme_enb_t *enb, uint32_t enb_ue_s1ap_id) * 0 : Non UE signalling * 1-29 : UE specific association */ + ogs_assert((enb->max_num_of_ostreams-1) >= 1); /* NEXT_ID(MAX >= MIN) */ enb_ue->enb_ostream_id = OGS_NEXT_ID(enb->ostream_id, 1, enb->max_num_of_ostreams-1); diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index d92ddd07a..0683acde0 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -184,6 +184,7 @@ typedef struct mme_vlr_s { ogs_sock_t *sock; /* VLR SGsAP Socket */ ogs_sockaddr_t *addr; /* VLR SGsAP Connected Socket Address */ + ogs_sockopt_t *option; /* VLR SGsAP Socket Option */ ogs_poll_t *poll; /* VLR SGsAP Poll */ } mme_vlr_t; @@ -670,7 +671,7 @@ void mme_pgw_remove_all(void); ogs_sockaddr_t *mme_pgw_addr_find_by_apn( ogs_list_t *list, int family, char *apn); -mme_vlr_t *mme_vlr_add(ogs_sockaddr_t *addr); +mme_vlr_t *mme_vlr_add(ogs_sockaddr_t *addr, ogs_sockopt_t *option); void mme_vlr_remove(mme_vlr_t *vlr); void mme_vlr_remove_all(void); void mme_vlr_close(mme_vlr_t *vlr); diff --git a/src/mme/mme-sm.c b/src/mme/mme-sm.c index 18165a5f7..7f3ec3877 100644 --- a/src/mme/mme-sm.c +++ b/src/mme/mme-sm.c @@ -184,10 +184,13 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) ogs_free(addr); } - enb->max_num_of_ostreams = - ogs_min(max_num_of_ostreams, enb->max_num_of_ostreams); + if (enb->max_num_of_ostreams) + enb->max_num_of_ostreams = + ogs_min(max_num_of_ostreams, enb->max_num_of_ostreams); + else + enb->max_num_of_ostreams = max_num_of_ostreams; - ogs_debug("eNB-S1 SCTP_COMM_UP[%s] Max Num of Outbound Streams[%d]", + ogs_info("eNB-N2[%s] max_num_of_ostreams : %d", OGS_ADDR(enb->sctp.addr, buf), enb->max_num_of_ostreams); break; diff --git a/src/mme/s1ap-sctp.c b/src/mme/s1ap-sctp.c index ed20ca38c..e63b4330c 100644 --- a/src/mme/s1ap-sctp.c +++ b/src/mme/s1ap-sctp.c @@ -35,22 +35,30 @@ ogs_sock_t *s1ap_server(ogs_socknode_t *node) { char buf[OGS_ADDRSTRLEN]; ogs_sock_t *sock = NULL; +#if !HAVE_USRSCTP + ogs_poll_t *poll = NULL; +#endif ogs_assert(node); #if HAVE_USRSCTP - sock = ogs_sctp_server(SOCK_SEQPACKET, node); + sock = ogs_sctp_server(SOCK_SEQPACKET, node->addr, node->option); if (!sock) return NULL; usrsctp_set_non_blocking((struct socket *)sock, 1); usrsctp_set_upcall((struct socket *)sock, usrsctp_recv_handler, NULL); #else - sock = ogs_sctp_server(SOCK_STREAM, node); + sock = ogs_sctp_server(SOCK_STREAM, node->addr, node->option); if (!sock) return NULL; - node->poll = ogs_pollset_add(ogs_app()->pollset, + poll = ogs_pollset_add(ogs_app()->pollset, OGS_POLLIN, sock->fd, lksctp_accept_handler, sock); - ogs_assert(node->poll); + ogs_assert(poll); + + node->poll = poll; #endif + node->sock = sock; + node->cleanup = ogs_sctp_destroy; + ogs_info("s1ap_server() [%s]:%d", OGS_ADDR(node->addr, buf), OGS_PORT(node->addr)); diff --git a/src/mme/sgsap-sctp.c b/src/mme/sgsap-sctp.c index bf7385ec9..ccd0ed1ea 100644 --- a/src/mme/sgsap-sctp.c +++ b/src/mme/sgsap-sctp.c @@ -35,19 +35,15 @@ static void recv_handler(ogs_sock_t *sock); ogs_sock_t *sgsap_client(mme_vlr_t *vlr) { char buf[OGS_ADDRSTRLEN]; - ogs_socknode_t node; ogs_sock_t *sock = NULL; ogs_assert(vlr); - memset(&node, 0, sizeof node); - node.addr = vlr->sa_list; - - sock = ogs_sctp_client(SOCK_SEQPACKET, &node); + sock = ogs_sctp_client(SOCK_SEQPACKET, vlr->sa_list, vlr->option); if (sock) { vlr->sock = sock; #if HAVE_USRSCTP - vlr->addr = node.addr; + vlr->addr = vlr->sa_list; usrsctp_set_non_blocking((struct socket *)sock, 1); usrsctp_set_upcall((struct socket *)sock, usrsctp_recv_handler, NULL); #else diff --git a/src/nssf/context.c b/src/nssf/context.c index 7dac31af9..bd64d7684 100644 --- a/src/nssf/context.c +++ b/src/nssf/context.c @@ -114,6 +114,9 @@ int nssf_context_parse_config(void) const char *key = NULL, *pem = NULL; const char *sst = NULL, *sd = NULL; + ogs_sockopt_t option; + bool is_option = false; + if (ogs_yaml_iter_type(&nsi_array) == YAML_MAPPING_NODE) { memcpy(&nsi_iter, &nsi_array, @@ -173,6 +176,11 @@ int nssf_context_parse_config(void) } } else if (!strcmp(nsi_key, "dev")) { dev = ogs_yaml_iter_value(&nsi_iter); + } else if (!strcmp(nsi_key, "option")) { + rv = ogs_app_config_parse_sockopt( + &nsi_iter, &option); + if (rv != OGS_OK) return rv; + is_option = true; } else if (!strcmp(nsi_key, "tls")) { ogs_yaml_iter_t tls_iter; ogs_yaml_iter_recurse(&nsi_iter, &tls_iter); @@ -223,9 +231,13 @@ int nssf_context_parse_config(void) if (addr) { if (ogs_app()->parameter.no_ipv4 == 0) - ogs_socknode_add(&list, AF_INET, addr); + ogs_socknode_add( + &list, AF_INET, addr, + is_option ? &option : NULL); if (ogs_app()->parameter.no_ipv6 == 0) - ogs_socknode_add(&list6, AF_INET6, addr); + ogs_socknode_add( + &list6, AF_INET6, addr, + is_option ? &option : NULL); ogs_freeaddrinfo(addr); } @@ -233,7 +245,8 @@ int nssf_context_parse_config(void) rv = ogs_socknode_probe( ogs_app()->parameter.no_ipv4 ? NULL : &list, ogs_app()->parameter.no_ipv6 ? NULL : &list6, - dev, port); + dev, port, + is_option ? &option : NULL); ogs_assert(rv == OGS_OK); } diff --git a/tests/common/context.c b/tests/common/context.c index 3fe9aab13..c1b326a06 100644 --- a/tests/common/context.c +++ b/tests/common/context.c @@ -161,6 +161,9 @@ int test_context_parse_config(void) const char *dev = NULL; ogs_sockaddr_t *addr = NULL; + ogs_sockopt_t option; + bool is_option = false; + if (ogs_yaml_iter_type(&ngap_array) == YAML_MAPPING_NODE) { memcpy(&ngap_iter, &ngap_array, @@ -217,6 +220,11 @@ int test_context_parse_config(void) if (v) port = atoi(v); } else if (!strcmp(ngap_key, "dev")) { dev = ogs_yaml_iter_value(&ngap_iter); + } else if (!strcmp(ngap_key, "option")) { + rv = ogs_app_config_parse_sockopt( + &ngap_iter, &option); + if (rv != OGS_OK) return rv; + is_option = true; } else ogs_warn("unknown key `%s`", ngap_key); } @@ -231,10 +239,12 @@ int test_context_parse_config(void) if (addr) { if (ogs_app()->parameter.no_ipv4 == 0) ogs_socknode_add( - &self.ngap_list, AF_INET, addr); + &self.ngap_list, AF_INET, addr, + is_option ? &option : NULL); if (ogs_app()->parameter.no_ipv6 == 0) ogs_socknode_add( - &self.ngap_list6, AF_INET6, addr); + &self.ngap_list6, AF_INET6, addr, + is_option ? &option : NULL); ogs_freeaddrinfo(addr); } @@ -244,7 +254,8 @@ int test_context_parse_config(void) NULL : &self.ngap_list, ogs_app()->parameter.no_ipv6 ? NULL : &self.ngap_list6, - dev, port); + dev, port, + is_option ? &option : NULL); ogs_assert(rv == OGS_OK); } @@ -258,7 +269,7 @@ int test_context_parse_config(void) NULL : &self.ngap_list, ogs_app()->parameter.no_ipv6 ? NULL : &self.ngap_list6, - NULL, self.ngap_port); + NULL, self.ngap_port, NULL); ogs_assert(rv == OGS_OK); } } if (!strcmp(amf_key, "tai")) { @@ -545,6 +556,9 @@ int test_context_parse_config(void) const char *dev = NULL; ogs_sockaddr_t *addr = NULL; + ogs_sockopt_t option; + bool is_option = false; + if (ogs_yaml_iter_type(&s1ap_array) == YAML_MAPPING_NODE) { memcpy(&s1ap_iter, &s1ap_array, @@ -601,6 +615,11 @@ int test_context_parse_config(void) if (v) port = atoi(v); } else if (!strcmp(s1ap_key, "dev")) { dev = ogs_yaml_iter_value(&s1ap_iter); + } else if (!strcmp(s1ap_key, "option")) { + rv = ogs_app_config_parse_sockopt( + &s1ap_iter, &option); + if (rv != OGS_OK) return rv; + is_option = true; } else ogs_warn("unknown key `%s`", s1ap_key); } @@ -615,10 +634,12 @@ int test_context_parse_config(void) if (addr) { if (ogs_app()->parameter.no_ipv4 == 0) ogs_socknode_add( - &self.s1ap_list, AF_INET, addr); + &self.s1ap_list, AF_INET, addr, + is_option ? &option : NULL); if (ogs_app()->parameter.no_ipv6 == 0) ogs_socknode_add( - &self.s1ap_list6, AF_INET6, addr); + &self.s1ap_list6, AF_INET6, addr, + is_option ? &option : NULL); ogs_freeaddrinfo(addr); } @@ -628,7 +649,8 @@ int test_context_parse_config(void) NULL : &self.s1ap_list, ogs_app()->parameter.no_ipv6 ? NULL : &self.s1ap_list6, - dev, port); + dev, port, + is_option ? &option : NULL); ogs_assert(rv == OGS_OK); } @@ -642,7 +664,7 @@ int test_context_parse_config(void) NULL : &self.s1ap_list, ogs_app()->parameter.no_ipv6 ? NULL : &self.s1ap_list6, - NULL, self.s1ap_port); + NULL, self.s1ap_port, NULL); ogs_assert(rv == OGS_OK); } } else if (!strcmp(mme_key, "tai")) { diff --git a/tests/common/gtpu.c b/tests/common/gtpu.c index 304a7289b..5850bce41 100644 --- a/tests/common/gtpu.c +++ b/tests/common/gtpu.c @@ -47,9 +47,11 @@ ogs_socknode_t *test_gtpu_server(int index, int family) node = ogs_socknode_new(addr); ogs_assert(node); - sock = ogs_udp_server(node, false); + sock = ogs_udp_server(node->addr, NULL); ogs_assert(sock); + node->sock = sock; + return node; } diff --git a/tests/common/sctp.c b/tests/common/sctp.c index ce66983ce..96fdc48f7 100644 --- a/tests/common/sctp.c +++ b/tests/common/sctp.c @@ -24,6 +24,7 @@ ogs_socknode_t *testsctp_server(const char *ipstr, int port) int rv; ogs_sockaddr_t *addr = NULL; ogs_socknode_t *node = NULL; + ogs_sock_t *sock = NULL; rv = ogs_getaddrinfo(&addr, AF_UNSPEC, ipstr, port, 0); ogs_assert(rv == OGS_OK); @@ -31,8 +32,11 @@ ogs_socknode_t *testsctp_server(const char *ipstr, int port) node = ogs_socknode_new(addr); ogs_assert(node); - ogs_sctp_server(SOCK_SEQPACKET, node); - ogs_assert(node->sock); + sock = ogs_sctp_server(SOCK_SEQPACKET, node->addr, NULL); + ogs_assert(sock); + + node->sock = sock; + node->cleanup = ogs_sctp_destroy; return node; } @@ -42,6 +46,7 @@ ogs_socknode_t *testsctp_client(const char *ipstr, int port) int rv; ogs_sockaddr_t *addr = NULL; ogs_socknode_t *node = NULL; + ogs_sock_t *sock = NULL; rv = ogs_getaddrinfo(&addr, AF_UNSPEC, ipstr, port, 0); ogs_assert(rv == OGS_OK); @@ -49,8 +54,67 @@ ogs_socknode_t *testsctp_client(const char *ipstr, int port) node = ogs_socknode_new(addr); ogs_assert(node); - ogs_sctp_client(SOCK_STREAM, node); - ogs_assert(node->sock); + sock = ogs_sctp_client(SOCK_STREAM, node->addr, NULL); + ogs_assert(sock); + + node->sock = sock; + node->cleanup = ogs_sctp_destroy; + + return node; +} + +ogs_socknode_t *tests1ap_client(int family) +{ + int rv; + ogs_sockaddr_t *addr = NULL; + ogs_socknode_t *node = NULL; + ogs_sock_t *sock = NULL; + + if (family == AF_INET6) + ogs_assert(OGS_OK == + ogs_copyaddrinfo(&addr, test_self()->s1ap_addr6)); + else + ogs_assert(OGS_OK == + ogs_copyaddrinfo(&addr, test_self()->s1ap_addr)); + + ogs_assert(addr); + + node = ogs_socknode_new(addr); + ogs_assert(node); + + sock = ogs_sctp_client(SOCK_STREAM, node->addr, NULL); + ogs_assert(sock); + + node->sock = sock; + node->cleanup = ogs_sctp_destroy; + + return node; +} + +ogs_socknode_t *testngap_client(int family) +{ + int rv; + ogs_sockaddr_t *addr = NULL; + ogs_socknode_t *node = NULL; + ogs_sock_t *sock = NULL; + + if (family == AF_INET6) + ogs_assert(OGS_OK == + ogs_copyaddrinfo(&addr, test_self()->ngap_addr6)); + else + ogs_assert(OGS_OK == + ogs_copyaddrinfo(&addr, test_self()->ngap_addr)); + + ogs_assert(addr); + + node = ogs_socknode_new(addr); + ogs_assert(node); + + sock = ogs_sctp_client(SOCK_STREAM, node->addr, NULL); + ogs_assert(sock); + + node->sock = sock; + node->cleanup = ogs_sctp_destroy; return node; } @@ -99,51 +163,3 @@ int testsctp_send(ogs_socknode_t *node, ogs_pkbuf_t *pkbuf, return OGS_OK; } - -ogs_socknode_t *tests1ap_client(int family) -{ - int rv; - ogs_sockaddr_t *addr = NULL; - ogs_socknode_t *node = NULL; - - if (family == AF_INET6) - ogs_assert(OGS_OK == - ogs_copyaddrinfo(&addr, test_self()->s1ap_addr6)); - else - ogs_assert(OGS_OK == - ogs_copyaddrinfo(&addr, test_self()->s1ap_addr)); - - ogs_assert(addr); - - node = ogs_socknode_new(addr); - ogs_assert(node); - - ogs_sctp_client(SOCK_STREAM, node); - ogs_assert(node->sock); - - return node; -} - -ogs_socknode_t *testngap_client(int family) -{ - int rv; - ogs_sockaddr_t *addr = NULL; - ogs_socknode_t *node = NULL; - - if (family == AF_INET6) - ogs_assert(OGS_OK == - ogs_copyaddrinfo(&addr, test_self()->ngap_addr6)); - else - ogs_assert(OGS_OK == - ogs_copyaddrinfo(&addr, test_self()->ngap_addr)); - - ogs_assert(addr); - - node = ogs_socknode_new(addr); - ogs_assert(node); - - ogs_sctp_client(SOCK_STREAM, node); - ogs_assert(node->sock); - - return node; -} diff --git a/tests/common/sctp.h b/tests/common/sctp.h index 9cb65797e..01858030f 100644 --- a/tests/common/sctp.h +++ b/tests/common/sctp.h @@ -28,14 +28,13 @@ extern ogs_sockaddr_t ogs_test_sctp_last_addr; ogs_socknode_t *testsctp_server(const char *ipstr, int port); ogs_socknode_t *testsctp_client(const char *ipstr, int port); +ogs_socknode_t *tests1ap_client(int family); +ogs_socknode_t *testngap_client(int family); + int testsctp_send(ogs_socknode_t *node, ogs_pkbuf_t *pkbuf, int ppid, uint16_t stream_no, int type); ogs_pkbuf_t *testsctp_read(ogs_socknode_t *node, int type); -ogs_socknode_t *tests1ap_client(int family); -ogs_socknode_t *testngap_client(int family); - -#define testenb_s1ap_client(x) testsctp_client(x, OGS_S1AP_SCTP_PORT) #define testenb_s1ap_read(x) testsctp_read(x, 0); #define testenb_s1ap_send(x, y) \ testsctp_send(x, y, OGS_SCTP_S1AP_PPID, 0, 0) diff --git a/tests/core/poll-test.c b/tests/core/poll-test.c index e97c0fcb1..02476863b 100644 --- a/tests/core/poll-test.c +++ b/tests/core/poll-test.c @@ -62,13 +62,13 @@ static void test1_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, OGS_OK, rv); server[i] = ogs_socknode_new(addr); ABTS_PTR_NOTNULL(tc, server[i]); - ogs_udp_server(server[i], false, false); + server[i]->sock = ogs_udp_server(server[i]->addr, NULL); ABTS_PTR_NOTNULL(tc, server[i]->sock); rv = ogs_getaddrinfo(&addr, AF_INET, "127.0.0.1", PORT+i, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); client[i] = ogs_socknode_new(addr); ABTS_PTR_NOTNULL(tc, client[i]); - ogs_udp_client(client[i]); + client[i]->sock = ogs_udp_client(client[i]->addr, NULL); ABTS_PTR_NOTNULL(tc, client[i]->sock); } @@ -132,8 +132,7 @@ static void test1_func(abts_case *tc, void *data) } #endif -static ogs_socknode_t *test2_server, *test2_client; -static ogs_sock_t *test2_accept; +static ogs_sock_t *test2_client; static int test2_okay = 1; static void test2_handler(short when, ogs_socket_t fd, void *data) @@ -147,7 +146,7 @@ static void test2_handler(short when, ogs_socket_t fd, void *data) len = ogs_send(fd, test, (int)strlen(test) + 1, 0); if (len > 0) { - ogs_socknode_free(test2_client); + ogs_sock_destroy(test2_client); } test2_okay = 0; @@ -157,29 +156,30 @@ static void test2_func(abts_case *tc, void *data) { int rv; ogs_poll_t *poll; + ogs_sock_t *server, *client, *accept; ogs_sockaddr_t *addr; ogs_pollset_t *pollset = ogs_pollset_create(512); ABTS_PTR_NOTNULL(tc, pollset); rv = ogs_getaddrinfo(&addr, AF_INET, "127.0.0.1", PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - test2_server = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, test2_server); - ogs_tcp_server(test2_server); - ABTS_PTR_NOTNULL(tc, test2_server->sock); + server = ogs_tcp_server(addr, NULL); + ABTS_PTR_NOTNULL(tc, server); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); rv = ogs_getaddrinfo(&addr, AF_INET, "127.0.0.1", PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - test2_client = ogs_socknode_new(addr); + test2_client = ogs_tcp_client(addr, NULL); ABTS_PTR_NOTNULL(tc, test2_client); - ogs_tcp_client(test2_client); - ABTS_PTR_NOTNULL(tc, test2_client->sock); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); - test2_accept = ogs_sock_accept(test2_server->sock); - ABTS_PTR_NOTNULL(tc, test2_accept); + accept = ogs_sock_accept(server); + ABTS_PTR_NOTNULL(tc, accept); poll = ogs_pollset_add(pollset, OGS_POLLOUT, - test2_accept->fd, test2_handler, tc); + accept->fd, test2_handler, tc); ABTS_PTR_NOTNULL(tc, poll); rv = ogs_pollset_poll(pollset, OGS_INFINITE_TIME); @@ -189,8 +189,8 @@ static void test2_func(abts_case *tc, void *data) ogs_pollset_remove(poll); - ogs_sock_destroy(test2_accept); - ogs_socknode_free(test2_server); + ogs_sock_destroy(accept); + ogs_sock_destroy(server); ogs_pollset_destroy(pollset); } @@ -249,7 +249,7 @@ static void test4_main(void *data) ogs_sockaddr_t *sa; ssize_t size; - udp = ogs_udp_socket(AF_INET, NULL); + udp = ogs_sock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); ABTS_PTR_NOTNULL(tc, udp); rv = ogs_getaddrinfo(&sa, AF_INET, NULL, PORT, 0); @@ -291,9 +291,7 @@ static void test4_func(abts_case *tc, void *data) rv = ogs_getaddrinfo(&addr, AF_INET, NULL, PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - udp = ogs_udp_server(node, false); + udp = ogs_udp_server(addr, NULL); ABTS_PTR_NOTNULL(tc, udp); poll = ogs_pollset_add(pollset, OGS_POLLIN, udp->fd, test4_handler, tc); @@ -306,7 +304,11 @@ static void test4_func(abts_case *tc, void *data) ogs_thread_destroy(test4_thread); ogs_pollset_remove(poll); - ogs_socknode_free(node); + + ogs_sock_destroy(udp); + + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); ogs_pollset_destroy(pollset); } @@ -460,57 +462,59 @@ static void test8_func(abts_case *tc, void *data) { int rv; ogs_poll_t *write1, *write2, *write3; + ogs_sock_t *server, *client1, *client2, *client3; + ogs_sock_t *accept1, *accept2, *accept3; ogs_sockaddr_t *addr; ogs_pollset_t *pollset = ogs_pollset_create(512); ABTS_PTR_NOTNULL(tc, pollset); rv = ogs_getaddrinfo(&addr, AF_INET, "127.0.0.1", PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - test8_server = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, test8_server); - ogs_tcp_server(test8_server); - ABTS_PTR_NOTNULL(tc, test8_server->sock); + server = ogs_tcp_server(addr, NULL); + ABTS_PTR_NOTNULL(tc, server); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); rv = ogs_getaddrinfo(&addr, AF_INET, "127.0.0.1", PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - test8_client1 = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, test8_client1); - ogs_tcp_client(test8_client1); - ABTS_PTR_NOTNULL(tc, test8_client1->sock); + client1 = ogs_tcp_client(addr, NULL); + ABTS_PTR_NOTNULL(tc, client1); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); - test8_accept1 = ogs_sock_accept(test8_server->sock); - ABTS_PTR_NOTNULL(tc, test8_accept1); + accept1 = ogs_sock_accept(server); + ABTS_PTR_NOTNULL(tc, accept1); rv = ogs_getaddrinfo(&addr, AF_INET, "127.0.0.1", PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - test8_client2 = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, test8_client2); - ogs_tcp_client(test8_client2); - ABTS_PTR_NOTNULL(tc, test8_client2->sock); + client2 = ogs_tcp_client(addr, NULL); + ABTS_PTR_NOTNULL(tc, client2); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); - test8_accept2 = ogs_sock_accept(test8_server->sock); - ABTS_PTR_NOTNULL(tc, test8_accept2); + accept2 = ogs_sock_accept(server); + ABTS_PTR_NOTNULL(tc, accept2); rv = ogs_getaddrinfo(&addr, AF_INET, "127.0.0.1", PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - test8_client3 = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, test8_client3); - ogs_tcp_client(test8_client3); - ABTS_PTR_NOTNULL(tc, test8_client3->sock); + client3 = ogs_tcp_client(addr, NULL); + ABTS_PTR_NOTNULL(tc, client3); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); - test8_accept3 = ogs_sock_accept(test8_server->sock); - ABTS_PTR_NOTNULL(tc, test8_accept3); + accept3 = ogs_sock_accept(server); + ABTS_PTR_NOTNULL(tc, accept3); write1 = ogs_pollset_add(pollset, OGS_POLLOUT, - test8_accept1->fd, test8_handler, NULL); + accept1->fd, test8_handler, NULL); ABTS_PTR_NOTNULL(tc, write1); write2 = ogs_pollset_add(pollset, OGS_POLLOUT, - test8_accept2->fd, test8_handler, NULL); + accept2->fd, test8_handler, NULL); ABTS_PTR_NOTNULL(tc, write2); write3 = ogs_pollset_add(pollset, OGS_POLLOUT, - test8_accept3->fd, test8_handler, NULL); + accept3->fd, test8_handler, NULL); ABTS_PTR_NOTNULL(tc, write3); rv = ogs_pollset_poll(pollset, OGS_INFINITE_TIME); @@ -523,11 +527,11 @@ static void test8_func(abts_case *tc, void *data) ogs_pollset_remove(write3); write2 = ogs_pollset_add(pollset, OGS_POLLOUT, - test8_accept2->fd, test8_handler, NULL); + accept2->fd, test8_handler, NULL); ABTS_PTR_NOTNULL(tc, write2); write3 = ogs_pollset_add(pollset, OGS_POLLOUT, - test8_accept3->fd, test8_handler, NULL); + accept3->fd, test8_handler, NULL); ABTS_PTR_NOTNULL(tc, write3); rv = ogs_pollset_poll(pollset, OGS_INFINITE_TIME); @@ -539,7 +543,7 @@ static void test8_func(abts_case *tc, void *data) ogs_pollset_remove(write3); write3 = ogs_pollset_add(pollset, OGS_POLLOUT, - test8_accept3->fd, test8_handler, NULL); + accept3->fd, test8_handler, NULL); ABTS_PTR_NOTNULL(tc, write3); rv = ogs_pollset_poll(pollset, OGS_INFINITE_TIME); @@ -550,17 +554,17 @@ static void test8_func(abts_case *tc, void *data) ogs_pollset_remove(write3); write1 = ogs_pollset_add(pollset, OGS_POLLOUT, - test8_accept1->fd, test8_handler_with_remove, + accept1->fd, test8_handler_with_remove, ogs_pollset_self_handler_data()); ABTS_PTR_NOTNULL(tc, write1); write2 = ogs_pollset_add(pollset, OGS_POLLOUT, - test8_accept2->fd, test8_handler_with_remove, + accept2->fd, test8_handler_with_remove, ogs_pollset_self_handler_data()); ABTS_PTR_NOTNULL(tc, write2); write3 = ogs_pollset_add(pollset, OGS_POLLOUT, - test8_accept3->fd, test8_handler_with_remove, + accept3->fd, test8_handler_with_remove, ogs_pollset_self_handler_data()); ABTS_PTR_NOTNULL(tc, write3); @@ -570,12 +574,12 @@ static void test8_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, 10, test8_okay); write1 = ogs_pollset_add(pollset, OGS_POLLOUT, - test8_accept1->fd, test8_handler_with_remove, + accept1->fd, test8_handler_with_remove, ogs_pollset_self_handler_data()); ABTS_PTR_NOTNULL(tc, write1); write2 = ogs_pollset_add(pollset, OGS_POLLOUT, - test8_accept2->fd, test8_handler_with_remove, + accept2->fd, test8_handler_with_remove, ogs_pollset_self_handler_data()); ABTS_PTR_NOTNULL(tc, write2); @@ -585,7 +589,7 @@ static void test8_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, 12, test8_okay); write1 = ogs_pollset_add(pollset, OGS_POLLOUT, - test8_accept1->fd, test8_handler_with_remove, + accept1->fd, test8_handler_with_remove, ogs_pollset_self_handler_data()); ABTS_PTR_NOTNULL(tc, write1); @@ -595,17 +599,17 @@ static void test8_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, 13, test8_okay); write1 = ogs_pollset_add(pollset, OGS_POLLIN|OGS_POLLOUT, - test8_accept1->fd, test8_handler_with_remove, + accept1->fd, test8_handler_with_remove, ogs_pollset_self_handler_data()); ABTS_PTR_NOTNULL(tc, write1); write2 = ogs_pollset_add(pollset, OGS_POLLIN|OGS_POLLOUT, - test8_accept2->fd, test8_handler_with_remove, + accept2->fd, test8_handler_with_remove, ogs_pollset_self_handler_data()); ABTS_PTR_NOTNULL(tc, write2); write3 = ogs_pollset_add(pollset, OGS_POLLIN|OGS_POLLOUT, - test8_accept3->fd, test8_handler_with_remove, + accept3->fd, test8_handler_with_remove, ogs_pollset_self_handler_data()); ABTS_PTR_NOTNULL(tc, write3); @@ -615,12 +619,12 @@ static void test8_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, 16, test8_okay); write2 = ogs_pollset_add(pollset, OGS_POLLIN|OGS_POLLOUT, - test8_accept2->fd, test8_handler_with_remove, + accept2->fd, test8_handler_with_remove, ogs_pollset_self_handler_data()); ABTS_PTR_NOTNULL(tc, write2); write3 = ogs_pollset_add(pollset, OGS_POLLIN|OGS_POLLOUT, - test8_accept3->fd, test8_handler_with_remove, + accept3->fd, test8_handler_with_remove, ogs_pollset_self_handler_data()); ABTS_PTR_NOTNULL(tc, write3); @@ -630,7 +634,7 @@ static void test8_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, 18, test8_okay); write3 = ogs_pollset_add(pollset, OGS_POLLIN|OGS_POLLOUT, - test8_accept3->fd, test8_handler_with_remove, + accept3->fd, test8_handler_with_remove, ogs_pollset_self_handler_data()); ABTS_PTR_NOTNULL(tc, write3); @@ -639,16 +643,16 @@ static void test8_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, 19, test8_okay); - ogs_socknode_free(test8_client1); - ogs_sock_destroy(test8_accept1); + ogs_sock_destroy(client1); + ogs_sock_destroy(accept1); - ogs_socknode_free(test8_client2); - ogs_sock_destroy(test8_accept2); + ogs_sock_destroy(client2); + ogs_sock_destroy(accept2); - ogs_socknode_free(test8_client3); - ogs_sock_destroy(test8_accept3); + ogs_sock_destroy(client3); + ogs_sock_destroy(accept3); - ogs_socknode_free(test8_server); + ogs_sock_destroy(server); ogs_pollset_destroy(pollset); } diff --git a/tests/core/socket-test.c b/tests/core/socket-test.c index d19739e02..7ae84a57f 100644 --- a/tests/core/socket-test.c +++ b/tests/core/socket-test.c @@ -34,31 +34,30 @@ static void test1_func(abts_case *tc, void *data) int rv; ogs_sock_t *udp; ogs_sockaddr_t *addr; - ogs_socknode_t *node; rv = ogs_getaddrinfo(&addr, AF_UNSPEC, NULL, PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - udp = ogs_udp_server(node, false); + udp = ogs_udp_server(addr, NULL); ABTS_PTR_NOTNULL(tc, udp); - ogs_socknode_free(node); + ogs_sock_destroy(udp); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); rv = ogs_getaddrinfo(&addr, AF_UNSPEC, "127.0.0.1", PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - udp = ogs_udp_server(node, false); + udp = ogs_udp_server(addr, NULL); ABTS_PTR_NOTNULL(tc, udp); - ogs_socknode_free(node); + ogs_sock_destroy(udp); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); rv = ogs_getaddrinfo(&addr, AF_UNSPEC, "::1", PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - udp = ogs_udp_server(node, false); + udp = ogs_udp_server(addr, NULL); ABTS_PTR_NOTNULL(tc, udp); - ogs_socknode_free(node); + ogs_sock_destroy(udp); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); } static ogs_thread_t *test2_thread; @@ -68,21 +67,20 @@ static void test2_main(void *data) abts_case *tc = data; ogs_sock_t *tcp; ogs_sockaddr_t *addr; - ogs_socknode_t *node; char str[STRLEN]; ssize_t size; rv = ogs_getaddrinfo(&addr, AF_UNSPEC, "::1", PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - tcp = ogs_tcp_client(node); + tcp = ogs_tcp_client(addr, NULL); ABTS_PTR_NOTNULL(tc, tcp); size = ogs_recv(tcp->fd, str, STRLEN, 0); ABTS_INT_EQUAL(tc, strlen(DATASTR), size); - ogs_socknode_free(node); + ogs_sock_destroy(tcp); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); } static void test2_func(abts_case *tc, void *data) @@ -95,9 +93,7 @@ static void test2_func(abts_case *tc, void *data) rv = ogs_getaddrinfo(&addr, AF_INET6, NULL, PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - tcp = ogs_tcp_server(node); + tcp = ogs_tcp_server(addr, NULL); ABTS_PTR_NOTNULL(tc, tcp); test2_thread = ogs_thread_create(test2_main, tc); @@ -112,7 +108,9 @@ static void test2_func(abts_case *tc, void *data) ogs_thread_destroy(test2_thread); ogs_sock_destroy(tcp2); - ogs_socknode_free(node); + ogs_sock_destroy(tcp); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); } static ogs_thread_t *test3_thread; @@ -127,7 +125,7 @@ static void test3_main(void *data) rv = ogs_getaddrinfo(&addr, AF_INET, NULL, PORT, 0); ABTS_INT_EQUAL(tc, OGS_OK, rv); - udp = ogs_udp_socket(AF_INET, NULL); + udp = ogs_sock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); ABTS_PTR_NOTNULL(tc, udp); size = ogs_sendto(udp->fd, DATASTR, strlen(DATASTR), 0, addr); @@ -146,15 +144,12 @@ static void test3_func(abts_case *tc, void *data) ssize_t size; ogs_sockaddr_t sa; ogs_sockaddr_t *addr; - ogs_socknode_t *node; char str[STRLEN]; char buf[OGS_ADDRSTRLEN]; rv = ogs_getaddrinfo(&addr, AF_INET, NULL, PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - udp = ogs_udp_server(node, false); + udp = ogs_udp_server(addr, NULL); ABTS_PTR_NOTNULL(tc, udp); test3_thread = ogs_thread_create(test3_main, tc); @@ -166,7 +161,10 @@ static void test3_func(abts_case *tc, void *data) ogs_thread_destroy(test3_thread); - ogs_socknode_free(node); + ogs_sock_destroy(udp); + + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); } static ogs_thread_t *test4_thread; @@ -176,15 +174,12 @@ static void test4_main(void *data) abts_case *tc = data; ogs_sock_t *udp; ogs_sockaddr_t *addr; - ogs_socknode_t *node; char str[STRLEN]; ssize_t size; rv = ogs_getaddrinfo(&addr, AF_INET, NULL, PORT, 0); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - udp = ogs_udp_client(node); + udp = ogs_udp_client(addr, NULL); ABTS_PTR_NOTNULL(tc, udp); size = ogs_send(udp->fd, DATASTR, strlen(DATASTR), 0); @@ -193,7 +188,10 @@ static void test4_main(void *data) size = ogs_recv(udp->fd, str, STRLEN, 0); ABTS_INT_EQUAL(tc, strlen(DATASTR), size); - ogs_socknode_free(node); + ogs_sock_destroy(udp); + + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); } static void test4_func(abts_case *tc, void *data) @@ -203,15 +201,12 @@ static void test4_func(abts_case *tc, void *data) ssize_t size; ogs_sockaddr_t sa; ogs_sockaddr_t *addr; - ogs_socknode_t *node; char str[STRLEN]; char buf[OGS_ADDRSTRLEN]; rv = ogs_getaddrinfo(&addr, AF_INET, NULL, PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - udp = ogs_udp_server(node, false); + udp = ogs_udp_server(addr, NULL); ABTS_PTR_NOTNULL(tc, udp); test4_thread = ogs_thread_create(test4_main, tc); @@ -226,7 +221,10 @@ static void test4_func(abts_case *tc, void *data) ogs_thread_destroy(test4_thread); - ogs_socknode_free(node); + ogs_sock_destroy(udp); + + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); } static ogs_thread_t *test5_thread; @@ -242,10 +240,10 @@ static void test5_main(void *data) rv = ogs_getaddrinfo(&addr, AF_INET6, NULL, PORT2, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - udp = ogs_udp_server(node, false); + udp = ogs_udp_server(addr, NULL); ABTS_PTR_NOTNULL(tc, udp); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); rv = ogs_getaddrinfo(&addr, AF_INET6, NULL, PORT, 0); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -260,7 +258,7 @@ static void test5_main(void *data) size = ogs_recv(udp->fd, str, STRLEN, 0); ABTS_INT_EQUAL(tc, strlen(DATASTR), size); - ogs_socknode_free(node); + ogs_sock_destroy(udp); } static void test5_func(abts_case *tc, void *data) @@ -269,16 +267,15 @@ static void test5_func(abts_case *tc, void *data) int rv; ssize_t size; ogs_sockaddr_t sa, *addr; - ogs_socknode_t *node; char str[STRLEN]; char buf[OGS_ADDRSTRLEN]; rv = ogs_getaddrinfo(&addr, AF_INET6, NULL, PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - udp = ogs_udp_server(node, false); + udp = ogs_udp_server(addr, NULL); ABTS_PTR_NOTNULL(tc, udp); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); rv = ogs_getaddrinfo(&addr, AF_INET6, NULL, PORT2, 0); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -299,7 +296,7 @@ static void test5_func(abts_case *tc, void *data) ogs_thread_destroy(test5_thread); - ogs_socknode_free(node); + ogs_sock_destroy(udp); } static void test6_func(abts_case *tc, void *data) @@ -389,14 +386,14 @@ static void test7_func(abts_case *tc, void *data) rv = ogs_getaddrinfo(&addr, AF_UNSPEC, "localhost", PORT, 0); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_add(&list, AF_INET, addr); + node = ogs_socknode_add(&list, AF_INET, addr, NULL); ABTS_PTR_NOTNULL(tc, node); ogs_freeaddrinfo(addr); ogs_socknode_remove_all(&list); - rv = ogs_socknode_probe(&list, &list6, NULL, PORT); + rv = ogs_socknode_probe(&list, &list6, NULL, PORT, NULL); ABTS_INT_EQUAL(tc, OGS_OK, rv); ogs_socknode_remove_all(&list); diff --git a/tests/non3gpp/gtp-path.c b/tests/non3gpp/gtp-path.c index 45f06dc81..f9cfb2fff 100644 --- a/tests/non3gpp/gtp-path.c +++ b/tests/non3gpp/gtp-path.c @@ -38,9 +38,11 @@ ogs_socknode_t *test_epdg_server(uint16_t port) node = ogs_socknode_new(addr); ogs_assert(node); - sock = ogs_udp_server(node, false); + sock = ogs_udp_server(node->addr, NULL); ogs_assert(sock); + node->sock = sock; + return node; } diff --git a/tests/sctp/sctp-test.c b/tests/sctp/sctp-test.c index 6cd18965d..1ac33b801 100644 --- a/tests/sctp/sctp-test.c +++ b/tests/sctp/sctp-test.c @@ -39,28 +39,27 @@ static void test1_func(abts_case *tc, void *data) { ogs_sock_t *sctp; ogs_sockaddr_t *addr; - ogs_socknode_t *node; int rv; - sctp = ogs_sctp_socket(AF_INET6, SOCK_SEQPACKET, NULL); + sctp = ogs_sctp_socket(AF_INET6, SOCK_SEQPACKET); ABTS_PTR_NOTNULL(tc, sctp); ogs_sctp_destroy(sctp); rv = ogs_getaddrinfo(&addr, AF_INET, NULL, TEST1_PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - sctp = ogs_sctp_server(SOCK_STREAM, node); + sctp = ogs_sctp_server(SOCK_STREAM, addr, NULL); ABTS_PTR_NOTNULL(tc, sctp); - ogs_socknode_free(node); + ogs_sctp_destroy(sctp); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); rv = ogs_getaddrinfo(&addr, AF_UNSPEC, NULL, TEST1_PORT2, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - sctp = ogs_sctp_server(SOCK_SEQPACKET, node); + sctp = ogs_sctp_server(SOCK_SEQPACKET, addr, NULL); ABTS_PTR_NOTNULL(tc, sctp); - ogs_socknode_free(node); + ogs_sctp_destroy(sctp); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); } static ogs_thread_t *test2_thread; @@ -74,14 +73,11 @@ static void test2_main(void *data) uint32_t ppid; ogs_sctp_info_t sinfo; ogs_sockaddr_t *addr; - ogs_socknode_t *node; ogs_sockaddr_t from; rv = ogs_getaddrinfo(&addr, AF_UNSPEC, NULL, TEST2_PORT, 0); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - sctp = ogs_sctp_client(SOCK_SEQPACKET, node); + sctp = ogs_sctp_client(SOCK_SEQPACKET, addr, NULL); ABTS_PTR_NOTNULL(tc, sctp); size = ogs_sctp_recvdata(sctp, str, STRLEN, &from, &sinfo); @@ -90,7 +86,9 @@ static void test2_main(void *data) ABTS_INT_EQUAL(tc, PPID, sinfo.ppid); #endif - ogs_socknode_free(node); + ogs_sctp_destroy(sctp); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); } static void test2_func(abts_case *tc, void *data) @@ -99,13 +97,10 @@ static void test2_func(abts_case *tc, void *data) ogs_sock_t *sctp, *sctp2; ssize_t size; ogs_sockaddr_t *addr; - ogs_socknode_t *node; rv = ogs_getaddrinfo(&addr, AF_INET6, NULL, TEST2_PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - sctp = ogs_sctp_server(SOCK_STREAM, node); + sctp = ogs_sctp_server(SOCK_STREAM, addr, NULL); ABTS_PTR_NOTNULL(tc, sctp); test2_thread = ogs_thread_create(test2_main, tc); @@ -120,7 +115,10 @@ static void test2_func(abts_case *tc, void *data) ogs_thread_destroy(test2_thread); ogs_sctp_destroy(sctp2); - ogs_socknode_free(node); + ogs_sctp_destroy(sctp); + + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); } static ogs_thread_t *test3_thread; @@ -135,9 +133,12 @@ static void test3_main(void *data) ssize_t size; int rc; - sctp = ogs_sctp_socket(AF_INET, SOCK_SEQPACKET, NULL); + sctp = ogs_sctp_socket(AF_INET, SOCK_SEQPACKET); ABTS_PTR_NOTNULL(tc, sctp); + rv = ogs_sctp_nodelay(sctp, 1); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = ogs_getaddrinfo(&to, AF_INET, NULL, TEST3_PORT, 0); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -156,16 +157,13 @@ static void test3_func(abts_case *tc, void *data) int rv; ssize_t size; ogs_sockaddr_t from, *addr; - ogs_socknode_t *node; char str[STRLEN]; char buf[OGS_ADDRSTRLEN]; ogs_sctp_info_t sinfo; rv = ogs_getaddrinfo(&addr, AF_INET, NULL, TEST3_PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - sctp = ogs_sctp_server(SOCK_SEQPACKET, node); + sctp = ogs_sctp_server(SOCK_SEQPACKET, addr, NULL); ABTS_PTR_NOTNULL(tc, sctp); test3_thread = ogs_thread_create(test3_main, tc); @@ -179,7 +177,10 @@ static void test3_func(abts_case *tc, void *data) ogs_thread_destroy(test3_thread); - ogs_socknode_free(node); + ogs_sctp_destroy(sctp); + + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); } static ogs_thread_t *test4_thread; @@ -189,16 +190,13 @@ static void test4_main(void *data) abts_case *tc = data; ogs_sock_t *sctp; ogs_sockaddr_t *addr; - ogs_socknode_t *node; char str[STRLEN]; ssize_t size; ogs_sctp_info_t sinfo; rv = ogs_getaddrinfo(&addr, AF_UNSPEC, NULL, TEST4_PORT, 0); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - sctp = ogs_sctp_client(SOCK_STREAM, node); + sctp = ogs_sctp_client(SOCK_STREAM, addr, NULL); ABTS_PTR_NOTNULL(tc, sctp); size = ogs_sctp_sendmsg(sctp, DATASTR, strlen(DATASTR), NULL, PPID, 0); @@ -210,7 +208,10 @@ static void test4_main(void *data) ABTS_INT_EQUAL(tc, PPID, sinfo.ppid); #endif - ogs_socknode_free(node); + ogs_sctp_destroy(sctp); + + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); } static void test4_func(abts_case *tc, void *data) @@ -219,16 +220,13 @@ static void test4_func(abts_case *tc, void *data) ogs_sock_t *sctp; ssize_t size; ogs_sockaddr_t from, *addr; - ogs_socknode_t *node; char str[STRLEN]; ogs_sctp_info_t sinfo; char buf[OGS_ADDRSTRLEN]; rv = ogs_getaddrinfo(&addr, AF_INET6, NULL, TEST4_PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - sctp = ogs_sctp_server(SOCK_SEQPACKET, node); + sctp = ogs_sctp_server(SOCK_SEQPACKET, addr, NULL); ABTS_PTR_NOTNULL(tc, sctp); test4_thread = ogs_thread_create(test4_main, tc); @@ -245,7 +243,11 @@ static void test4_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, strlen(DATASTR), size); ogs_thread_destroy(test4_thread); - ogs_socknode_free(node); + + ogs_sctp_destroy(sctp); + + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); } static ogs_thread_t *test5_thread; @@ -256,17 +258,16 @@ static void test5_main(void *data) ogs_sock_t *sctp; char str[STRLEN]; ogs_sockaddr_t from, *remote_addr, *addr; - ogs_socknode_t *node; ogs_sctp_info_t sinfo; ssize_t size; char buf[OGS_ADDRSTRLEN]; rv = ogs_getaddrinfo(&addr, AF_INET6, NULL, TEST5_PORT2, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - sctp = ogs_sctp_server(SOCK_SEQPACKET, node); + sctp = ogs_sctp_server(SOCK_SEQPACKET, addr, NULL); ABTS_PTR_NOTNULL(tc, sctp); + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); rv = ogs_getaddrinfo(&addr, AF_INET6, NULL, TEST5_PORT, 0); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -293,7 +294,7 @@ static void test5_main(void *data) ABTS_INT_EQUAL(tc, PPID, sinfo.ppid); #endif - ogs_socknode_free(node); + ogs_sctp_destroy(sctp); } static void test5_func(abts_case *tc, void *data) @@ -303,7 +304,6 @@ static void test5_func(abts_case *tc, void *data) ssize_t size; ogs_sockaddr_t from; ogs_sockaddr_t *addr; - ogs_socknode_t *node; socklen_t addrlen; char str[STRLEN]; ogs_sctp_info_t sinfo; @@ -311,9 +311,7 @@ static void test5_func(abts_case *tc, void *data) rv = ogs_getaddrinfo(&addr, AF_INET6, NULL, TEST5_PORT, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); - node = ogs_socknode_new(addr); - ABTS_PTR_NOTNULL(tc, node); - sctp = ogs_sctp_server(SOCK_SEQPACKET, node); + sctp = ogs_sctp_server(SOCK_SEQPACKET, addr, NULL); ABTS_PTR_NOTNULL(tc, sctp); test5_thread = ogs_thread_create(test5_main, tc); @@ -331,7 +329,11 @@ static void test5_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, strlen(DATASTR), size); ogs_thread_destroy(test5_thread); - ogs_socknode_free(node); + + ogs_sctp_destroy(sctp); + + rv = ogs_freeaddrinfo(addr); + ABTS_INT_EQUAL(tc, OGS_OK, rv); } abts_suite *test_sctp(abts_suite *suite)