diff --git a/.appveyor.yml b/.appveyor.yml
index 846afcba..7b5755c1 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -27,4 +27,4 @@ environment:
build_script:
- cd C:\projects\dps-for-iot
-- scons variant=%VARIANT% transport=%TRANSPORT% PYTHON_PATH=C:\Python27-x64 SWIG=C:\ProgramData\chocolatey\bin\swig.exe
+- scons variant=%VARIANT% transports=%TRANSPORT% PYTHON_PATH=C:\Python27-x64 SWIG=C:\ProgramData\chocolatey\bin\swig.exe
diff --git a/.gitignore b/.gitignore
index 9c40639f..179f1066 100755
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,5 @@ out
*.pdb
go/bin/*
go/pkg/*
+*.orig
+*.rej
diff --git a/.travis.yml b/.travis.yml
index 1f845972..baf77429 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,29 +7,23 @@ compiler:
- gcc
env:
- - VARIANT=debug TRANSPORT=udp BINDINGS=all ASAN=yes FSAN=no
- - VARIANT=debug TRANSPORT=tcp BINDINGS=all ASAN=yes FSAN=no
- - VARIANT=debug TRANSPORT=dtls BINDINGS=all ASAN=yes FSAN=no
- - VARIANT=debug TRANSPORT=pipe BINDINGS=all ASAN=yes FSAN=no
- - VARIANT=release TRANSPORT=udp BINDINGS=all ASAN=yes FSAN=no
- - VARIANT=release TRANSPORT=tcp BINDINGS=all ASAN=yes FSAN=no
- - VARIANT=release TRANSPORT=dtls BINDINGS=all ASAN=yes FSAN=no
- - VARIANT=release TRANSPORT=dtls BINDINGS=python,nodejs ASAN=yes FSAN=yes
- - VARIANT=release TRANSPORT=pipe BINDINGS=all ASAN=yes FSAN=no
- - VARIANT=release TRANSPORT=fuzzer BINDINGS=python,nodejs ASAN=yes FSAN=yes
+ - VARIANT=debug TRANSPORTS=udp,tcp,dtls,pipe BINDINGS=all ASAN=yes FSAN=no
+ - VARIANT=release TRANSPORTS=udp,tcp,dtls,pipe BINDINGS=all ASAN=yes FSAN=no
+ - VARIANT=release TRANSPORTS=dtls BINDINGS=python,nodejs ASAN=yes FSAN=yes
+ - VARIANT=release TRANSPORTS=fuzzer BINDINGS=python,nodejs ASAN=yes FSAN=yes
matrix:
exclude:
- compiler: clang
- compiler: gcc
- env: VARIANT=release TRANSPORT=dtls BINDINGS=python,nodejs ASAN=yes FSAN=yes
+ env: VARIANT=release TRANSPORTS=dtls BINDINGS=python,nodejs ASAN=yes FSAN=yes
- compiler: gcc
- env: VARIANT=release TRANSPORT=fuzzer BINDINGS=python,nodejs ASAN=yes FSAN=yes
+ env: VARIANT=release TRANSPORTS=fuzzer BINDINGS=python,nodejs ASAN=yes FSAN=yes
include:
- compiler: clang
- env: VARIANT=release TRANSPORT=dtls BINDINGS=python,nodejs ASAN=yes FSAN=yes
+ env: VARIANT=release TRANSPORTS=dtls BINDINGS=python,nodejs ASAN=yes FSAN=yes
- compiler: clang
- env: VARIANT=release TRANSPORT=fuzzer BINDINGS=python,nodejs ASAN=yes FSAN=yes
+ env: VARIANT=release TRANSPORTS=fuzzer BINDINGS=python,nodejs ASAN=yes FSAN=yes
addons:
apt:
@@ -54,5 +48,5 @@ install:
- pip install --user pexpect
script:
- - scons CC=$CC CXX=$CXX variant=$VARIANT transport=$TRANSPORT bindings=$BINDINGS asan=$ASAN ubsan=yes fsan=$FSAN
+ - scons CC=$CC CXX=$CXX variant=$VARIANT transports=$TRANSPORTS bindings=$BINDINGS asan=$ASAN ubsan=yes fsan=$FSAN
- ./test_scripts/run.py -d
diff --git a/SConscript b/SConscript
index 0880fb93..51857e1c 100755
--- a/SConscript
+++ b/SConscript
@@ -15,6 +15,20 @@ else:
commonenv.Append(CFLAGS = ['-Wstrict-prototypes'])
commonenv.Append(CPPPATH = ['#/inc'])
+# Additional transport defines for these files
+if commonenv['udp']:
+ commonenv['USE_UDP'] = 'true'
+ commonenv.Append(CPPDEFINES = ['DPS_USE_UDP'])
+if commonenv['tcp']:
+ commonenv['USE_TCP'] = 'true'
+ commonenv.Append(CPPDEFINES = ['DPS_USE_TCP'])
+if commonenv['dtls']:
+ commonenv['USE_DTLS'] = 'true'
+ commonenv.Append(CPPDEFINES = ['DPS_USE_DTLS'])
+if commonenv['pipe']:
+ commonenv['USE_PIPE'] = 'true'
+ commonenv.Append(CPPDEFINES = ['DPS_USE_PIPE'])
+
# Core libraries
libenv = commonenv.Clone()
@@ -61,19 +75,17 @@ srcs = ['src/bitvec.c',
'src/mbedtls.c',
'src/queue.c']
-if env['transport'] == 'udp':
- srcs.extend(['src/multicast/network.c',
- 'src/udp/network.c'])
-elif env['transport'] == 'dtls':
- srcs.extend(['src/multicast/network.c',
- 'src/dtls/network.c'])
-elif env['transport'] == 'tcp':
- srcs.extend(['src/multicast/network.c',
- 'src/tcp/network.c'])
-elif env['transport'] == 'pipe':
- srcs.extend(['src/multicast/network.c',
- 'src/pipe/network.c'])
-elif env['transport'] == 'fuzzer':
+if env['udp'] or env['dtls'] or env['tcp'] or env['pipe']:
+ srcs.extend(['src/multicast/network.c'])
+if env['udp']:
+ srcs.extend(['src/udp/network.c'])
+if env['dtls']:
+ srcs.extend(['src/dtls/network.c'])
+if env['tcp']:
+ srcs.extend(['src/tcp/network.c'])
+if env['pipe']:
+ srcs.extend(['src/pipe/network.c'])
+if env['fuzzer']:
srcs.extend(['src/fuzzer/network.c'])
Depends(srcs, ext_objs)
@@ -137,7 +149,7 @@ if env['python']:
elif 'gcc' in pyenv['CC']:
pyenv.Append(CCFLAGS = ['-Wno-ignored-qualifiers', '-Wno-cast-function-type'])
elif 'clang' in pyenv['CC']:
- pyenv.Append(CCFLAGS = ['-Wno-deprecated-register', '-Wno-ignored-qualifiers'])
+ pyenv.Append(CCFLAGS = ['-std=c++11', '-Wno-deprecated-register', '-Wno-ignored-qualifiers'])
pyenv.Append(SWIGFLAGS = ['-python', '-c++', '-Wextra', '-Werror', '-v', '-O'], SWIGPATH = ['#/inc', './swig/py'])
pyenv.Append(CPPPATH = ['swig', 'swig/py'])
@@ -313,9 +325,9 @@ if env['PLATFORM'] == 'posix' and env['fsan'] == True:
fenv.Append(LIBS = [lib, env['DPS_LIBS']])
fsrcs = ['test/fuzzer/cbor_fuzzer.c']
- if env['transport'] == 'dtls':
+ if 'dtls' in env['transports']:
fsrcs.extend(['test/fuzzer/dtls_fuzzer.c'])
- elif env['transport'] == 'fuzzer':
+ elif 'fuzzer' in env['transports']:
fsrcs.extend(['test/fuzzer/net_receive_fuzzer.c',
'test/fuzzer/multicast_receive_fuzzer.c'])
diff --git a/SConstruct b/SConstruct
index b637fe98..7a1c6acf 100755
--- a/SConstruct
+++ b/SConstruct
@@ -5,6 +5,7 @@ AddOption('--tool', action='append', dest='tools', help='Add tool to the environ
vars = Variables()
+transports = Split('udp tcp dtls pipe fuzzer')
bindings = Split('python nodejs go')
# Generic build variables
@@ -16,7 +17,7 @@ vars.AddVariables(
BoolVariable('fsan', 'Enable fuzzer sanitizer?', False),
BoolVariable('cov', 'Enable code coverage?', False),
EnumVariable('variant', 'Build variant', default='release', allowed_values=('debug', 'release'), ignorecase=2),
- EnumVariable('transport', 'Transport protocol', default='udp', allowed_values=('udp', 'tcp', 'dtls', 'pipe', 'fuzzer'), ignorecase=2),
+ ListVariable(['transports', 'transport'], 'Transport protocol', [t for t in transports if t != 'fuzzer'], transports),
EnumVariable('target', 'Build target', default='local', allowed_values=('local', 'yocto'), ignorecase=2),
ListVariable('bindings', 'Bindings to build', bindings, bindings),
PathVariable('application', 'Application to build', '', PathVariable.PathAccept),
@@ -63,18 +64,9 @@ for key, val in ARGLIST:
for b in bindings:
env[b] = b in env['bindings']
-if env['transport'] == 'udp':
- env['USE_UDP'] = 'true'
- env.Append(CPPDEFINES = ['DPS_USE_UDP'])
-elif env['transport'] == 'tcp':
- env['USE_TCP'] = 'true'
- env.Append(CPPDEFINES = ['DPS_USE_TCP'])
-elif env['transport'] == 'dtls':
- env['USE_DTLS'] = 'true'
- env.Append(CPPDEFINES = ['DPS_USE_DTLS'])
-elif env['transport'] == 'pipe':
- env['USE_PIPE'] = 'true'
- env.Append(CPPDEFINES = ['DPS_USE_PIPE'])
+# Unpack transports into individually testable booleans
+for t in transports:
+ env[t] = t in env['transports']
print("Building for " + env['variant'])
diff --git a/doc/Building-and-Running.dox b/doc/Building-and-Running.dox
index 6985cf79..b33c97f6 100644
--- a/doc/Building-and-Running.dox
+++ b/doc/Building-and-Running.dox
@@ -104,7 +104,7 @@ To build the DPS libraries, examples, bindings, and documentation run
@c scons.
@verbatim
-$ scons [variant=debug|release] [transport=udp|tcp|dtls] [bindings=all|none|{python,nodejs,go}]
+$ scons [variant=debug|release] [transports=udp|tcp|dtls] [bindings=all|none|{python,nodejs,go}]
@endverbatim
To build with a different compiler use the @c CC and @c CXX build
@@ -125,7 +125,7 @@ Depending on the platform and compiler only a subset of bindings are supported.
To see the complete list of build options run scons --help.
-The default build configuration is variant=release transport=udp
+The default build configuration is variant=release transports=udp
bindings=all.
@note A limitation of the current implementation is that the transport
diff --git a/doc/tutorial/hello_world.dox b/doc/tutorial/hello_world.dox
index 60fb74ae..c6340abe 100644
--- a/doc/tutorial/hello_world.dox
+++ b/doc/tutorial/hello_world.dox
@@ -32,9 +32,9 @@ parameter value allows both @c / and @c . as separators.
Once created, a node must be started. Starting a node enables it
to begin sending and receiving DPS messages in the network.
-For this example, we are going to be sending and receiving
-multicast publications so we enable both and let DPS assign the
-listening port.
+For this example, we are going to be sending and receiving multicast
+publications so we enable both and let DPS assign the listening
+address for the chosen network.
@see DPS_MCAST_PUB_DISABLED, DPS_GetListenAddress()
diff --git a/doc/tutorial/link.dox b/doc/tutorial/link.dox
index a03c2f5a..5ddd77cc 100644
--- a/doc/tutorial/link.dox
+++ b/doc/tutorial/link.dox
@@ -27,10 +27,10 @@ the @c mcastPub parameter of DPS_StartNode(). All publications and
subscriptions will go through the forwarding node.
The second thing we do is specify the @c listenAddr parameter to
-DPS_StartNode(). In this instance we bind the node to all available
-interfaces at the port provided. A port value of zero lets DPS assign
-an ephemeral listening port. A value of non-zero requests a specific
-port.
+DPS_StartNode(). In this instance we select UDP and bind the node to
+all available interfaces at the port provided for the chosen network.
+For IP networks, a port value of zero lets DPS assign an ephemeral
+listening port while a value of non-zero requests a specific port.
The last thing we do is get the port DPS has chosen with
DPS_GetListenAddress(). This will be used by the subscriber and
diff --git a/doc/tutorial/security.dox b/doc/tutorial/security.dox
index 4321beec..e8c0c28c 100644
--- a/doc/tutorial/security.dox
+++ b/doc/tutorial/security.dox
@@ -16,7 +16,7 @@ The first step to enabling network layer security is to build with
a transport that supports it.
@code
-$ scons transport=dtls
+$ scons transports=dtls
@endcode
The DTLS transport supports two mechanisms for securing the
diff --git a/doc/tutorial/tutorial.c b/doc/tutorial/tutorial.c
index af90ef44..9b308d0f 100644
--- a/doc/tutorial/tutorial.c
+++ b/doc/tutorial/tutorial.c
@@ -76,9 +76,10 @@ static DPS_Node* CreateNodeWithNetworkCert(const DPS_KeyId* nodeId);
static DPS_Node* CreateNodeWithSymmetricKeyStore(void);
static DPS_Node* CreateNodeWithAsymmetricKeyStore(void);
static DPS_Node* CreateNodeWithAuthenticatedSender(const DPS_KeyId* nodeId);
-static DPS_Status StartMulticastNode(DPS_Node* node);
-static DPS_Status StartUnicastNode(DPS_Node* node, uint16_t listenPort);
-static DPS_Status StartNode(DPS_Node* node, int mcastPub, const char* listenText);
+static DPS_Status StartMulticastNode(DPS_Node* node, const char* network);
+static DPS_Status StartUnicastNode(DPS_Node* node, const char* network, uint16_t listenPort);
+static DPS_Status StartNode(DPS_Node* node, int mcastPub, const char* network,
+ const char* listenAddrText);
static void LinkComplete(DPS_Node* node, DPS_NodeAddress* addr, DPS_Status status, void* data);
static DPS_Status Publish(DPS_Node* node, const char* security, DPS_Publication** createdPub);
static DPS_Status PublishAck(DPS_Node* node, const char* security, DPS_Publication** createdPub);
@@ -106,13 +107,29 @@ static void DestroyNode(DPS_Node* node);
static void Usage(int argc, char** argv)
{
- DPS_PRINT("Usage %s [-d] [-l ] [-p ] [-x ] [auth] [publish|subscribe] [ack]\n", argv[0]);
+ DPS_PRINT("Usage %s [-d] [-n ] [-l ] [-p ] [-x ] [auth] [publish|subscribe] [ack]\n", argv[0]);
DPS_PRINT(" -d: Enable debug ouput if built for debug.\n");
- DPS_PRINT(" -l: Port to listen on. This may be 0 to request an ephemeral port.\n");
- DPS_PRINT(" -p: Port to link to.\n");
+ DPS_PRINT(" -n: Network of listen and link addresses.\n");
+ DPS_PRINT(" -l: Address to listen on. This may be 0 to request an ephemeral port.\n");
+ DPS_PRINT(" -p: Address to link to.\n");
DPS_PRINT(" -x: Secure the node.\n");
}
+static int ParseAddress(char** argv, int argc, int* port, const char** addrText)
+{
+ char* endp;
+ int i = 0;
+
+ (*port) = strtol(argv[i], &endp, 10);
+ if (*endp == 0) {
+ ++i;
+ } else {
+ (*addrText) = argv[i++];
+ }
+
+ return i;
+}
+
int main(int argc, char** argv)
{
DPS_Node* node = NULL;
@@ -122,12 +139,12 @@ int main(int argc, char** argv)
int subscribe = DPS_FALSE;
int ack = DPS_FALSE;
int listenPort = -1;
- const char* listenText = NULL;
+ const char* listenAddrText = NULL;
int linkPort = 0;
- const char* linkText = NULL;
+ const char* linkAddrText = NULL;
+ const char* network = NULL;
const char *security = 0;
int auth = DPS_FALSE;
- char* endp;
int i;
DPS_Status ret;
@@ -140,17 +157,9 @@ int main(int argc, char** argv)
} else if (!strcmp(argv[i], "ack")) {
ack = DPS_TRUE;
} else if (!strcmp(argv[i], "-l") && ((i + 1) < argc)) {
- listenPort = strtol(argv[i + 1], &endp, 10);
- if (*endp) {
- listenText = argv[i + 1];
- }
- ++i;
+ i += ParseAddress(&argv[i + 1], argc - (i + 1), &listenPort, &listenAddrText);
} else if (!strcmp(argv[i], "-p") && ((i + 1) < argc)) {
- linkPort = strtol(argv[i + 1], &endp, 10);
- if (*endp) {
- linkText = argv[i + 1];
- }
- ++i;
+ i += ParseAddress(&argv[i + 1], argc - (i + 1), &linkPort, &linkAddrText);
} else if (!strcmp(argv[i], "-x") && ((i + 1) < argc)) {
security = argv[i + 1];
++i;
@@ -158,6 +167,9 @@ int main(int argc, char** argv)
auth = DPS_TRUE;
} else if (!strcmp(argv[i], "-d")) {
DPS_Debug = DPS_TRUE;
+ } else if (!strcmp(argv[i], "-n") && ((i + 1) < argc)) {
+ network = argv[i + 1];
+ ++i;
} else {
Usage(argc, argv);
return EXIT_FAILURE;
@@ -199,22 +211,22 @@ int main(int argc, char** argv)
goto Exit;
}
- if (linkText || listenText) {
- ret = StartNode(node, DPS_MCAST_PUB_DISABLED, listenText);
+ if (linkAddrText || listenAddrText) {
+ ret = StartNode(node, DPS_MCAST_PUB_DISABLED, network, listenAddrText);
} else if (linkPort || (listenPort >= 0)) {
if (listenPort == -1) {
listenPort = 0;
}
- ret = StartUnicastNode(node, listenPort);
+ ret = StartUnicastNode(node, network, listenPort);
} else {
- ret = StartMulticastNode(node);
+ ret = StartMulticastNode(node, network);
}
if (ret != DPS_OK) {
goto Exit;
}
- if (linkText) {
- ret = DPS_Link(node, linkText, LinkComplete, NULL);
+ if (linkAddrText) {
+ ret = DPS_Link(node, network, linkAddrText, LinkComplete, NULL);
if (ret != DPS_OK) {
goto Exit;
}
@@ -224,7 +236,7 @@ int main(int argc, char** argv)
/** [Linking to a node] */
char addrText[24];
snprintf(addrText, sizeof(addrText), "127.0.0.1:%d", linkPort);
- ret = DPS_Link(node, addrText, LinkComplete, NULL);
+ ret = DPS_Link(node, network, addrText, LinkComplete, NULL);
if (ret != DPS_OK) {
goto Exit;
}
@@ -362,18 +374,19 @@ static DPS_Node* CreateNodeWithAuthenticatedSender(const DPS_KeyId* nodeId)
return node;
}
-static DPS_Status StartNode(DPS_Node* node, int mcastPub, const char* listenText)
+static DPS_Status StartNode(DPS_Node* node, int mcastPub, const char* network,
+ const char* listenAddrText)
{
DPS_Status ret;
DPS_NodeAddress* listenAddr = NULL;
- if (listenText) {
+ if (network || listenAddrText) {
listenAddr = DPS_CreateAddress();
if (!listenAddr) {
ret = DPS_ERR_RESOURCES;
goto Exit;
}
- DPS_SetAddress(listenAddr, listenText);
+ DPS_SetAddress(listenAddr, network, listenAddrText);
}
ret = DPS_StartNode(node, mcastPub, listenAddr);
if (ret != DPS_OK) {
@@ -386,11 +399,18 @@ static DPS_Status StartNode(DPS_Node* node, int mcastPub, const char* listenText
return ret;
}
-static DPS_Status StartMulticastNode(DPS_Node* node)
+static DPS_Status StartMulticastNode(DPS_Node* node, const char* network)
{
+ DPS_Status ret;
/** [Starting a node] */
int mcastPub = DPS_MCAST_PUB_ENABLE_SEND | DPS_MCAST_PUB_ENABLE_RECV;
- DPS_Status ret = DPS_StartNode(node, mcastPub, NULL);
+ DPS_NodeAddress* listenAddr = DPS_CreateAddress();
+ if (!listenAddr) {
+ ret = DPS_ERR_RESOURCES;
+ goto Exit;
+ }
+ DPS_SetAddress(listenAddr, network, NULL);
+ ret = DPS_StartNode(node, mcastPub, listenAddr);
if (ret != DPS_OK) {
goto Exit;
}
@@ -398,10 +418,11 @@ static DPS_Status StartMulticastNode(DPS_Node* node)
DPS_PRINT("Node is listening on %s\n", DPS_GetListenAddressString(node));
Exit:
+ DPS_DestroyAddress(listenAddr);
return ret;
}
-static DPS_Status StartUnicastNode(DPS_Node* node, uint16_t port)
+static DPS_Status StartUnicastNode(DPS_Node* node, const char* network, uint16_t port)
{
DPS_Status ret;
char addrText[24];
@@ -413,7 +434,7 @@ static DPS_Status StartUnicastNode(DPS_Node* node, uint16_t port)
goto Exit;
}
snprintf(addrText, sizeof(addrText), "[::]:%d", port);
- DPS_SetAddress(listenAddr, addrText);
+ DPS_SetAddress(listenAddr, network, addrText);
ret = DPS_StartNode(node, mcastPub, listenAddr);
if (ret != DPS_OK) {
goto Exit;
diff --git a/dps_shared.def b/dps_shared.def
index 396148df..0bf998e4 100644
--- a/dps_shared.def
+++ b/dps_shared.def
@@ -43,6 +43,7 @@ DPS_LinkTo
DPS_Log
DPS_LogBytes
DPS_MemoryKeyStoreHandle
+DPS_NodeAddrNetwork
DPS_NodeAddrToString
DPS_PublicationAddSubId
DPS_PublicationGetNode
diff --git a/examples/common.c b/examples/common.c
index dfff3680..76ed84c3 100644
--- a/examples/common.c
+++ b/examples/common.c
@@ -51,84 +51,82 @@ int IntArg(char* opt, char*** argp, int* argcp, int* val, int min, int max)
return DPS_TRUE;
}
-int ListenArg(char*** argp, int* argcp, DPS_NodeAddress** addr)
+int AddressArg(char* opt, char*** argp, int* argcp, char** addrText)
{
char** arg = *argp;
int argc = *argcp;
int port = 0;
char str[256];
- strcpy(str, "[::]:0");
-
- if (IntArg("-l", &arg, &argc, &port, 1000, UINT16_MAX)) {
- snprintf(str, sizeof(str), "[::]:%d", port);
- } else if (strcmp(*arg, "-l") == 0) {
+ if (IntArg(opt, &arg, &argc, &port, 1000, UINT16_MAX)) {
+ snprintf(str, sizeof(str), "[::1]:%d", port);
+ *addrText = strdup(str);
+ } else if (strcmp(*arg, opt) == 0) {
++arg;
if (!--argc) {
return DPS_FALSE;
}
- strncpy(str, *arg++, sizeof(str));
+ *addrText = strdup(*arg++);
} else {
return DPS_FALSE;
}
- *addr = DPS_CreateAddress();
- if (!*addr) {
- return DPS_FALSE;
- }
- if (!DPS_SetAddress(*addr, str)) {
- DPS_DestroyAddress(*addr);
- *addr = NULL;
- return DPS_FALSE;
- }
*argp = arg;
*argcp = argc;
return DPS_TRUE;
}
-int LinkArg(char*** argp, int* argcp, char** addrText, int* numAddrText)
+void DestroyAddressArg(char* addrText, DPS_NodeAddress* addr)
{
- char** arg = *argp;
- int argc = *argcp;
- int port = 0;
- char str[256];
+ if (addrText) {
+ free(addrText);
+ }
+ DPS_DestroyAddress(addr);
+}
- if (IntArg("-p", &arg, &argc, &port, 1000, UINT16_MAX)) {
- if ((*numAddrText) == (MAX_LINKS - 1)) {
- DPS_PRINT("Too many -p options\n");
- return DPS_FALSE;
- }
- snprintf(str, sizeof(str), "[::1]:%d", port);
- addrText[(*numAddrText)++] = strdup(str);
- } else if (strcmp(*arg, "-p") == 0) {
- if ((*numAddrText) == (MAX_LINKS - 1)) {
+DPS_NodeAddress* CreateAddressFromArg(const char* network, const char* addrText)
+{
+ DPS_NodeAddress* addr = NULL;
+
+ addr = DPS_CreateAddress();
+ if (!addr) {
+ return NULL;
+ }
+ if (!DPS_SetAddress(addr, network, addrText)) {
+ DPS_DestroyAddress(addr);
+ return NULL;
+ }
+ return addr;
+}
+
+int LinkArg(char*** argp, int* argcp, char** addrText, int* count)
+{
+ char* text;
+
+ if (AddressArg("-p", argp, argcp, &text)) {
+ if ((*count) == (MAX_LINKS - 1)) {
DPS_PRINT("Too many -p options\n");
return DPS_FALSE;
}
- ++arg;
- if (!--argc) {
- return DPS_FALSE;
- }
- addrText[(*numAddrText)++] = strdup(*arg++);
+ addrText[*count] = text;
+ ++(*count);
+ return DPS_TRUE;
} else {
return DPS_FALSE;
}
- *argp = arg;
- *argcp = argc;
- return DPS_TRUE;
}
-DPS_Status Link(DPS_Node* node, char** addrText, DPS_NodeAddress** addr, int numAddr)
+DPS_Status Link(DPS_Node* node, const char* network, char** addrText, DPS_NodeAddress** addr, int count)
{
DPS_Status ret;
int i;
- for (i = 0; i < numAddr; ++i) {
+ for (i = 0; i < count; ++i) {
addr[i] = DPS_CreateAddress();
if (!addr[i]) {
ret = DPS_ERR_RESOURCES;
goto Exit;
}
- ret = DPS_LinkTo(node, addrText[i], addr[i]);
+ ret = DPS_LinkTo(node, network, addrText[i], addr[i]);
if (ret == DPS_OK) {
DPS_PRINT("Node is linked to %s\n", DPS_NodeAddrToString(addr[i]));
} else {
@@ -141,21 +139,18 @@ DPS_Status Link(DPS_Node* node, char** addrText, DPS_NodeAddress** addr, int num
return ret;
}
-void Unlink(DPS_Node* node, DPS_NodeAddress** addr, int numAddr)
+void Unlink(DPS_Node* node, DPS_NodeAddress** addr, int count)
{
int i;
- for (i = 0; i < numAddr; ++i) {
+ for (i = 0; i < count; ++i) {
DPS_UnlinkFrom(node, addr[i]);
}
}
-void DestroyLinkArg(char **addrText, DPS_NodeAddress** addr, int numAddr)
+void DestroyLinkArg(char** addrText, DPS_NodeAddress** addr, int count)
{
int i;
- for (i = 0; i < numAddr; ++i) {
- if (addrText[i]) {
- free(addrText[i]);
- }
- DPS_DestroyAddress(addr[i]);
+ for (i = 0; i < count; ++i) {
+ DestroyAddressArg(addrText ? addrText[i]: NULL, addr ? addr[i] : NULL);
}
}
diff --git a/examples/common.h b/examples/common.h
index f14eb8e4..69bfafd0 100644
--- a/examples/common.h
+++ b/examples/common.h
@@ -36,11 +36,13 @@ extern "C" {
#define MAX_LINKS 16
int IntArg(char* opt, char*** argp, int* argcp, int* val, int min, int max);
-int ListenArg(char*** argp, int* argcp, DPS_NodeAddress** addr);
-int LinkArg(char*** argp, int* argcp, char** addrText, int* numAddrText);
-DPS_Status Link(DPS_Node* node, char** addrText, DPS_NodeAddress** addr, int numAddr);
-void Unlink(DPS_Node* node, DPS_NodeAddress** addr, int numAddr);
-void DestroyLinkArg(char **addrText, DPS_NodeAddress** addr, int numAddr);
+int AddressArg(char* opt, char*** argp, int* argcp, char** addrText);
+DPS_NodeAddress* CreateAddressFromArg(const char* network, const char* addrText);
+void DestroyAddressArg(char* addrText, DPS_NodeAddress* addr);
+int LinkArg(char*** argp, int* argcp, char** addrText, int* count);
+DPS_Status Link(DPS_Node* node, const char* network, char** addrText, DPS_NodeAddress** addr, int count);
+void Unlink(DPS_Node* node, DPS_NodeAddress** addr, int count);
+void DestroyLinkArg(char** addrText, DPS_NodeAddress** addr, int count);
#ifdef __cplusplus
}
diff --git a/examples/pub_many.c b/examples/pub_many.c
index c18fe483..caa8eb39 100644
--- a/examples/pub_many.c
+++ b/examples/pub_many.c
@@ -76,7 +76,9 @@ int main(int argc, char** argv)
DPS_Publication* pub = NULL;
DPS_Node* node;
char** arg = argv + 1;
+ DPS_NodeAddress* listenAddr = NULL;
DPS_NodeAddress* linkAddr[MAX_LINKS] = { NULL };
+ char* network = NULL;
char* linkText[MAX_LINKS] = { NULL };
int numLinks = 0;
char* msg = NULL;
@@ -85,6 +87,14 @@ int main(int argc, char** argv)
DPS_Debug = 0;
while (--argc) {
+ if (strcmp(*arg, "-n") == 0) {
+ ++arg;
+ if (!--argc) {
+ goto Usage;
+ }
+ network = *arg++;
+ continue;
+ }
if (LinkArg(&arg, &argc, linkText, &numLinks)) {
continue;
}
@@ -129,13 +139,18 @@ int main(int argc, char** argv)
}
node = DPS_CreateNode("/.", NULL, NULL);
- ret = DPS_StartNode(node, mcast, NULL);
+ listenAddr = CreateAddressFromArg(network, NULL);
+ if (!listenAddr) {
+ DPS_ERRPRINT("CreateAddressFromArg failed\n");
+ return 1;
+ }
+ ret = DPS_StartNode(node, mcast, listenAddr);
if (ret != DPS_OK) {
DPS_ERRPRINT("DPS_CreateNode failed: %s\n", DPS_ErrTxt(ret));
return 1;
}
- ret = Link(node, linkText, linkAddr, numLinks);
+ ret = Link(node, network, linkText, linkAddr, numLinks);
if (ret != DPS_OK) {
DPS_ERRPRINT("DPS_ResolveAddress returned %s\n", DPS_ErrTxt(ret));
return 1;
@@ -162,11 +177,12 @@ int main(int argc, char** argv)
DPS_WaitForEvent(nodeDestroyed);
DPS_DestroyEvent(nodeDestroyed);
DestroyLinkArg(linkText, linkAddr, numLinks);
+ DestroyAddressArg(NULL, listenAddr);
return 0;
Usage:
- DPS_PRINT("Usage %s [-d] [-p ] [-m ] [-t ] [-c ] [topic1 topic2 ... topicN]\n", *argv);
+ DPS_PRINT("Usage %s [-d] [-n ] [-p ] [-m ] [-t ] [-c ] [topic1 topic2 ... topicN]\n", *argv);
return 1;
}
diff --git a/examples/publisher.c b/examples/publisher.c
index aa738d24..de690394 100644
--- a/examples/publisher.c
+++ b/examples/publisher.c
@@ -234,6 +234,7 @@ int main(int argc, char** argv)
DPS_Node* node;
char** arg = argv + 1;
DPS_NodeAddress* linkAddr[MAX_LINKS] = { NULL };
+ char* network = NULL;
char* linkText[MAX_LINKS] = { NULL };
int numLinks = 0;
int wait = 0;
@@ -242,10 +243,19 @@ int main(int argc, char** argv)
int subsRate = DPS_SUBSCRIPTION_UPDATE_RATE;
char* msg = NULL;
int mcast = DPS_MCAST_PUB_ENABLE_SEND;
+ char* listenText = NULL;
DPS_NodeAddress* listenAddr = NULL;
DPS_Debug = DPS_FALSE;
while (--argc) {
+ if (strcmp(*arg, "-n") == 0) {
+ ++arg;
+ if (!--argc) {
+ goto Usage;
+ }
+ network = *arg++;
+ continue;
+ }
if (LinkArg(&arg, &argc, linkText, &numLinks)) {
continue;
}
@@ -266,7 +276,7 @@ int main(int argc, char** argv)
msg = *arg++;
continue;
}
- if (ListenArg(&arg, &argc, &listenAddr)) {
+ if (AddressArg("-l", &arg, &argc, &listenText)) {
continue;
}
if (IntArg("-w", &arg, &argc, &wait, 0, 30)) {
@@ -330,14 +340,19 @@ int main(int argc, char** argv)
node = DPS_CreateNode("/.", DPS_MemoryKeyStoreHandle(memoryKeyStore), nodeKeyId);
DPS_SetNodeSubscriptionUpdateDelay(node, subsRate);
+ listenAddr = CreateAddressFromArg(network, listenText);
+ if (!listenAddr) {
+ DPS_ERRPRINT("CreateAddressFromArg returned NULL\n");
+ return 1;
+ }
ret = DPS_StartNode(node, mcast, listenAddr);
if (ret != DPS_OK) {
- DPS_ERRPRINT("DPS_CreateNode failed: %s\n", DPS_ErrTxt(ret));
+ DPS_ERRPRINT("DPS_StartNode failed: %s\n", DPS_ErrTxt(ret));
return 1;
}
DPS_PRINT("Publisher is listening on %s\n", DPS_GetListenAddressString(node));
- ret = Link(node, linkText, linkAddr, numLinks);
+ ret = Link(node, network, linkText, linkAddr, numLinks);
if (ret != DPS_OK) {
DPS_ERRPRINT("Link returned %s\n", DPS_ErrTxt(ret));
return 1;
@@ -393,7 +408,7 @@ int main(int argc, char** argv)
if (numLinks) {
Unlink(node, linkAddr, numLinks);
}
- if (listenAddr) {
+ if (listenText) {
DPS_PRINT("Waiting for remote to link\n");
DPS_TimedWaitForEvent(nodeDestroyed, 60 * 1000);
}
@@ -405,17 +420,18 @@ int main(int argc, char** argv)
DPS_WaitForEvent(nodeDestroyed);
DPS_DestroyEvent(nodeDestroyed);
DPS_DestroyMemoryKeyStore(memoryKeyStore);
- DPS_DestroyAddress(listenAddr);
+ DestroyAddressArg(listenText, listenAddr);
DestroyLinkArg(linkText, linkAddr, numLinks);
return 0;
Usage:
- DPS_PRINT("Usage %s [-d] [-x 0|1|2|3] [-a] [-w ] [-t ] [-p ] [-l ] [-m|-j ] [-r ] [topic1 topic2 ... topicN]\n", argv[0]);
+ DPS_PRINT("Usage %s [-d] [-x 0|1|2|3] [-a] [-w ] [-t ] [-n ] [-p ] [-l ] [-m|-j ] [-r ] [topic1 topic2 ... topicN]\n", argv[0]);
DPS_PRINT(" -d: Enable debug ouput if built for debug.\n");
DPS_PRINT(" -x: Disable (0) or enable symmetric encryption (1), asymmetric encryption (2), or authentication (3). Default is symmetric encryption enabled.\n");
DPS_PRINT(" -a: Request an acknowledgement\n");
DPS_PRINT(" -t: Set a time-to-live on a publication\n");
DPS_PRINT(" -w: Time to wait between linking to remote node and sending publication\n");
+ DPS_PRINT(" -n: Network of listen and link addresses.\n");
DPS_PRINT(" -l: Address to listen on for incoming connections\n");
DPS_PRINT(" -p: Address to link. Multiple -p options are permitted.\n");
DPS_PRINT(" -m: A string payload to accompany the publication.\n");
diff --git a/examples/reg_pubs.c b/examples/reg_pubs.c
index 36444837..c0f0f041 100644
--- a/examples/reg_pubs.c
+++ b/examples/reg_pubs.c
@@ -161,8 +161,9 @@ static void ReadStdin(DPS_Node* node)
}
}
-static DPS_Status FindAndLink(DPS_Node* node, char** linkText, int numLinks, const char* tenant,
- uint8_t count, uint16_t timeout, DPS_NodeAddress** linkAddr)
+static DPS_Status FindAndLink(DPS_Node* node, const char* network, char** linkText, int numLinks,
+ const char* tenant, uint8_t count, uint16_t timeout,
+ DPS_NodeAddress** linkAddr)
{
DPS_Status ret = DPS_OK;
DPS_RegistrationList* regs = NULL;
@@ -173,7 +174,7 @@ static DPS_Status FindAndLink(DPS_Node* node, char** linkText, int numLinks, con
* Find nodes to link to
*/
regs = DPS_CreateRegistrationList(count);
- ret = DPS_Registration_GetSyn(node, linkText[i], tenant, regs, timeout);
+ ret = DPS_Registration_GetSyn(node, network, linkText[i], tenant, regs, timeout);
if (ret != DPS_OK) {
DPS_ERRPRINT("Registration service lookup failed: %s\n", DPS_ErrTxt(ret));
return ret;
@@ -220,12 +221,22 @@ int main(int argc, char** argv)
int subsRate = DPS_SUBSCRIPTION_UPDATE_RATE;
int timeout = DPS_REGISTRATION_GET_TIMEOUT;
int count = 16;
+ DPS_NodeAddress* listenAddr = NULL;
DPS_NodeAddress* linkAddr[MAX_LINKS] = { NULL };
+ char* network = NULL;
char* linkText[MAX_LINKS] = { NULL };
int numLinks = 0;
DPS_Debug = DPS_FALSE;
while (--argc) {
+ if (strcmp(*arg, "-n") == 0) {
+ ++arg;
+ if (!--argc) {
+ goto Usage;
+ }
+ network = *arg++;
+ continue;
+ }
if (LinkArg(&arg, &argc, linkText, &numLinks)) {
continue;
}
@@ -290,7 +301,12 @@ int main(int argc, char** argv)
node = DPS_CreateNode("/.", DPS_MemoryKeyStoreHandle(memoryKeyStore), NULL);
DPS_SetNodeSubscriptionUpdateDelay(node, subsRate);
- ret = DPS_StartNode(node, mcastPub, NULL);
+ listenAddr = CreateAddressFromArg(network, NULL);
+ if (!listenAddr) {
+ DPS_ERRPRINT("CreateAddressFromArg failed\n");
+ return 1;
+ }
+ ret = DPS_StartNode(node, mcastPub, listenAddr);
if (ret != DPS_OK) {
DPS_ERRPRINT("Failed to start node: %s\n", DPS_ErrTxt(ret));
return 1;
@@ -299,7 +315,7 @@ int main(int argc, char** argv)
nodeDestroyed = DPS_CreateEvent();
- ret = FindAndLink(node, linkText, numLinks, tenant, count, timeout, linkAddr);
+ ret = FindAndLink(node, network, linkText, numLinks, tenant, count, timeout, linkAddr);
if (ret != DPS_OK) {
DPS_ERRPRINT("Failed to link to node: %s\n", DPS_ErrTxt(ret));
goto Exit;
@@ -342,14 +358,16 @@ int main(int argc, char** argv)
DPS_DestroyEvent(nodeDestroyed);
DPS_DestroyMemoryKeyStore(memoryKeyStore);
DestroyLinkArg(linkText, linkAddr, numLinks);
+ DestroyAddressArg(NULL, listenAddr);
return 0;
Usage:
- DPS_PRINT("Usage %s [-d] [-a] [-w ] [-t ] [-p ] [--tenant ] [-c ] [--timeout ] [-m ] [-r ] [topic1 topic2 ... topicN]\n", *argv);
+ DPS_PRINT("Usage %s [-d] [-a] [-w ] [-t ] [-n ] [-p ] [--tenant ] [-c ] [--timeout ] [-m ] [-r ] [topic1 topic2 ... topicN]\n", *argv);
DPS_PRINT(" -d: Enable debug ouput if built for debug.\n");
DPS_PRINT(" -a: Request an acknowledgement\n");
DPS_PRINT(" -t: Set a time-to-live on a publication\n");
DPS_PRINT(" -w: Time to wait between linking to remote node and sending publication\n");
+ DPS_PRINT(" -n: Network of listen and link addresses.\n");
DPS_PRINT(" -p: Address to link. Multiple -p options are permitted.\n");
DPS_PRINT(" -m: A payload message to accompany the publication.\n");
DPS_PRINT(" -r: Time to delay between subscription updates.\n");
diff --git a/examples/reg_subs.c b/examples/reg_subs.c
index 0c26b7f0..30ae3234 100644
--- a/examples/reg_subs.c
+++ b/examples/reg_subs.c
@@ -85,7 +85,7 @@ static void OnPubMatch(DPS_Subscription* sub, const DPS_Publication* pub, uint8_
}
}
-static DPS_Status RegisterAndJoin(DPS_Node* node, char** linkText, int numLink,
+static DPS_Status RegisterAndJoin(DPS_Node* node, const char* network, char** linkText, int numLink,
const char* tenant, uint8_t count, uint16_t timeout)
{
DPS_Status ret = DPS_OK;
@@ -98,7 +98,7 @@ static DPS_Status RegisterAndJoin(DPS_Node* node, char** linkText, int numLink,
* Register with the registration service
*/
regs = DPS_CreateRegistrationList(count);
- ret = DPS_Registration_PutSyn(node, linkText[i], tenant, DPS_REGISTRATION_PUT_TIMEOUT);
+ ret = DPS_Registration_PutSyn(node, network, linkText[i], tenant, DPS_REGISTRATION_PUT_TIMEOUT);
if (ret != DPS_OK) {
DPS_ERRPRINT("Failed to register with registration service: %s\n", DPS_ErrTxt(ret));
return ret;
@@ -106,7 +106,7 @@ static DPS_Status RegisterAndJoin(DPS_Node* node, char** linkText, int numLink,
/*
* Find nodes to join
*/
- ret = DPS_Registration_GetSyn(node, linkText[i], tenant, regs, timeout);
+ ret = DPS_Registration_GetSyn(node, network, linkText[i], tenant, regs, timeout);
if (ret != DPS_OK) {
DPS_ERRPRINT("Registration service lookup failed: %s\n", DPS_ErrTxt(ret));
return ret;
@@ -149,18 +149,28 @@ int main(int argc, char** argv)
size_t numTopics = 0;
DPS_MemoryKeyStore* memoryKeyStore = NULL;
DPS_Node* node;
+ char* listenText = NULL;
DPS_NodeAddress* listenAddr = NULL;
int subsRate = DPS_SUBSCRIPTION_UPDATE_RATE;
int timeout = DPS_REGISTRATION_GET_TIMEOUT;
int count = 16;
DPS_NodeAddress* linkAddr[MAX_LINKS] = { NULL };
+ char* network = NULL;
char* linkText[MAX_LINKS] = { NULL };
int numLinks = 0;
DPS_Debug = DPS_FALSE;
while (--argc) {
- if (ListenArg(&arg, &argc, &listenAddr)) {
+ if (strcmp(*arg, "-n") == 0) {
+ ++arg;
+ if (!--argc) {
+ goto Usage;
+ }
+ network = *arg++;
+ continue;
+ }
+ if (AddressArg("-l", &arg, &argc, &listenText)) {
continue;
}
if (LinkArg(&arg, &argc, linkText, &numLinks)) {
@@ -213,6 +223,11 @@ int main(int argc, char** argv)
node = DPS_CreateNode("/.", DPS_MemoryKeyStoreHandle(memoryKeyStore), NULL);
DPS_SetNodeSubscriptionUpdateDelay(node, subsRate);
+ listenAddr = CreateAddressFromArg(network, listenText);
+ if (!listenAddr) {
+ DPS_ERRPRINT("CreateAddressFromArg returned NULL\n");
+ return 1;
+ }
ret = DPS_StartNode(node, DPS_MCAST_PUB_DISABLED, listenAddr);
if (ret != DPS_OK) {
DPS_ERRPRINT("Failed to start node: %s\n", DPS_ErrTxt(ret));
@@ -222,7 +237,7 @@ int main(int argc, char** argv)
nodeDestroyed = DPS_CreateEvent();
- ret = RegisterAndJoin(node, linkText, numLinks, tenant, count, timeout);
+ ret = RegisterAndJoin(node, network, linkText, numLinks, tenant, count, timeout);
if (ret != DPS_OK) {
DPS_PRINT("Failed to link with any other \"%s\" nodes - continuing\n", tenant);
}
@@ -239,13 +254,14 @@ int main(int argc, char** argv)
DPS_WaitForEvent(nodeDestroyed);
DPS_DestroyEvent(nodeDestroyed);
DPS_DestroyMemoryKeyStore(memoryKeyStore);
- DPS_DestroyAddress(listenAddr);
+ DestroyAddressArg(listenText, listenAddr);
DestroyLinkArg(linkText, linkAddr, numLinks);
return 0;
Usage:
- DPS_PRINT("Usage %s [-d] [-l ] [-p ] [-t ] [-r ] [-c ] [--timeout ] topic1 topic2 ... topicN\n", *argv);
+ DPS_PRINT("Usage %s [-d] [-l ] [-n ] [-p ] [-t ] [-r ] [-c ] [--timeout ] topic1 topic2 ... topicN\n", *argv);
DPS_PRINT(" -d: Enable debug ouput if built for debug.\n");
+ DPS_PRINT(" -n: Network of listen and link addresses.\n");
DPS_PRINT(" -l: Address to listen on.\n");
DPS_PRINT(" -p: Address to link.\n");
DPS_PRINT(" -t: Tenant string to use.\n");
diff --git a/examples/registry.c b/examples/registry.c
index 7651bc8c..5f556460 100644
--- a/examples/registry.c
+++ b/examples/registry.c
@@ -56,13 +56,23 @@ int main(int argc, char** argv)
DPS_Event* nodeDestroyed;
const char* topics[1];
DPS_Subscription* subscription;
+ char* network = NULL;
+ char* listenText = NULL;
DPS_NodeAddress* listenAddr = NULL;
int subsRate = DPS_SUBSCRIPTION_UPDATE_RATE;
DPS_Debug = DPS_FALSE;
while (--argc) {
- if (ListenArg(&arg, &argc, &listenAddr)) {
+ if (strcmp(*arg, "-n") == 0) {
+ ++arg;
+ if (!--argc) {
+ goto Usage;
+ }
+ network = *arg++;
+ continue;
+ }
+ if (AddressArg("-l", &arg, &argc, &listenText)) {
continue;
}
if (strcmp(*arg, "-d") == 0) {
@@ -83,13 +93,17 @@ int main(int argc, char** argv)
node = DPS_CreateNode("/.", DPS_MemoryKeyStoreHandle(memoryKeyStore), NULL);
DPS_SetNodeSubscriptionUpdateDelay(node, subsRate);
+ listenAddr = CreateAddressFromArg(network, listenText);
+ if (!listenAddr) {
+ DPS_ERRPRINT("CreateAddressFromArg returned NULL\n");
+ return 1;
+ }
ret = DPS_StartNode(node, 0, listenAddr);
if (ret != DPS_OK) {
DPS_ERRPRINT("Failed to start node: %s\n", DPS_ErrTxt(ret));
return 1;
}
- DPS_PRINT("Registration services is listening on %s\n",
- DPS_GetListenAddressString(node));
+ DPS_PRINT("Registration services is listening on %s\n", DPS_GetListenAddressString(node));
nodeDestroyed = DPS_CreateEvent();
@@ -103,10 +117,10 @@ int main(int argc, char** argv)
DPS_WaitForEvent(nodeDestroyed);
DPS_DestroyEvent(nodeDestroyed);
DPS_DestroyMemoryKeyStore(memoryKeyStore);
- DPS_DestroyAddress(listenAddr);
+ DestroyAddressArg(listenText, listenAddr);
return 0;
Usage:
- DPS_PRINT("Usage %s [-l ] [-d]\n", *argv);
+ DPS_PRINT("Usage %s [-n ] [-l ] [-d]\n", *argv);
return 1;
}
diff --git a/examples/subscriber.c b/examples/subscriber.c
index 95639c81..b6a15aea 100644
--- a/examples/subscriber.c
+++ b/examples/subscriber.c
@@ -125,7 +125,8 @@ static void OnPubMatch(DPS_Subscription* sub, const DPS_Publication* pub, uint8_
typedef struct _Args {
int numTopics;
char* topicList[64];
- DPS_NodeAddress* listenAddr;
+ char* listenText;
+ char* network;
char* linkText[MAX_LINKS];
int numLinks;
int wait;
@@ -154,7 +155,6 @@ static int IsInteractive(Args* args)
static int ParseArgs(int argc, char** argv, Args* args)
{
- memset(args, 0, sizeof(Args));
args->encrypt = 1;
args->subsRate = DPS_SUBSCRIPTION_UPDATE_RATE;
args->mcastPub = DPS_MCAST_PUB_DISABLED;
@@ -164,7 +164,15 @@ static int ParseArgs(int argc, char** argv, Args* args)
* Topics must come last
*/
if (args->numTopics == 0) {
- if (ListenArg(&argv, &argc, &args->listenAddr)) {
+ if (strcmp(*argv, "-n") == 0) {
+ ++argv;
+ if (!--argc) {
+ return DPS_FALSE;
+ }
+ args->network = *argv++;
+ continue;
+ }
+ if (AddressArg("-l", &argv, &argc, &args->listenText)) {
continue;
}
if (LinkArg(&argv, &argc, args->linkText, &args->numLinks)) {
@@ -290,7 +298,8 @@ static int LinkTo(Subscriber* subscriber, Args* args)
ret = DPS_ERR_RESOURCES;
}
if (ret == DPS_OK) {
- ret = DPS_Link(subscriber->node, args->linkText[j], OnLinkComplete, subscriber->addrs[j]);
+ ret = DPS_Link(subscriber->node, args->network, args->linkText[j], OnLinkComplete,
+ subscriber->addrs[j]);
}
}
if (ret == DPS_OK) {
@@ -311,7 +320,7 @@ static void UnlinkFrom(Subscriber* subscriber)
#define MAX_TOPICS 64
#define MAX_ARGS (32 + MAX_TOPICS)
-static void ReadStdin(Subscriber* subscriber)
+static void ReadStdin(Args* mainArgs, Subscriber* subscriber)
{
char lineBuf[MAX_LINE_LEN + 1];
@@ -330,6 +339,11 @@ static void ReadStdin(Subscriber* subscriber)
argv[argc++] = tok;
}
}
+ /*
+ * Inherit network argument from command line
+ */
+ memset(&args, 0, sizeof(Args));
+ args.network = mainArgs->network;
if (!ParseArgs(argc, argv, &args)) {
continue;
}
@@ -346,10 +360,12 @@ int main(int argc, char** argv)
const DPS_KeyId* nodeKeyId = NULL;
DPS_Event* nodeDestroyed = NULL;
Subscriber subscriber;
+ DPS_NodeAddress* listenAddr = NULL;
DPS_Debug = DPS_FALSE;
memset(&subscriber, 0, sizeof(subscriber));
+ memset(&args, 0, sizeof(Args));
if (!ParseArgs(argc - 1, argv + 1, &args)) {
goto Usage;
}
@@ -380,13 +396,18 @@ int main(int argc, char** argv)
nodeDestroyed = DPS_CreateEvent();
- ret = DPS_StartNode(subscriber.node, args.mcastPub, args.listenAddr);
+ listenAddr = CreateAddressFromArg(args.network, args.listenText);
+ if (!listenAddr) {
+ DPS_ERRPRINT("CreateAddressFromArg returned NULL\n");
+ ret = DPS_ERR_RESOURCES;
+ goto Exit;
+ }
+ ret = DPS_StartNode(subscriber.node, args.mcastPub, listenAddr);
if (ret != DPS_OK) {
DPS_ERRPRINT("Failed to start node: %s\n", DPS_ErrTxt(ret));
goto Exit;
}
- DPS_PRINT("Subscriber is listening on %s\n",
- DPS_GetListenAddressString(subscriber.node));
+ DPS_PRINT("Subscriber is listening on %s\n", DPS_GetListenAddressString(subscriber.node));
if (args.wait) {
/*
@@ -405,7 +426,7 @@ int main(int argc, char** argv)
}
if (IsInteractive(&args)) {
DPS_PRINT("Running in interactive mode\n");
- ReadStdin(&subscriber);
+ ReadStdin(&args, &subscriber);
UnlinkFrom(&subscriber);
DPS_DestroyNode(subscriber.node, OnNodeDestroyed, nodeDestroyed);
}
@@ -417,17 +438,18 @@ int main(int argc, char** argv)
DPS_WaitForEvent(nodeDestroyed);
DPS_DestroyEvent(nodeDestroyed);
DPS_DestroyMemoryKeyStore(memoryKeyStore);
- DPS_DestroyAddress(args.listenAddr);
+ DestroyAddressArg(args.listenText, listenAddr);
DestroyLinkArg(args.linkText, NULL, args.numLinks);
DestroyLinkArg(NULL, subscriber.addrs, subscriber.numAddrs);
return (ret == DPS_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
Usage:
- DPS_PRINT("Usage %s [-d] [-q] [-m] [-w ] [-x 0|1|2|3] [-p ] [-l ] [[-s] topic1 ... topicN]\n", argv[0]);
+ DPS_PRINT("Usage %s [-d] [-q] [-m] [-w ] [-x 0|1|2|3] [-n ] [-p ] [-l ] [[-s] topic1 ... topicN]\n", argv[0]);
DPS_PRINT(" -d: Enable debug ouput if built for debug.\n");
DPS_PRINT(" -q: Quiet - suppresses output about received publications.\n");
DPS_PRINT(" -x: Disable (0) or enable symmetric encryption (1), asymmetric encryption (2), or authentication (3). Default is symmetric encryption enabled.\n");
DPS_PRINT(" -w: Time to wait before establishing links\n");
+ DPS_PRINT(" -n: Network of listen and link addresses.\n");
DPS_PRINT(" -p: An address to link. Multiple -p options are permitted.\n");
DPS_PRINT(" -m: Enable multicast receive. Enabled by default is there are no -p options.\n");
DPS_PRINT(" -l: Address listen on.\n");
diff --git a/go/dps.go b/go/dps.go
index 9dd2352d..f4435474 100644
--- a/go/dps.go
+++ b/go/dps.go
@@ -116,8 +116,8 @@ import (
goOnLinkComplete(node, addr, status, (uintptr_t)data);
}
- static DPS_Status link(DPS_Node* node, const char* addrText, uintptr_t data) {
- return DPS_Link(node, addrText, onLinkComplete, (void*)data);
+ static DPS_Status link(DPS_Node* node, const char* network, const char* addrText, uintptr_t data) {
+ return DPS_Link(node, network, addrText, onLinkComplete, (void*)data);
}
extern void goOnUnlinkComplete(DPS_Node* node, DPS_NodeAddress* addr, uintptr_t data);
@@ -135,8 +135,8 @@ import (
goOnResolveAddressComplete(node, (DPS_NodeAddress*)addr, (uintptr_t)data);
}
- static DPS_Status resolveAddress(DPS_Node* node, char* host, char* service, uintptr_t data) {
- return DPS_ResolveAddress(node, host, service, onResolveAddressComplete, (void*)data);
+ static DPS_Status resolveAddress(DPS_Node* node, const char* network, char* host, char* service, uintptr_t data) {
+ return DPS_ResolveAddress(node, network, host, service, onResolveAddressComplete, (void*)data);
}
static char** makeTopics(size_t n) {
@@ -248,14 +248,25 @@ func NodeAddrToString(addr *NodeAddress) string {
caddr := (*C.DPS_NodeAddress)(addr)
return C.GoString(C.DPS_NodeAddrToString(caddr))
}
+func NodeAddrNetwork(addr *NodeAddress) string {
+ caddr := (*C.DPS_NodeAddress)(addr)
+ return C.GoString(C.DPS_NodeAddrNetwork(caddr))
+}
func CreateAddress() *NodeAddress {
return (*NodeAddress)(C.DPS_CreateAddress())
}
-func SetAddress(addr *NodeAddress, hostport string) *NodeAddress {
+func SetAddress(addr *NodeAddress, network, addrText *string) *NodeAddress {
caddr := (*C.DPS_NodeAddress)(addr)
- chostport := C.CString(hostport)
- defer C.free(unsafe.Pointer(chostport))
- return (*NodeAddress)(C.DPS_SetAddress(caddr, chostport))
+ var cnetwork, caddrText *C.char
+ if network != nil {
+ cnetwork = C.CString(*network)
+ defer C.free(unsafe.Pointer(cnetwork))
+ }
+ if addrText != nil {
+ caddrText = C.CString(*addrText)
+ defer C.free(unsafe.Pointer(caddrText))
+ }
+ return (*NodeAddress)(C.DPS_SetAddress(caddr, cnetwork, caddrText))
}
func CopyAddress(dest *NodeAddress, src *NodeAddress) {
cdest := (*C.DPS_NodeAddress)(dest)
@@ -663,12 +674,14 @@ func GetListenAddressString(node *Node) string {
type OnLinkComplete func(node *Node, addr *NodeAddress, status int)
-func Link(node *Node, addrText string, cb OnLinkComplete) int {
+func Link(node *Node, network, addrText string, cb OnLinkComplete) int {
cnode := (*C.DPS_Node)(node)
+ cnetwork := C.CString(network)
+ defer C.free(unsafe.Pointer(cnetwork))
caddrText := C.CString(addrText)
defer C.free(unsafe.Pointer(caddrText))
handle := reg.register(cb)
- return int(C.link(cnode, caddrText, C.uintptr_t(handle)))
+ return int(C.link(cnode, cnetwork, caddrText, C.uintptr_t(handle)))
}
//export goOnLinkComplete
@@ -704,14 +717,16 @@ func goOnUnlinkComplete(cnode *C.DPS_Node, caddr *C.DPS_NodeAddress, handle uint
type OnResolveAddressComplete func(node *Node, addr *NodeAddress)
-func ResolveAddress(node *Node, host string, service string, cb OnResolveAddressComplete) int {
+func ResolveAddress(node *Node, network, host, service string, cb OnResolveAddressComplete) int {
cnode := (*C.DPS_Node)(node)
+ cnetwork := C.CString(network)
+ defer C.free(unsafe.Pointer(cnetwork))
chost := C.CString(host)
defer C.free(unsafe.Pointer(chost))
cservice := C.CString(service)
defer C.free(unsafe.Pointer(cservice))
handle := reg.register(cb)
- return int(C.resolveAddress(cnode, chost, cservice, C.uintptr_t(handle)))
+ return int(C.resolveAddress(cnode, cnetwork, chost, cservice, C.uintptr_t(handle)))
}
//export goOnResolveAddressComplete
@@ -1041,15 +1056,17 @@ func CBOR2JSON(cbor []byte, pretty bool) (json string, err int) {
return
}
-func LinkTo(node *Node, addrText string, addr *NodeAddress) int {
+func LinkTo(node *Node, network, addrText string, addr *NodeAddress) int {
cnode := (*C.DPS_Node)(node)
+ cnetwork := C.CString(network)
+ defer C.free(unsafe.Pointer(cnetwork))
var caddrText *C.char
if len(addrText) > 0 {
caddrText = C.CString(addrText)
}
defer C.free(unsafe.Pointer(caddrText))
caddr := (*C.DPS_NodeAddress)(addr)
- return int(C.DPS_LinkTo(cnode, caddrText, caddr))
+ return int(C.DPS_LinkTo(cnode, cnetwork, caddrText, caddr))
}
func UnlinkFrom(node *Node, addr *NodeAddress) int {
diff --git a/go/examples/simple_pub/simple_pub.go b/go/examples/simple_pub/simple_pub.go
index 791c01da..0f7f96e2 100644
--- a/go/examples/simple_pub/simple_pub.go
+++ b/go/examples/simple_pub/simple_pub.go
@@ -3,37 +3,37 @@ package main
import (
"dps"
"dps/examples/keys"
+ "flag"
"fmt"
- "os"
- "strconv"
"time"
)
+var (
+ debug = flag.Bool("d", false, "enable debug output if built for debug")
+ encryption = flag.Int("x", 1, "disable (0) or enable symmetric encryption (1), asymmetric encryption (2), or authentication (3)")
+ network = flag.String("n", "udp", "Network of listen and link addresses")
+)
+
func main() {
- dps.SetDebug(0)
- encryption := 1
- for i := 0; i < len(os.Args); i++ {
- if os.Args[i] == "-x" {
- i++
- encryption, _ = strconv.Atoi(os.Args[i])
- } else if os.Args[i] == "-d" {
- dps.SetDebug(1)
- }
+ flag.Parse()
+ if *debug {
+ dps.SetDebug(1)
+ } else {
+ dps.SetDebug(0)
}
-
var nodeId, pubKeyId []byte
keyStore := dps.CreateMemoryKeyStore()
dps.SetNetworkKey(keyStore, keys.NetworkKeyId, keys.NetworkKey)
- if encryption == 0 {
+ if *encryption == 0 {
nodeId = nil
pubKeyId = nil
- } else if encryption == 1 {
+ } else if *encryption == 1 {
for i := 0; i < len(keys.KeyId); i++ {
dps.SetContentKey(keyStore, keys.KeyId[i], keys.KeyData[i])
}
nodeId = nil
pubKeyId = keys.KeyId[0]
- } else if encryption == 2 {
+ } else if *encryption == 2 {
dps.SetTrustedCA(keyStore, keys.CA)
dps.SetCertificate(keyStore, keys.PublisherCert, &keys.PublisherPrivateKey, &keys.PublisherPassword)
dps.SetCertificate(keyStore, keys.SubscriberCert, nil, nil)
@@ -42,7 +42,10 @@ func main() {
}
node := dps.CreateNode("/", keyStore, nodeId)
- dps.StartNode(node, dps.MCAST_PUB_ENABLE_SEND, nil)
+ addr := dps.CreateAddress()
+ dps.SetAddress(addr, network, nil)
+ dps.StartNode(node, dps.MCAST_PUB_ENABLE_SEND, addr)
+ dps.DestroyAddress(addr)
fmt.Printf("Publisher is listening on %v\n", dps.GetListenAddressString(node))
pub := dps.CreatePublication(node)
diff --git a/go/examples/simple_pub_ks/simple_pub_ks.go b/go/examples/simple_pub_ks/simple_pub_ks.go
index 59605617..2fa6c51c 100644
--- a/go/examples/simple_pub_ks/simple_pub_ks.go
+++ b/go/examples/simple_pub_ks/simple_pub_ks.go
@@ -6,12 +6,17 @@ import (
"crypto/rand"
"dps"
"dps/examples/keys"
+ "flag"
"fmt"
- "os"
- "strconv"
"time"
)
+var (
+ debug = flag.Bool("d", false, "enable debug output if built for debug")
+ encryption = flag.Int("x", 1, "disable (0) or enable symmetric encryption (1), asymmetric encryption (2), or authentication (3)")
+ network = flag.String("n", "udp", "Network of listen and link addresses")
+)
+
func pad(in []byte, n int) (out []byte) {
out = make([]byte, n)
low := len(out) - len(in)
@@ -71,35 +76,33 @@ func main() {
return dps.SetCA(request, keys.CA)
}
- dps.SetDebug(0)
- encryption := 1
- for i := 0; i < len(os.Args); i++ {
- if os.Args[i] == "-x" {
- i++
- encryption, _ = strconv.Atoi(os.Args[i])
- } else if os.Args[i] == "-d" {
- dps.SetDebug(1)
- }
+ flag.Parse()
+ if *debug {
+ dps.SetDebug(1)
+ } else {
+ dps.SetDebug(0)
}
-
var keyStore dps.KeyStore
var nodeId, pubKeyId []byte
- if encryption == 0 {
+ if *encryption == 0 {
keyStore = dps.CreateKeyStore(onKeyAndId, onKey, onEphemeralKey, nil)
nodeId = nil
pubKeyId = nil
- } else if encryption == 1 {
+ } else if *encryption == 1 {
keyStore = dps.CreateKeyStore(onKeyAndId, onKey, onEphemeralKey, nil)
nodeId = nil
pubKeyId = keys.KeyId[0]
- } else if encryption == 2 {
+ } else if *encryption == 2 {
keyStore = dps.CreateKeyStore(onKeyAndId, onKey, onEphemeralKey, onCA)
nodeId = []byte(keys.PublisherId)
pubKeyId = []byte(keys.SubscriberId)
}
node := dps.CreateNode("/", keyStore, nodeId)
- dps.StartNode(node, dps.MCAST_PUB_ENABLE_SEND, nil)
+ addr := dps.CreateAddress()
+ dps.SetAddress(addr, network, nil)
+ dps.StartNode(node, dps.MCAST_PUB_ENABLE_SEND, addr)
+ dps.DestroyAddress(addr)
fmt.Printf("Publisher is listening on %v\n", dps.GetListenAddressString(node))
pub := dps.CreatePublication(node)
diff --git a/go/examples/simple_sub/simple_sub.go b/go/examples/simple_sub/simple_sub.go
index f8bf9c77..c8de79df 100644
--- a/go/examples/simple_sub/simple_sub.go
+++ b/go/examples/simple_sub/simple_sub.go
@@ -3,36 +3,36 @@ package main
import (
"dps"
"dps/examples/keys"
+ "flag"
"fmt"
- "os"
- "strconv"
"strings"
"time"
)
+var (
+ debug = flag.Bool("d", false, "enable debug output if built for debug")
+ encryption = flag.Int("x", 1, "disable (0) or enable symmetric encryption (1), asymmetric encryption (2), or authentication (3)")
+ network = flag.String("n", "udp", "Network of listen and link addresses")
+)
+
func main() {
- dps.SetDebug(0)
- encryption := 1
- for i := 0; i < len(os.Args); i++ {
- if os.Args[i] == "-x" {
- i++
- encryption, _ = strconv.Atoi(os.Args[i])
- } else if os.Args[i] == "-d" {
- dps.SetDebug(1)
- }
+ flag.Parse()
+ if *debug {
+ dps.SetDebug(1)
+ } else {
+ dps.SetDebug(0)
}
-
var nodeId []byte
keyStore := dps.CreateMemoryKeyStore()
dps.SetNetworkKey(keyStore, keys.NetworkKeyId, keys.NetworkKey)
- if encryption == 0 {
+ if *encryption == 0 {
nodeId = nil
- } else if encryption == 1 {
+ } else if *encryption == 1 {
for i := 0; i < len(keys.KeyId); i++ {
dps.SetContentKey(keyStore, keys.KeyId[i], keys.KeyData[i])
}
nodeId = nil
- } else if encryption == 2 {
+ } else if *encryption == 2 {
dps.SetTrustedCA(keyStore, keys.CA)
dps.SetCertificate(keyStore, keys.SubscriberCert, &keys.SubscriberPrivateKey, &keys.SubscriberPassword)
dps.SetCertificate(keyStore, keys.PublisherCert, nil, nil)
@@ -40,7 +40,10 @@ func main() {
}
node := dps.CreateNode("/", keyStore, nodeId)
- dps.StartNode(node, dps.MCAST_PUB_ENABLE_RECV, nil)
+ addr := dps.CreateAddress()
+ dps.SetAddress(addr, network, nil)
+ dps.StartNode(node, dps.MCAST_PUB_ENABLE_RECV, addr)
+ dps.DestroyAddress(addr)
fmt.Printf("Subscriber is listening on %v\n", dps.GetListenAddressString(node))
sub := dps.CreateSubscription(node, []string{"a/b/c"})
diff --git a/go/examples/simple_sub_ks/simple_sub_ks.go b/go/examples/simple_sub_ks/simple_sub_ks.go
index d661892a..6ab92e0d 100644
--- a/go/examples/simple_sub_ks/simple_sub_ks.go
+++ b/go/examples/simple_sub_ks/simple_sub_ks.go
@@ -6,13 +6,18 @@ import (
"crypto/rand"
"dps"
"dps/examples/keys"
+ "flag"
"fmt"
- "os"
- "strconv"
"strings"
"time"
)
+var (
+ debug = flag.Bool("d", false, "enable debug output if built for debug")
+ encryption = flag.Int("x", 1, "disable (0) or enable symmetric encryption (1), asymmetric encryption (2), or authentication (3)")
+ network = flag.String("n", "udp", "Network of listen and link addresses")
+)
+
func pad(in []byte, n int) (out []byte) {
out = make([]byte, n)
low := len(out) - len(in)
@@ -72,32 +77,30 @@ func main() {
return dps.SetCA(request, keys.CA)
}
- dps.SetDebug(0)
- encryption := 1
- for i := 0; i < len(os.Args); i++ {
- if os.Args[i] == "-x" {
- i++
- encryption, _ = strconv.Atoi(os.Args[i])
- } else if os.Args[i] == "-d" {
- dps.SetDebug(1)
- }
+ flag.Parse()
+ if *debug {
+ dps.SetDebug(1)
+ } else {
+ dps.SetDebug(0)
}
-
var keyStore dps.KeyStore
var nodeId []byte
- if encryption == 0 {
+ if *encryption == 0 {
keyStore = dps.CreateKeyStore(onKeyAndId, onKey, onEphemeralKey, nil)
nodeId = nil
- } else if encryption == 1 {
+ } else if *encryption == 1 {
keyStore = dps.CreateKeyStore(onKeyAndId, onKey, onEphemeralKey, nil)
nodeId = nil
- } else if encryption == 2 {
+ } else if *encryption == 2 {
keyStore = dps.CreateKeyStore(onKeyAndId, onKey, onEphemeralKey, onCA)
nodeId = []byte(keys.SubscriberId)
}
node := dps.CreateNode("/", keyStore, nodeId)
- dps.StartNode(node, dps.MCAST_PUB_ENABLE_RECV, nil)
+ addr := dps.CreateAddress()
+ dps.SetAddress(addr, network, nil)
+ dps.StartNode(node, dps.MCAST_PUB_ENABLE_RECV, addr)
+ dps.DestroyAddress(addr)
fmt.Printf("Subscriber is listening on %v\n", dps.GetListenAddressString(node))
sub := dps.CreateSubscription(node, []string{"a/b/c"})
diff --git a/go/test/perf_publisher/perf_publisher.go b/go/test/perf_publisher/perf_publisher.go
index 20998c2e..74bb0201 100644
--- a/go/test/perf_publisher/perf_publisher.go
+++ b/go/test/perf_publisher/perf_publisher.go
@@ -14,6 +14,7 @@ import (
var (
debug = flag.Bool("d", false, "enable debug output if built for debug")
+ network = flag.String("n", "udp", "network to link")
linkText = flag.String("p", "", "address to link")
payloadSize = flag.Int("s", 0, "size of PUB payload")
numPubs = flag.Int("n", 1000, "number of publications to send")
@@ -65,7 +66,7 @@ func main() {
dps.StartNode(node, mcast, nil)
if *linkText != "" {
- err := dps.LinkTo(node, *linkText, nil)
+ err := dps.LinkTo(node, *network, *linkText, nil)
if err != dps.OK {
fmt.Printf("dps.LinkTo %v returned %s\n", *linkText, dps.ErrTxt(err))
return
diff --git a/go/test/perf_subscriber/perf_subscriber.go b/go/test/perf_subscriber/perf_subscriber.go
index 7e434db9..55c902b1 100644
--- a/go/test/perf_subscriber/perf_subscriber.go
+++ b/go/test/perf_subscriber/perf_subscriber.go
@@ -12,6 +12,7 @@ import (
var (
debug = flag.Bool("d", false, "enable debug output if built for debug")
+ network = flag.String("n", "udp", "network to link")
listenText = flag.Int("p", 0, "address to link")
payloadSize = flag.Int("s", 0, "size of PUB payload")
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
@@ -52,7 +53,8 @@ func main() {
node := dps.CreateNode("/", nil, nil)
listenAddr := dps.CreateAddress()
- dps.SetAddress(listenAddr, fmt.Sprintf(":%v", *listenText))
+ addrText := fmt.Sprintf(":%v", *listenText)
+ dps.SetAddress(listenAddr, network, &addrText)
dps.StartNode(node, dps.MCAST_PUB_ENABLE_RECV, listenAddr)
fmt.Printf("Subscriber is listening on %v\n", dps.GetListenAddressString(node))
diff --git a/inc/dps/dps.h b/inc/dps/dps.h
index c9016480..e9b4ac85 100644
--- a/inc/dps/dps.h
+++ b/inc/dps/dps.h
@@ -66,6 +66,15 @@ typedef struct _DPS_NodeAddress DPS_NodeAddress;
*/
const char* DPS_NodeAddrToString(const DPS_NodeAddress* addr);
+/**
+ * Get text representation of an address's network.
+ *
+ * @param addr to get the network for
+ *
+ * @return A text string for the network
+ */
+const char* DPS_NodeAddrNetwork(const DPS_NodeAddress* addr);
+
/**
* Creates a node address.
*
@@ -77,11 +86,12 @@ DPS_NodeAddress* DPS_CreateAddress(void);
* Set a node address
*
* @param addr The address to set
+ * @param network The name of the network the address is on
* @param addrText The text string for the address
*
* @return The addr passed in, or NULL if an error occurred
*/
-DPS_NodeAddress* DPS_SetAddress(DPS_NodeAddress* addr, const char* addrText);
+DPS_NodeAddress* DPS_SetAddress(DPS_NodeAddress* addr, const char* network, const char* addrText);
/**
* Copy a node address
@@ -575,13 +585,14 @@ typedef void (*DPS_OnLinkComplete)(DPS_Node* node, DPS_NodeAddress* addr, DPS_St
* Link the local node to a remote node
*
* @param node The local node to use
+ * @param network The name of the network the address is on
* @param addrText The text string of the address to link to
* @param cb The callback function to call on completion, can be NULL which case the function is synchronous
- * @param data Application data to be passed to the callback
+ * @param data Application data to be passed to the callback
*
* @return DPS_OK or an error status. If an error status is returned the callback function will not be called.
*/
-DPS_Status DPS_Link(DPS_Node* node, const char* addrText, DPS_OnLinkComplete cb, void* data);
+DPS_Status DPS_Link(DPS_Node* node, const char* network, const char* addrText, DPS_OnLinkComplete cb, void* data);
/**
* Function prototype for function called when a DPS_Unlink() completes.
@@ -617,6 +628,7 @@ typedef void (*DPS_OnResolveAddressComplete)(DPS_Node* node, const DPS_NodeAddre
* Resolve a host name or IP address and service name or port number.
*
* @param node The local node to use
+ * @param network The name of the network the address to resolve is on
* @param host The host name or IP address to resolve
* @param service The port or service name to resolve
* @param cb The callback function to call on completion
@@ -624,7 +636,7 @@ typedef void (*DPS_OnResolveAddressComplete)(DPS_Node* node, const DPS_NodeAddre
*
* @return DPS_OK or an error status. If an error status is returned the callback function will not be called.
*/
-DPS_Status DPS_ResolveAddress(DPS_Node* node, const char* host, const char* service, DPS_OnResolveAddressComplete cb, void* data);
+DPS_Status DPS_ResolveAddress(DPS_Node* node, const char* network, const char* host, const char* service, DPS_OnResolveAddressComplete cb, void* data);
/** @} */ /* end of node group */
diff --git a/inc/dps/private/network.h b/inc/dps/private/network.h
index 672627ca..d5814444 100644
--- a/inc/dps/private/network.h
+++ b/inc/dps/private/network.h
@@ -38,16 +38,58 @@ extern "C" {
#define DPS_MAX_HOST_LEN 256 /**< Per RFC 1034/1035 */
#define DPS_MAX_SERVICE_LEN 16 /**< Per RFC 6335 section 5.1 */
+#define DPS_MAX_NETWORK_LEN 4 /**< Network/transport name */
+
+typedef struct _DPS_NetContext DPS_NetContext;
+typedef struct _DPS_NetEndpoint DPS_NetEndpoint;
+typedef struct _DPS_NetConnection DPS_NetConnection;
/**
- * Opaque data structure for network-specific state
+ * Prototype for function called when a send completes.
+ *
+ * @param node Opaque pointer to the DPS node
+ * @param appCtx Application context pointer that was passed into
+ * DPS_NetSend()
+ * @param endpoint The endpoint for which the send was complete
+ * @param bufs Array holding pointers to the buffers passed in the
+ * send API call. The data in these buffers can now be
+ * freed.
+ * @param numBufs The length of the bufs array
+ * @param status Indicates if the send was successful or not
*/
-typedef struct _DPS_NetContext DPS_NetContext;
+typedef void (*DPS_NetSendComplete)(DPS_Node* node, void* appCtx, DPS_NetEndpoint* endpoint,
+ uv_buf_t* bufs, size_t numBufs, DPS_Status status);
+
+/** @copydoc DPS_NetGetListenAddress() */
+typedef DPS_NodeAddress* (*DPS_NetGetListenAddressHandler)(DPS_NodeAddress* addr, DPS_NetContext* netCtx);
+/** @copydoc DPS_NetStop() */
+typedef void (*DPS_NetStopHandler)(DPS_NetContext* netCtx);
+/** @copydoc DPS_NetSend() */
+typedef DPS_Status (*DPS_NetSendHandler)(DPS_Node* node, void* appCtx, DPS_NetEndpoint* endpoint,
+ uv_buf_t* bufs, size_t numBufs,
+ DPS_NetSendComplete sendCompleteCB);
/**
- * Opaque type for managing connection state for connection-oriented transports
+ * Data structure for network-specific state
*/
-typedef struct _DPS_NetConnection DPS_NetConnection;
+typedef struct _DPS_NetContext {
+ DPS_NetGetListenAddressHandler getListenAddress; /**< DPS_GetListenAddress */
+ DPS_NetStopHandler stop; /**< DPS_NetStop */
+ DPS_NetSendHandler send; /**< DPS_NetSend */
+} DPS_NetContext;
+
+/** @copydoc DPS_NetConnectionIncRef() */
+typedef void (*DPS_NetConnectionIncRefHandler)(DPS_NetConnection* cn);
+/** @copydoc DPS_NetConnectionDecRef() */
+typedef void (*DPS_NetConnectionDecRefHandler)(DPS_NetConnection* cn);
+
+/**
+ * Type for managing connection state for connection-oriented transports
+ */
+typedef struct _DPS_NetConnection {
+ DPS_NetConnectionIncRefHandler incRef; /**< DPS_NetConnectIncRef */
+ DPS_NetConnectionDecRefHandler decRef; /**< DPS_NetConnectionDecRef */
+} DPS_NetConnection;
/**
* Type for a remote network endpoint. This provides an abstraction connectionless and
@@ -287,22 +329,6 @@ DPS_NodeAddress* DPS_NetGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext*
*/
void DPS_NetStop(DPS_NetContext* netCtx);
-/**
- * Prototype for function called when a send completes.
- *
- * @param node Opaque pointer to the DPS node
- * @param appCtx Application context pointer that was passed into
- * DPS_NetSend()
- * @param endpoint The endpoint for which the send was complete
- * @param bufs Array holding pointers to the buffers passed in the
- * send API call. The data in these buffers can now be
- * freed.
- * @param numBufs The length of the bufs array
- * @param status Indicates if the send was successful or not
- */
-typedef void (*DPS_NetSendComplete)(DPS_Node* node, void* appCtx, DPS_NetEndpoint* endpoint,
- uv_buf_t* bufs, size_t numBufs, DPS_Status status);
-
/**
* Send data to a specific endpoint.
*
@@ -403,6 +429,42 @@ void DPS_MapAddrToV6(struct sockaddr* addr);
DPS_Status DPS_SplitAddress(const char* addrText, char* host, size_t hostLen,
char* service, size_t serviceLen);
+/**
+ * Return address type of transport.
+ *
+ * @param network The network name
+ *
+ * @return the address type
+ */
+DPS_NodeAddressType DPS_NetAddressType(const char* network);
+
+/** @copydoc DPS_NetStart() */
+typedef DPS_NetContext* (*DPS_NetStartHandler)(DPS_Node* node, const DPS_NodeAddress* addr,
+ DPS_OnReceive cb);
+/**
+ * A transport definition.
+ */
+typedef struct _DPS_NetTransport {
+ DPS_NodeAddressType type; /**< Transport type */
+ DPS_NetStartHandler start; /**< DPS_NetStart */
+} DPS_NetTransport;
+
+#ifdef DPS_USE_UDP
+extern DPS_NetTransport DPS_NetUdpTransport; /**< The UDP transport */
+#endif
+#ifdef DPS_USE_TCP
+extern DPS_NetTransport DPS_NetTcpTransport; /**< The TCP transport */
+#endif
+#ifdef DPS_USE_DTLS
+extern DPS_NetTransport DPS_NetDtlsTransport; /**< The DTLS transport */
+#endif
+#ifdef DPS_USE_PIPE
+extern DPS_NetTransport DPS_NetPipeTransport; /**< The pipe transport */
+#endif
+#ifdef DPS_USE_FUZZ
+extern DPS_NetTransport DPS_NetFuzzerTransport; /**< The fuzz transport */
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/inc/dps/registration.h b/inc/dps/registration.h
index 73e70b9c..7a4edd35 100644
--- a/inc/dps/registration.h
+++ b/inc/dps/registration.h
@@ -66,6 +66,7 @@ extern const char* DPS_RegistryTopicString;
*/
typedef struct _DPS_Registration {
uint8_t flags; /**< Registration entry flags */
+ char* network; /**< The registered network */
char* addrText; /**< The registered address text */
} DPS_Registration;
@@ -109,6 +110,7 @@ typedef void (*DPS_OnRegPutComplete)(DPS_Status status, void* data);
* Register a local node with a registration service.
*
* @param node The local node to register
+ * @param network The name of the network the address is on
* @param addrText The text string of the registration service address
* @param tenantString Topic string identifying the tenant
* @param timeout Timeout in milliseconds
@@ -118,22 +120,24 @@ typedef void (*DPS_OnRegPutComplete)(DPS_Status status, void* data);
* @return DPS_OK if the registration put request was successfully initiated, otherwise returns an
* error status and the callback function will not be called.
*/
-DPS_Status DPS_Registration_Put(DPS_Node* node, const char* addrText, const char* tenantString,
- uint16_t timeout, DPS_OnRegPutComplete cb, void* data);
+DPS_Status DPS_Registration_Put(DPS_Node* node, const char* network, const char* addrText,
+ const char* tenantString, uint16_t timeout, DPS_OnRegPutComplete cb,
+ void* data);
/**
* Synchronous version of DPS_RegistrationPut(). This function blocks until the operations is
* complete.
*
* @param node The local node to register
+ * @param network The name of the network the address is on
* @param addrText The text string of the registration service address
* @param tenantString Topic string identifying the tenant
* @param timeout Timeout in milliseconds
*
* @return DPS_OK if the put request succeeded or and error status for the failure.
*/
-DPS_Status DPS_Registration_PutSyn(DPS_Node* node, const char* addrText, const char* tenantString,
- uint16_t timeout);
+DPS_Status DPS_Registration_PutSyn(DPS_Node* node, const char* network, const char* addrText,
+ const char* tenantString, uint16_t timeout);
/**
* Function prototype for callback called when DPS_Registration_Get() completes
@@ -148,6 +152,7 @@ typedef void (*DPS_OnRegGetComplete)(DPS_RegistrationList* regs, DPS_Status stat
* Lookup the addresses registered with a registration service.
*
* @param node The node
+ * @param network The name of the network the address is on
* @param addrText The text string of the registration service address
* @param tenantString Topic string identifying the tenant
* @param regs Registration list for accumulating the results. The count field must be
@@ -160,15 +165,16 @@ typedef void (*DPS_OnRegGetComplete)(DPS_RegistrationList* regs, DPS_Status stat
* @return DPS_OK if the registration get request was successfully initiated, otherwise returns an
* error status and the callback function will not be called.
*/
-DPS_Status DPS_Registration_Get(DPS_Node* node, const char* addrText, const char* tenantString,
- DPS_RegistrationList* regs, uint16_t timeout, DPS_OnRegGetComplete cb,
- void* data);
+DPS_Status DPS_Registration_Get(DPS_Node* node, const char* network, const char* addrText,
+ const char* tenantString, DPS_RegistrationList* regs, uint16_t timeout,
+ DPS_OnRegGetComplete cb, void* data);
/**
* A synchronous version of DPS_RegistrationGet() this function blocks until the candidate list has
* been populated or the request times out.
*
* @param node The node
+ * @param network The name of the network the address is on
* @param addrText The text string of the registration service address
* @param tenantString Topic string identifying the tenant
* @param regs Registration list for accumulating the results.
@@ -176,8 +182,9 @@ DPS_Status DPS_Registration_Get(DPS_Node* node, const char* addrText, const char
*
* @return DPS_OK if the get request succeeded or and error status for the failure.
*/
-DPS_Status DPS_Registration_GetSyn(DPS_Node* node, const char* addrText, const char* tenantString,
- DPS_RegistrationList* regs, uint16_t timeout);
+DPS_Status DPS_Registration_GetSyn(DPS_Node* node, const char* network, const char* addrText,
+ const char* tenantString, DPS_RegistrationList* regs,
+ uint16_t timeout);
/**
* Function prototype for callback called when DPS_Registration_LinkTo() completes
diff --git a/inc/dps/synchronous.h b/inc/dps/synchronous.h
index 46e6f922..0d30ecf2 100644
--- a/inc/dps/synchronous.h
+++ b/inc/dps/synchronous.h
@@ -43,12 +43,13 @@ extern "C" {
* Synchronous helper that wraps DPS_Link().
*
* @param node The local node to link from
+ * @param network The name of the network the address is on
* @param addrText The text string of the address to link to
* @param addr Returns the resolved address for the remote node
*
* @return DPS_OK if the link is successful, an error otherwise
*/
-DPS_Status DPS_LinkTo(DPS_Node* node, const char* addrText, DPS_NodeAddress* addr);
+DPS_Status DPS_LinkTo(DPS_Node* node, const char* network, const char* addrText, DPS_NodeAddress* addr);
/**
* Synchronous helper that wraps DPS_Unlink().
diff --git a/js_scripts/simple_pub.js b/js_scripts/simple_pub.js
index b69076c2..2048c15b 100644
--- a/js_scripts/simple_pub.js
+++ b/js_scripts/simple_pub.js
@@ -89,6 +89,8 @@ var dps = require("dps");
var pubKeyId;
var i;
var encryption;
+ var network = null;
+ var addr;
var onAck = function (pub, payload) {
console.log("Ack for pub UUID " + dps.publicationGetUUID(pub) + "(" + dps.publicationGetSequenceNum(pub) + ")");
@@ -111,6 +113,8 @@ var dps = require("dps");
for (i = 0; i < process.argv.length; ++i) {
if (process.argv[i] == "-x") {
encryption = process.argv[++i];
+ } else if (process.argv[i] == "-n") {
+ network = process.argv[++i];
} else if (process.argv[i] == "-d") {
dps.debug = 1;
}
@@ -136,7 +140,10 @@ var dps = require("dps");
}
node = dps.createNode("/", keyStore, nodeId);
- dps.startNode(node, dps.MCAST_PUB_ENABLE_SEND, null);
+ addr = dps.createAddress()
+ dps.setAddress(addr, network, null);
+ dps.startNode(node, dps.MCAST_PUB_ENABLE_SEND, addr);
+ dps.destroyAddress(addr);
console.log("Publisher is listening on " + dps.getListenAddress(node));
pub = dps.createPublication(node);
diff --git a/js_scripts/simple_pub_ks.js b/js_scripts/simple_pub_ks.js
index 7eb35039..95392bfb 100644
--- a/js_scripts/simple_pub_ks.js
+++ b/js_scripts/simple_pub_ks.js
@@ -90,6 +90,8 @@ var crypto = require("crypto");
var pubKeyId;
var i;
var encryption;
+ var network = null;
+ var addr;
var compare = function(a, b) {
var i;
@@ -193,6 +195,8 @@ var crypto = require("crypto");
for (i = 0; i < process.argv.length; ++i) {
if (process.argv[i] == "-x") {
encryption = process.argv[++i];
+ } else if (process.argv[i] == "-n") {
+ network = process.argv[++i];
} else if (process.argv[i] == "-d") {
dps.debug = 1;
}
@@ -213,7 +217,10 @@ var crypto = require("crypto");
}
node = dps.createNode("/", keyStore, nodeId);
- dps.startNode(node, dps.MCAST_PUB_ENABLE_SEND, null);
+ addr = dps.createAddress()
+ dps.setAddress(addr, network, null);
+ dps.startNode(node, dps.MCAST_PUB_ENABLE_SEND, addr);
+ dps.destroyAddress(addr);
console.log("Publisher is listening on " + dps.getListenAddress(node));
pub = dps.createPublication(node);
diff --git a/js_scripts/simple_sub.js b/js_scripts/simple_sub.js
index acf4ec81..f578e664 100644
--- a/js_scripts/simple_sub.js
+++ b/js_scripts/simple_sub.js
@@ -88,6 +88,8 @@ var dps = require("dps");
var sub;
var i;
var encryption;
+ var network = null;
+ var addr;
var onPub = function (sub, pub, payload) {
var ackMsg;
@@ -107,6 +109,8 @@ var dps = require("dps");
for (i = 0; i < process.argv.length; ++i) {
if (process.argv[i] == "-x") {
encryption = process.argv[++i];
+ } else if (process.argv[i] == "-n") {
+ network = process.argv[++i];
} else if (process.argv[i] == "-d") {
dps.debug = 1;
}
@@ -129,7 +133,10 @@ var dps = require("dps");
}
node = dps.createNode("/", keyStore, nodeId);
- dps.startNode(node, dps.MCAST_PUB_ENABLE_RECV, null);
+ addr = dps.createAddress()
+ dps.setAddress(addr, network, null);
+ dps.startNode(node, dps.MCAST_PUB_ENABLE_RECV, addr);
+ dps.destroyAddress(addr);
console.log("Subscriber is listening on " + dps.getListenAddress(node));
sub = dps.createSubscription(node, ["a/b/c"]);
dps.subscribe(sub, onPub);
diff --git a/js_scripts/simple_sub_ks.js b/js_scripts/simple_sub_ks.js
index 7c66a7a7..d53efe29 100644
--- a/js_scripts/simple_sub_ks.js
+++ b/js_scripts/simple_sub_ks.js
@@ -89,6 +89,8 @@ var crypto = require("crypto");
var sub;
var i;
var encryption;
+ var network = null;
+ var addr;
var compare = function(a, b) {
var i;
@@ -187,6 +189,8 @@ var crypto = require("crypto");
for (i = 0; i < process.argv.length; ++i) {
if (process.argv[i] == "-x") {
encryption = process.argv[++i];
+ } else if (process.argv[i] == "-n") {
+ network = process.argv[++i];
} else if (process.argv[i] == "-d") {
dps.debug = 1;
}
@@ -204,7 +208,10 @@ var crypto = require("crypto");
}
node = dps.createNode("/", keyStore, nodeId);
- dps.startNode(node, dps.MCAST_PUB_ENABLE_RECV, null);
+ addr = dps.createAddress()
+ dps.setAddress(addr, network, null);
+ dps.startNode(node, dps.MCAST_PUB_ENABLE_RECV, addr);
+ dps.destroyAddress(addr);
console.log("Subscriber is listening on " + dps.getListenAddress(node));
sub = dps.createSubscription(node, ["a/b/c"]);
dps.subscribe(sub, onPub);
diff --git a/py_scripts/late_sub.py b/py_scripts/late_sub.py
index c1ea1b95..f133c25a 100755
--- a/py_scripts/late_sub.py
+++ b/py_scripts/late_sub.py
@@ -18,11 +18,15 @@ def on_pub(sub, pub, payload):
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--debug", action='store_true',
help="Enable debug ouput if built for debug.")
+parser.add_argument("-n", "--network", default="udp",
+ help="Network of listen and link addresses.")
args = parser.parse_args()
dps.cvar.debug = args.debug
node = dps.create_node("/")
-dps.start_node(node, dps.MCAST_PUB_ENABLE_RECV + dps.MCAST_PUB_ENABLE_SEND, None)
+addr = dps.create_address()
+dps.set_address(addr, args.network, None)
+dps.start_node(node, dps.MCAST_PUB_ENABLE_RECV + dps.MCAST_PUB_ENABLE_SEND, addr)
print("Subscriber is listening on %s" % (dps.get_listen_address(node)))
sub = dps.create_subscription(node, ['a/b/c']);
dps.subscribe(sub, on_pub)
diff --git a/py_scripts/retained_pub.py b/py_scripts/retained_pub.py
index 1c8a6f19..9e4b3cef 100755
--- a/py_scripts/retained_pub.py
+++ b/py_scripts/retained_pub.py
@@ -21,11 +21,15 @@ def on_destroy(node):
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--debug", action='store_true',
help="Enable debug ouput if built for debug.")
+parser.add_argument("-n", "--network", default="udp",
+ help="Network of listen and link addresses.")
args = parser.parse_args()
dps.cvar.debug = args.debug
node = dps.create_node("/")
-dps.start_node(node, dps.MCAST_PUB_ENABLE_SEND + dps.MCAST_PUB_ENABLE_RECV, None)
+addr = dps.create_address()
+dps.set_address(addr, args.network, None)
+dps.start_node(node, dps.MCAST_PUB_ENABLE_SEND + dps.MCAST_PUB_ENABLE_RECV, addr)
print("Publisher is listening on %s" % (dps.get_listen_address(node)))
pub = dps.create_publication(node)
diff --git a/py_scripts/simple_pub.py b/py_scripts/simple_pub.py
index 1fb806a1..2dd17dc8 100755
--- a/py_scripts/simple_pub.py
+++ b/py_scripts/simple_pub.py
@@ -97,6 +97,8 @@
help="Enable debug ouput if built for debug.")
parser.add_argument("-x", "--encryption", type=int, choices=[0,1,2,3], default=1,
help="Disable (0) or enable symmetric encryption (1), asymmetric encryption (2), or authentication (3). Default is symmetric encryption enabled.")
+parser.add_argument("-n", "--network", default="udp",
+ help="Network of listen and link addresses.")
parser.add_argument("-l", "--listen", default=None,
help="Address to listen on for incoming connections.")
parser.add_argument("-p", "--port", default=None,
@@ -150,13 +152,11 @@ def on_destroy(node):
mcast = dps.MCAST_PUB_DISABLED
node = dps.create_node("/", key_store, node_id)
-listen_addr = None
-if args.listen != None:
- listen_addr = dps.create_address()
- try:
- dps.set_address(listen_addr, "[::]:%d" % (int(args.listen)))
- except ValueError:
- dps.set_address(listen_addr, args.listen)
+listen_addr = dps.create_address()
+try:
+ dps.set_address(listen_addr, args.network, "[::]:%d" % (int(args.listen)))
+except:
+ dps.set_address(listen_addr, args.network, args.listen)
dps.start_node(node, mcast, listen_addr)
print("Publisher is listening on %s" % (dps.get_listen_address(node)))
@@ -166,7 +166,7 @@ def on_destroy(node):
except ValueError:
addr_text = args.port
event.clear()
- ret = dps.link(node, addr_text, on_link)
+ ret = dps.link(node, args.network, addr_text, on_link)
if ret == dps.OK:
event.wait()
else:
diff --git a/py_scripts/simple_pub_ks.py b/py_scripts/simple_pub_ks.py
index 8fd2af7d..cd4c63da 100644
--- a/py_scripts/simple_pub_ks.py
+++ b/py_scripts/simple_pub_ks.py
@@ -97,6 +97,8 @@
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--debug", action='store_true',
help="Enable debug ouput if built for debug.")
+parser.add_argument("-n", "--network", default="udp",
+ help="Network of listen and link addresses.")
parser.add_argument("-x", "--encryption", type=int, choices=[0,1,2], default=1,
help="Disable (0) or enable symmetric (1) or asymmetric(2) encryption. Default is symmetric encryption enabled.")
args = parser.parse_args()
@@ -180,7 +182,9 @@ def on_destroy(node):
dps.destroy_key_store(key_store)
node = dps.create_node("/", key_store, node_id)
-dps.start_node(node, dps.MCAST_PUB_ENABLE_SEND, None)
+addr = dps.create_address()
+dps.set_address(addr, args.network, None)
+dps.start_node(node, dps.MCAST_PUB_ENABLE_SEND, addr)
print("Publisher is listening on %s" % (dps.get_listen_address(node)))
pub = dps.create_publication(node)
@@ -195,3 +199,4 @@ def on_destroy(node):
dps.destroy_publication(pub)
dps.destroy_node(node, on_destroy)
+dps.destroy_addr(addr)
diff --git a/py_scripts/simple_sub.py b/py_scripts/simple_sub.py
index 6f5e9a17..6dc5ae95 100755
--- a/py_scripts/simple_sub.py
+++ b/py_scripts/simple_sub.py
@@ -96,6 +96,8 @@
help="Enable debug ouput if built for debug.")
parser.add_argument("-x", "--encryption", type=int, choices=[0,1,2], default=1,
help="Disable (0) or enable symmetric (1) or asymmetric(2) encryption. Default is symmetric encryption enabled.")
+parser.add_argument("-n", "--network", default="udp",
+ help="Network of listen and link addresses.")
parser.add_argument("-l", "--listen", default=None,
help="Address to listen on for incoming connections.")
parser.add_argument("-p", "--port", default=None,
@@ -138,13 +140,11 @@ def on_link(node, addr, status):
event.set()
node = dps.create_node("/", key_store, node_id)
-listen_addr = None
-if args.listen != None:
- listen_addr = dps.create_address()
- try:
- dps.set_address(listen_addr, "[::]:%d" % (int(args.listen)))
- except ValueError:
- dps.set_address(listen_addr, args.listen)
+listen_addr = dps.create_address()
+try:
+ dps.set_address(listen_addr, args.network, "[::]:%d" % (int(args.listen)))
+except:
+ dps.set_address(listen_addr, args.network, args.listen)
dps.start_node(node, dps.MCAST_PUB_ENABLE_RECV, listen_addr)
print("Subscriber is listening on %s" % (dps.get_listen_address(node)))
@@ -157,7 +157,7 @@ def on_link(node, addr, status):
except ValueError:
addr_text = args.port
event.clear()
- ret = dps.link(node, addr_text, on_link)
+ ret = dps.link(node, args.network, addr_text, on_link)
if ret == dps.OK:
event.wait()
else:
diff --git a/py_scripts/simple_sub_ks.py b/py_scripts/simple_sub_ks.py
index 1c6d8a77..0b7f8985 100644
--- a/py_scripts/simple_sub_ks.py
+++ b/py_scripts/simple_sub_ks.py
@@ -97,6 +97,8 @@
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--debug", action='store_true',
help="Enable debug ouput if built for debug.")
+parser.add_argument("-n", "--network", default="udp",
+ help="Network of listen and link addresses.")
parser.add_argument("-x", "--encryption", type=int, choices=[0,1,2], default=1,
help="Disable (0) or enable symmetric (1) or asymmetric(2) encryption. Default is symmetric encryption enabled.")
args = parser.parse_args()
@@ -180,7 +182,9 @@ def on_pub(sub, pub, payload):
dps.ack_publication(pub, ack_msg);
node = dps.create_node("/", key_store, node_id)
-dps.start_node(node, dps.MCAST_PUB_ENABLE_RECV, None)
+addr = dps.create_address()
+dps.set_address(addr, args.network, None)
+dps.start_node(node, dps.MCAST_PUB_ENABLE_RECV, addr)
print("Subscriber is listening on %s" % (dps.get_listen_address(node)))
sub = dps.create_subscription(node, ['a/b/c']);
dps.subscribe(sub, on_pub)
diff --git a/py_scripts/subs_tree.py b/py_scripts/subs_tree.py
index 3cb3276d..18d8b916 100755
--- a/py_scripts/subs_tree.py
+++ b/py_scripts/subs_tree.py
@@ -14,6 +14,15 @@
# |
# +/#
+import argparse
+parser = argparse.ArgumentParser()
+parser.add_argument("-d", "--debug", action='store_true',
+ help="Enable debug ouput if built for debug.")
+parser.add_argument("-n", "--network", default="udp",
+ help="Network of listen and link addresses.")
+args = parser.parse_args()
+dps.cvar.debug = args.debug
+
key_id = [
0xed,0x54,0x14,0xa8,0x5c,0x4d,0x4d,0x15,0xb6,0x9f,0x0e,0x99,0x8a,0xb1,0x71,0xf2
]
@@ -48,25 +57,22 @@ def on_link(node, addr, status):
nodes = []
def subscriber(topic, remote_listen_addr):
node = dps.create_node("/", key_store, None)
- dps.start_node(node, 0, None)
+ addr = dps.create_address()
+ dps.set_address(addr, args.network, None)
+ dps.start_node(node, 0, addr)
+ dps.destroy_address(addr)
print("Subscriber is listening on %s" % dps.get_listen_address(node))
sub = dps.create_subscription(node, [topic])
dps.subscribe(sub, on_pub)
if remote_listen_addr != None:
event.clear()
- ret = dps.link(node, str(remote_listen_addr), on_link)
+ ret = dps.link(node, dps.node_addr_network(remote_listen_addr), str(remote_listen_addr),
+ on_link)
if ret == dps.OK:
event.wait()
nodes.append(node)
return node
-import argparse
-parser = argparse.ArgumentParser()
-parser.add_argument("-d", "--debug", action='store_true',
- help="Enable debug ouput if built for debug.")
-args = parser.parse_args()
-dps.cvar.debug = args.debug
-
sub1 = subscriber('B/B', None)
sub2 = subscriber('A/A', dps.get_listen_address(sub1))
sub3 = subscriber('C/C', dps.get_listen_address(sub1))
diff --git a/src/cbor.c b/src/cbor.c
index 8f580859..f7409c8d 100644
--- a/src/cbor.c
+++ b/src/cbor.c
@@ -527,6 +527,7 @@ DPS_Status CBOR_DecodeInt32(DPS_RxBuffer* buffer, int32_t* n)
DPS_Status CBOR_DecodeBytes(DPS_RxBuffer* buffer, uint8_t** data, size_t* size)
{
+ uint8_t* rxPos = buffer->rxPos;
DPS_Status ret;
uint64_t len;
@@ -535,7 +536,7 @@ DPS_Status CBOR_DecodeBytes(DPS_RxBuffer* buffer, uint8_t** data, size_t* size)
ret = DecodeUint(buffer, &len, CBOR_BYTES);
if (ret == DPS_OK) {
if (len > DPS_RxBufferAvail(buffer)) {
- ret = DPS_ERR_INVALID;
+ ret = DPS_ERR_EOD;
} else {
if (len) {
*data = buffer->rxPos;
@@ -544,18 +545,22 @@ DPS_Status CBOR_DecodeBytes(DPS_RxBuffer* buffer, uint8_t** data, size_t* size)
}
}
}
+ if (ret != DPS_OK) {
+ buffer->rxPos = rxPos;
+ }
return ret;
}
DPS_Status CBOR_DecodeString(DPS_RxBuffer* buffer, char** data, size_t* size)
{
+ uint8_t* rxPos = buffer->rxPos;
DPS_Status ret;
uint64_t len;
ret = DecodeUint(buffer, &len, CBOR_STRING);
if (ret == DPS_OK) {
if (len > DPS_RxBufferAvail(buffer)) {
- ret = DPS_ERR_INVALID;
+ ret = DPS_ERR_EOD;
} else if (len > 0) {
*data = (char*)buffer->rxPos;
*size = len;
@@ -565,6 +570,9 @@ DPS_Status CBOR_DecodeString(DPS_RxBuffer* buffer, char** data, size_t* size)
*size = 0;
}
}
+ if (ret != DPS_OK) {
+ buffer->rxPos = rxPos;
+ }
return ret;
}
diff --git a/src/dps.c b/src/dps.c
index 4c132212..ed59583a 100755
--- a/src/dps.c
+++ b/src/dps.c
@@ -1282,6 +1282,7 @@ DPS_Node* DPS_CreateNode(const char* separators, DPS_KeyStore* keyStore, const D
strncpy_s(node->separators, sizeof(node->separators), separators, sizeof(node->separators) - 1);
node->keyStore = keyStore;
DPS_QueueInit(&node->ackQueue);
+ DPS_QueueInit(&node->resolverQueue);
/*
* Set default probe configuration and subscription rate parameters
*/
@@ -1529,15 +1530,14 @@ static void OnResolve(DPS_Node* node, const DPS_NodeAddress* addr, void* data)
}
}
-DPS_Status DPS_Link(DPS_Node* node, const char* addrText, DPS_OnLinkComplete cb, void* data)
+DPS_Status DPS_Link(DPS_Node* node, const char* network, const char* addrText,
+ DPS_OnLinkComplete cb, void* data)
{
DPS_Status ret = DPS_OK;
OnOpCompletion* completion = NULL;
DPS_NodeAddress* addr = NULL;
-#if defined(DPS_USE_DTLS) || defined(DPS_USE_TCP) || defined(DPS_USE_UDP)
char host[DPS_MAX_HOST_LEN + 1];
char service[DPS_MAX_SERVICE_LEN + 1];
-#endif
DPS_DBGTRACE();
@@ -1550,34 +1550,42 @@ DPS_Status DPS_Link(DPS_Node* node, const char* addrText, DPS_OnLinkComplete cb,
ret = DPS_ERR_RESOURCES;
goto Exit;
}
-#if defined(DPS_USE_DTLS) || defined(DPS_USE_TCP) || defined(DPS_USE_UDP)
- ret = DPS_SplitAddress(addrText, host, sizeof(host), service, sizeof(service));
- if (ret != DPS_OK) {
- DPS_ERRPRINT("DPS_SplitAddress returned %s\n", DPS_ErrTxt(ret));
- goto Exit;
- }
- ret = DPS_ResolveAddress(node, host, service, OnResolve, completion);
- if (ret != DPS_OK) {
- DPS_ERRPRINT("DPS_ResolveAddress returned %s\n", DPS_ErrTxt(ret));
- goto Exit;
- }
-#elif defined(DPS_USE_PIPE)
- addr = DPS_CreateAddress();
- if (!addr) {
- ret = DPS_ERR_RESOURCES;
- goto Exit;
- }
- if (DPS_SetAddress(addr, addrText) == NULL) {
- DPS_ERRPRINT("DPS_SetAddress failed\n");
- ret = DPS_ERR_INVALID;
- goto Exit;
- }
- ret = Link(node, addr, completion);
- if (ret != DPS_OK) {
- DPS_ERRPRINT("Link returned %s\n", DPS_ErrTxt(ret));
- goto Exit;
+ switch (DPS_NetAddressType(network)) {
+ case DPS_DTLS:
+ case DPS_TCP:
+ case DPS_UDP:
+ ret = DPS_SplitAddress(addrText, host, sizeof(host), service, sizeof(service));
+ if (ret != DPS_OK) {
+ DPS_ERRPRINT("DPS_SplitAddress returned %s\n", DPS_ErrTxt(ret));
+ goto Exit;
+ }
+ ret = DPS_ResolveAddress(node, network, host, service, OnResolve, completion);
+ if (ret != DPS_OK) {
+ DPS_ERRPRINT("DPS_ResolveAddress returned %s\n", DPS_ErrTxt(ret));
+ goto Exit;
+ }
+ break;
+ case DPS_PIPE:
+ addr = DPS_CreateAddress();
+ if (!addr) {
+ ret = DPS_ERR_RESOURCES;
+ goto Exit;
+ }
+ if (DPS_SetAddress(addr, "pipe", addrText) == NULL) {
+ DPS_ERRPRINT("DPS_SetAddress failed\n");
+ ret = DPS_ERR_INVALID;
+ goto Exit;
+ }
+ ret = Link(node, addr, completion);
+ if (ret != DPS_OK) {
+ DPS_ERRPRINT("Link returned %s\n", DPS_ErrTxt(ret));
+ goto Exit;
+ }
+ break;
+ default:
+ ret = DPS_ERR_ARGS;
+ break;
}
-#endif
Exit:
DPS_DestroyAddress(addr);
if (ret != DPS_OK) {
@@ -1649,6 +1657,12 @@ const char* DPS_NodeAddrToString(const DPS_NodeAddress* addr)
return "NULL";
}
+const char* DPS_NodeAddrNetwork(const DPS_NodeAddress* addr)
+{
+ static const char* txt[] = { NULL, "dtls", "tcp", "udp", "pipe" };
+ return txt[addr->type];
+}
+
DPS_NodeAddress* DPS_CreateAddress()
{
return calloc(1, sizeof(DPS_NodeAddress));
diff --git a/src/dtls/network.c b/src/dtls/network.c
index 93afabec..6c9dbb73 100755
--- a/src/dtls/network.c
+++ b/src/dtls/network.c
@@ -66,6 +66,9 @@ DPS_DEBUG_CONTROL(DPS_DEBUG_ON);
/* Personalization string for the DRBG */
#define PERSONALIZATION_STRING "DPS_DRBG"
+typedef struct _DPS_NetDtlsConnection DPS_NetDtlsConnection;
+typedef struct _DPS_NetDtlsContext DPS_NetDtlsContext;
+
typedef struct _RecvData {
DPS_Queue queue;
uv_buf_t buf;
@@ -73,7 +76,7 @@ typedef struct _RecvData {
typedef struct _SendRequest {
DPS_Queue queue;
- DPS_NetConnection* cn;
+ DPS_NetDtlsConnection* cn;
void* appCtx;
uv_buf_t* bufs;
size_t numBufs;
@@ -83,13 +86,14 @@ typedef struct _SendRequest {
} SendRequest;
/*
- * DPS_NetConnection holds mbedtls supporting data and any pending
+ * DPS_NetDtlsConnection holds mbedtls supporting data and any pending
* reads and writes. These pending structures are used for buffering
* during handshake phase, but also to solve some memory lifecycle
* issues -- ensuring certain buffers are alive for enough time.
*/
-typedef struct _DPS_NetConnection {
- DPS_NetContext* netCtx;
+typedef struct _DPS_NetDtlsConnection {
+ DPS_NetConnection cn;
+ DPS_NetDtlsContext* netCtx;
DPS_Node* node;
/*
* The ref counting strategy is as follows:
@@ -174,15 +178,16 @@ typedef struct _DPS_NetConnection {
mbedtls_ssl_cookie_ctx cookieCtx;
mbedtls_ssl_cache_context cacheCtx;
- DPS_NetConnection* next;
-} DPS_NetConnection;
+ DPS_NetDtlsConnection* next;
+} DPS_NetDtlsConnection;
#define MAX_READ_LEN 65536
#define NET_RUNNING 1 /**< Net layer is running */
#define NET_STOPPING 2 /**< Net layer is stopping */
-struct _DPS_NetContext {
+struct _DPS_NetDtlsContext {
+ DPS_NetContext ctx;
int state;
uv_udp_t rxSocket;
uv_udp_recv_cb dataCB;
@@ -190,7 +195,7 @@ struct _DPS_NetContext {
uint32_t handshakeTimeoutMax;
DPS_Node* node;
DPS_OnReceive receiveCB;
- DPS_NetConnection* cns;
+ DPS_NetDtlsConnection* cns;
};
/*
@@ -223,6 +228,36 @@ static const int PskCipherSuites[] = {
0
};
+DPS_NodeAddress* DPS_NetDtlsGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext* netCtx);
+void DPS_NetDtlsStop(DPS_NetContext* netCtx);
+DPS_Status DPS_NetDtlsSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf_t* bufs,
+ size_t numBufs, DPS_NetSendComplete sendCompleteCB);
+void DPS_NetDtlsConnectionIncRef(DPS_NetConnection* cn);
+void DPS_NetDtlsConnectionDecRef(DPS_NetConnection* cn);
+
+static void DestroyConnection(DPS_NetDtlsConnection* cn);
+static int TLSHandshake(DPS_NetDtlsConnection* cn);
+static void ConsumePending(DPS_NetDtlsConnection* cn);
+
+static void ConnectionIncRef(DPS_NetDtlsConnection* cn)
+{
+ if (cn) {
+ DPS_DBGTRACEA("cn=%p\n", cn);
+ ++cn->refCount;
+ }
+}
+
+static void ConnectionDecRef(DPS_NetDtlsConnection* cn)
+{
+ if (cn) {
+ DPS_DBGTRACEA("cn=%p\n", cn);
+ assert(cn->refCount > 0);
+ if (--cn->refCount == 0) {
+ DestroyConnection(cn);
+ }
+ }
+}
+
static void AllocBuffer(uv_handle_t* handle, size_t suggestedSize, uv_buf_t* buf)
{
buf->base = calloc(MAX_READ_LEN, sizeof(uint8_t));
@@ -235,34 +270,34 @@ static void AllocBuffer(uv_handle_t* handle, size_t suggestedSize, uv_buf_t* buf
static void OnServerData(uv_udp_t* socket, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags)
{
- DPS_NetContext* netCtx = socket->data;
+ DPS_NetDtlsContext* netCtx = socket->data;
netCtx->dataCB(socket, nread, buf, addr, flags);
}
static void OnClientData(uv_udp_t* socket, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags)
{
- DPS_NetConnection* cn = socket->data;
- DPS_NetContext* netCtx = cn->netCtx;
+ DPS_NetDtlsConnection* cn = socket->data;
+ DPS_NetDtlsContext* netCtx = cn->netCtx;
/*
* Use the rxSocket here as it's only purpose in dataCB is to get
- * to the DPS_NetContext
+ * to the DPS_NetDtlsContext
*/
netCtx->dataCB(&netCtx->rxSocket, nread, buf, addr, flags);
}
-static uv_udp_t* GetSocket(DPS_NetConnection* cn)
+static uv_udp_t* GetSocket(DPS_NetDtlsConnection* cn)
{
if (cn->type == MBEDTLS_SSL_IS_SERVER) {
- DPS_NetContext* netCtx = cn->netCtx;
+ DPS_NetDtlsContext* netCtx = cn->netCtx;
return &netCtx->rxSocket;
} else {
return &cn->socket;
}
}
-static DPS_NetConnection* LookupConnection(DPS_NetContext* netCtx, DPS_NodeAddress* addr)
+static DPS_NetDtlsConnection* LookupConnection(DPS_NetDtlsContext* netCtx, DPS_NodeAddress* addr)
{
- DPS_NetConnection* cn;
+ DPS_NetDtlsConnection* cn;
for (cn = netCtx->cns; cn != NULL; cn = cn->next) {
if (DPS_SameAddr(cn->peerAddr, addr)) {
@@ -331,12 +366,12 @@ static void DestroySendRequest(SendRequest* req)
}
}
-static void CancelPending(DPS_NetConnection* cn)
+static void CancelPendingSend(DPS_NetDtlsConnection* cn)
{
/*
* Protect connection while we are modifying the queues.
*/
- DPS_NetConnectionIncRef(cn);
+ ConnectionIncRef(cn);
while (!DPS_QueueEmpty(&cn->sendQueue)) {
SendRequest* req = (SendRequest*)DPS_QueueFront(&cn->sendQueue);
@@ -349,11 +384,29 @@ static void CancelPending(DPS_NetConnection* cn)
SendRequest* req = (SendRequest*)DPS_QueueFront(&cn->sendCompletedQueue);
DPS_QueueRemove(&req->queue);
req->sendCompleteCB(cn->node, req->appCtx, &cn->peer, req->bufs, req->numBufs, req->status);
- DPS_NetConnectionDecRef(cn);
+ ConnectionDecRef(cn);
DestroySendRequest(req);
}
- DPS_NetConnectionDecRef(cn);
+ ConnectionDecRef(cn);
+}
+
+static void CancelPending(DPS_NetDtlsConnection* cn)
+{
+ /*
+ * Protect connection while we are modifying the queues.
+ */
+ ConnectionIncRef(cn);
+
+ while (!DPS_QueueEmpty(&cn->recvQueue)) {
+ RecvData* data = (RecvData*)DPS_QueueFront(&cn->recvQueue);
+ DPS_QueueRemove(&data->queue);
+ ConnectionDecRef(cn);
+ DestroyRecvData(data);
+ }
+ CancelPendingSend(cn);
+
+ ConnectionDecRef(cn);
}
static void OnTLSDebug(void *ctx, int level, const char *file, int line, const char *str)
@@ -379,17 +432,13 @@ static void OnTLSDebug(void *ctx, int level, const char *file, int line, const c
}
}
-static void DestroyConnection(DPS_NetConnection* cn);
-static int TLSHandshake(DPS_NetConnection* cn);
-static void ConsumePending(DPS_NetConnection* cn);
-
/*
* PSK
*/
static DPS_Status TLSPSKSet(DPS_KeyStoreRequest* request, const DPS_Key* key)
{
- DPS_NetConnection* cn = request->data;
+ DPS_NetDtlsConnection* cn = request->data;
int ret = mbedtls_ssl_set_hs_psk(&cn->ssl, key->symmetric.key, key->symmetric.len);
if (ret != 0) {
DPS_ERRPRINT("Set PSK failed: %s\n", TLSErrTxt(ret));
@@ -400,7 +449,7 @@ static DPS_Status TLSPSKSet(DPS_KeyStoreRequest* request, const DPS_Key* key)
static int OnTLSPSKGet(void *data, mbedtls_ssl_context* ssl, const uint8_t* id, size_t idLen)
{
- DPS_NetConnection* cn = data;
+ DPS_NetDtlsConnection* cn = data;
DPS_KeyStore* keyStore = cn->node->keyStore;
DPS_KeyId keyId = { id, idLen };
DPS_KeyStoreRequest request;
@@ -436,7 +485,7 @@ static int OnTLSPSKGet(void *data, mbedtls_ssl_context* ssl, const uint8_t* id,
static void OnTimeout(uv_timer_t* timer)
{
- DPS_NetConnection* cn = timer->data;
+ DPS_NetDtlsConnection* cn = timer->data;
int ret;
DPS_DBGTRACEA("cn=%p\n", cn);
@@ -453,18 +502,18 @@ static void OnTimeout(uv_timer_t* timer)
* perform a handshake step.
*/
ret = TLSHandshake(cn);
- if (ret == DPS_TRUE && cn->handshakeDone) {
+ if (ret == 0 && cn->handshakeDone) {
ConsumePending(cn);
- } else if (ret == DPS_FALSE) {
+ } else if (ret != 0) {
CancelPending(cn);
}
- DPS_NetConnectionDecRef(cn);
+ ConnectionDecRef(cn);
}
}
static void OnTLSTimerSet(void* data, uint32_t int_ms, uint32_t fin_ms)
{
- DPS_NetConnection* cn = data;
+ DPS_NetDtlsConnection* cn = data;
DPS_DBGTRACEA("cn=%p,int_ms=%u,fin_ms=%u\n", cn, int_ms, fin_ms);
@@ -474,7 +523,7 @@ static void OnTLSTimerSet(void* data, uint32_t int_ms, uint32_t fin_ms)
cn->timerStatus = -1;
if (active) {
uv_timer_stop(&cn->timer);
- DPS_NetConnectionDecRef(cn);
+ ConnectionDecRef(cn);
}
return;
}
@@ -487,13 +536,13 @@ static void OnTLSTimerSet(void* data, uint32_t int_ms, uint32_t fin_ms)
}
uv_timer_start(&cn->timer, OnTimeout, int_ms, fin_ms - int_ms);
if (!active) {
- DPS_NetConnectionIncRef(cn);
+ ConnectionIncRef(cn);
}
}
static int OnTLSTimerGet(void* data)
{
- DPS_NetConnection* cn = data;
+ DPS_NetDtlsConnection* cn = data;
DPS_DBGTRACEA("cn=%p timerStatus=%d\n", cn, cn->timerStatus);
@@ -515,7 +564,7 @@ static int OnTLSTimerGet(void* data)
static int OnTLSRecv(void* userData, unsigned char *buf, size_t len)
{
- DPS_NetConnection* cn = userData;
+ DPS_NetDtlsConnection* cn = userData;
RecvData* data;
DPS_DBGTRACEA("cn=%p,buf=%p,len=%d\n", cn, buf, len);
@@ -539,7 +588,7 @@ static int OnTLSRecv(void* userData, unsigned char *buf, size_t len)
memcpy_s(buf, data->buf.len, data->buf.base, dataLen);
DPS_QueueRemove(&data->queue);
- DPS_NetConnectionDecRef(cn);
+ ConnectionDecRef(cn);
DestroyRecvData(data);
return (int) dataLen;
}
@@ -547,10 +596,10 @@ static int OnTLSRecv(void* userData, unsigned char *buf, size_t len)
typedef struct _SendReq {
uv_udp_send_t uvReq;
uv_buf_t buf;
- DPS_NetConnection* cn;
+ DPS_NetDtlsConnection* cn;
} SendReq;
-static SendReq* CreateSendReq(DPS_NetConnection* cn, const unsigned char *buf, size_t len)
+static SendReq* CreateSendReq(DPS_NetDtlsConnection* cn, const unsigned char *buf, size_t len)
{
SendReq* sendReq;
@@ -604,13 +653,13 @@ static void OnSendComplete(uv_udp_send_t *req, int status)
if (status != 0) {
DPS_ERRPRINT("Send failed: %s\n", uv_err_name(status));
}
- DPS_NetConnectionDecRef(sendReq->cn);
+ ConnectionDecRef(sendReq->cn);
DestroySendReq(sendReq);
}
static int OnTLSSend(void* data, const unsigned char *buf, size_t len)
{
- DPS_NetConnection* cn = data;
+ DPS_NetDtlsConnection* cn = data;
SendReq* sendReq = NULL;
DPS_DBGTRACEA("cn=%p,buf=%p,len=%d\n", cn, buf, len);
@@ -637,7 +686,7 @@ static int OnTLSSend(void* data, const unsigned char *buf, size_t len)
DPS_ERRPRINT("Send failed: %s\n", uv_err_name(err));
goto ErrorExit;
}
- DPS_NetConnectionIncRef(cn);
+ ConnectionIncRef(cn);
return (int) len;
@@ -652,7 +701,7 @@ static void RxHandleClosed(uv_handle_t* handle)
free(handle->data);
}
-static void FreeConnection(DPS_NetConnection* cn)
+static void FreeConnection(DPS_NetDtlsConnection* cn)
{
mbedtls_ssl_free(&cn->ssl);
mbedtls_ssl_config_free(&cn->conf);
@@ -671,11 +720,11 @@ static void FreeConnection(DPS_NetConnection* cn)
}
if (cn->netCtx) {
- DPS_NetConnection* next = cn->next;
+ DPS_NetDtlsConnection* next = cn->next;
if (cn->netCtx->cns == cn) {
cn->netCtx->cns = next;
} else if (cn->netCtx->cns) {
- DPS_NetConnection* prev = cn->netCtx->cns;
+ DPS_NetDtlsConnection* prev = cn->netCtx->cns;
while (prev->next != cn) {
prev = prev->next;
assert(prev);
@@ -697,13 +746,13 @@ static void FreeConnection(DPS_NetConnection* cn)
static void TimerClosed(uv_handle_t* handle)
{
- DPS_NetConnection* cn = (DPS_NetConnection*)handle->data;
+ DPS_NetDtlsConnection* cn = (DPS_NetDtlsConnection*)handle->data;
FreeConnection(cn);
}
static void IdleForCallbacksClosed(uv_handle_t* handle)
{
- DPS_NetConnection* cn = (DPS_NetConnection*)handle->data;
+ DPS_NetDtlsConnection* cn = (DPS_NetDtlsConnection*)handle->data;
if (!uv_is_closing((uv_handle_t*)&cn->timer)) {
uv_close((uv_handle_t*)&cn->timer, TimerClosed);
} else {
@@ -713,7 +762,7 @@ static void IdleForCallbacksClosed(uv_handle_t* handle)
static void SocketClosed(uv_handle_t* handle)
{
- DPS_NetConnection* cn = (DPS_NetConnection*)handle->data;
+ DPS_NetDtlsConnection* cn = (DPS_NetDtlsConnection*)handle->data;
if (!uv_is_closing((uv_handle_t*)&cn->idleForSendCallbacks)) {
uv_close((uv_handle_t*)&cn->idleForSendCallbacks, IdleForCallbacksClosed);
@@ -724,7 +773,7 @@ static void SocketClosed(uv_handle_t* handle)
}
}
-static void DestroyConnection(DPS_NetConnection* cn)
+static void DestroyConnection(DPS_NetDtlsConnection* cn)
{
DPS_DBGTRACEA("cn=%p\n", cn);
@@ -733,8 +782,7 @@ static void DestroyConnection(DPS_NetConnection* cn)
assert(DPS_QueueEmpty(&cn->sendQueue));
assert(DPS_QueueEmpty(&cn->sendCompletedQueue));
assert(cn->handshake != MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED &&
- cn->handshake != MBEDTLS_ERR_SSL_WANT_READ &&
- cn->handshake != MBEDTLS_ERR_SSL_WANT_WRITE);
+ cn->handshake != MBEDTLS_ERR_SSL_WANT_READ);
switch (cn->state) {
case CN_OPEN:
@@ -743,6 +791,7 @@ static void DestroyConnection(DPS_NetConnection* cn)
if (ret != 0) {
DPS_ERRPRINT("Close notify failed: %s\n", TLSErrTxt(ret));
}
+ DPS_DBGPRINT("OPEN -> CLOSE_NOTIFIED cn=%p\n", cn);
/*
* The ref count may be non-0 now if mbedtls has work to do
* for the close notify above.
@@ -753,10 +802,11 @@ static void DestroyConnection(DPS_NetConnection* cn)
/* FALLTHROUGH */
case CN_CLOSE_NOTIFIED:
cn->state = CN_CLOSING;
+ DPS_DBGPRINT("CLOSE_NOTIFIED -> CLOSING cn=%p\n", cn);
assert(!uv_is_active((uv_handle_t*)&cn->timer));
if (uv_is_active((uv_handle_t*)&cn->idleForSendCallbacks)) {
uv_idle_stop(&cn->idleForSendCallbacks);
- DPS_NetConnectionDecRef(cn);
+ ConnectionDecRef(cn);
}
if (cn->type == MBEDTLS_SSL_IS_CLIENT) {
uv_udp_recv_stop(&cn->socket);
@@ -780,7 +830,7 @@ static void DestroyConnection(DPS_NetConnection* cn)
}
}
-static int ResetConnection(DPS_NetConnection* cn, const struct sockaddr* addr)
+static int ResetConnection(DPS_NetDtlsConnection* cn, const struct sockaddr* addr)
{
char clientID[INET6_ADDRSTRLEN] = { 0 };
int ret;
@@ -813,7 +863,7 @@ static int ResetConnection(DPS_NetConnection* cn, const struct sockaddr* addr)
static DPS_Status SetCA(DPS_KeyStoreRequest* request, const char* ca)
{
- DPS_NetConnection* cn = request->data;
+ DPS_NetDtlsConnection* cn = request->data;
size_t len;
int ret;
@@ -832,7 +882,7 @@ static DPS_Status SetCA(DPS_KeyStoreRequest* request, const char* ca)
static DPS_Status SetCert(DPS_KeyStoreRequest* request, const DPS_Key* key)
{
- DPS_NetConnection* cn = request->data;
+ DPS_NetDtlsConnection* cn = request->data;
size_t len;
size_t pwLen;
int ret;
@@ -869,7 +919,7 @@ static DPS_Status SetCert(DPS_KeyStoreRequest* request, const DPS_Key* key)
static DPS_Status SetKeyAndId(DPS_KeyStoreRequest* request, const DPS_Key* key,
const DPS_KeyId* keyId)
{
- DPS_NetConnection* cn = request->data;
+ DPS_NetDtlsConnection* cn = request->data;
int ret = mbedtls_ssl_conf_psk(&cn->conf, key->symmetric.key, key->symmetric.len, keyId->id, keyId->len);
if (ret != 0) {
DPS_WARNPRINT("Set PSK failed: %s\n", TLSErrTxt(ret));
@@ -878,11 +928,11 @@ static DPS_Status SetKeyAndId(DPS_KeyStoreRequest* request, const DPS_Key* key,
return DPS_OK;
}
-static DPS_NetConnection* CreateConnection(DPS_Node* node, const struct sockaddr* addr, int type)
+static DPS_NetDtlsConnection* CreateConnection(DPS_Node* node, const struct sockaddr* addr, int type)
{
int ret;
- DPS_NetConnection* cn;
- DPS_NetContext* netCtx = node->netCtx;
+ DPS_NetDtlsConnection* cn;
+ DPS_NetDtlsContext* netCtx = (DPS_NetDtlsContext*)node->netCtx;
DPS_KeyStore* keyStore = node->keyStore;
DPS_KeyStoreRequest request;
const int* ciphersuites = AllCipherSuites;
@@ -895,11 +945,12 @@ static DPS_NetConnection* CreateConnection(DPS_Node* node, const struct sockaddr
return NULL;
}
- cn = calloc(1, sizeof(DPS_NetConnection));
+ cn = calloc(1, sizeof(DPS_NetDtlsConnection));
if (!cn) {
return NULL;
}
-
+ cn->cn.incRef = DPS_NetDtlsConnectionIncRef;
+ cn->cn.decRef = DPS_NetDtlsConnectionDecRef;
cn->netCtx = netCtx;
cn->node = node;
cn->type = type;
@@ -1067,7 +1118,7 @@ static DPS_NetConnection* CreateConnection(DPS_Node* node, const struct sockaddr
static void OnIdleForSendCallbacks(uv_idle_t* idle)
{
- DPS_NetConnection* cn = (DPS_NetConnection*)idle->data;
+ DPS_NetDtlsConnection* cn = (DPS_NetDtlsConnection*)idle->data;
DPS_DBGTRACE();
@@ -1075,12 +1126,12 @@ static void OnIdleForSendCallbacks(uv_idle_t* idle)
SendRequest* req = (SendRequest*)DPS_QueueFront(&cn->sendCompletedQueue);
DPS_QueueRemove(&req->queue);
req->sendCompleteCB(cn->node, req->appCtx, &cn->peer, req->bufs, req->numBufs, req->status);
- DPS_NetConnectionDecRef(cn);
+ ConnectionDecRef(cn);
DestroySendRequest(req);
}
uv_idle_stop(&cn->idleForSendCallbacks);
- DPS_NetConnectionDecRef(cn);
+ ConnectionDecRef(cn);
}
/*
@@ -1095,7 +1146,7 @@ static void OnIdleForSendCallbacks(uv_idle_t* idle)
* debugging and handling our data structures.
*/
-static void TLSSend(DPS_NetConnection* cn)
+static void TLSSend(DPS_NetDtlsConnection* cn)
{
int ret;
uint8_t* base;
@@ -1118,7 +1169,7 @@ static void TLSSend(DPS_NetConnection* cn)
/*
* Add a ref while OnIdleForSendCallbacks is pending.
*/
- DPS_NetConnectionIncRef(cn);
+ ConnectionIncRef(cn);
}
}
DPS_DBGPRINT("Using pending send with %d bufs\n", req->numBufs);
@@ -1155,7 +1206,7 @@ static void TLSSend(DPS_NetConnection* cn)
* Protect cn since mbedtls_ssl_write may consume all the
* references.
*/
- DPS_NetConnectionIncRef(cn);
+ ConnectionIncRef(cn);
/*
* HERE: there's no data pointer to make a connection between this
@@ -1171,7 +1222,7 @@ static void TLSSend(DPS_NetConnection* cn)
ret = mbedtls_ssl_write(&cn->ssl, base, total);
} while (0 < ret && (size_t)ret < total);
- DPS_NetConnectionDecRef(cn);
+ ConnectionDecRef(cn);
if (req->numBufs != 1) {
DPS_TxBufferFree(&txbuf);
@@ -1183,9 +1234,9 @@ static void TLSSend(DPS_NetConnection* cn)
}
}
-static void TLSRecv(DPS_NetConnection* cn)
+static int TLSRecv(DPS_NetDtlsConnection* cn)
{
- DPS_NetContext* netCtx = cn->netCtx;
+ DPS_NetDtlsContext* netCtx = cn->netCtx;
DPS_NetRxBuffer* buf = NULL;
int ret;
DPS_Status status;
@@ -1194,11 +1245,12 @@ static void TLSRecv(DPS_NetConnection* cn)
* Protect cn since mbedtls_ssl_read may consume all the
* references.
*/
- DPS_NetConnectionIncRef(cn);
+ ConnectionIncRef(cn);
buf = DPS_CreateNetRxBuffer(MAX_READ_LEN);
if (!buf) {
DPS_ERRPRINT("Create buffer failed: %s\n", DPS_ErrTxt(DPS_ERR_RESOURCES));
+ ret = -1;
goto Exit;
}
ret = mbedtls_ssl_read(&cn->ssl, buf->rx.base, DPS_RxBufferAvail(&buf->rx));
@@ -1208,6 +1260,7 @@ static void TLSRecv(DPS_NetConnection* cn)
switch (cn->state) {
case CN_OPEN:
cn->state = CN_CLOSE_NOTIFIED;
+ DPS_DBGPRINT("OPEN -> CLOSE_NOTIFIED cn=%p\n", cn);
case CN_CLOSE_NOTIFIED:
case CN_CLOSING:
break;
@@ -1215,11 +1268,10 @@ static void TLSRecv(DPS_NetConnection* cn)
status = DPS_ERR_EOF;
} else if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
DPS_DBGPRINT("Want read cn=%p\n", cn);
- goto Exit;
- } else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
- DPS_DBGPRINT("Want write cn=%p\n", cn);
+ ret = 0;
goto Exit;
} else {
+ assert(ret != MBEDTLS_ERR_SSL_WANT_WRITE); /* Writes never block */
DPS_WARNPRINT("Failed - %s\n", TLSErrTxt(ret));
status = DPS_ERR_NETWORK;
}
@@ -1231,7 +1283,7 @@ static void TLSRecv(DPS_NetConnection* cn)
status = DPS_OK;
}
- ret = netCtx->receiveCB(netCtx->node, &cn->peer, status, buf);
+ netCtx->receiveCB(netCtx->node, &cn->peer, status, buf);
/*
* See comment in TLSHandshake about holding onto a reference
@@ -1240,16 +1292,17 @@ static void TLSRecv(DPS_NetConnection* cn)
*/
if (cn->handshake == MBEDTLS_ERR_SSL_WANT_READ) {
assert(cn->refCount > 1);
- DPS_NetConnectionDecRef(cn);
+ ConnectionDecRef(cn);
cn->handshake = 0;
}
Exit:
DPS_NetRxBufferDecRef(buf);
- DPS_NetConnectionDecRef(cn);
+ ConnectionDecRef(cn);
+ return ret;
}
-static int TLSHandshake(DPS_NetConnection* cn)
+static int TLSHandshake(DPS_NetDtlsConnection* cn)
{
int ret;
@@ -1268,14 +1321,14 @@ static int TLSHandshake(DPS_NetConnection* cn)
switch (cn->handshake) {
case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED:
case MBEDTLS_ERR_SSL_WANT_READ:
- case MBEDTLS_ERR_SSL_WANT_WRITE:
break;
default:
- DPS_NetConnectionIncRef(cn);
+ ConnectionIncRef(cn);
break;
}
ret = mbedtls_ssl_handshake(&cn->ssl);
+ assert(ret != MBEDTLS_ERR_SSL_WANT_WRITE); /* Writes never block */
cn->handshake = ret;
if (ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) {
@@ -1289,7 +1342,7 @@ static int TLSHandshake(DPS_NetConnection* cn)
}
/*
- * The two cases below just let us know that handshake is waiting for more
+ * The case below just lets us know that handshake is waiting for more
* data to be sent or received.
*/
if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
@@ -1297,11 +1350,6 @@ static int TLSHandshake(DPS_NetConnection* cn)
ret = 0;
goto Exit;
}
- if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
- DPS_DBGPRINT("Want write cn=%p\n", cn);
- ret = 0;
- goto Exit;
- }
/*
* The configured authmode (verify required) will result in
@@ -1333,32 +1381,37 @@ static int TLSHandshake(DPS_NetConnection* cn)
switch (cn->handshake) {
case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED:
case MBEDTLS_ERR_SSL_WANT_READ:
- case MBEDTLS_ERR_SSL_WANT_WRITE:
break;
default:
- DPS_NetConnectionDecRef(cn);
+ ConnectionDecRef(cn);
break;
}
- return !ret;
+ return ret;
}
-static void ConsumePending(DPS_NetConnection* cn)
+static void ConsumePending(DPS_NetDtlsConnection* cn)
{
assert(cn->handshakeDone);
while (!DPS_QueueEmpty(&cn->recvQueue)) {
- TLSRecv(cn);
+ int ret = TLSRecv(cn);
+ if (ret != 0) {
+ goto Exit;
+ }
}
while (!DPS_QueueEmpty(&cn->sendQueue)) {
TLSSend(cn);
}
+
+Exit:
+ CancelPending(cn);
}
static void OnUdpData(uv_udp_t* socket, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags)
{
- DPS_NetContext* netCtx = socket->data;
+ DPS_NetDtlsContext* netCtx = socket->data;
RecvData* data = NULL;
DPS_NodeAddress* nodeAddr = NULL;
- DPS_NetConnection* cn;
+ DPS_NetDtlsConnection* cn;
DPS_DBGTRACEA("nread=%d,addr=%s\n", nread, DPS_NetAddrText(addr));
@@ -1411,7 +1464,7 @@ static void OnUdpData(uv_udp_t* socket, ssize_t nread, const uv_buf_t* buf, cons
goto Exit;
}
cn->peer.addr = *nodeAddr;
- cn->peer.cn = cn;
+ cn->peer.cn = (DPS_NetConnection*)cn;
} else {
DPS_DBGPRINT("Found cn=%p,peerAddr=%s\n", cn, DPS_NodeAddrToString(cn->peerAddr));
}
@@ -1426,17 +1479,20 @@ static void OnUdpData(uv_udp_t* socket, ssize_t nread, const uv_buf_t* buf, cons
DPS_QueuePushBack(&cn->recvQueue, &data->queue);
data = NULL;
- DPS_NetConnectionIncRef(cn);
+ ConnectionIncRef(cn);
if (!cn->handshakeDone) {
int ret = TLSHandshake(cn);
- if (ret == DPS_TRUE && cn->handshakeDone) {
+ if (ret == 0 && cn->handshakeDone) {
ConsumePending(cn);
- } else if (ret == DPS_FALSE) {
+ } else if (ret != 0) {
CancelPending(cn);
}
} else {
- TLSRecv(cn);
+ int ret = TLSRecv(cn);
+ if (ret != 0) {
+ CancelPending(cn);
+ }
}
Exit:
@@ -1444,19 +1500,23 @@ static void OnUdpData(uv_udp_t* socket, ssize_t nread, const uv_buf_t* buf, cons
DPS_DestroyAddress(nodeAddr);
}
-DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_OnReceive cb)
+DPS_NetContext* DPS_NetDtlsStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_OnReceive cb)
{
+ static struct sockaddr_storage sszero = { 0 };
int ret;
- DPS_NetContext* netCtx;
+ DPS_NetDtlsContext* netCtx;
struct sockaddr* sa;
DPS_NodeAddress any;
DPS_DBGTRACEA("node=%p,addr=%s,cb=%p\n", node, DPS_NodeAddrToString(addr), cb);
- netCtx = calloc(1, sizeof(DPS_NetContext));
+ netCtx = calloc(1, sizeof(DPS_NetDtlsContext));
if (!netCtx) {
return NULL;
}
+ netCtx->ctx.getListenAddress = DPS_NetDtlsGetListenAddress;
+ netCtx->ctx.stop = DPS_NetDtlsStop;
+ netCtx->ctx.send = DPS_NetDtlsSend;
ret = uv_udp_init(node->loop, &netCtx->rxSocket);
if (ret) {
DPS_ERRPRINT("UDP init failed: %s\n", uv_err_name(ret));
@@ -1468,10 +1528,10 @@ DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_On
netCtx->handshakeTimeoutMax = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX;
netCtx->node = node;
netCtx->receiveCB = cb;
- if (addr) {
+ if (addr && memcmp(&addr->u.inaddr, &sszero, sizeof(struct sockaddr_storage))) {
sa = (struct sockaddr*)&addr->u.inaddr;
} else {
- if (!DPS_SetAddress(&any, "[::]:0")) {
+ if (!DPS_SetAddress(&any, "dtls", "[::]:0")) {
goto ErrorExit;
}
sa = (struct sockaddr*)&any.u.inaddr;
@@ -1490,7 +1550,7 @@ DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_On
netCtx->state = NET_RUNNING;
DPS_DBGPRINT("Created netCtx=%p\n", netCtx);
- return netCtx;
+ return (DPS_NetContext*)netCtx;
ErrorExit:
DPS_ERRPRINT("Net start failed- %s\n", uv_err_name(ret));
@@ -1498,8 +1558,9 @@ DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_On
return NULL;
}
-DPS_NodeAddress* DPS_NetGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext* netCtx)
+DPS_NodeAddress* DPS_NetDtlsGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext* ctx)
{
+ DPS_NetDtlsContext* netCtx = (DPS_NetDtlsContext*)ctx;
int len;
DPS_DBGTRACEA("netCtx=%p\n", netCtx);
@@ -1517,9 +1578,10 @@ DPS_NodeAddress* DPS_NetGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext*
return addr;
}
-void DPS_NetStop(DPS_NetContext* netCtx)
+void DPS_NetDtlsStop(DPS_NetContext* ctx)
{
- DPS_NetConnection* cns;
+ DPS_NetDtlsContext* netCtx = (DPS_NetDtlsContext*)ctx;
+ DPS_NetDtlsConnection* cns;
DPS_DBGTRACEA("netCtx=%p\n", netCtx);
@@ -1535,9 +1597,9 @@ void DPS_NetStop(DPS_NetContext* netCtx)
*/
cns = netCtx->cns;
while (cns) {
- DPS_NetConnection* cn = cns;
+ DPS_NetDtlsConnection* cn = cns;
cns = cns->next;
- CancelPending(cn);
+ CancelPendingSend(cn);
}
/*
* When no connections are active we can close the rxSocket
@@ -1551,10 +1613,11 @@ void DPS_NetStop(DPS_NetContext* netCtx)
}
}
-DPS_Status DPS_NetSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf_t* bufs, size_t numBufs,
- DPS_NetSendComplete sendCompleteCB)
+DPS_Status DPS_NetDtlsSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf_t* bufs,
+ size_t numBufs, DPS_NetSendComplete sendCompleteCB)
{
SendRequest* req;
+ DPS_NetDtlsConnection* cn = NULL;
DPS_DBGTRACEA("node=%p,appCtx=%p,ep={addr=%s,cn=%p},bufs=%p,numBufs=%p,sendCompleteCB=%p\n",
node, appCtx, DPS_NodeAddrToString(&ep->addr), ep->cn, bufs, numBufs, sendCompleteCB);
@@ -1576,22 +1639,23 @@ DPS_Status DPS_NetSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf
}
if (ep->cn) {
+ cn = (DPS_NetDtlsConnection*)ep->cn;
int queueEmpty;
- req->cn = ep->cn;
- queueEmpty= DPS_QueueEmpty(&ep->cn->sendQueue);
- DPS_QueuePushBack(&ep->cn->sendQueue, &req->queue);
- DPS_NetConnectionIncRef(ep->cn);
- if (queueEmpty && ep->cn->handshakeDone) {
- TLSSend(ep->cn);
+ req->cn = cn;
+ queueEmpty= DPS_QueueEmpty(&cn->sendQueue);
+ DPS_QueuePushBack(&cn->sendQueue, &req->queue);
+ ConnectionIncRef(cn);
+ if (queueEmpty && cn->handshakeDone) {
+ TLSSend(cn);
}
return DPS_OK;
}
- ep->cn = CreateConnection(node, (const struct sockaddr*)&ep->addr.u.inaddr, MBEDTLS_SSL_IS_CLIENT);
- if (!ep->cn) {
+ cn = CreateConnection(node, (const struct sockaddr*)&ep->addr.u.inaddr, MBEDTLS_SSL_IS_CLIENT);
+ if (!cn) {
goto ErrorExit;
}
- ep->cn->peer = *ep;
- if (!TLSHandshake(ep->cn)) {
+ cn->peer = *ep;
+ if (TLSHandshake(cn) != 0) {
goto ErrorExit;
}
/*
@@ -1599,49 +1663,46 @@ DPS_Status DPS_NetSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf
* return DPS_OK (the send complete callback should not be called
* if DPS_NetSend returns an error).
*/
- req->cn = ep->cn;
- DPS_QueuePushBack(&ep->cn->sendQueue, &req->queue);
+ req->cn = cn;
+ DPS_QueuePushBack(&cn->sendQueue, &req->queue);
req = NULL;
- DPS_NetConnectionIncRef(ep->cn);
- if (ep->cn->handshakeDone) {
- ConsumePending(ep->cn);
+ ConnectionIncRef(cn);
+ if (cn->handshakeDone) {
+ ConsumePending(cn);
}
/* The caller gets a ref count to own. */
- DPS_NetConnectionIncRef(ep->cn);
+ ConnectionIncRef(cn);
+ ep->cn = (DPS_NetConnection*)cn;
return DPS_OK;
ErrorExit:
DestroySendRequest(req);
- if (ep->cn && ep->cn->refCount == 0) {
- DestroyConnection(ep->cn);
+ if (cn && cn->refCount == 0) {
+ DestroyConnection(cn);
}
ep->cn = NULL;
return DPS_ERR_NETWORK;
}
-void DPS_NetConnectionIncRef(DPS_NetConnection* cn)
+void DPS_NetDtlsConnectionIncRef(DPS_NetConnection* cn)
{
- if (cn) {
- DPS_DBGTRACEA("cn=%p\n", cn);
- ++cn->refCount;
- }
+ ConnectionIncRef((DPS_NetDtlsConnection*)cn);
}
-void DPS_NetConnectionDecRef(DPS_NetConnection* cn)
+void DPS_NetDtlsConnectionDecRef(DPS_NetConnection* cn)
{
- if (cn) {
- DPS_DBGTRACEA("cn=%p\n", cn);
- assert(cn->refCount > 0);
- if (--cn->refCount == 0) {
- DestroyConnection(cn);
- }
- }
+ ConnectionDecRef((DPS_NetDtlsConnection*)cn);
}
+DPS_NetTransport DPS_NetDtlsTransport = {
+ DPS_DTLS,
+ DPS_NetDtlsStart
+};
+
#ifdef DPS_USE_FUZZ
uv_udp_recv_cb Fuzz_OnData(DPS_Node* node, uv_udp_recv_cb cb)
{
- DPS_NetContext* netCtx = node->netCtx;
+ DPS_NetDtlsContext* netCtx = (DPS_NetDtlsContext*)node->netCtx;
uv_udp_recv_cb ret;
/*
diff --git a/src/fuzzer/network.c b/src/fuzzer/network.c
index 7d4b4bbf..3fea4a65 100644
--- a/src/fuzzer/network.c
+++ b/src/fuzzer/network.c
@@ -31,10 +31,11 @@
*/
DPS_DEBUG_CONTROL(DPS_DEBUG_ON);
-struct _DPS_NetContext {
+typedef struct _DPS_NetFuzzerContext {
+ DPS_NetContext ctx;
DPS_Node* node;
DPS_OnReceive receiveCB;
-};
+} DPS_NetFuzzerContext;
struct _DPS_MulticastReceiver {
DPS_Node* node;
@@ -45,24 +46,32 @@ struct _DPS_MulticastSender {
DPS_Node* node;
};
-DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_OnReceive cb)
+DPS_NodeAddress* DPS_NetFuzzerGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext* netCtx);
+void DPS_NetFuzzerStop(DPS_NetContext* netCtx);
+DPS_Status DPS_NetFuzzerSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* endpoint, uv_buf_t* bufs,
+ size_t numBufs, DPS_NetSendComplete sendCompleteCB);
+
+DPS_NetContext* DPS_NetFuzzerStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_OnReceive cb)
{
- DPS_NetContext* netCtx = NULL;
+ DPS_NetFuzzerContext* netCtx = NULL;
- netCtx = malloc(sizeof(DPS_NetContext));
+ netCtx = malloc(sizeof(DPS_NetFuzzerContext));
if (netCtx) {
+ netCtx->ctx.getListenAddress = DPS_NetFuzzerGetListenAddress;
+ netCtx->ctx.stop = DPS_NetFuzzerStop;
+ netCtx->ctx.send = DPS_NetFuzzerSend;
netCtx->node = node;
netCtx->receiveCB = cb;
}
- return netCtx;
+ return (DPS_NetContext*)netCtx;
}
-void DPS_NetStop(DPS_NetContext* netCtx)
+void DPS_NetFuzzerStop(DPS_NetContext* netCtx)
{
free(netCtx);
}
-DPS_NodeAddress* DPS_NetGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext* netCtx)
+DPS_NodeAddress* DPS_NetFuzzerGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext* netCtx)
{
struct sockaddr_in6* saddr;
@@ -75,20 +84,17 @@ DPS_NodeAddress* DPS_NetGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext*
return addr;
}
-DPS_Status DPS_NetSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* endpoint,
- uv_buf_t* bufs, size_t numBufs,
- DPS_NetSendComplete sendCompleteCB)
+DPS_Status DPS_NetFuzzerSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* endpoint,
+ uv_buf_t* bufs, size_t numBufs,
+ DPS_NetSendComplete sendCompleteCB)
{
return DPS_ERR_NOT_IMPLEMENTED;
}
-void DPS_NetConnectionIncRef(DPS_NetConnection* cn)
-{
-}
-
-void DPS_NetConnectionDecRef(DPS_NetConnection* cn)
-{
-}
+DPS_NetTransport DPS_NetFuzzerTransport = {
+ DPS_UNKNOWN,
+ DPS_NetFuzzerStart
+};
DPS_MulticastReceiver* DPS_MulticastStartReceive(DPS_Node* node, DPS_OnReceive cb)
{
@@ -130,6 +136,7 @@ DPS_Status DPS_MulticastSend(DPS_MulticastSender* sender, void* appCtx, uv_buf_t
void Fuzz_OnNetReceive(DPS_Node* node, const uint8_t* data, size_t len)
{
+ DPS_NetFuzzerContext* netCtx = (DPS_NetFuzzerContext*)node->netCtx;
DPS_NetEndpoint ep;
struct sockaddr_in sa;
DPS_NetRxBuffer* buf;
@@ -144,7 +151,7 @@ void Fuzz_OnNetReceive(DPS_Node* node, const uint8_t* data, size_t len)
return;
}
memcpy(buf->rx.rxPos, data, len);
- node->netCtx->receiveCB(node, &ep, DPS_OK, buf);
+ netCtx->receiveCB(node, &ep, DPS_OK, buf);
DPS_NetRxBufferDecRef(buf);
}
diff --git a/src/multicast/network.c b/src/multicast/network.c
index 72024595..a762eeb8 100644
--- a/src/multicast/network.c
+++ b/src/multicast/network.c
@@ -40,6 +40,7 @@ DPS_DEBUG_CONTROL(DPS_DEBUG_ON);
struct _DPS_MulticastReceiver {
uint8_t ipVersions;
+ uint16_t port;
uv_udp_t udp6Rx;
uv_udp_t udp4Rx;
DPS_Node* node;
@@ -53,11 +54,28 @@ typedef struct {
struct _DPS_MulticastSender {
uint8_t ipVersions;
+ uint16_t port;
TxSocket* udpTx; /* Array of Tx sockets - one per interface */
size_t numTx; /* Number of Tx sockets */
DPS_Node* node;
};
+static uint16_t GetPort(void)
+{
+ char str[DPS_MAX_SERVICE_LEN + 1];
+ size_t sz = DPS_MAX_SERVICE_LEN + 1;
+ char* endp;
+ uint16_t port;
+
+ if (uv_os_getenv("DPS_MCAST_PORT", str, &sz) == 0) {
+ port = strtol(str, &endp, 10);
+ if (*endp == 0) {
+ return port;
+ }
+ }
+ return COAP_UDP_PORT;
+}
+
static int UseInterface(uint8_t ipVersions, uv_interface_address_t* ifn)
{
if (ifn->is_internal) {
@@ -129,7 +147,7 @@ static DPS_Status MulticastRxInit(DPS_MulticastReceiver* receiver)
int numIfs = 0;
int i;
- DPS_DBGPRINT("MulticastRxInit UDP port %d\n", COAP_UDP_PORT);
+ DPS_DBGPRINT("MulticastRxInit UDP port %d\n", receiver->port);
/*
* Initialize v4 udp multicast listener
@@ -137,7 +155,7 @@ static DPS_Status MulticastRxInit(DPS_MulticastReceiver* receiver)
if (receiver->ipVersions & USE_IPV4) {
ret = uv_udp_init(uv, &receiver->udp4Rx);
assert(ret == 0);
- ret = uv_ip4_addr("0.0.0.0", COAP_UDP_PORT, (struct sockaddr_in*)&recv_addr);
+ ret = uv_ip4_addr("0.0.0.0", receiver->port, (struct sockaddr_in*)&recv_addr);
ret = uv_udp_bind(&receiver->udp4Rx, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR);
if (ret) {
DPS_ERRPRINT("UDP IPv6 bind failed %s\n", uv_err_name(ret));
@@ -150,7 +168,7 @@ static DPS_Status MulticastRxInit(DPS_MulticastReceiver* receiver)
if (receiver->ipVersions & USE_IPV6) {
ret = uv_udp_init(uv, &receiver->udp6Rx);
if (ret == 0) {
- ret = uv_ip6_addr("::", COAP_UDP_PORT, (struct sockaddr_in6*)&recv_addr);
+ ret = uv_ip6_addr("::", receiver->port, (struct sockaddr_in6*)&recv_addr);
}
if (ret == 0) {
ret = uv_udp_bind(&receiver->udp6Rx, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR);
@@ -214,6 +232,7 @@ DPS_MulticastReceiver* DPS_MulticastStartReceive(DPS_Node* node, DPS_OnReceive c
return NULL;
}
receiver->ipVersions = USE_IPV6 | USE_IPV4;
+ receiver->port = GetPort();
receiver->cb = cb;
receiver->node = node;
@@ -351,6 +370,7 @@ DPS_MulticastSender* DPS_MulticastStartSend(DPS_Node* node)
return NULL;
}
sender->ipVersions = USE_IPV6 | USE_IPV4;
+ sender->port = GetPort();
sender->node = node;
ret = MulticastTxInit(sender);
@@ -474,9 +494,9 @@ DPS_Status DPS_MulticastSend(DPS_MulticastSender* sender, void* appCtx, uv_buf_t
struct sockaddr_storage addr;
uv_udp_send_t* sendReq;
if (sender->udpTx[i].family == AF_INET6) {
- ret = uv_ip6_addr(COAP_MCAST_ALL_NODES_LINK_LOCAL_6, COAP_UDP_PORT, (struct sockaddr_in6*)&addr);
+ ret = uv_ip6_addr(COAP_MCAST_ALL_NODES_LINK_LOCAL_6, sender->port, (struct sockaddr_in6*)&addr);
} else {
- ret = uv_ip4_addr(COAP_MCAST_ALL_NODES_LINK_LOCAL_4, COAP_UDP_PORT, (struct sockaddr_in*)&addr);
+ ret = uv_ip4_addr(COAP_MCAST_ALL_NODES_LINK_LOCAL_4, sender->port, (struct sockaddr_in*)&addr);
}
if (ret) {
continue;
diff --git a/src/network.c b/src/network.c
index 2af6c4a1..759e042e 100644
--- a/src/network.c
+++ b/src/network.c
@@ -294,7 +294,7 @@ static DPS_Status GetScope(const char* host, const char* service, struct sockadd
return err ? DPS_ERR_NETWORK : DPS_OK;
}
-DPS_NodeAddress* DPS_SetAddress(DPS_NodeAddress* addr, const char* addrText)
+DPS_NodeAddress* DPS_SetAddress(DPS_NodeAddress* addr, const char* network, const char* addrText)
{
char host[DPS_MAX_HOST_LEN + 1];
char service[DPS_MAX_SERVICE_LEN + 1];
@@ -302,35 +302,31 @@ DPS_NodeAddress* DPS_SetAddress(DPS_NodeAddress* addr, const char* addrText)
DPS_DBGTRACE();
- if (!addr || !addrText) {
+ if (!addr) {
goto ErrorExit;
}
memset(addr, 0, sizeof(DPS_NodeAddress));
-#if defined(DPS_USE_DTLS)
- addr->type = DPS_DTLS;
-#elif defined(DPS_USE_TCP)
- addr->type = DPS_TCP;
-#elif defined(DPS_USE_UDP)
- addr->type = DPS_UDP;
-#elif defined(DPS_USE_PIPE)
- addr->type = DPS_PIPE;
-#endif
+ addr->type = DPS_NetAddressType(network);
switch (addr->type) {
case DPS_DTLS:
case DPS_TCP:
case DPS_UDP:
- ret = DPS_SplitAddress(addrText, host, sizeof(host), service, sizeof(service));
- if (ret != DPS_OK) {
- goto ErrorExit;
- }
- ret = GetScope(host, service, &addr->u.inaddr);
- if (ret != DPS_OK) {
- goto ErrorExit;
+ if (addrText) {
+ ret = DPS_SplitAddress(addrText, host, sizeof(host), service, sizeof(service));
+ if (ret != DPS_OK) {
+ goto ErrorExit;
+ }
+ ret = GetScope(host, service, &addr->u.inaddr);
+ if (ret != DPS_OK) {
+ goto ErrorExit;
+ }
}
return addr;
case DPS_PIPE:
- strncpy(addr->u.path, addrText, DPS_NODE_ADDRESS_PATH_MAX - 1);
+ if (addrText) {
+ strncpy(addr->u.path, addrText, DPS_NODE_ADDRESS_PATH_MAX - 1);
+ }
return addr;
default:
break;
@@ -495,3 +491,96 @@ void DPS_NetRxBufferDecRef(DPS_NetRxBuffer* buf)
}
}
}
+
+static const DPS_NodeAddressType AddressDefaultType =
+#if defined(DPS_USE_UDP)
+ DPS_UDP
+#elif defined(DPS_USE_TCP)
+ DPS_TCP
+#elif defined(DPS_USE_PIPE)
+ DPS_PIPE
+#elif defined(DPS_USE_DTLS)
+ DPS_DTLS
+#else
+ DPS_UNKNOWN
+#endif
+ ;
+
+DPS_NodeAddressType DPS_NetAddressType(const char* network)
+{
+ if (!network) {
+ return AddressDefaultType;
+ } else if (!strcmp(network, "dtls")) {
+ return DPS_DTLS;
+ } else if (!strcmp(network, "tcp")) {
+ return DPS_TCP;
+ } else if (!strcmp(network, "udp")) {
+ return DPS_UDP;
+ } else if (!strcmp(network, "pipe")) {
+ return DPS_PIPE;
+ } else {
+ return DPS_UNKNOWN;
+ }
+}
+
+DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_OnReceive cb)
+{
+ DPS_NodeAddressType type = addr ? addr->type : AddressDefaultType;
+
+ switch (type) {
+#ifdef DPS_USE_DTLS
+ case DPS_DTLS:
+ return DPS_NetDtlsTransport.start(node, addr, cb);
+#endif
+#ifdef DPS_USE_TCP
+ case DPS_TCP:
+ return DPS_NetTcpTransport.start(node, addr, cb);
+#endif
+#ifdef DPS_USE_UDP
+ case DPS_UDP:
+ return DPS_NetUdpTransport.start(node, addr, cb);
+#endif
+#ifdef DPS_USE_PIPE
+ case DPS_PIPE:
+ return DPS_NetPipeTransport.start(node, addr, cb);
+#endif
+
+#if defined(DPS_USE_FUZZ) && !defined(DPS_USE_DTLS)
+ case DPS_UNKNOWN:
+ return DPS_NetFuzzerTransport.start(node, addr, cb);
+#endif
+
+ default:
+ return NULL;
+ }
+}
+
+DPS_NodeAddress* DPS_NetGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext* netCtx)
+{
+ return netCtx->getListenAddress(addr, netCtx);
+}
+
+void DPS_NetStop(DPS_NetContext* netCtx)
+{
+ netCtx->stop(netCtx);
+}
+
+DPS_Status DPS_NetSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* endpoint, uv_buf_t* bufs,
+ size_t numBufs, DPS_NetSendComplete sendCompleteCB)
+{
+ return node->netCtx->send(node, appCtx, endpoint, bufs, numBufs, sendCompleteCB);
+}
+
+void DPS_NetConnectionIncRef(DPS_NetConnection* cn)
+{
+ if (cn) {
+ cn->incRef(cn);
+ }
+}
+
+void DPS_NetConnectionDecRef(DPS_NetConnection* cn)
+{
+ if (cn) {
+ cn->decRef(cn);
+ }
+}
diff --git a/src/node.h b/src/node.h
index 9e7c5871..044ba1c4 100644
--- a/src/node.h
+++ b/src/node.h
@@ -70,11 +70,6 @@ typedef struct _LinkMonitor LinkMonitor;
*/
typedef struct _OnOpCompletion OnOpCompletion;
-/**
- * Context for network address resolution
- */
-typedef struct _ResolverInfo ResolverInfo;
-
/**
* Link monitor configuration values. All times are in milliseconds.
*/
@@ -141,7 +136,7 @@ typedef struct _DPS_Node {
LinkMonitorConfig linkMonitorConfig; /**< Configuration parameters for mesh probe publications */
uv_async_t resolverAsync; /**< Async handler for address resolver */
- ResolverInfo* resolverList; /**< Linked list of address resolution requests */
+ DPS_Queue resolverQueue; /**< Queue of address resolution requests */
} DPS_Node;
diff --git a/src/pipe/network.c b/src/pipe/network.c
index 23805e13..1b631618 100644
--- a/src/pipe/network.c
+++ b/src/pipe/network.c
@@ -45,26 +45,32 @@
*/
DPS_DEBUG_CONTROL(DPS_DEBUG_ON);
+typedef struct _DPS_NetPipeConnection DPS_NetPipeConnection;
+
+#define SIZEOF_HEADER CBOR_SIZEOF(uint32_t) + \
+ CBOR_SIZEOF_STRING_AND_LENGTH(DPS_NODE_ADDRESS_PATH_MAX)
+
typedef struct _SendRequest {
DPS_Queue queue;
- DPS_NetConnection* cn;
+ DPS_NetPipeConnection* cn;
uv_write_t writeReq;
DPS_NetSendComplete onSendComplete;
void* appCtx;
DPS_Status status;
size_t numBufs;
- uint8_t lenBuf[CBOR_SIZEOF(uint32_t)]; /* pre-allocated buffer for serializing message length */
+ uint8_t hdrBuf[SIZEOF_HEADER]; /* pre-allocated buffer for serializing message header */
uv_buf_t bufs[1];
} SendRequest;
-typedef struct _DPS_NetConnection {
+typedef struct _DPS_NetPipeConnection {
+ DPS_NetConnection cn;
DPS_Node* node;
uv_pipe_t socket;
DPS_NetEndpoint peerEp;
int refCount;
uv_shutdown_t shutdownReq;
/* Rx side */
- uint8_t lenBuf[CBOR_SIZEOF(uint32_t)]; /* pre-allocated buffer for deserializing message length */
+ uint8_t hdrBuf[SIZEOF_HEADER]; /* pre-allocated buffer for deserializing message header */
size_t readLen; /* how much data has already been read */
DPS_NetRxBuffer* msgBuf;
/* Tx side */
@@ -72,27 +78,52 @@ typedef struct _DPS_NetConnection {
DPS_Queue sendQueue;
DPS_Queue sendCompletedQueue;
uv_idle_t idle;
-} DPS_NetConnection;
+} DPS_NetPipeConnection;
-struct _DPS_NetContext {
+typedef struct _DPS_NetPipeContext {
+ DPS_NetContext ctx;
uv_pipe_t socket; /* the listen socket */
DPS_Node* node;
DPS_OnReceive receiveCB;
-};
+} DPS_NetPipeContext;
-#define MIN_BUF_ALLOC_SIZE 512
-#define MIN_READ_SIZE CBOR_SIZEOF(uint32_t)
+DPS_NodeAddress* DPS_NetPipeGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext* netCtx);
+void DPS_NetPipeStop(DPS_NetContext* netCtx);
+DPS_Status DPS_NetPipeSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf_t* bufs, size_t numBufs,
+ DPS_NetSendComplete sendCompleteCB);
+void DPS_NetPipeConnectionIncRef(DPS_NetConnection* cn);
+void DPS_NetPipeConnectionDecRef(DPS_NetConnection* cn);
+static void Shutdown(DPS_NetPipeConnection* cn);
+
+static void ConnectionIncRef(DPS_NetPipeConnection* cn)
+{
+ if (cn) {
+ DPS_DBGTRACE();
+ ++cn->refCount;
+ }
+}
+
+static void ConnectionDecRef(DPS_NetPipeConnection* cn)
+{
+ if (cn) {
+ DPS_DBGTRACE();
+ assert(cn->refCount > 0);
+ if (--cn->refCount == 0) {
+ Shutdown(cn);
+ }
+ }
+}
static void AllocBuffer(uv_handle_t* handle, size_t suggestedSize, uv_buf_t* buf)
{
- DPS_NetConnection* cn = (DPS_NetConnection*)handle->data;
+ DPS_NetPipeConnection* cn = (DPS_NetPipeConnection*)handle->data;
if (cn->msgBuf) {
buf->len = DPS_RxBufferAvail(&cn->msgBuf->rx);
buf->base = (char*)cn->msgBuf->rx.rxPos;
} else {
- buf->len = (uint32_t)(sizeof(cn->lenBuf) - cn->readLen);
- buf->base = (char*)(cn->lenBuf + cn->readLen);
+ buf->len = (uint32_t)(sizeof(cn->hdrBuf) - cn->readLen);
+ buf->base = (char*)(cn->hdrBuf + cn->readLen);
}
}
@@ -102,7 +133,7 @@ static void ListenSocketClosed(uv_handle_t* handle)
free(handle->data);
}
-static void CancelPendingSends(DPS_NetConnection* cn)
+static void CancelPendingSends(DPS_NetPipeConnection* cn)
{
while (!DPS_QueueEmpty(&cn->sendQueue)) {
SendRequest* req = (SendRequest*)DPS_QueueFront(&cn->sendQueue);
@@ -113,7 +144,7 @@ static void CancelPendingSends(DPS_NetConnection* cn)
}
}
-static void SendCompleted(DPS_NetConnection* cn)
+static void SendCompleted(DPS_NetPipeConnection* cn)
{
while (!DPS_QueueEmpty(&cn->sendCompletedQueue)) {
SendRequest* req = (SendRequest*)DPS_QueueFront(&cn->sendCompletedQueue);
@@ -126,12 +157,12 @@ static void SendCompleted(DPS_NetConnection* cn)
static void SendCompletedTask(uv_idle_t* idle)
{
- DPS_NetConnection* cn = idle->data;
+ DPS_NetPipeConnection* cn = idle->data;
SendCompleted(cn);
uv_idle_stop(idle);
}
-static void FreeConnection(DPS_NetConnection* cn)
+static void FreeConnection(DPS_NetPipeConnection* cn)
{
/*
* Free memory for any pending sends
@@ -145,13 +176,13 @@ static void FreeConnection(DPS_NetConnection* cn)
static void IdleClosed(uv_handle_t* handle)
{
- DPS_NetConnection* cn = handle->data;
+ DPS_NetPipeConnection* cn = handle->data;
FreeConnection(cn);
}
static void StreamClosed(uv_handle_t* handle)
{
- DPS_NetConnection* cn = (DPS_NetConnection*)handle->data;
+ DPS_NetPipeConnection* cn = (DPS_NetPipeConnection*)handle->data;
DPS_DBGPRINT("Closed stream handle %p\n", handle);
if (!uv_is_closing((uv_handle_t*)&cn->idle)) {
@@ -161,7 +192,7 @@ static void StreamClosed(uv_handle_t* handle)
static void OnShutdownComplete(uv_shutdown_t* req, int status)
{
- DPS_NetConnection* cn = (DPS_NetConnection*)req->data;
+ DPS_NetPipeConnection* cn = (DPS_NetPipeConnection*)req->data;
DPS_DBGPRINT("Shutdown complete handle %p\n", req->handle);
if (!uv_is_closing((uv_handle_t*)req->handle)) {
@@ -170,7 +201,7 @@ static void OnShutdownComplete(uv_shutdown_t* req, int status)
}
}
-static void Shutdown(DPS_NetConnection* cn)
+static void Shutdown(DPS_NetPipeConnection* cn)
{
if (!cn->shutdownReq.data) {
int r;
@@ -191,10 +222,13 @@ static void Shutdown(DPS_NetConnection* cn)
static void OnData(uv_stream_t* socket, ssize_t nread, const uv_buf_t* buf)
{
DPS_Status ret = DPS_OK;
- DPS_NetConnection* cn = (DPS_NetConnection*)socket->data;
- DPS_NetContext* netCtx = cn->node->netCtx;
+ DPS_NetPipeConnection* cn = (DPS_NetPipeConnection*)socket->data;
+ DPS_NetPipeContext* netCtx = (DPS_NetPipeContext*)cn->node->netCtx;
+ DPS_RxBuffer hdrBuf;
DPS_DBGTRACE();
+
+ DPS_RxBufferClear(&hdrBuf);
/*
* netCtx will be null if we are shutting down
*/
@@ -208,86 +242,108 @@ static void OnData(uv_stream_t* socket, ssize_t nread, const uv_buf_t* buf)
return;
}
if (nread < 0) {
- uv_read_stop(socket);
- netCtx->receiveCB(cn->node, &cn->peerEp, nread == UV_EOF ? DPS_ERR_EOF : DPS_ERR_NETWORK, NULL);
- return;
+ ret = nread == UV_EOF ? DPS_ERR_EOF : DPS_ERR_NETWORK;
+ goto Done;
}
assert(socket == (uv_stream_t*)&cn->socket);
- /*
- * Parse out the message length
- */
- if (!cn->msgBuf) {
- DPS_RxBuffer lenBuf;
- uint32_t msgLen;
+ while (nread && (ret == DPS_OK)) {
/*
- * Keep reading if we don't have enough data to parse the length
+ * Parse out the message length
*/
- cn->readLen += nread;
- if (cn->readLen < MIN_READ_SIZE) {
- return;
- }
- assert(cn->readLen == MIN_READ_SIZE);
- DPS_RxBufferInit(&lenBuf, cn->lenBuf, cn->readLen);
- ret = CBOR_DecodeUint32(&lenBuf, &msgLen);
- if (ret == DPS_OK) {
+ if (!cn->msgBuf) {
+ uint32_t msgLen;
+ uint8_t* pos;
+ char* path;
+ size_t size;
+ cn->readLen += nread;
+ DPS_RxBufferInit(&hdrBuf, cn->hdrBuf, cn->readLen);
+ ret = CBOR_DecodeUint32(&hdrBuf, &msgLen);
+ if (ret == DPS_ERR_EOD) {
+ /*
+ * Keep reading if we don't have enough data to parse the length
+ */
+ return;
+ } else if (ret != DPS_OK) {
+ goto Done;
+ }
+ pos = hdrBuf.rxPos;
+ ret = CBOR_DecodeString(&hdrBuf, &path, &size);
+ if (ret == DPS_ERR_EOD) {
+ return;
+ } else if (ret != DPS_OK) {
+ goto Done;
+ }
+ if (memcpy_s(cn->peerEp.addr.u.path, DPS_NODE_ADDRESS_PATH_MAX, path, size) != EOK) {
+ ret = DPS_ERR_INVALID;
+ goto Done;
+ }
+ cn->peerEp.addr.type = DPS_PIPE;
+ msgLen -= hdrBuf.rxPos - pos;
cn->msgBuf = DPS_CreateNetRxBuffer(msgLen);
if (cn->msgBuf) {
/*
* Copy message bytes if any
*/
- memcpy(cn->msgBuf->rx.rxPos, lenBuf.rxPos, DPS_RxBufferAvail(&lenBuf));
- cn->msgBuf->rx.rxPos += DPS_RxBufferAvail(&lenBuf);
+ size = (msgLen < DPS_RxBufferAvail(&hdrBuf)) ? msgLen : DPS_RxBufferAvail(&hdrBuf);
+ memcpy(cn->msgBuf->rx.rxPos, hdrBuf.rxPos, size);
+ cn->msgBuf->rx.rxPos += size;
+ hdrBuf.rxPos += size;
} else {
ret = DPS_ERR_RESOURCES;
}
+ } else {
+ cn->msgBuf->rx.rxPos += nread;
}
- if (ret != DPS_OK) {
+ if (cn->msgBuf) {
/*
- * Report error to receive callback
+ * Keep reading if we don't have a complete message
*/
- netCtx->receiveCB(cn->node, &cn->peerEp, ret, NULL);
+ if (DPS_RxBufferAvail(&cn->msgBuf->rx)) {
+ return;
+ }
+ DPS_DBGPRINT("Received message of length %zd\n", cn->msgBuf->rx.eod - cn->msgBuf->rx.base);
+ cn->msgBuf->rx.rxPos = cn->msgBuf->rx.base;
}
- } else {
- cn->msgBuf->rx.rxPos += nread;
- }
- if (cn->msgBuf) {
+ Done:
/*
- * Keep reading if we don't have a complete message
+ * Issue callback if we've received enough to have a valid
+ * peer endpoint.
*/
- if (DPS_RxBufferAvail(&cn->msgBuf->rx)) {
- return;
+ if (cn->peerEp.addr.type == DPS_PIPE) {
+ netCtx->receiveCB(cn->node, &cn->peerEp, ret, cn->msgBuf);
}
- DPS_DBGPRINT("Received message of length %zd\n", cn->msgBuf->rx.eod - cn->msgBuf->rx.base);
+ DPS_NetRxBufferDecRef(cn->msgBuf);
+ cn->msgBuf = NULL;
+ cn->readLen = 0;
/*
- * Reset rxPos to beginning of complete message before passing up
+ * Stop reading if we got an error
*/
- cn->msgBuf->rx.rxPos = cn->msgBuf->rx.base;
- ret = netCtx->receiveCB(cn->node, &cn->peerEp, DPS_OK, cn->msgBuf);
- }
- DPS_NetRxBufferDecRef(cn->msgBuf);
- cn->msgBuf = NULL;
- cn->readLen = 0;
- /*
- * Stop reading if we got an error
- */
- if (ret != DPS_OK) {
- uv_read_stop(socket);
- }
- /*
- * Shutdown the connection if the upper layer didn't IncRef to keep it alive
- */
- if (cn->refCount == 0) {
- Shutdown(cn);
+ if (ret != DPS_OK) {
+ uv_read_stop(socket);
+ }
+ /*
+ * Shutdown the connection if the upper layer didn't IncRef to keep it alive
+ */
+ if (cn->refCount == 0) {
+ Shutdown(cn);
+ }
+
+ /*
+ * If there's leftover data in the hdrBuf, we'll loop back and consume it
+ */
+ nread = DPS_RxBufferAvail(&hdrBuf);
+ if (nread) {
+ memmove(hdrBuf.base, hdrBuf.rxPos, nread);
+ }
}
}
static void OnIncomingConnection(uv_stream_t* stream, int status)
{
int ret;
- DPS_NetContext* netCtx = (DPS_NetContext*)stream->data;
- DPS_NetConnection* cn;
- size_t sz;
+ DPS_NetPipeContext* netCtx = (DPS_NetPipeContext*)stream->data;
+ DPS_NetPipeConnection* cn;
DPS_DBGTRACE();
@@ -299,11 +355,13 @@ static void OnIncomingConnection(uv_stream_t* stream, int status)
goto FailConnection;
}
- cn = calloc(1, sizeof(DPS_NetConnection));
+ cn = calloc(1, sizeof(DPS_NetPipeConnection));
if (!cn) {
DPS_ERRPRINT("OnIncomingConnection malloc failed\n");
goto FailConnection;
}
+ cn->cn.incRef = DPS_NetPipeConnectionIncRef;
+ cn->cn.decRef = DPS_NetPipeConnectionDecRef;
ret = uv_pipe_init(stream->loop, &cn->socket, 0);
if (ret) {
DPS_ERRPRINT("uv_pipe_init error=%s\n", uv_err_name(ret));
@@ -312,7 +370,7 @@ static void OnIncomingConnection(uv_stream_t* stream, int status)
}
cn->node = netCtx->node;
cn->socket.data = cn;
- cn->peerEp.cn = cn;
+ cn->peerEp.cn = (DPS_NetConnection*)cn;
DPS_QueueInit(&cn->sendQueue);
DPS_QueueInit(&cn->sendCompletedQueue);
uv_idle_init(stream->loop, &cn->idle);
@@ -323,14 +381,6 @@ static void OnIncomingConnection(uv_stream_t* stream, int status)
DPS_ERRPRINT("OnIncomingConnection accept %s\n", uv_strerror(ret));
goto FailConnection;
}
- cn->peerEp.addr.type = DPS_PIPE;
- sz = sizeof(cn->peerEp.addr.u.path);
- uv_pipe_getpeername((uv_pipe_t*)&cn->socket, cn->peerEp.addr.u.path, &sz);
-#ifdef _WIN32
- if (!strncmp(cn->peerEp.addr.u.path, "\\\\?", 3)) {
- cn->peerEp.addr.u.path[2] = '.';
- }
-#endif
ret = uv_read_start((uv_stream_t*)&cn->socket, AllocBuffer, OnData);
if (ret) {
DPS_ERRPRINT("OnIncomingConnection read start %s\n", uv_strerror(ret));
@@ -376,17 +426,20 @@ static int GetScopeId(struct sockaddr_in6* addr)
#define LISTEN_BACKLOG 2
-DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_OnReceive cb)
+DPS_NetContext* DPS_NetPipeStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_OnReceive cb)
{
char path[DPS_NODE_ADDRESS_PATH_MAX] = { 0 };
- DPS_NetContext* netCtx = NULL;
+ DPS_NetPipeContext* netCtx = NULL;
DPS_UUID uuid;
int ret;
- netCtx = calloc(1, sizeof(DPS_NetContext));
+ netCtx = calloc(1, sizeof(DPS_NetPipeContext));
if (!netCtx) {
return NULL;
}
+ netCtx->ctx.getListenAddress = DPS_NetPipeGetListenAddress;
+ netCtx->ctx.stop = DPS_NetPipeStop;
+ netCtx->ctx.send = DPS_NetPipeSend;
ret = uv_pipe_init(node->loop, &netCtx->socket, 0);
if (ret) {
DPS_ERRPRINT("uv_pipe_init error=%s\n", uv_err_name(ret));
@@ -396,7 +449,7 @@ DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_On
netCtx->socket.data = netCtx;
netCtx->node = node;
netCtx->receiveCB = cb;
- if (addr) {
+ if (addr && addr->u.path[0]) {
ret = uv_pipe_bind(&netCtx->socket, addr->u.path);
} else {
/*
@@ -438,7 +491,7 @@ DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_On
*/
signal(SIGPIPE, SIG_IGN);
#endif
- return netCtx;
+ return (DPS_NetContext*)netCtx;
ErrorExit:
DPS_ERRPRINT("Failed to start net netCtx: error=%s\n", uv_err_name(ret));
@@ -446,8 +499,9 @@ DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_On
return NULL;
}
-DPS_NodeAddress* DPS_NetGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext* netCtx)
+DPS_NodeAddress* DPS_NetPipeGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext* ctx)
{
+ DPS_NetPipeContext* netCtx = (DPS_NetPipeContext*)ctx;
size_t len;
DPS_DBGTRACEA("netCtx=%p\n", netCtx);
@@ -470,8 +524,10 @@ DPS_NodeAddress* DPS_NetGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext*
return addr;
}
-void DPS_NetStop(DPS_NetContext* netCtx)
+void DPS_NetPipeStop(DPS_NetContext* ctx)
{
+ DPS_NetPipeContext* netCtx = (DPS_NetPipeContext*)ctx;
+
if (netCtx) {
netCtx->socket.data = netCtx;
uv_close((uv_handle_t*)&netCtx->socket, ListenSocketClosed);
@@ -481,7 +537,7 @@ void DPS_NetStop(DPS_NetContext* netCtx)
static void OnWriteComplete(uv_write_t* writeReq, int status)
{
SendRequest* req = (SendRequest*)writeReq->data;
- DPS_NetConnection* cn = req->cn;
+ DPS_NetPipeConnection* cn = req->cn;
if (status) {
DPS_DBGPRINT("OnWriteComplete status=%s\n", uv_err_name(status));
@@ -491,10 +547,10 @@ static void OnWriteComplete(uv_write_t* writeReq, int status)
}
DPS_QueuePushBack(&cn->sendCompletedQueue, &req->queue);
SendCompleted(cn);
- DPS_NetConnectionDecRef(cn);
+ ConnectionDecRef(cn);
}
-static void DoSend(DPS_NetConnection* cn)
+static void DoSend(DPS_NetPipeConnection* cn)
{
while (!DPS_QueueEmpty(&cn->sendQueue)) {
SendRequest* req = (SendRequest*)DPS_QueueFront(&cn->sendQueue);
@@ -503,7 +559,7 @@ static void DoSend(DPS_NetConnection* cn)
int r = uv_write(&req->writeReq, (uv_stream_t*)&cn->socket, req->bufs, (uint32_t)req->numBufs,
OnWriteComplete);
if (r == 0) {
- DPS_NetConnectionIncRef(cn);
+ ConnectionIncRef(cn);
} else {
DPS_ERRPRINT("DoSend - write failed: %s\n", uv_err_name(r));
req->status = DPS_ERR_NETWORK;
@@ -514,7 +570,7 @@ static void DoSend(DPS_NetConnection* cn)
static void OnOutgoingConnection(uv_connect_t *req, int status)
{
- DPS_NetConnection* cn = (DPS_NetConnection*)req->data;
+ DPS_NetPipeConnection* cn = (DPS_NetPipeConnection*)req->data;
if (status == 0) {
cn->socket.data = cn;
status = uv_read_start((uv_stream_t*)&cn->socket, AllocBuffer, OnData);
@@ -530,17 +586,19 @@ static void OnOutgoingConnection(uv_connect_t *req, int status)
SendCompleted(cn);
}
-DPS_Status DPS_NetSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf_t* bufs,
- size_t numBufs, DPS_NetSendComplete sendCompleteCB)
+DPS_Status DPS_NetPipeSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf_t* bufs,
+ size_t numBufs, DPS_NetSendComplete sendCompleteCB)
{
DPS_Status ret;
- DPS_TxBuffer lenBuf;
+ DPS_TxBuffer hdrBuf;
SendRequest* req;
+ DPS_NetPipeConnection* cn = NULL;
uv_handle_t* socket = NULL;
int r;
size_t i;
size_t len = 0;
+ len += CBOR_SIZEOF_STRING(node->addr.u.path);
for (i = 0; i < numBufs; ++i) {
len += bufs[i].len;
}
@@ -555,15 +613,23 @@ DPS_Status DPS_NetSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf
return DPS_ERR_RESOURCES;
}
/*
- * Write total message length
+ * Write message header
*/
- DPS_TxBufferInit(&lenBuf, req->lenBuf, sizeof(req->lenBuf));
- ret = CBOR_EncodeUint32(&lenBuf, len);
+ DPS_TxBufferInit(&hdrBuf, req->hdrBuf, sizeof(req->hdrBuf));
+ ret = CBOR_EncodeUint32(&hdrBuf, len);
if (ret != DPS_OK) {
goto ErrExit;
}
- req->bufs[0].base = (char*)req->lenBuf;
- req->bufs[0].len = DPS_TxBufferUsed(&lenBuf);
+ /*
+ * Include our listening address, otherwise all clients will look
+ * the same to the server since the socket peername is unnamed
+ */
+ ret = CBOR_EncodeString(&hdrBuf, node->addr.u.path);
+ if (ret != DPS_OK) {
+ goto ErrExit;
+ }
+ req->bufs[0].base = (char*)req->hdrBuf;
+ req->bufs[0].len = DPS_TxBufferUsed(&hdrBuf);
/*
* Copy other uvbufs into the send request
*/
@@ -577,42 +643,46 @@ DPS_Status DPS_NetSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf
* See if we already have a connection
*/
if (ep->cn) {
- req->cn = ep->cn;
+ cn = (DPS_NetPipeConnection*)ep->cn;
+ req->cn = cn;
/*
* If there are pending sends the connection is not up yet
*/
- if (!DPS_QueueEmpty(&ep->cn->sendQueue)) {
- DPS_QueuePushBack(&ep->cn->sendQueue, &req->queue);
+ if (!DPS_QueueEmpty(&cn->sendQueue)) {
+ DPS_QueuePushBack(&cn->sendQueue, &req->queue);
return DPS_OK;
}
- DPS_QueuePushBack(&ep->cn->sendQueue, &req->queue);
- DoSend(ep->cn);
- uv_idle_start(&ep->cn->idle, SendCompletedTask);
+ DPS_QueuePushBack(&cn->sendQueue, &req->queue);
+ DoSend(cn);
+ uv_idle_start(&cn->idle, SendCompletedTask);
return DPS_OK;
}
- ep->cn = calloc(1, sizeof(DPS_NetConnection));
- if (!ep->cn) {
+ cn = calloc(1, sizeof(DPS_NetPipeConnection));
+ if (!cn) {
goto ErrExit;
}
- r = uv_pipe_init(node->loop, &ep->cn->socket, 0);
+ cn->cn.incRef = DPS_NetPipeConnectionIncRef;
+ cn->cn.decRef = DPS_NetPipeConnectionDecRef;
+ r = uv_pipe_init(node->loop, &cn->socket, 0);
if (r) {
goto ErrExit;
}
- ep->cn->peerEp.addr = ep->addr;
- ep->cn->node = node;
- DPS_QueueInit(&ep->cn->sendQueue);
- DPS_QueueInit(&ep->cn->sendCompletedQueue);
- uv_idle_init(node->loop, &ep->cn->idle);
- ep->cn->idle.data = ep->cn;
- socket = (uv_handle_t*)&ep->cn->socket;
-
- ep->cn->connectReq.data = ep->cn;
- uv_pipe_connect(&ep->cn->connectReq, &ep->cn->socket, ep->addr.u.path, OnOutgoingConnection);
- ep->cn->peerEp.cn = ep->cn;
- DPS_QueuePushBack(&ep->cn->sendQueue, &req->queue);
- req->cn = ep->cn;
- DPS_NetConnectionIncRef(ep->cn);
+ cn->peerEp.addr = ep->addr;
+ cn->node = node;
+ DPS_QueueInit(&cn->sendQueue);
+ DPS_QueueInit(&cn->sendCompletedQueue);
+ uv_idle_init(node->loop, &cn->idle);
+ cn->idle.data = cn;
+ socket = (uv_handle_t*)&cn->socket;
+
+ cn->connectReq.data = cn;
+ uv_pipe_connect(&cn->connectReq, &cn->socket, ep->addr.u.path, OnOutgoingConnection);
+ cn->peerEp.cn = (DPS_NetConnection*)cn;
+ DPS_QueuePushBack(&cn->sendQueue, &req->queue);
+ req->cn = cn;
+ ConnectionIncRef(cn);
+ ep->cn = (DPS_NetConnection*)cn;
return DPS_OK;
ErrExit:
@@ -621,32 +691,28 @@ DPS_Status DPS_NetSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf
free(req);
}
if (socket) {
- socket->data = ep->cn;
+ socket->data = cn;
uv_close(socket, StreamClosed);
} else {
- if (ep->cn) {
- free(ep->cn);
+ if (cn) {
+ free(cn);
}
}
ep->cn = NULL;
return DPS_ERR_NETWORK;
}
-void DPS_NetConnectionIncRef(DPS_NetConnection* cn)
+void DPS_NetPipeConnectionIncRef(DPS_NetConnection* cn)
{
- if (cn) {
- DPS_DBGTRACE();
- ++cn->refCount;
- }
+ ConnectionIncRef((DPS_NetPipeConnection*)cn);
}
-void DPS_NetConnectionDecRef(DPS_NetConnection* cn)
+void DPS_NetPipeConnectionDecRef(DPS_NetConnection* cn)
{
- if (cn) {
- DPS_DBGTRACE();
- assert(cn->refCount > 0);
- if (--cn->refCount == 0) {
- Shutdown(cn);
- }
- }
+ ConnectionDecRef((DPS_NetPipeConnection*)cn);
}
+
+DPS_NetTransport DPS_NetPipeTransport = {
+ DPS_PIPE,
+ DPS_NetPipeStart
+};
diff --git a/src/registration.c b/src/registration.c
index fb1409b9..c1ad5d97 100644
--- a/src/registration.c
+++ b/src/registration.c
@@ -308,7 +308,8 @@ static DPS_Status BuildPutPayload(DPS_TxBuffer* payload, const DPS_NodeAddress*
}
}
ret = DPS_TxBufferInit(payload, NULL, CBOR_SIZEOF_UINT(extIfs) +
- extIfs * DPS_NODE_ADDRESS_MAX_STRING_LEN);
+ extIfs * (CBOR_SIZEOF_STRING_AND_LENGTH(DPS_MAX_NETWORK_LEN) +
+ CBOR_SIZEOF_STRING_AND_LENGTH(DPS_NODE_ADDRESS_MAX_STRING_LEN)));
if (ret != DPS_OK) {
goto Exit;
}
@@ -328,6 +329,10 @@ static DPS_Status BuildPutPayload(DPS_TxBuffer* payload, const DPS_NodeAddress*
continue;
}
AddrSetPort(sa, port);
+ ret = CBOR_EncodeString(payload, DPS_NodeAddrNetwork(addr));
+ if (ret != DPS_OK) {
+ goto Exit;
+ }
ret = CBOR_EncodeString(payload, DPS_NetAddrText(sa));
if (ret != DPS_OK) {
goto Exit;
@@ -335,13 +340,19 @@ static DPS_Status BuildPutPayload(DPS_TxBuffer* payload, const DPS_NodeAddress*
}
break;
case DPS_PIPE:
- ret = DPS_TxBufferInit(payload, NULL, CBOR_SIZEOF_UINT(1) + DPS_NODE_ADDRESS_MAX_STRING_LEN);
+ ret = DPS_TxBufferInit(payload, NULL, CBOR_SIZEOF_UINT(1) +
+ CBOR_SIZEOF_STRING_AND_LENGTH(DPS_MAX_NETWORK_LEN) +
+ CBOR_SIZEOF_STRING_AND_LENGTH(DPS_NODE_ADDRESS_MAX_STRING_LEN));
if (ret != DPS_OK) {
goto Exit;
}
DPS_DBGPRINT("Encoding 1 addresses\n");
ret = CBOR_EncodeUint8(payload, 1);
assert(ret == DPS_OK);
+ ret = CBOR_EncodeString(payload, DPS_NodeAddrNetwork(addr));
+ if (ret != DPS_OK) {
+ goto Exit;
+ }
ret = CBOR_EncodeString(payload, DPS_NodeAddrToString(addr));
break;
default:
@@ -356,12 +367,14 @@ static DPS_Status BuildPutPayload(DPS_TxBuffer* payload, const DPS_NodeAddress*
return ret;
}
-DPS_Status DPS_Registration_Put(DPS_Node* node, const char* addrText, const char* tenantString,
- uint16_t timeout, DPS_OnRegPutComplete cb, void* data)
+DPS_Status DPS_Registration_Put(DPS_Node* node, const char* network, const char* addrText,
+ const char* tenantString, uint16_t timeout, DPS_OnRegPutComplete cb,
+ void* data)
{
DPS_Status ret;
RegPut* regPut;
const DPS_NodeAddress* localAddr;
+ DPS_NodeAddress* addr = NULL;
DPS_DBGTRACE();
@@ -387,13 +400,22 @@ DPS_Status DPS_Registration_Put(DPS_Node* node, const char* addrText, const char
goto Exit;
}
- ret = DPS_StartNode(regPut->node, DPS_MCAST_PUB_DISABLED, NULL);
+ addr = DPS_CreateAddress();
+ if (!addr) {
+ ret = DPS_ERR_RESOURCES;
+ goto Exit;
+ }
+ if (!DPS_SetAddress(addr, DPS_NodeAddrNetwork(localAddr), NULL)) {
+ ret = DPS_ERR_FAILURE;
+ goto Exit;
+ }
+ ret = DPS_StartNode(regPut->node, DPS_MCAST_PUB_DISABLED, addr);
if (ret != DPS_OK) {
DPS_ERRPRINT("Failed to start node: %s\n", DPS_ErrTxt(ret));
} else {
ret = BuildPutPayload(®Put->payload, localAddr);
if (ret == DPS_OK) {
- ret = DPS_Link(regPut->node, addrText, OnLinkedPut, regPut);
+ ret = DPS_Link(regPut->node, network, addrText, OnLinkedPut, regPut);
}
}
@@ -410,6 +432,7 @@ DPS_Status DPS_Registration_Put(DPS_Node* node, const char* addrText, const char
}
free(regPut);
}
+ DPS_DestroyAddress(addr);
return ret;
}
@@ -419,8 +442,8 @@ static void OnPutComplete(DPS_Status status, void* data)
DPS_SignalEvent(event, status);
}
-DPS_Status DPS_Registration_PutSyn(DPS_Node* node, const char* addrText, const char* tenantString,
- uint16_t timeout)
+DPS_Status DPS_Registration_PutSyn(DPS_Node* node, const char* network, const char* addrText,
+ const char* tenantString, uint16_t timeout)
{
DPS_Status ret;
DPS_Event* event = DPS_CreateEvent();
@@ -430,7 +453,7 @@ DPS_Status DPS_Registration_PutSyn(DPS_Node* node, const char* addrText, const c
if (!event) {
return DPS_ERR_RESOURCES;
}
- ret = DPS_Registration_Put(node, addrText, tenantString, timeout, OnPutComplete, event);
+ ret = DPS_Registration_Put(node, network, addrText, tenantString, timeout, OnPutComplete, event);
if (ret == DPS_OK) {
ret = DPS_WaitForEvent(event);
}
@@ -521,8 +544,9 @@ static void OnPub(DPS_Subscription* sub, const DPS_Publication* pub, uint8_t* da
DPS_RxBufferInit(&buf, data, len);
ret = CBOR_DecodeUint8(&buf, &count);
if (ret == DPS_OK) {
+ char* network = NULL;
+ char* addrText = NULL;
while (count--) {
- char* addrText;
size_t len;
/*
* Stop if we have reached the max registrations
@@ -534,6 +558,13 @@ static void OnPub(DPS_Subscription* sub, const DPS_Publication* pub, uint8_t* da
uv_close((uv_handle_t*)®Get->timer, OnGetTimerClosed);
break;
}
+ if (CBOR_DecodeString(&buf, &network, &len) != DPS_OK) {
+ break;
+ }
+ network = strndup(network, len);
+ if (!network) {
+ break;
+ }
if (CBOR_DecodeString(&buf, &addrText, &len) != DPS_OK) {
break;
}
@@ -541,13 +572,23 @@ static void OnPub(DPS_Subscription* sub, const DPS_Publication* pub, uint8_t* da
if (!addrText) {
break;
}
- DPS_SetAddress(addr, addrText);
+ DPS_SetAddress(addr, network, addrText);
if (!IsLocalAddr(addr, regGet->localAddr)) {
+ regGet->regs->list[regGet->regs->count].network = network;
regGet->regs->list[regGet->regs->count].addrText = addrText;
++regGet->regs->count;
} else {
free(addrText);
+ free(network);
}
+ addrText = NULL;
+ network = NULL;
+ }
+ if (addrText) {
+ free(addrText);
+ }
+ if (network) {
+ free(network);
}
}
DPS_DestroyAddress(addr);
@@ -595,13 +636,14 @@ static void OnLinkedGet(DPS_Node* node, DPS_NodeAddress* addr, DPS_Status ret, v
}
}
-DPS_Status DPS_Registration_Get(DPS_Node* node, const char* addrText, const char* tenantString,
- DPS_RegistrationList* regs, uint16_t timeout, DPS_OnRegGetComplete cb,
- void* data)
+DPS_Status DPS_Registration_Get(DPS_Node* node, const char* network, const char* addrText,
+ const char* tenantString, DPS_RegistrationList* regs, uint16_t timeout,
+ DPS_OnRegGetComplete cb, void* data)
{
DPS_Status ret;
RegGet* regGet;
const DPS_NodeAddress* localAddr;
+ DPS_NodeAddress* addr = NULL;
DPS_DBGTRACE();
@@ -638,11 +680,20 @@ DPS_Status DPS_Registration_Get(DPS_Node* node, const char* addrText, const char
ret = DPS_ERR_RESOURCES;
goto Exit;
}
- ret = DPS_StartNode(regGet->node, DPS_MCAST_PUB_DISABLED, NULL);
+ addr = DPS_CreateAddress();
+ if (!addr) {
+ ret = DPS_ERR_RESOURCES;
+ goto Exit;
+ }
+ if (!DPS_SetAddress(addr, DPS_NodeAddrNetwork(localAddr), NULL)) {
+ ret = DPS_ERR_FAILURE;
+ goto Exit;
+ }
+ ret = DPS_StartNode(regGet->node, DPS_MCAST_PUB_DISABLED, addr);
if (ret != DPS_OK) {
DPS_ERRPRINT("Failed to start node: %s\n", DPS_ErrTxt(ret));
} else {
- ret = DPS_Link(regGet->node, addrText, OnLinkedGet, regGet);
+ ret = DPS_Link(regGet->node, network, addrText, OnLinkedGet, regGet);
}
Exit:
@@ -655,6 +706,7 @@ DPS_Status DPS_Registration_Get(DPS_Node* node, const char* addrText, const char
}
free(regGet);
}
+ DPS_DestroyAddress(addr);
return ret;
}
@@ -671,8 +723,9 @@ static void OnGetComplete(DPS_RegistrationList* regs, DPS_Status status, void* d
DPS_SignalEvent(getResult->event, status);
}
-DPS_Status DPS_Registration_GetSyn(DPS_Node* node, const char* addrText, const char* tenantString,
- DPS_RegistrationList* regs, uint16_t timeout)
+DPS_Status DPS_Registration_GetSyn(DPS_Node* node, const char* network, const char* addrText,
+ const char* tenantString, DPS_RegistrationList* regs,
+ uint16_t timeout)
{
DPS_Status ret;
GetResult getResult;
@@ -685,7 +738,8 @@ DPS_Status DPS_Registration_GetSyn(DPS_Node* node, const char* addrText, const c
if (!getResult.event) {
return DPS_ERR_RESOURCES;
}
- ret = DPS_Registration_Get(node, addrText, tenantString, regs, timeout, OnGetComplete, &getResult);
+ ret = DPS_Registration_Get(node, network, addrText, tenantString, regs, timeout, OnGetComplete,
+ &getResult);
if (ret == DPS_OK) {
ret = DPS_WaitForEvent(getResult.event);
}
@@ -724,7 +778,7 @@ static void OnLinked(DPS_Node* node, DPS_NodeAddress* addr, DPS_Status status, v
free(linkTo);
}
-static DPS_Status Link(DPS_Node* node, const char* addrText, LinkTo* linkTo)
+static DPS_Status Link(DPS_Node* node, const char* network, const char* addrText, LinkTo* linkTo)
{
DPS_Status ret = DPS_ERR_NO_ROUTE;
@@ -733,7 +787,7 @@ static DPS_Status Link(DPS_Node* node, const char* addrText, LinkTo* linkTo)
DPS_DBGPRINT("Candidate %d INVALID\n", linkTo->candidate);
linkTo->regs->list[linkTo->candidate].flags = DPS_CANDIDATE_FAILED;
} else {
- ret = DPS_Link(node, addrText, OnLinked, linkTo);
+ ret = DPS_Link(node, network, addrText, OnLinked, linkTo);
}
}
return ret;
@@ -774,7 +828,7 @@ DPS_Status DPS_Registration_LinkTo(DPS_Node* node, DPS_RegistrationList* regs,
ret = DPS_ERR_RESOURCES;
}
if (ret == DPS_OK) {
- ret = Link(node, regs->list[r].addrText, linkTo);
+ ret = Link(node, regs->list[r].network, regs->list[r].addrText, linkTo);
}
if (ret == DPS_OK) {
break;
diff --git a/src/resolver.c b/src/resolver.c
index 1108894f..06ea0283 100644
--- a/src/resolver.c
+++ b/src/resolver.c
@@ -34,29 +34,24 @@
*/
DPS_DEBUG_CONTROL(DPS_DEBUG_ON);
-typedef struct _ResolverInfo {
+typedef struct _ResolverRequest {
+ DPS_Queue queue;
DPS_Node* node;
DPS_OnResolveAddressComplete cb;
void* data;
uv_getaddrinfo_t info;
+ DPS_NodeAddressType network;
char host[DPS_MAX_HOST_LEN + 1];
char service[DPS_MAX_SERVICE_LEN + 1];
- struct _ResolverInfo* next;
-} ResolverInfo;
+} ResolverRequest;
static void GetAddrInfoCB(uv_getaddrinfo_t* req, int status, struct addrinfo* res)
{
- ResolverInfo* resolver = (ResolverInfo*)req->data;
+ ResolverRequest* resolver = (ResolverRequest*)req->data;
if (status == 0) {
DPS_NodeAddress addr;
-#if defined(DPS_USE_DTLS)
- addr.type = DPS_DTLS;
-#elif defined(DPS_USE_TCP)
- addr.type = DPS_TCP;
-#elif defined(DPS_USE_UDP)
- addr.type = DPS_UDP;
-#endif
+ addr.type = resolver->network;
if (res->ai_family == AF_INET6) {
memcpy_s(&addr.u.inaddr, sizeof(addr.u.inaddr), res->ai_addr, sizeof(struct sockaddr_in6));
} else {
@@ -73,7 +68,7 @@ static void GetAddrInfoCB(uv_getaddrinfo_t* req, int status, struct addrinfo* re
static void TryGetAddrInfoCB(uv_getaddrinfo_t* req, int status, struct addrinfo* res)
{
- ResolverInfo* resolver = (ResolverInfo*)req->data;
+ ResolverRequest* resolver = (ResolverRequest*)req->data;
if (status == UV_EAI_ADDRFAMILY) {
/*
@@ -110,11 +105,11 @@ void DPS_AsyncResolveAddress(uv_async_t* async)
DPS_LockNode(node);
- while (node->resolverList) {
+ while (!DPS_QueueEmpty(&node->resolverQueue)) {
int r;
struct addrinfo hints;
- ResolverInfo* resolver = node->resolverList;
- node->resolverList = resolver->next;
+ ResolverRequest* resolver = (ResolverRequest*)DPS_QueueFront(&node->resolverQueue);
+ DPS_QueueRemove(&resolver->queue);
if (node->state != DPS_NODE_RUNNING) {
resolver->cb(resolver->node, NULL, resolver->data);
@@ -136,11 +131,11 @@ void DPS_AsyncResolveAddress(uv_async_t* async)
DPS_UnlockNode(node);
}
-DPS_Status DPS_ResolveAddress(DPS_Node* node, const char* host, const char* service,
+DPS_Status DPS_ResolveAddress(DPS_Node* node, const char* network, const char* host, const char* service,
DPS_OnResolveAddressComplete cb, void* data)
{
DPS_Status ret;
- ResolverInfo* resolver;
+ ResolverRequest* resolver;
DPS_DBGTRACE();
@@ -158,10 +153,11 @@ DPS_Status DPS_ResolveAddress(DPS_Node* node, const char* host, const char* serv
if (!host || !strcmp(host, "0.0.0.0") || !strcmp(host, "::")) {
host = "::1";
}
- resolver = calloc(1, sizeof(ResolverInfo));
+ resolver = calloc(1, sizeof(ResolverRequest));
if (!resolver) {
return DPS_ERR_RESOURCES;
}
+ resolver->network = DPS_NetAddressType(network);
strncpy_s(resolver->host, sizeof(resolver->host), host, sizeof(resolver->host) - 1);
strncpy_s(resolver->service, sizeof(resolver->service), service, sizeof(resolver->service) - 1);
resolver->node = node;
@@ -177,8 +173,7 @@ DPS_Status DPS_ResolveAddress(DPS_Node* node, const char* host, const char* serv
free(resolver);
ret = DPS_ERR_FAILURE;
} else {
- resolver->next = node->resolverList;
- node->resolverList = resolver;
+ DPS_QueuePushBack(&node->resolverQueue, &resolver->queue);
ret = DPS_OK;
}
DPS_UnlockNode(node);
diff --git a/src/synchronous.c b/src/synchronous.c
index e6f6ae0e..5a35e12f 100644
--- a/src/synchronous.c
+++ b/src/synchronous.c
@@ -43,7 +43,7 @@ static void OnLinked(DPS_Node* node, DPS_NodeAddress* addr, DPS_Status status, v
DPS_SignalEvent(event, status);
}
-DPS_Status DPS_LinkTo(DPS_Node* node, const char* addrText, DPS_NodeAddress* addr)
+DPS_Status DPS_LinkTo(DPS_Node* node, const char* network, const char* addrText, DPS_NodeAddress* addr)
{
DPS_Event* event = NULL;
DPS_Status ret;
@@ -55,7 +55,7 @@ DPS_Status DPS_LinkTo(DPS_Node* node, const char* addrText, DPS_NodeAddress* add
return DPS_ERR_RESOURCES;
}
DPS_SetEventData(event, addr);
- ret = DPS_Link(node, addrText, OnLinked, event);
+ ret = DPS_Link(node, network, addrText, OnLinked, event);
if (ret != DPS_OK) {
DPS_ERRPRINT("DPS_Link returned: %s\n", DPS_ErrTxt(ret));
goto Exit;
diff --git a/src/tcp/network.c b/src/tcp/network.c
index 707cbddc..41d64c61 100755
--- a/src/tcp/network.c
+++ b/src/tcp/network.c
@@ -42,9 +42,11 @@
*/
DPS_DEBUG_CONTROL(DPS_DEBUG_ON);
+typedef struct _DPS_NetTcpConnection DPS_NetTcpConnection;
+
typedef struct _SendRequest {
DPS_Queue queue;
- DPS_NetConnection* cn;
+ DPS_NetTcpConnection* cn;
uv_write_t writeReq;
DPS_NetSendComplete onSendComplete;
void* appCtx;
@@ -54,7 +56,8 @@ typedef struct _SendRequest {
uv_buf_t bufs[1];
} SendRequest;
-typedef struct _DPS_NetConnection {
+typedef struct _DPS_NetTcpConnection {
+ DPS_NetConnection cn;
DPS_Node* node;
uv_tcp_t socket;
DPS_NetEndpoint peerEp;
@@ -69,20 +72,47 @@ typedef struct _DPS_NetConnection {
DPS_Queue sendQueue;
DPS_Queue sendCompletedQueue;
uv_idle_t idle;
-} DPS_NetConnection;
+} DPS_NetTcpConnection;
-struct _DPS_NetContext {
+typedef struct _DPS_NetTcpContext {
+ DPS_NetContext ctx;
uv_tcp_t socket; /* the listen socket */
DPS_Node* node;
DPS_OnReceive receiveCB;
-};
+} DPS_NetTcpContext;
-#define MIN_BUF_ALLOC_SIZE 512
#define MIN_READ_SIZE CBOR_SIZEOF(uint32_t)
+DPS_NodeAddress* DPS_NetTcpGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext* netCtx);
+void DPS_NetTcpStop(DPS_NetContext* netCtx);
+DPS_Status DPS_NetTcpSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf_t* bufs, size_t numBufs,
+ DPS_NetSendComplete sendCompleteCB);
+void DPS_NetTcpConnectionIncRef(DPS_NetConnection* cn);
+void DPS_NetTcpConnectionDecRef(DPS_NetConnection* cn);
+static void Shutdown(DPS_NetTcpConnection* cn);
+
+static void ConnectionIncRef(DPS_NetTcpConnection* cn)
+{
+ if (cn) {
+ DPS_DBGTRACE();
+ ++cn->refCount;
+ }
+}
+
+static void ConnectionDecRef(DPS_NetTcpConnection* cn)
+{
+ if (cn) {
+ DPS_DBGTRACE();
+ assert(cn->refCount > 0);
+ if (--cn->refCount == 0) {
+ Shutdown(cn);
+ }
+ }
+}
+
static void AllocBuffer(uv_handle_t* handle, size_t suggestedSize, uv_buf_t* buf)
{
- DPS_NetConnection* cn = (DPS_NetConnection*)handle->data;
+ DPS_NetTcpConnection* cn = (DPS_NetTcpConnection*)handle->data;
if (cn->msgBuf) {
buf->len = DPS_RxBufferAvail(&cn->msgBuf->rx);
@@ -99,7 +129,7 @@ static void ListenSocketClosed(uv_handle_t* handle)
free(handle->data);
}
-static void CancelPendingSends(DPS_NetConnection* cn)
+static void CancelPendingSends(DPS_NetTcpConnection* cn)
{
while (!DPS_QueueEmpty(&cn->sendQueue)) {
SendRequest* req = (SendRequest*)DPS_QueueFront(&cn->sendQueue);
@@ -110,7 +140,7 @@ static void CancelPendingSends(DPS_NetConnection* cn)
}
}
-static void SendCompleted(DPS_NetConnection* cn)
+static void SendCompleted(DPS_NetTcpConnection* cn)
{
while (!DPS_QueueEmpty(&cn->sendCompletedQueue)) {
SendRequest* req = (SendRequest*)DPS_QueueFront(&cn->sendCompletedQueue);
@@ -123,12 +153,12 @@ static void SendCompleted(DPS_NetConnection* cn)
static void SendCompletedTask(uv_idle_t* idle)
{
- DPS_NetConnection* cn = idle->data;
+ DPS_NetTcpConnection* cn = idle->data;
SendCompleted(cn);
uv_idle_stop(idle);
}
-static void FreeConnection(DPS_NetConnection* cn)
+static void FreeConnection(DPS_NetTcpConnection* cn)
{
/*
* Free memory for any pending sends
@@ -142,13 +172,13 @@ static void FreeConnection(DPS_NetConnection* cn)
static void IdleClosed(uv_handle_t* handle)
{
- DPS_NetConnection* cn = handle->data;
+ DPS_NetTcpConnection* cn = handle->data;
FreeConnection(cn);
}
static void StreamClosed(uv_handle_t* handle)
{
- DPS_NetConnection* cn = (DPS_NetConnection*)handle->data;
+ DPS_NetTcpConnection* cn = (DPS_NetTcpConnection*)handle->data;
DPS_DBGPRINT("Closed stream handle %p\n", handle);
if (!uv_is_closing((uv_handle_t*)&cn->idle)) {
@@ -158,7 +188,7 @@ static void StreamClosed(uv_handle_t* handle)
static void OnShutdownComplete(uv_shutdown_t* req, int status)
{
- DPS_NetConnection* cn = (DPS_NetConnection*)req->data;
+ DPS_NetTcpConnection* cn = (DPS_NetTcpConnection*)req->data;
DPS_DBGPRINT("Shutdown complete handle %p\n", req->handle);
if (!uv_is_closing((uv_handle_t*)req->handle)) {
@@ -167,7 +197,7 @@ static void OnShutdownComplete(uv_shutdown_t* req, int status)
}
}
-static void Shutdown(DPS_NetConnection* cn)
+static void Shutdown(DPS_NetTcpConnection* cn)
{
if (!cn->shutdownReq.data) {
int r;
@@ -188,8 +218,8 @@ static void Shutdown(DPS_NetConnection* cn)
static void OnData(uv_stream_t* socket, ssize_t nread, const uv_buf_t* buf)
{
DPS_Status ret = DPS_OK;
- DPS_NetConnection* cn = (DPS_NetConnection*)socket->data;
- DPS_NetContext* netCtx = cn->node->netCtx;
+ DPS_NetTcpConnection* cn = (DPS_NetTcpConnection*)socket->data;
+ DPS_NetTcpContext* netCtx = (DPS_NetTcpContext*)cn->node->netCtx;
DPS_DBGTRACE();
/*
@@ -282,8 +312,8 @@ static void OnData(uv_stream_t* socket, ssize_t nread, const uv_buf_t* buf)
static void OnIncomingConnection(uv_stream_t* stream, int status)
{
int ret;
- DPS_NetContext* netCtx = (DPS_NetContext*)stream->data;
- DPS_NetConnection* cn;
+ DPS_NetTcpContext* netCtx = (DPS_NetTcpContext*)stream->data;
+ DPS_NetTcpConnection* cn;
int sz = sizeof(cn->peerEp.addr.u.inaddr);
DPS_DBGTRACE();
@@ -296,11 +326,13 @@ static void OnIncomingConnection(uv_stream_t* stream, int status)
goto FailConnection;
}
- cn = calloc(1, sizeof(DPS_NetConnection));
+ cn = calloc(1, sizeof(DPS_NetTcpConnection));
if (!cn) {
DPS_ERRPRINT("OnIncomingConnection malloc failed\n");
goto FailConnection;
}
+ cn->cn.incRef = DPS_NetTcpConnectionIncRef;
+ cn->cn.decRef = DPS_NetTcpConnectionDecRef;
ret = uv_tcp_init(stream->loop, &cn->socket);
if (ret) {
DPS_ERRPRINT("uv_tcp_init error=%s\n", uv_err_name(ret));
@@ -309,7 +341,7 @@ static void OnIncomingConnection(uv_stream_t* stream, int status)
}
cn->node = netCtx->node;
cn->socket.data = cn;
- cn->peerEp.cn = cn;
+ cn->peerEp.cn = (DPS_NetConnection*)cn;
DPS_QueueInit(&cn->sendQueue);
DPS_QueueInit(&cn->sendCompletedQueue);
uv_idle_init(stream->loop, &cn->idle);
@@ -367,17 +399,21 @@ static int GetScopeId(struct sockaddr_in6* addr)
#define LISTEN_BACKLOG 2
-DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_OnReceive cb)
+DPS_NetContext* DPS_NetTcpStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_OnReceive cb)
{
+ static struct sockaddr_storage sszero = { 0 };
int ret;
- DPS_NetContext* netCtx;
+ DPS_NetTcpContext* netCtx;
struct sockaddr* sa;
DPS_NodeAddress any;
- netCtx = calloc(1, sizeof(DPS_NetContext));
+ netCtx = calloc(1, sizeof(DPS_NetTcpContext));
if (!netCtx) {
return NULL;
}
+ netCtx->ctx.getListenAddress = DPS_NetTcpGetListenAddress;
+ netCtx->ctx.stop = DPS_NetTcpStop;
+ netCtx->ctx.send = DPS_NetTcpSend;
ret = uv_tcp_init(node->loop, &netCtx->socket);
if (ret) {
DPS_ERRPRINT("uv_tcp_init error=%s\n", uv_err_name(ret));
@@ -386,10 +422,10 @@ DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_On
}
netCtx->node = node;
netCtx->receiveCB = cb;
- if (addr) {
+ if (addr && memcmp(&addr->u.inaddr, &sszero, sizeof(struct sockaddr_storage))) {
sa = (struct sockaddr*)&addr->u.inaddr;
} else {
- if (!DPS_SetAddress(&any, "[::]:0")) {
+ if (!DPS_SetAddress(&any, "tcp", "[::]:0")) {
goto ErrorExit;
}
sa = (struct sockaddr*)&any.u.inaddr;
@@ -410,7 +446,7 @@ DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_On
*/
signal(SIGPIPE, SIG_IGN);
#endif
- return netCtx;
+ return (DPS_NetContext*)netCtx;
ErrorExit:
@@ -420,8 +456,9 @@ DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_On
return NULL;
}
-DPS_NodeAddress* DPS_NetGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext* netCtx)
+DPS_NodeAddress* DPS_NetTcpGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext* ctx)
{
+ DPS_NetTcpContext* netCtx = (DPS_NetTcpContext*)ctx;
int len;
DPS_DBGTRACEA("netCtx=%p\n", netCtx);
@@ -439,8 +476,10 @@ DPS_NodeAddress* DPS_NetGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext*
return addr;
}
-void DPS_NetStop(DPS_NetContext* netCtx)
+void DPS_NetTcpStop(DPS_NetContext* ctx)
{
+ DPS_NetTcpContext* netCtx = (DPS_NetTcpContext*)ctx;
+
if (netCtx) {
netCtx->socket.data = netCtx;
uv_close((uv_handle_t*)&netCtx->socket, ListenSocketClosed);
@@ -450,7 +489,7 @@ void DPS_NetStop(DPS_NetContext* netCtx)
static void OnWriteComplete(uv_write_t* writeReq, int status)
{
SendRequest* req = (SendRequest*)writeReq->data;
- DPS_NetConnection* cn = req->cn;
+ DPS_NetTcpConnection* cn = req->cn;
if (status) {
DPS_DBGPRINT("OnWriteComplete status=%s\n", uv_err_name(status));
@@ -460,10 +499,10 @@ static void OnWriteComplete(uv_write_t* writeReq, int status)
}
DPS_QueuePushBack(&cn->sendCompletedQueue, &req->queue);
SendCompleted(cn);
- DPS_NetConnectionDecRef(cn);
+ ConnectionDecRef(cn);
}
-static void DoSend(DPS_NetConnection* cn)
+static void DoSend(DPS_NetTcpConnection* cn)
{
while (!DPS_QueueEmpty(&cn->sendQueue)) {
SendRequest* req = (SendRequest*)DPS_QueueFront(&cn->sendQueue);
@@ -472,7 +511,7 @@ static void DoSend(DPS_NetConnection* cn)
int r = uv_write(&req->writeReq, (uv_stream_t*)&cn->socket, req->bufs, (uint32_t)req->numBufs,
OnWriteComplete);
if (r == 0) {
- DPS_NetConnectionIncRef(cn);
+ ConnectionIncRef(cn);
} else {
DPS_ERRPRINT("DoSend - write failed: %s\n", uv_err_name(r));
req->status = DPS_ERR_NETWORK;
@@ -483,7 +522,7 @@ static void DoSend(DPS_NetConnection* cn)
static void OnOutgoingConnection(uv_connect_t *req, int status)
{
- DPS_NetConnection* cn = (DPS_NetConnection*)req->data;
+ DPS_NetTcpConnection* cn = (DPS_NetTcpConnection*)req->data;
if (status == 0) {
cn->socket.data = cn;
status = uv_read_start((uv_stream_t*)&cn->socket, AllocBuffer, OnData);
@@ -499,12 +538,13 @@ static void OnOutgoingConnection(uv_connect_t *req, int status)
SendCompleted(cn);
}
-DPS_Status DPS_NetSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf_t* bufs,
- size_t numBufs, DPS_NetSendComplete sendCompleteCB)
+DPS_Status DPS_NetTcpSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf_t* bufs,
+ size_t numBufs, DPS_NetSendComplete sendCompleteCB)
{
DPS_Status ret;
DPS_TxBuffer lenBuf;
SendRequest* req;
+ DPS_NetTcpConnection* cn = NULL;
uv_handle_t* socket = NULL;
int r;
size_t i;
@@ -546,35 +586,38 @@ DPS_Status DPS_NetSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf
* See if we already have a connection
*/
if (ep->cn) {
- req->cn = ep->cn;
+ cn = (DPS_NetTcpConnection*)ep->cn;
+ req->cn = cn;
/*
* If there are pending sends the connection is not up yet
*/
- if (!DPS_QueueEmpty(&ep->cn->sendQueue)) {
- DPS_QueuePushBack(&ep->cn->sendQueue, &req->queue);
+ if (!DPS_QueueEmpty(&cn->sendQueue)) {
+ DPS_QueuePushBack(&cn->sendQueue, &req->queue);
return DPS_OK;
}
- DPS_QueuePushBack(&ep->cn->sendQueue, &req->queue);
- DoSend(ep->cn);
- uv_idle_start(&ep->cn->idle, SendCompletedTask);
+ DPS_QueuePushBack(&cn->sendQueue, &req->queue);
+ DoSend(cn);
+ uv_idle_start(&cn->idle, SendCompletedTask);
return DPS_OK;
}
- ep->cn = calloc(1, sizeof(DPS_NetConnection));
- if (!ep->cn) {
+ cn = calloc(1, sizeof(DPS_NetTcpConnection));
+ if (!cn) {
goto ErrExit;
}
- r = uv_tcp_init(node->loop, &ep->cn->socket);
+ cn->cn.incRef = DPS_NetTcpConnectionIncRef;
+ cn->cn.decRef = DPS_NetTcpConnectionDecRef;
+ r = uv_tcp_init(node->loop, &cn->socket);
if (r) {
goto ErrExit;
}
- ep->cn->peerEp.addr = ep->addr;
- ep->cn->node = node;
- DPS_QueueInit(&ep->cn->sendQueue);
- DPS_QueueInit(&ep->cn->sendCompletedQueue);
- uv_idle_init(node->loop, &ep->cn->idle);
- ep->cn->idle.data = ep->cn;
- socket = (uv_handle_t*)&ep->cn->socket;
+ cn->peerEp.addr = ep->addr;
+ cn->node = node;
+ DPS_QueueInit(&cn->sendQueue);
+ DPS_QueueInit(&cn->sendCompletedQueue);
+ uv_idle_init(node->loop, &cn->idle);
+ cn->idle.data = cn;
+ socket = (uv_handle_t*)&cn->socket;
if (ep->addr.u.inaddr.ss_family == AF_INET6) {
struct sockaddr_in6* in6 = (struct sockaddr_in6*)&ep->addr.u.inaddr;
@@ -582,17 +625,18 @@ DPS_Status DPS_NetSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf
in6->sin6_scope_id = GetScopeId(in6);
}
}
- ep->cn->connectReq.data = ep->cn;
- r = uv_tcp_connect(&ep->cn->connectReq, &ep->cn->socket, (struct sockaddr*)&ep->addr.u.inaddr,
+ cn->connectReq.data = cn;
+ r = uv_tcp_connect(&cn->connectReq, &cn->socket, (struct sockaddr*)&ep->addr.u.inaddr,
OnOutgoingConnection);
if (r) {
DPS_ERRPRINT("uv_tcp_connect %s error=%s\n", DPS_NodeAddrToString(&ep->addr), uv_err_name(r));
goto ErrExit;
}
- ep->cn->peerEp.cn = ep->cn;
- DPS_QueuePushBack(&ep->cn->sendQueue, &req->queue);
- req->cn = ep->cn;
- DPS_NetConnectionIncRef(ep->cn);
+ cn->peerEp.cn = (DPS_NetConnection*)cn;
+ DPS_QueuePushBack(&cn->sendQueue, &req->queue);
+ req->cn = cn;
+ ConnectionIncRef(cn);
+ ep->cn = (DPS_NetConnection*)cn;
return DPS_OK;
ErrExit:
@@ -601,32 +645,28 @@ DPS_Status DPS_NetSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf
free(req);
}
if (socket) {
- socket->data = ep->cn;
+ socket->data = cn;
uv_close(socket, StreamClosed);
} else {
- if (ep->cn) {
- free(ep->cn);
+ if (cn) {
+ free(cn);
}
}
ep->cn = NULL;
return DPS_ERR_NETWORK;
}
-void DPS_NetConnectionIncRef(DPS_NetConnection* cn)
+void DPS_NetTcpConnectionIncRef(DPS_NetConnection* cn)
{
- if (cn) {
- DPS_DBGTRACE();
- ++cn->refCount;
- }
+ ConnectionIncRef((DPS_NetTcpConnection*)cn);
}
-void DPS_NetConnectionDecRef(DPS_NetConnection* cn)
+void DPS_NetTcpConnectionDecRef(DPS_NetConnection* cn)
{
- if (cn) {
- DPS_DBGTRACE();
- assert(cn->refCount > 0);
- if (--cn->refCount == 0) {
- Shutdown(cn);
- }
- }
+ ConnectionDecRef((DPS_NetTcpConnection*)cn);
}
+
+DPS_NetTransport DPS_NetTcpTransport = {
+ DPS_TCP,
+ DPS_NetTcpStart
+};
diff --git a/src/udp/network.c b/src/udp/network.c
index 2c77a01d..f322eac4 100755
--- a/src/udp/network.c
+++ b/src/udp/network.c
@@ -36,11 +36,17 @@ DPS_DEBUG_CONTROL(DPS_DEBUG_ON);
#define MAX_READ_LEN 65536
-struct _DPS_NetContext {
+typedef struct _DPS_NetUdpContext {
+ DPS_NetContext ctx;
uv_udp_t rxSocket;
DPS_Node* node;
DPS_OnReceive receiveCB;
-};
+} DPS_NetUdpContext;
+
+DPS_NodeAddress* DPS_NetUdpGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext* netCtx);
+void DPS_NetUdpStop(DPS_NetContext* netCtx);
+DPS_Status DPS_NetUdpSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf_t* bufs,
+ size_t numBufs, DPS_NetSendComplete sendCompleteCB);
static void AllocBuffer(uv_handle_t* handle, size_t suggestedSize, uv_buf_t* uvBuf)
{
@@ -63,7 +69,7 @@ static void RxHandleClosed(uv_handle_t* handle)
static void OnData(uv_udp_t* socket, ssize_t nread, const uv_buf_t* uvBuf, const struct sockaddr* addr,
unsigned flags)
{
- DPS_NetContext* netCtx = (DPS_NetContext*)socket->data;
+ DPS_NetUdpContext* netCtx = (DPS_NetUdpContext*)socket->data;
DPS_NetRxBuffer* buf = NULL;
DPS_NetEndpoint ep;
@@ -98,17 +104,21 @@ static void OnData(uv_udp_t* socket, ssize_t nread, const uv_buf_t* uvBuf, const
DPS_NetRxBufferDecRef(buf);
}
-DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_OnReceive cb)
+DPS_NetContext* DPS_NetUdpStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_OnReceive cb)
{
+ static struct sockaddr_storage sszero = { 0 };
int ret;
- DPS_NetContext* netCtx;
+ DPS_NetUdpContext* netCtx;
struct sockaddr* sa;
DPS_NodeAddress any;
- netCtx = calloc(1, sizeof(DPS_NetContext));
+ netCtx = calloc(1, sizeof(DPS_NetUdpContext));
if (!netCtx) {
return NULL;
}
+ netCtx->ctx.getListenAddress = DPS_NetUdpGetListenAddress;
+ netCtx->ctx.stop = DPS_NetUdpStop;
+ netCtx->ctx.send = DPS_NetUdpSend;
ret = uv_udp_init(node->loop, &netCtx->rxSocket);
if (ret) {
DPS_ERRPRINT("uv_udp_init error=%s\n", uv_err_name(ret));
@@ -117,10 +127,10 @@ DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_On
}
netCtx->node = node;
netCtx->receiveCB = cb;
- if (addr) {
+ if (addr && memcmp(&addr->u.inaddr, &sszero, sizeof(struct sockaddr_storage))) {
sa = (struct sockaddr*)&addr->u.inaddr;
} else {
- if (!DPS_SetAddress(&any, "[::]:0")) {
+ if (!DPS_SetAddress(&any, "udp", "[::]:0")) {
goto ErrorExit;
}
sa = (struct sockaddr*)&any.u.inaddr;
@@ -134,7 +144,7 @@ DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_On
if (ret) {
goto ErrorExit;
}
- return netCtx;
+ return (DPS_NetContext*)netCtx;
ErrorExit:
@@ -143,8 +153,9 @@ DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_On
return NULL;
}
-DPS_NodeAddress* DPS_NetGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext* netCtx)
+DPS_NodeAddress* DPS_NetUdpGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext* ctx)
{
+ DPS_NetUdpContext* netCtx = (DPS_NetUdpContext*)ctx;
int len;
DPS_DBGTRACEA("netCtx=%p\n", netCtx);
@@ -162,8 +173,10 @@ DPS_NodeAddress* DPS_NetGetListenAddress(DPS_NodeAddress* addr, DPS_NetContext*
return addr;
}
-void DPS_NetStop(DPS_NetContext* netCtx)
+void DPS_NetUdpStop(DPS_NetContext* ctx)
{
+ DPS_NetUdpContext* netCtx = (DPS_NetUdpContext*)ctx;
+
if (netCtx) {
uv_udp_recv_stop(&netCtx->rxSocket);
uv_close((uv_handle_t*)&netCtx->rxSocket, RxHandleClosed);
@@ -195,8 +208,10 @@ static void OnSendComplete(uv_udp_send_t* req, int status)
free(send);
}
-DPS_Status DPS_NetSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf_t* bufs, size_t numBufs, DPS_NetSendComplete sendCompleteCB)
+DPS_Status DPS_NetUdpSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf_t* bufs,
+ size_t numBufs, DPS_NetSendComplete sendCompleteCB)
{
+ DPS_NetUdpContext* netCtx = (DPS_NetUdpContext*)node->netCtx;
int ret;
NetSend* send;
@@ -231,7 +246,7 @@ DPS_Status DPS_NetSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf
memcpy_s(&inaddr, sizeof(inaddr), &ep->addr.u.inaddr, sizeof(ep->addr.u.inaddr));
DPS_MapAddrToV6((struct sockaddr *)&inaddr);
- ret = uv_udp_send(&send->sendReq, &node->netCtx->rxSocket, send->bufs, (uint32_t)numBufs,
+ ret = uv_udp_send(&send->sendReq, &netCtx->rxSocket, send->bufs, (uint32_t)numBufs,
(const struct sockaddr *)&inaddr, OnSendComplete);
if (ret) {
DPS_ERRPRINT("DPS_NetSend status=%s\n", uv_err_name(ret));
@@ -241,12 +256,7 @@ DPS_Status DPS_NetSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv_buf
return DPS_OK;
}
-void DPS_NetConnectionIncRef(DPS_NetConnection* cn)
-{
- /* No-op for udp */
-}
-
-void DPS_NetConnectionDecRef(DPS_NetConnection* cn)
-{
- /* No-op for udp */
-}
+DPS_NetTransport DPS_NetUdpTransport = {
+ DPS_UDP,
+ DPS_NetUdpStart
+};
diff --git a/swig/dps.i b/swig/dps.i
index 7b07b867..42eb4e32 100644
--- a/swig/dps.i
+++ b/swig/dps.i
@@ -118,6 +118,7 @@ public:
Handler* m_caHandler;
};
+static int AsCharOrNullPtr(Handle obj, char** cptr, int *alloc);
static int AsVal_bytes(Handle obj, uint8_t** bytes, size_t* len);
static int AsSafeVal_bytes(Handle obj, uint8_t** bytes, size_t* len);
static Handle From_bytes(const uint8_t* bytes, size_t len);
@@ -658,6 +659,30 @@ DPS_Status CBOR2JSON(const uint8_t* cbor, size_t len, int pretty, char** json);
$1 = 0;
}
+/*
+ * Strings that may be NULL need special handling.
+ */
+
+%typemap(in) const char* network (int res = 0) {
+ res = AsCharOrNullPtr($input, &$1);
+ if (!SWIG_IsOK(res)) {
+ SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum"" of type '" "$1_type""'");
+ }
+}
+%typemap(freearg) const char* network {
+ if (SWIG_IsNewObj(res$argnum)) delete[] $1;
+}
+
+%typemap(in) const char* addrText (int res = 0) {
+ res = AsCharOrNullPtr($input, &$1);
+ if (!SWIG_IsOK(res)) {
+ SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum"" of type '" "$1_type""'");
+ }
+}
+%typemap(freearg) const char* addrText {
+ if (SWIG_IsNewObj(res$argnum)) delete[] $1;
+}
+
%{
class Buffer {
public:
diff --git a/swig/js/dps_impl.i b/swig/js/dps_impl.i
index 74992597..e129342f 100644
--- a/swig/js/dps_impl.i
+++ b/swig/js/dps_impl.i
@@ -87,6 +87,21 @@ static Handle From_topics(const char** topics, size_t len)
return arr;
}
+static int AsCharOrNullPtr(Handle obj, char** cptr)
+{
+ if (obj->IsNull()) {
+ *cptr = NULL;
+ return SWIG_OK;
+ } else {
+ int alloc;
+ int res = SWIG_AsCharPtrAndSize(obj, cptr, NULL, &alloc);
+ if (SWIG_IsOK(res)) {
+ return alloc;
+ }
+ return res;
+ }
+}
+
class Callback {
public:
std::condition_variable* m_cond;
diff --git a/swig/py/dps_impl.i b/swig/py/dps_impl.i
index 51b4003a..b406fd53 100644
--- a/swig/py/dps_impl.i
+++ b/swig/py/dps_impl.i
@@ -94,6 +94,21 @@ static Handle From_topics(const char** topics, size_t len)
return list;
}
+static int AsCharOrNullPtr(Handle obj, char** cptr)
+{
+ if (obj == Py_None) {
+ *cptr = NULL;
+ return SWIG_OK;
+ } else {
+ int alloc;
+ int res = SWIG_AsCharPtrAndSize(obj, cptr, NULL, &alloc);
+ if (SWIG_IsOK(res)) {
+ return alloc;
+ }
+ return res;
+ }
+}
+
static DPS_Status KeyAndIdHandler(DPS_KeyStoreRequest* request)
{
KeyStore* keyStore = (KeyStore*)DPS_GetKeyStoreData(DPS_KeyStoreHandle(request));
diff --git a/test/dtls_fuzzer.c b/test/dtls_fuzzer.c
index e8064165..bf03cce8 100644
--- a/test/dtls_fuzzer.c
+++ b/test/dtls_fuzzer.c
@@ -97,6 +97,7 @@ static void DestroyNode(Node* node)
static Node* CreateNode()
{
Node* node = NULL;
+ DPS_NodeAddress* addr = NULL;
DPS_Status ret;
node = calloc(1, sizeof(Node));
@@ -116,13 +117,22 @@ static Node* CreateNode()
goto ErrorExit;
}
DPS_SetNodeSubscriptionUpdateDelay(node->node, 10);
- ret = DPS_StartNode(node->node, DPS_MCAST_PUB_ENABLE_SEND | DPS_MCAST_PUB_ENABLE_RECV, NULL);
+ addr = DPS_CreateAddress();
+ if (!addr) {
+ goto ErrorExit;
+ }
+ if (!DPS_SetAddress(addr, "dtls", NULL)) {
+ goto ErrorExit;
+ }
+ ret = DPS_StartNode(node->node, DPS_MCAST_PUB_ENABLE_SEND | DPS_MCAST_PUB_ENABLE_RECV, addr);
if (ret != DPS_OK) {
goto ErrorExit;
}
+ DPS_DestroyAddress(addr);
return node;
ErrorExit:
+ DPS_DestroyAddress(addr);
DestroyNode(node);
return NULL;
}
@@ -184,6 +194,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len)
DPS_Subscription* sub = NULL;
DPS_Publication* pub = NULL;
const char *topic = "T";
+ const DPS_NodeAddress* serverAddr = NULL;
DPS_NodeAddress* addr = NULL;
DPS_Status ret;
@@ -228,11 +239,12 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len)
goto Exit;
}
+ serverAddr = DPS_GetListenAddress(server->node);
addr = DPS_CreateAddress();
if (!addr) {
goto Exit;
}
- DPS_LinkTo(client->node, DPS_GetListenAddressString(server->node), addr);
+ DPS_LinkTo(client->node, DPS_NodeAddrNetwork(serverAddr), DPS_NodeAddrToString(serverAddr), addr);
Exit:
DPS_DestroyAddress(addr);
diff --git a/test/link.c b/test/link.c
index 7592096b..8cd4c7ad 100644
--- a/test/link.c
+++ b/test/link.c
@@ -59,6 +59,7 @@ static void TestRemoteLinkedAlready(void)
DPS_MemoryKeyStore* memoryKeyStore = NULL;
DPS_Node* a = NULL;
DPS_Node* b = NULL;
+ const DPS_NodeAddress* dst = NULL;
DPS_NodeAddress* addr = NULL;
DPS_Status ret;
@@ -68,13 +69,15 @@ static void TestRemoteLinkedAlready(void)
a = CreateNode(DPS_MemoryKeyStoreHandle(memoryKeyStore));
b = CreateNode(DPS_MemoryKeyStoreHandle(memoryKeyStore));
+ dst = DPS_GetListenAddress(b);
addr = DPS_CreateAddress();
- ret = DPS_LinkTo(a, DPS_GetListenAddressString(b), addr);
+ ret = DPS_LinkTo(a, DPS_NodeAddrNetwork(dst), DPS_NodeAddrToString(dst), addr);
ASSERT(ret == DPS_OK);
DPS_DestroyAddress(addr);
+ dst = DPS_GetListenAddress(a);
addr = DPS_CreateAddress();
- ret = DPS_LinkTo(b, DPS_GetListenAddressString(a), addr);
+ ret = DPS_LinkTo(b, DPS_NodeAddrNetwork(dst), DPS_NodeAddrToString(dst), addr);
ASSERT(ret == DPS_OK);
DPS_DestroyAddress(addr);
diff --git a/test/make_mesh.c b/test/make_mesh.c
index 62d798cd..b8dd2821 100644
--- a/test/make_mesh.c
+++ b/test/make_mesh.c
@@ -74,8 +74,7 @@ static void OnPubMatch(DPS_Subscription* sub, const DPS_Publication* pub, uint8_
if (DPS_PublicationIsAckRequested(pub)) {
char ackMsg[sizeof(AckFmt) + 64];
- sprintf(ackMsg, AckFmt,
- DPS_GetListenAddressString(DPS_PublicationGetNode(pub)));
+ sprintf(ackMsg, AckFmt, DPS_GetListenAddressString(DPS_PublicationGetNode(pub)));
ret = DPS_AckPublication(pub, (uint8_t*)ackMsg, sizeof(ackMsg));
if (ret != DPS_OK) {
DPS_PRINT("Failed to ack pub %s\n", DPS_ErrTxt(ret));
@@ -446,11 +445,12 @@ static void OnLinked(DPS_Node* node, DPS_NodeAddress* addr, DPS_Status status, v
static DPS_Status LinkNodes(DPS_Node* src, DPS_Node* dst)
{
DPS_Status ret;
- ret = DPS_Link(src, DPS_GetListenAddressString(dst), OnLinked, NULL);
+ const DPS_NodeAddress* addr;
+ addr = DPS_GetListenAddress(dst);
+ ret = DPS_Link(src, DPS_NodeAddrNetwork(addr), DPS_NodeAddrToString(addr), OnLinked, NULL);
if (ret != DPS_OK) {
uv_mutex_lock(&lock);
- DPS_ERRPRINT("DPS_Link for %s returned %s\n", DPS_GetListenAddressString(dst),
- DPS_ErrTxt(ret));
+ DPS_ERRPRINT("DPS_Link for %s returned %s\n", DPS_NodeAddrToString(addr), DPS_ErrTxt(ret));
++LinksFailed;
uv_mutex_unlock(&lock);
}
@@ -481,6 +481,7 @@ int main(int argc, char** argv)
int expMuted;
int l1 = 0;
int l2 = 0;
+ const char* network = NULL;
const char* inFn = NULL;
const char* outFn = NULL;
uint16_t killList[MAX_KILLS];
@@ -490,6 +491,9 @@ int main(int argc, char** argv)
DPS_Debug = 0;
while (--argc) {
+ if (StrArg("-f", &arg, &argc, &network)) {
+ continue;
+ }
if (StrArg("-f", &arg, &argc, &inFn)) {
continue;
}
@@ -554,7 +558,7 @@ int main(int argc, char** argv)
DPS_ERRPRINT("Failed to create address: %s\n", DPS_ErrTxt(DPS_ERR_RESOURCES));
return 1;
}
- DPS_SetAddress(listenAddr, "[::1]:0");
+ DPS_SetAddress(listenAddr, network, NULL);
ret = DPS_StartNode(node, DPS_FALSE, listenAddr);
DPS_DestroyAddress(listenAddr);
if (ret != DPS_OK) {
diff --git a/test/mesh_stress.c b/test/mesh_stress.c
index f09876c8..b0e7082c 100644
--- a/test/mesh_stress.c
+++ b/test/mesh_stress.c
@@ -259,11 +259,12 @@ static void OnLinked(DPS_Node* node, DPS_NodeAddress* addr, DPS_Status status, v
static DPS_Status LinkNodes(DPS_Node* src, DPS_Node* dst)
{
DPS_Status ret;
- ret = DPS_Link(src, DPS_GetListenAddressString(dst), OnLinked, NULL);
+ const DPS_NodeAddress* addr;
+ addr = DPS_GetListenAddress(dst);
+ ret = DPS_Link(src, DPS_NodeAddrNetwork(addr), DPS_NodeAddrToString(addr), OnLinked, NULL);
if (ret != DPS_OK) {
uv_mutex_lock(&lock);
- DPS_ERRPRINT("DPS_Link for %s returned %s\n", DPS_GetListenAddressString(dst),
- DPS_ErrTxt(ret));
+ DPS_ERRPRINT("DPS_Link for %s returned %s\n", DPS_NodeAddrToString(addr), DPS_ErrTxt(ret));
++LinksFailed;
uv_mutex_unlock(&lock);
}
@@ -281,12 +282,16 @@ int main(int argc, char** argv)
int numIds = 0;
int numMuted = 0;
int expMuted;
+ const char* network = NULL;
const char* inFn = NULL;
int i;
DPS_Debug = 0;
while (--argc) {
+ if (StrArg("-n", &arg, &argc, &network)) {
+ continue;
+ }
if (StrArg("-f", &arg, &argc, &inFn)) {
continue;
}
@@ -345,7 +350,7 @@ int main(int argc, char** argv)
DPS_ERRPRINT("Failed to create address: %s\n", DPS_ErrTxt(DPS_ERR_RESOURCES));
return EXIT_FAILURE;
}
- DPS_SetAddress(listenAddr, "[::1]:0");
+ DPS_SetAddress(listenAddr, network, NULL);
ret = DPS_StartNode(node, DPS_FALSE, listenAddr);
DPS_DestroyAddress(listenAddr);
if (ret != DPS_OK) {
diff --git a/test/node.c b/test/node.c
index c0d70754..5e383bbb 100644
--- a/test/node.c
+++ b/test/node.c
@@ -169,6 +169,8 @@ int main(int argc, char** argv)
char* pubs[MAX_TOPICS];
size_t numPubs = 0;
DPS_AcknowledgementHandler ackHandler = AcknowledgementHandler;
+ char* network = NULL;
+ char* listenText = NULL;
DPS_NodeAddress* listenAddr = NULL;
DPS_Node* node = NULL;
const Id* self = NULL;
@@ -201,7 +203,13 @@ int main(int argc, char** argv)
goto Usage;
}
pubs[numPubs++] = *arg++;
- } else if (AddressArg("-l", &arg, &argc, &listenAddr)) {
+ } else if (strcmp(*arg, "-n") == 0) {
+ ++arg;
+ if (!--argc) {
+ goto Usage;
+ }
+ network = *arg++;
+ } else if (AddressArg("-l", &arg, &argc, &listenText)) {
} else {
goto Usage;
}
@@ -229,6 +237,11 @@ int main(int argc, char** argv)
ret = DPS_ERR_RESOURCES;
goto Exit;
}
+ listenAddr = CreateAddressFromArg(network, listenText);
+ if (!listenAddr) {
+ ret = DPS_ERR_RESOURCES;
+ goto Exit;
+ }
ret = DPS_StartNode(node, mcast, listenAddr);
if (ret != DPS_OK) {
goto Exit;
@@ -290,11 +303,12 @@ int main(int argc, char** argv)
return ret;
Usage:
- DPS_PRINT("Usage %s [-d] [-u ] [-s ] [-p ] [-l ]\n", argv[0]);
+ DPS_PRINT("Usage %s [-d] [-u ] [-s ] [-p ] [-n ] [-l ]\n", argv[0]);
DPS_PRINT(" -d: Enable debug ouput if built for debug.\n");
DPS_PRINT(" -u: Set user ID.\n");
DPS_PRINT(" -s: Subscribe to topic. May be repeated.\n");
DPS_PRINT(" -p: Publish to topic. May be repeated.\n");
+ DPS_PRINT(" -n: Network of listen and link addresses.\n");
DPS_PRINT(" -l: Address to listen on for incoming connections.\n");
return DPS_ERR_FAILURE;
}
diff --git a/test/packtest.c b/test/packtest.c
index eba7b63f..95aee5a9 100644
--- a/test/packtest.c
+++ b/test/packtest.c
@@ -173,9 +173,16 @@ int main(int argc, char** argv)
int i = 1;
DPS_Debug = DPS_FALSE;
- if ((i < argc) && !strcmp(argv[i], "-d")) {
- DPS_Debug = DPS_TRUE;
- ++i;
+ while (i < argc) {
+ if (!strcmp(argv[i], "-d")) {
+ DPS_Debug = DPS_TRUE;
+ ++i;
+ } else if (!strcmp(argv[i], "-n") && ((i + 1) < argc)) {
+ /* Ignore the network argument for compatibility with other tests */
+ i += 2;
+ } else {
+ break;
+ }
}
if (i < argc) {
filterBits = atoi(argv[i]);
diff --git a/test/perf/publisher.c b/test/perf/publisher.c
index 4b670148..5fba5bf5 100644
--- a/test/perf/publisher.c
+++ b/test/perf/publisher.c
@@ -96,6 +96,7 @@ int main(int argc, char** argv)
uint8_t* payload = NULL;
int payloadSize = 0;
int mcast = DPS_MCAST_PUB_ENABLE_SEND;
+ char* network = NULL;
int listenPort = 0;
DPS_NodeAddress* listenAddr = NULL;
char addrText[24];
@@ -111,6 +112,14 @@ int main(int argc, char** argv)
DPS_Debug = DPS_TRUE;
continue;
}
+ if (strcmp(*arg, "-n") == 0) {
+ ++arg;
+ if (!--argc) {
+ goto Usage;
+ }
+ network = *arg++;
+ continue;
+ }
if (strcmp(*arg, "-p") == 0) {
++arg;
if (!--argc) {
@@ -122,7 +131,7 @@ int main(int argc, char** argv)
if (IntArg("-s", &arg, &argc, &payloadSize, 0, UINT16_MAX)) {
continue;
}
- if (IntArg("-n", &arg, &argc, &numPubs, 1, 1000000)) {
+ if (IntArg("-c", &arg, &argc, &numPubs, 1, 1000000)) {
continue;
}
}
@@ -140,7 +149,7 @@ int main(int argc, char** argv)
return 1;
}
snprintf(addrText, sizeof(addrText), "[::]:%d", listenPort);
- DPS_SetAddress(listenAddr, addrText);
+ DPS_SetAddress(listenAddr, network, addrText);
ret = DPS_StartNode(node, mcast, listenAddr);
if (ret != DPS_OK) {
DPS_ERRPRINT("DPS_StartNode failed: %s\n", DPS_ErrTxt(ret));
@@ -148,7 +157,7 @@ int main(int argc, char** argv)
}
for (i = 0; i < numLinks; ++i) {
- ret = DPS_LinkTo(node, linkText[i], NULL);
+ ret = DPS_LinkTo(node, network, linkText[i], NULL);
if (ret != DPS_OK) {
DPS_ERRPRINT("DPS_LinkTo %s returned %s\n", linkText[i], DPS_ErrTxt(ret));
return 1;
@@ -205,9 +214,10 @@ int main(int argc, char** argv)
return 0;
Usage:
- DPS_PRINT("Usage %s [-d] [-n ] [-p ] [-s ]\n", argv[0]);
+ DPS_PRINT("Usage %s [-d] [-c ] [-n ] [-p ] [-s ]\n", argv[0]);
DPS_PRINT(" -d: Enable debug ouput if built for debug.\n");
- DPS_PRINT(" -n: Number of publications to send.\n");
+ DPS_PRINT(" -c: Number of publications to send.\n");
+ DPS_PRINT(" -n: Network of listen and link addresses.\n");
DPS_PRINT(" -p: port to link.\n");
DPS_PRINT(" -s: Size of PUB payload.\n");
return 1;
diff --git a/test/perf/subscriber.c b/test/perf/subscriber.c
index e13df017..9c4434f0 100644
--- a/test/perf/subscriber.c
+++ b/test/perf/subscriber.c
@@ -68,6 +68,7 @@ int main(int argc, char** argv)
char** arg = argv + 1;
DPS_Event* nodeDestroyed = NULL;
DPS_Subscription* subscription = NULL;
+ char* network = NULL;
int listenPort = 0;
DPS_NodeAddress* listenAddr = NULL;
char addrText[24];
@@ -81,6 +82,14 @@ int main(int argc, char** argv)
DPS_Debug = DPS_TRUE;
continue;
}
+ if (strcmp(*arg, "-n") == 0) {
+ ++arg;
+ if (!--argc) {
+ goto Usage;
+ }
+ network = *arg++;
+ continue;
+ }
if (IntArg("-s", &arg, &argc, &payloadSize, -1, UINT16_MAX)) {
continue;
}
@@ -101,7 +110,7 @@ int main(int argc, char** argv)
goto Exit;
}
snprintf(addrText, sizeof(addrText), "[::]:%d", listenPort);
- DPS_SetAddress(listenAddr, addrText);
+ DPS_SetAddress(listenAddr, network, addrText);
ret = DPS_StartNode(node, DPS_MCAST_PUB_ENABLE_RECV, listenAddr);
if (ret != DPS_OK) {
DPS_ERRPRINT("Failed to start node: %s\n", DPS_ErrTxt(ret));
@@ -126,8 +135,9 @@ int main(int argc, char** argv)
return (ret == DPS_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
Usage:
- DPS_PRINT("Usage %s [-d] [-s ]\n", argv[0]);
+ DPS_PRINT("Usage %s [-d] [-n ] [-p ] [-s ]\n", argv[0]);
DPS_PRINT(" -d: Enable debug ouput if built for debug.\n");
+ DPS_PRINT(" -n: Network of listen and link addresses.\n");
DPS_PRINT(" -p: port to listen on.\n");
DPS_PRINT(" -s: Size of ACK payload.\n");
return EXIT_FAILURE;
diff --git a/test/publish.c b/test/publish.c
index 0101a374..3b093282 100644
--- a/test/publish.c
+++ b/test/publish.c
@@ -289,7 +289,6 @@ static void TestBackToBackPublish(DPS_Node* node, DPS_KeyStore* keyStore)
DPS_DestroyPublication(pub);
}
-#if defined(DPS_USE_TCP)
static void OnLinkComplete(DPS_Node* node, DPS_NodeAddress* addr, DPS_Status status, void* data)
{
if (data) {
@@ -310,6 +309,10 @@ static void TestBackToBackPublishSeparateNodes(DPS_Node* node, DPS_KeyStore* key
DPS_Status ret;
size_t i;
+ if (strcmp(DPS_NodeAddrNetwork(DPS_GetListenAddress(node)), "tcp")) {
+ return;
+ }
+
DPS_PRINT("%s\n", __FUNCTION__);
pub = CreatePublication(node, topics, numTopics, NULL);
@@ -319,8 +322,12 @@ static void TestBackToBackPublishSeparateNodes(DPS_Node* node, DPS_KeyStore* key
subNode = DPS_CreateNode("/.", keyStore, NULL);
ASSERT(subNode);
- ret = DPS_StartNode(subNode, DPS_MCAST_PUB_DISABLED, NULL);
+ addr = DPS_CreateAddress();
+ ASSERT(addr);
+ DPS_SetAddress(addr, "tcp", NULL);
+ ret = DPS_StartNode(subNode, DPS_MCAST_PUB_DISABLED, addr);
ASSERT(ret == DPS_OK);
+ DPS_DestroyAddress(addr);
sub = DPS_CreateSubscription(subNode, topics, numTopics);
ASSERT(sub);
@@ -331,8 +338,9 @@ static void TestBackToBackPublishSeparateNodes(DPS_Node* node, DPS_KeyStore* key
addr = DPS_CreateAddress();
ASSERT(addr);
- ret = DPS_LinkTo(subNode, DPS_GetListenAddressString(node), addr);
+ ret = DPS_LinkTo(subNode, "tcp", DPS_GetListenAddressString(node), addr);
ASSERT(ret == DPS_OK);
+ DPS_DestroyAddress(addr);
seqNum = DPS_PublicationGetSequenceNum(pub) + 1;
for (i = 0; i < depth; ++i) {
@@ -346,14 +354,12 @@ static void TestBackToBackPublishSeparateNodes(DPS_Node* node, DPS_KeyStore* key
*/
SLEEP(1000);
- DPS_DestroyAddress(addr);
DPS_DestroySubscription(sub);
DPS_DestroyNode(subNode, OnNodeDestroyed, event);
DPS_WaitForEvent(event);
DPS_DestroyEvent(event);
DPS_DestroyPublication(pub);
}
-#endif
static void TestRetainedMessage(DPS_Node* node, DPS_KeyStore* keyStore)
{
@@ -436,6 +442,8 @@ int main(int argc, char** argv)
DPS_Event* event = NULL;
DPS_MemoryKeyStore* memoryKeyStore = NULL;
DPS_Node *node = NULL;
+ char* network = NULL;
+ DPS_NodeAddress* addr = NULL;
DPS_Status ret;
DPS_Debug = DPS_FALSE;
@@ -443,6 +451,12 @@ int main(int argc, char** argv)
if (strcmp(*arg, "-d") == 0) {
++arg;
DPS_Debug = DPS_TRUE;
+ } else if (strcmp(*arg, "-n") == 0) {
+ ++arg;
+ if (!--argc) {
+ return EXIT_FAILURE;
+ }
+ network = *arg++;
}
}
@@ -454,8 +468,12 @@ int main(int argc, char** argv)
DPS_SetNetworkKey(memoryKeyStore, &NetworkKeyId, &NetworkKey);
node = DPS_CreateNode("/.", DPS_MemoryKeyStoreHandle(memoryKeyStore), NULL);
ASSERT(node);
- ret = DPS_StartNode(node, DPS_MCAST_PUB_ENABLE_SEND | DPS_MCAST_PUB_ENABLE_RECV, NULL);
+ addr = DPS_CreateAddress();
+ ASSERT(addr);
+ DPS_SetAddress(addr, network, NULL);
+ ret = DPS_StartNode(node, DPS_MCAST_PUB_ENABLE_SEND | DPS_MCAST_PUB_ENABLE_RECV, addr);
ASSERT(ret == DPS_OK);
+ DPS_DestroyAddress(addr);
(*test)(node, DPS_MemoryKeyStoreHandle(memoryKeyStore));
DPS_DestroyNode(node, OnNodeDestroyed, event);
DPS_WaitForEvent(event);
diff --git a/test/pubsub.c b/test/pubsub.c
index 5c4ba96d..e88d8795 100644
--- a/test/pubsub.c
+++ b/test/pubsub.c
@@ -85,7 +85,7 @@ int main(int argc, char** argv)
}
continue;
}
- if (strcmp(*arg, "-n") == 0) {
+ if (strcmp(*arg, "-c") == 0) {
++arg;
if (!--argc) {
goto Usage;
@@ -101,6 +101,15 @@ int main(int argc, char** argv)
DPS_Debug = DPS_TRUE;
continue;
}
+ if (strcmp(*arg, "-n") == 0) {
+ /* Ignore the network argument for compatibility with other tests */
+ ++arg;
+ if (!--argc) {
+ goto Usage;
+ }
+ ++arg;
+ continue;
+ }
goto Usage;
}
@@ -178,6 +187,6 @@ int main(int argc, char** argv)
return EXIT_SUCCESS;
Usage:
- DPS_PRINT("Usage %s: [-r] [-b ] [-n ]\n", argv[0]);
+ DPS_PRINT("Usage %s: [-r] [-b ] [-c ]\n", argv[0]);
return EXIT_FAILURE;
}
diff --git a/test/rle_compression.c b/test/rle_compression.c
index 0297c3ea..a98e1511 100644
--- a/test/rle_compression.c
+++ b/test/rle_compression.c
@@ -56,7 +56,7 @@ int main(int argc, char** argv)
}
continue;
}
- if (strcmp(*arg, "-n") == 0) {
+ if (strcmp(*arg, "-c") == 0) {
++arg;
if (!--argc) {
goto Usage;
@@ -72,6 +72,15 @@ int main(int argc, char** argv)
DPS_Debug = DPS_TRUE;
continue;
}
+ if (strcmp(*arg, "-n") == 0) {
+ /* Ignore the network argument for compatibility with other tests */
+ ++arg;
+ if (!--argc) {
+ goto Usage;
+ }
+ ++arg;
+ continue;
+ }
goto Usage;
}
@@ -104,6 +113,6 @@ int main(int argc, char** argv)
Usage:
- DPS_PRINT("Usage %s: [-d] [-b ] [-n ]\n", argv[0]);
+ DPS_PRINT("Usage %s: [-d] [-b ] [-c ]\n", argv[0]);
return EXIT_FAILURE;
}
diff --git a/test/test.c b/test/test.c
index 05dadde4..c4c45003 100644
--- a/test/test.c
+++ b/test/test.c
@@ -47,36 +47,41 @@ int IntArg(char* opt, char*** argp, int* argcp, int* val, int min, int max)
return 1;
}
-int AddressArg(char* opt, char*** argp, int* argcp, DPS_NodeAddress** addr)
+int AddressArg(char* opt, char*** argp, int* argcp, char** addrText)
{
char** arg = *argp;
int argc = *argcp;
int port = 0;
char str[256];
- strcpy(str, "[::]:0");
-
if (IntArg(opt, &arg, &argc, &port, 1000, UINT16_MAX)) {
snprintf(str, sizeof(str), "[::]:%d", port);
+ *addrText = strdup(str);
} else if (strcmp(*arg, opt) == 0) {
++arg;
if (!--argc) {
return DPS_FALSE;
}
- strncpy(str, *arg++, sizeof(str));
+ *addrText = strdup(*arg++);
} else {
return DPS_FALSE;
}
- *addr = DPS_CreateAddress();
- if (!*addr) {
- return DPS_FALSE;
- }
- if (!DPS_SetAddress(*addr, str)) {
- DPS_DestroyAddress(*addr);
- *addr = NULL;
- return DPS_FALSE;
- }
*argp = arg;
*argcp = argc;
return DPS_TRUE;
}
+
+DPS_NodeAddress* CreateAddressFromArg(const char* network, const char* addrText)
+{
+ DPS_NodeAddress* addr = NULL;
+
+ addr = DPS_CreateAddress();
+ if (!addr) {
+ return NULL;
+ }
+ if (!DPS_SetAddress(addr, network, addrText)) {
+ DPS_DestroyAddress(addr);
+ return NULL;
+ }
+ return addr;
+}
diff --git a/test/test.h b/test/test.h
index 9c0910f5..ac4d0012 100644
--- a/test/test.h
+++ b/test/test.h
@@ -51,6 +51,7 @@
#define ASSERT(cond) do { assert(cond); if (!(cond)) exit(EXIT_FAILURE); } while (0)
int IntArg(char* opt, char*** argp, int* argcp, int* val, int min, int max);
-int AddressArg(char* opt, char*** argp, int* argcp, DPS_NodeAddress** addr);
+int AddressArg(char* opt, char*** argp, int* argcp, char** addrText);
+DPS_NodeAddress* CreateAddressFromArg(const char* network, const char* addrText);
#endif
diff --git a/test/topic_match.c b/test/topic_match.c
index 58563669..6a0e439f 100644
--- a/test/topic_match.c
+++ b/test/topic_match.c
@@ -92,6 +92,15 @@ int main(int argc, char** argv)
continue;
}
if (strcmp(*arg, "-n") == 0) {
+ /* Ignore the network argument for compatibility with other tests */
+ ++arg;
+ if (!--argc) {
+ goto Usage;
+ }
+ ++arg;
+ continue;
+ }
+ if (strcmp(*arg, "-w") == 0) {
++arg;
noWildCard = DPS_TRUE;
continue;
diff --git a/test/version.c b/test/version.c
index c69ba6a9..e5e1c239 100644
--- a/test/version.c
+++ b/test/version.c
@@ -158,9 +158,12 @@ int main(int argc, char** argv)
int encrypt = DPS_TRUE;
int mcast = DPS_MCAST_PUB_ENABLE_SEND;
DPS_MemoryKeyStore* memoryKeyStore = NULL;
+ char* network = NULL;
+ char* addrText = NULL;
DPS_NodeAddress* addr = NULL;
DPS_NetEndpoint ep;
DPS_Node *node = NULL;
+ DPS_NodeAddress* listenAddr = NULL;
DPS_Event* nodeDestroyed = NULL;
DPS_Status ret;
@@ -172,7 +175,15 @@ int main(int argc, char** argv)
if (IntArg("-t", &arg, &argc, &type, 1, UINT8_MAX)) {
continue;
}
- if (AddressArg("-p", &arg, &argc, &addr)) {
+ if (strcmp(*arg, "-n") == 0) {
+ ++arg;
+ if (!--argc) {
+ goto Usage;
+ }
+ network = *arg++;
+ continue;
+ }
+ if (AddressArg("-p", &arg, &argc, &addrText)) {
continue;
}
if (IntArg("-x", &arg, &argc, &encrypt, 0, 1)) {
@@ -188,7 +199,12 @@ int main(int argc, char** argv)
}
}
memset(&ep, 0, sizeof(ep));
- if (addr) {
+ if (addrText) {
+ addr = CreateAddressFromArg(network, addrText);
+ if (!addr) {
+ DPS_ERRPRINT("Failed to create address\n");
+ return EXIT_FAILURE;
+ }
mcast = DPS_MCAST_PUB_DISABLED;
DPS_CopyAddress(&ep.addr, addr);
}
@@ -204,7 +220,12 @@ int main(int argc, char** argv)
nodeDestroyed = DPS_CreateEvent();
node = DPS_CreateNode("/.", DPS_MemoryKeyStoreHandle(memoryKeyStore), NULL);
- ret = DPS_StartNode(node, mcast, NULL);
+ listenAddr = CreateAddressFromArg(network, NULL);
+ if (!listenAddr) {
+ DPS_ERRPRINT("CreateAddressFromArg failed\n");
+ return EXIT_FAILURE;
+ }
+ ret = DPS_StartNode(node, mcast, listenAddr);
if (ret != DPS_OK) {
DPS_ERRPRINT("Failed to start node: %s\n", DPS_ErrTxt(ret));
return EXIT_FAILURE;
@@ -218,13 +239,15 @@ int main(int argc, char** argv)
DPS_WaitForEvent(nodeDestroyed);
DPS_DestroyEvent(nodeDestroyed);
DPS_DestroyMemoryKeyStore(memoryKeyStore);
+ DPS_DestroyAddress(listenAddr);
DPS_DestroyAddress(addr);
return EXIT_SUCCESS;
Usage:
- DPS_PRINT("Usage %s [-d] [-x 0/1] [-p ] [-v version] [-t type]\n", argv[0]);
+ DPS_PRINT("Usage %s [-d] [-x 0/1] [-n ] [-p ] [-v version] [-t type]\n", argv[0]);
DPS_PRINT(" -d: Enable debug ouput if built for debug.\n");
DPS_PRINT(" -x: Enable or disable encryption. Default is encryption enabled.\n");
+ DPS_PRINT(" -n: Network of listen and link addresses.\n");
DPS_PRINT(" -p: An address to send to.\n");
DPS_PRINT(" -v: The version number to send.\n");
DPS_PRINT(" -t: The message type to send.\n");
diff --git a/test_scripts/common.py b/test_scripts/common.py
index 64bd2739..e724f9b7 100644
--- a/test_scripts/common.py
+++ b/test_scripts/common.py
@@ -1,40 +1,48 @@
#!/usr/bin/python
+from __future__ import print_function
import argparse
import collections
import copy
+import glob
import os
import pexpect
from pexpect import popen_spawn
+import random
import re
import signal
import shutil
+import socket
from subprocess import check_output
import sys
-os.environ['USE_DTLS'] = '0'
-try:
- if os.environ['TRANSPORT'] == 'dtls':
- os.environ['USE_DTLS'] = '1'
-except KeyError:
- pass
-
os.environ['PYTHONPATH'] = os.path.join('build', 'dist', 'py')
os.environ['NODE_PATH'] = os.path.join('build', 'dist', 'js')
os.environ['LSAN_OPTIONS'] = 'suppressions={}/asan.supp'.format(os.getcwd())
+def _set_mcast_port():
+ global _sock
+ _sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
+ _sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ _sock.bind(('', 0))
+ host, port = _sock.getsockname()
+ os.environ['DPS_MCAST_PORT'] = str(port)
+_set_mcast_port()
_parser = argparse.ArgumentParser()
_parser.add_argument("-d", "--debug", action='store_true',
- help="Enable debug ouput if built for debug.")
-_args = _parser.parse_args()
-if _args.debug:
- _debug = ['-d']
-else:
- _debug = []
+ help="Enable debug ouput if built for debug.")
+_parser.add_argument("-n", "--network", default=None,
+ help="Network of addresses.")
+args = _parser.parse_args()
+_cmd_args = []
+if args.debug:
+ _cmd_args.extend(['-d'])
+if args.network:
+ _cmd_args.extend(['-n', args.network])
_children = []
_logs = []
-if os.environ['USE_DTLS'] == '1':
+if args.network == 'dtls':
_subs_rate = ['-r', '800']
_pub_wait = ['-w', '4']
else:
@@ -51,19 +59,21 @@
_t = 0
_tm = 0
_v = 0
+_log_dir = 'out'
def _spawn_env():
spawn_env = os.environ.copy()
if 'ASAN' in os.environ and os.environ['ASAN'] == 'yes':
- match = re.search('libasan.*', check_output('ldconfig -p', shell=True))
- libasan = match.group(0).split()[-1]
- spawn_env.update({'LD_PRELOAD': libasan})
+ if 'FSAN' not in os.environ or os.environ['FSAN'] == 'no':
+ match = re.search('libasan.*', check_output('ldconfig -p', shell=True))
+ libasan = match.group(0).split()[-1]
+ spawn_env.update({'LD_PRELOAD': libasan})
return spawn_env
def _spawn_helper(n, cmd, interpreter=[]):
- global _children, _logs
+ global _children, _logs, _log_dir
name = os.path.basename(cmd[0])
- log_name = 'out/{}{}.log'.format(name, n)
+ log_name = os.path.join(_log_dir, '{}{}.log'.format(name, n))
log = open(log_name, 'wb')
log.write('=============================\n{}{} {}\n'.format(name, n, ' '.join(cmd[1:])).encode())
log.write('=============================\n'.encode())
@@ -169,7 +179,7 @@ def _expect_ack(children, allow_error=False, timeout=-1, signers=None):
signers.append(child.match.group(1).decode())
def cleanup():
- global _children
+ global _children, _sock
for child in _children:
if sys.platform == 'win32':
child.kill(signal.SIGBREAK)
@@ -181,9 +191,10 @@ def cleanup():
_children = []
for log in _logs:
log.close()
+ _sock.close()
-def reset_logs():
- global _ms, _n, _p, _r, _rp, _rs, _s, _t, _tm, _v
+def reset_logs(transport_name=args.network, test_name=sys.argv[0]):
+ global _ms, _n, _p, _r, _rp, _rs, _s, _t, _log_dir, _tm, _v
_ms = 0
_n = 0
_p = 0
@@ -192,18 +203,24 @@ def reset_logs():
_rs = 0
_s = 0
_t = 0
+ if transport_name:
+ _log_dir = os.path.join('out', transport_name, test_name)
+ else:
+ _log_dir = os.path.join('out', test_name)
_tm = 0
_v = 0
cleanup()
- shutil.rmtree('out', ignore_errors=True)
+ shutil.rmtree(_log_dir, ignore_errors=True)
try:
- os.makedirs('out')
+ os.makedirs(_log_dir)
except OSError:
- if not os.path.isdir('out'):
+ if not os.path.isdir(_log_dir):
raise
-def bin(cmd):
- global _children
+def bin_log(log_dir, cmd):
+ global _children, _log_dir
+ _log_dir = log_dir
+ _set_mcast_port()
child = _spawn(1, cmd)
buf = child.read(8192)
while buf:
@@ -212,8 +229,22 @@ def bin(cmd):
_children.remove(child)
return status
+def bin(cmd):
+ global _children, _log_dir
+ try:
+ i = cmd.index('-n')
+ return bin_log(os.path.join('out', cmd[i + 1], cmd[0]), cmd)
+ except ValueError:
+ return bin_log(os.path.join('out', cmd[0]), cmd)
+
def py(cmd):
- global _children
+ global _children, _log_dir
+ try:
+ i = cmd.index('-n')
+ _log_dir = os.path.join('out', cmd[i + 1], cmd[0])
+ except ValueError:
+ _log_dir = os.path.join('out', cmd[0])
+ _set_mcast_port()
child = _py_spawn(1, cmd)
child.expect(pexpect.EOF, timeout=300)
status = child.wait()
@@ -223,7 +254,7 @@ def py(cmd):
def node(args):
global _n
_n = _n + 1
- cmd = [os.path.join('build', 'test', 'bin', 'node')] + _debug + args.split()
+ cmd = [os.path.join('build', 'test', 'bin', 'node')] + _cmd_args + args.split()
child = _spawn(_n, cmd)
_expect([child], ['Ready'])
return child
@@ -231,7 +262,7 @@ def node(args):
def sub(args=''):
global _s
_s = _s + 1
- cmd = [os.path.join('build', 'dist', 'bin', 'subscriber')] + _debug + _subs_rate + args.split()
+ cmd = [os.path.join('build', 'dist', 'bin', 'subscriber')] + _cmd_args + _subs_rate + args.split()
child = _spawn(_s, cmd)
_expect_listening(child)
_expect_linked(child, args)
@@ -240,7 +271,7 @@ def sub(args=''):
def pub(args):
global _p
_p = _p + 1
- cmd = [os.path.join('build', 'dist', 'bin', 'publisher')] + _debug + _subs_rate + _pub_wait + args.split()
+ cmd = [os.path.join('build', 'dist', 'bin', 'publisher')] + _cmd_args + _subs_rate + _pub_wait + args.split()
child = _spawn(_p, cmd)
_expect_listening(child)
_expect_linked(child, args)
@@ -249,7 +280,7 @@ def pub(args):
def py_sub(args=''):
global _s
_s = _s + 1
- cmd = [os.path.join('py_scripts', 'simple_sub.py')] + _debug + args.split()
+ cmd = [os.path.join('py_scripts', 'simple_sub.py')] + _cmd_args + args.split()
child = _py_spawn(_s, cmd)
_expect_listening(child)
return child
@@ -257,7 +288,7 @@ def py_sub(args=''):
def py_pub(args=''):
global _p
_p = _p + 1
- cmd = [os.path.join('py_scripts', 'simple_pub.py')] + _debug + args.split()
+ cmd = [os.path.join('py_scripts', 'simple_pub.py')] + _cmd_args + args.split()
child = _py_spawn(_p, cmd)
_expect_listening(child)
return child
@@ -265,7 +296,7 @@ def py_pub(args=''):
def py_late_sub():
global _s
_s = _s + 1
- cmd = [os.path.join('py_scripts', 'late_sub.py')] + _debug
+ cmd = [os.path.join('py_scripts', 'late_sub.py')] + _cmd_args
child = _py_spawn(_s, cmd)
_expect_listening(child)
return child
@@ -273,7 +304,7 @@ def py_late_sub():
def py_retained_pub():
global _p
_p = _p + 1
- cmd = [os.path.join('py_scripts', 'retained_pub.py')] + _debug
+ cmd = [os.path.join('py_scripts', 'retained_pub.py')] + _cmd_args
child = _py_spawn(_p, cmd)
_expect_listening(child)
return child
@@ -281,7 +312,7 @@ def py_retained_pub():
def py_sub_ks(args=''):
global _s
_s = _s + 1
- cmd = [os.path.join('py_scripts', 'simple_sub_ks.py')] + _debug + args.split()
+ cmd = [os.path.join('py_scripts', 'simple_sub_ks.py')] + _cmd_args + args.split()
child = _py_spawn(_s, cmd)
_expect_listening(child)
return child
@@ -289,7 +320,7 @@ def py_sub_ks(args=''):
def py_pub_ks(args=''):
global _p
_p = _p + 1
- cmd = [os.path.join('py_scripts', 'simple_pub_ks.py')] + _debug + args.split()
+ cmd = [os.path.join('py_scripts', 'simple_pub_ks.py')] + _cmd_args + args.split()
child = _py_spawn(_p, cmd)
_expect_listening(child)
return child
@@ -297,7 +328,7 @@ def py_pub_ks(args=''):
def js_sub(args=''):
global _s
_s = _s + 1
- cmd = [os.path.join('js_scripts', 'simple_sub.js')] + _debug + args.split()
+ cmd = [os.path.join('js_scripts', 'simple_sub.js')] + _cmd_args + args.split()
child = _js_spawn(_s, cmd)
_expect_listening(child)
return child
@@ -305,7 +336,7 @@ def js_sub(args=''):
def js_pub(args=''):
global _p
_p = _p + 1
- cmd = [os.path.join('js_scripts', 'simple_pub.js')] + _debug + args.split()
+ cmd = [os.path.join('js_scripts', 'simple_pub.js')] + _cmd_args + args.split()
child = _js_spawn(_p, cmd)
_expect_listening(child)
return child
@@ -313,7 +344,7 @@ def js_pub(args=''):
def js_sub_ks(args=''):
global _s
_s = _s + 1
- cmd = [os.path.join('js_scripts', 'simple_sub_ks.js')] + _debug + args.split()
+ cmd = [os.path.join('js_scripts', 'simple_sub_ks.js')] + _cmd_args + args.split()
child = _js_spawn(_s, cmd)
_expect_listening(child)
return child
@@ -321,7 +352,7 @@ def js_sub_ks(args=''):
def js_pub_ks(args=''):
global _p
_p = _p + 1
- cmd = [os.path.join('js_scripts', 'simple_pub_ks.js')] + _debug + args.split()
+ cmd = [os.path.join('js_scripts', 'simple_pub_ks.js')] + _cmd_args + args.split()
child = _js_spawn(_p, cmd)
_expect_listening(child)
return child
@@ -329,7 +360,7 @@ def js_pub_ks(args=''):
def go_sub(args=''):
global _s
_s = _s + 1
- cmd = [os.path.join('build', 'dist', 'go', 'bin', 'simple_sub')] + _debug + args.split()
+ cmd = [os.path.join('build', 'dist', 'go', 'bin', 'simple_sub')] + _cmd_args + args.split()
child = _spawn(_s, cmd)
_expect_listening(child)
return child
@@ -337,7 +368,7 @@ def go_sub(args=''):
def go_pub(args=''):
global _p
_p = _p + 1
- cmd = [os.path.join('build', 'dist', 'go', 'bin', 'simple_pub')] + _debug + args.split()
+ cmd = [os.path.join('build', 'dist', 'go', 'bin', 'simple_pub')] + _cmd_args + args.split()
child = _spawn(_p, cmd)
_expect_listening(child)
return child
@@ -345,7 +376,7 @@ def go_pub(args=''):
def go_sub_ks(args=''):
global _s
_s = _s + 1
- cmd = [os.path.join('build', 'dist', 'go', 'bin', 'simple_sub_ks')] + _debug + args.split()
+ cmd = [os.path.join('build', 'dist', 'go', 'bin', 'simple_sub_ks')] + _cmd_args + args.split()
child = _spawn(_s, cmd)
_expect_listening(child)
return child
@@ -353,7 +384,7 @@ def go_sub_ks(args=''):
def go_pub_ks(args=''):
global _p
_p = _p + 1
- cmd = [os.path.join('build', 'dist', 'go', 'bin', 'simple_pub_ks')] + _debug + args.split()
+ cmd = [os.path.join('build', 'dist', 'go', 'bin', 'simple_pub_ks')] + _cmd_args + args.split()
child = _spawn(_p, cmd)
_expect_listening(child)
return child
@@ -361,7 +392,7 @@ def go_pub_ks(args=''):
def tutorial(args=''):
global _t
_t = _t + 1
- cmd = [os.path.join('build', 'dist', 'bin', 'tutorial')] + _debug + args.split()
+ cmd = [os.path.join('build', 'dist', 'bin', 'tutorial')] + _cmd_args + args.split()
child = _spawn(_t, cmd)
_expect_listening(child)
_expect_linked(child, args)
@@ -370,7 +401,7 @@ def tutorial(args=''):
def ver(args=''):
global _v
_v = _v + 1
- cmd = [os.path.join('build', 'test', 'bin', 'version')] + _debug + args.split()
+ cmd = [os.path.join('build', 'test', 'bin', 'version')] + _cmd_args + args.split()
child = _spawn(_v, cmd)
_expect_listening(child)
return child
@@ -378,7 +409,7 @@ def ver(args=''):
def reg(args=''):
global _r
_r = _r + 1
- cmd = [os.path.join('build', 'dist', 'bin', 'registry')] + _debug + _subs_rate + args.split()
+ cmd = [os.path.join('build', 'dist', 'bin', 'registry')] + _cmd_args + _subs_rate + args.split()
child = _spawn(_r, cmd)
_expect_listening(child)
return child
@@ -386,7 +417,7 @@ def reg(args=''):
def reg_subs(args=''):
global _rs
_rs = _rs + 1
- cmd = [os.path.join('build', 'dist', 'bin', 'reg_subs')] + _debug + args.split()
+ cmd = [os.path.join('build', 'dist', 'bin', 'reg_subs')] + _cmd_args + args.split()
child = _spawn(_rs, cmd)
_expect_listening(child)
return child
@@ -394,7 +425,7 @@ def reg_subs(args=''):
def reg_pubs(args=''):
global _rp
_rp = _rp + 1
- cmd = [os.path.join('build', 'dist', 'bin', 'reg_pubs')] + _debug + _pub_wait + args.split()
+ cmd = [os.path.join('build', 'dist', 'bin', 'reg_pubs')] + _cmd_args + _pub_wait + args.split()
child = _spawn(_rp, cmd)
_expect_listening(child)
return child
@@ -402,7 +433,7 @@ def reg_pubs(args=''):
def topic_match(pattern, args=''):
global _tm
_tm = _tm + 1
- cmd = [os.path.join('build', 'test', 'bin', 'topic_match')] + _debug + args.split()
+ cmd = [os.path.join('build', 'test', 'bin', 'topic_match')] + _cmd_args + args.split()
child = _spawn(_tm, cmd)
_expect([child], [pattern])
@@ -414,7 +445,7 @@ def expect_reg_linked(children):
def mesh_stress(args=''):
global _ms
_ms = _ms + 1
- cmd = [os.path.join('build', 'test', 'bin', 'mesh_stress')] + _debug + args.split()
+ cmd = [os.path.join('build', 'test', 'bin', 'mesh_stress')] + _cmd_args + args.split()
return _spawn(_ms, cmd)
def link(child, ports):
@@ -451,4 +482,14 @@ def expect_pub_not_received(children, topic, allow_error=False):
def expect_error(children, error):
expect(children, 'ERROR.*{}'.format(error), allow_error=True)
+def dump_logs(test_name):
+ log_dir = os.path.join('out', test_name)
+ for log in glob.glob(os.path.join(log_dir, '*.log')):
+ size = os.path.getsize(log)
+ with open(log, 'r') as l:
+ print('==> {} <=='.format(log))
+ if size > 32768:
+ l.seek(-32768, os.SEEK_END)
+ print(l.read(), end='')
+
reset_logs()
diff --git a/test_scripts/fuzzer_check.py b/test_scripts/fuzzer_check.py
index 1ef64156..f58ddb1e 100755
--- a/test_scripts/fuzzer_check.py
+++ b/test_scripts/fuzzer_check.py
@@ -6,25 +6,33 @@
atexit.register(cleanup)
-def _fuzzer_check(fuzzer, corpus):
+def _fuzzer_check(test, cmd_args, corpus):
+ # Work around max argument length by slicing corpus args
+ transport = args.network
while corpus:
- # Work around max argument length by slicing
- bin(fuzzer + corpus[:1024])
+ reset_logs(transport, test)
+ name = os.path.join(transport, test)
+ print('[ RUN ] ' + name)
+ status = bin_log(os.path.join('out', transport, test), [test] + cmd_args + corpus[:1024])
+ if status == 0:
+ print('[ OK ] ' + name)
+ else:
+ print('[ FAILED ] ' + name)
+ dump_logs(name)
+ sys.exit(status)
del corpus[:1024]
-if os.environ['USE_DTLS'] == '0':
- _fuzzer_check([os.path.join('build', 'test', 'bin', 'cbor_fuzzer')],
+if args.network != 'dtls':
+ _fuzzer_check(os.path.join('build', 'test', 'bin', 'cbor_fuzzer'), [],
glob.glob('test/corpus/cbor/*'))
- _fuzzer_check([os.path.join('build', 'test', 'bin', 'multicast_receive_fuzzer')],
+ _fuzzer_check(os.path.join('build', 'test', 'bin', 'multicast_receive_fuzzer'), [],
glob.glob('test/corpus/multicast_receive/*'))
- _fuzzer_check([os.path.join('build', 'test', 'bin', 'net_receive_fuzzer')],
+ _fuzzer_check(os.path.join('build', 'test', 'bin', 'net_receive_fuzzer'), [],
glob.glob('test/corpus/unicast_receive/*'))
else:
for step in range(7):
- _fuzzer_check([os.path.join('build', 'test', 'bin', 'dtls_fuzzer'), 'server', '{}'.format(step)],
+ _fuzzer_check(os.path.join('build', 'test', 'bin', 'dtls_fuzzer'), ['server', '{}'.format(step)],
glob.glob('test/corpus/dtls_server_{}/*'.format(step)))
for step in range(8):
- _fuzzer_check([os.path.join('build', 'test', 'bin', 'dtls_fuzzer'), 'client', '{}'.format(step)],
+ _fuzzer_check(os.path.join('build', 'test', 'bin', 'dtls_fuzzer'), ['client', '{}'.format(step)],
glob.glob('test/corpus/dtls_client_{}/*'.format(step)))
-
-
diff --git a/test_scripts/run.py b/test_scripts/run.py
index 0a39fc4a..1db4b623 100755
--- a/test_scripts/run.py
+++ b/test_scripts/run.py
@@ -4,6 +4,8 @@
from common import *
import glob
import os
+import multiprocessing
+from multiprocessing import Pool
import pexpect
from pexpect import popen_spawn
import platform
@@ -42,8 +44,8 @@
if 'BINDINGS' not in os.environ or 'all' in os.environ['BINDINGS'] or 'python' in os.environ['BINDINGS']:
tests.extend([
os.path.join('py_scripts', 'subs_tree.py'),
- os.path.join('test_scripts', 'simple_py_test.py'),
- os.path.join('test_scripts', 'simple_py_ks_test.py')
+ os.path.join('test_scripts', 'simple_py_test.py'),
+ os.path.join('test_scripts', 'simple_py_ks_test.py')
])
if 'BINDINGS' not in os.environ or 'all' in os.environ['BINDINGS'] or 'nodejs' in os.environ['BINDINGS']:
tests.extend([
@@ -58,38 +60,44 @@
else:
tests = [os.path.join('test_scripts', 'fuzzer_check.py')]
-ok = 0
-failed = 0
-failed_tests = ''
-
-def _dump_logs():
- for log in glob.glob('out/*.log'):
- size = os.path.getsize(log)
- with open(log, 'r') as l:
- print('==> {} <=='.format(log))
- if size > 32768:
- l.seek(-32768, os.SEEK_END)
- print(l.read(), end='')
-
-for test in tests:
- reset_logs()
- print('[ RUN ] ' + test)
+def run_test(args):
+ (transport, test) = args
+ reset_logs(transport, test)
+ name = os.path.join(transport, test)
+ print('[ RUN ] ' + name)
if test.startswith('test_scripts'):
- child = popen_spawn.PopenSpawn(['python', test] + sys.argv[1:], logfile=sys.stdout)
+ child = popen_spawn.PopenSpawn(['python', test, '-n', transport] + sys.argv[1:], logfile=sys.stdout)
child.expect(pexpect.EOF, timeout=300)
status = child.wait()
elif test.startswith('py_scripts'):
- status = py([test] + sys.argv[1:])
+ status = py([test, '-n', transport] + sys.argv[1:])
+ else:
+ status = bin([test, '-n', transport] + sys.argv[1:])
+ if status == 0:
+ print('[ OK ] ' + name)
else:
- status = bin([test] + sys.argv[1:])
+ print('[ FAILED ] ' + name)
+ dump_logs(name)
+ return (name, status)
+
+args = []
+for transport in os.environ['TRANSPORTS'].split(','):
+ for test in tests:
+ args = args + [(transport, test)]
+
+pool = Pool()
+results = pool.map(run_test, args)
+
+ok = 0
+failed = 0
+failed_tests = ''
+for result in results:
+ (name, status) = result
if status == 0:
- print('[ OK ] ' + test)
ok = ok + 1
else:
- print('[ FAILED ] ' + test)
failed = failed + 1
- failed_tests += '[ FAILED ] ' + test + '\n'
- _dump_logs()
+ failed_tests += '[ FAILED ] ' + name + '\n'
print('[==========] {} tests ran.'.format(ok + failed))
if ok > 0:
diff --git a/test_scripts/tutorial.py b/test_scripts/tutorial.py
index 37b9b241..26f6a07e 100755
--- a/test_scripts/tutorial.py
+++ b/test_scripts/tutorial.py
@@ -10,7 +10,7 @@
# When DTLS being used, security must be enabled for the ack to be
# succesfully delivered.
#
-if os.environ['USE_DTLS'] == '0':
+if args.network != 'dtls':
#
# Hello world
#
@@ -34,7 +34,7 @@
expect(tutorial2, 'payload=Hello{}'.format(os.linesep))
expect(tutorial3, 'payload=World{}'.format(os.linesep))
-if os.environ['USE_DTLS'] != '0':
+if args.network == 'dtls':
#
# DTLS with pre-shared keys
#
@@ -57,7 +57,7 @@
expect(tutorial1, 'payload=Hello{}'.format(os.linesep))
expect(tutorial2, 'payload=World{}'.format(os.linesep))
-if os.environ['USE_DTLS'] == '0':
+if args.network != 'dtls':
#
# Protecting the payload - symmetric key
#
diff --git a/tools/README.md b/tools/README.md
index 124c4620..a06a6608 100644
--- a/tools/README.md
+++ b/tools/README.md
@@ -69,9 +69,9 @@ fuzzer_cov directory.
Example:
```
$ rm *.profraw
-$ scons ... transport=fuzzer cov=yes
+$ scons ... transports=fuzzer cov=yes
$ ./fuzzer_cov
-$ scons ... transport=dtls cov=yes
+$ scons ... transports=dtls cov=yes
$ USE_DTLS=1 ./fuzzer_cov
```
@@ -83,9 +83,9 @@ Runs all the fuzzers to generate more test cases.
Example:
```
-$ scons ... transport=fuzzer
+$ scons ... transports=fuzzer
$ ./fuzzer_run
-$ scons ... transport=dtls
+$ scons ... transports=dtls
$ USE_DTLS=1 ./fuzzer_run
```
diff --git a/tools/fuzzer_cov b/tools/fuzzer_cov
index 660cceec..b90942cd 100755
--- a/tools/fuzzer_cov
+++ b/tools/fuzzer_cov
@@ -4,9 +4,9 @@
#
# example:
# $ rm *.profraw
-# $ scons ... transport=fuzzer cov=yes
+# $ scons ... transports=fuzzer cov=yes
# $ ./fuzzer_cov
-# $ scons ... transport=dtls cov=yes
+# $ scons ... transports=dtls cov=yes
# $ USE_DTLS=1 ./fuzzer_cov
#
diff --git a/tools/fuzzer_run b/tools/fuzzer_run
index 56133d3f..22256c0e 100755
--- a/tools/fuzzer_run
+++ b/tools/fuzzer_run
@@ -3,9 +3,9 @@
# run all the fuzzers to generate more test cases
#
# example:
-# $ scons ... transport=fuzzer
+# $ scons ... transports=fuzzer
# $ ./fuzzer_run
-# $ scons ... transport=dtls
+# $ scons ... transports=dtls
# $ USE_DTLS=1 ./fuzzer_run
#