osSocket.c 29.2 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
typedef struct TdSocket {
#if SOCKET_WITH_LOCK
  TdThreadRwlock rwlock;
#endif
  int      refId;
  SocketFd fd;
58
} *TdSocketPtr, TdSocket;
wafwerar's avatar
wafwerar 已提交
59

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;
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
  int     refId;
  EpollFd fd;
74
} *TdEpollPtr, TdEpoll;
S
Shengliang Guan 已提交
75

dengyihao's avatar
dengyihao 已提交
76
#if 0
wafwerar's avatar
wafwerar 已提交
77
int32_t taosSendto(TdSocketPtr pSocket, void *buf, int len, unsigned int flags, const struct sockaddr *dest_addr,
dengyihao's avatar
dengyihao 已提交
78
                   int addrlen) {
wafwerar's avatar
wafwerar 已提交
79 80
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
S
Shengliang Guan 已提交
81
  }
wafwerar's avatar
wafwerar 已提交
82
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
83 84 85 86 87
  return sendto(pSocket->fd, buf, len, flags, dest_addr, addrlen);
#else
  return sendto(pSocket->fd, buf, len, flags, dest_addr, addrlen);
#endif
}
dengyihao's avatar
dengyihao 已提交
88

wafwerar's avatar
wafwerar 已提交
89 90 91
int32_t taosWriteSocket(TdSocketPtr pSocket, void *buf, int len) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
S
Shengliang Guan 已提交
92
  }
wafwerar's avatar
wafwerar 已提交
93
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
94 95 96 97 98 99 100 101 102
  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 已提交
103
  }
wafwerar's avatar
wafwerar 已提交
104
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
105 106 107 108 109 110
  return recv(pSocket->fd, buf, len, 0);
  ;
#else
  return read(pSocket->fd, buf, len);
#endif
}
S
Shengliang Guan 已提交
111

dengyihao's avatar
dengyihao 已提交
112 113
int32_t taosReadFromSocket(TdSocketPtr pSocket, void *buf, int32_t len, int32_t flags, struct sockaddr *destAddr,
                           int *addrLen) {
wafwerar's avatar
wafwerar 已提交
114 115
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
S
Shengliang Guan 已提交
116
  }
wafwerar's avatar
wafwerar 已提交
117 118
  return recvfrom(pSocket->fd, buf, len, flags, destAddr, addrLen);
}
dengyihao's avatar
dengyihao 已提交
119 120
#endif  // endif 0

wafwerar's avatar
wafwerar 已提交
121
int32_t taosCloseSocketNoCheck1(SocketFd fd) {
wafwerar's avatar
wafwerar 已提交
122
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
123 124 125
  return closesocket(fd);
#else
  return close(fd);
S
Shengliang Guan 已提交
126
#endif
wafwerar's avatar
wafwerar 已提交
127
}
dengyihao's avatar
dengyihao 已提交
128

wafwerar's avatar
wafwerar 已提交
129 130 131 132 133 134 135
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 已提交
136
  taosMemoryFree(*ppSocket);
wafwerar's avatar
wafwerar 已提交
137 138
  return code;
}
dengyihao's avatar
dengyihao 已提交
139 140

#if 0
wafwerar's avatar
wafwerar 已提交
141 142 143 144 145 146 147
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 已提交
148
  taosMemoryFree(*ppSocketServer);
wafwerar's avatar
wafwerar 已提交
149 150
  return code;
}
S
Shengliang Guan 已提交
151

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

wafwerar's avatar
wafwerar 已提交
177 178 179
int32_t taosShutDownSocketWR(TdSocketPtr pSocket) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
S
Shengliang Guan 已提交
180
  }
wafwerar's avatar
wafwerar 已提交
181 182 183 184 185 186
#ifdef WINDOWS
  return closesocket(pSocket->fd);
#elif __APPLE__
  return close(pSocket->fd);
#else
  return shutdown(pSocket->fd, SHUT_WR);
S
slguan 已提交
187
#endif
S
Shengliang Guan 已提交
188
}
wafwerar's avatar
wafwerar 已提交
189 190 191 192 193 194 195 196 197 198
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 已提交
199
#endif
wafwerar's avatar
wafwerar 已提交
200 201 202 203
}
int32_t taosShutDownSocketRDWR(TdSocketPtr pSocket) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
S
Shengliang Guan 已提交
204
  }
wafwerar's avatar
wafwerar 已提交
205 206 207 208 209 210 211 212 213 214 215
#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 已提交
216
  }
wafwerar's avatar
wafwerar 已提交
217 218 219 220 221 222 223
#ifdef WINDOWS
  return closesocket(pSocketServer->fd);
#elif __APPLE__
  return close(pSocketServer->fd);
#else
  return shutdown(pSocketServer->fd, SHUT_RDWR);
#endif
224
}
wafwerar's avatar
wafwerar 已提交
225 226 227 228 229

int32_t taosSetNonblocking(TdSocketPtr pSocket, int32_t on) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
230
#ifdef WINDOWS
S
Shengliang Guan 已提交
231 232 233
  u_long mode;
  if (on) {
    mode = 1;
wafwerar's avatar
wafwerar 已提交
234
    ioctlsocket(pSocket->fd, FIONBIO, &mode);
S
Shengliang Guan 已提交
235 236
  } else {
    mode = 0;
wafwerar's avatar
wafwerar 已提交
237 238 239 240 241 242 243
    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 已提交
244
  }
wafwerar's avatar
wafwerar 已提交
245 246 247 248 249 250 251 252 253 254 255

  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 已提交
256 257
  return 0;
}
dengyihao's avatar
dengyihao 已提交
258 259
#endif  // endif 0

wafwerar's avatar
wafwerar 已提交
260 261 262 263
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 已提交
264
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
265
#ifdef TCP_KEEPCNT
S
Shengliang Guan 已提交
266 267 268
  if (level == SOL_SOCKET && optname == TCP_KEEPCNT) {
    return 0;
  }
wafwerar's avatar
wafwerar 已提交
269
#endif
S
Shengliang Guan 已提交
270

wafwerar's avatar
wafwerar 已提交
271
#ifdef TCP_KEEPIDLE
S
Shengliang Guan 已提交
272 273 274
  if (level == SOL_TCP && optname == TCP_KEEPIDLE) {
    return 0;
  }
wafwerar's avatar
wafwerar 已提交
275
#endif
S
Shengliang Guan 已提交
276

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

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

wafwerar's avatar
wafwerar 已提交
289 290
  return setsockopt(pSocket->fd, level, optname, optval, optlen);
#else
wafwerar's avatar
wafwerar 已提交
291
  return setsockopt(pSocket->fd, level, optname, optval, (int)optlen);
wafwerar's avatar
wafwerar 已提交
292 293
#endif
}
dengyihao's avatar
dengyihao 已提交
294 295

#if 0
wafwerar's avatar
wafwerar 已提交
296 297 298 299
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 已提交
300
#ifdef WINDOWS
301
  assert(0);
wafwerar's avatar
wafwerar 已提交
302 303
  return 0;
#else
wafwerar's avatar
wafwerar 已提交
304
  return getsockopt(pSocket->fd, level, optname, optval, (int *)optlen);
wafwerar's avatar
wafwerar 已提交
305
#endif
S
Shengliang Guan 已提交
306
}
dengyihao's avatar
dengyihao 已提交
307 308 309

#endif

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

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

  nleft = nbytes;

  while (nleft > 0) {
wafwerar's avatar
wafwerar 已提交
344
    nwritten = taosWriteSocket(pSocket, (char *)ptr, (size_t)nleft);
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
    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 已提交
363 364 365 366
int32_t taosReadMsg(TdSocketPtr pSocket, void *buf, int32_t nbytes) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
367
  int32_t nleft, nread;
dengyihao's avatar
dengyihao 已提交
368
  char   *ptr = (char *)buf;
369 370 371 372

  nleft = nbytes;

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

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

  return (nbytes - nleft);
}

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

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

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

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

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

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

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

    nleft -= nwritten;
    ptr += nwritten;
  }

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

  return (nbytes - nleft);
}

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

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

  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 已提交
452 453 454 455
  if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) <= 2) {
    // printf("failed to open udp socket: %d (%s)", errno, strerror(errno));
    taosCloseSocketNoCheck1(fd);
    return NULL;
456 457
  }

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

wafwerar's avatar
wafwerar 已提交
466 467 468 469 470 471 472 473 474 475
  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;
476 477 478
  }

  /* bind socket to local address */
wafwerar's avatar
wafwerar 已提交
479 480 481 482
  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;
483 484
  }

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

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

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

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

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

510 511
  /* set REUSEADDR option, so the portnumber can be re-used */
  int32_t reuse = 1;
wafwerar's avatar
wafwerar 已提交
512 513 514 515
  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;
516 517
  }

wafwerar's avatar
wafwerar 已提交
518 519 520 521
  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;
522 523
  }

wafwerar's avatar
wafwerar 已提交
524 525 526 527
  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;
528 529 530 531 532 533 534 535 536
  }

  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 已提交
537 538 539 540 541
    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;
542 543 544 545 546 547 548 549
    }
  }

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

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

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

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

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

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

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

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

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

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

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

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

  return 0;
}

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

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

#if 0
wafwerar's avatar
wafwerar 已提交
781
TdSocketServerPtr taosOpenTcpServerSocket(uint32_t ip, uint16_t port) {
782
  struct sockaddr_in serverAdd;
wafwerar's avatar
wafwerar 已提交
783
  SocketFd           fd;
784 785
  int32_t            reuse;

wafwerar's avatar
wafwerar 已提交
786
  // printf("open tcp server socket:0x%x:%hu", ip, port);
787 788 789 790 791 792

  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 已提交
793 794 795 796 797 798
  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 已提交
799
  TdSocketPtr pSocket = (TdSocketPtr)taosMemoryMalloc(sizeof(TdSocket));
wafwerar's avatar
wafwerar 已提交
800 801 802
  if (pSocket == NULL) {
    taosCloseSocketNoCheck1(fd);
    return NULL;
803
  }
wafwerar's avatar
wafwerar 已提交
804 805
  pSocket->refId = 0;
  pSocket->fd = fd;
806 807 808

  /* set REUSEADDR option, so the portnumber can be re-used */
  reuse = 1;
wafwerar's avatar
wafwerar 已提交
809 810 811 812
  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;
813 814 815
  }

  /* bind socket to server address */
wafwerar's avatar
wafwerar 已提交
816 817 818 819
  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;
820 821
  }

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

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

wafwerar's avatar
wafwerar 已提交
833
  return (TdSocketServerPtr)pSocket;
834 835
}

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

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

wafwerar's avatar
wafwerar 已提交
881
    writeLen = taosWriteMsg(pDestSocket, temp, (int32_t)readLen);
882 883

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

    leftLen -= readLen;
  }

  return len;
}
894

dengyihao's avatar
dengyihao 已提交
895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924
// 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);
}

#endif  // endif 0

925
void taosBlockSIGPIPE() {
wafwerar's avatar
wafwerar 已提交
926
#ifdef WINDOWS
927
  // assert(0);
928
#else
929 930 931
  sigset_t signal_mask;
  sigemptyset(&signal_mask);
  sigaddset(&signal_mask, SIGPIPE);
wafwerar's avatar
wafwerar 已提交
932
  int32_t rc = pthread_sigmask(SIG_BLOCK, &signal_mask, NULL);
933
  if (rc != 0) {
wafwerar's avatar
wafwerar 已提交
934
    // printf("failed to block SIGPIPE");
935
  }
936
#endif
937
}
938 939

uint32_t taosGetIpv4FromFqdn(const char *fqdn) {
wafwerar's avatar
wafwerar 已提交
940 941 942
#ifdef WINDOWS
  // Initialize Winsock
  WSADATA wsaData;
dengyihao's avatar
dengyihao 已提交
943
  int     iResult;
wafwerar's avatar
wafwerar 已提交
944 945
  iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
  if (iResult != 0) {
dengyihao's avatar
dengyihao 已提交
946
    // printf("WSAStartup failed: %d\n", iResult);
947
    return 0xFFFFFFFF;
wafwerar's avatar
wafwerar 已提交
948 949
  }
#endif
950 951 952 953 954 955 956 957
  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 已提交
958
    struct sockaddr    *sa = result->ai_addr;
959 960 961 962 963 964 965 966
    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 已提交
967
      // printf("failed to get the ip address, fqdn:%s, errno:%d, since:%s", fqdn, errno, strerror(errno));
968
    } else {
dengyihao's avatar
dengyihao 已提交
969
      // printf("failed to get the ip address, fqdn:%s, ret:%d, since:%s", fqdn, ret, gai_strerror(ret));
970
    }
971
#else
dengyihao's avatar
dengyihao 已提交
972
    // printf("failed to get the ip address, fqdn:%s, ret:%d, since:%s", fqdn, ret, gai_strerror(ret));
973 974 975 976 977 978
#endif
    return 0xFFFFFFFF;
  }
}

int32_t taosGetFqdn(char *fqdn) {
wafwerar's avatar
wafwerar 已提交
979 980 981 982 983 984 985 986 987 988
#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
989 990
  char hostname[1024];
  hostname[1023] = '\0';
991
  if (taosGetlocalhostname(hostname, 1023) == -1) {
wafwerar's avatar
wafwerar 已提交
992
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
993
    printf("failed to get hostname, reason:%s\n", strerror(WSAGetLastError()));
wafwerar's avatar
wafwerar 已提交
994
#else
wafwerar's avatar
wafwerar 已提交
995
    printf("failed to get hostname, reason:%s\n", strerror(errno));
wafwerar's avatar
wafwerar 已提交
996
#endif
wafwerar's avatar
wafwerar 已提交
997
    assert(0);
998 999 1000 1001 1002 1003 1004 1005
    return -1;
  }

#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
1006 1007
  // hints.ai_family = AF_INET;
  strcpy(fqdn, hostname);
1008
  strcpy(fqdn + strlen(hostname), ".local");
wafwerar's avatar
wafwerar 已提交
1009
#else   // __APPLE__
1010 1011
  struct addrinfo  hints = {0};
  struct addrinfo *result = NULL;
1012
  hints.ai_flags = AI_CANONNAME;
1013

1014 1015
  int32_t ret = getaddrinfo(hostname, NULL, &hints, &result);
  if (!result) {
wafwerar's avatar
wafwerar 已提交
1016
    fprintf(stderr, "failed to get fqdn, code:%d, reason:%s\n", ret, gai_strerror(ret));
1017 1018 1019 1020
    return -1;
  }
  strcpy(fqdn, result->ai_canonname);
  freeaddrinfo(result);
1021 1022
#endif  // __APPLE__

1023 1024 1025 1026 1027 1028 1029
  return 0;
}

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 已提交
1030
void taosIgnSIGPIPE() { signal(SIGPIPE, SIG_IGN); }
1031 1032

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

dengyihao's avatar
dengyihao 已提交
1046
#if 0
wafwerar's avatar
wafwerar 已提交
1047
int32_t taosGetSocketName(TdSocketPtr pSocket, struct sockaddr *destAddr, int *addrLen) {
wafwerar's avatar
wafwerar 已提交
1048 1049 1050 1051 1052
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
  return getsockname(pSocket->fd, destAddr, addrLen);
}
dengyihao's avatar
dengyihao 已提交
1053
#endif  // endif 0
wafwerar's avatar
wafwerar 已提交
1054

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

dengyihao's avatar
dengyihao 已提交
1088 1089
  return (int)fd;
}
dengyihao's avatar
dengyihao 已提交
1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102

void taosWinSocketInit() {
#ifdef WINDOWS
  static char flag = 0;
  if (flag == 0) {
    WORD    wVersionRequested;
    WSADATA wsaData;
    wVersionRequested = MAKEWORD(1, 1);
    if (WSAStartup(wVersionRequested, &wsaData) == 0) {
      flag = 1;
    }
  }
#else
dengyihao's avatar
dengyihao 已提交
1103
#endif
dengyihao's avatar
dengyihao 已提交
1104
}
dengyihao's avatar
dengyihao 已提交
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131

uint64_t taosHton64(uint64_t val) {
#if defined(WINDOWS) || defined(DARWIN)
  return ((val & 0x00000000000000ff) << 7 * 8) | ((val & 0x000000000000ff00) << 5 * 8) |
         ((val & 0x0000000000ff0000) << 3 * 8) | ((val & 0x00000000ff000000) << 1 * 8) |
         ((val & 0x000000ff00000000) >> 1 * 8) | ((val & 0x0000ff0000000000) >> 3 * 8) |
         ((val & 0x00ff000000000000) >> 5 * 8) | ((val & 0xff00000000000000) >> 7 * 8);
#else
  if (__BYTE_ORDER == __LITTLE_ENDIAN) {
    return (((uint64_t)htonl((int)((val << 32) >> 32))) << 32) | (unsigned int)htonl((int)(val >> 32));
  } else if (__BYTE_ORDER == __BIG_ENDIAN) {
    return val;
  }
#endif
}

uint64_t taosNtoh64(uint64_t val) {
#if defined(WINDOWS) || defined(DARWIN)
  return taosHton64(val);
#else
  if (__BYTE_ORDER == __LITTLE_ENDIAN) {
    return (((uint64_t)htonl((int)((val << 32) >> 32))) << 32) | (unsigned int)htonl((int)(val >> 32));
  } else if (__BYTE_ORDER == __BIG_ENDIAN) {
    return val;
  }
#endif
}