Commit graph

79 commits

Author SHA1 Message Date
Thomas Haller
95ccfdb69a shared: add NM_CMP_DIRECT_PTR() macro 2020-04-22 09:49:45 +02:00
Thomas Haller
f3ca61e6e4 shared/trivial: fix typo in code comment and reword 2020-04-10 10:55:22 +02:00
Thomas Haller
d1c2572e11 shared: add NM_UTILS_GET_NEXT_REALLOC_SIZE_1000 define
When we have a buffer that we want to grow exponentially with
nm_utils_get_next_realloc_size(), then there are certain buffer
sizes that are better suited.

For example, if you have an empty NMStrBuf (len == 0), and you
want to allocate roughly one kilobyte, then 1024 is a bad choice,
because nm_utils_get_next_realloc_size() will give you 2024 bytes.

NM_UTILS_GET_NEXT_REALLOC_SIZE_1000 might be better in this case.
2020-04-10 10:44:37 +02:00
Thomas Haller
be8be0f091 shared: fix crash in _NM_UTILS_STRING_TABLE_LOOKUP_DEFINE()
If you have a LIST with 7 elements, and you lookup a value that
is not in the (sorted) list and would lie before the first element,
the binary search will dig down to imin=0, imid=0, imax=0 and
strcmp will give positive cmp value (indicating that the searched
value is sorted before).

Then, we would do "imax = imid - 1;", which wrapped to G_MAXUINT,
and the following "if (G_UNLIKELY (imin > imax))" would not hit,
resulting in an out of bound access next.

The easy fix is to not used unsigned integers.

The binary search was adapted from nm_utils_array_find_binary_search()
and nm_utils_ptrarray_find_binary_search(), which already used signed
integers to avoid this problem.

Fixes: 17d9b852c8 ('shared: explicitly implement binary search in NM_UTILS_STRING_TABLE_LOOKUP_DEFINE*()')
2020-04-10 07:57:08 +02:00
Thomas Haller
5cc7abd7a4 shared: add nm_utils_escaped_tokens_options_*() API
This will be used for splitting and escaping option parameters in
nmcli (vpn.data).
2020-04-04 19:51:34 +02:00
Thomas Haller
d1a9c2bd42 shared: add flags for nm_utils_escaped_tokens_escape_full()
Add flags to explicitly escape leading or trailing spaces. Note
that we were already escaping trailing spaces.

This will be used later when supporting backslash escapes for
option parameters for nmcli (vpn.data).
2020-04-04 19:51:34 +02:00
Thomas Haller
484d44fc87 shared/trivial: improve code comments about NMUtilsStrsplitSetFlags flags 2020-04-04 19:51:34 +02:00
Thomas Haller
63545d31ca shared: add nm_g_hash_table_*() utils for accepting %NULL hash argument 2020-04-04 19:51:34 +02:00
Thomas Haller
55a058aeef libnmm,shared: extract and move nm_utils_strdict_to_variant_ass() to shared
This is a helper function that converts a string dictionary to an "a{ss}"
GVariant. It is generally useful, and should be independent from the
caller.
2020-04-04 19:51:34 +02:00
Thomas Haller
27e788cce8 shared: add NM_UTILS_STR_UTF8_SAFE_FLAG_SECRET flag
The new flag tells that as we re-allocate data buffers during
escaping, we bzero the memory to avoid leaking secrets.
2020-04-03 11:31:12 +02:00
Thomas Haller
04d0d1bbe5 shared: add nm_utils_get_next_realloc_size() helper
When growing a buffer by appending a previously unknown number
of elements, the often preferable strategy is growing it exponentially,
so that the amortized runtime and re-allocation costs scale linearly.
GString just always increases the buffer length to the next power of
two. That works.

I think there is value in trying to find an optimal next size. Because
while it doesn't matter in terms of asymptotic behavior, in practice
a better choice should make a difference. This is inspired by what QT
does ([1]), to take more care when growing the buffers:

  - QString allocates 4 characters at a time until it reaches size 20.
  - From 20 to 4084, it advances by doubling the size each time. More
    precisely, it advances to the next power of two, minus 12. (Some memory
    allocators perform worst when requested exact powers of two, because
    they use a few bytes per block for book-keeping.)
  - From 4084 on, it advances by blocks of 2048 characters (4096 bytes).
    This makes sense because modern operating systems don't copy the entire
    data when reallocating a buffer; the physical memory pages are simply
    reordered, and only the data on the first and last pages actually needs
    to be copied.

Note that a QT is talking about 12 characters, so we use 24 bytes
head room.

[1] https://doc.qt.io/qt-5/containers.html#growth-strategies
2020-04-03 11:31:12 +02:00
Thomas Haller
3b58c5fef4 shared: add nm_g_ascii_strtoull() to workaround bug 2020-04-01 17:18:01 +02:00
Thomas Haller
35a9f632a8 shared: add nm_g_ascii_strtod() to workaround bug 2020-04-01 17:18:01 +02:00
Thomas Haller
f4446e34c6 shared: add nm_g_ascii_strtoll() to workaround bug 2020-04-01 17:18:00 +02:00
Thomas Haller
d3e5eab734 shared: add nm_g_variant_is_of_type() helper 2020-03-17 08:02:54 +01:00
Thomas Haller
4087024a9b shared: move assertion in _NM_UTILS_STRING_TABLE_LOOKUP_DEFINE()
Move the assertion for valid LIST first. It only checks static data,
and regardless of the entry_cmd, it should be done first.

Fixes: f4d12f7b59 ('shared: add NM_UTILS_STRING_TABLE_LOOKUP_STRUCT_DEFINE() macro for lookup of structs')
2020-03-02 16:20:50 +01:00
Thomas Haller
294de8487e shared: add NMU_IFACE_OVS_OR_KERNEL for nm_utils_ifname_valid()
Depending on the type, OVS interfaces also have a corresponding netdev
in kernel (e.g. type "internal" does, type "patch" does not).

Such a case is neither NMU_IFACE_OVS nor NMU_IFACE_KERNEL (alone). There should
be a special type to represent those cases.

Add NMU_IFACE_OVS_OR_KERNEL for that.
2020-02-26 17:51:14 +01:00
Thomas Haller
807cddc754 shared: add NMU_IFACE_ANY for nm_utils_ifname_valid()
nm_utils_ifname_valid() is to validate "connection.interface-name"
property. But the exact validation depends on the connection type.

Add "NMU_IFACE_ANY" to validate the name to check whether it would be
valid for any connection type.

This is for completeness and for places where the caller might not know
the connection type.
2020-02-26 17:51:14 +01:00
Thomas Haller
cba938f3ee shared: add nm_utils_named_values_from_str_dict_full() to allow different sort order (or none) 2020-02-19 16:24:55 +01:00
Thomas Haller
f4d12f7b59 shared: add NM_UTILS_STRING_TABLE_LOOKUP_STRUCT_DEFINE() macro for lookup of structs 2020-02-19 15:35:07 +01:00
Antonio Cardace
550f538564 nm-shared-utils: add nm_utils_ifname_valid*() to shared utils
Move the body of nm_utils_is_valid_iface_name() to
nm_utils_ifname_valid_kernel() so that it's shared between NM and
clients.
2020-02-17 15:27:35 +01:00
Thomas Haller
cd31437024 shared: drop _STATIC variant of macros that define functions
Several macros are used to define function. They had a "_STATIC" variant,
to define the function as static.

I think those macros should not try to abstract entirely what they do.
They should not accept the function scope as argument (or have two
variants per scope). This also because it might make sense to add
additional __attribute__(()) to the function. That only works, if
the macro does not pretend to *not* define a plain function.

Instead, embrace what the function does and let the users place the
function scope as they see fit.

This also follows what is already done with

    static NM_CACHED_QUARK_FCN ("autoconnect-root", autoconnect_root_quark)
2020-02-13 17:17:07 +01:00
Thomas Haller
17d9b852c8 shared: explicitly implement binary search in NM_UTILS_STRING_TABLE_LOOKUP_DEFINE*()
When looking at nm_utils_array_find_binary_search(), we see that binary
search really isn't complicated. In nm_utils_array_find_binary_search()
it looks complicated, because that is our general purpose function which
accepts arbitrary lists, uses an opaque compare function, accepts a user
data argument, and returns the insertion position.

This is unnecessary for the narrow purpose in NM_UTILS_STRING_TABLE_LOOKUP_DEFINE*().
When we inline the binary search, it can be simplified, and the remaining
parts is simple enough to prefer this duplication of binary search over
using our general purpose function.

Also, this gives the compiler more chance for optimization. For
example, we can use "unsigned" as index type instead of gssize, because
we know (at compile time), that this type will always be large enough
for our LIST. Also, we can directly call strcmp().

The result is that the macro's implementation is also fast in the best
case (where the needle is found with only one strcmp()) and in the cases
where there is a small number of items to search.
It thus alleviates concerns that using the macro might be slower than
an optimized implementation.

The binary size of the defined function increases slightly (from 112
bytes to 192 bytes, on x86_64, GCC, -O2). But according to my tests it
is slightly and measurably faster.
2020-02-13 14:49:45 +01:00
Thomas Haller
487141d4a8 shared: add entry_cmd argument to NM_UTILS_STRING_TABLE_LOOKUP_DEFINE*() macro
This extra argument allows to tweak whether to assert for the input argument name.
2020-02-13 10:46:34 +01:00
Thomas Haller
8c23586a77 shared: drop nm_utils_dbus_normalize_object_path() in favor of nm_dbus_path_not_empty()
They do the same thing. Unify and drop one.
2020-02-10 19:11:50 +01:00
Thomas Haller
c7e6573eb4 shared: add nm_g_variant_lookup() and nm_g_variant_lookup_value() helpers
It's often convenient to accept %NULL as dictionary argument.
2020-02-10 19:11:50 +01:00
Thomas Haller
455cec9986 shared: add nm_utils_strdup_reset() helper 2020-02-10 19:11:50 +01:00
Thomas Haller
f4fa003434 shared: add NM_UTILS_STRING_TABLE_LOOKUP_DEFINE() macro to simplify defining string lookup functions 2020-02-10 19:11:50 +01:00
Thomas Haller
53f6858a27 all: add nm_utils_error_is_cancelled() and nm_utils_error_is_cancelled_or_disposing()
Most callers would pass FALSE to nm_utils_error_is_cancelled(). That's
not very useful. Split the two functions and have nm_utils_error_is_cancelled()
and nm_utils_error_is_cancelled_is_disposing().
2020-02-10 19:11:50 +01:00
Thomas Haller
228519fe79 shared: add nm_ip_addr_cmp()/nm_ip_addr_equal() helpers 2020-01-28 11:43:22 +01:00
Thomas Haller
b9c5c07c4d shared: add NM_IP_ADDR_ZERO macro for initializing NMIPAddr to zero 2020-01-28 11:17:41 +01:00
Thomas Haller
cdfbbe651b shared: add nm_utils_ipaddr_is_valid()/nm_utils_ipaddr_is_normalized() helpers 2020-01-28 11:17:41 +01:00
Thomas Haller
0f9664f417 shared: use static array indices in function parameter declarations of _nm_utils_inet[46]_ntop()
This should give the compiler more possibilities to warn about wrong
use of the API.

In practice, my current compiler wouldn't flag any issues. However,
some compilers (or compile options) might.
2020-01-28 11:17:41 +01:00
Thomas Haller
c0bd6752b9 shared: move nm_utils_inet* helpers from libnm-core to shared 2020-01-28 11:17:41 +01:00
Thomas Haller
6e7e18c86f shared: add nm_g_main_context_is_thread_default() util 2020-01-28 10:54:14 +01:00
Thomas Haller
24b50625bd shared: add NM_UTILS_USEC_PER_SEC macro 2020-01-28 10:54:14 +01:00
Thomas Haller
1afabd5ffd shared: add nm_source_func_unref_gobject() helper 2020-01-16 12:42:41 +01:00
Thomas Haller
421256073b shared: add nm_g_unix_fd_source_new() helper 2020-01-13 15:46:04 +01:00
Thomas Haller
bd9b253540 all: rename time related function to spell out nsec/usec/msec/sec
The abbreviations "ns" and "ms" seem not very clear to me. Spell them
out to nsec/msec. Also, in parts we already used the longer abbreviations,
so it wasn't consistent.
2019-12-13 16:54:40 +01:00
Thomas Haller
8fbf67d138 shared: add nm_utils_parse_inaddr_bin_full() to support legacy IPv4 formats as inet_aton()
inet_aton() also supports IPv4 addresses in octal (with a leading '0')
or where not all 4 digits of the address are present.

Add nm_utils_parse_inaddr_bin_full() to optionally fallback to
parse the address with inet_aton().

Note taht inet_aton() also supports all crazy formats, including
ignoring trailing garbage after a whitespace. We don't want to accept
that in general.

Note that even in legacy format we:

  - accept everything that inet_pton() would accept

  - additionally, we also accept some forms which inet_aton() would
    accept, but not all.

That means, the legacy format that we accept is a superset of
inet_pton() and a subset of inet_aton(). Which is desirable.
2019-12-05 12:36:13 +01:00
Thomas Haller
06a976358b shared: add nm_utils_addr_family_from_size() helper 2019-12-05 12:36:13 +01:00
Thomas Haller
2b6f5a305c shared: add nm_utils_error_new() and nm_utils_error_new_cancelled() helper 2019-11-28 19:20:33 +01:00
Thomas Haller
4fad8c7c64 shared: add nm_utils_g_main_context_create_integrate_source() for integrating a GMainContext in another
We will rework NMClient entirely. Then, the synchronous initialization will also use
the asynchronous code paths. The difference will be that with synchronous initialization,
all D-Bus interaction will be done with an internal GMainContext as current thread default,
and that internal context will run until initialization completes.

Note that even after initialization completes, it cannot be swapped back to the user's
(outer) GMainContext. That is because contexts are essentially the queue for our
D-Bus events, and we cannot swap from one queue to the other in a race
free manner (or a full resync). In other words, the two contexts are not in sync,
so after using the internal context NMClient needs to stick to that (at least, until
the name owner gets lost, which gives an opportunity to resync and switch back to the
user's main context).

We thus need to hook the internal (inner) GMainContext with the user's (outer) context,
so when the user iterates the outer context, events on the inner context get dispatched.

Add nm_utils_g_main_context_create_integrate_source() to create such a GSource for
integrating two contexts.

Note that the use-case here is limited: the integrated, inner main context must
not be explicitly iterated except from being dispatched by the integrating
source. Otherwise, you'd get recursive runs, possible deadlocks and general
ugliness. NMClient must show restrain how to use the inner context while it is
integrated.
2019-11-25 12:58:33 +01:00
Thomas Haller
58811e019d shared: add nm_auto_unref_gmaincontext macro 2019-11-25 12:58:33 +01:00
Thomas Haller
ec868916c8 shared: move nm_utils_ip._address_clear_host_address() helpers to shared 2019-11-22 15:32:52 +01:00
Thomas Haller
2ef5014f98 shared: add nm_clear_g_source_inst()
glib really likes the numeric source IDs. That is, g_idle_add(), g_timeout_add(),
etc. return those IDs, that can then be destroyed with g_remove_source() (or
nm_clear_g_source()).

I think these numeric IDs are really not great.

- API like g_idle_add() and g_remove_source() only works with the g_main_context_get_default()
  instance. That means, you cannot use this API for any other contexts. If you'd insist on using
  numeric IDs, you'd need to call g_main_context_find_source_by_id() on the right context
  first (but you'd also have to track the context alongside the ID).
- g_remove_source() requires first a call to g_main_context_find_source_by_id(). This involves
  taking a mutex and doing an extra hash lookup.

Instead, it often seems preferable to use the GSource instance directly. It works
with any context, it can be referenced and unreferenced, and it can be destroyed, and
avoids the overhead of g_main_context_find_source_by_id().

The only downside really is that keeping a GSource pointer takes one pointer size, while
the guint source ID is usually only 4 bytes.

Anyway, I think we should deal more with GSource instances directly. Hence, add this
convenience macro, that works like nm_clear_g_source().
2019-11-22 15:32:52 +01:00
Thomas Haller
c40ff42ae6 shared: add nm_g_*_source_new() and nm_g_source_attach() helpers
Small utilities to make is more convenient to create and attach GSource
instances.
2019-11-22 15:32:52 +01:00
Thomas Haller
afa54fdfd5 shared: add nm_g_main_context_push_thread_default*() and nm_auto helper 2019-11-07 11:34:36 +01:00
Thomas Haller
3b95905ae3 shared: add nm_auto_destroy_and_unref_gsource macro 2019-11-07 11:34:36 +01:00
Thomas Haller
9b2d5742c1 shared: add nm_g_set_error_take*() util 2019-11-07 11:34:36 +01:00