Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A sync PR #1100

Merged
merged 11 commits into from
Oct 29, 2024
4 changes: 3 additions & 1 deletion .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ jobs:
github-binarycache: true

- name: Configure
run: cmake ${{ steps.vcpkg.outputs.vcpkg-cmake-config }} -D NNG_ENABLE_TLS=ON -B build
# TLS on Windows is not good because vcpkg is *old* mbedTLS 2.28, and we don't pass some newer tests.
# We should explore testing WolfSSL here instead.
run: cmake ${{ steps.vcpkg.outputs.vcpkg-cmake-config }} -B build

- name: Build
run: cmake --build build
Expand Down
18 changes: 18 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,24 @@ if (NOT WIN32 AND NOT CYGWIN)
endif ()
endif ()

# Detect endianness -- this only handles little and big endian.
# PDP users, sorry, but you're out of luck.'
if (DEFINED CMAKE_LANG_C_BYTE_ORDER)
if (CMAKE_LANG_BYTE_ORDER EQUAL BIG_ENDIAN)
add_definitions(-DNNG_BIG_ENDIAN=1)
else()
add_definitions(-DNNG_LITTLE_ENDIAN=1)
endif()
else()
include(TestBigEndian)
test_big_endian(NNG_BIG_ENDIAN)
if (NNG_BIG_ENDIAN)
add_definitions(-DNNG_BIG_EDNDIAN=1)
else()
add_definitions(-DNNG_LITTLE_ENDIAN=1)
endif()
endif()

if (CMAKE_SYSTEM_NAME MATCHES "Linux")
add_definitions(-DNNG_PLATFORM_POSIX)
add_definitions(-DNNG_PLATFORM_LINUX)
Expand Down
8 changes: 8 additions & 0 deletions docs/man/nng_id_map.3supp.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ void *nng_id_get(nng_id_map *map, uint64_t id);
int nng_id_set(nng_id_map *map, uint64_t, void *value);
int nng_id_alloc(nng_id_map *map, uint64_t *id_p, void *value);
int nng_id_remove(nng_id_map *map, uint64_t id);
bool nng_id_visit(nng_id_map *map, uint64_t *id_p, void **value_p, uint32_t *cursor);
----

Expand Down Expand Up @@ -74,6 +75,13 @@ the supplied _value_.

The `nng_id_remove()` function removes the identifier and its associated value from the table.

The `nng_id_visit()` function is used to iterate over all items in the table.
The caller starts the iteration by setting the _cursor_ to 0 before calling it.
For each call, the associated key and value of the next item will be returned in __id_p__, and __value_p__ and the _cursor_ will be updated.
When all items have been iterated, the function returns `false`.
The order of items returned is not guaranteed to be sequential.
The caller must not attempt to derive any value of the _cursor_ as it refers to internal table indices.

NOTE: These functions are limited to storing at most 2^32^ identifiers, even though the identifers may
themselves be larger than 2^32^.

Expand Down
2 changes: 1 addition & 1 deletion docs/man/nng_sub.7.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ TIP: To receive all messages, an empty topic (zero length) can be used.

((`NNG_OPT_SUB_UNSUBSCRIBE`))::

This option, also read-only, removes a topic from the subscription list.
This option, also write-only, removes a topic from the subscription list.
Note that if the topic was not previously subscribed to with
`NNG_OPT_SUB_SUBSCRIBE` then an `NNG_ENOENT` error will result.

Expand Down
11 changes: 7 additions & 4 deletions include/nng/supplemental/util/idhash.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,20 @@ typedef struct nng_id_map_s nng_id_map;

#define NNG_MAP_RANDOM 1

// For NanoNNG
NNG_DECL void nng_id_map_foreach(
nng_id_map *map, void (*)(void *, void *));
NNG_DECL void nng_id_map_foreach2(nng_id_map *map,
void (*)(void *, void *, void *), void *);

NNG_DECL int nng_id_map_alloc(
nng_id_map **map, uint64_t lo, uint64_t hi, int flags);
NNG_DECL void nng_id_map_free(nng_id_map *map);
NNG_DECL void *nng_id_get(nng_id_map *, uint64_t);
NNG_DECL int nng_id_set(nng_id_map *, uint64_t, void *);
NNG_DECL int nng_id_alloc(nng_id_map *, uint64_t *, void *);
NNG_DECL int nng_id_remove(nng_id_map *, uint64_t);
NNG_DECL void nng_id_map_foreach(
nng_id_map *map, void (*)(void *, void *));
NNG_DECL void nng_id_map_foreach2(nng_id_map *map,
void (*)(void *, void *, void *), void *);
NNG_DECL bool nng_id_visit(nng_id_map *, uint64_t *, void **, uint32_t *);

#ifdef __cplusplus
}
Expand Down
64 changes: 64 additions & 0 deletions src/core/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#define CORE_DEFS_H

#include <stdint.h>
#include <stdbool.h>

// C compilers may get unhappy when named arguments are not used. While
// there are things like __attribute__((unused)) which are arguably
Expand Down Expand Up @@ -124,6 +125,54 @@ typedef void (*nni_idhash_cb2)(void *, void *, void *);
(((uint64_t) ((uint8_t) (ptr)[6])) << 8u) + \
(((uint64_t) (uint8_t) (ptr)[7]))

// Modern CPUs are all little endian. Let's stop paying the endian tax.

#define NNI_PUT16LE(ptr, u) \
do { \
(ptr)[1] = (uint8_t) (((uint16_t) (u)) >> 8u); \
(ptr)[0] = (uint8_t) ((uint16_t) (u)); \
} while (0)

#define NNI_PUT32LE(ptr, u) \
do { \
(ptr)[3] = (uint8_t) (((uint32_t) (u)) >> 24u); \
(ptr)[2] = (uint8_t) (((uint32_t) (u)) >> 16u); \
(ptr)[1] = (uint8_t) (((uint32_t) (u)) >> 8u); \
(ptr)[0] = (uint8_t) ((uint32_t) (u)); \
} while (0)

#define NNI_PUT64LE(ptr, u) \
do { \
(ptr)[7] = (uint8_t) (((uint64_t) (u)) >> 56u); \
(ptr)[6] = (uint8_t) (((uint64_t) (u)) >> 48u); \
(ptr)[5] = (uint8_t) (((uint64_t) (u)) >> 40u); \
(ptr)[4] = (uint8_t) (((uint64_t) (u)) >> 32u); \
(ptr)[3] = (uint8_t) (((uint64_t) (u)) >> 24u); \
(ptr)[2] = (uint8_t) (((uint64_t) (u)) >> 16u); \
(ptr)[1] = (uint8_t) (((uint64_t) (u)) >> 8u); \
(ptr)[0] = (uint8_t) ((uint64_t) (u)); \
} while (0)

#define NNI_GET16LE(ptr, v) \
v = (((uint16_t) ((uint8_t) (ptr)[1])) << 8u) + \
(((uint16_t) (uint8_t) (ptr)[0]))

#define NNI_GET32LE(ptr, v) \
v = (((uint32_t) ((uint8_t) (ptr)[3])) << 24u) + \
(((uint32_t) ((uint8_t) (ptr)[2])) << 16u) + \
(((uint32_t) ((uint8_t) (ptr)[1])) << 8u) + \
(((uint32_t) (uint8_t) (ptr)[0]))

#define NNI_GET64LE(ptr, v) \
v = (((uint64_t) ((uint8_t) (ptr)[7])) << 56u) + \
(((uint64_t) ((uint8_t) (ptr)[6])) << 48u) + \
(((uint64_t) ((uint8_t) (ptr)[5])) << 40u) + \
(((uint64_t) ((uint8_t) (ptr)[4])) << 32u) + \
(((uint64_t) ((uint8_t) (ptr)[3])) << 24u) + \
(((uint64_t) ((uint8_t) (ptr)[2])) << 16u) + \
(((uint64_t) ((uint8_t) (ptr)[1])) << 8u) + \
(((uint64_t) (uint8_t) (ptr)[0]))

// This increments a pointer a fixed number of byte cells.
#define NNI_INCPTR(ptr, n) ((ptr) = (void *) ((char *) (ptr) + (n)))

Expand Down Expand Up @@ -192,4 +241,19 @@ typedef struct subinfo subinfo;
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif

#if !defined(NNG_BIG_ENDIAN) && !defined(NNG_LITTLE_ENDIAN)
#if defined(__BYTE_ORDER__)
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define NNG_BIG_ENDIAN 1
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define NNG_LITTLE_ENDIAN 1
#else // middle-endian? (aka PDP-11)
#error "Unsupported or unknown endian"
#endif // __BYTE_ORDER__
#else // defined(__BYTE_ORDER__)
#define NNG_LITTLE_ENDIAN 1
#error "Unknown endian: specify -DNNG_BIG_ENDIAN=1 or -DNNG_LITTLE_ENDIAN=1"
#endif // defined(__BYTE_ORDER)
#endif // defined() endianness

#endif // CORE_DEFS_H
32 changes: 30 additions & 2 deletions src/core/idhash.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
Expand Down Expand Up @@ -466,4 +466,32 @@ nni_id_alloc32(nni_id_map *m, uint32_t *idp, void *val)
NNI_ASSERT(id < (1ULL << 32));
*idp = (uint32_t) id;
return (rv);
}
}

bool
nni_id_visit(nni_id_map *m, uint64_t *keyp, void **valp, uint32_t *cursor)
{
// cursor is just a cursor into the table
uint32_t index = *cursor;
while (index < m->id_cap) {
if (m->id_entries[index].val != NULL) {
if (valp != NULL) {
*valp = m->id_entries[index].val;
}
if (keyp != NULL) {
*keyp = m->id_entries[index].key;
}
*cursor = index + 1;
return true;
}
index++;
}
*cursor = index;
return (false);
}

uint32_t
nni_id_count(const nni_id_map *m)
{
return (m->id_count);
}
20 changes: 11 additions & 9 deletions src/core/idhash.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
Expand Down Expand Up @@ -46,14 +46,16 @@ struct nni_id_map {
#define NNI_ID_FLAG_RANDOM 2 // start at a random value
#define NNI_ID_FLAG_REGISTER 4 // map is registered for finalization

extern void nni_id_map_init(nni_id_map *, uint64_t, uint64_t, bool);
extern void nni_id_map_fini(nni_id_map *);
extern void *nni_id_get(nni_id_map *, uint64_t);
extern int nni_id_set(nni_id_map *, uint64_t, void *);
extern int nni_id_alloc(nni_id_map *, uint64_t *, void *);
extern int nni_id_alloc32(nni_id_map *, uint32_t *, void *);
extern int nni_id_remove(nni_id_map *, uint64_t);
extern void nni_id_map_sys_fini(void);
extern void nni_id_map_init(nni_id_map *, uint64_t, uint64_t, bool);
extern void nni_id_map_fini(nni_id_map *);
extern void *nni_id_get(nni_id_map *, uint64_t);
extern int nni_id_set(nni_id_map *, uint64_t, void *);
extern int nni_id_alloc(nni_id_map *, uint64_t *, void *);
extern int nni_id_alloc32(nni_id_map *, uint32_t *, void *);
extern int nni_id_remove(nni_id_map *, uint64_t);
extern void nni_id_map_sys_fini(void);
extern bool nni_id_visit(nni_id_map *, uint64_t *, void **, uint32_t *);
extern uint32_t nni_id_count(const nni_id_map *);

// For NanoNNG
extern void nni_id_map_foreach(nni_id_map *, nni_idhash_cb);
Expand Down
60 changes: 17 additions & 43 deletions src/core/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,20 @@

#include <nng/nng.h>

#include "core/nng_impl.h"
#include "core/tcp.h"
#include "core/url.h"
#include "nng_impl.h"
#include "tcp.h"

typedef struct {
nng_stream_dialer ops;
char * host;
char * port;
char *host;
char *port;
int af; // address family
bool closed;
nng_sockaddr sa;
nni_tcp_dialer * d; // platform dialer implementation
nni_aio * resaio; // resolver aio
nni_aio * conaio; // platform connection aio
nni_tcp_dialer *d; // platform dialer implementation
nni_aio *resaio; // resolver aio
nni_aio *conaio; // platform connection aio
nni_list conaios;
nni_mtx mtx;
} tcp_dialer;
Expand Down Expand Up @@ -62,7 +63,7 @@ static void
tcp_dial_res_cb(void *arg)
{
tcp_dialer *d = arg;
nni_aio * aio;
nni_aio *aio;
int rv;

nni_mtx_lock(&d->mtx);
Expand Down Expand Up @@ -94,7 +95,7 @@ static void
tcp_dial_con_cb(void *arg)
{
tcp_dialer *d = arg;
nng_aio * aio;
nng_aio *aio;
int rv;

nni_mtx_lock(&d->mtx);
Expand Down Expand Up @@ -124,7 +125,7 @@ static void
tcp_dialer_close(void *arg)
{
tcp_dialer *d = arg;
nni_aio * aio;
nni_aio *aio;
nni_mtx_lock(&d->mtx);
d->closed = true;
while ((aio = nni_list_first(&d->conaios)) != NULL) {
Expand Down Expand Up @@ -237,10 +238,6 @@ nni_tcp_dialer_alloc(nng_stream_dialer **dp, const nng_url *url)
int rv;
const char *p;

if ((rv = nni_init()) != 0) {
return (rv);
}

if ((rv = tcp_dialer_alloc(&d)) != 0) {
return (rv);
}
Expand Down Expand Up @@ -275,7 +272,7 @@ nni_tcp_dialer_alloc(nng_stream_dialer **dp, const nng_url *url)

typedef struct {
nng_stream_listener ops;
nni_tcp_listener * l;
nni_tcp_listener *l;
nng_sockaddr sa;
} tcp_listener;

Expand Down Expand Up @@ -316,7 +313,7 @@ tcp_listener_get_port(void *arg, void *buf, size_t *szp, nni_type t)
nng_sockaddr sa;
size_t sz;
int port;
uint8_t * paddr;
uint8_t *paddr;

sz = sizeof(sa);
rv = nni_tcp_listener_get(
Expand Down Expand Up @@ -372,6 +369,9 @@ tcp_listener_alloc_addr(nng_stream_listener **lp, const nng_sockaddr *sa)
tcp_listener *l;
int rv;

if ((rv = nni_init()) != 0) {
return (rv);
}
if ((l = NNI_ALLOC_STRUCT(l)) == NULL) {
return (NNG_ENOMEM);
}
Expand All @@ -395,41 +395,15 @@ tcp_listener_alloc_addr(nng_stream_listener **lp, const nng_sockaddr *sa)
int
nni_tcp_listener_alloc(nng_stream_listener **lp, const nng_url *url)
{
nni_aio * aio;
int af;
int rv;
nng_sockaddr sa;
const char * h;

if ((rv = nni_init()) != 0) {
return (rv);
}
if (strchr(url->u_scheme, '4') != NULL) {
af = NNG_AF_INET;
} else if (strchr(url->u_scheme, '6') != NULL) {
af = NNG_AF_INET6;
} else {
af = NNG_AF_UNSPEC;
}

if ((rv = nng_aio_alloc(&aio, NULL, NULL)) != 0) {
return (rv);
}

h = url->u_hostname;

// Wildcard special case, which means bind to INADDR_ANY.
if ((h != NULL) && ((strcmp(h, "*") == 0) || (strcmp(h, "") == 0))) {
h = NULL;
}
nni_resolv_ip(h, url->u_port, af, true, &sa, aio);
nni_aio_wait(aio);

if ((rv = nni_aio_result(aio)) != 0) {
nni_aio_free(aio);
if ((rv = nni_url_to_address(&sa, url)) != 0) {
return (rv);
}
nni_aio_free(aio);

return (tcp_listener_alloc_addr(lp, &sa));
}
Loading
Loading