All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
as_socket.h
Go to the documentation of this file.
1 /*
2  * Copyright 2008-2017 Aerospike, Inc.
3  *
4  * Portions may be licensed to Aerospike, Inc. under one or more contributor
5  * license agreements.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8  * use this file except in compliance with the License. You may obtain a copy of
9  * the License at 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, WITHOUT
13  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14  * License for the specific language governing permissions and limitations under
15  * the License.
16  */
17 #pragma once
18 
19 #include <aerospike/as_error.h>
20 #include <citrusleaf/cf_clock.h>
21 #include <stddef.h>
22 #include <stdint.h>
23 
24 #include <openssl/ssl.h>
25 
26 #include <aerospike/as_config.h>
27 
28 #if defined(__linux__) || defined(__APPLE__)
29 #include <unistd.h>
30 #include <arpa/inet.h>
31 #include <netinet/in.h>
32 #include <sys/socket.h>
33 
34 // Windows send() and recv() parameter types are different.
35 #define as_socket_data_t void
36 #define as_socket_size_t size_t
37 #define as_close(fd) (close(fd))
38 #endif
39 
40 #if defined(__APPLE__)
41 #define SOL_TCP IPPROTO_TCP
42 #define MSG_NOSIGNAL 0
43 #endif
44 
45 #if defined(CF_WINDOWS)
46 #include <WinSock2.h>
47 #include <Ws2tcpip.h>
48 
49 #define as_socket_data_t char
50 #define as_socket_size_t int
51 #define as_close(fd) (closesocket(fd))
52 
53 #define MSG_DONTWAIT 0
54 #define MSG_NOSIGNAL 0
55 
56 #define SHUT_RDWR SD_BOTH
57 #endif // CF_WINDOWS
58 
59 #ifdef __cplusplus
60 extern "C" {
61 #endif
62 
63 /**
64  * This structure holds TLS context which can be shared (read-only)
65  * by all the connections to a specific cluster.
66  */
67 typedef struct as_tls_context_s {
68  SSL_CTX* ssl_ctx;
70  uint64_t max_socket_idle;
73 
74 struct as_queue_lock_s;
75 
76 /**
77  * Socket fields for both regular and TLS sockets.
78  */
79 typedef struct as_socket_s {
80  int fd;
81  int family;
82  union {
83  struct as_queue_lock_s* queue; // Used when sync socket is active.
84  uint64_t last_used; // Used when socket in pool.
85  };
87  const char* tls_name;
88  SSL* ssl;
89 } as_socket;
90 
91 /**
92  * @private
93  * Initialize an as_socket structure.
94  */
95 void
97 
98 /**
99  * @private
100  * Create non-blocking socket. Family should be AF_INET or AF_INET6.
101  * If socket create fails, return -errno.
102  */
103 int
104 as_socket_create_fd(int family);
105 
106 /**
107  * @private
108  * Create non-blocking socket.
109  * Family should be AF_INET or AF_INET6.
110  */
111 int
112 as_socket_create(as_socket* sock, int family, as_tls_context* ctx, const char* tls_name);
113 
114 /**
115  * @private
116  * Wrap existing fd in a socket.
117  * Family should be AF_INET or AF_INET6.
118  */
119 bool
120 as_socket_wrap(as_socket* sock, int family, int fd, as_tls_context* ctx, const char* tls_name);
121 
122 /**
123  * @private
124  * Connect to non-blocking socket.
125  */
126 bool
127 as_socket_start_connect(as_socket* sock, struct sockaddr* addr);
128 
129 /**
130  * @private
131  * Create non-blocking socket and connect.
132  */
133 as_status
134 as_socket_create_and_connect(as_socket* sock, as_error* err, struct sockaddr* addr, as_tls_context* ctx, const char* tls_name);
135 
136 /**
137  * @private
138  * Close and release resources associated with a as_socket.
139  */
140 void
142 
143 /**
144  * @private
145  * Peek for socket connection status using underlying fd.
146  * Needed to support libuv.
147  *
148  * @return 0 : socket is connected, but no data available.
149  * > 0 : byte size of data available.
150  * < 0 : socket is invalid.
151  */
152 int
153 as_socket_validate_fd(int fd);
154 
155 /**
156  * @private
157  * Peek for socket connection status.
158  *
159  * @return 0 : socket is connected, but no data available.
160  * > 0 : byte size of data available.
161  * < 0 : socket is invalid.
162  */
163 int
165 
166 #if defined(__linux__) || defined(__APPLE__)
167 
168 /**
169  * @private
170  * Calculate future deadline given timeout.
171  */
172 static inline uint64_t
173 as_socket_deadline(uint32_t timeout_ms)
174 {
175  return (timeout_ms && timeout_ms <= INT32_MAX)? cf_getms() + timeout_ms : 0;
176 }
177 
178 /**
179  * @private
180  * Write socket data without timeouts.
181  */
182 as_status
183 as_socket_write_forever(as_error* err, as_socket* sock, uint8_t *buf, size_t buf_len);
184 
185 /**
186  * @private
187  * Write socket data with future deadline in milliseconds.
188  * Do not adjust for zero deadline.
189  */
190 as_status
191 as_socket_write_limit(as_error* err, as_socket* sock, uint8_t *buf, size_t buf_len, uint64_t deadline);
192 
193 /**
194  * @private
195  * Write socket data with future deadline in milliseconds.
196  * If deadline is zero, do not set deadline.
197  */
198 static inline as_status
199 as_socket_write_deadline(as_error* err, as_socket* sock, uint8_t *buf, size_t buf_len, uint64_t deadline)
200 {
201  if (deadline) {
202  return as_socket_write_limit(err, sock, buf, buf_len, deadline);
203  }
204  else {
205  return as_socket_write_forever(err, sock, buf, buf_len);
206  }
207 }
208 
209 /**
210  * @private
211  * Write socket data with timeout in milliseconds.
212  * If timeout is zero or > MAXINT, do not set timeout.
213  */
214 static inline as_status
215 as_socket_write_timeout(as_error* err, as_socket* sock, uint8_t *buf, size_t buf_len, uint32_t timeout_ms)
216 {
217  if (timeout_ms && timeout_ms <= INT32_MAX) {
218  return as_socket_write_limit(err, sock, buf, buf_len, cf_getms() + timeout_ms);
219  }
220  else {
221  return as_socket_write_forever(err, sock, buf, buf_len);
222  }
223 }
224 
225 /**
226  * @private
227  * Read socket data without timeouts.
228  */
229 as_status
230 as_socket_read_forever(as_error* err, as_socket* sock, uint8_t *buf, size_t buf_len);
231 
232 /**
233  * @private
234  * Read socket data with future deadline in milliseconds.
235  * Do not adjust for zero deadline.
236  */
237 as_status
238 as_socket_read_limit(as_error* err, as_socket* sock, uint8_t *buf, size_t buf_len, uint64_t deadline);
239 
240 /**
241  * @private
242  * Read socket data with future deadline in milliseconds.
243  * If deadline is zero, do not set deadline.
244  */
245 static inline as_status
246 as_socket_read_deadline(as_error* err, as_socket* sock, uint8_t *buf, size_t buf_len, uint64_t deadline)
247 {
248  if (deadline) {
249  return as_socket_read_limit(err, sock, buf, buf_len, deadline);
250  }
251  else {
252  return as_socket_read_forever(err, sock, buf, buf_len);
253  }
254 }
255 
256 /**
257  * @private
258  * Read socket data with timeout in milliseconds.
259  * If timeout is zero or > MAXINT, do not set timeout.
260  */
261 static inline as_status
262 as_socket_read_timeout(as_error* err, as_socket* sock, uint8_t *buf, size_t buf_len, uint32_t timeout_ms)
263 {
264  if (timeout_ms && timeout_ms <= INT32_MAX) {
265  return as_socket_read_limit(err, sock, buf, buf_len, cf_getms() + timeout_ms);
266  }
267  else {
268  return as_socket_read_forever(err, sock, buf, buf_len);
269  }
270 }
271 
272 #endif
273 
274 #ifdef __cplusplus
275 } // end extern "C"
276 #endif