1 /**
2 * Copyright (C) 2008 Happy Fish / YuQing
3 *
4 * FastDFS may be copied only under the terms of the GNU General
5 * Public License V3, which may be found in the FastDFS source kit.
6 * Please visit the FastDFS Home Page http://www.fastken.com/ for more detail.
7 **/
8
9 //socketopt.h
10
11 #ifndef _SOCKETOPT_H_
12 #define _SOCKETOPT_H_
13
14 #include <net/if.h>
15 #include <string.h>
16 #include <fcntl.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <sys/socket.h>
20 #include "common_define.h"
21
22 #define FAST_WRITE_BUFF_SIZE (256 * 1024)
23
24 typedef struct fast_if_config {
25 char name[IF_NAMESIZE]; //if name
26 char mac[32];
27 char ipv4[IP_ADDRESS_SIZE];
28 char ipv6[48];
29 } FastIFConfig;
30
31 typedef struct ip_addr_s {
32 char ip_addr[INET6_ADDRSTRLEN];
33 int socket_domain;
34 } ip_addr_t;
35
36 typedef struct sockaddr_convert_s {
37 socklen_t len;
38 union {
39 struct sockaddr addr;
40 struct sockaddr_in addr4;
41 struct sockaddr_in6 addr6;
42 } sa;
43 } sockaddr_convert_t;
44
45 #ifdef SO_NOSIGPIPE
46 #define SET_SOCKOPT_NOSIGPIPE(sock) \
47 do { \
48 int set = 1; \
49 setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof(int)); \
50 } while (0)
51 #else
52 #define SET_SOCKOPT_NOSIGPIPE(sock)
53 #endif
54
55 #ifdef __cplusplus
56 extern "C" {
57 #endif
58
59 typedef int (*getnamefunc)(int socket, struct sockaddr *address, \
60 socklen_t *address_len);
61
62 typedef int (*tcpsenddatafunc)(int sock, void* data, const int size, \
63 const int timeout);
64
65 typedef int (*tcprecvdata_exfunc)(int sock, void *data, const int size, \
66 const int timeout, int *count);
67
68 #define getSockIpaddr(sock, buff, bufferSize) \
69 getIpaddr(getsockname, sock, buff, bufferSize)
70
71 #define getPeerIpaddr(sock, buff, bufferSize) \
72 getIpaddr(getpeername, sock, buff, bufferSize)
73
74 /** get a line from socket
75 * parameters:
76 * sock: the socket
77 * s: the buffer
78 * size: buffer size (max bytes can receive)
79 * timeout: read timeout
80 * return: error no, 0 success, != 0 fail
81 */
82 int tcpgets(int sock, char *s, const int size, const int timeout);
83
84 /** recv data (block mode)
85 * parameters:
86 * sock: the socket
87 * data: the buffer
88 * size: buffer size (max bytes can receive)
89 * timeout: read timeout
90 * count: store the bytes recveived
91 * return: error no, 0 success, != 0 fail
92 */
93 int tcprecvdata_ex(int sock, void *data, const int size, \
94 const int timeout, int *count);
95
96 /** recv data (non-block mode)
97 * parameters:
98 * sock: the socket
99 * data: the buffer
100 * size: buffer size (max bytes can receive)
101 * timeout: read timeout in seconds
102 * count: store the bytes recveived
103 * return: error no, 0 success, != 0 fail
104 */
105 int tcprecvdata_nb_ex(int sock, void *data, const int size, \
106 const int timeout, int *count);
107
108 /** recv data (non-block mode) in ms
109 * parameters:
110 * sock: the socket
111 * data: the buffer
112 * size: buffer size (max bytes can receive)
113 * timeout: read timeout in milliseconds
114 * count: store the bytes recveived
115 * return: error no, 0 success, != 0 fail
116 */
117 int tcprecvdata_nb_ms(int sock, void *data, const int size, \
118 const int timeout_ms, int *count);
119
120 /** send data (block mode)
121 * parameters:
122 * sock: the socket
123 * data: the buffer to send
124 * size: buffer size
125 * timeout: write timeout
126 * return: error no, 0 success, != 0 fail
127 */
128 int tcpsenddata(int sock, void* data, const int size, const int timeout);
129
130 /** send data (non-block mode)
131 * parameters:
132 * sock: the socket
133 * data: the buffer to send
134 * size: buffer size
135 * timeout: write timeout
136 * return: error no, 0 success, != 0 fail
137 */
138 int tcpsenddata_nb(int sock, void* data, const int size, const int timeout);
139
140 /** connect to server by block mode
141 * parameters:
142 * sock: the socket
143 * server_ip: ip address of the server
144 * server_port: port of the server
145 * return: error no, 0 success, != 0 fail
146 */
147 int connectserverbyip(int sock, const char *server_ip, const short server_port);
148
149 /** connect to server by non-block mode
150 * parameters:
151 * sock: the socket
152 * server_ip: ip address of the server
153 * server_port: port of the server
154 * timeout: connect timeout in seconds
155 * auto_detect: if detect and adjust the block mode of the socket
156 * return: error no, 0 success, != 0 fail
157 */
158 int connectserverbyip_nb_ex(int sock, const char *server_ip, \
159 const short server_port, const int timeout, \
160 const bool auto_detect);
161
162 /** connect to server by non-block mode, the socket must be set to non-block
163 * parameters:
164 * sock: the socket, must be set to non-block
165 * server_ip: ip address of the server
166 * server_port: port of the server
167 * timeout: connect timeout in seconds
168 * return: error no, 0 success, != 0 fail
169 */
170 #define connectserverbyip_nb(sock, server_ip, server_port, timeout) \
171 connectserverbyip_nb_ex(sock, server_ip, server_port, timeout, false)
172
173 /** connect to server by non-block mode, auto detect socket block mode
174 * parameters:
175 * sock: the socket, can be block mode
176 * server_ip: ip address of the server
177 * server_port: port of the server
178 * timeout: connect timeout in seconds
179 * return: error no, 0 success, != 0 fail
180 */
181 #define connectserverbyip_nb_auto(sock, server_ip, server_port, timeout) \
182 connectserverbyip_nb_ex(sock, server_ip, server_port, timeout, true)
183
184 /** accept client connect request
185 * parameters:
186 * sock: the server socket
187 * timeout: read timeout
188 * err_no: store the error no, 0 for success
189 * return: client socket, < 0 for error
190 */
191 int nbaccept(int sock, const int timeout, int *err_no);
192
193 /** set socket options
194 * parameters:
195 * sock: the socket
196 * timeout: read & write timeout
197 * return: error no, 0 success, != 0 fail
198 */
199 int tcpsetserveropt(int fd, const int timeout);
200
201 /** set socket non-block options
202 * parameters:
203 * sock: the socket
204 * return: error no, 0 success, != 0 fail
205 */
206 int tcpsetnonblockopt(int fd);
207
208 /** set socket no delay on send data
209 * parameters:
210 * sock: the socket
211 * timeout: read & write timeout
212 * return: error no, 0 success, != 0 fail
213 */
214 int tcpsetnodelay(int fd, const int timeout);
215
216 /** set socket keep-alive
217 * parameters:
218 * sock: the socket
219 * idleSeconds: max idle time (seconds)
220 * return: error no, 0 success, != 0 fail
221 */
222 int tcpsetkeepalive(int fd, const int idleSeconds);
223
224 /** print keep-alive related parameters
225 * parameters:
226 * sock: the socket
227 * return: error no, 0 success, != 0 fail
228 */
229 int tcpprintkeepalive(int fd);
230
231 /** get ip address
232 * parameters:
233 * getname: the function name, should be getpeername or getsockname
234 * sock: the socket
235 * buff: buffer to store the ip address
236 * bufferSize: the buffer size (max bytes)
237 * return: in_addr_t, INADDR_NONE for fail
238 */
239 in_addr_t getIpaddr(getnamefunc getname, int sock, \
240 char *buff, const int bufferSize);
241
242 /** get hostname by it's ip address
243 * parameters:
244 * szIpAddr: the ip address
245 * buff: buffer to store the hostname
246 * bufferSize: the buffer size (max bytes)
247 * return: hostname, empty buffer for error
248 */
249 char *getHostnameByIp(const char *szIpAddr, char *buff, const int bufferSize);
250
251 /** get by IPv4 address by it's hostname
252 * parameters:
253 * name: the hostname
254 * buff: buffer to store the ip address
255 * bufferSize: the buffer size (max bytes)
256 * return: in_addr_t, INADDR_NONE for fail
257 */
258 in_addr_t getIpaddrByName(const char *name, char *buff, const int bufferSize);
259
260 /** get by ip addresses by it's hostname
261 * parameters:
262 * name: the hostname
263 * ip_addr_arr: ip address array to store the ip address
264 * ip_addr_arr_size: ip address array size
265 * return: ip address count
266 */
267 int getIpaddrsByName(const char *name, ip_addr_t *ip_addr_arr, const int ip_addr_arr_size);
268
269 /** bind wrapper for IPv4
270 * parameters:
271 * sock: the socket
272 * bind_ipaddr: the ip address to bind
273 * port: the port to bind
274 * return: error no, 0 success, != 0 fail
275 */
276 int socketBind(int sock, const char *bind_ipaddr, const int port);
277
278 /** bind wrapper for IPv6
279 * parameters:
280 * sock: the socket
281 * bind_ipaddr: the ip address to bind
282 * port: the port to bind
283 * return: error no, 0 success, != 0 fail
284 */
285 int socketBindIPv6(int sock, const char *bind_ipaddr, const int port);
286
287 /** bind wrapper for IPv4 or IPv6
288 * parameters:
289 * af: family, AF_INET or AF_INET6
290 * sock: the socket
291 * bind_ipaddr: the ip address to bind
292 * port: the port to bind
293 * return: error no, 0 success, != 0 fail
294 */
295 int socketBind2(int af, int sock, const char *bind_ipaddr, const int port);
296
297 /** start a socket server for IPv4 (socket, bind and listen)
298 * parameters:
299 * sock: the socket
300 * bind_ipaddr: the ip address to bind
301 * port: the port to bind
302 * err_no: store the error no
303 * return: >= 0 server socket, < 0 fail
304 */
305 int socketServer(const char *bind_ipaddr, const int port, int *err_no);
306
307 /** start a socket server for IPv6 (socket, bind and listen)
308 * parameters:
309 * sock: the socket
310 * bind_ipaddr: the ip address to bind
311 * port: the port to bind
312 * err_no: store the error no
313 * return: >= 0 server socket, < 0 fail
314 */
315 int socketServerIPv6(const char *bind_ipaddr, const int port, int *err_no);
316
317 /** start a socket server for IPv4 or IPv6 (socket, bind and listen)
318 * parameters:
319 * af: family, AF_INET or AF_INET6
320 * sock: the socket
321 * bind_ipaddr: the ip address to bind
322 * port: the port to bind
323 * err_no: store the error no
324 * return: >= 0 server socket, < 0 fail
325 */
326 int socketServer2(int af, const char *bind_ipaddr, const int port, int *err_no);
327
328 /** create socket (NOT connect to server yet)
329 * parameters:
330 * af: family, AF_UNSPEC (auto dectect), AF_INET or AF_INET6
331 * server_ip: ip address of the server to detect family when af == AF_UNSPEC
332 * timeout: connect timeout in seconds
333 * flags: socket flags such as O_NONBLOCK for non-block socket
334 * bind_ipaddr: the ip address to bind, NULL or empty for bind ANY
335 * err_no: store the error no
336 * return: >= 0 server socket, < 0 fail
337 */
338 int socketCreateEx2(int af, const char *server_ip,
339 const int timeout, const int flags,
340 const char *bind_ipaddr, int *err_no);
341
342 /** create socket (NOT connect to server yet)
343 * parameters:
344 * server_ip: ip address of the server to detect family
345 * timeout: connect timeout in seconds
346 * flags: socket flags such as O_NONBLOCK for non-block socket
347 * bind_ipaddr: the ip address to bind, NULL or empty for bind ANY
348 * err_no: store the error no
349 * return: >= 0 server socket, < 0 fail
350 */
socketCreateExAuto(const char * server_ip,const int timeout,const int flags,const char * bind_ipaddr,int * err_no)351 static inline int socketCreateExAuto(const char *server_ip,
352 const int timeout, const int flags,
353 const char *bind_ipaddr, int *err_no)
354 {
355 return socketCreateEx2(AF_UNSPEC, server_ip, timeout, flags,
356 bind_ipaddr, err_no);
357 }
358
359 /** connect to server
360 * parameters:
361 * af: family, AF_UNSPEC (auto dectect), AF_INET or AF_INET6
362 * server_ip: ip address of the server
363 * server_port: port of the server
364 * timeout: connect timeout in seconds
365 * flags: socket flags such as O_NONBLOCK for non-block socket
366 * bind_ipaddr: the ip address to bind, NULL or empty for bind ANY
367 * err_no: store the error no
368 * return: >= 0 server socket, < 0 fail
369 */
370 int socketClientEx2(int af, const char *server_ip,
371 const short server_port, const int timeout,
372 const int flags, const char *bind_ipaddr, int *err_no);
373
374 /** connect to server
375 * parameters:
376 * server_ip: ip address of the server
377 * server_port: port of the server
378 * timeout: connect timeout in seconds
379 * flags: socket flags such as O_NONBLOCK for non-block socket
380 * bind_ipaddr: the ip address to bind, NULL or empty for bind ANY
381 * err_no: store the error no
382 * return: >= 0 server socket, < 0 fail
383 */
socketClientExAuto(const char * server_ip,const short server_port,const int timeout,const int flags,const char * bind_ipaddr,int * err_no)384 static inline int socketClientExAuto(const char *server_ip,
385 const short server_port, const int timeout,
386 const int flags, const char *bind_ipaddr, int *err_no)
387 {
388 return socketClientEx2(AF_UNSPEC, server_ip, server_port,
389 timeout, flags, bind_ipaddr, err_no);
390 }
391
392 /** connect to server
393 * parameters:
394 * server_ip: ip address of the server
395 * server_port: port of the server
396 * timeout: connect timeout in seconds
397 * flags: socket flags such as O_NONBLOCK for non-block socket
398 * bind_ipaddr: the ip address to bind, NULL or empty for bind ANY
399 * err_no: store the error no
400 * return: >= 0 server socket, < 0 fail
401 */
socketClientAuto(const char * server_ip,const short server_port,const int timeout,const int flags,int * err_no)402 static inline int socketClientAuto(const char *server_ip,
403 const short server_port, const int timeout,
404 const int flags, int *err_no)
405 {
406 return socketClientEx2(AF_UNSPEC, server_ip, server_port,
407 timeout, flags, NULL, err_no);
408 }
409
410 /** connect to server
411 * parameters:
412 * af: family, AF_UNSPEC (auto dectect), AF_INET or AF_INET6
413 * server_ip: ip address of the server
414 * server_port: port of the server
415 * timeout: connect timeout in seconds
416 * flags: socket flags such as O_NONBLOCK for non-block socket
417 * err_no: store the error no
418 * return: >= 0 server socket, < 0 fail
419 */
socketClient2(int af,const char * server_ip,const short server_port,const int timeout,const int flags,int * err_no)420 static inline int socketClient2(int af, const char *server_ip,
421 const short server_port, const int timeout,
422 const int flags, int *err_no)
423 {
424 return socketClientEx2(af, server_ip, server_port,
425 timeout, flags, NULL, err_no);
426 }
427
428 /** connect to server with IPv4 socket
429 * parameters:
430 * server_ip: ip address of the server
431 * server_port: port of the server
432 * timeout: connect timeout in seconds
433 * flags: socket flags such as O_NONBLOCK for non-block socket
434 * err_no: store the error no
435 * return: >= 0 server socket, < 0 fail
436 */
socketClient(const char * server_ip,const short server_port,const int timeout,const int flags,int * err_no)437 static inline int socketClient(const char *server_ip,
438 const short server_port, const int timeout,
439 const int flags, int *err_no)
440 {
441 return socketClient2(AF_INET, server_ip, server_port,
442 timeout, flags, err_no);
443 }
444
445 /** connect to server with IPv6 socket
446 * parameters:
447 * server_ip: ip address of the server
448 * server_port: port of the server
449 * timeout: connect timeout in seconds
450 * flags: socket flags such as O_NONBLOCK for non-block socket
451 * err_no: store the error no
452 * return: >= 0 server socket, < 0 fail
453 */
socketClientIPv6(const char * server_ip,const short server_port,const int timeout,const int flags,int * err_no)454 static inline int socketClientIPv6(const char *server_ip,
455 const short server_port, const int timeout,
456 const int flags, int *err_no)
457 {
458 return socketClient2(AF_INET6, server_ip, server_port,
459 timeout, flags, err_no);
460 }
461
462 #define tcprecvdata(sock, data, size, timeout) \
463 tcprecvdata_ex(sock, data, size, timeout, NULL)
464
465 #define tcpsendfile(sock, filename, file_bytes, timeout, total_send_bytes) \
466 tcpsendfile_ex(sock, filename, 0, file_bytes, timeout, total_send_bytes)
467
468 #define tcprecvdata_nb(sock, data, size, timeout) \
469 tcprecvdata_nb_ex(sock, data, size, timeout, NULL)
470
471 /** send a file
472 * parameters:
473 * sock: the socket
474 * filename: the file to send
475 * file_offset: file offset, start position
476 * file_bytes: send file length
477 * timeout: write timeout
478 * total_send_bytes: store the send bytes
479 * return: error no, 0 success, != 0 fail
480 */
481 int tcpsendfile_ex(int sock, const char *filename, const int64_t file_offset, \
482 const int64_t file_bytes, const int timeout, int64_t *total_send_bytes);
483
484 /** receive data to a file
485 * parameters:
486 * sock: the socket
487 * filename: the file to write
488 * file_bytes: file size (bytes)
489 * fsync_after_written_bytes: call fsync every x bytes
490 * timeout: read/recv timeout
491 * true_file_bytes: store the true file bytes
492 * return: error no, 0 success, != 0 fail
493 */
494 int tcprecvfile(int sock, const char *filename, const int64_t file_bytes, \
495 const int fsync_after_written_bytes, const int timeout, \
496 int64_t *true_file_bytes);
497
498
499 #define tcprecvinfinitefile(sock, filename, fsync_after_written_bytes, \
500 timeout, file_bytes) \
501 tcprecvfile(sock, filename, INFINITE_FILE_SIZE, \
502 fsync_after_written_bytes, timeout, file_bytes)
503
504
505 /** receive data to a file
506 * parameters:
507 * sock: the socket
508 * filename: the file to write
509 * file_bytes: file size (bytes)
510 * fsync_after_written_bytes: call fsync every x bytes
511 * hash_codes: return hash code of file content
512 * timeout: read/recv timeout
513 * return: error no, 0 success, != 0 fail
514 */
515 int tcprecvfile_ex(int sock, const char *filename, const int64_t file_bytes, \
516 const int fsync_after_written_bytes, \
517 unsigned int *hash_codes, const int timeout);
518
519 /** receive specified data and discard
520 * parameters:
521 * sock: the socket
522 * bytes: data bytes to discard
523 * timeout: read timeout
524 * total_recv_bytes: store the total recv bytes
525 * return: error no, 0 success, != 0 fail
526 */
527 int tcpdiscard(int sock, const int bytes, const int timeout, \
528 int64_t *total_recv_bytes);
529
530 /** get local host ip addresses
531 * parameters:
532 * ip_addrs: store the ip addresses
533 * max_count: max ip address (max ip_addrs elements)
534 * count: store the ip address count
535 * return: error no, 0 success, != 0 fail
536 */
537 int getlocaladdrs(char ip_addrs[][IP_ADDRESS_SIZE], \
538 const int max_count, int *count);
539
540 /** get local host ip addresses by if alias prefix
541 * parameters:
542 * if_alias_prefixes: if alias prefixes, such as eth, bond etc.
543 * prefix_count: if alias prefix count
544 * ip_addrs: store the ip addresses
545 * max_count: max ip address (max ip_addrs elements)
546 * count: store the ip address count
547 * return: error no, 0 success, != 0 fail
548 */
549 int gethostaddrs(char **if_alias_prefixes, const int prefix_count, \
550 char ip_addrs[][IP_ADDRESS_SIZE], const int max_count, int *count);
551
552 /** get local if configs
553 * parameters:
554 * if_configs: store the if configs
555 * max_count: max ifconfig elements
556 * count: store the ifconfig count
557 * return: error no, 0 success, != 0 fail
558 */
559 int getifconfigs(FastIFConfig *if_configs, const int max_count, int *count);
560
561 /** set socket address by ip and port
562 * parameters:
563 * ip: the ip address
564 * port: the port
565 * convert: the convert struct for IPv4 and IPv6 compatibility
566 * return: error no, 0 success, != 0 fail
567 */
568 int setsockaddrbyip(const char *ip, const short port, sockaddr_convert_t *convert);
569
is_ipv6_addr(const char * ip)570 static inline bool is_ipv6_addr(const char *ip)
571 {
572 return (*ip == ':' || strchr(ip, ':') != NULL); //ipv6
573 }
574
575 void tcp_set_try_again_when_interrupt(const bool value);
576
tcp_dont_try_again_when_interrupt()577 static inline void tcp_dont_try_again_when_interrupt()
578 {
579 tcp_set_try_again_when_interrupt(false);
580 }
581
582 #ifdef __cplusplus
583 }
584 #endif
585
586 #endif
587
588