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-2015 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 #if defined(__linux__) || defined(__APPLE__)
25 #include <unistd.h>
26 #include <arpa/inet.h>
27 #include <netinet/in.h>
28 #include <sys/socket.h>
29 
30 // Windows send() and recv() parameter types are different.
31 #define as_socket_data_t void
32 #define as_socket_size_t size_t
33 #define as_close(fd) (close(fd))
34 #endif
35 
36 #if defined(__APPLE__)
37 #define MSG_NOSIGNAL SO_NOSIGPIPE
38 #endif
39 
40 #if defined(CF_WINDOWS)
41 #include <WinSock2.h>
42 #include <Ws2tcpip.h>
43 
44 #define as_socket_data_t char
45 #define as_socket_size_t int
46 #define as_close(fd) (closesocket(fd))
47 
48 #define MSG_DONTWAIT 0
49 #define MSG_NOSIGNAL 0
50 
51 #define SHUT_RDWR SD_BOTH
52 #endif // CF_WINDOWS
53 
54 #ifdef __cplusplus
55 extern "C" {
56 #endif
57 
58 /**
59  * @private
60  * Create non-blocking socket.
61  */
63 as_socket_create_nb(as_error* err, int* fd);
64 
65 /**
66  * @private
67  * Connect to non-blocking socket.
68  */
70 as_socket_start_connect_nb(as_error* err, int fd, struct sockaddr_in *sa);
71 
72 /**
73  * @private
74  * Create non-blocking socket and connect.
75  */
77 as_socket_create_and_connect_nb(as_error* err, struct sockaddr_in *sa, int* fd);
78 
79 /**
80  * @private
81  * Peek for socket connection status. Close socket if not connected.
82  *
83  * @param fd Socket identifier.
84  * @param expect_empty Log message if socket contains data.
85  *
86  * @return if socket is connected.
87  */
88 bool
89 as_socket_validate(int fd, bool expect_empty);
90 
91 #if defined(__linux__) || defined(__APPLE__)
92 
93 /**
94  * @private
95  * Calculate future deadline given timeout.
96  */
97 static inline uint64_t
98 as_socket_deadline(uint32_t timeout_ms)
99 {
100  return (timeout_ms && timeout_ms <= INT32_MAX)? cf_getms() + timeout_ms : 0;
101 }
102 
103 /**
104  * @private
105  * Write socket data without timeouts.
106  */
107 as_status
108 as_socket_write_forever(as_error* err, int fd, uint8_t *buf, size_t buf_len);
109 
110 /**
111  * @private
112  * Write socket data with future deadline in milliseconds.
113  * Do not adjust for zero deadline.
114  */
115 as_status
116 as_socket_write_limit(as_error* err, int fd, uint8_t *buf, size_t buf_len, uint64_t deadline);
117 
118 /**
119  * @private
120  * Write socket data with future deadline in milliseconds.
121  * If deadline is zero, do not set deadline.
122  */
123 static inline as_status
124 as_socket_write_deadline(as_error* err, int fd, uint8_t *buf, size_t buf_len, uint64_t deadline)
125 {
126  if (deadline) {
127  return as_socket_write_limit(err, fd, buf, buf_len, deadline);
128  }
129  else {
130  return as_socket_write_forever(err, fd, buf, buf_len);
131  }
132 }
133 
134 /**
135  * @private
136  * Write socket data with timeout in milliseconds.
137  * If timeout is zero or > MAXINT, do not set timeout.
138  */
139 static inline as_status
140 as_socket_write_timeout(as_error* err, int fd, uint8_t *buf, size_t buf_len, uint32_t timeout_ms)
141 {
142  if (timeout_ms && timeout_ms <= INT32_MAX) {
143  return as_socket_write_limit(err, fd, buf, buf_len, cf_getms() + timeout_ms);
144  }
145  else {
146  return as_socket_write_forever(err, fd, buf, buf_len);
147  }
148 }
149 
150 /**
151  * @private
152  * Read socket data without timeouts.
153  */
154 as_status
155 as_socket_read_forever(as_error* err, int fd, uint8_t *buf, size_t buf_len);
156 
157 /**
158  * @private
159  * Read socket data with future deadline in milliseconds.
160  * Do not adjust for zero deadline.
161  */
162 as_status
163 as_socket_read_limit(as_error* err, int fd, uint8_t *buf, size_t buf_len, uint64_t deadline);
164 
165 /**
166  * @private
167  * Read socket data with future deadline in milliseconds.
168  * If deadline is zero, do not set deadline.
169  */
170 static inline as_status
171 as_socket_read_deadline(as_error* err, int fd, uint8_t *buf, size_t buf_len, uint64_t deadline)
172 {
173  if (deadline) {
174  return as_socket_read_limit(err, fd, buf, buf_len, deadline);
175  }
176  else {
177  return as_socket_read_forever(err, fd, buf, buf_len);
178  }
179 }
180 
181 /**
182  * @private
183  * Read socket data with timeout in milliseconds.
184  * If timeout is zero or > MAXINT, do not set timeout.
185  */
186 static inline as_status
187 as_socket_read_timeout(as_error* err, int fd, uint8_t *buf, size_t buf_len, uint32_t timeout_ms)
188 {
189  if (timeout_ms && timeout_ms <= INT32_MAX) {
190  return as_socket_read_limit(err, fd, buf, buf_len, cf_getms() + timeout_ms);
191  }
192  else {
193  return as_socket_read_forever(err, fd, buf, buf_len);
194  }
195 }
196 
197 /**
198  * @private
199  * Convert socket address to a string.
200  */
201 static inline void
202 as_socket_address_name(struct sockaddr_in* address, char* name)
203 {
204  inet_ntop(AF_INET, &(address->sin_addr), name, INET_ADDRSTRLEN);
205 }
206 
207 #endif
208 
209 #ifdef __cplusplus
210 } // end extern "C"
211 #endif