tsocket.c 15.0 KB
Newer Older
H
hzcheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * 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/>.
 */

S
slguan 已提交
16
#include "os.h"
S
slguan 已提交
17
#include "tulog.h"
H
hzcheng 已提交
18
#include "tsocket.h"
19
#include "taoserror.h"
H
hzcheng 已提交
20

S
TD-2524  
Shengliang Guan 已提交
21 22 23 24
#ifndef SIGPIPE
  #define SIGPIPE EPIPE
#endif

Y
yihaoDeng 已提交
25
#define TCP_CONN_TIMEOUT 3000  // conn timeout
Y
yihaoDeng 已提交
26

S
TD-1912  
Shengliang Guan 已提交
27
int32_t taosGetFqdn(char *fqdn) {
J
jtao1735 已提交
28 29
  char hostname[1024];
  hostname[1023] = '\0';
30 31 32 33
  if (gethostname(hostname, 1023) == -1) {
    uError("failed to get hostname, reason:%s", strerror(errno));
    return -1;
  }
J
jtao1735 已提交
34

S
TD-1912  
Shengliang Guan 已提交
35
  struct addrinfo  hints = {0};
36
  struct addrinfo *result = NULL;
F
freemine 已提交
37 38 39 40 41 42 43
#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;
#else // __APPLE__
44
  hints.ai_flags = AI_CANONNAME;
F
freemine 已提交
45
#endif // __APPLE__
S
TD-1912  
Shengliang Guan 已提交
46
  int32_t ret = getaddrinfo(hostname, NULL, &hints, &result);
47
  if (!result) {
H
Haojun Liao 已提交
48
    uError("failed to get fqdn, code:%d, reason:%s", ret, gai_strerror(ret));
49
    return -1;
S
slguan 已提交
50
  }
J
jtao1735 已提交
51

F
freemine 已提交
52 53 54 55
#ifdef __APPLE__
  // refer to comments above
  strcpy(fqdn, hostname);
#else // __APPLE__
56
  strcpy(fqdn, result->ai_canonname);
F
freemine 已提交
57
#endif // __APPLE__
58 59
  freeaddrinfo(result);
  return 0;
H
hzcheng 已提交
60 61
}

62
uint32_t taosGetIpv4FromFqdn(const char *fqdn) {
63
  struct addrinfo hints = {0};
64
  hints.ai_family = AF_INET;
H
Haojun Liao 已提交
65 66
  hints.ai_socktype = SOCK_STREAM;

67 68
  struct addrinfo *result = NULL;

69
  int32_t ret = getaddrinfo(fqdn, NULL, &hints, &result);
70
  if (result) {
S
TD-1912  
Shengliang Guan 已提交
71 72 73 74
    struct sockaddr *   sa = result->ai_addr;
    struct sockaddr_in *si = (struct sockaddr_in *)sa;
    struct in_addr      ia = si->sin_addr;
    uint32_t            ip = ia.s_addr;
75 76 77
    freeaddrinfo(result);
    return ip;
  } else {
78
#ifdef EAI_SYSTEM
79
    if (ret == EAI_SYSTEM) {
S
TD-2051  
Shengliang Guan 已提交
80
      uError("failed to get the ip address, fqdn:%s, since:%s", fqdn, strerror(errno));
81 82
      terrno = TAOS_SYSTEM_ERROR(errno);
    } else {
S
TD-2051  
Shengliang Guan 已提交
83
      uError("failed to get the ip address, fqdn:%s, since:%s", fqdn, gai_strerror(ret));
84
    }
85
#else
S
TD-2051  
Shengliang Guan 已提交
86
    uError("failed to get the ip address, fqdn:%s, since:%s", fqdn, gai_strerror(ret));
87
#endif
88
    return 0xFFFFFFFF;
89
  }
J
jtao1735 已提交
90 91
}

S
TD-1912  
Shengliang Guan 已提交
92
// Function converting an IP address string to an uint32_t.
S
slguan 已提交
93
uint32_t ip2uint(const char *const ip_addr) {
H
hzcheng 已提交
94 95 96
  char ip_addr_cpy[20];
  char ip[5];

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
97
  tstrncpy(ip_addr_cpy, ip_addr, sizeof(ip_addr_cpy));
H
hzcheng 已提交
98 99 100 101 102

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

S
TD-1912  
Shengliang Guan 已提交
103
  int32_t k;
H
hzcheng 已提交
104 105 106 107 108 109 110 111 112 113 114 115 116

  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';

S
TD-1912  
Shengliang Guan 已提交
117
  return *((uint32_t *)ip);
H
hzcheng 已提交
118 119
}

S
TD-1912  
Shengliang Guan 已提交
120 121 122
int32_t taosWriteMsg(SOCKET fd, void *buf, int32_t nbytes) {
  int32_t nleft, nwritten;
  char *  ptr = (char *)buf;
H
hzcheng 已提交
123 124 125 126

  nleft = nbytes;

  while (nleft > 0) {
S
TD-1912  
Shengliang Guan 已提交
127
    nwritten = (int32_t)taosWriteSocket(fd, (char *)ptr, (size_t)nleft);
H
hzcheng 已提交
128
    if (nwritten <= 0) {
S
TD-2157  
Shengliang Guan 已提交
129
      if (errno == EINTR /* || errno == EAGAIN || errno == EWOULDBLOCK */)
H
hzcheng 已提交
130 131 132 133 134 135 136
        continue;
      else
        return -1;
    } else {
      nleft -= nwritten;
      ptr += nwritten;
    }
S
TD-2506  
Shengliang Guan 已提交
137 138 139 140

    if (errno == SIGPIPE || errno == EPIPE) {
      return -1;
    }
H
hzcheng 已提交
141 142 143 144 145
  }

  return (nbytes - nleft);
}

S
TD-1912  
Shengliang Guan 已提交
146 147 148
int32_t taosReadMsg(SOCKET fd, void *buf, int32_t nbytes) {
  int32_t nleft, nread;
  char *  ptr = (char *)buf;
H
hzcheng 已提交
149 150 151 152 153 154

  nleft = nbytes;

  if (fd < 0) return -1;

  while (nleft > 0) {
S
TD-1912  
Shengliang Guan 已提交
155
    nread = (int32_t)taosReadSocket(fd, ptr, (size_t)nleft);
H
hzcheng 已提交
156 157 158
    if (nread == 0) {
      break;
    } else if (nread < 0) {
S
TD-2157  
Shengliang Guan 已提交
159
      if (errno == EINTR/* || errno == EAGAIN || errno == EWOULDBLOCK*/) {
H
hzcheng 已提交
160 161 162 163 164 165 166 167
        continue;
      } else {
        return -1;
      }
    } else {
      nleft -= nread;
      ptr += nread;
    }
S
TD-2506  
Shengliang Guan 已提交
168 169 170 171

    if (errno == SIGPIPE || errno == EPIPE) {
      return -1;
    }
H
hzcheng 已提交
172 173 174 175 176
  }

  return (nbytes - nleft);
}

S
TD-1912  
Shengliang Guan 已提交
177
int32_t taosNonblockwrite(SOCKET fd, char *ptr, int32_t nbytes) {
H
hzcheng 已提交
178 179
  taosSetNonblocking(fd, 1);

S
TD-1912  
Shengliang Guan 已提交
180 181
  int32_t nleft, nwritten, nready;
  fd_set  fset;
H
hzcheng 已提交
182 183 184 185 186 187 188 189
  struct timeval tv;

  nleft = nbytes;
  while (nleft > 0) {
    tv.tv_sec = 30;
    tv.tv_usec = 0;
    FD_ZERO(&fset);
    FD_SET(fd, &fset);
S
TD-1912  
Shengliang Guan 已提交
190
    if ((nready = select((int32_t)(fd + 1), NULL, &fset, NULL, &tv)) == 0) {
H
hzcheng 已提交
191
      errno = ETIMEDOUT;
S
slguan 已提交
192
      uError("fd %d timeout, no enough space to write", fd);
H
hzcheng 已提交
193 194 195 196 197
      break;

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

S
slguan 已提交
198
      uError("select error, %d (%s)", errno, strerror(errno));
H
hzcheng 已提交
199 200 201
      return -1;
    }

S
TD-1912  
Shengliang Guan 已提交
202
    nwritten = (int32_t)taosSend(fd, ptr, (size_t)nleft, MSG_NOSIGNAL);
H
hzcheng 已提交
203 204 205
    if (nwritten <= 0) {
      if (errno == EAGAIN || errno == EINTR) continue;

S
slguan 已提交
206
      uError("write error, %d (%s)", errno, strerror(errno));
H
hzcheng 已提交
207 208 209 210 211 212 213 214 215 216 217 218
      return -1;
    }

    nleft -= nwritten;
    ptr += nwritten;
  }

  taosSetNonblocking(fd, 0);

  return (nbytes - nleft);
}

S
TD-1912  
Shengliang Guan 已提交
219 220
int32_t taosReadn(SOCKET fd, char *ptr, int32_t nbytes) {
  int32_t nread, nready, nleft = nbytes;
H
hzcheng 已提交
221

S
TD-1912  
Shengliang Guan 已提交
222
  fd_set fset;
H
hzcheng 已提交
223 224 225 226 227 228 229
  struct timeval tv;

  while (nleft > 0) {
    tv.tv_sec = 30;
    tv.tv_usec = 0;
    FD_ZERO(&fset);
    FD_SET(fd, &fset);
S
TD-1912  
Shengliang Guan 已提交
230
    if ((nready = select((int32_t)(fd + 1), NULL, &fset, NULL, &tv)) == 0) {
H
hzcheng 已提交
231
      errno = ETIMEDOUT;
S
slguan 已提交
232
      uError("fd %d timeout\n", fd);
H
hzcheng 已提交
233 234 235
      break;
    } else if (nready < 0) {
      if (errno == EINTR) continue;
S
slguan 已提交
236
      uError("select error, %d (%s)", errno, strerror(errno));
H
hzcheng 已提交
237 238 239
      return -1;
    }

S
TD-1912  
Shengliang Guan 已提交
240
    if ((nread = (int32_t)taosReadSocket(fd, ptr, (size_t)nleft)) < 0) {
H
hzcheng 已提交
241
      if (errno == EINTR) continue;
S
slguan 已提交
242
      uError("read error, %d (%s)", errno, strerror(errno));
H
hzcheng 已提交
243 244 245
      return -1;

    } else if (nread == 0) {
S
slguan 已提交
246
      uError("fd %d EOF", fd);
H
hzcheng 已提交
247 248 249 250 251 252 253 254 255 256
      break;  // EOF
    }

    nleft -= nread;
    ptr += nread;
  }

  return (nbytes - nleft);
}

S
TD-1057  
Shengliang Guan 已提交
257
SOCKET taosOpenUdpSocket(uint32_t ip, uint16_t port) {
H
hzcheng 已提交
258
  struct sockaddr_in localAddr;
259
  SOCKET sockFd;
S
TD-1912  
Shengliang Guan 已提交
260
  int32_t bufSize = 1024000;
H
hzcheng 已提交
261

262
  uDebug("open udp socket:0x%x:%hu", ip, port);
H
hzcheng 已提交
263 264 265

  memset((char *)&localAddr, 0, sizeof(localAddr));
  localAddr.sin_family = AF_INET;
J
jtao1735 已提交
266
  localAddr.sin_addr.s_addr = ip;
L
lihui 已提交
267
  localAddr.sin_port = (uint16_t)htons(port);
H
hzcheng 已提交
268

269
  if ((sockFd = socket(AF_INET, SOCK_DGRAM, 0)) <= 2) {
S
slguan 已提交
270
    uError("failed to open udp socket: %d (%s)", errno, strerror(errno));
S
TD-1090  
Shengliang Guan 已提交
271
    taosCloseSocketNoCheck(sockFd);
H
hzcheng 已提交
272 273 274 275
    return -1;
  }

  if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_SNDBUF, (void *)&bufSize, sizeof(bufSize)) != 0) {
S
slguan 已提交
276
    uError("failed to set the send buffer size for UDP socket\n");
S
TD-1057  
Shengliang Guan 已提交
277
    taosCloseSocket(sockFd);
H
hzcheng 已提交
278 279 280 281
    return -1;
  }

  if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_RCVBUF, (void *)&bufSize, sizeof(bufSize)) != 0) {
S
slguan 已提交
282
    uError("failed to set the receive buffer size for UDP socket\n");
S
TD-1057  
Shengliang Guan 已提交
283
    taosCloseSocket(sockFd);
H
hzcheng 已提交
284 285 286 287 288
    return -1;
  }

  /* bind socket to local address */
  if (bind(sockFd, (struct sockaddr *)&localAddr, sizeof(localAddr)) < 0) {
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
289
    uError("failed to bind udp socket: %d (%s), 0x%x:%hu", errno, strerror(errno), ip, port);
S
TD-1057  
Shengliang Guan 已提交
290
    taosCloseSocket(sockFd);
H
hzcheng 已提交
291 292 293 294 295 296
    return -1;
  }

  return sockFd;
}

S
TD-1057  
Shengliang Guan 已提交
297
SOCKET taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientIp) {
298
  SOCKET sockFd = 0;
S
TD-1912  
Shengliang Guan 已提交
299
  int32_t ret;
H
hzcheng 已提交
300
  struct sockaddr_in serverAddr, clientAddr;
Y
yihaoDeng 已提交
301
  int32_t bufSize = 1024 * 1024;
H
hzcheng 已提交
302

S
TD-1057  
Shengliang Guan 已提交
303
  sockFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
F
freemine 已提交
304

S
TD-1165  
Shengliang Guan 已提交
305
  if (sockFd <= 2) {
S
slguan 已提交
306
    uError("failed to open the socket: %d (%s)", errno, strerror(errno));
S
TD-1090  
Shengliang Guan 已提交
307
    taosCloseSocketNoCheck(sockFd);
H
hzcheng 已提交
308 309 310
    return -1;
  }

311
  /* set REUSEADDR option, so the portnumber can be re-used */
S
TD-1912  
Shengliang Guan 已提交
312
  int32_t reuse = 1;
313 314
  if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse)) < 0) {
    uError("setsockopt SO_REUSEADDR failed: %d (%s)", errno, strerror(errno));
S
TD-1057  
Shengliang Guan 已提交
315
    taosCloseSocket(sockFd);
316
    return -1;
S
TD-1165  
Shengliang Guan 已提交
317
  }
318

Y
yihaoDeng 已提交
319 320 321 322 323 324 325 326 327 328 329 330
  if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_SNDBUF, (void *)&bufSize, sizeof(bufSize)) != 0) {
    uError("failed to set the send buffer size for TCP socket\n");
    taosCloseSocket(sockFd);
    return -1;
  }

  if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_RCVBUF, (void *)&bufSize, sizeof(bufSize)) != 0) {
    uError("failed to set the receive buffer size for TCP socket\n");
    taosCloseSocket(sockFd);
    return -1;
  }

S
TD-1057  
Shengliang Guan 已提交
331
  if (clientIp != 0) {
H
hzcheng 已提交
332 333
    memset((char *)&clientAddr, 0, sizeof(clientAddr));
    clientAddr.sin_family = AF_INET;
J
jtao1735 已提交
334
    clientAddr.sin_addr.s_addr = clientIp;
H
hzcheng 已提交
335 336 337 338
    clientAddr.sin_port = 0;

    /* bind socket to client address */
    if (bind(sockFd, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0) {
S
TD-1912  
Shengliang Guan 已提交
339 340
      uError("bind tcp client socket failed, client(0x%x:0), dest(0x%x:%d), reason:(%s)", clientIp, destIp, destPort,
             strerror(errno));
S
TD-1057  
Shengliang Guan 已提交
341
      taosCloseSocket(sockFd);
H
hzcheng 已提交
342 343 344 345 346 347
      return -1;
    }
  }

  memset((char *)&serverAddr, 0, sizeof(serverAddr));
  serverAddr.sin_family = AF_INET;
J
jtao1735 已提交
348
  serverAddr.sin_addr.s_addr = destIp;
H
hzcheng 已提交
349 350
  serverAddr.sin_port = (uint16_t)htons((uint16_t)destPort);

Y
yihaoDeng 已提交
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
#ifdef _TD_LINUX 
  taosSetNonblocking(sockFd, 1);   
  ret = connect(sockFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); 
  if (ret == -1) {
    if (errno == EHOSTUNREACH) {
      uError("failed to connect socket, ip:0x%x, port:%hu(%s)", destIp, destPort, strerror(errno));
      taosCloseSocket(sockFd);
      return -1; 
    } else if (errno == EINPROGRESS || errno == EAGAIN || errno == EWOULDBLOCK) {
      struct pollfd wfd[1]; 

      wfd[0].fd = sockFd;
      wfd[0].events = POLLOUT;
    
      int res = poll(wfd, 1, TCP_CONN_TIMEOUT);
      if (res == -1 || res == 0) {
Y
yihaoDeng 已提交
367
        uError("failed to connect socket, ip:0x%x, port:%hu(poll error/conn timeout)", destIp, destPort);
Y
yihaoDeng 已提交
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
        taosCloseSocket(sockFd); //  
        return -1;
      }
      int optVal = -1, optLen = sizeof(int);  
      if ((0 != taosGetSockOpt(sockFd, SOL_SOCKET, SO_ERROR, &optVal, &optLen)) || (optVal != 0)) {
        uError("failed to connect socket, ip:0x%x, port:%hu(connect host error)", destIp, destPort);
        taosCloseSocket(sockFd); //  
        return -1;
      }
      ret = 0;
    } else { // Other error
      uError("failed to connect socket, ip:0x%x, port:%hu(target host cannot be reached)", destIp, destPort);
      taosCloseSocket(sockFd); //  
      return -1; 
    } 
  }
  taosSetNonblocking(sockFd, 0);   

#else
  ret = connect(sockFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); 
#endif
H
hzcheng 已提交
389 390

  if (ret != 0) {
Y
yihaoDeng 已提交
391
    uError("failed to connect socket, ip:0x%x, port:%hu(%s)", destIp, destPort, strerror(errno));
S
TD-1057  
Shengliang Guan 已提交
392
    taosCloseSocket(sockFd);
H
hzcheng 已提交
393
    sockFd = -1;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
394 395
  } else {
    taosKeepTcpAlive(sockFd);
H
hzcheng 已提交
396 397
  }

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
398
  return sockFd;
H
hzcheng 已提交
399 400
}

S
TD-1912  
Shengliang Guan 已提交
401 402
int32_t taosKeepTcpAlive(SOCKET sockFd) {
  int32_t alive = 1;
H
hzcheng 已提交
403
  if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_KEEPALIVE, (void *)&alive, sizeof(alive)) < 0) {
S
slguan 已提交
404
    uError("fd:%d setsockopt SO_KEEPALIVE failed: %d (%s)", sockFd, errno, strerror(errno));
S
TD-1057  
Shengliang Guan 已提交
405
    taosCloseSocket(sockFd);
H
hzcheng 已提交
406 407 408
    return -1;
  }

F
eok  
freemine 已提交
409
#ifndef __APPLE__
410
  // all fails on macosx
S
TD-1912  
Shengliang Guan 已提交
411
  int32_t probes = 3;
H
hzcheng 已提交
412
  if (taosSetSockOpt(sockFd, SOL_TCP, TCP_KEEPCNT, (void *)&probes, sizeof(probes)) < 0) {
S
slguan 已提交
413
    uError("fd:%d setsockopt SO_KEEPCNT failed: %d (%s)", sockFd, errno, strerror(errno));
S
TD-1057  
Shengliang Guan 已提交
414
    taosCloseSocket(sockFd);
H
hzcheng 已提交
415 416 417
    return -1;
  }

S
TD-1912  
Shengliang Guan 已提交
418
  int32_t alivetime = 10;
H
hzcheng 已提交
419
  if (taosSetSockOpt(sockFd, SOL_TCP, TCP_KEEPIDLE, (void *)&alivetime, sizeof(alivetime)) < 0) {
S
slguan 已提交
420
    uError("fd:%d setsockopt SO_KEEPIDLE failed: %d (%s)", sockFd, errno, strerror(errno));
S
TD-1057  
Shengliang Guan 已提交
421
    taosCloseSocket(sockFd);
H
hzcheng 已提交
422 423 424
    return -1;
  }

S
TD-1912  
Shengliang Guan 已提交
425
  int32_t interval = 3;
H
hzcheng 已提交
426
  if (taosSetSockOpt(sockFd, SOL_TCP, TCP_KEEPINTVL, (void *)&interval, sizeof(interval)) < 0) {
S
slguan 已提交
427
    uError("fd:%d setsockopt SO_KEEPINTVL failed: %d (%s)", sockFd, errno, strerror(errno));
S
TD-1057  
Shengliang Guan 已提交
428
    taosCloseSocket(sockFd);
H
hzcheng 已提交
429 430
    return -1;
  }
F
freemine 已提交
431
#endif // __APPLE__
H
hzcheng 已提交
432

S
TD-1912  
Shengliang Guan 已提交
433
  int32_t nodelay = 1;
H
hzcheng 已提交
434
  if (taosSetSockOpt(sockFd, IPPROTO_TCP, TCP_NODELAY, (void *)&nodelay, sizeof(nodelay)) < 0) {
S
slguan 已提交
435
    uError("fd:%d setsockopt TCP_NODELAY failed %d (%s)", sockFd, errno, strerror(errno));
S
TD-1057  
Shengliang Guan 已提交
436
    taosCloseSocket(sockFd);
H
hzcheng 已提交
437 438 439
    return -1;
  }

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
440 441
  struct linger linger = {0};
  linger.l_onoff = 1;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
442
  linger.l_linger = 3;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
443 444
  if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger)) < 0) {
    uError("setsockopt SO_LINGER failed: %d (%s)", errno, strerror(errno));
S
TD-1057  
Shengliang Guan 已提交
445
    taosCloseSocket(sockFd);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
446 447 448
    return -1;
  }

H
hzcheng 已提交
449 450 451
  return 0;
}

S
TD-1057  
Shengliang Guan 已提交
452
SOCKET taosOpenTcpServerSocket(uint32_t ip, uint16_t port) {
H
hzcheng 已提交
453
  struct sockaddr_in serverAdd;
S
TD-1912  
Shengliang Guan 已提交
454 455
  SOCKET             sockFd;
  int32_t            reuse;
H
hzcheng 已提交
456

457
  uDebug("open tcp server socket:0x%x:%hu", ip, port);
H
hzcheng 已提交
458 459 460

  bzero((char *)&serverAdd, sizeof(serverAdd));
  serverAdd.sin_family = AF_INET;
J
jtao1735 已提交
461
  serverAdd.sin_addr.s_addr = ip;
L
lihui 已提交
462
  serverAdd.sin_port = (uint16_t)htons(port);
H
hzcheng 已提交
463

464
  if ((sockFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <= 2) {
S
slguan 已提交
465
    uError("failed to open TCP socket: %d (%s)", errno, strerror(errno));
S
TD-1090  
Shengliang Guan 已提交
466
    taosCloseSocketNoCheck(sockFd);
H
hzcheng 已提交
467 468 469 470 471 472
    return -1;
  }

  /* set REUSEADDR option, so the portnumber can be re-used */
  reuse = 1;
  if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse)) < 0) {
S
slguan 已提交
473
    uError("setsockopt SO_REUSEADDR failed: %d (%s)", errno, strerror(errno));
S
TD-1057  
Shengliang Guan 已提交
474
    taosCloseSocket(sockFd);
H
hzcheng 已提交
475
    return -1;
476
  }
H
hzcheng 已提交
477 478 479

  /* bind socket to server address */
  if (bind(sockFd, (struct sockaddr *)&serverAdd, sizeof(serverAdd)) < 0) {
J
jtao1735 已提交
480
    uError("bind tcp server socket failed, 0x%x:%hu(%s)", ip, port, strerror(errno));
S
TD-1057  
Shengliang Guan 已提交
481
    taosCloseSocket(sockFd);
H
hzcheng 已提交
482 483 484
    return -1;
  }

485 486
  if (taosKeepTcpAlive(sockFd) < 0) {
    uError("failed to set tcp server keep-alive option, 0x%x:%hu(%s)", ip, port, strerror(errno));
S
TD-1057  
Shengliang Guan 已提交
487
    taosCloseSocket(sockFd);
488 489
    return -1;
  }
H
hzcheng 已提交
490

491
  if (listen(sockFd, 1024) < 0) {
J
jtao1735 已提交
492
    uError("listen tcp server socket failed, 0x%x:%hu(%s)", ip, port, strerror(errno));
S
TD-1057  
Shengliang Guan 已提交
493
    taosCloseSocket(sockFd);
H
hzcheng 已提交
494 495 496 497 498 499
    return -1;
  }

  return sockFd;
}

S
TD-1912  
Shengliang Guan 已提交
500
void tinet_ntoa(char *ipstr, uint32_t ip) {
H
hzcheng 已提交
501 502 503 504 505 506
  sprintf(ipstr, "%d.%d.%d.%d", ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, ip >> 24);
}

#define COPY_SIZE 32768
// sendfile shall be used

S
TD-3354  
Shengliang Guan 已提交
507
int64_t taosCopyFds(SOCKET sfd, int32_t dfd, int64_t len) {
H
hzcheng 已提交
508
  int64_t leftLen;
S
TD-3354  
Shengliang Guan 已提交
509
  int64_t readLen, writeLen;
H
hzcheng 已提交
510 511 512 513 514 515
  char    temp[COPY_SIZE];

  leftLen = len;

  while (leftLen > 0) {
    if (leftLen < COPY_SIZE)
S
TD-3354  
Shengliang Guan 已提交
516
      readLen = leftLen;
H
hzcheng 已提交
517 518 519
    else
      readLen = COPY_SIZE;  // 4K

S
TD-3354  
Shengliang Guan 已提交
520
    int64_t retLen = taosReadMsg(sfd, temp, (int32_t)readLen);
H
hzcheng 已提交
521
    if (readLen != retLen) {
S
TD-3354  
Shengliang Guan 已提交
522 523
      uError("read error, readLen:%" PRId64 " retLen:%" PRId64 " len:%" PRId64 " leftLen:%" PRId64 ", reason:%s",
             readLen, retLen, len, leftLen, strerror(errno));
H
hzcheng 已提交
524 525 526
      return -1;
    }

S
Shengliang Guan 已提交
527
    writeLen = taosWriteMsg(dfd, temp, (int32_t)readLen);
H
hzcheng 已提交
528 529

    if (readLen != writeLen) {
S
TD-3354  
Shengliang Guan 已提交
530 531
      uError("copy error, readLen:%" PRId64 " writeLen:%" PRId64 " len:%" PRId64 " leftLen:%" PRId64 ", reason:%s",
             readLen, writeLen, len, leftLen, strerror(errno));
H
hzcheng 已提交
532 533 534 535 536 537
      return -1;
    }

    leftLen -= readLen;
  }

S
TD-3354  
Shengliang Guan 已提交
538
  return len;
H
hzcheng 已提交
539
}