1 /** @file
2
3 A brief file description
4
5 @section license License
6
7 Licensed to the Apache Software Foundation (ASF) under one
8 or more contributor license agreements. See the NOTICE file
9 distributed with this work for additional information
10 regarding copyright ownership. The ASF licenses this file
11 to you under the Apache License, Version 2.0 (the
12 "License"); you may not use this file except in compliance
13 with the License. You may obtain a copy of the License at
14
15 http://www.apache.org/licenses/LICENSE-2.0
16
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22 */
23
24 /****************************************************************************
25
26
27 This file implements an I/O Processor for network I/O on Unix.
28
29
30 ****************************************************************************/
31
32 #pragma once
33
34 #include "tscore/ink_sock.h"
35 #include "I_NetVConnection.h"
36 #include "P_UnixNetState.h"
37 #include "P_Connection.h"
38 #include "P_NetAccept.h"
39 #include "NetEvent.h"
40
41 class UnixNetVConnection;
42 class NetHandler;
43 struct PollDescriptor;
44
45 inline void
reset()46 NetVCOptions::reset()
47 {
48 ip_proto = USE_TCP;
49 ip_family = AF_INET;
50 local_ip.invalidate();
51 local_port = 0;
52 addr_binding = ANY_ADDR;
53 f_blocking = false;
54 f_blocking_connect = false;
55 socks_support = NORMAL_SOCKS;
56 socks_version = SOCKS_DEFAULT_VERSION;
57 socket_recv_bufsize =
58 #if defined(RECV_BUF_SIZE)
59 RECV_BUF_SIZE;
60 #else
61 0;
62 #endif
63 socket_send_bufsize = 0;
64 sockopt_flags = 0;
65 packet_mark = 0;
66 packet_tos = 0;
67
68 etype = ET_NET;
69
70 sni_servername = nullptr;
71 ssl_servername = nullptr;
72 sni_hostname = nullptr;
73 ssl_client_cert_name = nullptr;
74 ssl_client_private_key_name = nullptr;
75 }
76
77 inline void
set_sock_param(int _recv_bufsize,int _send_bufsize,unsigned long _opt_flags,unsigned long _packet_mark,unsigned long _packet_tos)78 NetVCOptions::set_sock_param(int _recv_bufsize, int _send_bufsize, unsigned long _opt_flags, unsigned long _packet_mark,
79 unsigned long _packet_tos)
80 {
81 socket_recv_bufsize = _recv_bufsize;
82 socket_send_bufsize = _send_bufsize;
83 sockopt_flags = _opt_flags;
84 packet_mark = _packet_mark;
85 packet_tos = _packet_tos;
86 }
87
88 struct OOB_callback : public Continuation {
89 char *data;
90 int length;
91 Event *trigger;
92 UnixNetVConnection *server_vc;
93 Continuation *server_cont;
94 int retry_OOB_send(int, Event *);
95
OOB_callbackOOB_callback96 OOB_callback(Ptr<ProxyMutex> &m, NetVConnection *vc, Continuation *cont, char *buf, int len)
97 : Continuation(m), data(buf), length(len), trigger(nullptr)
98 {
99 server_vc = (UnixNetVConnection *)vc;
100 server_cont = cont;
101 SET_HANDLER(&OOB_callback::retry_OOB_send);
102 }
103 };
104
105 enum tcp_congestion_control_t { CLIENT_SIDE, SERVER_SIDE };
106
107 class UnixNetVConnection : public NetVConnection, public NetEvent
108 {
109 public:
110 VIO *do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf) override;
111 VIO *do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner = false) override;
112
113 Continuation *read_vio_cont() override;
114 Continuation *write_vio_cont() override;
115
116 bool get_data(int id, void *data) override;
117
118 Action *send_OOB(Continuation *cont, char *buf, int len) override;
119 void cancel_OOB() override;
120
121 const char *
get_server_name()122 get_server_name() const override
123 {
124 return nullptr;
125 }
126
127 void do_io_close(int lerrno = -1) override;
128 void do_io_shutdown(ShutdownHowTo_t howto) override;
129
130 ////////////////////////////////////////////////////////////
131 // Set the timeouts associated with this connection. //
132 // active_timeout is for the total elapsed time of //
133 // the connection. //
134 // inactivity_timeout is the elapsed time from the time //
135 // a read or a write was scheduled during which the //
136 // connection was unable to sink/provide data. //
137 // calling these functions repeatedly resets the timeout. //
138 // These functions are NOT THREAD-SAFE, and may only be //
139 // called when handing an event from this NetVConnection,//
140 // or the NetVConnection creation callback. //
141 ////////////////////////////////////////////////////////////
142 virtual void set_active_timeout(ink_hrtime timeout_in) override;
143 virtual void set_inactivity_timeout(ink_hrtime timeout_in) override;
144 virtual void set_default_inactivity_timeout(ink_hrtime timeout_in) override;
145 virtual bool is_default_inactivity_timeout() override;
146 virtual void cancel_active_timeout() override;
147 virtual void cancel_inactivity_timeout() override;
148 void set_action(Continuation *c) override;
149 const Action *get_action() const;
150 virtual void add_to_keep_alive_queue() override;
151 virtual void remove_from_keep_alive_queue() override;
152 virtual bool add_to_active_queue() override;
153 virtual void remove_from_active_queue();
154
155 // The public interface is VIO::reenable()
156 void reenable(VIO *vio) override;
157 void reenable_re(VIO *vio) override;
158
159 SOCKET get_socket() override;
160
161 ~UnixNetVConnection() override;
162
163 /////////////////////////////////////////////////////////////////
164 // instances of UnixNetVConnection should be allocated //
165 // only from the free list using UnixNetVConnection::alloc(). //
166 // The constructor is public just to avoid compile errors. //
167 /////////////////////////////////////////////////////////////////
168 UnixNetVConnection();
169
170 int populate_protocol(std::string_view *results, int n) const override;
171 const char *protocol_contains(std::string_view tag) const override;
172
173 // noncopyable
174 UnixNetVConnection(const NetVConnection &) = delete;
175 UnixNetVConnection &operator=(const NetVConnection &) = delete;
176
177 /////////////////////////
178 // UNIX implementation //
179 /////////////////////////
180 void set_enabled(VIO *vio);
181
182 void get_local_sa();
183
184 // these are not part of the pure virtual interface. They were
185 // added to reduce the amount of duplicate code in classes inherited
186 // from NetVConnection (SSL).
187 virtual int
sslStartHandShake(int event,int & err)188 sslStartHandShake(int event, int &err)
189 {
190 (void)event;
191 (void)err;
192 return EVENT_ERROR;
193 }
194
195 virtual bool
getSSLHandShakeComplete()196 getSSLHandShakeComplete() const
197 {
198 return (true);
199 }
200
201 virtual bool
trackFirstHandshake()202 trackFirstHandshake()
203 {
204 return false;
205 }
206
207 // NetEvent
208 virtual void net_read_io(NetHandler *nh, EThread *lthread) override;
209 virtual void net_write_io(NetHandler *nh, EThread *lthread) override;
210 virtual void free(EThread *t) override;
211 virtual int
close()212 close() override
213 {
214 return this->con.close();
215 }
216 virtual int
get_fd()217 get_fd() override
218 {
219 return this->con.fd;
220 }
221
222 virtual EThread *
get_thread()223 get_thread() override
224 {
225 return this->thread;
226 }
227
228 virtual int
229 callback(int event = CONTINUATION_EVENT_NONE, void *data = nullptr) override
230 {
231 return this->handleEvent(event, data);
232 }
233
234 virtual Ptr<ProxyMutex> &
get_mutex()235 get_mutex() override
236 {
237 return this->mutex;
238 }
239
240 virtual ContFlags &
get_control_flags()241 get_control_flags() override
242 {
243 return this->control_flags;
244 }
245
246 virtual int64_t load_buffer_and_write(int64_t towrite, MIOBufferAccessor &buf, int64_t &total_written, int &needs);
247 void readDisable(NetHandler *nh);
248 void readSignalError(NetHandler *nh, int err);
249 int readSignalDone(int event, NetHandler *nh);
250 int readSignalAndUpdate(int event);
251 void readReschedule(NetHandler *nh);
252 void writeReschedule(NetHandler *nh);
253 void netActivity(EThread *lthread);
254 /**
255 * If the current object's thread does not match the t argument, create a new
256 * NetVC in the thread t context based on the socket and ssl information in the
257 * current NetVC and mark the current NetVC to be closed.
258 */
259 UnixNetVConnection *migrateToCurrentThread(Continuation *c, EThread *t);
260
261 Action action_;
262
263 unsigned int id = 0;
264
265 Connection con;
266 int recursion = 0;
267 OOB_callback *oob_ptr = nullptr;
268 bool from_accept_thread = false;
269 NetAccept *accept_object = nullptr;
270
271 int startEvent(int event, Event *e);
272 int acceptEvent(int event, Event *e);
273 int mainEvent(int event, Event *e);
274 virtual int connectUp(EThread *t, int fd);
275 /**
276 * Populate the current object based on the socket information in in the
277 * con parameter.
278 * This is logic is invoked when the NetVC object is created in a new thread context
279 */
280 virtual int populate(Connection &con, Continuation *c, void *arg);
281 virtual void clear();
282
283 ink_hrtime get_inactivity_timeout() override;
284 ink_hrtime get_active_timeout() override;
285
286 virtual void set_local_addr() override;
287 void set_mptcp_state() override;
288 virtual void set_remote_addr() override;
289 void set_remote_addr(const sockaddr *) override;
290 int set_tcp_congestion_control(int side) override;
291 void apply_options() override;
292
293 friend void write_to_net_io(NetHandler *, UnixNetVConnection *, EThread *);
294
295 private:
296 virtual void *_prepareForMigration();
297 virtual NetProcessor *_getNetProcessor();
298 };
299
300 extern ClassAllocator<UnixNetVConnection> netVCAllocator;
301
302 typedef int (UnixNetVConnection::*NetVConnHandler)(int, void *);
303
304 inline void
set_remote_addr()305 UnixNetVConnection::set_remote_addr()
306 {
307 ats_ip_copy(&remote_addr, &con.addr);
308 this->control_flags.set_flag(ContFlags::DEBUG_OVERRIDE, diags->test_override_ip(remote_addr));
309 }
310
311 inline void
set_remote_addr(const sockaddr * new_sa)312 UnixNetVConnection::set_remote_addr(const sockaddr *new_sa)
313 {
314 ats_ip_copy(&remote_addr, new_sa);
315 this->control_flags.set_flag(ContFlags::DEBUG_OVERRIDE, diags->test_override_ip(remote_addr));
316 }
317
318 inline void
set_local_addr()319 UnixNetVConnection::set_local_addr()
320 {
321 int local_sa_size = sizeof(local_addr);
322 // This call will fail if fd is closed already. That is ok, because the
323 // `local_addr` is checked within get_local_addr() and the `got_local_addr`
324 // is set only with a valid `local_addr`.
325 ATS_UNUSED_RETURN(safe_getsockname(con.fd, &local_addr.sa, &local_sa_size));
326 }
327
328 // Update the internal VC state variable for MPTCP
329 inline void
set_mptcp_state()330 UnixNetVConnection::set_mptcp_state()
331 {
332 int mptcp_enabled = -1;
333 int mptcp_enabled_size = sizeof(mptcp_enabled);
334
335 if (0 == safe_getsockopt(con.fd, IPPROTO_TCP, MPTCP_ENABLED, (char *)&mptcp_enabled, &mptcp_enabled_size)) {
336 Debug("socket_mptcp", "MPTCP socket state: %d", mptcp_enabled);
337 mptcp_state = mptcp_enabled > 0 ? true : false;
338 } else {
339 Debug("socket_mptcp", "MPTCP failed getsockopt(): %s", strerror(errno));
340 }
341 }
342
343 inline ink_hrtime
get_active_timeout()344 UnixNetVConnection::get_active_timeout()
345 {
346 return active_timeout_in;
347 }
348
349 inline ink_hrtime
get_inactivity_timeout()350 UnixNetVConnection::get_inactivity_timeout()
351 {
352 return inactivity_timeout_in;
353 }
354
355 inline void
set_active_timeout(ink_hrtime timeout_in)356 UnixNetVConnection::set_active_timeout(ink_hrtime timeout_in)
357 {
358 Debug("socket", "Set active timeout=%" PRId64 ", NetVC=%p", timeout_in, this);
359 active_timeout_in = timeout_in;
360 next_activity_timeout_at = (active_timeout_in > 0) ? Thread::get_hrtime() + timeout_in : 0;
361 }
362
363 inline void
cancel_inactivity_timeout()364 UnixNetVConnection::cancel_inactivity_timeout()
365 {
366 Debug("socket", "Cancel inactive timeout for NetVC=%p", this);
367 inactivity_timeout_in = 0;
368 next_inactivity_timeout_at = 0;
369 }
370
371 inline void
cancel_active_timeout()372 UnixNetVConnection::cancel_active_timeout()
373 {
374 Debug("socket", "Cancel active timeout for NetVC=%p", this);
375 active_timeout_in = 0;
376 next_activity_timeout_at = 0;
377 }
378
~UnixNetVConnection()379 inline UnixNetVConnection::~UnixNetVConnection() {}
380
381 inline SOCKET
get_socket()382 UnixNetVConnection::get_socket()
383 {
384 return con.fd;
385 }
386
387 inline void
set_action(Continuation * c)388 UnixNetVConnection::set_action(Continuation *c)
389 {
390 action_ = c;
391 }
392
393 inline const Action *
get_action()394 UnixNetVConnection::get_action() const
395 {
396 return &action_;
397 }
398
399 // declarations for local use (within the net module)
400
401 void write_to_net(NetHandler *nh, UnixNetVConnection *vc, EThread *thread);
402 void write_to_net_io(NetHandler *nh, UnixNetVConnection *vc, EThread *thread);
403 void net_activity(UnixNetVConnection *vc, EThread *thread);
404