DSL
sockets3.cpp
1 //@AUTOHEADER@BEGIN@
2 /***********************************************************************\
3 | Drift Standard Libraries v1.01 |
4 | Copyright 2010-2023 Drift Solutions / Indy Sams |
5 | Docs and more information available at https://www.driftsolutions.dev |
6 | This file released under the 3-clause BSD license, |
7 | see included DSL.LICENSE.TXT file for details. |
8 \***********************************************************************/
9 //@AUTOHEADER@END@
10 
11 #include <drift/dslcore.h>
12 #include <drift/sockets3.h>
13 #include <drift/Threading.h>
14 #include <drift/GenLib.h>
15 
16 /*
17 struct DSL_SOCKET_IO {
18  void (*read)(DSL_SOCKET * sock, char * buf, uint32 bufSize);
19  void (*peek)(DSL_SOCKET * sock, char * buf, uint32 bufSize);
20  void (*write)(DSL_SOCKET * sock, char * buf, uint32 bufSize);
21  void (*close)(DSL_SOCKET * sock);
22 };
23 */
24 
25 void DSL_CC DFD_ZERO(DSL_SOCKET_LIST * x) {
26  x->socks.clear();
27 }
28 void DSL_CC DFD_SET(DSL_SOCKET_LIST * x, DSL_SOCKET * sock) {
29  x->socks.insert(sock);
30 }
31 bool DSL_CC DFD_ISSET(DSL_SOCKET_LIST * x, DSL_SOCKET * sock) {
32  return (x->socks.find(sock) != x->socks.end());
33 }
34 void DSL_CC DFD_CLR(DSL_SOCKET_LIST * x, DSL_SOCKET * sock) {
35  auto it = x->socks.find(sock);
36  if (it != x->socks.end()) {
37  x->socks.erase(it);
38  }
39 }
40 void DSL_CC DFD_COPY(DSL_SOCKET_LIST * const in, DSL_SOCKET_LIST * out) {
41  out->socks = in->socks;
42 }
43 
44 void DSL_Sockets3_Base::Silent(bool bSilent) {
45  silent = bSilent;
46 }
47 
48 DSL_Sockets3_Base::DSL_Sockets3_Base(DSL_Mutex_Base * mutex) {
49  dsl_init();
50  if (mutex != NULL) {
51  free_mutex = false;
52  hMutex = mutex;
53  } else {
54  hMutex = new DSL_Mutex();
55  free_mutex = true;
56  }
57 #ifdef ENABLE_ZLIB
58  avail_flags |= DS3_FLAG_ZIP;
59  enabled_flags |= DS3_FLAG_ZIP;
60 #endif
61  memset(bError,0,sizeof(bError));
62  bErrNo = 0;
63 #if defined(DEBUG)
64  silent = false;
65 #else
66  silent = true;
67 #endif
68 }
69 
70 DSL_Sockets3_Base::~DSL_Sockets3_Base() {
71  hMutex->Lock();
72  for (knownSocketList::const_iterator i = sockets.begin(); i != sockets.end(); i++) {
73  if (!silent) { printf("WARNING: DSL_SOCKET 0x%p (%s:%d) was not closed before DSL_Sockets3 was deleted!\n", *i, (*i)->remote_ip, (*i)->remote_port); }
74  //Close(sockets[i]);
75  }
76  hMutex->Release();
77  if (free_mutex) {
78  delete hMutex;
79  }
80  dsl_cleanup();
81 }
82 
83 #if !defined(WIN32)
84 #define WspiapiGetAddrInfo getaddrinfo
85 #define WspiapiFreeAddrInfo freeaddrinfo
86 #endif
87 
88 addrinfo * DSL_Sockets3_Base::pResolve(DSL_SOCKET * sock, const char * host, int port) {
89  char buf[64]={0};
90 #if defined(itoa)
91  itoa(port, buf, 10);
92 #else
93  sprintf(buf, "%d", port);
94 #endif
95 
96  struct addrinfo hints, *ret;
97 
98  memset(&hints, 0, sizeof(hints));
99  hints.ai_family = sock->family;
100  hints.ai_socktype = sock->type;
101  hints.ai_protocol = sock->proto;
102  int error = WspiapiGetAddrInfo(host, buf, &hints, &ret);//getaddrinfo
103  if (error) {
104  pUpdateError(sock);
105  return NULL;
106  }
107 
108  return ret;
109 }
110 
111 void DSL_Sockets3_Base::pFreeAddrInfo(addrinfo * ai) {
112  WspiapiFreeAddrInfo(ai);//freeaddrinfo(
113 }
114 
115 bool DSL_Sockets3_Base::pUpdateAddrInfo(DSL_SOCKET * sock) {
116  sockaddr_storage addr;
117  socklen_t addrLen = sizeof(addr);
118 
119  sock->remote_ip[0]=0;
120  sock->remote_port=0;
121  sock->local_ip[0]=0;
122  sock->local_port=0;
123 
124  bool ret = true;
125 
126  char port[DS3_MAX_SERVLEN]={0};
127  if (getpeername(sock->sock, (sockaddr *)&addr, &addrLen) == 0) {
128  if (getnameinfo((sockaddr *)&addr, addrLen, sock->remote_ip, sizeof(sock->remote_ip), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV) == 0) {
129  sock->remote_port = atoi(port);
130  } else {
131  ret = false;
132  }
133  } else {
134  ret = false;
135  }
136 
137  addrLen = ADDRLEN;
138  if (getsockname(sock->sock, (sockaddr *)&addr, &addrLen) == 0) {
139  if (getnameinfo((sockaddr *)&addr, addrLen, sock->local_ip, sizeof(sock->local_ip), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV) == 0) {
140  sock->local_port = atoi(port);
141  }
142  }
143 
144  return ret;
145 }
146 
147 bool DSL_Sockets3_Base::IsKnownSocket(DSL_SOCKET * sock) {
148  AutoMutexPtr(hMutex);
149  if (sock != NULL) {
150  knownSocketList::const_iterator i = sockets.find(sock);
151  if (i != sockets.end()) {
152  return true;
153  }
154  }
155  return false;
156 }
157 
158 DSL_SOCKET * DSL_Sockets3_Base::pAllocSocket() {
159  return new DSL_SOCKET();
160 }
161 
162 DSL_SOCKET * DSL_Sockets3_Base::Create(int family, int type, int proto, uint32 flags) {
163  DSL_SOCKET * ret = pAllocSocket();
164 
165  ret->family = family;
166  ret->type = type;
167  ret->proto = proto;
168  ret->sock = socket(family,type,proto);
169 #ifdef WIN32
170  if (ret->sock == INVALID_SOCKET) {
171 #else
172  if (ret->sock == -1) {
173 #endif
174  pUpdateError(ret);
175  delete ret;
176  return NULL;
177  }
178 
179  if (flags & DS3_FLAG_ZIP) {
180 #ifdef ENABLE_ZLIB
181  ret->flags |= DS3_FLAG_ZIP;
182 #else
183  strcpy(bError,"DSL has not been compiled with zlib support");
184  bErrNo = 0x54530000;
185  this->Close(ret);
186  return NULL;
187 #endif
188  }
189 
190  hMutex->Lock();
191  sockets.insert(ret);
192  hMutex->Release();
193  return ret;
194 }
195 
196 bool DSL_Sockets3_Base::IsEnabled(unsigned int flag) {
197  if ((enabled_flags & flag) == flag) {
198  return true;
199  }
200  return false;
201 }
202 
203 bool DSL_Sockets3_Base::IsSupported(unsigned int flag) {
204  if ((avail_flags & flag) == flag) {
205  return true;
206  }
207  return false;
208 }
209 
210 DSL_SOCKET * DSL_Sockets3_Base::Accept(DSL_SOCKET * s, uint32 flags) {
211  sockaddr_storage addr;
212  memset(&addr, 0, sizeof(addr));
213  socklen_t addrlen = sizeof(addr);
214  return Accept(s, (sockaddr *)&addr, &addrlen, flags);
215 }
216 
217 DSL_SOCKET * DSL_Sockets3_Base::Accept(DSL_SOCKET * s, sockaddr *addr, socklen_t *addrlen, uint32 flags) {
218  DSL_SOCKET * ret = pAllocSocket();
219  memset(addr, 0, *addrlen);
220  ret->sock = accept(s->sock,addr,addrlen);
221 #ifdef WIN32
222  if (ret->sock == INVALID_SOCKET) {
223 #else
224  if (ret->sock == -1) {
225 #endif
226  pUpdateError(ret);
227  delete ret;
228  return NULL;
229  }
230 
231  hMutex->Lock();
232  sockets.insert(ret);
233  hMutex->Release();
234 
235  pUpdateAddrInfo(ret);
236 
237  if (flags & DS3_FLAG_SSL) {
238  DSL_Sockets3_SSL * ssl = dynamic_cast<DSL_Sockets3_SSL *>(this);
239  if (ssl) {
240  if (IsEnabled(DS3_FLAG_SSL)) {
241  if (ssl->SwitchToSSL_Server(ret)) {
242  ret->flags |= DS3_FLAG_SSL;
243  } else {
244  Close(ret);
245  return NULL;
246  }
247  } else {
248  strcpy(bError, "SSL has not been enabled!");
249  bErrNo = 0x54530000;
250  this->Close(ret);
251  return NULL;
252  }
253  } else {
254  this->Close(ret);
255  strcpy(bError, "DSL has not been compiled with SSL support");
256  bErrNo = 0x54530000;
257  return NULL;
258  }
259  }
260 
261  if (flags & DS3_FLAG_ZIP) {
262 #ifdef ENABLE_ZLIB
263  ret->flags |= DS3_FLAG_ZIP;
264 #else
265  this->Close(ret);
266  strcpy(bError,"DSL has not been compiled with zlib support");
267  bErrNo = 0x54530000;
268  return NULL;
269 #endif
270  }
271  return ret;
272 }
273 
274 bool DSL_Sockets3_Base::BindToAddr(DSL_SOCKET * sock, const char * host, int port) {
275 #if defined(DEBUG)
276  char buf[NI_MAXHOST], sport[NI_MAXSERV];
277 #endif
278 
279  if (sock->family == AF_UNIX) {
280  struct sockaddr_un addr;
281  memset(&addr, 0, sizeof(addr));
282  addr.sun_family = sock->family;
283  if (*host == '\0') {
284  *addr.sun_path = '\0';
285  strlcpy(addr.sun_path + 1, host + 1, sizeof(addr.sun_path) - 1);
286  } else {
287  sstrcpy(addr.sun_path, host);
288  if (access(host, F_OK) == 0) {
289  unlink(host);
290  }
291  }
292  int ret = bind(sock->sock, (struct sockaddr*)&addr, sizeof(addr));
293  if (ret == 0) {
294 #if defined(DEBUG)
295  if (getnameinfo((struct sockaddr*)&addr, sizeof(addr), buf, sizeof(buf), sport, sizeof(sport), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
296  printf("DSL_Sockets3_Base::BindToAddr() -> Bound to %s:%s\n", buf, sport);
297  }
298 #endif
299  return true;
300  } else {
301  pUpdateError(sock);
302  return false;
303  }
304  }
305 
306  bool bret = false;
307  bool tried = false;
308  addrinfo * ai = pResolve(sock, host, port);
309  if (ai) {
310  addrinfo * Scan = ai;
311  while (!bret && Scan) {
312  if (Scan->ai_family == sock->family || sock->family == AF_UNSPEC) {
313  if (port > 0 && Scan->ai_family == AF_INET) {
314  ((sockaddr_in *)Scan->ai_addr)->sin_port = htons(port);
315  }
316  if (port > 0 && Scan->ai_family == AF_INET6) {
317  ((sockaddr_in6 *)Scan->ai_addr)->sin6_port = htons(port);
318  }
319  tried = true;
320  int ret = bind(sock->sock, Scan->ai_addr, Scan->ai_addrlen);
321  if (ret == 0) {
322 #if defined(DEBUG)
323  if (getnameinfo(Scan->ai_addr, Scan->ai_addrlen, buf, sizeof(buf), sport, sizeof(sport), NI_NUMERICHOST|NI_NUMERICSERV) == 0) {
324  printf("DSL_Sockets3_Base::BindToAddr() -> Bound to %s:%s\n", buf, sport);
325  }
326 #endif
327  bret = true;
328  } else {
329  pUpdateError(sock);
330 #if defined(DEBUG)
331  if (getnameinfo(Scan->ai_addr, Scan->ai_addrlen, buf, sizeof(buf), sport, sizeof(sport), NI_NUMERICHOST|NI_NUMERICSERV) == 0) {
332  printf("DSL_Sockets3_Base::BindToAddr() -> Error binding %s:%s\n", buf, sport);
333  }
334 #endif
335  }
336  }
337  Scan = Scan->ai_next;
338  }
339  pFreeAddrInfo(ai);
340  }
341  if (!tried) {
342  pUpdateError(sock, 999, "Could not resolve any addresses matching address family.");
343  }
344  return bret;
345 }
346 
347 bool DSL_Sockets3_Base::Bind(DSL_SOCKET * sock, int port) {
348  if (sock->family == AF_UNIX) {
349  pUpdateError(sock, 999, "Bind() does not support Unix Domain Sockets.");
350  /* use BindToAddr() with the filename in the addr field. port is ignored for AF_UNIX sockets */
351  return false;
352  }
353 
354  int ret=0;
355 #if !defined(NO_IPV6)
356  if (sock->family == AF_INET6) {
357  sockaddr_in6 addr;
358  memset(&addr, 0, sizeof(addr));
359  addr.sin6_family = AF_INET6;
360  addr.sin6_port = htons(port);
361  ret = bind(sock->sock,(const sockaddr *)&addr, sizeof(sockaddr_in6));
362  } else {
363 #endif
364  sockaddr_in addr;
365  memset(&addr, 0, sizeof(addr));
366  addr.sin_addr.s_addr = INADDR_ANY;
367  addr.sin_family = AF_INET;
368  addr.sin_port = htons(port);
369  memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
370  ret = bind(sock->sock,(const sockaddr *)&addr, sizeof(sockaddr_in));
371 #if !defined(NO_IPV6)
372  }
373 #endif
374  pUpdateError(sock);
375  return (ret == 0) ? true:false;
376 }
377 
378 bool DSL_Sockets3_Base::Listen(DSL_SOCKET * sock, int backlog) {
379  int ret = listen(sock->sock,backlog);
380  if (ret) {
381  pUpdateError(sock);
382  return false;
383  }
384  return true;
385 }
386 
387 int DSL_Sockets3_Base::Close(DSL_SOCKET * sock) {
388  if (sock == NULL) { return -1; }
389 
390  hMutex->Lock();
391  knownSocketList::iterator x = sockets.find(sock);
392  if (x != sockets.end()) {
393  sockets.erase(x);
394  }
395  hMutex->Release();
396 
397  SOCKET s = sock->sock;
398 
399  if (sock->flags & DS3_FLAG_SSL) {
400  DSL_Sockets3_SSL * ssl = dynamic_cast<DSL_Sockets3_SSL *>(this);
401  if (ssl) {
402  ssl->pCloseSSL(sock);
403  } else {
404  delete sock;
405  }
406  } else {
407  delete sock;
408  }
409 
410 #if defined(WIN32)
411  return closesocket(s);
412 #else
413  return close(s);
414 #endif
415 }
416 
417 int DSL_Sockets3_Base::GetFamilyHint(const char * host, int port) {
418  DSL_SOCKET sock;
419  sock.family = PF_UNSPEC;
420  addrinfo * ai = pResolve(&sock, host, port);
421  int ret = PF_INET;
422  if (ai) {
423  ret = ai->ai_family;
424  pFreeAddrInfo(ai);
425  }
426  return ret;
427 }
428 
429 bool DSL_Sockets3_Base::Connect(DSL_SOCKET * sock, sockaddr * addr, size_t addrlen) {
430  if (connect(sock->sock,addr,addrlen) != 0) {
431  pUpdateError(sock);
432  pUpdateAddrInfo(sock);
433  return false;
434  }
435  pUpdateAddrInfo(sock);
436  return true;
437 }
438 
439 bool DSL_Sockets3_Base::Connect(DSL_SOCKET * sock, const char * host, int port) {
440  if (sock->family == AF_UNIX) {
441  struct sockaddr_un addr;
442  memset(&addr, 0, sizeof(addr));
443  addr.sun_family = sock->family;
444  if (*host == '\0') {
445  *addr.sun_path = '\0';
446  strlcpy(addr.sun_path + 1, host + 1, sizeof(addr.sun_path) - 1);
447  } else {
448  sstrcpy(addr.sun_path, host);
449  }
450  int ret = connect(sock->sock, (struct sockaddr*)&addr, sizeof(addr));
451  if (ret == 0) {
452  return true;
453  } else {
454  pUpdateError(sock);
455  return false;
456  }
457  }
458 
459  addrinfo * ai = pResolve(sock, host, port);
460  bool ret = false;
461  if (ai) {
462  addrinfo * Scan = ai;
463  while (Scan && !(ret = Connect(sock,Scan->ai_addr,Scan->ai_addrlen)) && !sock->nonblocking) {
464  Scan = Scan->ai_next;
465  }
466  if (!ret) { pUpdateError(sock); }
467  pFreeAddrInfo(ai);
468  return ret;
469  } else {
470  //pResolve should have set an error
471  return false;
472  }
473 }
474 
475 bool DSL_Sockets3_Base::ConnectWithTimeout(DSL_SOCKET * sock, const char * host, int port, uint32 timeout) {
476  if (sock->family == AF_UNIX) {
477  pUpdateError(sock, 999, "ConnectWithTimeout() does not support Unix Domain Sockets.");
478  return false;
479  }
480 
481  addrinfo * ai = pResolve(sock, host, port);
482  if (ai == NULL) {
483  //pResolve should have set an error
484  return false;
485  }
486 
487  bool nb = sock->nonblocking;
488  if (!nb) {
489  SetNonBlocking(sock,true);
490  }
491 
492  bool ret = false;
493 
494  addrinfo * Scan = ai;
495  timeval timeo;
496  int tries=5;
497  while (Scan && tries--) {
498  Connect(sock, Scan->ai_addr, Scan->ai_addrlen);
499 #if defined(DEBUG)
500  printf("DSL_Sockets3_Base::ConnectWithTimeout(%s:%d): Trying %s ...\n", host, port, sock->remote_ip);
501 #endif
502  memset(&timeo,0,sizeof(timeo));
503  timeo.tv_sec = (timeout / 1000);
504  timeo.tv_usec = timeout - (timeo.tv_sec * 1000);
505  timeo.tv_usec *= 1000;//convert to microseconds
506  if (Select_Write(sock, &timeo) > 0) {
507  if (pUpdateAddrInfo(sock)) { /* select() sometimes returns writeable even on failure, this should catch those edge cases */
508  ret = true;
509  break;
510  }
511  }
512  Scan = Scan->ai_next;
513  }
514  //if (!ret) { pUpdateError(sock); }
515 
516  if (!nb) {
517  SetNonBlocking(sock,false);
518  }
519  pFreeAddrInfo(ai);
520  return ret;
521 }
522 
523 int DSL_Sockets3_Base::Send(DSL_SOCKET * sock, const char * data_in, int datalen, bool doloop) {
524  char * data = (char *)data_in;
525  if (datalen == -1) { datalen = strlen(data); }
526 
527 #ifdef ENABLE_ZLIB
528  if (sock->flags & DS3_FLAG_ZIP) {
529  unsigned long dlen = compressBound(datalen)+9;
530  char * data2 = (char *)dsl_malloc(dlen);
531  if (compress2((Bytef *)data2+9, &dlen, (Bytef *)data, datalen, 5) == Z_OK && dlen < datalen) {
532  data2[0] = 'Z';
533  memcpy(data2+1, &dlen, 4);
534  memcpy(data2+5, &datalen, 4);
535  datalen = dlen+9;
536  } else {
537  data2[0] = 'U';
538  memcpy(data2+1, &datalen, 4);
539  memcpy(data2+5, data, datalen);
540  datalen = datalen+5;
541  }
542  data = data2;
543  }
544 #endif
545 
546  if (datalen == 0) { return 0; }
547  int left = datalen;
548  int n = 0;
549  do {
550  int o = pSend(sock,data+n,left);
551  switch(o) {
552  case -1:
553  pUpdateError(sock);
554 #ifdef ENABLE_ZLIB
555  if (sock->flags & DS3_FLAG_ZIP) {
556  dsl_free(data);
557  }
558 #endif
559  return -1;
560  case 0:
561  pUpdateError(sock);
562 #ifdef ENABLE_ZLIB
563  if (sock->flags & DS3_FLAG_ZIP) {
564  dsl_free(data);
565  }
566 #endif
567  return 0;
568  default:
569  left -= o;
570  n += o;
571  break;
572  }
573  } while (left > 0 && doloop);
574 
575 #ifdef ENABLE_ZLIB
576  if (sock->flags & DS3_FLAG_ZIP) {
577  dsl_free(data);
578  }
579 #endif
580  return n;
581 }
582 
583 int DSL_Sockets3_Base::pSend(DSL_SOCKET * sock, const char * data, uint32 datalen) {
584  return send(sock->sock, data, datalen, 0);
585 }
586 
587 int DSL_Sockets3_Base::SendTo(DSL_SOCKET * sock, const char * host, int port, const char * data_in, int datalen) {
588  char * data = (char *)data_in;
589  if (sock->flags & DS3_FLAG_SSL) {
590  sprintf(bError, "SendTo doesn't work with SSL");
591  bErrNo = 0x54530000;
592  return -1;
593  }
594 
595  if (datalen == -1) { datalen = strlen(data); }
596 
597 #ifdef ENABLE_ZLIB
598  if (sock->flags & DS3_FLAG_ZIP) {
599  unsigned long dlen = compressBound(datalen)+9;
600  char * data2 = (char *)dsl_malloc(dlen);
601  if (compress2((Bytef *)data2+9, &dlen, (Bytef *)data, datalen, 5) == Z_OK && dlen < datalen) {
602  data2[0] = 'Z';
603  memcpy(data2+1, &dlen, 4);
604  memcpy(data2+5, &datalen, 4);
605  datalen = dlen+9;
606  } else {
607  data2[0] = 'U';
608  memcpy(data2+1, &datalen, 4);
609  memcpy(data2+5, data, datalen);
610  datalen = datalen+5;
611  }
612  data = data2;
613  }
614 #endif
615 
616  addrinfo * ai = pResolve(sock, host, port);
617  if (ai) {
618  int ret = sendto(sock->sock,data,datalen,0,ai->ai_addr,ai->ai_addrlen);
619  if (ret <= 0) { pUpdateError(sock); }
620  pUpdateAddrInfo(sock);
621 #ifdef ENABLE_ZLIB
622  if (sock->flags & DS3_FLAG_ZIP) {
623  dsl_free(data);
624  }
625 #endif
626  return ret;
627  }
628  pUpdateError(sock);
629 #ifdef ENABLE_ZLIB
630  if (sock->flags & DS3_FLAG_ZIP) {
631  dsl_free(data);
632  }
633 #endif
634  return -1;
635 }
636 
637 int DSL_Sockets3_Base::RecvFrom(DSL_SOCKET * sock, char * host, uint32 hostSize, int * port, char * buf, uint32 bufsize) {
638  if (sock->flags & DS3_FLAG_SSL) {
639  sprintf(bError, "RecvFrom doesn't work with SSL");
640  bErrNo = 0x54530000;
641  return -1;
642  }
643 
644  sockaddr * addr = (sockaddr *)dsl_malloc(ADDRLEN);
645  memset(addr, 0, ADDRLEN);
646 #if defined(WIN32)
647  int addrLen = ADDRLEN;
648 #else
649  socklen_t addrLen = ADDRLEN;
650 #endif
651  int n = recvfrom(sock->sock,buf,bufsize,0, (sockaddr *)addr, &addrLen);
652  if (n <= 0) { pUpdateError(sock); }
653 
654  if (addr->sa_family == AF_INET) {
655  sockaddr_in * p = (sockaddr_in *)addr;
656  inet_ntop(addr->sa_family, &p->sin_addr, sock->remote_ip, sizeof(sock->remote_ip));
657  sock->remote_port = ntohs(p->sin_port);
658  } else if (addr->sa_family == AF_INET6) {
659  sockaddr_in6 * p = (sockaddr_in6 *)addr;
660  inet_ntop(addr->sa_family, &p->sin6_addr, sock->remote_ip, sizeof(sock->remote_ip));
661  sock->remote_port = ntohs(p->sin6_port);
662  } else {
663  sprintf(bError, "Unknown address family!");
664  bErrNo = 0x54530000;
665  return -1;
666  }
667 
668  //pUpdateAddrInfo(sock);
669  if (host) {
670  memset(host, 0, hostSize);
671  strncpy(host, sock->remote_ip, hostSize-1);
672  }
673  if (port) {
674  *port = sock->remote_port;
675  }
676 
677  dsl_free(addr);
678  return n;
679 }
680 
681 int DSL_Sockets3_Base::pRecv(DSL_SOCKET * sock, char * buf, uint32 bufsize) {
682  int n = recv(sock->sock,buf,bufsize,0);
683  if (n <= 0) { pUpdateError(sock); }
684  if (n < 0) { n = -1; }
685  return n;
686 }
687 
688 int DSL_Sockets3_Base::pPeek(DSL_SOCKET * sock, char * buf, uint32 bufsize) {
689  int n = recv(sock->sock,buf,bufsize,MSG_PEEK);
690  if (n <= 0) { pUpdateError(sock); }
691  if (n < 0) { n = -1; }
692  return n;
693 }
694 
695 int DSL_Sockets3_Base::Recv(DSL_SOCKET * sock, char * buf, uint32 bufsize) {
696 #ifdef ENABLE_ZLIB
697  int n = 0;
698  if (sock->flags & DS3_FLAG_ZIP) {
699  if (bufsize < 8) {
700  bErrNo = 0x54530021;
701  strcpy(bError,"Buffer too small");
702  return -1;
703  }
704 
705  n = pRecv(sock, buf, 1);
706  if (n <= 0) {
707  return n;
708  }
709 
710  //printf("ZIP-Type: %c\n", buf[0]);
711  if (buf[0] == 'Z') {
712  pRecv(sock, buf, 8);
713  char *p = buf;
714  uint32 * sizec = (uint32 *)p;
715  p += 4;
716  uint32 * sizeu = (uint32 *)p;
717  if (*sizeu > bufsize) {
718  bErrNo = 0x54530021;
719  strcpy(bError,"Buffer too small");
720  return -1;
721  } else {
722  uint32 left = *sizec;
723  uLongf size = *sizeu;
724  uint32 ind = 0;
725  char * tmp = (char *)dsl_malloc(left);
726  while (left) {
727  n = pRecv(sock, tmp+ind, left);
728  if (n <= 0) {
729  return n;
730  }
731  ind += n;
732  left -= n;
733  }
734  if (uncompress((Bytef *)buf, (uLongf *)&size, (Bytef *)tmp, ind) == Z_OK) {
735  dsl_free(tmp);
736  return size;
737  } else {
738  dsl_free(tmp);
739  bErrNo = 0x54530022;
740  strcpy(bError,"Error uncompressing data stream");
741  return -1;
742  }
743  }
744  } else if (buf[0] == 'U') {
745  pRecv(sock, buf, 4);
746  uint32 * size = (uint32 *)buf;
747  if (*size > bufsize) {
748  bErrNo = 0x54530021;
749  strcpy(bError,"Buffer too small");
750  n = -1;
751  } else {
752  uint32 left = *size;
753  uint32 ind = 0;
754  while (left) {
755  n = pRecv(sock, buf+ind, left);
756  if (n <= 0) {
757  return n;
758  }
759  ind += n;
760  left -= n;
761  }
762  return ind;
763  }
764  } else {
765  bErrNo = 0x54530020;
766  strcpy(bError,"ERROR: Stream does not appear to be zipped!");
767  return -1;
768  }
769  }
770 #endif
771  return pRecv(sock,buf,bufsize);
772 }
773 
774 int DSL_Sockets3_Base::Peek(DSL_SOCKET * sock, char * buf, uint32 bufsize) {
775  return pPeek(sock,buf,bufsize);
776 }
777 
778 int DSL_Sockets3_Base::PeekFrom(DSL_SOCKET * sock, char * host, uint32 hostSize, int * port, char * buf, uint32 bufsize) {
779  if (sock->flags & DS3_FLAG_SSL) {
780  sprintf(bError, "PeekFrom doesn't work with SSL");
781  bErrNo = 0x54530000;
782  return -1;
783  }
784 
785  sockaddr * addr = (sockaddr *)dsl_malloc(ADDRLEN);
786  memset(addr, 0, ADDRLEN);
787 #if defined(WIN32)
788  int addrLen = ADDRLEN;
789 #else
790  socklen_t addrLen = ADDRLEN;
791 #endif
792  int n = recvfrom(sock->sock,buf,bufsize, MSG_PEEK, (sockaddr *)addr, &addrLen);
793  if (n <= 0) { pUpdateError(sock); }
794 
795  pUpdateAddrInfo(sock);
796  if (host) {
797  memset(host, 0, hostSize);
798  strncpy(host, sock->remote_ip, hostSize-1);
799  }
800  if (port) {
801  *port = sock->remote_port;
802  }
803 
804  dsl_free(addr);
805  return n;
806 }
807 
808 int DSL_Sockets3_Base::RecvLine(DSL_SOCKET * sock, char * buf, int bufsize) {
809  int n = Peek(sock,buf,bufsize - 1);
810  if (n < 0) { return RL3_ERROR; }
811  if (n == 0) { return RL3_CLOSED; }
812 
813  buf[n]=0;
814  char *p = strchr(buf, '\n');
815  //if (p == NULL) { p = strchr(buf,'\r'); }
816  if (p != NULL) {
817  n = (p - buf) + 1;
818  memset(buf, 0, bufsize);
819  Recv(sock,buf,n);
820  while (buf[strlen(buf) - 1] == '\n') { buf[strlen(buf) - 1] = 0; }
821  while (buf[strlen(buf) - 1] == '\r') { buf[strlen(buf) - 1] = 0; }
822  return strlen(buf);
823  } else if (n == (bufsize-1)) {
824  return RL3_LINETOOLONG;
825  }
826 
827  return RL3_NOLINE;
828 }
829 
830 int DSL_Sockets3_Base::RecvLineFrom(DSL_SOCKET * sock, char * host, uint32 hostSize, int * port, char * buf, uint32 bufsize) {
831  int n = PeekFrom(sock, host, hostSize, port, buf,bufsize - 1);
832  if (n <= 0) { pUpdateError(sock); }
833  if (n < 0) { return RL3_ERROR; }
834  if (n == 0) { return RL3_CLOSED; }
835 
836  buf[n]=0;
837  char *p = strchr(buf,'\n');
838  if (p != NULL) {
839  n = (p - buf) + 1;
840  memset(buf, 0, bufsize);
841  RecvFrom(sock, host, hostSize, port, buf,n);
842  while (buf[strlen(buf) - 1] == '\n') { buf[strlen(buf) - 1] = 0; }
843  while (buf[strlen(buf) - 1] == '\r') { buf[strlen(buf) - 1] = 0; }
844  return strlen(buf);
845  }
846 
847  return RL3_NOLINE;
848 }
849 
850 int DSL_Sockets3_Base::Select_Read(DSL_SOCKET * sock, uint32 millisec) {
851  timeval timeo;
852  timeo.tv_sec = millisec / 1000;
853  millisec -= (timeo.tv_sec * 1000);
854  timeo.tv_usec = (millisec * 1000);
855  return Select_Read(sock, &timeo);
856 }
857 
858 int DSL_Sockets3_Base::pSelect_Read(DSL_SOCKET * sock, timeval * timeo) {
859  fd_set fd;
860  FD_ZERO(&fd);
861  FD_SET(sock->sock, &fd);
862  int ret = select(sock->sock + 1, &fd, NULL, NULL, timeo);
863  if (ret < 0) { pUpdateError(sock); }
864  return ret;
865 }
866 
867 int DSL_Sockets3_Base::Select_Read(DSL_SOCKET * sock, timeval * timeo) {
868  return pSelect_Read(sock, timeo);
869 }
870 
871 int DSL_Sockets3_Base::Select_List(DSL_SOCKET_LIST * list_r, DSL_SOCKET_LIST * list_w, timeval * timeo) {
872  fd_set fd, fd2;
873  FD_ZERO(&fd);
874  FD_ZERO(&fd2);
875  SOCKET high = 0;
876  DSL_SOCKET_LIST tmp, tmp2;
877 
878  if (list_r) {
879  DFD_COPY(list_r, &tmp);
880  for (auto x = list_r->socks.begin(); x != list_r->socks.end(); x++) {
881  if ((*x)->sock > high) {
882  high = (*x)->sock;
883  }
884  FD_SET((*x)->sock, &fd);
885  }
886  DFD_ZERO(list_r);
887  }
888 
889  if (list_w) {
890  DFD_COPY(list_w, &tmp2);
891  for (auto x = list_w->socks.begin(); x != list_w->socks.end(); x++) {
892  if ((*x)->sock > high) {
893  high = (*x)->sock;
894  }
895  FD_SET((*x)->sock, &fd2);
896  }
897  DFD_ZERO(list_w);
898  }
899 
900  int ret = select(high+1, list_r ? &fd : NULL, list_w ? &fd2 : NULL, NULL, timeo);
901  if (ret < 0) { pUpdateError(NULL); }
902 
903  if (list_r) {
904  for (auto x = tmp.socks.begin(); x != tmp.socks.end(); x++) {
905  if (FD_ISSET((*x)->sock, &fd)) {
906  DFD_SET(list_r, *x);
907  }
908  }
909  }
910 
911  if (list_w) {
912  for (auto x = tmp2.socks.begin(); x != tmp2.socks.end(); x++) {
913  if (FD_ISSET((*x)->sock, &fd2)) {
914  DFD_SET(list_w, *x);
915  }
916  }
917  }
918 
919  return ret;
920 }
921 
922 int DSL_Sockets3_Base::Select_List(DSL_SOCKET_LIST * list_r, DSL_SOCKET_LIST * list_w, uint32 millisec) {
923  timeval timeo;
924  timeo.tv_sec = millisec / 1000;
925  millisec -= (timeo.tv_sec * 1000);
926  timeo.tv_usec = (millisec * 1000);
927  return Select_List(list_r, list_w, &timeo);
928 }
929 
930 int DSL_Sockets3_Base::Select_Read_List(DSL_SOCKET_LIST * list_r, timeval * timeo) {
931  fd_set fd;
932  FD_ZERO(&fd);
933  SOCKET high = 0;
934  DSL_SOCKET_LIST tmp;
935 
936  if (list_r) {
937  tmp.socks = list_r->socks;
938  for (auto x = list_r->socks.begin(); x != list_r->socks.end(); x++) {
939  if ((*x)->sock > high) {
940  high = (*x)->sock;
941  }
942  FD_SET((*x)->sock, &fd);
943  }
944  DFD_ZERO(list_r);
945  }
946 
947  int ret = select(high+1, list_r ? &fd : NULL, NULL, NULL, timeo);
948  if (ret < 0) { pUpdateError(NULL); }
949 
950  if (list_r) {
951  for (auto x = tmp.socks.begin(); x != tmp.socks.end(); x++) {
952  if (FD_ISSET((*x)->sock, &fd)) {
953  DFD_SET(list_r, *x);
954  }
955  }
956  }
957 
958  return ret;
959 }
960 
962  timeval timeo;
963  timeo.tv_sec = millisec / 1000;
964  millisec -= (timeo.tv_sec * 1000);
965  timeo.tv_usec = (millisec * 1000);
966  return Select_Read_List(list, &timeo);
967 }
968 
969 int DSL_Sockets3_Base::Select_Write(DSL_SOCKET * sock, timeval * timeo) {
970  fd_set fd;
971  FD_ZERO(&fd);
972  FD_SET(sock->sock, &fd);
973  int ret = select(sock->sock+1,NULL,&fd,NULL,timeo);
974  if (ret < 0) { pUpdateError(sock); }
975  return ret;
976 }
977 
978 int DSL_Sockets3_Base::Select_Write(DSL_SOCKET * sock, uint32 millisec) {
979  timeval timeo;
980  timeo.tv_sec = millisec / 1000;
981  millisec -= (timeo.tv_sec * 1000);
982  timeo.tv_usec = (millisec * 1000);
983  return Select_Write(sock, &timeo);
984 
985 }
986 
987 int DSL_Sockets3_Base::SetLinger(DSL_SOCKET * sock, bool linger, unsigned short timeo) {
988  struct linger lin = { linger ? 1:0, linger ? timeo:0 };
989  int ret = setsockopt(sock->sock, SOL_SOCKET, SO_LINGER, (char *)&lin, sizeof(lin));
990  pUpdateError(sock);
991  return ret;
992 }
993 
994 int DSL_Sockets3_Base::SetReuseAddr(DSL_SOCKET * sock, bool reuse_addr) {
995  int ra = reuse_addr ? 1:0;
996  int ret = setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&ra, sizeof(ra));
997  pUpdateError(sock);
998  return ret;
999 }
1000 
1001 int DSL_Sockets3_Base::SetNoDelay(DSL_SOCKET * sock, bool no_delay) {
1002 #ifdef TCP_NODELAY
1003  int nodelay = no_delay ? 1:0;
1004  int ret = setsockopt(sock->sock, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(int));
1005  pUpdateError(sock);
1006  return ret;
1007 #else
1008  pUpdateError(sock, 999, "Feature not supported on this platform");
1009  return 0;
1010 #endif
1011 }
1012 
1013 int DSL_Sockets3_Base::SetKeepAlive(DSL_SOCKET * sock, bool ka) {
1014  int keepalive = ka ? 1:0;
1015  int ret = setsockopt(sock->sock,SOL_SOCKET,SO_KEEPALIVE,(char *)&keepalive,sizeof(int));
1016  pUpdateError(sock);
1017  return ret;
1018 }
1019 
1020 int DSL_Sockets3_Base::SetBroadcast(DSL_SOCKET * sock, bool broadcast) {
1021  int tmp = broadcast ? 1:0;
1022  int ret = setsockopt(sock->sock,SOL_SOCKET,SO_BROADCAST,(char *)&tmp,sizeof(tmp));
1023  pUpdateError(sock);
1024  return ret;
1025 }
1026 
1027 #if defined(WIN32)
1028 #ifndef SIO_UDP_CONNRESET
1029 #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
1030 #endif
1031 bool DSL_Sockets3_Base::DisableUDPConnReset(DSL_SOCKET * sock, bool noconnreset) {
1032  DWORD dwBytesReturned = 0;
1033  BOOL bNewBehavior = noconnreset ? false:true;
1034  return (WSAIoctl(sock->sock, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior), NULL, 0, &dwBytesReturned, NULL, NULL) == 0) ? true:false;
1035 }
1036 #else
1037 bool DSL_Sockets3_Base::DisableUDPConnReset(DSL_SOCKET * sock, bool noconnreset) {
1038  return true;
1039 }
1040 #endif
1041 
1042 
1043 int DSL_Sockets3_Base::SetRecvTimeout(DSL_SOCKET * sock, uint32 millisec) {
1044 #ifdef WIN32
1045  int ret = setsockopt(sock->sock,SOL_SOCKET,SO_RCVTIMEO,(char *)&millisec,sizeof(millisec));
1046 #else
1047  timeval tv;
1048  tv.tv_sec = millisec / 1000;
1049  tv.tv_usec = millisec - (tv.tv_sec * 1000);
1050  int ret = setsockopt(sock->sock,SOL_SOCKET,SO_RCVTIMEO,(char *)&tv,sizeof(tv));
1051 #endif
1052  pUpdateError(sock);
1053  return ret;
1054 }
1055 
1056 int DSL_Sockets3_Base::SetSendTimeout(DSL_SOCKET * sock, uint32 millisec) {
1057 #ifdef WIN32
1058  int ret = setsockopt(sock->sock,SOL_SOCKET,SO_SNDTIMEO,(char *)&millisec,sizeof(millisec));
1059 #else
1060  timeval tv;
1061  tv.tv_sec = millisec / 1000;
1062  tv.tv_usec = millisec - (tv.tv_sec * 1000);
1063  int ret = setsockopt(sock->sock,SOL_SOCKET,SO_SNDTIMEO,(char *)&tv,sizeof(tv));
1064 #endif
1065  pUpdateError(sock);
1066  return ret;
1067 }
1068 
1069 bool DSL_Sockets3_Base::IsNonBlocking(DSL_SOCKET * sock) {
1070  return sock->nonblocking;
1071 }
1072 
1073 void DSL_Sockets3_Base::SetNonBlocking(DSL_SOCKET * sock, bool non_blocking) {
1074  sock->nonblocking = non_blocking;
1075 #ifdef _WIN32
1076  unsigned long blah = non_blocking ? 1:0;
1077  ioctlsocket(sock->sock,FIONBIO,&blah);
1078 #else
1079  if (non_blocking){
1080  fcntl(sock->sock, F_SETFL, fcntl(sock->sock, F_GETFL) | O_NONBLOCK);
1081  } else {
1082  fcntl(sock->sock, F_SETFL, fcntl(sock->sock, F_GETFL) & ~O_NONBLOCK);
1083  }
1084 #endif
1085  pUpdateError(sock);
1086 }
1087 
1088 std::string DSL_Sockets3_Base::GetHostIP(const char * host, int type, int proto) {
1089  struct addrinfo hints, *ret, *scan;
1090  std::string str="";
1091 
1092  memset(&hints, 0, sizeof(hints));
1093  hints.ai_family = AF_UNSPEC;
1094  //hints.ai_socktype = type;
1095  //hints.ai_protocol = proto;
1096  int error = WspiapiGetAddrInfo(host, "", &hints, &ret);
1097  if (error) {
1098  pUpdateError(NULL);
1099  return str;
1100  }
1101 
1102  char buf[DS3_MAX_HOSTLEN];
1103  if (ret) {
1104  //sockaddr_in * sa = (sockaddr_in *)ret->ai_addr;
1105  scan = ret;
1106  while (scan) {
1107  if (getnameinfo(scan->ai_addr, scan->ai_addrlen, buf, sizeof(buf), NULL, 0, NI_NUMERICHOST|NI_NUMERICSERV) == 0) {
1108  str = buf;
1109  break;
1110  }
1111  scan = scan->ai_next;
1112  }
1113  //uint8 * b = (uint8 *)&sa->sin_addr;
1114  //char buf[16];
1115  //sprintf(buf, inet_ntoa(sa->sin_addr));
1116  //str = inet_ntoa(sa->sin_addr);
1117  WspiapiFreeAddrInfo(ret);//freeaddrinfo(
1118  }
1119  return str;
1120 }
1121 
1122 int DSL_Sockets3_Base::GetLastError(D_SOCKET * sock) {
1123  if (sock) { return sock->last_errno; }
1124  return bErrNo;
1125 }
1126 const char * DSL_Sockets3_Base::GetLastErrorString(D_SOCKET * sock) {
1127  if (sock) { return sock->last_error; }
1128  return bError;
1129 }
1130 
1131 void DSL_Sockets3_Base::pUpdateError(DSL_SOCKET * sock, int serrno, const char * errstr) {
1132  bErrNo = errno;
1133  sstrcpy(bError, errstr);
1134  if (sock != NULL) {
1135  sock->last_errno = bErrNo;
1136  sstrcpy(sock->last_error, bError);
1137  }
1138  if (!silent && bErrNo != 0 && bErrNo != EWOULDBLOCK && bErrNo != ENOTCONN && bErrNo != EINPROGRESS && bErrNo != ENOENT) {
1139  printf("pUpdateError(): %d -> %s\n",bErrNo,bError);
1140  }
1141 }
1142 
1143 void DSL_Sockets3_Base::pUpdateError(DSL_SOCKET * sock) {
1144 #if defined(WIN32)
1145  bErrNo = WSAGetLastError();
1146  if (bErrNo) {
1147  bError[sizeof(bError)-1] = 0;
1148  if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, bErrNo, LANG_SYSTEM_DEFAULT, bError, sizeof(bError)-1, NULL) == 0) {
1149  sstrcpy(bError, "Error getting error message!");
1150  }
1151  }
1152 #else
1153  bErrNo = errno;
1154  if (bErrNo != 0) {
1155  char *error = strerror(bErrNo);
1156  if (error) {
1157  sstrcpy(bError,error);
1158  } else {
1159  sprintf(bError,"Unknown Error (Code: %d)",bErrNo);
1160  }
1161  }
1162 #endif
1163  if (sock != NULL) {
1164  sock->last_errno = bErrNo;
1165  sstrcpy(sock->last_error, bError);
1166  }
1167  if (bErrNo != 0 && bErrNo != EWOULDBLOCK && bErrNo != ENOTCONN && bErrNo != EINPROGRESS && bErrNo != ENOENT && !silent) {
1168  printf("pUpdateError(): %d -> %s\n",bErrNo,bError);
1169  }
1170 }
virtual int Select_Read_List(DSL_SOCKET_LIST *list, timeval *timeo)
same return value as select(). Use below functions to build your lists.
Definition: sockets3.cpp:930
virtual bool IsSupported(unsigned int flag)
This lets you know if a feature is supported.
Definition: sockets3.cpp:203
virtual int GetFamilyHint(const char *host, int port)
Returns PF_INET or PF_INET6 for a domain or IP address.
Definition: sockets3.cpp:417
virtual bool IsEnabled(unsigned int flag)
This lets you know if a feature is supported and activated (ie. EnableSSL() has been called)
Definition: sockets3.cpp:196
virtual int Select_List(DSL_SOCKET_LIST *list_r, DSL_SOCKET_LIST *list_w, timeval *timeo)
same return value as select()
Definition: sockets3.cpp:871
virtual int Select_Read(DSL_SOCKET *sock, timeval *timeo)
same return value as select()
Definition: sockets3.cpp:867
virtual bool BindToAddr(DSL_SOCKET *sock, const char *host, int port)
Bind to specific IP.
Definition: sockets3.cpp:274
virtual int PeekFrom(DSL_SOCKET *sock, char *host, uint32 hostSize, int *port, char *buf, uint32 bufsize)
For UDP/datagram sockets, same details otherwise as Peek()
Definition: sockets3.cpp:778
virtual int SendTo(DSL_SOCKET *sock, const char *host, int port, const char *buf, int datalen=-1)
For UDP/datagram sockets, same details otherwise as Send()
Definition: sockets3.cpp:587
virtual bool Bind(DSL_SOCKET *sock, int port)
Bind to all interfaces (0.0.0.0)
Definition: sockets3.cpp:347
virtual int RecvLineFrom(DSL_SOCKET *sock, char *host, uint32 hostSize, int *port, char *buf, uint32 bufsize)
For UDP/datagram sockets, same details otherwise as RecvLine()
Definition: sockets3.cpp:830
virtual int Select_Write(DSL_SOCKET *sock, timeval *timeo)
same return value as select()
Definition: sockets3.cpp:969
virtual bool ConnectWithTimeout(DSL_SOCKET *sock, const char *host, int port, uint32 timeout)
Connect with timeout in milliseconds.
Definition: sockets3.cpp:475
virtual int RecvFrom(DSL_SOCKET *sock, char *host, uint32 hostSize, int *port, char *buf, uint32 bufsize)
For UDP/datagram sockets, same details otherwise as Recv()
Definition: sockets3.cpp:637
virtual void Silent(bool bSilent)
Don't print socket errors to the console.
Definition: sockets3.cpp:44
DSL_API void DSL_CC dsl_free(void *ptr)
Definition: dsl.cpp:345
DSL_API void dsl_cleanup()
Definition: dsl.cpp:77
DSL_API bool DSL_CC dsl_init()
Definition: dsl.cpp:45
DSL_API size_t DSL_CC strlcpy(char *dst, const char *src, size_t siz)
Definition: GenLib.cpp:905
#define sstrcpy(x, y)
Definition: GenLib.h:102