osSocket.c 28.1 KB
Newer Older
S
Shengliang Guan 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#define _DEFAULT_SOURCE
17
#define ALLOW_FORBID_FUNC
S
Shengliang Guan 已提交
18
#include "os.h"
S
Shengliang Guan 已提交
19

20
#if defined(WINDOWS)
wafwerar's avatar
wafwerar 已提交
21 22 23 24 25 26 27
#include <IPHlpApi.h>
#include <WS2tcpip.h>
#include <Winsock2.h>
#include <stdio.h>
#include <string.h>
#include <tchar.h>
#include <winbase.h>
S
Shengliang Guan 已提交
28
#else
wafwerar's avatar
wafwerar 已提交
29 30
#include <arpa/inet.h>
#include <fcntl.h>
dengyihao's avatar
dengyihao 已提交
31
#include <net/if.h>
wafwerar's avatar
wafwerar 已提交
32 33 34 35 36 37 38
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <sys/socket.h>
#include <unistd.h>
39 40

#if defined(DARWIN)
dengyihao's avatar
dengyihao 已提交
41 42
#include <dispatch/dispatch.h>
#include "osEok.h"
43
#else
dengyihao's avatar
dengyihao 已提交
44
#include <sys/epoll.h>
45
#endif
S
Shengliang Guan 已提交
46 47
#endif

dengyihao's avatar
dengyihao 已提交
48 49 50 51
#ifndef INVALID_SOCKET
#define INVALID_SOCKET -1
#endif

wafwerar's avatar
wafwerar 已提交
52 53 54 55 56 57 58 59
typedef struct TdSocket {
#if SOCKET_WITH_LOCK
  TdThreadRwlock rwlock;
#endif
  int      refId;
  SocketFd fd;
} * TdSocketPtr, TdSocket;

wafwerar's avatar
wafwerar 已提交
60 61
typedef struct TdSocketServer {
#if SOCKET_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
62
  TdThreadRwlock rwlock;
wafwerar's avatar
wafwerar 已提交
63 64 65
#endif
  int      refId;
  SocketFd fd;
dengyihao's avatar
dengyihao 已提交
66
} * TdSocketServerPtr, TdSocketServer;
S
Shengliang Guan 已提交
67

wafwerar's avatar
wafwerar 已提交
68 69
typedef struct TdEpoll {
#if SOCKET_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
70
  TdThreadRwlock rwlock;
wafwerar's avatar
wafwerar 已提交
71
#endif
dengyihao's avatar
dengyihao 已提交
72 73 74
  int     refId;
  EpollFd fd;
} * TdEpollPtr, TdEpoll;
S
Shengliang Guan 已提交
75

wafwerar's avatar
wafwerar 已提交
76
int32_t taosSendto(TdSocketPtr pSocket, void *buf, int len, unsigned int flags, const struct sockaddr *dest_addr,
dengyihao's avatar
dengyihao 已提交
77
                   int addrlen) {
wafwerar's avatar
wafwerar 已提交
78 79
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
S
Shengliang Guan 已提交
80
  }
wafwerar's avatar
wafwerar 已提交
81
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
82 83 84 85 86 87 88 89
  return sendto(pSocket->fd, buf, len, flags, dest_addr, addrlen);
#else
  return sendto(pSocket->fd, buf, len, flags, dest_addr, addrlen);
#endif
}
int32_t taosWriteSocket(TdSocketPtr pSocket, void *buf, int len) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
S
Shengliang Guan 已提交
90
  }
wafwerar's avatar
wafwerar 已提交
91
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
92 93 94 95 96 97 98 99 100
  return send(pSocket->fd, buf, len, 0);
  ;
#else
  return write(pSocket->fd, buf, len);
#endif
}
int32_t taosReadSocket(TdSocketPtr pSocket, void *buf, int len) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
S
Shengliang Guan 已提交
101
  }
wafwerar's avatar
wafwerar 已提交
102
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
103 104 105 106 107 108
  return recv(pSocket->fd, buf, len, 0);
  ;
#else
  return read(pSocket->fd, buf, len);
#endif
}
S
Shengliang Guan 已提交
109

dengyihao's avatar
dengyihao 已提交
110 111
int32_t taosReadFromSocket(TdSocketPtr pSocket, void *buf, int32_t len, int32_t flags, struct sockaddr *destAddr,
                           int *addrLen) {
wafwerar's avatar
wafwerar 已提交
112 113
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
S
Shengliang Guan 已提交
114
  }
wafwerar's avatar
wafwerar 已提交
115 116 117
  return recvfrom(pSocket->fd, buf, len, flags, destAddr, addrLen);
}
int32_t taosCloseSocketNoCheck1(SocketFd fd) {
wafwerar's avatar
wafwerar 已提交
118
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
119 120 121
  return closesocket(fd);
#else
  return close(fd);
S
Shengliang Guan 已提交
122
#endif
wafwerar's avatar
wafwerar 已提交
123 124 125 126 127 128 129 130
}
int32_t taosCloseSocket(TdSocketPtr *ppSocket) {
  int32_t code;
  if (ppSocket == NULL || *ppSocket == NULL || (*ppSocket)->fd < 0) {
    return -1;
  }
  code = taosCloseSocketNoCheck1((*ppSocket)->fd);
  (*ppSocket)->fd = -1;
wafwerar's avatar
wafwerar 已提交
131
  taosMemoryFree(*ppSocket);
wafwerar's avatar
wafwerar 已提交
132 133 134 135 136 137 138 139 140
  return code;
}
int32_t taosCloseSocketServer(TdSocketServerPtr *ppSocketServer) {
  int32_t code;
  if (ppSocketServer == NULL || *ppSocketServer == NULL || (*ppSocketServer)->fd < 0) {
    return -1;
  }
  code = taosCloseSocketNoCheck1((*ppSocketServer)->fd);
  (*ppSocketServer)->fd = -1;
wafwerar's avatar
wafwerar 已提交
141
  taosMemoryFree(*ppSocketServer);
wafwerar's avatar
wafwerar 已提交
142 143
  return code;
}
S
Shengliang Guan 已提交
144

wafwerar's avatar
wafwerar 已提交
145 146 147 148
int32_t taosShutDownSocketRD(TdSocketPtr pSocket) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
S
Shengliang Guan 已提交
149
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
150
  return closesocket(pSocket->fd);
S
Shengliang Guan 已提交
151
#elif __APPLE__
wafwerar's avatar
wafwerar 已提交
152
  return close(pSocket->fd);
S
Shengliang Guan 已提交
153
#else
wafwerar's avatar
wafwerar 已提交
154
  return shutdown(pSocket->fd, SHUT_RD);
S
Shengliang Guan 已提交
155 156
#endif
}
wafwerar's avatar
wafwerar 已提交
157 158 159 160
int32_t taosShutDownSocketServerRD(TdSocketServerPtr pSocketServer) {
  if (pSocketServer == NULL || pSocketServer->fd < 0) {
    return -1;
  }
S
Shengliang Guan 已提交
161
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
162
  return closesocket(pSocketServer->fd);
S
Shengliang Guan 已提交
163
#elif __APPLE__
wafwerar's avatar
wafwerar 已提交
164
  return close(pSocketServer->fd);
S
Shengliang Guan 已提交
165
#else
wafwerar's avatar
wafwerar 已提交
166
  return shutdown(pSocketServer->fd, SHUT_RD);
S
Shengliang Guan 已提交
167 168
#endif
}
S
Shengliang Guan 已提交
169

wafwerar's avatar
wafwerar 已提交
170 171 172
int32_t taosShutDownSocketWR(TdSocketPtr pSocket) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
S
Shengliang Guan 已提交
173
  }
wafwerar's avatar
wafwerar 已提交
174 175 176 177 178 179
#ifdef WINDOWS
  return closesocket(pSocket->fd);
#elif __APPLE__
  return close(pSocket->fd);
#else
  return shutdown(pSocket->fd, SHUT_WR);
S
slguan 已提交
180
#endif
S
Shengliang Guan 已提交
181
}
wafwerar's avatar
wafwerar 已提交
182 183 184 185 186 187 188 189 190 191
int32_t taosShutDownSocketServerWR(TdSocketServerPtr pSocketServer) {
  if (pSocketServer == NULL || pSocketServer->fd < 0) {
    return -1;
  }
#ifdef WINDOWS
  return closesocket(pSocketServer->fd);
#elif __APPLE__
  return close(pSocketServer->fd);
#else
  return shutdown(pSocketServer->fd, SHUT_WR);
S
Shengliang Guan 已提交
192
#endif
wafwerar's avatar
wafwerar 已提交
193 194 195 196
}
int32_t taosShutDownSocketRDWR(TdSocketPtr pSocket) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
S
Shengliang Guan 已提交
197
  }
wafwerar's avatar
wafwerar 已提交
198 199 200 201 202 203 204 205 206 207 208
#ifdef WINDOWS
  return closesocket(pSocket->fd);
#elif __APPLE__
  return close(pSocket->fd);
#else
  return shutdown(pSocket->fd, SHUT_RDWR);
#endif
}
int32_t taosShutDownSocketServerRDWR(TdSocketServerPtr pSocketServer) {
  if (pSocketServer == NULL || pSocketServer->fd < 0) {
    return -1;
S
Shengliang Guan 已提交
209
  }
wafwerar's avatar
wafwerar 已提交
210 211 212 213 214 215 216
#ifdef WINDOWS
  return closesocket(pSocketServer->fd);
#elif __APPLE__
  return close(pSocketServer->fd);
#else
  return shutdown(pSocketServer->fd, SHUT_RDWR);
#endif
217
}
wafwerar's avatar
wafwerar 已提交
218

wafwerar's avatar
wafwerar 已提交
219 220
void taosWinSocketInit() {
#ifdef WINDOWS
S
Shengliang Guan 已提交
221 222 223 224 225 226 227 228 229
  static char flag = 0;
  if (flag == 0) {
    WORD    wVersionRequested;
    WSADATA wsaData;
    wVersionRequested = MAKEWORD(1, 1);
    if (WSAStartup(wVersionRequested, &wsaData) == 0) {
      flag = 1;
    }
  }
wafwerar's avatar
wafwerar 已提交
230 231
#else
#endif
232
}
wafwerar's avatar
wafwerar 已提交
233 234 235 236
int32_t taosSetNonblocking(TdSocketPtr pSocket, int32_t on) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
237
#ifdef WINDOWS
S
Shengliang Guan 已提交
238 239 240
  u_long mode;
  if (on) {
    mode = 1;
wafwerar's avatar
wafwerar 已提交
241
    ioctlsocket(pSocket->fd, FIONBIO, &mode);
S
Shengliang Guan 已提交
242 243
  } else {
    mode = 0;
wafwerar's avatar
wafwerar 已提交
244 245 246 247 248 249 250
    ioctlsocket(pSocket->fd, FIONBIO, &mode);
  }
#else
  int32_t flags = 0;
  if ((flags = fcntl(pSocket->fd, F_GETFL, 0)) < 0) {
    // printf("fcntl(F_GETFL) error: %d (%s)\n", errno, strerror(errno));
    return 1;
S
Shengliang Guan 已提交
251
  }
wafwerar's avatar
wafwerar 已提交
252 253 254 255 256 257 258 259 260 261 262

  if (on)
    flags |= O_NONBLOCK;
  else
    flags &= ~O_NONBLOCK;

  if ((flags = fcntl(pSocket->fd, F_SETFL, flags)) < 0) {
    // printf("fcntl(F_SETFL) error: %d (%s)\n", errno, strerror(errno));
    return 1;
  }
#endif
S
Shengliang Guan 已提交
263 264
  return 0;
}
wafwerar's avatar
wafwerar 已提交
265 266 267 268
int32_t taosSetSockOpt(TdSocketPtr pSocket, int32_t level, int32_t optname, void *optval, int32_t optlen) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
269
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
270
#ifdef TCP_KEEPCNT
S
Shengliang Guan 已提交
271 272 273
  if (level == SOL_SOCKET && optname == TCP_KEEPCNT) {
    return 0;
  }
wafwerar's avatar
wafwerar 已提交
274
#endif
S
Shengliang Guan 已提交
275

wafwerar's avatar
wafwerar 已提交
276
#ifdef TCP_KEEPIDLE
S
Shengliang Guan 已提交
277 278 279
  if (level == SOL_TCP && optname == TCP_KEEPIDLE) {
    return 0;
  }
wafwerar's avatar
wafwerar 已提交
280
#endif
S
Shengliang Guan 已提交
281

wafwerar's avatar
wafwerar 已提交
282
#ifdef TCP_KEEPINTVL
S
Shengliang Guan 已提交
283 284 285
  if (level == SOL_TCP && optname == TCP_KEEPINTVL) {
    return 0;
  }
wafwerar's avatar
wafwerar 已提交
286
#endif
S
Shengliang Guan 已提交
287

wafwerar's avatar
wafwerar 已提交
288
#ifdef TCP_KEEPCNT
S
Shengliang Guan 已提交
289 290 291
  if (level == SOL_TCP && optname == TCP_KEEPCNT) {
    return 0;
  }
wafwerar's avatar
wafwerar 已提交
292
#endif
S
Shengliang Guan 已提交
293

wafwerar's avatar
wafwerar 已提交
294 295
  return setsockopt(pSocket->fd, level, optname, optval, optlen);
#else
wafwerar's avatar
wafwerar 已提交
296
  return setsockopt(pSocket->fd, level, optname, optval, (int)optlen);
wafwerar's avatar
wafwerar 已提交
297 298 299 300 301 302
#endif
}
int32_t taosGetSockOpt(TdSocketPtr pSocket, int32_t level, int32_t optname, void *optval, int32_t *optlen) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
303
#ifdef WINDOWS
304
  assert(0);
wafwerar's avatar
wafwerar 已提交
305 306
  return 0;
#else
wafwerar's avatar
wafwerar 已提交
307
  return getsockopt(pSocket->fd, level, optname, optval, (int *)optlen);
wafwerar's avatar
wafwerar 已提交
308
#endif
S
Shengliang Guan 已提交
309
}
S
config  
Shengliang Guan 已提交
310
uint32_t taosInetAddr(const char *ipAddr) {
wafwerar's avatar
wafwerar 已提交
311
#ifdef WINDOWS
S
Shengliang Guan 已提交
312 313 314 315 316 317 318
  uint32_t value;
  int32_t  ret = inet_pton(AF_INET, ipAddr, &value);
  if (ret <= 0) {
    return INADDR_NONE;
  } else {
    return value;
  }
wafwerar's avatar
wafwerar 已提交
319 320 321
#else
  return inet_addr(ipAddr);
#endif
S
Shengliang Guan 已提交
322
}
wafwerar's avatar
wafwerar 已提交
323 324
const char *taosInetNtoa(struct in_addr ipInt, char *dstStr, int32_t len) {
  return inet_ntop(AF_INET, &ipInt, dstStr, len);
wafwerar's avatar
wafwerar 已提交
325
}
326 327

#ifndef SIGPIPE
wafwerar's avatar
wafwerar 已提交
328
#define SIGPIPE EPIPE
329 330 331 332
#endif

#define TCP_CONN_TIMEOUT 3000  // conn timeout

wafwerar's avatar
wafwerar 已提交
333 334 335 336
int32_t taosWriteMsg(TdSocketPtr pSocket, void *buf, int32_t nbytes) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
337
  int32_t nleft, nwritten;
dengyihao's avatar
dengyihao 已提交
338
  char   *ptr = (char *)buf;
339 340 341 342

  nleft = nbytes;

  while (nleft > 0) {
wafwerar's avatar
wafwerar 已提交
343
    nwritten = taosWriteSocket(pSocket, (char *)ptr, (size_t)nleft);
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
    if (nwritten <= 0) {
      if (errno == EINTR /* || errno == EAGAIN || errno == EWOULDBLOCK */)
        continue;
      else
        return -1;
    } else {
      nleft -= nwritten;
      ptr += nwritten;
    }

    if (errno == SIGPIPE || errno == EPIPE) {
      return -1;
    }
  }

  return (nbytes - nleft);
}

wafwerar's avatar
wafwerar 已提交
362 363 364 365
int32_t taosReadMsg(TdSocketPtr pSocket, void *buf, int32_t nbytes) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
366
  int32_t nleft, nread;
dengyihao's avatar
dengyihao 已提交
367
  char   *ptr = (char *)buf;
368 369 370 371

  nleft = nbytes;

  while (nleft > 0) {
wafwerar's avatar
wafwerar 已提交
372
    nread = taosReadSocket(pSocket, ptr, (size_t)nleft);
373 374 375
    if (nread == 0) {
      break;
    } else if (nread < 0) {
wafwerar's avatar
wafwerar 已提交
376
      if (errno == EINTR /* || errno == EAGAIN || errno == EWOULDBLOCK*/) {
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
        continue;
      } else {
        return -1;
      }
    } else {
      nleft -= nread;
      ptr += nread;
    }

    if (errno == SIGPIPE || errno == EPIPE) {
      return -1;
    }
  }

  return (nbytes - nleft);
}

wafwerar's avatar
wafwerar 已提交
394 395 396 397 398
int32_t taosNonblockwrite(TdSocketPtr pSocket, char *ptr, int32_t nbytes) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
  taosSetNonblocking(pSocket, 1);
399

wafwerar's avatar
wafwerar 已提交
400 401
  int32_t        nleft, nwritten, nready;
  fd_set         fset;
402 403 404 405 406 407 408
  struct timeval tv;

  nleft = nbytes;
  while (nleft > 0) {
    tv.tv_sec = 30;
    tv.tv_usec = 0;
    FD_ZERO(&fset);
wafwerar's avatar
wafwerar 已提交
409 410
    FD_SET(pSocket->fd, &fset);
    if ((nready = select((SocketFd)(pSocket->fd + 1), NULL, &fset, NULL, &tv)) == 0) {
411
      errno = ETIMEDOUT;
wafwerar's avatar
wafwerar 已提交
412
      // printf("fd %d timeout, no enough space to write", fd);
413 414 415 416 417
      break;

    } else if (nready < 0) {
      if (errno == EINTR) continue;

wafwerar's avatar
wafwerar 已提交
418
      // printf("select error, %d (%s)", errno, strerror(errno));
419 420 421
      return -1;
    }

wafwerar's avatar
wafwerar 已提交
422
    nwritten = (int32_t)send(pSocket->fd, ptr, (size_t)nleft, MSG_NOSIGNAL);
423 424 425
    if (nwritten <= 0) {
      if (errno == EAGAIN || errno == EINTR) continue;

wafwerar's avatar
wafwerar 已提交
426
      // printf("write error, %d (%s)", errno, strerror(errno));
427 428 429 430 431 432 433
      return -1;
    }

    nleft -= nwritten;
    ptr += nwritten;
  }

wafwerar's avatar
wafwerar 已提交
434
  taosSetNonblocking(pSocket, 0);
435 436 437 438

  return (nbytes - nleft);
}

wafwerar's avatar
wafwerar 已提交
439
TdSocketPtr taosOpenUdpSocket(uint32_t ip, uint16_t port) {
440
  struct sockaddr_in localAddr;
wafwerar's avatar
wafwerar 已提交
441 442
  SocketFd           fd;
  int32_t            bufSize = 1024000;
443

wafwerar's avatar
wafwerar 已提交
444
  // printf("open udp socket:0x%x:%hu", ip, port);
445 446 447 448 449 450

  memset((char *)&localAddr, 0, sizeof(localAddr));
  localAddr.sin_family = AF_INET;
  localAddr.sin_addr.s_addr = ip;
  localAddr.sin_port = (uint16_t)htons(port);

wafwerar's avatar
wafwerar 已提交
451 452 453 454
  if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) <= 2) {
    // printf("failed to open udp socket: %d (%s)", errno, strerror(errno));
    taosCloseSocketNoCheck1(fd);
    return NULL;
455 456
  }

wafwerar's avatar
wafwerar 已提交
457
  TdSocketPtr pSocket = (TdSocketPtr)taosMemoryMalloc(sizeof(TdSocket));
wafwerar's avatar
wafwerar 已提交
458 459 460
  if (pSocket == NULL) {
    taosCloseSocketNoCheck1(fd);
    return NULL;
461
  }
wafwerar's avatar
wafwerar 已提交
462 463
  pSocket->fd = fd;
  pSocket->refId = 0;
464

wafwerar's avatar
wafwerar 已提交
465 466 467 468 469 470 471 472 473 474
  if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_SNDBUF, (void *)&bufSize, sizeof(bufSize)) != 0) {
    // printf("failed to set the send buffer size for UDP socket\n");
    taosCloseSocket(&pSocket);
    return NULL;
  }

  if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_RCVBUF, (void *)&bufSize, sizeof(bufSize)) != 0) {
    // printf("failed to set the receive buffer size for UDP socket\n");
    taosCloseSocket(&pSocket);
    return NULL;
475 476 477
  }

  /* bind socket to local address */
wafwerar's avatar
wafwerar 已提交
478 479 480 481
  if (bind(pSocket->fd, (struct sockaddr *)&localAddr, sizeof(localAddr)) < 0) {
    // printf("failed to bind udp socket: %d (%s), 0x%x:%hu", errno, strerror(errno), ip, port);
    taosCloseSocket(&pSocket);
    return NULL;
482 483
  }

wafwerar's avatar
wafwerar 已提交
484
  return pSocket;
485 486
}

wafwerar's avatar
wafwerar 已提交
487 488 489
TdSocketPtr taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientIp) {
  SocketFd           fd = -1;
  int32_t            ret;
490
  struct sockaddr_in serverAddr, clientAddr;
wafwerar's avatar
wafwerar 已提交
491
  int32_t            bufSize = 1024 * 1024;
492

wafwerar's avatar
wafwerar 已提交
493
  fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
494

wafwerar's avatar
wafwerar 已提交
495 496 497 498
  if (fd <= 2) {
    // printf("failed to open the socket: %d (%s)", errno, strerror(errno));
    if (fd >= 0) taosCloseSocketNoCheck1(fd);
    return NULL;
499 500
  }

wafwerar's avatar
wafwerar 已提交
501
  TdSocketPtr pSocket = (TdSocketPtr)taosMemoryMalloc(sizeof(TdSocket));
wafwerar's avatar
wafwerar 已提交
502 503 504 505 506 507 508
  if (pSocket == NULL) {
    taosCloseSocketNoCheck1(fd);
    return NULL;
  }
  pSocket->fd = fd;
  pSocket->refId = 0;

509 510
  /* set REUSEADDR option, so the portnumber can be re-used */
  int32_t reuse = 1;
wafwerar's avatar
wafwerar 已提交
511 512 513 514
  if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse)) < 0) {
    // printf("setsockopt SO_REUSEADDR failed: %d (%s)", errno, strerror(errno));
    taosCloseSocket(&pSocket);
    return NULL;
515 516
  }

wafwerar's avatar
wafwerar 已提交
517 518 519 520
  if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_SNDBUF, (void *)&bufSize, sizeof(bufSize)) != 0) {
    // printf("failed to set the send buffer size for TCP socket\n");
    taosCloseSocket(&pSocket);
    return NULL;
521 522
  }

wafwerar's avatar
wafwerar 已提交
523 524 525 526
  if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_RCVBUF, (void *)&bufSize, sizeof(bufSize)) != 0) {
    // printf("failed to set the receive buffer size for TCP socket\n");
    taosCloseSocket(&pSocket);
    return NULL;
527 528 529 530 531 532 533 534 535
  }

  if (clientIp != 0) {
    memset((char *)&clientAddr, 0, sizeof(clientAddr));
    clientAddr.sin_family = AF_INET;
    clientAddr.sin_addr.s_addr = clientIp;
    clientAddr.sin_port = 0;

    /* bind socket to client address */
wafwerar's avatar
wafwerar 已提交
536 537 538 539 540
    if (bind(pSocket->fd, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0) {
      // printf("bind tcp client socket failed, client(0x%x:0), dest(0x%x:%d), reason:(%s)", clientIp, destIp, destPort,
      //        strerror(errno));
      taosCloseSocket(&pSocket);
      return NULL;
541 542 543 544 545 546 547 548
    }
  }

  memset((char *)&serverAddr, 0, sizeof(serverAddr));
  serverAddr.sin_family = AF_INET;
  serverAddr.sin_addr.s_addr = destIp;
  serverAddr.sin_port = (uint16_t)htons((uint16_t)destPort);

wafwerar's avatar
wafwerar 已提交
549 550 551
#ifdef _TD_LINUX
  taosSetNonblocking(pSocket, 1);
  ret = connect(pSocket->fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
552 553
  if (ret == -1) {
    if (errno == EHOSTUNREACH) {
wafwerar's avatar
wafwerar 已提交
554 555 556
      // printf("failed to connect socket, ip:0x%x, port:%hu(%s)", destIp, destPort, strerror(errno));
      taosCloseSocket(&pSocket);
      return -1;
557
    } else if (errno == EINPROGRESS || errno == EAGAIN || errno == EWOULDBLOCK) {
wafwerar's avatar
wafwerar 已提交
558
      struct pollfd wfd[1];
559

wafwerar's avatar
wafwerar 已提交
560
      wfd[0].fd = pSocket->fd;
561
      wfd[0].events = POLLOUT;
wafwerar's avatar
wafwerar 已提交
562

563 564
      int res = poll(wfd, 1, TCP_CONN_TIMEOUT);
      if (res == -1 || res == 0) {
wafwerar's avatar
wafwerar 已提交
565 566
        // printf("failed to connect socket, ip:0x%x, port:%hu(poll error/conn timeout)", destIp, destPort);
        taosCloseSocket(&pSocket);  //
567 568
        return -1;
      }
wafwerar's avatar
wafwerar 已提交
569 570 571 572
      int optVal = -1, optLen = sizeof(int);
      if ((0 != taosGetSockOpt(pSocket, SOL_SOCKET, SO_ERROR, &optVal, &optLen)) || (optVal != 0)) {
        // printf("failed to connect socket, ip:0x%x, port:%hu(connect host error)", destIp, destPort);
        taosCloseSocket(&pSocket);  //
573 574 575
        return -1;
      }
      ret = 0;
wafwerar's avatar
wafwerar 已提交
576 577 578 579 580
    } else {  // Other error
      // printf("failed to connect socket, ip:0x%x, port:%hu(target host cannot be reached)", destIp, destPort);
      taosCloseSocket(&pSocket);  //
      return -1;
    }
581
  }
wafwerar's avatar
wafwerar 已提交
582
  taosSetNonblocking(pSocket, 0);
583 584

#else
wafwerar's avatar
wafwerar 已提交
585
  ret = connect(pSocket->fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
586 587 588
#endif

  if (ret != 0) {
wafwerar's avatar
wafwerar 已提交
589 590 591
    // printf("failed to connect socket, ip:0x%x, port:%hu(%s)", destIp, destPort, strerror(errno));
    taosCloseSocket(&pSocket);
    return NULL;
592
  } else {
dengyihao's avatar
dengyihao 已提交
593 594 595
    if (taosKeepTcpAlive(pSocket) == -1) {
      return NULL;
    }
596 597
  }

wafwerar's avatar
wafwerar 已提交
598
  return pSocket;
599 600
}

wafwerar's avatar
wafwerar 已提交
601 602 603 604
int32_t taosKeepTcpAlive(TdSocketPtr pSocket) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
605
  int32_t alive = 1;
wafwerar's avatar
wafwerar 已提交
606 607 608
  if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_KEEPALIVE, (void *)&alive, sizeof(alive)) < 0) {
    // printf("fd:%d setsockopt SO_KEEPALIVE failed: %d (%s)", sockFd, errno, strerror(errno));
    taosCloseSocket(&pSocket);
609 610 611 612 613
    return -1;
  }

#ifndef __APPLE__
  // all fails on macosx
wafwerar's avatar
wafwerar 已提交
614
#ifdef TCP_KEEPCNT
615
  int32_t probes = 3;
wafwerar's avatar
wafwerar 已提交
616 617 618
  if (taosSetSockOpt(pSocket, SOL_TCP, TCP_KEEPCNT, (void *)&probes, sizeof(probes)) < 0) {
    // printf("fd:%d setsockopt SO_KEEPCNT failed: %d (%s)", sockFd, errno, strerror(errno));
    taosCloseSocket(&pSocket);
619 620
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
621
#endif
622

wafwerar's avatar
wafwerar 已提交
623
#ifdef TCP_KEEPIDLE
624
  int32_t alivetime = 10;
wafwerar's avatar
wafwerar 已提交
625 626 627
  if (taosSetSockOpt(pSocket, SOL_TCP, TCP_KEEPIDLE, (void *)&alivetime, sizeof(alivetime)) < 0) {
    // printf("fd:%d setsockopt SO_KEEPIDLE failed: %d (%s)", sockFd, errno, strerror(errno));
    taosCloseSocket(&pSocket);
628 629
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
630
#endif
631

wafwerar's avatar
wafwerar 已提交
632
#ifdef TCP_KEEPINTVL
633
  int32_t interval = 3;
wafwerar's avatar
wafwerar 已提交
634 635 636
  if (taosSetSockOpt(pSocket, SOL_TCP, TCP_KEEPINTVL, (void *)&interval, sizeof(interval)) < 0) {
    // printf("fd:%d setsockopt SO_KEEPINTVL failed: %d (%s)", sockFd, errno, strerror(errno));
    taosCloseSocket(&pSocket);
637 638
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
639
#endif
wafwerar's avatar
wafwerar 已提交
640
#endif  // __APPLE__
641 642

  int32_t nodelay = 1;
wafwerar's avatar
wafwerar 已提交
643 644 645
  if (taosSetSockOpt(pSocket, IPPROTO_TCP, TCP_NODELAY, (void *)&nodelay, sizeof(nodelay)) < 0) {
    // printf("fd:%d setsockopt TCP_NODELAY failed %d (%s)", sockFd, errno, strerror(errno));
    taosCloseSocket(&pSocket);
646 647 648 649 650 651
    return -1;
  }

  struct linger linger = {0};
  linger.l_onoff = 1;
  linger.l_linger = 3;
wafwerar's avatar
wafwerar 已提交
652 653 654
  if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger)) < 0) {
    // printf("setsockopt SO_LINGER failed: %d (%s)", errno, strerror(errno));
    taosCloseSocket(&pSocket);
655 656 657 658 659 660
    return -1;
  }

  return 0;
}

dengyihao's avatar
dengyihao 已提交
661 662 663
int taosGetLocalIp(const char *eth, char *ip) {
#if defined(WINDOWS)
  // DO NOTHAING
664
  assert(0);
dengyihao's avatar
dengyihao 已提交
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682
  return 0;
#else
  int                fd;
  struct ifreq       ifr;
  struct sockaddr_in sin;

  fd = socket(AF_INET, SOCK_DGRAM, 0);
  if (-1 == fd) {
    return -1;
  }
  strncpy(ifr.ifr_name, eth, IFNAMSIZ);
  ifr.ifr_name[IFNAMSIZ - 1] = 0;

  if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
    taosCloseSocketNoCheck1(fd);
    return -1;
  }
  memcpy(&sin, &ifr.ifr_addr, sizeof(sin));
wafwerar's avatar
wafwerar 已提交
683
  taosInetNtoa(sin.sin_addr, ip, 64);
dengyihao's avatar
dengyihao 已提交
684 685 686 687 688 689 690
  taosCloseSocketNoCheck1(fd);
#endif
  return 0;
}
int taosValidIp(uint32_t ip) {
#if defined(WINDOWS)
  // DO NOTHAING
691
  assert(0);
dengyihao's avatar
dengyihao 已提交
692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
  return 0;
#else
  int ret = -1;
  int fd;

  struct ifconf ifconf;

  char buf[512] = {0};
  ifconf.ifc_len = 512;
  ifconf.ifc_buf = buf;

  if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    return -1;
  }

  ioctl(fd, SIOCGIFCONF, &ifconf);
  struct ifreq *ifreq = (struct ifreq *)ifconf.ifc_buf;
  for (int i = (ifconf.ifc_len / sizeof(struct ifreq)); i > 0; i--) {
    char ip_str[64] = {0};
    if (ifreq->ifr_flags == AF_INET) {
      ret = taosGetLocalIp(ifreq->ifr_name, ip_str);
      if (ret != 0) {
        break;
      }
dengyihao's avatar
dengyihao 已提交
716 717 718 719 720
      ret = -1;
      if (ip == (uint32_t)taosInetAddr(ip_str)) {
        ret = 0;
        break;
      }
dengyihao's avatar
dengyihao 已提交
721 722 723 724 725 726 727 728 729
      ifreq++;
    }
  }
  taosCloseSocketNoCheck1(fd);
  return ret;
#endif
  return 0;
}

730 731 732 733 734 735 736 737 738
bool taosValidIpAndPort(uint32_t ip, uint16_t port) {
  struct sockaddr_in serverAdd;
  SocketFd           fd;
  int32_t            reuse;

  // printf("open tcp server socket:0x%x:%hu", ip, port);

  bzero((char *)&serverAdd, sizeof(serverAdd));
  serverAdd.sin_family = AF_INET;
wafwerar's avatar
wafwerar 已提交
739 740 741
#ifdef WINDOWS
  serverAdd.sin_addr.s_addr = INADDR_ANY;
#else
742
  serverAdd.sin_addr.s_addr = ip;
wafwerar's avatar
wafwerar 已提交
743
#endif
744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764
  serverAdd.sin_port = (uint16_t)htons(port);

  if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <= 2) {
    // printf("failed to open TCP socket: %d (%s)", errno, strerror(errno));
    taosCloseSocketNoCheck1(fd);
    return false;
  }

  TdSocketPtr pSocket = (TdSocketPtr)taosMemoryMalloc(sizeof(TdSocket));
  if (pSocket == NULL) {
    taosCloseSocketNoCheck1(fd);
    return false;
  }
  pSocket->refId = 0;
  pSocket->fd = fd;

  /* set REUSEADDR option, so the portnumber can be re-used */
  reuse = 1;
  if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse)) < 0) {
    // printf("setsockopt SO_REUSEADDR failed: %d (%s)", errno, strerror(errno));
    taosCloseSocket(&pSocket);
dengyihao's avatar
dengyihao 已提交
765
    return false;
766 767 768 769 770 771 772 773
  }
  /* bind socket to server address */
  if (bind(pSocket->fd, (struct sockaddr *)&serverAdd, sizeof(serverAdd)) < 0) {
    // printf("bind tcp server socket failed, 0x%x:%hu(%s)", ip, port, strerror(errno));
    taosCloseSocket(&pSocket);
    return false;
  }
  taosCloseSocket(&pSocket);
dengyihao's avatar
dengyihao 已提交
774 775
  return true;
  // return 0 == taosValidIp(ip) ? true : false;
776
}
wafwerar's avatar
wafwerar 已提交
777
TdSocketServerPtr taosOpenTcpServerSocket(uint32_t ip, uint16_t port) {
778
  struct sockaddr_in serverAdd;
wafwerar's avatar
wafwerar 已提交
779
  SocketFd           fd;
780 781
  int32_t            reuse;

wafwerar's avatar
wafwerar 已提交
782
  // printf("open tcp server socket:0x%x:%hu", ip, port);
783 784 785 786 787 788

  bzero((char *)&serverAdd, sizeof(serverAdd));
  serverAdd.sin_family = AF_INET;
  serverAdd.sin_addr.s_addr = ip;
  serverAdd.sin_port = (uint16_t)htons(port);

wafwerar's avatar
wafwerar 已提交
789 790 791 792 793 794
  if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <= 2) {
    // printf("failed to open TCP socket: %d (%s)", errno, strerror(errno));
    taosCloseSocketNoCheck1(fd);
    return NULL;
  }

wafwerar's avatar
wafwerar 已提交
795
  TdSocketPtr pSocket = (TdSocketPtr)taosMemoryMalloc(sizeof(TdSocket));
wafwerar's avatar
wafwerar 已提交
796 797 798
  if (pSocket == NULL) {
    taosCloseSocketNoCheck1(fd);
    return NULL;
799
  }
wafwerar's avatar
wafwerar 已提交
800 801
  pSocket->refId = 0;
  pSocket->fd = fd;
802 803 804

  /* set REUSEADDR option, so the portnumber can be re-used */
  reuse = 1;
wafwerar's avatar
wafwerar 已提交
805 806 807 808
  if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse)) < 0) {
    // printf("setsockopt SO_REUSEADDR failed: %d (%s)", errno, strerror(errno));
    taosCloseSocket(&pSocket);
    return NULL;
809 810 811
  }

  /* bind socket to server address */
wafwerar's avatar
wafwerar 已提交
812 813 814 815
  if (bind(pSocket->fd, (struct sockaddr *)&serverAdd, sizeof(serverAdd)) < 0) {
    // printf("bind tcp server socket failed, 0x%x:%hu(%s)", ip, port, strerror(errno));
    taosCloseSocket(&pSocket);
    return NULL;
816 817
  }

wafwerar's avatar
wafwerar 已提交
818 819 820
  if (taosKeepTcpAlive(pSocket) < 0) {
    // printf("failed to set tcp server keep-alive option, 0x%x:%hu(%s)", ip, port, strerror(errno));
    return NULL;
821 822
  }

wafwerar's avatar
wafwerar 已提交
823 824 825 826
  if (listen(pSocket->fd, 1024) < 0) {
    // printf("listen tcp server socket failed, 0x%x:%hu(%s)", ip, port, strerror(errno));
    taosCloseSocket(&pSocket);
    return NULL;
827 828
  }

wafwerar's avatar
wafwerar 已提交
829
  return (TdSocketServerPtr)pSocket;
830 831
}

dengyihao's avatar
dengyihao 已提交
832
TdSocketPtr taosAcceptTcpConnectSocket(TdSocketServerPtr pServerSocket, struct sockaddr *destAddr, int *addrLen) {
wafwerar's avatar
wafwerar 已提交
833 834 835 836 837 838 839 840 841
  if (pServerSocket == NULL || pServerSocket->fd < 0) {
    return NULL;
  }
  SocketFd fd = accept(pServerSocket->fd, destAddr, addrLen);
  if (fd == -1) {
    // tError("TCP accept failure(%s)", strerror(errno));
    return NULL;
  }

wafwerar's avatar
wafwerar 已提交
842
  TdSocketPtr pSocket = (TdSocketPtr)taosMemoryMalloc(sizeof(TdSocket));
wafwerar's avatar
wafwerar 已提交
843 844 845 846 847 848 849 850
  if (pSocket == NULL) {
    taosCloseSocketNoCheck1(fd);
    return NULL;
  }
  pSocket->fd = fd;
  pSocket->refId = 0;
  return pSocket;
}
851 852 853
#define COPY_SIZE 32768
// sendfile shall be used

wafwerar's avatar
wafwerar 已提交
854 855 856 857
int64_t taosCopyFds(TdSocketPtr pSrcSocket, TdSocketPtr pDestSocket, int64_t len) {
  if (pSrcSocket == NULL || pSrcSocket->fd < 0 || pDestSocket == NULL || pDestSocket->fd < 0) {
    return -1;
  }
858 859 860 861 862 863 864 865 866 867 868 869
  int64_t leftLen;
  int64_t readLen, writeLen;
  char    temp[COPY_SIZE];

  leftLen = len;

  while (leftLen > 0) {
    if (leftLen < COPY_SIZE)
      readLen = leftLen;
    else
      readLen = COPY_SIZE;  // 4K

wafwerar's avatar
wafwerar 已提交
870
    int64_t retLen = taosReadMsg(pSrcSocket, temp, (int32_t)readLen);
871
    if (readLen != retLen) {
wafwerar's avatar
wafwerar 已提交
872 873
      // printf("read error, readLen:%" PRId64 " retLen:%" PRId64 " len:%" PRId64 " leftLen:%" PRId64 ", reason:%s",
      //        readLen, retLen, len, leftLen, strerror(errno));
874 875 876
      return -1;
    }

wafwerar's avatar
wafwerar 已提交
877
    writeLen = taosWriteMsg(pDestSocket, temp, (int32_t)readLen);
878 879

    if (readLen != writeLen) {
wafwerar's avatar
wafwerar 已提交
880 881
      // printf("copy error, readLen:%" PRId64 " writeLen:%" PRId64 " len:%" PRId64 " leftLen:%" PRId64 ", reason:%s",
      //        readLen, writeLen, len, leftLen, strerror(errno));
882 883 884 885 886 887 888 889
      return -1;
    }

    leftLen -= readLen;
  }

  return len;
}
890 891

void taosBlockSIGPIPE() {
wafwerar's avatar
wafwerar 已提交
892
#ifdef WINDOWS
893
  // assert(0);
894
#else
895 896 897
  sigset_t signal_mask;
  sigemptyset(&signal_mask);
  sigaddset(&signal_mask, SIGPIPE);
wafwerar's avatar
wafwerar 已提交
898
  int32_t rc = pthread_sigmask(SIG_BLOCK, &signal_mask, NULL);
899
  if (rc != 0) {
wafwerar's avatar
wafwerar 已提交
900
    // printf("failed to block SIGPIPE");
901
  }
902
#endif
903
}
904 905

uint32_t taosGetIpv4FromFqdn(const char *fqdn) {
wafwerar's avatar
wafwerar 已提交
906 907 908
#ifdef WINDOWS
  // Initialize Winsock
  WSADATA wsaData;
dengyihao's avatar
dengyihao 已提交
909
  int     iResult;
wafwerar's avatar
wafwerar 已提交
910 911
  iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
  if (iResult != 0) {
dengyihao's avatar
dengyihao 已提交
912 913
    // printf("WSAStartup failed: %d\n", iResult);
    return 1;
wafwerar's avatar
wafwerar 已提交
914 915
  }
#endif
916 917 918 919 920 921 922 923
  struct addrinfo hints = {0};
  hints.ai_family = AF_INET;
  hints.ai_socktype = SOCK_STREAM;

  struct addrinfo *result = NULL;

  int32_t ret = getaddrinfo(fqdn, NULL, &hints, &result);
  if (result) {
dengyihao's avatar
dengyihao 已提交
924
    struct sockaddr    *sa = result->ai_addr;
925 926 927 928 929 930 931 932
    struct sockaddr_in *si = (struct sockaddr_in *)sa;
    struct in_addr      ia = si->sin_addr;
    uint32_t            ip = ia.s_addr;
    freeaddrinfo(result);
    return ip;
  } else {
#ifdef EAI_SYSTEM
    if (ret == EAI_SYSTEM) {
dengyihao's avatar
dengyihao 已提交
933
      // printf("failed to get the ip address, fqdn:%s, errno:%d, since:%s", fqdn, errno, strerror(errno));
934
    } else {
dengyihao's avatar
dengyihao 已提交
935
      // printf("failed to get the ip address, fqdn:%s, ret:%d, since:%s", fqdn, ret, gai_strerror(ret));
936
    }
937
#else
dengyihao's avatar
dengyihao 已提交
938
    // printf("failed to get the ip address, fqdn:%s, ret:%d, since:%s", fqdn, ret, gai_strerror(ret));
939 940 941 942 943 944
#endif
    return 0xFFFFFFFF;
  }
}

int32_t taosGetFqdn(char *fqdn) {
wafwerar's avatar
wafwerar 已提交
945 946 947 948 949 950 951 952 953 954
#ifdef WINDOWS
  // Initialize Winsock
  WSADATA wsaData;
  int     iResult;
  iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
  if (iResult != 0) {
    // printf("WSAStartup failed: %d\n", iResult);
    return 1;
  }
#endif
955 956 957
  char hostname[1024];
  hostname[1023] = '\0';
  if (gethostname(hostname, 1023) == -1) {
wafwerar's avatar
wafwerar 已提交
958
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
959
    printf("failed to get hostname, reason:%s\n", strerror(WSAGetLastError()));
wafwerar's avatar
wafwerar 已提交
960
#else
wafwerar's avatar
wafwerar 已提交
961
    printf("failed to get hostname, reason:%s\n", strerror(errno));
wafwerar's avatar
wafwerar 已提交
962
#endif
wafwerar's avatar
wafwerar 已提交
963
    assert(0);
964 965 966 967 968 969 970 971 972 973 974
    return -1;
  }

  struct addrinfo  hints = {0};
  struct addrinfo *result = NULL;
#ifdef __APPLE__
  // on macosx, hostname -f has the form of xxx.local
  // which will block getaddrinfo for a few seconds if AI_CANONNAME is set
  // thus, we choose AF_INET (ipv4 for the moment) to make getaddrinfo return
  // immediately
  hints.ai_family = AF_INET;
wafwerar's avatar
wafwerar 已提交
975
#else   // __APPLE__
976
  hints.ai_flags = AI_CANONNAME;
wafwerar's avatar
wafwerar 已提交
977
#endif  // __APPLE__
978 979
  int32_t ret = getaddrinfo(hostname, NULL, &hints, &result);
  if (!result) {
wafwerar's avatar
wafwerar 已提交
980
    fprintf(stderr, "failed to get fqdn, code:%d, reason:%s\n", ret, gai_strerror(ret));
981 982 983 984 985 986
    return -1;
  }

#ifdef __APPLE__
  // refer to comments above
  strcpy(fqdn, hostname);
wafwerar's avatar
wafwerar 已提交
987
#else   // __APPLE__
988
  strcpy(fqdn, result->ai_canonname);
wafwerar's avatar
wafwerar 已提交
989
#endif  // __APPLE__
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
  freeaddrinfo(result);
  return 0;
}

// Function converting an IP address string to an uint32_t.
uint32_t ip2uint(const char *const ip_addr) {
  char ip_addr_cpy[20];
  char ip[5];

  tstrncpy(ip_addr_cpy, ip_addr, sizeof(ip_addr_cpy));

  char *s_start, *s_end;
  s_start = ip_addr_cpy;
  s_end = ip_addr_cpy;

  int32_t k;

  for (k = 0; *s_start != '\0'; s_start = s_end) {
    for (s_end = s_start; *s_end != '.' && *s_end != '\0'; s_end++) {
    }
    if (*s_end == '.') {
      *s_end = '\0';
      s_end++;
    }
    ip[k++] = (char)atoi(s_start);
  }

  ip[k] = '\0';

  return *((uint32_t *)ip);
}

void tinet_ntoa(char *ipstr, uint32_t ip) {
  sprintf(ipstr, "%d.%d.%d.%d", ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, ip >> 24);
}

dengyihao's avatar
dengyihao 已提交
1026
void taosIgnSIGPIPE() { signal(SIGPIPE, SIG_IGN); }
1027 1028

void taosSetMaskSIGPIPE() {
wafwerar's avatar
wafwerar 已提交
1029
#ifdef WINDOWS
1030
  // assert(0);
1031 1032 1033 1034
#else
  sigset_t signal_mask;
  sigemptyset(&signal_mask);
  sigaddset(&signal_mask, SIGPIPE);
wafwerar's avatar
wafwerar 已提交
1035
  int32_t rc = pthread_sigmask(SIG_SETMASK, &signal_mask, NULL);
1036
  if (rc != 0) {
wafwerar's avatar
wafwerar 已提交
1037 1038 1039 1040 1041
    // printf("failed to setmask SIGPIPE");
  }
#endif
}

wafwerar's avatar
wafwerar 已提交
1042
int32_t taosGetSocketName(TdSocketPtr pSocket, struct sockaddr *destAddr, int *addrLen) {
wafwerar's avatar
wafwerar 已提交
1043 1044 1045 1046 1047 1048
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
  return getsockname(pSocket->fd, destAddr, addrLen);
}

dengyihao's avatar
dengyihao 已提交
1049 1050 1051 1052
/*
 * Set TCP connection timeout per-socket level.
 * ref [https://github.com/libuv/help/issues/54]
 */
dengyihao's avatar
dengyihao 已提交
1053
int32_t taosCreateSocketWithTimeout(uint32_t timeout) {
dengyihao's avatar
dengyihao 已提交
1054 1055 1056 1057 1058 1059 1060 1061 1062
#if defined(WINDOWS)
  SOCKET fd;
#else
  int      fd;
#endif
  if ((fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
    return -1;
  }
#if defined(WINDOWS)
dengyihao's avatar
dengyihao 已提交
1063
  if (0 != setsockopt(fd, IPPROTO_TCP, TCP_MAXRT, (char *)&timeout, sizeof(timeout))) {
dengyihao's avatar
dengyihao 已提交
1064
    taosCloseSocketNoCheck1(fd);
dengyihao's avatar
dengyihao 已提交
1065 1066
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
1067 1068 1069
#elif defined(_TD_DARWIN_64)
  uint32_t conn_timeout_ms = timeout * 1000;
  if (0 != setsockopt(fd, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT, (char *)&conn_timeout_ms, sizeof(conn_timeout_ms))) {
dengyihao's avatar
dengyihao 已提交
1070
    taosCloseSocketNoCheck1(fd);
wafwerar's avatar
wafwerar 已提交
1071 1072
    return -1;
  }
dengyihao's avatar
dengyihao 已提交
1073
#else  // Linux like systems
dengyihao's avatar
dengyihao 已提交
1074
  uint32_t conn_timeout_ms = timeout * 1000;
dengyihao's avatar
dengyihao 已提交
1075
  if (0 != setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, (char *)&conn_timeout_ms, sizeof(conn_timeout_ms))) {
dengyihao's avatar
dengyihao 已提交
1076
    taosCloseSocketNoCheck1(fd);
dengyihao's avatar
dengyihao 已提交
1077 1078 1079
    return -1;
  }
#endif
dengyihao's avatar
dengyihao 已提交
1080

dengyihao's avatar
dengyihao 已提交
1081 1082
  return (int)fd;
}