/src/logging-log4cxx/src/main/cpp/aprsocket.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/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(LOG4CXX_16_CONST 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{ NULL }; |
44 | | bool connected{ false }; |
45 | | }; |
46 | | |
47 | 0 | #define _priv static_cast<APRSocketPriv*>(m_priv.get()) |
48 | | |
49 | | APRSocket::APRSocket(LOG4CXX_16_CONST InetAddressPtr& address, int port) |
50 | 0 | : Socket(std::make_unique<APRSocketPriv>(address, port)) |
51 | 0 | { |
52 | 0 | apr_status_t status = |
53 | 0 | apr_socket_create(&_priv->socket, APR_INET, SOCK_STREAM, |
54 | 0 | APR_PROTO_TCP, _priv->pool.getAPRPool()); |
55 | |
|
56 | 0 | if (status != APR_SUCCESS) |
57 | 0 | { |
58 | 0 | throw SocketException(status); |
59 | 0 | } |
60 | 0 | open(); |
61 | 0 | } |
62 | | |
63 | | void APRSocket::open() |
64 | 0 | { |
65 | 0 | LOG4CXX_ENCODE_CHAR(host, _priv->address->getHostAddress()); |
66 | | |
67 | | // create socket address (including port) |
68 | 0 | apr_sockaddr_t* client_addr; |
69 | 0 | apr_status_t status = apr_sockaddr_info_get |
70 | 0 | ( &client_addr |
71 | 0 | , host.c_str() |
72 | 0 | , APR_INET |
73 | 0 | , _priv->port |
74 | 0 | , 0 |
75 | 0 | , _priv->pool.getAPRPool() |
76 | 0 | ); |
77 | |
|
78 | 0 | if (status != APR_SUCCESS) |
79 | 0 | { |
80 | 0 | throw ConnectException(status); |
81 | 0 | } |
82 | | |
83 | | // connect the socket |
84 | 0 | status = apr_socket_connect(_priv->socket, client_addr); |
85 | |
|
86 | 0 | if (status != APR_SUCCESS) |
87 | 0 | { |
88 | 0 | throw ConnectException(status); |
89 | 0 | } |
90 | 0 | _priv->connected = true; |
91 | 0 | } |
92 | | |
93 | | // Is the socket available for use? |
94 | | bool APRSocket::is_open() |
95 | 0 | { |
96 | 0 | return _priv->socket && _priv->connected; |
97 | 0 | } |
98 | | |
99 | | APRSocket::APRSocket(apr_socket_t* s, apr_pool_t* pool) : |
100 | 0 | Socket(std::make_unique<APRSocketPriv>(s, pool)){ |
101 | 0 | apr_sockaddr_t* sa; |
102 | 0 | apr_status_t status = apr_socket_addr_get(&sa, APR_REMOTE, s); |
103 | |
|
104 | 0 | if (status == APR_SUCCESS) |
105 | 0 | { |
106 | 0 | _priv->port = sa->port; |
107 | 0 | LogString remotename; |
108 | 0 | LogString remoteip; |
109 | |
|
110 | 0 | if (sa->hostname != NULL) |
111 | 0 | { |
112 | 0 | Transcoder::decode(sa->hostname, remotename); |
113 | 0 | } |
114 | |
|
115 | 0 | char* buf = 0; |
116 | 0 | status = apr_sockaddr_ip_get(&buf, sa); |
117 | |
|
118 | 0 | if (status == APR_SUCCESS) |
119 | 0 | { |
120 | 0 | Transcoder::decode(buf, remoteip); |
121 | 0 | } |
122 | |
|
123 | 0 | _priv->address = std::make_shared<InetAddress>(remotename, remoteip); |
124 | 0 | } |
125 | 0 | } |
126 | | |
127 | | size_t APRSocket::write(ByteBuffer& buf) |
128 | 0 | { |
129 | 0 | if (_priv->socket == 0) |
130 | 0 | { |
131 | 0 | throw ClosedChannelException(); |
132 | 0 | } |
133 | | |
134 | 0 | size_t totalWritten = 0; |
135 | |
|
136 | 0 | while (buf.remaining() > 0) |
137 | 0 | { |
138 | 0 | apr_size_t written = buf.remaining(); |
139 | | |
140 | | // while writing to the socket, we need to ignore the SIGPIPE |
141 | | // signal. Otherwise, when the client has closed the connection, |
142 | | // the send() function would not return an error but call the |
143 | | // SIGPIPE handler. |
144 | 0 | #if APR_HAVE_SIGACTION |
145 | 0 | apr_sigfunc_t* old = apr_signal(SIGPIPE, SIG_IGN); |
146 | 0 | apr_status_t status = apr_socket_send(_priv->socket, buf.current(), &written); |
147 | 0 | apr_signal(SIGPIPE, old); |
148 | | #else |
149 | | apr_status_t status = apr_socket_send(_priv->socket, buf.current(), &written); |
150 | | #endif |
151 | |
|
152 | 0 | buf.increment_position(written); |
153 | 0 | totalWritten += written; |
154 | |
|
155 | 0 | if (status != APR_SUCCESS) |
156 | 0 | { |
157 | 0 | throw SocketException(status); |
158 | 0 | } |
159 | 0 | } |
160 | | |
161 | 0 | return totalWritten; |
162 | 0 | } |
163 | | |
164 | | void APRSocket::setNonBlocking(bool newValue) |
165 | 0 | { |
166 | 0 | auto status = apr_socket_opt_set(_priv->socket, APR_SO_NONBLOCK, newValue); |
167 | 0 | if (status != APR_SUCCESS) |
168 | 0 | throw SocketException(status); |
169 | 0 | } |
170 | | |
171 | | void APRSocket::close() |
172 | 0 | { |
173 | 0 | if (_priv->socket != 0) |
174 | 0 | { |
175 | 0 | apr_status_t status = apr_socket_close(_priv->socket); |
176 | |
|
177 | 0 | if (status != APR_SUCCESS) |
178 | 0 | { |
179 | 0 | throw SocketException(status); |
180 | 0 | } |
181 | | |
182 | 0 | _priv->socket = 0; |
183 | 0 | } |
184 | 0 | } |
185 | | |
186 | | apr_socket_t* APRSocket::getSocketPtr() const |
187 | 0 | { |
188 | 0 | return _priv->socket; |
189 | 0 | } |
190 | | |
191 | | } //namespace helpers |
192 | | } //namespace log4cxx |