From 9684c57a3e3ccbeefa940a5dd7f76aca5d65cbc7 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Wed, 27 Mar 2019 11:07:52 -0700 Subject: [PATCH 01/23] Support runtime selection of transport. Signed-off-by: Todd Malsbary --- SConscript | 24 +- SConstruct | 15 +- doc/tutorial/link.dox | 8 +- doc/tutorial/tutorial.c | 77 ++++-- dps_shared.def | 1 + examples/common.c | 93 ++++--- examples/common.h | 12 +- examples/pub_many.c | 11 +- examples/publisher.c | 23 +- examples/reg_pubs.c | 18 +- examples/reg_subs.c | 27 +- examples/registry.c | 22 +- examples/subscriber.c | 30 ++- go/dps.go | 40 +-- go/test/perf_publisher/perf_publisher.go | 3 +- go/test/perf_subscriber/perf_subscriber.go | 3 +- inc/dps/dps.h | 20 +- inc/dps/private/network.h | 91 +++++-- inc/dps/registration.h | 25 +- inc/dps/synchronous.h | 3 +- py_scripts/simple_pub.py | 8 +- py_scripts/simple_sub.py | 8 +- py_scripts/subs_tree.py | 3 +- src/dps.c | 76 +++--- src/dtls/network.c | 277 ++++++++++++--------- src/network.c | 103 ++++++-- src/pipe/network.c | 186 ++++++++------ src/registration.c | 72 ++++-- src/resolver.c | 12 +- src/synchronous.c | 4 +- src/tcp/network.c | 187 ++++++++------ src/udp/network.c | 54 ++-- test/link.c | 7 +- test/make_mesh.c | 16 +- test/mesh_stress.c | 13 +- test/node.c | 15 +- test/perf/publisher.c | 13 +- test/perf/subscriber.c | 11 +- test/publish.c | 8 +- test/test.c | 31 ++- test/test.h | 3 +- test/version.c | 19 +- 42 files changed, 1088 insertions(+), 584 deletions(-) diff --git a/SConscript b/SConscript index 0880fb93..b36e6585 100755 --- a/SConscript +++ b/SConscript @@ -61,19 +61,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) diff --git a/SConstruct b/SConstruct index b637fe98..e3f1172c 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 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,16 +64,20 @@ for key, val in ARGLIST: for b in bindings: env[b] = b in env['bindings'] -if env['transport'] == 'udp': +# Unpack transports into individually testable booleans +for t in transports: + env[t] = t in env['transports'] + +if env['udp']: env['USE_UDP'] = 'true' env.Append(CPPDEFINES = ['DPS_USE_UDP']) -elif env['transport'] == 'tcp': +if env['tcp']: env['USE_TCP'] = 'true' env.Append(CPPDEFINES = ['DPS_USE_TCP']) -elif env['transport'] == 'dtls': +if env['dtls']: env['USE_DTLS'] = 'true' env.Append(CPPDEFINES = ['DPS_USE_DTLS']) -elif env['transport'] == 'pipe': +if env['pipe']: env['USE_PIPE'] = 'true' env.Append(CPPDEFINES = ['DPS_USE_PIPE']) diff --git a/doc/tutorial/link.dox b/doc/tutorial/link.dox index a03c2f5a..f70778f1 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. A port value of zero +lets DPS assign an ephemeral listening port. 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/tutorial.c b/doc/tutorial/tutorial.c index af90ef44..ea0088f1 100644 --- a/doc/tutorial/tutorial.c +++ b/doc/tutorial/tutorial.c @@ -78,7 +78,8 @@ 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 StartNode(DPS_Node* node, int mcastPub, const char* listenNetwork, + 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); @@ -108,11 +109,32 @@ static void Usage(int argc, char** argv) { DPS_PRINT("Usage %s [-d] [-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(" -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** network, const char** addrText) +{ + char* endp; + int i = 0; + + (*port) = strtol(argv[i], &endp, 10); + if (*endp == 0) { + ++i; + } else { + if (!strcmp(argv[i], "dtls") || !strcmp(argv[i], "tcp") || + !strcmp(argv[i], "udp") || !strcmp(argv[i], "pipe")) { + (*network) = argv[i++]; + } + if (i < argc) { + (*addrText) = argv[i++]; + } + } + + return i; +} + int main(int argc, char** argv) { DPS_Node* node = NULL; @@ -122,12 +144,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 +162,23 @@ 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]; + const char* listenNetwork = NULL; + i += ParseAddress(&argv[i + 1], argc - (i + 1), &listenPort, &listenNetwork, &listenAddrText); + if (network && strcmp(listenNetwork, network)) { + Usage(argc, argv); + return EXIT_FAILURE; + } else { + network = listenNetwork; } - ++i; } else if (!strcmp(argv[i], "-p") && ((i + 1) < argc)) { - linkPort = strtol(argv[i + 1], &endp, 10); - if (*endp) { - linkText = argv[i + 1]; + const char* linkNetwork = NULL; + i += ParseAddress(&argv[i + 1], argc - (i + 1), &linkPort, &linkNetwork, &linkAddrText); + if (network && strcmp(linkNetwork, network)) { + Usage(argc, argv); + return EXIT_FAILURE; + } else { + network = linkNetwork; } - ++i; } else if (!strcmp(argv[i], "-x") && ((i + 1) < argc)) { security = argv[i + 1]; ++i; @@ -199,8 +227,8 @@ 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; @@ -213,8 +241,8 @@ int main(int argc, char** argv) 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; } @@ -222,9 +250,10 @@ int main(int argc, char** argv) SLEEP(1000); } else if (linkPort) { /** [Linking to a node] */ + char network[] = "udp"; 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 +391,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* listenNetwork, + const char* listenAddrText) { DPS_Status ret; DPS_NodeAddress* listenAddr = NULL; - if (listenText) { + if (listenNetwork || listenAddrText) { listenAddr = DPS_CreateAddress(); if (!listenAddr) { ret = DPS_ERR_RESOURCES; goto Exit; } - DPS_SetAddress(listenAddr, listenText); + DPS_SetAddress(listenAddr, listenNetwork, listenAddrText); } ret = DPS_StartNode(node, mcastPub, listenAddr); if (ret != DPS_OK) { @@ -412,8 +442,9 @@ static DPS_Status StartUnicastNode(DPS_Node* node, uint16_t port) ret = DPS_ERR_RESOURCES; goto Exit; } + char network[] = "udp"; 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..80f0e911 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(char* network, 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, 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..604438db 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(char* network, 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, 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..0fa15832 100644 --- a/examples/pub_many.c +++ b/examples/pub_many.c @@ -77,6 +77,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; char* msg = NULL; @@ -85,6 +86,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; } @@ -135,7 +144,7 @@ int main(int argc, char** argv) 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; diff --git a/examples/publisher.c b/examples/publisher.c index aa738d24..f7cd299f 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; @@ -405,7 +420,7 @@ 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; diff --git a/examples/reg_pubs.c b/examples/reg_pubs.c index 36444837..48ac0897 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, 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; @@ -221,11 +222,20 @@ int main(int argc, char** argv) 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 (strcmp(*arg, "-n") == 0) { + ++arg; + if (!--argc) { + goto Usage; + } + network = *arg++; + continue; + } if (LinkArg(&arg, &argc, linkText, &numLinks)) { continue; } @@ -299,7 +309,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; diff --git a/examples/reg_subs.c b/examples/reg_subs.c index 0c26b7f0..004b0685 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, 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,7 +254,7 @@ 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; diff --git a/examples/registry.c b/examples/registry.c index 7651bc8c..f04f002f 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,7 +117,7 @@ int main(int argc, char** argv) DPS_WaitForEvent(nodeDestroyed); DPS_DestroyEvent(nodeDestroyed); DPS_DestroyMemoryKeyStore(memoryKeyStore); - DPS_DestroyAddress(listenAddr); + DestroyAddressArg(listenText, listenAddr); return 0; Usage: diff --git a/examples/subscriber.c b/examples/subscriber.c index 95639c81..b15a921b 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; @@ -164,7 +165,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 +299,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) { @@ -346,6 +356,7 @@ 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)); @@ -380,13 +391,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) { /* @@ -417,7 +433,7 @@ 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; diff --git a/go/dps.go b/go/dps.go index 9dd2352d..00305168 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, 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,20 @@ 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)) + cnetwork := C.CString(network) + defer C.free(unsafe.Pointer(cnetwork)) + 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 +669,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 +712,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 +1051,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/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..c7e4f904 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,7 @@ func main() { node := dps.CreateNode("/", nil, nil) listenAddr := dps.CreateAddress() - dps.SetAddress(listenAddr, fmt.Sprintf(":%v", *listenText)) + dps.SetAddress(listenAddr, *network, fmt.Sprintf(":%v", *listenText)) 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..68868be5 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; + +/** + * 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); + +/** @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 data structure for network-specific state + * Data structure for network-specific state */ -typedef struct _DPS_NetContext DPS_NetContext; +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); /** - * Opaque type for managing connection state for connection-oriented transports + * Type for managing connection state for connection-oriented transports */ -typedef struct _DPS_NetConnection DPS_NetConnection; +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,31 @@ 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; + +extern DPS_NetTransport DPS_NetUdpTransport; /**< The UDP transport */ +extern DPS_NetTransport DPS_NetTcpTransport; /**< The TCP transport */ +extern DPS_NetTransport DPS_NetDtlsTransport; /**< The DTLS transport */ +extern DPS_NetTransport DPS_NetPipeTransport; /**< The pipe transport */ + #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/py_scripts/simple_pub.py b/py_scripts/simple_pub.py index 1fb806a1..cf8a8d6f 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, @@ -154,9 +156,9 @@ def on_destroy(node): if args.listen != None: listen_addr = dps.create_address() try: - dps.set_address(listen_addr, "[::]:%d" % (int(args.listen))) + dps.set_address(listen_addr, args.network, "[::]:%d" % (int(args.listen))) except ValueError: - dps.set_address(listen_addr, args.listen) + 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 +168,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_sub.py b/py_scripts/simple_sub.py index 6f5e9a17..30b018f7 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, @@ -142,9 +144,9 @@ def on_link(node, addr, status): if args.listen != None: listen_addr = dps.create_address() try: - dps.set_address(listen_addr, "[::]:%d" % (int(args.listen))) + dps.set_address(listen_addr, args.network, "[::]:%d" % (int(args.listen))) except ValueError: - dps.set_address(listen_addr, args.listen) + 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 +159,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/subs_tree.py b/py_scripts/subs_tree.py index 3cb3276d..9c9836fb 100755 --- a/py_scripts/subs_tree.py +++ b/py_scripts/subs_tree.py @@ -54,7 +54,8 @@ def subscriber(topic, remote_listen_addr): 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) diff --git a/src/dps.c b/src/dps.c index 4c132212..5621d520 100755 --- a/src/dps.c +++ b/src/dps.c @@ -1529,15 +1529,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 +1549,45 @@ 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_UNKNOWN: + network = "udp"; + /* FALLTHROUGH */ + 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 +1659,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..9b89d131 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 CancelPending(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,11 @@ 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 OnTLSDebug(void *ctx, int level, const char *file, int line, const char *str) @@ -379,17 +414,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 +431,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 +467,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); @@ -458,13 +489,13 @@ static void OnTimeout(uv_timer_t* timer) } else if (ret == DPS_FALSE) { 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 +505,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 +518,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 +546,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 +570,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 +578,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 +635,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 +668,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 +683,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 +702,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 +728,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 +744,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 +755,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); @@ -756,7 +787,7 @@ static void DestroyConnection(DPS_NetConnection* 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 +811,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 +844,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 +863,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 +900,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 +909,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 +926,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 +1099,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 +1107,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 +1127,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 +1150,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 +1187,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 +1203,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 +1215,9 @@ static void TLSSend(DPS_NetConnection* cn) } } -static void TLSRecv(DPS_NetConnection* cn) +static void TLSRecv(DPS_NetDtlsConnection* cn) { - DPS_NetContext* netCtx = cn->netCtx; + DPS_NetDtlsContext* netCtx = cn->netCtx; DPS_NetRxBuffer* buf = NULL; int ret; DPS_Status status; @@ -1194,7 +1226,7 @@ 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) { @@ -1240,16 +1272,16 @@ 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); } -static int TLSHandshake(DPS_NetConnection* cn) +static int TLSHandshake(DPS_NetDtlsConnection* cn) { int ret; @@ -1271,7 +1303,7 @@ static int TLSHandshake(DPS_NetConnection* cn) case MBEDTLS_ERR_SSL_WANT_WRITE: break; default: - DPS_NetConnectionIncRef(cn); + ConnectionIncRef(cn); break; } @@ -1336,13 +1368,13 @@ static int TLSHandshake(DPS_NetConnection* cn) case MBEDTLS_ERR_SSL_WANT_WRITE: break; default: - DPS_NetConnectionDecRef(cn); + ConnectionDecRef(cn); break; } return !ret; } -static void ConsumePending(DPS_NetConnection* cn) +static void ConsumePending(DPS_NetDtlsConnection* cn) { assert(cn->handshakeDone); while (!DPS_QueueEmpty(&cn->recvQueue)) { @@ -1355,10 +1387,10 @@ static void ConsumePending(DPS_NetConnection* 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 +1443,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,7 +1458,7 @@ 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); @@ -1444,19 +1476,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 +1504,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 +1526,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 +1534,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 +1554,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,7 +1573,7 @@ void DPS_NetStop(DPS_NetContext* netCtx) */ cns = netCtx->cns; while (cns) { - DPS_NetConnection* cn = cns; + DPS_NetDtlsConnection* cn = cns; cns = cns->next; CancelPending(cn); } @@ -1551,10 +1589,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 +1615,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)) { goto ErrorExit; } /* @@ -1599,49 +1639,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 = node->netCtx; uv_udp_recv_cb ret; /* diff --git a/src/network.c b/src/network.c index 2af6c4a1..d6fa142d 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,34 @@ 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_UNKNOWN: + addr->type = DPS_UDP; + /* FALLTHROUGH */ 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 +494,69 @@ void DPS_NetRxBufferDecRef(DPS_NetRxBuffer* buf) } } } + +DPS_NodeAddressType DPS_NetAddressType(const char* network) +{ + if (!network) { + return DPS_UNKNOWN; + } 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 : DPS_UNKNOWN; + + switch (type) { + case DPS_DTLS: + return DPS_NetDtlsTransport.start(node, addr, cb); + case DPS_TCP: + return DPS_NetTcpTransport.start(node, addr, cb); + case DPS_UDP: + case DPS_UNKNOWN: + return DPS_NetUdpTransport.start(node, addr, cb); + case DPS_PIPE: + return DPS_NetPipeTransport.start(node, addr, cb); + 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/pipe/network.c b/src/pipe/network.c index 23805e13..e86e7531 100644 --- a/src/pipe/network.c +++ b/src/pipe/network.c @@ -45,9 +45,11 @@ */ DPS_DEBUG_CONTROL(DPS_DEBUG_ON); +typedef struct _DPS_NetPipeConnection DPS_NetPipeConnection; + typedef struct _SendRequest { DPS_Queue queue; - DPS_NetConnection* cn; + DPS_NetPipeConnection* cn; uv_write_t writeReq; DPS_NetSendComplete onSendComplete; void* appCtx; @@ -57,7 +59,8 @@ typedef struct _SendRequest { 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; @@ -72,20 +75,48 @@ 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); @@ -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,8 +222,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_NetPipeConnection* cn = (DPS_NetPipeConnection*)socket->data; + DPS_NetPipeContext* netCtx = (DPS_NetPipeContext*)cn->node->netCtx; DPS_DBGTRACE(); /* @@ -285,8 +316,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_NetPipeContext* netCtx = (DPS_NetPipeContext*)stream->data; + DPS_NetPipeConnection* cn; size_t sz; DPS_DBGTRACE(); @@ -299,11 +330,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 +345,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); @@ -376,17 +409,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 +432,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 +474,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 +482,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 +507,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 +520,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 +530,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 +542,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 +553,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,12 +569,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_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; SendRequest* req; + DPS_NetPipeConnection* cn = NULL; uv_handle_t* socket = NULL; int r; size_t i; @@ -577,42 +617,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 +665,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..a7e57082 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,8 +367,9 @@ 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; @@ -393,7 +405,7 @@ DPS_Status DPS_Registration_Put(DPS_Node* node, const char* addrText, const char } 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); } } @@ -419,8 +431,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 +442,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 +533,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 +547,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 +561,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,9 +625,9 @@ 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; @@ -642,7 +672,7 @@ DPS_Status DPS_Registration_Get(DPS_Node* node, const char* addrText, const char 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: @@ -671,8 +701,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 +716,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 +756,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 +765,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 +806,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..cbe43d69 100644 --- a/src/resolver.c +++ b/src/resolver.c @@ -39,6 +39,7 @@ typedef struct _ResolverInfo { 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; @@ -50,13 +51,7 @@ static void GetAddrInfoCB(uv_getaddrinfo_t* req, int status, struct addrinfo* re 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 { @@ -136,7 +131,7 @@ 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; @@ -162,6 +157,7 @@ DPS_Status DPS_ResolveAddress(DPS_Node* node, const char* host, const char* serv 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; 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..7526da03 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,48 @@ 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 +130,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 +141,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 +154,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 +173,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 +189,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 +198,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 +219,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 +313,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 +327,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 +342,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 +400,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 +423,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 +447,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 +457,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 +477,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 +490,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 +500,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 +512,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 +523,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 +539,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 +587,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 +626,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 +646,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/test/link.c b/test/link.c index 7592096b..c956f447 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(a); 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(b); 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..228588f6 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; diff --git a/test/perf/publisher.c b/test/perf/publisher.c index 4b670148..0001abec 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, "--network") == 0) { + ++arg; + if (!--argc) { + goto Usage; + } + network = *arg++; + continue; + } if (strcmp(*arg, "-p") == 0) { ++arg; if (!--argc) { @@ -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; diff --git a/test/perf/subscriber.c b/test/perf/subscriber.c index e13df017..6546ae8b 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, "--network") == 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)); diff --git a/test/publish.c b/test/publish.c index 0101a374..c2cb58b3 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); @@ -331,7 +334,7 @@ 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); seqNum = DPS_PublicationGetSequenceNum(pub) + 1; @@ -353,7 +356,6 @@ static void TestBackToBackPublishSeparateNodes(DPS_Node* node, DPS_KeyStore* key DPS_DestroyEvent(event); DPS_DestroyPublication(pub); } -#endif static void TestRetainedMessage(DPS_Node* node, DPS_KeyStore* keyStore) { diff --git a/test/test.c b/test/test.c index 05dadde4..bf36f2c6 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(char* network, 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..53bf53f2 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(char* network, char* addrText); #endif diff --git a/test/version.c b/test/version.c index c69ba6a9..ab124da1 100644 --- a/test/version.c +++ b/test/version.c @@ -158,6 +158,8 @@ 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; @@ -172,7 +174,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 +198,12 @@ int main(int argc, char** argv) } } memset(&ep, 0, sizeof(ep)); - if (addr) { + if (network || addr) { + 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); } From 735f60d9f1a146aa57836f40c630d68af8df3177 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Mon, 1 Apr 2019 10:22:02 -0700 Subject: [PATCH 02/23] Add "-n" option across the board to specify network of addresses. Signed-off-by: Todd Malsbary --- doc/tutorial/hello_world.dox | 6 +- doc/tutorial/link.dox | 6 +- doc/tutorial/tutorial.c | 66 +++++++++----------- examples/pub_many.c | 11 +++- examples/publisher.c | 5 +- examples/reg_pubs.c | 12 +++- examples/reg_subs.c | 3 +- examples/registry.c | 2 +- examples/subscriber.c | 3 +- go/dps.go | 15 +++-- go/examples/simple_pub/simple_pub.go | 35 ++++++----- go/examples/simple_pub_ks/simple_pub_ks.go | 35 ++++++----- go/examples/simple_sub/simple_sub.go | 35 ++++++----- go/examples/simple_sub_ks/simple_sub_ks.go | 35 ++++++----- go/test/perf_subscriber/perf_subscriber.go | 3 +- js_scripts/simple_pub.js | 9 ++- js_scripts/simple_pub_ks.js | 9 ++- js_scripts/simple_sub.js | 9 ++- js_scripts/simple_sub_ks.js | 9 ++- py_scripts/late_sub.py | 6 +- py_scripts/retained_pub.py | 6 +- py_scripts/simple_pub.py | 12 ++-- py_scripts/simple_pub_ks.py | 7 ++- py_scripts/simple_sub.py | 12 ++-- py_scripts/simple_sub_ks.py | 6 +- py_scripts/subs_tree.py | 21 ++++--- src/registration.c | 26 +++++++- swig/dps.i | 25 ++++++++ swig/js/dps_impl.i | 15 +++++ swig/py/dps_impl.i | 15 +++++ test/node.c | 3 +- test/packtest.c | 13 +++- test/perf/publisher.c | 9 +-- test/perf/subscriber.c | 5 +- test/pubsub.c | 13 +++- test/rle_compression.c | 13 +++- test/topic_match.c | 9 +++ test/version.c | 14 ++++- test_scripts/common.py | 72 ++++++++++------------ test_scripts/tutorial.py | 6 +- 40 files changed, 403 insertions(+), 213 deletions(-) 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 f70778f1..5ddd77cc 100644 --- a/doc/tutorial/link.dox +++ b/doc/tutorial/link.dox @@ -28,9 +28,9 @@ 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 select UDP and 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. +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/tutorial.c b/doc/tutorial/tutorial.c index ea0088f1..9b308d0f 100644 --- a/doc/tutorial/tutorial.c +++ b/doc/tutorial/tutorial.c @@ -76,9 +76,9 @@ 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* listenNetwork, +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); @@ -107,14 +107,15 @@ 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(" -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** network, const char** addrText) +static int ParseAddress(char** argv, int argc, int* port, const char** addrText) { char* endp; int i = 0; @@ -123,13 +124,7 @@ static int ParseAddress(char** argv, int argc, int* port, const char** network, if (*endp == 0) { ++i; } else { - if (!strcmp(argv[i], "dtls") || !strcmp(argv[i], "tcp") || - !strcmp(argv[i], "udp") || !strcmp(argv[i], "pipe")) { - (*network) = argv[i++]; - } - if (i < argc) { - (*addrText) = argv[i++]; - } + (*addrText) = argv[i++]; } return i; @@ -162,23 +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)) { - const char* listenNetwork = NULL; - i += ParseAddress(&argv[i + 1], argc - (i + 1), &listenPort, &listenNetwork, &listenAddrText); - if (network && strcmp(listenNetwork, network)) { - Usage(argc, argv); - return EXIT_FAILURE; - } else { - network = listenNetwork; - } + i += ParseAddress(&argv[i + 1], argc - (i + 1), &listenPort, &listenAddrText); } else if (!strcmp(argv[i], "-p") && ((i + 1) < argc)) { - const char* linkNetwork = NULL; - i += ParseAddress(&argv[i + 1], argc - (i + 1), &linkPort, &linkNetwork, &linkAddrText); - if (network && strcmp(linkNetwork, network)) { - Usage(argc, argv); - return EXIT_FAILURE; - } else { - network = linkNetwork; - } + i += ParseAddress(&argv[i + 1], argc - (i + 1), &linkPort, &linkAddrText); } else if (!strcmp(argv[i], "-x") && ((i + 1) < argc)) { security = argv[i + 1]; ++i; @@ -186,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; @@ -233,9 +217,9 @@ int main(int argc, char** argv) 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; @@ -250,7 +234,6 @@ int main(int argc, char** argv) SLEEP(1000); } else if (linkPort) { /** [Linking to a node] */ - char network[] = "udp"; char addrText[24]; snprintf(addrText, sizeof(addrText), "127.0.0.1:%d", linkPort); ret = DPS_Link(node, network, addrText, LinkComplete, NULL); @@ -391,19 +374,19 @@ static DPS_Node* CreateNodeWithAuthenticatedSender(const DPS_KeyId* nodeId) return node; } -static DPS_Status StartNode(DPS_Node* node, int mcastPub, const char* listenNetwork, +static DPS_Status StartNode(DPS_Node* node, int mcastPub, const char* network, const char* listenAddrText) { DPS_Status ret; DPS_NodeAddress* listenAddr = NULL; - if (listenNetwork || listenAddrText) { + if (network || listenAddrText) { listenAddr = DPS_CreateAddress(); if (!listenAddr) { ret = DPS_ERR_RESOURCES; goto Exit; } - DPS_SetAddress(listenAddr, listenNetwork, listenAddrText); + DPS_SetAddress(listenAddr, network, listenAddrText); } ret = DPS_StartNode(node, mcastPub, listenAddr); if (ret != DPS_OK) { @@ -416,11 +399,18 @@ static DPS_Status StartNode(DPS_Node* node, int mcastPub, const char* listenNetw 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; } @@ -428,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]; @@ -442,7 +433,6 @@ static DPS_Status StartUnicastNode(DPS_Node* node, uint16_t port) ret = DPS_ERR_RESOURCES; goto Exit; } - char network[] = "udp"; snprintf(addrText, sizeof(addrText), "[::]:%d", port); DPS_SetAddress(listenAddr, network, addrText); ret = DPS_StartNode(node, mcastPub, listenAddr); diff --git a/examples/pub_many.c b/examples/pub_many.c index 0fa15832..caa8eb39 100644 --- a/examples/pub_many.c +++ b/examples/pub_many.c @@ -76,6 +76,7 @@ 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 }; @@ -138,7 +139,12 @@ 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; @@ -171,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 f7cd299f..de690394 100644 --- a/examples/publisher.c +++ b/examples/publisher.c @@ -408,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); } @@ -425,12 +425,13 @@ int main(int argc, char** argv) 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 48ac0897..e4f480c9 100644 --- a/examples/reg_pubs.c +++ b/examples/reg_pubs.c @@ -221,6 +221,7 @@ 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 }; @@ -300,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; @@ -352,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 004b0685..d8153c5f 100644 --- a/examples/reg_subs.c +++ b/examples/reg_subs.c @@ -259,8 +259,9 @@ int main(int argc, char** argv) 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 f04f002f..5f556460 100644 --- a/examples/registry.c +++ b/examples/registry.c @@ -121,6 +121,6 @@ int main(int argc, char** argv) 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 b15a921b..df02a342 100644 --- a/examples/subscriber.c +++ b/examples/subscriber.c @@ -439,11 +439,12 @@ int main(int argc, char** argv) 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 00305168..f6c58be9 100644 --- a/go/dps.go +++ b/go/dps.go @@ -255,12 +255,17 @@ func NodeAddrNetwork(addr *NodeAddress) string { func CreateAddress() *NodeAddress { return (*NodeAddress)(C.DPS_CreateAddress()) } -func SetAddress(addr *NodeAddress, network, addrText string) *NodeAddress { +func SetAddress(addr *NodeAddress, network, addrText *string) *NodeAddress { caddr := (*C.DPS_NodeAddress)(addr) - cnetwork := C.CString(network) - defer C.free(unsafe.Pointer(cnetwork)) - caddrText := C.CString(addrText) - defer C.free(unsafe.Pointer(caddrText)) + 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) { 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_subscriber/perf_subscriber.go b/go/test/perf_subscriber/perf_subscriber.go index c7e4f904..55c902b1 100644 --- a/go/test/perf_subscriber/perf_subscriber.go +++ b/go/test/perf_subscriber/perf_subscriber.go @@ -53,7 +53,8 @@ func main() { node := dps.CreateNode("/", nil, nil) listenAddr := dps.CreateAddress() - dps.SetAddress(listenAddr, *network, 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/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 cf8a8d6f..2dd17dc8 100755 --- a/py_scripts/simple_pub.py +++ b/py_scripts/simple_pub.py @@ -152,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, args.network, "[::]:%d" % (int(args.listen))) - except ValueError: - dps.set_address(listen_addr, args.network, 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))) 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 30b018f7..6dc5ae95 100755 --- a/py_scripts/simple_sub.py +++ b/py_scripts/simple_sub.py @@ -140,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, args.network, "[::]:%d" % (int(args.listen))) - except ValueError: - dps.set_address(listen_addr, args.network, 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))) 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 9c9836fb..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,7 +57,10 @@ 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) @@ -61,13 +73,6 @@ def subscriber(topic, remote_listen_addr): 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/registration.c b/src/registration.c index a7e57082..c1ad5d97 100644 --- a/src/registration.c +++ b/src/registration.c @@ -374,6 +374,7 @@ DPS_Status DPS_Registration_Put(DPS_Node* node, const char* network, const char* DPS_Status ret; RegPut* regPut; const DPS_NodeAddress* localAddr; + DPS_NodeAddress* addr = NULL; DPS_DBGTRACE(); @@ -399,7 +400,16 @@ DPS_Status DPS_Registration_Put(DPS_Node* node, const char* network, 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 { @@ -422,6 +432,7 @@ DPS_Status DPS_Registration_Put(DPS_Node* node, const char* network, const char* } free(regPut); } + DPS_DestroyAddress(addr); return ret; } @@ -632,6 +643,7 @@ DPS_Status DPS_Registration_Get(DPS_Node* node, const char* network, const char* DPS_Status ret; RegGet* regGet; const DPS_NodeAddress* localAddr; + DPS_NodeAddress* addr = NULL; DPS_DBGTRACE(); @@ -668,7 +680,16 @@ DPS_Status DPS_Registration_Get(DPS_Node* node, const char* network, 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 { @@ -685,6 +706,7 @@ DPS_Status DPS_Registration_Get(DPS_Node* node, const char* network, const char* } free(regGet); } + DPS_DestroyAddress(addr); return ret; } 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/node.c b/test/node.c index 228588f6..5e383bbb 100644 --- a/test/node.c +++ b/test/node.c @@ -303,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 0001abec..5fba5bf5 100644 --- a/test/perf/publisher.c +++ b/test/perf/publisher.c @@ -112,7 +112,7 @@ int main(int argc, char** argv) DPS_Debug = DPS_TRUE; continue; } - if (strcmp(*arg, "--network") == 0) { + if (strcmp(*arg, "-n") == 0) { ++arg; if (!--argc) { goto Usage; @@ -131,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; } } @@ -214,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 6546ae8b..9c4434f0 100644 --- a/test/perf/subscriber.c +++ b/test/perf/subscriber.c @@ -82,7 +82,7 @@ int main(int argc, char** argv) DPS_Debug = DPS_TRUE; continue; } - if (strcmp(*arg, "--network") == 0) { + if (strcmp(*arg, "-n") == 0) { ++arg; if (!--argc) { goto Usage; @@ -135,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/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/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 ab124da1..e5e1c239 100644 --- a/test/version.c +++ b/test/version.c @@ -163,6 +163,7 @@ int main(int argc, char** argv) DPS_NodeAddress* addr = NULL; DPS_NetEndpoint ep; DPS_Node *node = NULL; + DPS_NodeAddress* listenAddr = NULL; DPS_Event* nodeDestroyed = NULL; DPS_Status ret; @@ -198,7 +199,7 @@ int main(int argc, char** argv) } } memset(&ep, 0, sizeof(ep)); - if (network || addr) { + if (addrText) { addr = CreateAddressFromArg(network, addrText); if (!addr) { DPS_ERRPRINT("Failed to create address\n"); @@ -219,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; @@ -233,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..3f3cdeeb 100644 --- a/test_scripts/common.py +++ b/test_scripts/common.py @@ -12,29 +12,25 @@ 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()) _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="udp", + 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: @@ -223,7 +219,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 +227,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 +236,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 +245,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 +253,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 +261,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 +269,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 +277,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 +285,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 +293,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 +301,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 +309,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 +317,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 +325,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 +333,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 +341,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 +349,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 +357,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 +366,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 +374,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 +382,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 +390,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 +398,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 +410,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): 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 # From d599154bfebbb3eae2b3dd69361eda3f08f10e3a Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Mon, 1 Apr 2019 11:17:42 -0700 Subject: [PATCH 03/23] Allow different multicast ports for test isolation. Signed-off-by: Todd Malsbary --- src/multicast/network.c | 30 +++++++++++++++++++++++++----- test_scripts/common.py | 30 +++++++++++++++++++++--------- test_scripts/run.py | 9 +++++---- 3 files changed, 51 insertions(+), 18 deletions(-) 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/test_scripts/common.py b/test_scripts/common.py index 3f3cdeeb..af2d74d1 100644 --- a/test_scripts/common.py +++ b/test_scripts/common.py @@ -6,6 +6,7 @@ import os import pexpect from pexpect import popen_spawn +import random import re import signal import shutil @@ -15,6 +16,9 @@ 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(): + os.environ['DPS_MCAST_PORT'] = str(random.randint(49152, 65536)) +_set_mcast_port() _parser = argparse.ArgumentParser() _parser.add_argument("-d", "--debug", action='store_true', @@ -47,6 +51,7 @@ _t = 0 _tm = 0 _v = 0 +_test_name = '' def _spawn_env(): spawn_env = os.environ.copy() @@ -57,9 +62,10 @@ def _spawn_env(): return spawn_env def _spawn_helper(n, cmd, interpreter=[]): - global _children, _logs + global _children, _logs, _test_name name = os.path.basename(cmd[0]) - log_name = 'out/{}{}.log'.format(name, n) + log_dir = os.path.join('out', _test_name) + 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()) @@ -178,8 +184,8 @@ def cleanup(): for log in _logs: log.close() -def reset_logs(): - global _ms, _n, _p, _r, _rp, _rs, _s, _t, _tm, _v +def reset_logs(test_name=sys.argv[0]): + global _ms, _n, _p, _r, _rp, _rs, _s, _t, _test_name, _tm, _v _ms = 0 _n = 0 _p = 0 @@ -188,18 +194,22 @@ def reset_logs(): _rs = 0 _s = 0 _t = 0 + _test_name = test_name _tm = 0 _v = 0 cleanup() - shutil.rmtree('out', ignore_errors=True) + log_dir = os.path.join('out', _test_name) + 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 + global _children, _test_name + _test_name = cmd[0] + _set_mcast_port() child = _spawn(1, cmd) buf = child.read(8192) while buf: @@ -209,7 +219,9 @@ def bin(cmd): return status def py(cmd): - global _children + global _children, _test_name + _test_name = cmd[0] + _set_mcast_port() child = _py_spawn(1, cmd) child.expect(pexpect.EOF, timeout=300) status = child.wait() diff --git a/test_scripts/run.py b/test_scripts/run.py index 0a39fc4a..febeaca4 100755 --- a/test_scripts/run.py +++ b/test_scripts/run.py @@ -62,8 +62,9 @@ failed = 0 failed_tests = '' -def _dump_logs(): - for log in glob.glob('out/*.log'): +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)) @@ -72,7 +73,7 @@ def _dump_logs(): print(l.read(), end='') for test in tests: - reset_logs() + reset_logs(test) print('[ RUN ] ' + test) if test.startswith('test_scripts'): child = popen_spawn.PopenSpawn(['python', test] + sys.argv[1:], logfile=sys.stdout) @@ -89,7 +90,7 @@ def _dump_logs(): print('[ FAILED ] ' + test) failed = failed + 1 failed_tests += '[ FAILED ] ' + test + '\n' - _dump_logs() + _dump_logs(test) print('[==========] {} tests ran.'.format(ok + failed)) if ok > 0: From dba05dc656e8b7f4133677683f1d75a1c61499bb Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Mon, 1 Apr 2019 11:48:16 -0700 Subject: [PATCH 04/23] Run tests in parallel. Signed-off-by: Todd Malsbary --- test_scripts/common.py | 41 +++++++++++++++++++++++--------------- test_scripts/run.py | 45 +++++++++++++++++++++++++++++------------- 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/test_scripts/common.py b/test_scripts/common.py index af2d74d1..ec172122 100644 --- a/test_scripts/common.py +++ b/test_scripts/common.py @@ -23,7 +23,7 @@ def _set_mcast_port(): _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", +_parser.add_argument("-n", "--network", default=None, help="Network of addresses.") args = _parser.parse_args() _cmd_args = [] @@ -51,7 +51,7 @@ def _set_mcast_port(): _t = 0 _tm = 0 _v = 0 -_test_name = '' +_log_dir = 'out' def _spawn_env(): spawn_env = os.environ.copy() @@ -62,10 +62,9 @@ def _spawn_env(): return spawn_env def _spawn_helper(n, cmd, interpreter=[]): - global _children, _logs, _test_name + global _children, _logs, _log_dir name = os.path.basename(cmd[0]) - log_dir = os.path.join('out', _test_name) - log_name = os.path.join(log_dir, '{}{}.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()) @@ -184,8 +183,8 @@ def cleanup(): for log in _logs: log.close() -def reset_logs(test_name=sys.argv[0]): - global _ms, _n, _p, _r, _rp, _rs, _s, _t, _test_name, _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 @@ -194,21 +193,27 @@ def reset_logs(test_name=sys.argv[0]): _rs = 0 _s = 0 _t = 0 - _test_name = test_name + 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() - log_dir = os.path.join('out', _test_name) - shutil.rmtree(log_dir, ignore_errors=True) + shutil.rmtree(_log_dir, ignore_errors=True) try: - os.makedirs(log_dir) + os.makedirs(_log_dir) except OSError: - if not os.path.isdir(log_dir): + if not os.path.isdir(_log_dir): raise def bin(cmd): - global _children, _test_name - _test_name = cmd[0] + 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 = _spawn(1, cmd) buf = child.read(8192) @@ -219,8 +224,12 @@ def bin(cmd): return status def py(cmd): - global _children, _test_name - _test_name = cmd[0] + 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) diff --git a/test_scripts/run.py b/test_scripts/run.py index febeaca4..c9595f38 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 @@ -58,10 +60,6 @@ else: tests = [os.path.join('test_scripts', 'fuzzer_check.py')] -ok = 0 -failed = 0 -failed_tests = '' - def _dump_logs(test_name): log_dir = os.path.join('out', test_name) for log in glob.glob(os.path.join(log_dir, '*.log')): @@ -72,25 +70,44 @@ def _dump_logs(test_name): l.seek(-32768, os.SEEK_END) print(l.read(), end='') -for test in tests: - reset_logs(test) - 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['TRANSPORT'].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(test) + failed_tests += '[ FAILED ] ' + name + '\n' print('[==========] {} tests ran.'.format(ok + failed)) if ok > 0: From b74c12b8f1eb47c8be811bea41812d3563d31a0c Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Mon, 1 Apr 2019 12:38:05 -0700 Subject: [PATCH 05/23] Use correct network in subscriber interactive mode. Signed-off-by: Todd Malsbary --- examples/subscriber.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/examples/subscriber.c b/examples/subscriber.c index df02a342..b6a15aea 100644 --- a/examples/subscriber.c +++ b/examples/subscriber.c @@ -155,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; @@ -321,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]; @@ -340,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; } @@ -361,6 +365,7 @@ int main(int argc, char** argv) DPS_Debug = DPS_FALSE; memset(&subscriber, 0, sizeof(subscriber)); + memset(&args, 0, sizeof(Args)); if (!ParseArgs(argc - 1, argv + 1, &args)) { goto Usage; } @@ -421,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); } From dd1c2a228a52e7cf1746be2532571237a51584be Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Mon, 1 Apr 2019 13:18:02 -0700 Subject: [PATCH 06/23] Support network argument in publish test. Signed-off-by: Todd Malsbary --- test/publish.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/test/publish.c b/test/publish.c index c2cb58b3..3b093282 100644 --- a/test/publish.c +++ b/test/publish.c @@ -322,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); @@ -336,6 +340,7 @@ static void TestBackToBackPublishSeparateNodes(DPS_Node* node, DPS_KeyStore* key ASSERT(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) { @@ -349,7 +354,6 @@ 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); @@ -438,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; @@ -445,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++; } } @@ -456,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); From 438ca098ae3397c6dc406851dfeaed3885c49af3 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Mon, 1 Apr 2019 17:05:28 -0700 Subject: [PATCH 07/23] Enable fuzzer transport again. Signed-off-by: Todd Malsbary --- SConscript | 6 ++--- inc/dps/private/network.h | 11 +++++++++ src/dtls/network.c | 2 +- src/fuzzer/network.c | 45 +++++++++++++++++++++--------------- src/network.c | 14 +++++++++++ test/dtls_fuzzer.c | 16 +++++++++++-- test_scripts/common.py | 35 ++++++++++++++++++++-------- test_scripts/fuzzer_check.py | 30 +++++++++++++++--------- test_scripts/run.py | 12 +--------- 9 files changed, 115 insertions(+), 56 deletions(-) diff --git a/SConscript b/SConscript index b36e6585..63da3b64 100755 --- a/SConscript +++ b/SConscript @@ -135,7 +135,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']) @@ -311,9 +311,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/inc/dps/private/network.h b/inc/dps/private/network.h index 68868be5..d5814444 100644 --- a/inc/dps/private/network.h +++ b/inc/dps/private/network.h @@ -449,10 +449,21 @@ typedef struct _DPS_NetTransport { 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 } diff --git a/src/dtls/network.c b/src/dtls/network.c index 9b89d131..b02f7daa 100755 --- a/src/dtls/network.c +++ b/src/dtls/network.c @@ -1678,7 +1678,7 @@ DPS_NetTransport DPS_NetDtlsTransport = { #ifdef DPS_USE_FUZZ uv_udp_recv_cb Fuzz_OnData(DPS_Node* node, uv_udp_recv_cb cb) { - DPS_NetDtlsContext* 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/network.c b/src/network.c index d6fa142d..dc55dbd2 100644 --- a/src/network.c +++ b/src/network.c @@ -517,15 +517,29 @@ DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_On DPS_NodeAddressType type = addr ? addr->type : DPS_UNKNOWN; 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: case DPS_UNKNOWN: 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; } 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_scripts/common.py b/test_scripts/common.py index ec172122..36436675 100644 --- a/test_scripts/common.py +++ b/test_scripts/common.py @@ -1,8 +1,10 @@ #!/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 @@ -56,9 +58,10 @@ def _set_mcast_port(): 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=[]): @@ -207,13 +210,9 @@ def reset_logs(transport_name=args.network, test_name=sys.argv[0]): if not os.path.isdir(_log_dir): raise -def bin(cmd): +def bin_log(log_dir, cmd): 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]) + _log_dir = log_dir _set_mcast_port() child = _spawn(1, cmd) buf = child.read(8192) @@ -223,6 +222,14 @@ 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, _log_dir try: @@ -468,4 +475,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 c9595f38..2f1d7725 100755 --- a/test_scripts/run.py +++ b/test_scripts/run.py @@ -60,16 +60,6 @@ else: tests = [os.path.join('test_scripts', 'fuzzer_check.py')] -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='') - def run_test(args): (transport, test) = args reset_logs(transport, test) @@ -87,7 +77,7 @@ def run_test(args): print('[ OK ] ' + name) else: print('[ FAILED ] ' + name) - _dump_logs(name) + dump_logs(name) return (name, status) args = [] From 53a45ddcf8cf4f1cdb5347767debc3c4685b4ee0 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Mon, 1 Apr 2019 17:05:56 -0700 Subject: [PATCH 08/23] Transports is plural now. Signed-off-by: Todd Malsbary --- .appveyor.yml | 2 +- .travis.yml | 2 +- doc/Building-and-Running.dox | 4 ++-- doc/tutorial/security.dox | 2 +- tools/README.md | 8 ++++---- tools/fuzzer_cov | 4 ++-- tools/fuzzer_run | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) 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/.travis.yml b/.travis.yml index 1f845972..686a4152 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,5 +54,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=$TRANSPORT bindings=$BINDINGS asan=$ASAN ubsan=yes fsan=$FSAN - ./test_scripts/run.py -d 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/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/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 # From cc28e372105a95401ae2c7e5b5f9b8de606980d8 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Mon, 1 Apr 2019 17:06:20 -0700 Subject: [PATCH 09/23] Reduce number of verified builds. Signed-off-by: Todd Malsbary --- .travis.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 686a4152..29bf1d32 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,15 +7,9 @@ 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=debug TRANSPORT=udp,tcp,dtls,pipe BINDINGS=all ASAN=yes FSAN=no + - VARIANT=release TRANSPORT=udp,tcp,dtls,pipe 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 matrix: From b4c85e3e622d15d306dc9437c9d06caf07b3fdbb Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Tue, 2 Apr 2019 10:05:31 -0700 Subject: [PATCH 10/23] Allow 'transports' or 'transport' as scons variable. Signed-off-by: Todd Malsbary --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index e3f1172c..40ff3d40 100755 --- a/SConstruct +++ b/SConstruct @@ -17,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), - ListVariable('transports', 'Transport protocol', [t for t in transports if t != 'fuzzer'], transports), + 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), From 3899e66537965873f58d0c8107693d09c0a73867 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Tue, 2 Apr 2019 12:26:09 -0700 Subject: [PATCH 11/23] Ensure ref counts are cleaned up on mbedTLS errors. Signed-off-by: Todd Malsbary --- src/dtls/network.c | 74 ++++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/src/dtls/network.c b/src/dtls/network.c index b02f7daa..6c9dbb73 100755 --- a/src/dtls/network.c +++ b/src/dtls/network.c @@ -366,7 +366,7 @@ static void DestroySendRequest(SendRequest* req) } } -static void CancelPending(DPS_NetDtlsConnection* cn) +static void CancelPendingSend(DPS_NetDtlsConnection* cn) { /* * Protect connection while we are modifying the queues. @@ -391,6 +391,24 @@ static void CancelPending(DPS_NetDtlsConnection* 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) { static const DPS_LogLevel levels[] = { @@ -484,9 +502,9 @@ 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); } ConnectionDecRef(cn); @@ -764,8 +782,7 @@ static void DestroyConnection(DPS_NetDtlsConnection* 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: @@ -774,6 +791,7 @@ static void DestroyConnection(DPS_NetDtlsConnection* 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. @@ -784,6 +802,7 @@ static void DestroyConnection(DPS_NetDtlsConnection* 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); @@ -1215,7 +1234,7 @@ static void TLSSend(DPS_NetDtlsConnection* cn) } } -static void TLSRecv(DPS_NetDtlsConnection* cn) +static int TLSRecv(DPS_NetDtlsConnection* cn) { DPS_NetDtlsContext* netCtx = cn->netCtx; DPS_NetRxBuffer* buf = NULL; @@ -1231,6 +1250,7 @@ static void TLSRecv(DPS_NetDtlsConnection* 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)); @@ -1240,6 +1260,7 @@ static void TLSRecv(DPS_NetDtlsConnection* 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; @@ -1247,11 +1268,10 @@ static void TLSRecv(DPS_NetDtlsConnection* 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; } @@ -1263,7 +1283,7 @@ static void TLSRecv(DPS_NetDtlsConnection* 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 @@ -1279,6 +1299,7 @@ static void TLSRecv(DPS_NetDtlsConnection* cn) Exit: DPS_NetRxBufferDecRef(buf); ConnectionDecRef(cn); + return ret; } static int TLSHandshake(DPS_NetDtlsConnection* cn) @@ -1300,7 +1321,6 @@ static int TLSHandshake(DPS_NetDtlsConnection* 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: ConnectionIncRef(cn); @@ -1308,6 +1328,7 @@ static int TLSHandshake(DPS_NetDtlsConnection* cn) } 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) { @@ -1321,7 +1342,7 @@ static int TLSHandshake(DPS_NetDtlsConnection* 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) { @@ -1329,11 +1350,6 @@ static int TLSHandshake(DPS_NetDtlsConnection* 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 @@ -1365,24 +1381,29 @@ static int TLSHandshake(DPS_NetDtlsConnection* 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: ConnectionDecRef(cn); break; } - return !ret; + return ret; } 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) @@ -1462,13 +1483,16 @@ static void OnUdpData(uv_udp_t* socket, ssize_t nread, const uv_buf_t* buf, cons 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: @@ -1575,7 +1599,7 @@ void DPS_NetDtlsStop(DPS_NetContext* ctx) while (cns) { DPS_NetDtlsConnection* cn = cns; cns = cns->next; - CancelPending(cn); + CancelPendingSend(cn); } /* * When no connections are active we can close the rxSocket @@ -1631,7 +1655,7 @@ DPS_Status DPS_NetDtlsSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv goto ErrorExit; } cn->peer = *ep; - if (!TLSHandshake(cn)) { + if (TLSHandshake(cn) != 0) { goto ErrorExit; } /* From cf4b5c868f66bfd7ac6ef6dab882da6c9dd45aa6 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Tue, 2 Apr 2019 14:23:05 -0700 Subject: [PATCH 12/23] Transports is plural now. Signed-off-by: Todd Malsbary --- .travis.yml | 18 +++++++++--------- test_scripts/run.py | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 29bf1d32..baf77429 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,23 +7,23 @@ compiler: - gcc env: - - VARIANT=debug TRANSPORT=udp,tcp,dtls,pipe BINDINGS=all ASAN=yes FSAN=no - - VARIANT=release TRANSPORT=udp,tcp,dtls,pipe BINDINGS=all ASAN=yes FSAN=no - - VARIANT=release TRANSPORT=dtls BINDINGS=python,nodejs ASAN=yes FSAN=yes - - 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: @@ -48,5 +48,5 @@ install: - pip install --user pexpect script: - - scons CC=$CC CXX=$CXX variant=$VARIANT transports=$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/test_scripts/run.py b/test_scripts/run.py index 2f1d7725..5988c743 100755 --- a/test_scripts/run.py +++ b/test_scripts/run.py @@ -81,7 +81,7 @@ def run_test(args): return (name, status) args = [] -for transport in os.environ['TRANSPORT'].split(','): +for transport in os.environ['TRANSPORTS'].split(','): for test in tests: args = args + [(transport, test)] From d7f520e3d2bb1fe1a49fb89ea1be0b01e0bf2515 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Wed, 3 Apr 2019 11:18:08 -0700 Subject: [PATCH 13/23] Rework multicast isolation for test runner to avoid EADDRINUSE. Signed-off-by: Todd Malsbary --- test_scripts/common.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/test_scripts/common.py b/test_scripts/common.py index 36436675..e724f9b7 100644 --- a/test_scripts/common.py +++ b/test_scripts/common.py @@ -12,6 +12,7 @@ import re import signal import shutil +import socket from subprocess import check_output import sys @@ -19,7 +20,12 @@ os.environ['NODE_PATH'] = os.path.join('build', 'dist', 'js') os.environ['LSAN_OPTIONS'] = 'suppressions={}/asan.supp'.format(os.getcwd()) def _set_mcast_port(): - os.environ['DPS_MCAST_PORT'] = str(random.randint(49152, 65536)) + 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() @@ -173,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) @@ -185,6 +191,7 @@ def cleanup(): _children = [] for log in _logs: log.close() + _sock.close() 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 From 43d01317f76d2dc99b07af9b0cce894c98399292 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Wed, 3 Apr 2019 11:18:43 -0700 Subject: [PATCH 14/23] Git ignore patch artifacts. Signed-off-by: Todd Malsbary --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) 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 From 6be92e2b68a59b382c86db31c207a08fa66c7427 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Wed, 3 Apr 2019 12:17:31 -0700 Subject: [PATCH 15/23] Use common queue for resolver requests. Signed-off-by: Todd Malsbary --- src/dps.c | 1 + src/node.h | 7 +------ src/resolver.c | 23 +++++++++++------------ 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/dps.c b/src/dps.c index 5621d520..4dabc147 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 */ 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/resolver.c b/src/resolver.c index cbe43d69..06ea0283 100644 --- a/src/resolver.c +++ b/src/resolver.c @@ -34,7 +34,8 @@ */ DPS_DEBUG_CONTROL(DPS_DEBUG_ON); -typedef struct _ResolverInfo { +typedef struct _ResolverRequest { + DPS_Queue queue; DPS_Node* node; DPS_OnResolveAddressComplete cb; void* data; @@ -42,12 +43,11 @@ typedef struct _ResolverInfo { 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; @@ -68,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) { /* @@ -105,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); @@ -135,7 +135,7 @@ DPS_Status DPS_ResolveAddress(DPS_Node* node, const char* network, const char* h DPS_OnResolveAddressComplete cb, void* data) { DPS_Status ret; - ResolverInfo* resolver; + ResolverRequest* resolver; DPS_DBGTRACE(); @@ -153,7 +153,7 @@ DPS_Status DPS_ResolveAddress(DPS_Node* node, const char* network, const char* h 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; } @@ -173,8 +173,7 @@ DPS_Status DPS_ResolveAddress(DPS_Node* node, const char* network, const char* h 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); From 3d320cc585b7bd419e54cef409bf2e9389e8d8b6 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Wed, 10 Apr 2019 10:49:44 -0700 Subject: [PATCH 16/23] Don't rebuild ext when transports change. Signed-off-by: Todd Malsbary --- SConscript | 14 ++++++++++++++ SConstruct | 13 ------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/SConscript b/SConscript index 63da3b64..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() diff --git a/SConstruct b/SConstruct index 40ff3d40..7a1c6acf 100755 --- a/SConstruct +++ b/SConstruct @@ -68,19 +68,6 @@ for b in bindings: for t in transports: env[t] = t in env['transports'] -if env['udp']: - env['USE_UDP'] = 'true' - env.Append(CPPDEFINES = ['DPS_USE_UDP']) -if env['tcp']: - env['USE_TCP'] = 'true' - env.Append(CPPDEFINES = ['DPS_USE_TCP']) -if env['dtls']: - env['USE_DTLS'] = 'true' - env.Append(CPPDEFINES = ['DPS_USE_DTLS']) -if env['pipe']: - env['USE_PIPE'] = 'true' - env.Append(CPPDEFINES = ['DPS_USE_PIPE']) - print("Building for " + env['variant']) # Platform specific configuration From 22791c58e1a3c484d5261479755d392b64e883b9 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Thu, 11 Apr 2019 13:51:20 -0700 Subject: [PATCH 17/23] Remove unused define. Signed-off-by: Todd Malsbary --- src/tcp/network.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tcp/network.c b/src/tcp/network.c index 7526da03..41d64c61 100755 --- a/src/tcp/network.c +++ b/src/tcp/network.c @@ -81,7 +81,6 @@ typedef struct _DPS_NetTcpContext { 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); From d94cdf9e991c19731105ef3f88d8923e68314277 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Thu, 11 Apr 2019 13:55:31 -0700 Subject: [PATCH 18/23] Whitespace. Signed-off-by: Todd Malsbary --- test_scripts/run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_scripts/run.py b/test_scripts/run.py index 5988c743..1db4b623 100755 --- a/test_scripts/run.py +++ b/test_scripts/run.py @@ -44,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([ From 6acd6e49d69223ce94a0224ea7772721ac1a4c3e Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Wed, 10 Apr 2019 13:51:16 -0700 Subject: [PATCH 19/23] Default network must be compiled in, not necessarily udp. Signed-off-by: Todd Malsbary --- src/dps.c | 3 --- src/network.c | 20 ++++++++++++++------ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/dps.c b/src/dps.c index 4dabc147..ed59583a 100755 --- a/src/dps.c +++ b/src/dps.c @@ -1551,9 +1551,6 @@ DPS_Status DPS_Link(DPS_Node* node, const char* network, const char* addrText, goto Exit; } switch (DPS_NetAddressType(network)) { - case DPS_UNKNOWN: - network = "udp"; - /* FALLTHROUGH */ case DPS_DTLS: case DPS_TCP: case DPS_UDP: diff --git a/src/network.c b/src/network.c index dc55dbd2..e4cdbaa8 100644 --- a/src/network.c +++ b/src/network.c @@ -309,9 +309,6 @@ DPS_NodeAddress* DPS_SetAddress(DPS_NodeAddress* addr, const char* network, cons memset(addr, 0, sizeof(DPS_NodeAddress)); addr->type = DPS_NetAddressType(network); switch (addr->type) { - case DPS_UNKNOWN: - addr->type = DPS_UDP; - /* FALLTHROUGH */ case DPS_DTLS: case DPS_TCP: case DPS_UDP: @@ -495,10 +492,22 @@ 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 +#endif + ; + DPS_NodeAddressType DPS_NetAddressType(const char* network) { if (!network) { - return DPS_UNKNOWN; + return AddressDefaultType; } else if (!strcmp(network, "dtls")) { return DPS_DTLS; } else if (!strcmp(network, "tcp")) { @@ -514,7 +523,7 @@ DPS_NodeAddressType DPS_NetAddressType(const char* network) DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_OnReceive cb) { - DPS_NodeAddressType type = addr ? addr->type : DPS_UNKNOWN; + DPS_NodeAddressType type = addr ? addr->type : AddressDefaultType; switch (type) { #ifdef DPS_USE_DTLS @@ -527,7 +536,6 @@ DPS_NetContext* DPS_NetStart(DPS_Node* node, const DPS_NodeAddress* addr, DPS_On #endif #ifdef DPS_USE_UDP case DPS_UDP: - case DPS_UNKNOWN: return DPS_NetUdpTransport.start(node, addr, cb); #endif #ifdef DPS_USE_PIPE From ae41e3ace3f2f4d731696984a85e143c4b83f8d6 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Thu, 11 Apr 2019 16:43:22 -0700 Subject: [PATCH 20/23] Return DPS_ERR_EOD when trying to decode bytes or strings. This makes decoding bytes and strings consistent with all other CBOR decode functions return DPS_ERR_EOD and do not modify the rxPos when there is not enough data available. Signed-off-by: Todd Malsbary --- src/cbor.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) 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; } From 48a2e79f9ba52de40ae22a74205d75d0b853cbd8 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Thu, 11 Apr 2019 13:51:52 -0700 Subject: [PATCH 21/23] Pipe transport must supply listen address for peer endpoint. In general, uv_pipe_getpeername() will return an empty name. Looking up remotes requires a unique name to work properly. Signed-off-by: Todd Malsbary --- src/pipe/network.c | 168 ++++++++++++++++++++++++++------------------- test/link.c | 4 +- 2 files changed, 99 insertions(+), 73 deletions(-) diff --git a/src/pipe/network.c b/src/pipe/network.c index e86e7531..1b631618 100644 --- a/src/pipe/network.c +++ b/src/pipe/network.c @@ -47,6 +47,9 @@ 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_NetPipeConnection* cn; @@ -55,7 +58,7 @@ typedef struct _SendRequest { 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; @@ -67,7 +70,7 @@ typedef struct _DPS_NetPipeConnection { 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 */ @@ -84,9 +87,6 @@ typedef struct _DPS_NetPipeContext { 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, @@ -122,8 +122,8 @@ static void AllocBuffer(uv_handle_t* handle, size_t suggestedSize, uv_buf_t* buf 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); } } @@ -224,8 +224,11 @@ static void OnData(uv_stream_t* socket, ssize_t nread, const uv_buf_t* buf) DPS_Status ret = DPS_OK; 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 */ @@ -239,77 +242,100 @@ 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); + } } } @@ -318,7 +344,6 @@ static void OnIncomingConnection(uv_stream_t* stream, int status) int ret; DPS_NetPipeContext* netCtx = (DPS_NetPipeContext*)stream->data; DPS_NetPipeConnection* cn; - size_t sz; DPS_DBGTRACE(); @@ -356,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)); @@ -573,7 +590,7 @@ DPS_Status DPS_NetPipeSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv 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; @@ -581,6 +598,7 @@ DPS_Status DPS_NetPipeSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv 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; } @@ -595,15 +613,23 @@ DPS_Status DPS_NetPipeSend(DPS_Node* node, void* appCtx, DPS_NetEndpoint* ep, uv return DPS_ERR_RESOURCES; } /* - * Write total message length + * Write message header + */ + DPS_TxBufferInit(&hdrBuf, req->hdrBuf, sizeof(req->hdrBuf)); + ret = CBOR_EncodeUint32(&hdrBuf, len); + if (ret != DPS_OK) { + goto ErrExit; + } + /* + * Include our listening address, otherwise all clients will look + * the same to the server since the socket peername is unnamed */ - DPS_TxBufferInit(&lenBuf, req->lenBuf, sizeof(req->lenBuf)); - ret = CBOR_EncodeUint32(&lenBuf, len); + ret = CBOR_EncodeString(&hdrBuf, node->addr.u.path); if (ret != DPS_OK) { goto ErrExit; } - req->bufs[0].base = (char*)req->lenBuf; - req->bufs[0].len = DPS_TxBufferUsed(&lenBuf); + req->bufs[0].base = (char*)req->hdrBuf; + req->bufs[0].len = DPS_TxBufferUsed(&hdrBuf); /* * Copy other uvbufs into the send request */ diff --git a/test/link.c b/test/link.c index c956f447..8cd4c7ad 100644 --- a/test/link.c +++ b/test/link.c @@ -69,13 +69,13 @@ static void TestRemoteLinkedAlready(void) a = CreateNode(DPS_MemoryKeyStoreHandle(memoryKeyStore)); b = CreateNode(DPS_MemoryKeyStoreHandle(memoryKeyStore)); - dst = DPS_GetListenAddress(a); + dst = DPS_GetListenAddress(b); addr = DPS_CreateAddress(); ret = DPS_LinkTo(a, DPS_NodeAddrNetwork(dst), DPS_NodeAddrToString(dst), addr); ASSERT(ret == DPS_OK); DPS_DestroyAddress(addr); - dst = DPS_GetListenAddress(b); + dst = DPS_GetListenAddress(a); addr = DPS_CreateAddress(); ret = DPS_LinkTo(b, DPS_NodeAddrNetwork(dst), DPS_NodeAddrToString(dst), addr); ASSERT(ret == DPS_OK); From 6d9ee6ddb35420dcde62b53de77f77853a40e8d5 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Fri, 12 Apr 2019 09:34:27 -0700 Subject: [PATCH 22/23] Fix fuzzer compile error. Signed-off-by: Todd Malsbary --- src/network.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/network.c b/src/network.c index e4cdbaa8..759e042e 100644 --- a/src/network.c +++ b/src/network.c @@ -501,6 +501,8 @@ static const DPS_NodeAddressType AddressDefaultType = DPS_PIPE #elif defined(DPS_USE_DTLS) DPS_DTLS +#else + DPS_UNKNOWN #endif ; From c031334949ccc483607baca454c1592568454b77 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Thu, 18 Apr 2019 14:23:41 -0700 Subject: [PATCH 23/23] Add missing const qualifiers. Signed-off-by: Todd Malsbary --- examples/common.c | 4 ++-- examples/common.h | 4 ++-- examples/reg_pubs.c | 2 +- examples/reg_subs.c | 2 +- go/dps.go | 2 +- test/test.c | 2 +- test/test.h | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/common.c b/examples/common.c index 80f0e911..76ed84c3 100644 --- a/examples/common.c +++ b/examples/common.c @@ -83,7 +83,7 @@ void DestroyAddressArg(char* addrText, DPS_NodeAddress* addr) DPS_DestroyAddress(addr); } -DPS_NodeAddress* CreateAddressFromArg(char* network, char* addrText) +DPS_NodeAddress* CreateAddressFromArg(const char* network, const char* addrText) { DPS_NodeAddress* addr = NULL; @@ -115,7 +115,7 @@ int LinkArg(char*** argp, int* argcp, char** addrText, int* count) } } -DPS_Status Link(DPS_Node* node, char* network, char** addrText, DPS_NodeAddress** addr, int count) +DPS_Status Link(DPS_Node* node, const char* network, char** addrText, DPS_NodeAddress** addr, int count) { DPS_Status ret; int i; diff --git a/examples/common.h b/examples/common.h index 604438db..69bfafd0 100644 --- a/examples/common.h +++ b/examples/common.h @@ -37,10 +37,10 @@ extern "C" { int IntArg(char* opt, char*** argp, int* argcp, int* val, int min, int max); int AddressArg(char* opt, char*** argp, int* argcp, char** addrText); -DPS_NodeAddress* CreateAddressFromArg(char* network, 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, char* network, char** addrText, DPS_NodeAddress** addr, 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); diff --git a/examples/reg_pubs.c b/examples/reg_pubs.c index e4f480c9..c0f0f041 100644 --- a/examples/reg_pubs.c +++ b/examples/reg_pubs.c @@ -161,7 +161,7 @@ static void ReadStdin(DPS_Node* node) } } -static DPS_Status FindAndLink(DPS_Node* node, char* network, char** linkText, int numLinks, +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) { diff --git a/examples/reg_subs.c b/examples/reg_subs.c index d8153c5f..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* network, 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; diff --git a/go/dps.go b/go/dps.go index f6c58be9..f4435474 100644 --- a/go/dps.go +++ b/go/dps.go @@ -135,7 +135,7 @@ import ( goOnResolveAddressComplete(node, (DPS_NodeAddress*)addr, (uintptr_t)data); } - static DPS_Status resolveAddress(DPS_Node* node, char* network, char* host, char* service, uintptr_t 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); } diff --git a/test/test.c b/test/test.c index bf36f2c6..c4c45003 100644 --- a/test/test.c +++ b/test/test.c @@ -71,7 +71,7 @@ int AddressArg(char* opt, char*** argp, int* argcp, char** addrText) return DPS_TRUE; } -DPS_NodeAddress* CreateAddressFromArg(char* network, char* addrText) +DPS_NodeAddress* CreateAddressFromArg(const char* network, const char* addrText) { DPS_NodeAddress* addr = NULL; diff --git a/test/test.h b/test/test.h index 53bf53f2..ac4d0012 100644 --- a/test/test.h +++ b/test/test.h @@ -52,6 +52,6 @@ int IntArg(char* opt, char*** argp, int* argcp, int* val, int min, int max); int AddressArg(char* opt, char*** argp, int* argcp, char** addrText); -DPS_NodeAddress* CreateAddressFromArg(char* network, char* addrText); +DPS_NodeAddress* CreateAddressFromArg(const char* network, const char* addrText); #endif