• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #3558

17 Dec 2024 06:05AM UTC coverage: 59.778% (+1.6%) from 58.204%
#3558

push

travis-ci

web-flow
Merge pull request #29179 from taosdata/merge/mainto3.0

merge: form main to 3.0 branch

132787 of 287595 branches covered (46.17%)

Branch coverage included in aggregate %.

104 of 191 new or added lines in 5 files covered. (54.45%)

6085 existing lines in 168 files now uncovered.

209348 of 284746 relevant lines covered (73.52%)

8164844.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

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

16
#define _DEFAULT_SOURCE
17
#define ALLOW_FORBID_FUNC
18
#include "os.h"
19

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

40
#if defined(DARWIN)
41
#include <dispatch/dispatch.h>
42
#include "osEok.h"
43
#else
44
#include <sys/epoll.h>
45
#endif
46
#endif
47

48
#ifndef INVALID_SOCKET
49
#define INVALID_SOCKET -1
50
#endif
51

52
typedef struct TdSocket {
53
#if SOCKET_WITH_LOCK
54
  TdThreadRwlock rwlock;
55
#endif
56
  int      refId;
57
  SocketFd fd;
58
} * TdSocketPtr, TdSocket;
59

60
typedef struct TdSocketServer {
61
#if SOCKET_WITH_LOCK
62
  TdThreadRwlock rwlock;
63
#endif
64
  int      refId;
65
  SocketFd fd;
66
} * TdSocketServerPtr, TdSocketServer;
67

68
typedef struct TdEpoll {
69
#if SOCKET_WITH_LOCK
70
  TdThreadRwlock rwlock;
71
#endif
72
  int     refId;
73
  EpollFd fd;
74
} * TdEpollPtr, TdEpoll;
75

76
int32_t taosCloseSocketNoCheck1(SocketFd fd) {
1,881✔
77
#ifdef WINDOWS
78
  int ret = closesocket(fd);
79
  if (ret == SOCKET_ERROR) {
80
    int errorCode = WSAGetLastError();
81
    return terrno = TAOS_SYSTEM_WINSOCKET_ERROR(errorCode);
82
  }
83
  return 0;
84
#else
85
  int32_t code = close(fd);
1,881✔
86
  if (-1 == code) {
1,881!
87
    terrno = TAOS_SYSTEM_ERROR(errno);
×
88
    return terrno;
×
89
  }
90
  return code;
1,881✔
91
#endif
92
}
93

94
int32_t taosCloseSocket(TdSocketPtr *ppSocket) {
1,881✔
95
  int32_t code;
96
  if (ppSocket == NULL || *ppSocket == NULL || (*ppSocket)->fd < 0) {
1,881!
97
    terrno = TSDB_CODE_INVALID_PARA;
×
98
    return terrno;
×
99
  }
100
  code = taosCloseSocketNoCheck1((*ppSocket)->fd);
1,881✔
101
  (*ppSocket)->fd = -1;
1,881✔
102
  taosMemoryFree(*ppSocket);
1,881!
103

104
  return code;
1,881✔
105
}
106

107
int32_t taosSetSockOpt(TdSocketPtr pSocket, int32_t level, int32_t optname, void *optval, int32_t optlen) {
1,881✔
108
  if (pSocket == NULL || pSocket->fd < 0) {
1,881!
109
    terrno = TSDB_CODE_INVALID_PARA;
×
110
    return terrno;
×
111
  }
112

113
#ifdef WINDOWS
114
#ifdef TCP_KEEPCNT
115
  if (level == SOL_SOCKET && optname == TCP_KEEPCNT) {
116
    return 0;
117
  }
118
#endif
119

120
#ifdef TCP_KEEPIDLE
121
  if (level == SOL_TCP && optname == TCP_KEEPIDLE) {
122
    return 0;
123
  }
124
#endif
125

126
#ifdef TCP_KEEPINTVL
127
  if (level == SOL_TCP && optname == TCP_KEEPINTVL) {
128
    return 0;
129
  }
130
#endif
131

132
#ifdef TCP_KEEPCNT
133
  if (level == SOL_TCP && optname == TCP_KEEPCNT) {
134
    return 0;
135
  }
136
#endif
137

138
  int ret = setsockopt(pSocket->fd, level, optname, optval, optlen);
139
  if (ret == SOCKET_ERROR) {
140
    int errorCode = WSAGetLastError();
141
    return terrno = TAOS_SYSTEM_WINSOCKET_ERROR(errorCode);
142
  }
143
#else
144
  int32_t code = setsockopt(pSocket->fd, level, optname, optval, (int)optlen);
1,881✔
145
  if (-1 == code) {
1,881!
146
    terrno = TAOS_SYSTEM_ERROR(errno);
×
147
    return terrno;
×
148
  }
149
  return 0;
1,881✔
150
#endif
151
}
152

153
const char *taosInetNtop(struct in_addr ipInt, char *dstStr, int32_t len) {
×
154
  const char *r = inet_ntop(AF_INET, &ipInt, dstStr, len);
×
155
  if (NULL == r) {
×
156
    terrno = TAOS_SYSTEM_ERROR(errno);
×
157
  }
158

159
  return r;
×
160
}
161

162
#ifndef SIGPIPE
163
#define SIGPIPE EPIPE
164
#endif
165

166
#define TCP_CONN_TIMEOUT 3000  // conn timeout
167

168
bool taosValidIpAndPort(uint32_t ip, uint16_t port) {
1,881✔
169
  struct sockaddr_in serverAdd;
170
  SocketFd           fd;
171
  int32_t            reuse;
172
  int32_t            code = 0;
1,881✔
173

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

176
  bzero((char *)&serverAdd, sizeof(serverAdd));
1,881✔
177
  serverAdd.sin_family = AF_INET;
1,881✔
178
#ifdef WINDOWS
179
  serverAdd.sin_addr.s_addr = INADDR_ANY;
180
#else
181
  serverAdd.sin_addr.s_addr = ip;
1,881✔
182
#endif
183
  serverAdd.sin_port = (uint16_t)htons(port);
1,881✔
184

185
  fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1,881✔
186
  if (-1 == fd) {  // exception
1,881!
187
    terrno = TAOS_SYSTEM_ERROR(errno);
×
188
    return false;
×
189
  }
190

191
  TdSocketPtr pSocket = (TdSocketPtr)taosMemoryMalloc(sizeof(TdSocket));
1,881!
192
  if (pSocket == NULL) {
1,881!
193
    TAOS_SKIP_ERROR(taosCloseSocketNoCheck1(fd));
×
194
    return false;
×
195
  }
196
  pSocket->refId = 0;
1,881✔
197
  pSocket->fd = fd;
1,881✔
198

199
  /* set REUSEADDR option, so the portnumber can be re-used */
200
  reuse = 1;
1,881✔
201
  if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse)) < 0) {
1,881!
202
    TAOS_SKIP_ERROR(taosCloseSocket(&pSocket));
×
203
    return false;
×
204
  }
205

206
  /* bind socket to server address */
207
  if (-1 == bind(pSocket->fd, (struct sockaddr *)&serverAdd, sizeof(serverAdd))) {
1,881✔
208
    terrno = TAOS_SYSTEM_ERROR(errno);
1✔
209
    TAOS_SKIP_ERROR(taosCloseSocket(&pSocket));
1✔
210
    return false;
1✔
211
  }
212

213
  TAOS_SKIP_ERROR(taosCloseSocket(&pSocket));
1,880✔
214

215
  return true;
1,880✔
216
}
217

218
int32_t taosBlockSIGPIPE() {
506,179✔
219
#ifdef WINDOWS
220
  return 0;
221
#else
222
  sigset_t signal_mask;
223
  (void)sigemptyset(&signal_mask);
506,179✔
224
  (void)sigaddset(&signal_mask, SIGPIPE);
506,188✔
225
  int32_t rc = pthread_sigmask(SIG_BLOCK, &signal_mask, NULL);
506,212✔
226
  if (rc != 0) {
506,331!
227
    terrno = TAOS_SYSTEM_ERROR(rc);
×
228
    return terrno;
×
229
  }
230

231
  return 0;
506,331✔
232
#endif
233
}
234

235
int32_t taosGetIpv4FromFqdn(const char *fqdn, uint32_t *ip) {
172,148✔
236
  int32_t code = 0;
172,148✔
237
  OS_PARAM_CHECK(fqdn);
172,148!
238
  OS_PARAM_CHECK(ip);
172,148!
239
  int64_t limitMs = 1000;
172,148✔
240
  int64_t st = taosGetTimestampMs(), cost = 0;
172,183✔
241
#ifdef WINDOWS
242
  // Initialize Winsock
243
  WSADATA wsaData;
244
  int     iResult;
245
  iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
246
  if (iResult != 0) {
247
    code = TAOS_SYSTEM_WINSOCKET_ERROR(WSAGetLastError());
248
    goto _err;
249
  }
250
#endif
251

252
#if defined(LINUX)
253
  struct addrinfo hints = {0};
172,183✔
254
  hints.ai_family = AF_INET;
172,183✔
255
  hints.ai_socktype = SOCK_STREAM;
172,183✔
256

257
  struct addrinfo *result = NULL;
172,183✔
258
  bool             inRetry = false;
172,183✔
259

260
  while (true) {
×
261
    int32_t ret = getaddrinfo(fqdn, NULL, &hints, &result);
172,183✔
262
    if (ret) {
172,164✔
263
      if (EAI_AGAIN == ret && !inRetry) {
5!
264
        inRetry = true;
×
265
        continue;
×
266
      } else if (EAI_SYSTEM == ret) {
5!
267
        code = TAOS_SYSTEM_ERROR(errno);
×
268
        goto _err;
172,154✔
269
      }
270

271
      code = TAOS_SYSTEM_ERROR(errno);
5✔
272
      goto _err;
5✔
273
    }
274

275
    struct sockaddr    *sa = result->ai_addr;
172,159✔
276
    struct sockaddr_in *si = (struct sockaddr_in *)sa;
172,159✔
277
    struct in_addr      ia = si->sin_addr;
172,159✔
278

279
    *ip = ia.s_addr;
172,159✔
280

281
    freeaddrinfo(result);
172,159✔
282
    goto _err;
172,149✔
283
  }
284
#else
285
  struct addrinfo hints = {0};
286
  hints.ai_family = AF_INET;
287
  hints.ai_socktype = SOCK_STREAM;
288

289
  struct addrinfo *result = NULL;
290

291
  int32_t ret = getaddrinfo(fqdn, NULL, &hints, &result);
292
  if (result) {
293
    struct sockaddr    *sa = result->ai_addr;
294
    struct sockaddr_in *si = (struct sockaddr_in *)sa;
295
    struct in_addr      ia = si->sin_addr;
296
    *ip = ia.s_addr;
297
    freeaddrinfo(result);
298
    goto _err;
299
  } else {
300
#ifdef EAI_SYSTEM
301
    if (ret == EAI_SYSTEM) {
302
      // printf("failed to get the ip address, fqdn:%s, errno:%d, since:%s", fqdn, errno, strerror(errno));
303
    } else {
304
      // printf("failed to get the ip address, fqdn:%s, ret:%d, since:%s", fqdn, ret, gai_strerror(ret));
305
    }
306
#else
307
    // printf("failed to get the ip address, fqdn:%s, ret:%d, since:%s", fqdn, ret, gai_strerror(ret));
308
#endif
309

310
    *ip = 0xFFFFFFFF;
311
    code = TSDB_CODE_RPC_FQDN_ERROR;
312
    goto _err;
313
  }
314
#endif
315
_err:
172,154✔
316
  cost = taosGetTimestampMs() - st;
172,162✔
317
  if (cost >= limitMs) {
172,162!
318
    uWarn("get ip from fqdn:%s, cost:%" PRId64 "ms", fqdn, cost);
×
319
  }
320
  return code;
172,177✔
321
}
322

323
int32_t taosGetFqdn(char *fqdn) {
34,752✔
324
  OS_PARAM_CHECK(fqdn);
34,752!
325
#ifdef WINDOWS
326
  // Initialize Winsock
327
  WSADATA wsaData;
328
  int     iResult;
329
  iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
330
  if (iResult != 0) {
331
    // printf("WSAStartup failed: %d\n", iResult);
332
    return TAOS_SYSTEM_WINSOCKET_ERROR(WSAGetLastError());
333
  }
334
#endif
335
  char hostname[1024];
336
  hostname[1023] = '\0';
34,752✔
337
  int32_t code = taosGetlocalhostname(hostname, 1023);
34,752✔
338
  if (code) {
34,752!
339
    return code;
×
340
  }
341

342
#ifdef __APPLE__
343
  // on macosx, hostname -f has the form of xxx.local
344
  // which will block getaddrinfo for a few seconds if AI_CANONNAME is set
345
  // thus, we choose AF_INET (ipv4 for the moment) to make getaddrinfo return
346
  // immediately
347
  // hints.ai_family = AF_INET;
348
  tstrncpy(fqdn, hostname, TD_FQDN_LEN);
349
  tstrncpy(fqdn + strlen(hostname), ".local", TD_FQDN_LEN - strlen(hostname));
350
#else  // linux
351

352
#endif  // linux
353

354
#if defined(LINUX)
355

356
  struct addrinfo  hints = {0};
34,752✔
357
  struct addrinfo *result = NULL;
34,752✔
358
  hints.ai_flags = AI_CANONNAME;
34,752✔
359

360
  while (true) {
×
361
    int32_t ret = getaddrinfo(hostname, NULL, &hints, &result);
34,752✔
362
    if (ret) {
34,751!
363
      if (EAI_AGAIN == ret) {
×
364
        continue;
×
365
      } else if (EAI_SYSTEM == ret) {
×
366
        terrno = TAOS_SYSTEM_ERROR(errno);
×
367
        return terrno;
×
368
      }
369

370
      terrno = TAOS_SYSTEM_ERROR(ret);
×
371
      return terrno;
×
372
    }
373

374
    break;
34,751✔
375
  }
376

377
  tstrncpy(fqdn, result->ai_canonname, TD_FQDN_LEN);
34,751✔
378

379
  freeaddrinfo(result);
34,751✔
380

381
#elif WINDOWS
382
  struct addrinfo  hints = {0};
383
  struct addrinfo *result = NULL;
384
  hints.ai_flags = AI_CANONNAME;
385

386
  int32_t ret = getaddrinfo(hostname, NULL, &hints, &result);
387
  if (!result) {
388
    // fprintf(stderr, "failed to get fqdn, code:%d, hostname:%s, reason:%s\n", ret, hostname, gai_strerror(ret));
389
    return TAOS_SYSTEM_WINSOCKET_ERROR(WSAGetLastError());
390
  }
391
  tstrncpy(fqdn, result->ai_canonname, TD_FQDN_LEN);
392
  freeaddrinfo(result);
393

394
#endif
395

396
  return 0;
34,751✔
397
}
398

399
void taosInetNtoa(char *ipstr, uint32_t ip) {
55,591✔
400
  if (ipstr == NULL) {
55,591!
401
    return;
×
402
  }
403
  unsigned char *bytes = (unsigned char *) &ip;
55,591✔
404
  (void)snprintf(ipstr, TD_IP_LEN, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]);
55,591✔
405
}
406

407
uint32_t taosInetAddr(const char *ipstr){
×
408
  if (ipstr == NULL) {
×
409
    return 0;
×
410
  }
411
  return inet_addr(ipstr);
×
412
}
413

414
int32_t taosIgnSIGPIPE() {
1,883✔
415
  sighandler_t h = signal(SIGPIPE, SIG_IGN);
1,883✔
416
  if (SIG_ERR == h) {
1,883!
417
    terrno = TAOS_SYSTEM_ERROR(errno);
×
418
    return terrno;
×
419
  }
420

421
  return 0;
1,883✔
422
}
423

424
/*
425
 * Set TCP connection timeout per-socket level.
426
 * ref [https://github.com/libuv/help/issues/54]
427
 */
428
int32_t taosCreateSocketWithTimeout(uint32_t timeout) {
154,412✔
429
#if defined(WINDOWS)
430
  SOCKET fd;
431
#else
432
  int fd;
433
#endif
434

435
  if ((fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
154,412!
436
    terrno = TAOS_SYSTEM_ERROR(errno);
×
437
    return terrno;
×
438
  }
439

440
#if defined(WINDOWS)
441
  if (0 != setsockopt(fd, IPPROTO_TCP, TCP_MAXRT, (char *)&timeout, sizeof(timeout))) {
442
    taosCloseSocketNoCheck1(fd);
443
    return TAOS_SYSTEM_WINSOCKET_ERROR(WSAGetLastError());
444
  }
445
#elif defined(_TD_DARWIN_64)
446
  // invalid config
447
  // uint32_t conn_timeout_ms = timeout * 1000;
448
  // if (0 != setsockopt(fd, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT, (char *)&conn_timeout_ms, sizeof(conn_timeout_ms))) {
449
  //  taosCloseSocketNoCheck1(fd);
450
  //  return -1;
451
  //}
452
#else  // Linux like systems
453
  uint32_t conn_timeout_ms = timeout;
154,447✔
454
  if (-1 == setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, (char *)&conn_timeout_ms, sizeof(conn_timeout_ms))) {
154,447!
UNCOV
455
    terrno = TAOS_SYSTEM_ERROR(errno);
×
456
    TAOS_SKIP_ERROR(taosCloseSocketNoCheck1(fd));
×
457
    return terrno;
×
458
  }
459
#endif
460

461
  return (int)fd;
154,360✔
462
}
463

464
int32_t taosWinSocketInit() {
×
465
#ifdef WINDOWS
466
  static int8_t flag = 0;
467
  if (atomic_val_compare_exchange_8(&flag, 0, 1) == 0) {
468
    WORD    wVersionRequested;
469
    WSADATA wsaData;
470
    wVersionRequested = MAKEWORD(1, 1);
471
    if (WSAStartup(wVersionRequested, &wsaData) != 0) {
472
      atomic_store_8(&flag, 0);
473
      int errorCode = WSAGetLastError();
474
      return terrno = TAOS_SYSTEM_WINSOCKET_ERROR(errorCode);
475
    }
476
  }
477
  return 0;
478
#else
479
#endif
480
  return 0;
×
481
}
482

483
uint64_t taosHton64(uint64_t val) {
246,046,856✔
484
#if defined(WINDOWS) || defined(DARWIN)
485
  return ((val & 0x00000000000000ff) << 7 * 8) | ((val & 0x000000000000ff00) << 5 * 8) |
486
         ((val & 0x0000000000ff0000) << 3 * 8) | ((val & 0x00000000ff000000) << 1 * 8) |
487
         ((val & 0x000000ff00000000) >> 1 * 8) | ((val & 0x0000ff0000000000) >> 3 * 8) |
488
         ((val & 0x00ff000000000000) >> 5 * 8) | ((val & 0xff00000000000000) >> 7 * 8);
489
#else
490
  if (__BYTE_ORDER == __LITTLE_ENDIAN) {
491
    return (((uint64_t)htonl((int)((val << 32) >> 32))) << 32) | (unsigned int)htonl((int)(val >> 32));
246,046,856✔
492
  } else if (__BYTE_ORDER == __BIG_ENDIAN) {
493
    return val;
494
  }
495
#endif
496
}
497

498
uint64_t taosNtoh64(uint64_t val) {
5,684,640✔
499
#if defined(WINDOWS) || defined(DARWIN)
500
  return taosHton64(val);
501
#else
502
  if (__BYTE_ORDER == __LITTLE_ENDIAN) {
503
    return (((uint64_t)htonl((int)((val << 32) >> 32))) << 32) | (unsigned int)htonl((int)(val >> 32));
5,684,640✔
504
  } else if (__BYTE_ORDER == __BIG_ENDIAN) {
505
    return val;
506
  }
507
#endif
508
}
509

510
int32_t taosSetSockOpt2(int32_t fd) {
44,423,745✔
511
#if defined(WINDOWS) || defined(DARWIN)
512
  return 0;
513
#else
514
  int32_t ret = setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){1}, sizeof(int));
44,423,745✔
515
  if (ret < 0) {
44,497,224!
516
    terrno = TAOS_SYSTEM_ERROR(errno);
×
517
    return terrno;
×
518
  } else {
519
    return 0;
44,517,418✔
520
  }
521
#endif
522
  return 0;
523
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc