osSocket.c 25.4 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 28 29 30
#include <IPHlpApi.h>
#include <WS2tcpip.h>
#include <Winsock2.h>
#include <stdio.h>
#include <string.h>
#include <tchar.h>
#include <winbase.h>
#include <winsock2.h>
#include <ws2def.h>
#include "winsock2.h"
S
Shengliang Guan 已提交
31
#else
wafwerar's avatar
wafwerar 已提交
32 33 34 35 36 37 38 39 40
#include <arpa/inet.h>
#include <fcntl.h>
#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>
41 42 43 44 45 46 47

#if defined(DARWIN)
  #include <dispatch/dispatch.h>
  #include "osEok.h"
#else
  #include <sys/epoll.h>
#endif
S
Shengliang Guan 已提交
48 49
#endif

wafwerar's avatar
wafwerar 已提交
50 51
typedef struct TdSocketServer {
#if SOCKET_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
52
  TdThreadRwlock rwlock;
wafwerar's avatar
wafwerar 已提交
53 54 55 56
#endif
  int      refId;
  SocketFd fd;
} *TdSocketServerPtr, TdSocketServer;
S
Shengliang Guan 已提交
57

wafwerar's avatar
wafwerar 已提交
58 59
typedef struct TdEpoll {
#if SOCKET_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
60
  TdThreadRwlock rwlock;
wafwerar's avatar
wafwerar 已提交
61 62 63 64
#endif
  int      refId;
  EpollFd  fd;
} *TdEpollPtr, TdEpoll;
S
Shengliang Guan 已提交
65

wafwerar's avatar
wafwerar 已提交
66 67 68 69
int32_t taosSendto(TdSocketPtr pSocket, void *buf, int len, unsigned int flags, const struct sockaddr *dest_addr,
                    int addrlen) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
S
Shengliang Guan 已提交
70
  }
wafwerar's avatar
wafwerar 已提交
71 72 73 74 75 76 77 78 79
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  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 已提交
80
  }
wafwerar's avatar
wafwerar 已提交
81 82 83 84 85 86 87 88 89 90
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  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 已提交
91
  }
wafwerar's avatar
wafwerar 已提交
92 93 94 95 96 97 98
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  return recv(pSocket->fd, buf, len, 0);
  ;
#else
  return read(pSocket->fd, buf, len);
#endif
}
S
Shengliang Guan 已提交
99

wafwerar's avatar
wafwerar 已提交
100 101 102
int32_t taosReadFromSocket(TdSocketPtr pSocket, void *buf, int32_t len, int32_t flags, struct sockaddr *destAddr, socklen_t *addrLen) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
S
Shengliang Guan 已提交
103
  }
wafwerar's avatar
wafwerar 已提交
104 105 106 107 108 109 110
  return recvfrom(pSocket->fd, buf, len, flags, destAddr, addrLen);
}
int32_t taosCloseSocketNoCheck1(SocketFd fd) {
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  return closesocket(fd);
#else
  return close(fd);
S
Shengliang Guan 已提交
111
#endif
wafwerar's avatar
wafwerar 已提交
112 113 114 115 116 117 118 119
}
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 已提交
120
  taosMemoryFree(*ppSocket);
wafwerar's avatar
wafwerar 已提交
121 122 123 124 125 126 127 128 129
  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 已提交
130
  taosMemoryFree(*ppSocketServer);
wafwerar's avatar
wafwerar 已提交
131 132
  return code;
}
S
Shengliang Guan 已提交
133

wafwerar's avatar
wafwerar 已提交
134 135 136 137
int32_t taosShutDownSocketRD(TdSocketPtr pSocket) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
S
Shengliang Guan 已提交
138
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
139
  return closesocket(pSocket->fd);
S
Shengliang Guan 已提交
140
#elif __APPLE__
wafwerar's avatar
wafwerar 已提交
141
  return close(pSocket->fd);
S
Shengliang Guan 已提交
142
#else
wafwerar's avatar
wafwerar 已提交
143
  return shutdown(pSocket->fd, SHUT_RD);
S
Shengliang Guan 已提交
144 145
#endif
}
wafwerar's avatar
wafwerar 已提交
146 147 148 149
int32_t taosShutDownSocketServerRD(TdSocketServerPtr pSocketServer) {
  if (pSocketServer == NULL || pSocketServer->fd < 0) {
    return -1;
  }
S
Shengliang Guan 已提交
150
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
151
  return closesocket(pSocketServer->fd);
S
Shengliang Guan 已提交
152
#elif __APPLE__
wafwerar's avatar
wafwerar 已提交
153
  return close(pSocketServer->fd);
S
Shengliang Guan 已提交
154
#else
wafwerar's avatar
wafwerar 已提交
155
  return shutdown(pSocketServer->fd, SHUT_RD);
S
Shengliang Guan 已提交
156 157
#endif
}
S
Shengliang Guan 已提交
158

wafwerar's avatar
wafwerar 已提交
159 160 161
int32_t taosShutDownSocketWR(TdSocketPtr pSocket) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
S
Shengliang Guan 已提交
162
  }
wafwerar's avatar
wafwerar 已提交
163 164 165 166 167 168
#ifdef WINDOWS
  return closesocket(pSocket->fd);
#elif __APPLE__
  return close(pSocket->fd);
#else
  return shutdown(pSocket->fd, SHUT_WR);
S
slguan 已提交
169
#endif
S
Shengliang Guan 已提交
170
}
wafwerar's avatar
wafwerar 已提交
171 172 173 174 175 176 177 178 179 180
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 已提交
181
#endif
wafwerar's avatar
wafwerar 已提交
182 183 184 185
}
int32_t taosShutDownSocketRDWR(TdSocketPtr pSocket) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
S
Shengliang Guan 已提交
186
  }
wafwerar's avatar
wafwerar 已提交
187 188 189 190 191 192 193 194 195 196 197
#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 已提交
198
  }
wafwerar's avatar
wafwerar 已提交
199 200 201 202 203 204 205
#ifdef WINDOWS
  return closesocket(pSocketServer->fd);
#elif __APPLE__
  return close(pSocketServer->fd);
#else
  return shutdown(pSocketServer->fd, SHUT_RDWR);
#endif
206
}
wafwerar's avatar
wafwerar 已提交
207 208

void taosWinSocketInit1() {
S
Shengliang Guan 已提交
209 210 211 212 213 214 215 216 217 218
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  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 已提交
219 220
#else
#endif
221
}
wafwerar's avatar
wafwerar 已提交
222 223 224 225 226
int32_t taosSetNonblocking(TdSocketPtr pSocket, int32_t on) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
S
Shengliang Guan 已提交
227 228 229
  u_long mode;
  if (on) {
    mode = 1;
wafwerar's avatar
wafwerar 已提交
230
    ioctlsocket(pSocket->fd, FIONBIO, &mode);
S
Shengliang Guan 已提交
231 232
  } else {
    mode = 0;
wafwerar's avatar
wafwerar 已提交
233 234 235 236 237 238 239
    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 已提交
240
  }
wafwerar's avatar
wafwerar 已提交
241 242 243 244 245 246 247 248 249 250 251

  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 已提交
252 253
  return 0;
}
wafwerar's avatar
wafwerar 已提交
254 255 256 257 258
int32_t taosSetSockOpt(TdSocketPtr pSocket, int32_t level, int32_t optname, void *optval, int32_t optlen) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
S
Shengliang Guan 已提交
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
  if (level == SOL_SOCKET && optname == TCP_KEEPCNT) {
    return 0;
  }

  if (level == SOL_TCP && optname == TCP_KEEPIDLE) {
    return 0;
  }

  if (level == SOL_TCP && optname == TCP_KEEPINTVL) {
    return 0;
  }

  if (level == SOL_TCP && optname == TCP_KEEPCNT) {
    return 0;
  }

wafwerar's avatar
wafwerar 已提交
275 276 277 278 279 280 281 282 283 284 285 286 287 288
  return setsockopt(pSocket->fd, level, optname, optval, optlen);
#else
  return setsockopt(pSocket->fd, level, optname, optval, (socklen_t)optlen);
#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;
  }
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  return 0;
#else
  return getsockopt(pSocket->fd, level, optname, optval, (socklen_t *)optlen);
#endif
S
Shengliang Guan 已提交
289
}
S
config  
Shengliang Guan 已提交
290
uint32_t taosInetAddr(const char *ipAddr) {
wafwerar's avatar
wafwerar 已提交
291
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
S
Shengliang Guan 已提交
292 293 294 295 296 297 298
  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 已提交
299 300 301
#else
  return inet_addr(ipAddr);
#endif
S
Shengliang Guan 已提交
302
}
S
Shengliang Guan 已提交
303
const char *taosInetNtoa(struct in_addr ipInt) {
wafwerar's avatar
wafwerar 已提交
304
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
S
Shengliang Guan 已提交
305 306 307
  // not thread safe, only for debug usage while print log
  static char tmpDstStr[16];
  return inet_ntop(AF_INET, &ipInt, tmpDstStr, INET6_ADDRSTRLEN);
wafwerar's avatar
wafwerar 已提交
308 309
#else
  return inet_ntoa(ipInt);
310
#endif
wafwerar's avatar
wafwerar 已提交
311
}
312 313

#ifndef SIGPIPE
wafwerar's avatar
wafwerar 已提交
314
#define SIGPIPE EPIPE
315 316 317 318
#endif

#define TCP_CONN_TIMEOUT 3000  // conn timeout

wafwerar's avatar
wafwerar 已提交
319 320 321 322
int32_t taosWriteMsg(TdSocketPtr pSocket, void *buf, int32_t nbytes) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
323
  int32_t nleft, nwritten;
wafwerar's avatar
wafwerar 已提交
324
  char   *ptr = (char *)buf;
325 326 327 328

  nleft = nbytes;

  while (nleft > 0) {
wafwerar's avatar
wafwerar 已提交
329
    nwritten = taosWriteSocket(pSocket, (char *)ptr, (size_t)nleft);
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
    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 已提交
348 349 350 351
int32_t taosReadMsg(TdSocketPtr pSocket, void *buf, int32_t nbytes) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
352
  int32_t nleft, nread;
wafwerar's avatar
wafwerar 已提交
353
  char   *ptr = (char *)buf;
354 355 356 357

  nleft = nbytes;

  while (nleft > 0) {
wafwerar's avatar
wafwerar 已提交
358
    nread = taosReadSocket(pSocket, ptr, (size_t)nleft);
359 360 361
    if (nread == 0) {
      break;
    } else if (nread < 0) {
wafwerar's avatar
wafwerar 已提交
362
      if (errno == EINTR /* || errno == EAGAIN || errno == EWOULDBLOCK*/) {
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
        continue;
      } else {
        return -1;
      }
    } else {
      nleft -= nread;
      ptr += nread;
    }

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

  return (nbytes - nleft);
}

wafwerar's avatar
wafwerar 已提交
380 381 382 383 384
int32_t taosNonblockwrite(TdSocketPtr pSocket, char *ptr, int32_t nbytes) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
  taosSetNonblocking(pSocket, 1);
385

wafwerar's avatar
wafwerar 已提交
386 387
  int32_t        nleft, nwritten, nready;
  fd_set         fset;
388 389 390 391 392 393 394
  struct timeval tv;

  nleft = nbytes;
  while (nleft > 0) {
    tv.tv_sec = 30;
    tv.tv_usec = 0;
    FD_ZERO(&fset);
wafwerar's avatar
wafwerar 已提交
395 396
    FD_SET(pSocket->fd, &fset);
    if ((nready = select((SocketFd)(pSocket->fd + 1), NULL, &fset, NULL, &tv)) == 0) {
397
      errno = ETIMEDOUT;
wafwerar's avatar
wafwerar 已提交
398
      // printf("fd %d timeout, no enough space to write", fd);
399 400 401 402 403
      break;

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

wafwerar's avatar
wafwerar 已提交
404
      // printf("select error, %d (%s)", errno, strerror(errno));
405 406 407
      return -1;
    }

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

wafwerar's avatar
wafwerar 已提交
412
      // printf("write error, %d (%s)", errno, strerror(errno));
413 414 415 416 417 418 419
      return -1;
    }

    nleft -= nwritten;
    ptr += nwritten;
  }

wafwerar's avatar
wafwerar 已提交
420
  taosSetNonblocking(pSocket, 0);
421 422 423 424

  return (nbytes - nleft);
}

wafwerar's avatar
wafwerar 已提交
425
TdSocketPtr taosOpenUdpSocket(uint32_t ip, uint16_t port) {
426
  struct sockaddr_in localAddr;
wafwerar's avatar
wafwerar 已提交
427 428
  SocketFd           fd;
  int32_t            bufSize = 1024000;
429

wafwerar's avatar
wafwerar 已提交
430
  // printf("open udp socket:0x%x:%hu", ip, port);
431 432 433 434 435 436

  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 已提交
437 438 439 440
  if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) <= 2) {
    // printf("failed to open udp socket: %d (%s)", errno, strerror(errno));
    taosCloseSocketNoCheck1(fd);
    return NULL;
441 442
  }

wafwerar's avatar
wafwerar 已提交
443
  TdSocketPtr pSocket = (TdSocketPtr)taosMemoryMalloc(sizeof(TdSocket));
wafwerar's avatar
wafwerar 已提交
444 445 446
  if (pSocket == NULL) {
    taosCloseSocketNoCheck1(fd);
    return NULL;
447
  }
wafwerar's avatar
wafwerar 已提交
448 449
  pSocket->fd = fd;
  pSocket->refId = 0;
450

wafwerar's avatar
wafwerar 已提交
451 452 453 454 455 456 457 458 459 460
  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;
461 462 463
  }

  /* bind socket to local address */
wafwerar's avatar
wafwerar 已提交
464 465 466 467
  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;
468 469
  }

wafwerar's avatar
wafwerar 已提交
470
  return pSocket;
471 472
}

wafwerar's avatar
wafwerar 已提交
473 474 475
TdSocketPtr taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientIp) {
  SocketFd           fd = -1;
  int32_t            ret;
476
  struct sockaddr_in serverAddr, clientAddr;
wafwerar's avatar
wafwerar 已提交
477
  int32_t            bufSize = 1024 * 1024;
478

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

wafwerar's avatar
wafwerar 已提交
481 482 483 484
  if (fd <= 2) {
    // printf("failed to open the socket: %d (%s)", errno, strerror(errno));
    if (fd >= 0) taosCloseSocketNoCheck1(fd);
    return NULL;
485 486
  }

wafwerar's avatar
wafwerar 已提交
487
  TdSocketPtr pSocket = (TdSocketPtr)taosMemoryMalloc(sizeof(TdSocket));
wafwerar's avatar
wafwerar 已提交
488 489 490 491 492 493 494
  if (pSocket == NULL) {
    taosCloseSocketNoCheck1(fd);
    return NULL;
  }
  pSocket->fd = fd;
  pSocket->refId = 0;

495 496
  /* set REUSEADDR option, so the portnumber can be re-used */
  int32_t reuse = 1;
wafwerar's avatar
wafwerar 已提交
497 498 499 500
  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;
501 502
  }

wafwerar's avatar
wafwerar 已提交
503 504 505 506
  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;
507 508
  }

wafwerar's avatar
wafwerar 已提交
509 510 511 512
  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;
513 514 515 516 517 518 519 520 521
  }

  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 已提交
522 523 524 525 526
    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;
527 528 529 530 531 532 533 534
    }
  }

  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 已提交
535 536 537
#ifdef _TD_LINUX
  taosSetNonblocking(pSocket, 1);
  ret = connect(pSocket->fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
538 539
  if (ret == -1) {
    if (errno == EHOSTUNREACH) {
wafwerar's avatar
wafwerar 已提交
540 541 542
      // printf("failed to connect socket, ip:0x%x, port:%hu(%s)", destIp, destPort, strerror(errno));
      taosCloseSocket(&pSocket);
      return -1;
543
    } else if (errno == EINPROGRESS || errno == EAGAIN || errno == EWOULDBLOCK) {
wafwerar's avatar
wafwerar 已提交
544
      struct pollfd wfd[1];
545

wafwerar's avatar
wafwerar 已提交
546
      wfd[0].fd = pSocket->fd;
547
      wfd[0].events = POLLOUT;
wafwerar's avatar
wafwerar 已提交
548

549 550
      int res = poll(wfd, 1, TCP_CONN_TIMEOUT);
      if (res == -1 || res == 0) {
wafwerar's avatar
wafwerar 已提交
551 552
        // printf("failed to connect socket, ip:0x%x, port:%hu(poll error/conn timeout)", destIp, destPort);
        taosCloseSocket(&pSocket);  //
553 554
        return -1;
      }
wafwerar's avatar
wafwerar 已提交
555 556 557 558
      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);  //
559 560 561
        return -1;
      }
      ret = 0;
wafwerar's avatar
wafwerar 已提交
562 563 564 565 566
    } else {  // Other error
      // printf("failed to connect socket, ip:0x%x, port:%hu(target host cannot be reached)", destIp, destPort);
      taosCloseSocket(&pSocket);  //
      return -1;
    }
567
  }
wafwerar's avatar
wafwerar 已提交
568
  taosSetNonblocking(pSocket, 0);
569 570

#else
wafwerar's avatar
wafwerar 已提交
571
  ret = connect(pSocket->fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
572 573 574
#endif

  if (ret != 0) {
wafwerar's avatar
wafwerar 已提交
575 576 577
    // printf("failed to connect socket, ip:0x%x, port:%hu(%s)", destIp, destPort, strerror(errno));
    taosCloseSocket(&pSocket);
    return NULL;
578
  } else {
wafwerar's avatar
wafwerar 已提交
579
    taosKeepTcpAlive(pSocket);
580 581
  }

wafwerar's avatar
wafwerar 已提交
582
  return pSocket;
583 584
}

wafwerar's avatar
wafwerar 已提交
585 586 587 588
int32_t taosKeepTcpAlive(TdSocketPtr pSocket) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
589
  int32_t alive = 1;
wafwerar's avatar
wafwerar 已提交
590 591 592
  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);
593 594 595 596 597 598
    return -1;
  }

#ifndef __APPLE__
  // all fails on macosx
  int32_t probes = 3;
wafwerar's avatar
wafwerar 已提交
599 600 601
  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);
602 603 604 605
    return -1;
  }

  int32_t alivetime = 10;
wafwerar's avatar
wafwerar 已提交
606 607 608
  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);
609 610 611 612
    return -1;
  }

  int32_t interval = 3;
wafwerar's avatar
wafwerar 已提交
613 614 615
  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);
616 617
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
618
#endif  // __APPLE__
619 620

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

  struct linger linger = {0};
  linger.l_onoff = 1;
  linger.l_linger = 3;
wafwerar's avatar
wafwerar 已提交
630 631 632
  if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger)) < 0) {
    // printf("setsockopt SO_LINGER failed: %d (%s)", errno, strerror(errno));
    taosCloseSocket(&pSocket);
633 634 635 636 637 638
    return -1;
  }

  return 0;
}

wafwerar's avatar
wafwerar 已提交
639
TdSocketServerPtr taosOpenTcpServerSocket(uint32_t ip, uint16_t port) {
640
  struct sockaddr_in serverAdd;
wafwerar's avatar
wafwerar 已提交
641
  SocketFd           fd;
642 643
  int32_t            reuse;

wafwerar's avatar
wafwerar 已提交
644
  // printf("open tcp server socket:0x%x:%hu", ip, port);
645 646 647 648 649 650

  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 已提交
651 652 653 654 655 656
  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 已提交
657
  TdSocketPtr pSocket = (TdSocketPtr)taosMemoryMalloc(sizeof(TdSocket));
wafwerar's avatar
wafwerar 已提交
658 659 660
  if (pSocket == NULL) {
    taosCloseSocketNoCheck1(fd);
    return NULL;
661
  }
wafwerar's avatar
wafwerar 已提交
662 663
  pSocket->refId = 0;
  pSocket->fd = fd;
664 665 666

  /* set REUSEADDR option, so the portnumber can be re-used */
  reuse = 1;
wafwerar's avatar
wafwerar 已提交
667 668 669 670
  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;
671 672 673
  }

  /* bind socket to server address */
wafwerar's avatar
wafwerar 已提交
674 675 676 677
  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;
678 679
  }

wafwerar's avatar
wafwerar 已提交
680 681 682 683
  if (taosKeepTcpAlive(pSocket) < 0) {
    // printf("failed to set tcp server keep-alive option, 0x%x:%hu(%s)", ip, port, strerror(errno));
    taosCloseSocket(&pSocket);
    return NULL;
684 685
  }

wafwerar's avatar
wafwerar 已提交
686 687 688 689
  if (listen(pSocket->fd, 1024) < 0) {
    // printf("listen tcp server socket failed, 0x%x:%hu(%s)", ip, port, strerror(errno));
    taosCloseSocket(&pSocket);
    return NULL;
690 691
  }

wafwerar's avatar
wafwerar 已提交
692
  return (TdSocketServerPtr)pSocket;
693 694
}

wafwerar's avatar
wafwerar 已提交
695 696 697 698 699 700 701 702 703 704 705
TdSocketPtr taosAcceptTcpConnectSocket(TdSocketServerPtr pServerSocket, struct sockaddr *destAddr,
                                       socklen_t *addrLen) {
  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 已提交
706
  TdSocketPtr pSocket = (TdSocketPtr)taosMemoryMalloc(sizeof(TdSocket));
wafwerar's avatar
wafwerar 已提交
707 708 709 710 711 712 713 714
  if (pSocket == NULL) {
    taosCloseSocketNoCheck1(fd);
    return NULL;
  }
  pSocket->fd = fd;
  pSocket->refId = 0;
  return pSocket;
}
715 716 717
#define COPY_SIZE 32768
// sendfile shall be used

wafwerar's avatar
wafwerar 已提交
718 719 720 721
int64_t taosCopyFds(TdSocketPtr pSrcSocket, TdSocketPtr pDestSocket, int64_t len) {
  if (pSrcSocket == NULL || pSrcSocket->fd < 0 || pDestSocket == NULL || pDestSocket->fd < 0) {
    return -1;
  }
722 723 724 725 726 727 728 729 730 731 732 733
  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 已提交
734
    int64_t retLen = taosReadMsg(pSrcSocket, temp, (int32_t)readLen);
735
    if (readLen != retLen) {
wafwerar's avatar
wafwerar 已提交
736 737
      // printf("read error, readLen:%" PRId64 " retLen:%" PRId64 " len:%" PRId64 " leftLen:%" PRId64 ", reason:%s",
      //        readLen, retLen, len, leftLen, strerror(errno));
738 739 740
      return -1;
    }

wafwerar's avatar
wafwerar 已提交
741
    writeLen = taosWriteMsg(pDestSocket, temp, (int32_t)readLen);
742 743

    if (readLen != writeLen) {
wafwerar's avatar
wafwerar 已提交
744 745
      // printf("copy error, readLen:%" PRId64 " writeLen:%" PRId64 " len:%" PRId64 " leftLen:%" PRId64 ", reason:%s",
      //        readLen, writeLen, len, leftLen, strerror(errno));
746 747 748 749 750 751 752 753
      return -1;
    }

    leftLen -= readLen;
  }

  return len;
}
754 755

void taosBlockSIGPIPE() {
756 757
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
#else
758 759 760
  sigset_t signal_mask;
  sigemptyset(&signal_mask);
  sigaddset(&signal_mask, SIGPIPE);
wafwerar's avatar
wafwerar 已提交
761
  int32_t rc = taosThreadSigMask(SIG_BLOCK, &signal_mask, NULL);
762
  if (rc != 0) {
wafwerar's avatar
wafwerar 已提交
763
    // printf("failed to block SIGPIPE");
764
  }
765
#endif
766
}
767 768 769 770 771 772 773 774 775 776

uint32_t taosGetIpv4FromFqdn(const char *fqdn) {
  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) {
wafwerar's avatar
wafwerar 已提交
777
    struct sockaddr    *sa = result->ai_addr;
778 779 780 781 782 783 784 785
    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) {
wafwerar's avatar
wafwerar 已提交
786
      // printf("failed to get the ip address, fqdn:%s, since:%s", fqdn, strerror(errno));
787
    } else {
wafwerar's avatar
wafwerar 已提交
788
      // printf("failed to get the ip address, fqdn:%s, since:%s", fqdn, gai_strerror(ret));
789
    }
790
#else
wafwerar's avatar
wafwerar 已提交
791
    // printf("failed to get the ip address, fqdn:%s, since:%s", fqdn, gai_strerror(ret));
792 793 794 795 796 797 798 799 800
#endif
    return 0xFFFFFFFF;
  }
}

int32_t taosGetFqdn(char *fqdn) {
  char hostname[1024];
  hostname[1023] = '\0';
  if (gethostname(hostname, 1023) == -1) {
wafwerar's avatar
wafwerar 已提交
801
    printf("failed to get hostname, reason:%s", strerror(errno));
wafwerar's avatar
wafwerar 已提交
802
    assert(0);
803 804 805 806 807 808 809 810 811 812 813
    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 已提交
814
#else   // __APPLE__
815
  hints.ai_flags = AI_CANONNAME;
wafwerar's avatar
wafwerar 已提交
816
#endif  // __APPLE__
817 818
  int32_t ret = getaddrinfo(hostname, NULL, &hints, &result);
  if (!result) {
wafwerar's avatar
wafwerar 已提交
819
    printf("failed to get fqdn, code:%d, reason:%s", ret, gai_strerror(ret));
wafwerar's avatar
wafwerar 已提交
820
    assert(0);
821 822 823 824 825 826
    return -1;
  }

#ifdef __APPLE__
  // refer to comments above
  strcpy(fqdn, hostname);
wafwerar's avatar
wafwerar 已提交
827
#else   // __APPLE__
828
  strcpy(fqdn, result->ai_canonname);
wafwerar's avatar
wafwerar 已提交
829
#endif  // __APPLE__
830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878
  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);
}

void taosIgnSIGPIPE() {
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
#else
  signal(SIGPIPE, SIG_IGN);
#endif
}

void taosSetMaskSIGPIPE() {
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
#else
  sigset_t signal_mask;
  sigemptyset(&signal_mask);
  sigaddset(&signal_mask, SIGPIPE);
wafwerar's avatar
wafwerar 已提交
879
  int32_t rc = taosThreadSigMask(SIG_SETMASK, &signal_mask, NULL);
880
  if (rc != 0) {
wafwerar's avatar
wafwerar 已提交
881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903
    // printf("failed to setmask SIGPIPE");
  }
#endif
}

int32_t taosGetSocketName(TdSocketPtr pSocket, struct sockaddr *destAddr, socklen_t *addrLen) {
  if (pSocket == NULL || pSocket->fd < 0) {
    return -1;
  }
  return getsockname(pSocket->fd, destAddr, addrLen);
}


TdEpollPtr taosCreateEpoll(int32_t size) {
  EpollFd fd = -1;
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
#else
  fd = epoll_create(size);
#endif
  if (fd < 0) {
    return NULL;
  }

wafwerar's avatar
wafwerar 已提交
904
  TdEpollPtr pEpoll = (TdEpollPtr)taosMemoryMalloc(sizeof(TdEpoll));
wafwerar's avatar
wafwerar 已提交
905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927
  if (pEpoll == NULL) {
    taosCloseSocketNoCheck1(fd);
    return NULL;
  }
  pEpoll->fd = fd;
  pEpoll->refId = 0;
  return pEpoll;
}
int32_t taosCtlEpoll(TdEpollPtr pEpoll, int32_t epollOperate, TdSocketPtr pSocket, struct epoll_event *event) {
  int32_t code = -1;
  if (pEpoll == NULL || pEpoll->fd < 0) {
    return -1;
  }
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
#else
  code = epoll_ctl(pEpoll->fd, epollOperate, pSocket->fd, event);
#endif
  return code;
}
int32_t taosWaitEpoll(TdEpollPtr pEpoll, struct epoll_event *event, int32_t maxEvents, int32_t timeout) {
  int32_t code = -1;
  if (pEpoll == NULL || pEpoll->fd < 0) {
    return -1;
928
  }
wafwerar's avatar
wafwerar 已提交
929 930 931
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
#else
  code = epoll_wait(pEpoll->fd, event, maxEvents, timeout);
932
#endif
wafwerar's avatar
wafwerar 已提交
933 934 935 936 937 938 939 940 941
  return code;
}
int32_t taosCloseEpoll(TdEpollPtr *ppEpoll) {
  int32_t code;
  if (ppEpoll == NULL || *ppEpoll == NULL || (*ppEpoll)->fd < 0) {
    return -1;
  }
  code = taosCloseSocketNoCheck1((*ppEpoll)->fd);
  (*ppEpoll)->fd = -1;
wafwerar's avatar
wafwerar 已提交
942
  taosMemoryFree(*ppEpoll);
wafwerar's avatar
wafwerar 已提交
943 944
  return code;
}