osSocket.c 27.9 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 {
wafwerar's avatar
wafwerar 已提交
593
    taosKeepTcpAlive(pSocket);
594 595
  }

wafwerar's avatar
wafwerar 已提交
596
  return pSocket;
597 598
}

wafwerar's avatar
wafwerar 已提交
599 600 601 602
int32_t taosKeepTcpAlive(TdSocketPtr pSocket) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
603
  int32_t alive = 1;
wafwerar's avatar
wafwerar 已提交
604 605 606
  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);
607 608 609 610 611
    return -1;
  }

#ifndef __APPLE__
  // all fails on macosx
wafwerar's avatar
wafwerar 已提交
612
#ifdef TCP_KEEPCNT
613
  int32_t probes = 3;
wafwerar's avatar
wafwerar 已提交
614 615 616
  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);
617 618
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
619
#endif
620

wafwerar's avatar
wafwerar 已提交
621
#ifdef TCP_KEEPIDLE
622
  int32_t alivetime = 10;
wafwerar's avatar
wafwerar 已提交
623 624 625
  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);
626 627
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
628
#endif
629

wafwerar's avatar
wafwerar 已提交
630
#ifdef TCP_KEEPINTVL
631
  int32_t interval = 3;
wafwerar's avatar
wafwerar 已提交
632 633 634
  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);
635 636
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
637
#endif
wafwerar's avatar
wafwerar 已提交
638
#endif  // __APPLE__
639 640

  int32_t nodelay = 1;
wafwerar's avatar
wafwerar 已提交
641 642 643
  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);
644 645 646 647 648 649
    return -1;
  }

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

  return 0;
}

dengyihao's avatar
dengyihao 已提交
659 660 661
int taosGetLocalIp(const char *eth, char *ip) {
#if defined(WINDOWS)
  // DO NOTHAING
662
  assert(0);
dengyihao's avatar
dengyihao 已提交
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
  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 已提交
681
  taosInetNtoa(sin.sin_addr, ip, 64);
dengyihao's avatar
dengyihao 已提交
682 683 684 685 686 687 688
  taosCloseSocketNoCheck1(fd);
#endif
  return 0;
}
int taosValidIp(uint32_t ip) {
#if defined(WINDOWS)
  // DO NOTHAING
689
  assert(0);
dengyihao's avatar
dengyihao 已提交
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
  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 已提交
714 715 716 717 718
      ret = -1;
      if (ip == (uint32_t)taosInetAddr(ip_str)) {
        ret = 0;
        break;
      }
dengyihao's avatar
dengyihao 已提交
719 720 721 722 723 724 725 726 727
      ifreq++;
    }
  }
  taosCloseSocketNoCheck1(fd);
  return ret;
#endif
  return 0;
}

728 729 730 731 732 733 734 735 736
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 已提交
737 738 739
#ifdef WINDOWS
  serverAdd.sin_addr.s_addr = INADDR_ANY;
#else
740
  serverAdd.sin_addr.s_addr = ip;
wafwerar's avatar
wafwerar 已提交
741
#endif
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
  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 已提交
763
    return false;
764 765 766 767 768 769 770 771
  }
  /* 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 已提交
772 773
  return true;
  // return 0 == taosValidIp(ip) ? true : false;
774
}
wafwerar's avatar
wafwerar 已提交
775
TdSocketServerPtr taosOpenTcpServerSocket(uint32_t ip, uint16_t port) {
776
  struct sockaddr_in serverAdd;
wafwerar's avatar
wafwerar 已提交
777
  SocketFd           fd;
778 779
  int32_t            reuse;

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

  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 已提交
787 788 789 790 791 792
  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 已提交
793
  TdSocketPtr pSocket = (TdSocketPtr)taosMemoryMalloc(sizeof(TdSocket));
wafwerar's avatar
wafwerar 已提交
794 795 796
  if (pSocket == NULL) {
    taosCloseSocketNoCheck1(fd);
    return NULL;
797
  }
wafwerar's avatar
wafwerar 已提交
798 799
  pSocket->refId = 0;
  pSocket->fd = fd;
800 801 802

  /* set REUSEADDR option, so the portnumber can be re-used */
  reuse = 1;
wafwerar's avatar
wafwerar 已提交
803 804 805 806
  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;
807 808 809
  }

  /* bind socket to server address */
wafwerar's avatar
wafwerar 已提交
810 811 812 813
  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;
814 815
  }

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

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

wafwerar's avatar
wafwerar 已提交
827
  return (TdSocketServerPtr)pSocket;
828 829
}

dengyihao's avatar
dengyihao 已提交
830
TdSocketPtr taosAcceptTcpConnectSocket(TdSocketServerPtr pServerSocket, struct sockaddr *destAddr, int *addrLen) {
wafwerar's avatar
wafwerar 已提交
831 832 833 834 835 836 837 838 839
  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 已提交
840
  TdSocketPtr pSocket = (TdSocketPtr)taosMemoryMalloc(sizeof(TdSocket));
wafwerar's avatar
wafwerar 已提交
841 842 843 844 845 846 847 848
  if (pSocket == NULL) {
    taosCloseSocketNoCheck1(fd);
    return NULL;
  }
  pSocket->fd = fd;
  pSocket->refId = 0;
  return pSocket;
}
849 850 851
#define COPY_SIZE 32768
// sendfile shall be used

wafwerar's avatar
wafwerar 已提交
852 853 854 855
int64_t taosCopyFds(TdSocketPtr pSrcSocket, TdSocketPtr pDestSocket, int64_t len) {
  if (pSrcSocket == NULL || pSrcSocket->fd < 0 || pDestSocket == NULL || pDestSocket->fd < 0) {
    return -1;
  }
856 857 858 859 860 861 862 863 864 865 866 867
  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 已提交
868
    int64_t retLen = taosReadMsg(pSrcSocket, temp, (int32_t)readLen);
869
    if (readLen != retLen) {
wafwerar's avatar
wafwerar 已提交
870 871
      // printf("read error, readLen:%" PRId64 " retLen:%" PRId64 " len:%" PRId64 " leftLen:%" PRId64 ", reason:%s",
      //        readLen, retLen, len, leftLen, strerror(errno));
872 873 874
      return -1;
    }

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

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

    leftLen -= readLen;
  }

  return len;
}
888 889

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

uint32_t taosGetIpv4FromFqdn(const char *fqdn) {
wafwerar's avatar
wafwerar 已提交
904 905 906
#ifdef WINDOWS
  // Initialize Winsock
  WSADATA wsaData;
dengyihao's avatar
dengyihao 已提交
907
  int     iResult;
wafwerar's avatar
wafwerar 已提交
908 909
  iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
  if (iResult != 0) {
dengyihao's avatar
dengyihao 已提交
910 911
    // printf("WSAStartup failed: %d\n", iResult);
    return 1;
wafwerar's avatar
wafwerar 已提交
912 913
  }
#endif
914 915 916 917 918 919 920 921
  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 已提交
922
    struct sockaddr    *sa = result->ai_addr;
923 924 925 926 927 928 929 930
    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 已提交
931
      // printf("failed to get the ip address, fqdn:%s, errno:%d, since:%s", fqdn, errno, strerror(errno));
932
    } else {
dengyihao's avatar
dengyihao 已提交
933
      // printf("failed to get the ip address, fqdn:%s, ret:%d, since:%s", fqdn, ret, gai_strerror(ret));
934
    }
935
#else
dengyihao's avatar
dengyihao 已提交
936
    // printf("failed to get the ip address, fqdn:%s, ret:%d, since:%s", fqdn, ret, gai_strerror(ret));
937 938 939 940 941 942
#endif
    return 0xFFFFFFFF;
  }
}

int32_t taosGetFqdn(char *fqdn) {
wafwerar's avatar
wafwerar 已提交
943 944 945 946 947 948 949 950 951 952
#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
953 954 955
  char hostname[1024];
  hostname[1023] = '\0';
  if (gethostname(hostname, 1023) == -1) {
wafwerar's avatar
wafwerar 已提交
956
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
957
    printf("failed to get hostname, reason:%s\n", strerror(WSAGetLastError()));
wafwerar's avatar
wafwerar 已提交
958
#else
wafwerar's avatar
wafwerar 已提交
959
    printf("failed to get hostname, reason:%s\n", strerror(errno));
wafwerar's avatar
wafwerar 已提交
960
#endif
wafwerar's avatar
wafwerar 已提交
961
    assert(0);
962 963 964 965 966 967 968 969 970 971 972
    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 已提交
973
#else   // __APPLE__
974
  hints.ai_flags = AI_CANONNAME;
wafwerar's avatar
wafwerar 已提交
975
#endif  // __APPLE__
976 977
  int32_t ret = getaddrinfo(hostname, NULL, &hints, &result);
  if (!result) {
wafwerar's avatar
wafwerar 已提交
978
    fprintf(stderr, "failed to get fqdn, code:%d, reason:%s\n", ret, gai_strerror(ret));
979 980 981 982 983 984
    return -1;
  }

#ifdef __APPLE__
  // refer to comments above
  strcpy(fqdn, hostname);
wafwerar's avatar
wafwerar 已提交
985
#else   // __APPLE__
986
  strcpy(fqdn, result->ai_canonname);
wafwerar's avatar
wafwerar 已提交
987
#endif  // __APPLE__
988 989 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
  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 已提交
1024
void taosIgnSIGPIPE() { signal(SIGPIPE, SIG_IGN); }
1025 1026

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

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

dengyihao's avatar
dengyihao 已提交
1047 1048 1049 1050
/*
 * Set TCP connection timeout per-socket level.
 * ref [https://github.com/libuv/help/issues/54]
 */
dengyihao's avatar
dengyihao 已提交
1051
int32_t taosCreateSocketWithTimeout(uint32_t timeout) {
dengyihao's avatar
dengyihao 已提交
1052 1053 1054 1055 1056 1057 1058 1059 1060
#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 已提交
1061
  if (0 != setsockopt(fd, IPPROTO_TCP, TCP_MAXRT, (char *)&timeout, sizeof(timeout))) {
dengyihao's avatar
dengyihao 已提交
1062 1063
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
1064 1065 1066 1067 1068
#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))) {
    return -1;
  }
dengyihao's avatar
dengyihao 已提交
1069
#else  // Linux like systems
dengyihao's avatar
dengyihao 已提交
1070
  uint32_t conn_timeout_ms = timeout * 1000;
dengyihao's avatar
dengyihao 已提交
1071 1072 1073 1074 1075 1076
  if (0 != setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, (char *)&conn_timeout_ms, sizeof(conn_timeout_ms))) {
    return -1;
  }
#endif
  return (int)fd;
}