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-2016 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 /**
75  * This structure holds just an fd when we are not using TLS and additional
76  * OpenSSL context when we are using TLS.
77  */
78 typedef struct as_socket_s {
79  int fd;
80  int family;
81  uint64_t last_used;
83  const char* tls_name;
84  SSL* ssl;
85 } as_socket;
86 
87 /**
88  * @private
89  * Initialize an as_socket structure.
90  */
91 void
93 
94 /**
95  * @private
96  * Create non-blocking socket. Family should be AF_INET or AF_INET6.
97  * If socket create fails, return -errno.
98  */
99 int
100 as_socket_create_fd(int family);
101 
102 /**
103  * @private
104  * Create non-blocking socket.
105  * Family should be AF_INET or AF_INET6.
106  */
107 int
108 as_socket_create(as_socket* sock, int family, as_tls_context* ctx, const char* tls_name);
109 
110 /**
111  * @private
112  * Wrap existing fd in a socket.
113  * Family should be AF_INET or AF_INET6.
114  */
115 bool
116 as_socket_wrap(as_socket* sock, int family, int fd, as_tls_context* ctx, const char* tls_name);
117 
118 /**
119  * @private
120  * Connect to non-blocking socket.
121  */
122 bool
123 as_socket_start_connect(as_socket* sock, struct sockaddr* addr);
124 
125 /**
126  * @private
127  * Create non-blocking socket and connect.
128  */
129 as_status
130 as_socket_create_and_connect(as_socket* sock, as_error* err, struct sockaddr* addr, as_tls_context* ctx, const char* tls_name);
131 
132 /**
133  * @private
134  * Close and release resources associated with a as_socket.
135  */
136 void
138 
139 /**
140  * @private
141  * Peek for socket connection status using underlying fd.
142  * Needed to support libuv.
143  *
144  * @return 0 : socket is connected, but no data available.
145  * > 0 : byte size of data available.
146  * < 0 : socket is invalid.
147  */
148 int
149 as_socket_validate_fd(int fd);
150 
151 /**
152  * @private
153  * Peek for socket connection status.
154  *
155  * @return 0 : socket is connected, but no data available.
156  * > 0 : byte size of data available.
157  * < 0 : socket is invalid.
158  */
159 int
161 
162 #if defined(__linux__) || defined(__APPLE__)
163 
164 /**
165  * @private
166  * Calculate future deadline given timeout.
167  */
168 static inline uint64_t
169 as_socket_deadline(uint32_t timeout_ms)
170 {
171  return (timeout_ms && timeout_ms <= INT32_MAX)? cf_getms() + timeout_ms : 0;
172 }
173 
174 /**
175  * @private
176  * Write socket data without timeouts.
177  */
178 as_status
179 as_socket_write_forever(as_error* err, as_socket* sock, uint8_t *buf, size_t buf_len);
180 
181 /**
182  * @private
183  * Write socket data with future deadline in milliseconds.
184  * Do not adjust for zero deadline.
185  */
186 as_status
187 as_socket_write_limit(as_error* err, as_socket* sock, uint8_t *buf, size_t buf_len, uint64_t deadline);
188 
189 /**
190  * @private
191  * Write socket data with future deadline in milliseconds.
192  * If deadline is zero, do not set deadline.
193  */
194 static inline as_status
195 as_socket_write_deadline(as_error* err, as_socket* sock, uint8_t *buf, size_t buf_len, uint64_t deadline)
196 {
197  if (deadline) {
198  return as_socket_write_limit(err, sock, buf, buf_len, deadline);
199  }
200  else {
201  return as_socket_write_forever(err, sock, buf, buf_len);
202  }
203 }
204 
205 /**
206  * @private
207  * Write socket data with timeout in milliseconds.
208  * If timeout is zero or > MAXINT, do not set timeout.
209  */
210 static inline as_status
211 as_socket_write_timeout(as_error* err, as_socket* sock, uint8_t *buf, size_t buf_len, uint32_t timeout_ms)
212 {
213  if (timeout_ms && timeout_ms <= INT32_MAX) {
214  return as_socket_write_limit(err, sock, buf, buf_len, cf_getms() + timeout_ms);
215  }
216  else {
217  return as_socket_write_forever(err, sock, buf, buf_len);
218  }
219 }
220 
221 /**
222  * @private
223  * Read socket data without timeouts.
224  */
225 as_status
226 as_socket_read_forever(as_error* err, as_socket* sock, uint8_t *buf, size_t buf_len);
227 
228 /**
229  * @private
230  * Read socket data with future deadline in milliseconds.
231  * Do not adjust for zero deadline.
232  */
233 as_status
234 as_socket_read_limit(as_error* err, as_socket* sock, uint8_t *buf, size_t buf_len, uint64_t deadline);
235 
236 /**
237  * @private
238  * Read socket data with future deadline in milliseconds.
239  * If deadline is zero, do not set deadline.
240  */
241 static inline as_status
242 as_socket_read_deadline(as_error* err, as_socket* sock, uint8_t *buf, size_t buf_len, uint64_t deadline)
243 {
244  if (deadline) {
245  return as_socket_read_limit(err, sock, buf, buf_len, deadline);
246  }
247  else {
248  return as_socket_read_forever(err, sock, buf, buf_len);
249  }
250 }
251 
252 /**
253  * @private
254  * Read socket data with timeout in milliseconds.
255  * If timeout is zero or > MAXINT, do not set timeout.
256  */
257 static inline as_status
258 as_socket_read_timeout(as_error* err, as_socket* sock, uint8_t *buf, size_t buf_len, uint32_t timeout_ms)
259 {
260  if (timeout_ms && timeout_ms <= INT32_MAX) {
261  return as_socket_read_limit(err, sock, buf, buf_len, cf_getms() + timeout_ms);
262  }
263  else {
264  return as_socket_read_forever(err, sock, buf, buf_len);
265  }
266 }
267 
268 #endif
269 
270 #ifdef __cplusplus
271 } // end extern "C"
272 #endif