Coverage Report

Created: 2025-07-01 06:08

/src/logging-log4cxx/src/main/cpp/aprsocket.cpp
Line
Count
Source (jump to first uncovered line)
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/aprsocket.h>
19
#include <log4cxx/private/socket_priv.h>
20
#include <log4cxx/helpers/bytebuffer.h>
21
#include <log4cxx/helpers/transcoder.h>
22
23
#include "apr_network_io.h"
24
#include "apr_signal.h"
25
26
namespace LOG4CXX_NS
27
{
28
namespace helpers
29
{
30
31
struct APRSocket::APRSocketPriv : public Socket::SocketPrivate {
32
  APRSocketPriv(InetAddressPtr& address, int port)
33
0
    : Socket::SocketPrivate(address, port)
34
0
    , socket(nullptr)
35
0
  {}
36
37
  APRSocketPriv(apr_socket_t* sock, apr_pool_t* p) :
38
0
    pool(p, true),
39
0
    socket(sock)
40
0
  {}
41
42
  Pool pool;
43
  apr_socket_t* socket;
44
};
45
46
0
#define _priv static_cast<APRSocketPriv*>(m_priv.get())
47
48
APRSocket::APRSocket(InetAddressPtr& address, int port) :
49
0
  Socket(std::make_unique<APRSocketPriv>(address, port)){
50
0
  apr_status_t status =
51
0
    apr_socket_create(&_priv->socket, APR_INET, SOCK_STREAM,
52
0
      APR_PROTO_TCP, _priv->pool.getAPRPool());
53
54
0
  if (status != APR_SUCCESS)
55
0
  {
56
0
    throw SocketException(status);
57
0
  }
58
59
0
  LOG4CXX_ENCODE_CHAR(host, address->getHostAddress());
60
61
  // create socket address (including port)
62
0
  apr_sockaddr_t* client_addr;
63
0
  status =
64
0
    apr_sockaddr_info_get(&client_addr, host.c_str(), APR_INET,
65
0
      port, 0, _priv->pool.getAPRPool());
66
67
0
  if (status != APR_SUCCESS)
68
0
  {
69
0
    throw ConnectException(status);
70
0
  }
71
72
  // connect the socket
73
0
  status =  apr_socket_connect(_priv->socket, client_addr);
74
75
0
  if (status != APR_SUCCESS)
76
0
  {
77
0
    throw ConnectException(status);
78
0
  }
79
0
}
80
81
APRSocket::APRSocket(apr_socket_t* s, apr_pool_t* pool) :
82
0
  Socket(std::make_unique<APRSocketPriv>(s, pool)){
83
0
  apr_sockaddr_t* sa;
84
0
  apr_status_t status = apr_socket_addr_get(&sa, APR_REMOTE, s);
85
86
0
  if (status == APR_SUCCESS)
87
0
  {
88
0
    _priv->port = sa->port;
89
0
    LogString remotename;
90
0
    LogString remoteip;
91
92
0
    if (sa->hostname != NULL)
93
0
    {
94
0
      Transcoder::decode(sa->hostname, remotename);
95
0
    }
96
97
0
    char* buf = 0;
98
0
    status = apr_sockaddr_ip_get(&buf, sa);
99
100
0
    if (status == APR_SUCCESS)
101
0
    {
102
0
      Transcoder::decode(buf, remoteip);
103
0
    }
104
105
0
    _priv->address = std::make_shared<InetAddress>(remotename, remoteip);
106
0
  }
107
0
}
108
109
size_t APRSocket::write(ByteBuffer& buf)
110
0
{
111
0
  if (_priv->socket == 0)
112
0
  {
113
0
    throw ClosedChannelException();
114
0
  }
115
116
0
  size_t totalWritten = 0;
117
118
0
  while (buf.remaining() > 0)
119
0
  {
120
0
    apr_size_t written = buf.remaining();
121
122
    // while writing to the socket, we need to ignore the SIGPIPE
123
    // signal. Otherwise, when the client has closed the connection,
124
    // the send() function would not return an error but call the
125
    // SIGPIPE handler.
126
0
#if APR_HAVE_SIGACTION
127
0
    apr_sigfunc_t* old = apr_signal(SIGPIPE, SIG_IGN);
128
0
    apr_status_t status = apr_socket_send(_priv->socket, buf.current(), &written);
129
0
    apr_signal(SIGPIPE, old);
130
#else
131
    apr_status_t status = apr_socket_send(_priv->socket, buf.current(), &written);
132
#endif
133
134
0
    buf.position(buf.position() + written);
135
0
    totalWritten += written;
136
137
0
    if (status != APR_SUCCESS)
138
0
    {
139
0
      throw SocketException(status);
140
0
    }
141
0
  }
142
143
0
  return totalWritten;
144
0
}
145
146
147
void APRSocket::close()
148
0
{
149
0
  if (_priv->socket != 0)
150
0
  {
151
0
    apr_status_t status = apr_socket_close(_priv->socket);
152
153
0
    if (status != APR_SUCCESS)
154
0
    {
155
0
      throw SocketException(status);
156
0
    }
157
158
0
    _priv->socket = 0;
159
0
  }
160
0
}
161
162
apr_socket_t* APRSocket::getSocketPtr() const
163
0
{
164
0
  return _priv->socket;
165
0
}
166
167
} //namespace helpers
168
} //namespace log4cxx