Coverage Report

Created: 2026-02-26 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/logging-log4cxx/src/main/cpp/aprserversocket.cpp
Line
Count
Source
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
#include <log4cxx/private/aprserversocket.h>
19
#include <log4cxx/private/serversocket_priv.h>
20
#include <log4cxx/private/aprsocket.h>
21
#include <log4cxx/helpers/transcoder.h>
22
#include "apr_network_io.h"
23
#include "apr_pools.h"
24
#include "apr_poll.h"
25
26
namespace LOG4CXX_NS
27
{
28
namespace helpers
29
{
30
31
0
#define _priv static_cast<APRServerSocketPriv*>(m_priv.get())
32
33
struct APRServerSocket::APRServerSocketPriv : public ServerSocketPrivate {
34
  Pool pool;
35
  std::mutex mutex;
36
  apr_socket_t* socket{ 0 };
37
  apr_pollset_t* pSet{ 0 };
38
};
39
40
#if LOG4CXX_ABI_VERSION <= 15
41
APRServerSocket::APRServerSocket(int port) : 
42
0
  APRServerSocket(port, false, {}) {}
43
#endif
44
45
APRServerSocket::APRServerSocket(int port, bool reuseAddress, const LogString& hostname) :
46
0
  ServerSocket(std::make_unique<APRServerSocketPriv>()){
47
0
  apr_status_t status =
48
0
    apr_socket_create(&_priv->socket, APR_INET, SOCK_STREAM,
49
0
      APR_PROTO_TCP, _priv->pool.getAPRPool());
50
51
0
  if (status != APR_SUCCESS)
52
0
  {
53
0
    throw SocketException(status);
54
0
  }
55
56
0
  status = apr_socket_opt_set(_priv->socket, APR_SO_NONBLOCK, 1);
57
58
0
  if (status != APR_SUCCESS)
59
0
  {
60
0
    throw SocketException(status);
61
0
  }
62
63
0
  if (reuseAddress) {
64
0
    apr_status_t status = apr_socket_opt_set(_priv->socket, APR_SO_REUSEADDR, 1);
65
66
0
    if (status != APR_SUCCESS)
67
0
    {
68
0
      throw SocketException(status);
69
0
    }
70
0
  }
71
72
  // Create server socket address (including port number)
73
0
  std::string hostname_str;
74
0
  const char* hostname_ptr = NULL;
75
0
  if (!hostname.empty()) {
76
0
    Transcoder::encode(hostname, hostname_str);
77
0
    hostname_ptr = hostname_str.c_str();
78
0
  }
79
80
0
  apr_sockaddr_t* server_addr;
81
0
  status =
82
0
    apr_sockaddr_info_get(&server_addr, hostname_ptr, APR_INET,
83
0
      port, 0, _priv->pool.getAPRPool());
84
85
0
  if (status != APR_SUCCESS)
86
0
  {
87
0
    throw ConnectException(status);
88
0
  }
89
90
  // bind the socket to the address
91
0
  status = apr_socket_bind(_priv->socket, server_addr);
92
93
0
  if (status != APR_SUCCESS)
94
0
  {
95
0
    throw BindException(status);
96
0
  }
97
98
99
0
  status = apr_socket_listen(_priv->socket, 50);
100
101
0
  if (status != APR_SUCCESS)
102
0
  {
103
0
    throw SocketException(status);
104
0
  }
105
0
}
106
107
void APRServerSocket::close()
108
0
{
109
0
  std::lock_guard<std::mutex> lock(_priv->mutex);
110
111
0
  if (_priv->pSet)
112
0
    apr_pollset_wakeup(_priv->pSet);
113
0
  if (_priv->socket != 0)
114
0
  {
115
0
    apr_status_t status = apr_socket_close(_priv->socket);
116
117
0
    if (status != APR_SUCCESS)
118
0
    {
119
0
      throw SocketException(status);
120
0
    }
121
122
0
    _priv->socket = 0;
123
0
  }
124
0
}
125
126
127
/** Listens for a connection to be made to this socket and
128
accepts it
129
*/
130
SocketPtr APRServerSocket::accept()
131
0
{
132
0
  apr_socket_t* s;
133
0
  {
134
0
    std::lock_guard<std::mutex> lock(_priv->mutex);
135
0
    s = _priv->socket;
136
0
  }
137
0
  if (s == 0)
138
0
  {
139
0
    throw NullPointerException(LOG4CXX_STR("socket"));
140
0
  }
141
142
0
  if (!_priv->pSet)
143
0
  {
144
0
    apr_pollfd_t poll;
145
0
    poll.p = _priv->pool.getAPRPool();
146
0
    poll.desc_type = APR_POLL_SOCKET;
147
0
    poll.reqevents = APR_POLLIN;
148
0
    poll.rtnevents = 0;
149
0
    poll.desc.s = s;
150
0
    poll.client_data = NULL;
151
0
    auto status = apr_pollset_create(&_priv->pSet, 1, _priv->pool.getAPRPool(), APR_POLLSET_WAKEABLE);
152
0
    if (status != APR_SUCCESS)
153
0
    {
154
0
      throw SocketException(status);
155
0
    }
156
0
    apr_pollset_add(_priv->pSet, &poll);
157
0
  }
158
159
0
  const apr_pollfd_t* descriptors;
160
0
  apr_int32_t signaled;
161
0
  apr_interval_time_t to = _priv->timeout * 1000;
162
0
  apr_status_t status = apr_pollset_poll(_priv->pSet, to, &signaled, &descriptors);
163
164
0
  if (APR_STATUS_IS_TIMEUP(status))
165
0
  {
166
0
    throw SocketTimeoutException();
167
0
  }
168
0
  else if (status != APR_SUCCESS)
169
0
  {
170
0
    throw SocketException(status);
171
0
  }
172
173
0
  apr_pool_t* newPool;
174
0
  status = apr_pool_create(&newPool, 0);
175
176
0
  if (status != APR_SUCCESS)
177
0
  {
178
0
    throw PoolException(status);
179
0
  }
180
181
0
  apr_socket_t* newSocket;
182
0
  status = apr_socket_accept(&newSocket, s, newPool);
183
184
0
  if (status != APR_SUCCESS)
185
0
  {
186
0
    apr_pool_destroy(newPool);
187
0
    throw SocketException(status);
188
0
  }
189
190
0
  status = apr_socket_opt_set(newSocket, APR_SO_NONBLOCK, 0);
191
192
0
  if (status != APR_SUCCESS)
193
0
  {
194
0
    apr_pool_destroy(newPool);
195
0
    throw SocketException(status);
196
0
  }
197
198
0
  return std::make_shared<APRSocket>(newSocket, newPool);
199
0
}
200
201
} //namespace helpers
202
} //namespace log4cxx