Coverage Report

Created: 2025-10-28 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libzmq/src/ws_address.cpp
Line
Count
Source
1
/* SPDX-License-Identifier: MPL-2.0 */
2
3
#include "precompiled.hpp"
4
#include <string>
5
#include <sstream>
6
7
#include "macros.hpp"
8
#include "ws_address.hpp"
9
#include "stdint.hpp"
10
#include "err.hpp"
11
#include "ip.hpp"
12
13
#ifndef ZMQ_HAVE_WINDOWS
14
#include <sys/types.h>
15
#include <arpa/inet.h>
16
#include <netinet/tcp.h>
17
#include <net/if.h>
18
#include <netdb.h>
19
#include <ctype.h>
20
#include <unistd.h>
21
#include <stdlib.h>
22
#endif
23
24
#include <limits.h>
25
26
zmq::ws_address_t::ws_address_t ()
27
867
{
28
867
    memset (&_address, 0, sizeof (_address));
29
867
}
30
31
zmq::ws_address_t::ws_address_t (const sockaddr *sa_, socklen_t sa_len_)
32
0
{
33
0
    zmq_assert (sa_ && sa_len_ > 0);
34
35
0
    memset (&_address, 0, sizeof (_address));
36
0
    if (sa_->sa_family == AF_INET
37
0
        && sa_len_ >= static_cast<socklen_t> (sizeof (_address.ipv4)))
38
0
        memcpy (&_address.ipv4, sa_, sizeof (_address.ipv4));
39
0
    else if (sa_->sa_family == AF_INET6
40
0
             && sa_len_ >= static_cast<socklen_t> (sizeof (_address.ipv6)))
41
0
        memcpy (&_address.ipv6, sa_, sizeof (_address.ipv6));
42
43
0
    _path = std::string ("");
44
45
0
    char hbuf[NI_MAXHOST];
46
0
    const int rc = getnameinfo (addr (), addrlen (), hbuf, sizeof (hbuf), NULL,
47
0
                                0, NI_NUMERICHOST);
48
0
    if (rc != 0) {
49
0
        _host = std::string ("localhost");
50
0
        return;
51
0
    }
52
53
0
    std::ostringstream os;
54
55
0
    if (_address.family () == AF_INET6)
56
0
        os << std::string ("[");
57
58
0
    os << std::string (hbuf);
59
60
0
    if (_address.family () == AF_INET6)
61
0
        os << std::string ("]");
62
63
0
    _host = os.str ();
64
0
}
65
66
int zmq::ws_address_t::resolve (const char *name_, bool local_, bool ipv6_)
67
867
{
68
    //  find the host part, It's important to use str*r*chr to only get
69
    //  the latest colon since IPv6 addresses use colons as delemiters.
70
867
    const char *delim = strrchr (name_, ':');
71
867
    if (delim == NULL) {
72
1
        errno = EINVAL;
73
1
        return -1;
74
1
    }
75
866
    _host = std::string (name_, delim - name_);
76
77
    // find the path part, which is optional
78
866
    delim = strrchr (name_, '/');
79
866
    std::string host_name;
80
866
    if (delim) {
81
453
        _path = std::string (delim);
82
        // remove the path, otherwise resolving the port will fail with wildcard
83
453
        host_name = std::string (name_, delim - name_);
84
453
    } else {
85
413
        _path = std::string ("/");
86
413
        host_name = name_;
87
413
    }
88
89
866
    ip_resolver_options_t resolver_opts;
90
866
    resolver_opts.bindable (local_)
91
866
      .allow_dns (!local_)
92
866
      .allow_nic_name (local_)
93
866
      .ipv6 (ipv6_)
94
866
      .allow_path (true)
95
866
      .expect_port (true);
96
97
866
    ip_resolver_t resolver (resolver_opts);
98
99
866
    return resolver.resolve (&_address, host_name.c_str ());
100
867
}
101
102
int zmq::ws_address_t::to_string (std::string &addr_) const
103
758
{
104
758
    std::ostringstream os;
105
758
    os << std::string ("ws://") << host () << std::string (":")
106
758
       << _address.port () << _path;
107
758
    addr_ = os.str ();
108
109
758
    return 0;
110
758
}
111
112
const sockaddr *zmq::ws_address_t::addr () const
113
0
{
114
0
    return _address.as_sockaddr ();
115
0
}
116
117
socklen_t zmq::ws_address_t::addrlen () const
118
0
{
119
0
    return _address.sockaddr_len ();
120
0
}
121
122
const char *zmq::ws_address_t::host () const
123
758
{
124
758
    return _host.c_str ();
125
758
}
126
127
const char *zmq::ws_address_t::path () const
128
0
{
129
0
    return _path.c_str ();
130
0
}
131
132
#if defined ZMQ_HAVE_WINDOWS
133
unsigned short zmq::ws_address_t::family () const
134
#else
135
sa_family_t zmq::ws_address_t::family () const
136
#endif
137
0
{
138
0
    return _address.family ();
139
0
}