Coverage Report

Created: 2026-10-26 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpac/src/utils/os_net.c
Line
Count
Source
1
/*
2
 *      GPAC - Multimedia Framework C SDK
3
 *
4
 *      Authors: Jean Le Feuvre
5
 *      Copyright (c) Telecom ParisTech 2000-2026
6
 *          All rights reserved
7
 *
8
 *  This file is part of GPAC / common tools sub-project
9
 *
10
 *  GPAC is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU Lesser General Public License as published by
12
 *  the Free Software Foundation; either version 2, or (at your option)
13
 *  any later version.
14
 *
15
 *  GPAC is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU Lesser General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU Lesser General Public
21
 *  License along with this library; see the file COPYING.  If not, write to
22
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23
 *
24
 */
25
26
#include <gpac/network.h>
27
28
#ifndef GPAC_DISABLE_NETWORK
29
30
#include <gpac/utf.h>
31
32
#if defined(WIN32) || defined(_WIN32_WCE)
33
#define _WINSOCK_DEPRECATED_NO_WARNINGS
34
35
#ifdef _WIN32_WCE
36
#include <winsock.h>
37
38
#if !defined(__GNUC__)
39
#pragma comment(lib, "winsock")
40
#endif
41
#else
42
43
#include <sys/timeb.h>
44
#include <winsock2.h>
45
#include <ws2tcpip.h>
46
47
#if !defined(__GNUC__)
48
#pragma comment(lib, "ws2_32")
49
#pragma comment(lib, "IPHLPAPI.lib")
50
#define GPAC_WIN_HAS_ADAPTER_INFO
51
#endif
52
53
#if !defined(POLLIN)
54
#ifdef GPAC_HAS_POLL
55
#undef GPAC_HAS_POLL
56
#endif
57
#endif
58
59
#ifdef GPAC_HAS_POLL
60
#define GF_POLLFD WSAPOLLFD
61
#define poll WSAPoll
62
#endif
63
64
#endif
65
66
#include <windows.h>
67
68
#if defined(IPV6_MULTICAST_IF)
69
#define GPAC_HAS_IPV6 1
70
#else
71
#undef GPAC_HAS_IPV6
72
#endif
73
74
 /*
75
 #if !defined(__GNUC__)
76
#if defined(GPAC_HAS_IPV6)
77
#pragma message("Using WinSock IPV6")
78
#else
79
#pragma message("Using WinSock IPV4")
80
#endif
81
82
#endif
83
*/
84
85
#include <errno.h>
86
87
#ifndef EISCONN
88
/*common win32 redefs*/
89
#undef EAGAIN
90
#define EAGAIN        WSAEWOULDBLOCK
91
#define EISCONN       WSAEISCONN
92
#define ENOTCONN      WSAENOTCONN
93
#define ECONNRESET      WSAECONNRESET
94
#define EINPROGRESS     WSAEINPROGRESS
95
#define EALREADY      WSAEALREADY
96
#define EMSGSIZE      WSAEMSGSIZE
97
#define ECONNABORTED    WSAECONNABORTED
98
#define ENETDOWN      WSAENETDOWN
99
#undef EINTR
100
#define EINTR       WSAEINTR
101
#undef EBADF
102
#define EBADF       WSAEBADF
103
#endif
104
105
106
#define LASTSOCKERROR WSAGetLastError()
107
108
/*the number of sockets used. This because the WinSock lib needs init*/
109
static int wsa_init = 0;
110
111
/*end-win32*/
112
#define SOCKET_INVALID(_s) (_s==INVALID_SOCKET)
113
114
#else
115
/*non-win32*/
116
#include <unistd.h>
117
#include <fcntl.h>
118
#include <netdb.h>
119
120
#ifndef __BEOS__
121
#include <errno.h>
122
#endif
123
124
#ifndef __DARWIN__
125
#include <sys/time.h>
126
#endif
127
128
#include <netinet/in.h>
129
#include <netinet/tcp.h>
130
#include <sys/socket.h>
131
#include <sys/types.h>
132
#include <arpa/inet.h>
133
134
#if defined(__FreeBSD__)
135
#include <sys/stat.h>
136
#endif
137
138
/*not defined on solaris*/
139
#if !defined(INADDR_NONE)
140
# if (defined(sun) && defined(__SVR4))
141
#  define INADDR_NONE -1
142
# else
143
#  define INADDR_NONE ((unsigned long)-1)
144
# endif
145
#endif
146
147
148
0
#define SOCKET_INVALID(_s) (_s<0)
149
0
#define INVALID_SOCKET  -1
150
151
0
#define SOCKET_ERROR -1
152
0
#define LASTSOCKERROR errno
153
154
typedef s32 SOCKET;
155
0
#define closesocket(v) close(v)
156
157
#ifdef GPAC_HAS_POLL
158
#include <poll.h>
159
160
0
#define GF_POLLFD struct pollfd
161
162
#endif
163
164
#endif /*WIN32||_WIN32_WCE*/
165
166
#ifdef GPAC_BUILD_FOR_WINXP
167
168
/* Added by M. Lackner to ensure Windows XP & XP x64 compatibility */
169
/* Adding PlibC's inet_ntop() function in a very slightly modified
170
and renamed variant for IPv6 address conversion support on Win XP's,
171
which is called by gf_sk_get_remote_address() further below.
172
The renamed function is called inet_ntop_xp().
173
Original source code taken from here:
174
https://sourceforge.net/projects/plibc/
175
176
This inet_ntop() implementation is (C) 1996-2001 Internet Software
177
Consortium and is licensed under the ISC license.
178
License text: https://opensource.org/licenses/ISC */
179
#define NS_INT16SZ   2
180
#define NS_IN6ADDRSZ  16
181
182
/*
183
* WARNING: Don't even consider trying to compile this on a system where
184
* sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
185
*/
186
187
static const char *inet_ntop4(const unsigned char *src, char *dst, size_t size);
188
189
#ifdef AF_INET6
190
static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size);
191
#endif
192
193
/* char *
194
* isc_net_ntop(af, src, dst, size)
195
*  convert a network format address to presentation format.
196
* return:
197
*  pointer to presentation format address (`dst'), or NULL (see errno).
198
* author:
199
*  Paul Vixie, 1996.
200
*/
201
const char * inet_ntop_xp(int af, const void *src, char *dst, size_t size)
202
{
203
  switch (af) {
204
  case AF_INET:
205
    return (inet_ntop4(src, dst, size));
206
#ifdef AF_INET6
207
  case AF_INET6:
208
    return (inet_ntop6(src, dst, size));
209
#endif
210
  default:
211
    errno = EAFNOSUPPORT;
212
    return (NULL);
213
  }
214
  /* NOTREACHED */
215
}
216
217
/* const char *
218
* inet_ntop4(src, dst, size)
219
*  format an IPv4 address
220
* return:
221
*  `dst' (as a const)
222
* notes:
223
*  (1) uses no statics
224
*  (2) takes a unsigned char* not an in_addr as input
225
* author:
226
*  Paul Vixie, 1996.
227
*/
228
static const char * inet_ntop4(const unsigned char *src, char *dst, size_t size)
229
{
230
  static const char *fmt = "%u.%u.%u.%u";
231
  char tmp[sizeof "255.255.255.255"];
232
  size_t len;
233
234
  len = snprintf(tmp, sizeof tmp, fmt, src[0], src[1], src[2], src[3]);
235
  if (len >= size) {
236
    errno = ENOSPC;
237
    return (NULL);
238
  }
239
  memcpy(dst, tmp, len + 1);
240
241
  return (dst);
242
}
243
244
/* const char *
245
* isc_inet_ntop6(src, dst, size)
246
*  convert IPv6 binary address into presentation (printable) format
247
* author:
248
*  Paul Vixie, 1996.
249
*/
250
#ifdef AF_INET6
251
static const char * inet_ntop6(const unsigned char *src, char *dst, size_t size)
252
{
253
  /*
254
  * Note that int32_t and int16_t need only be "at least" large enough
255
  * to contain a value of the specified size.  On some systems, like
256
  * Crays, there is no such thing as an integer variable with 16 bits.
257
  * Keep this in mind if you think this function should have been coded
258
  * to use pointer overlays.  All the world's not a VAX.
259
  */
260
  char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
261
  struct { int base, len; } best, cur;
262
  unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
263
  int i, inc;
264
265
  /*
266
  * Preprocess:
267
  *  Copy the input (bytewise) array into a wordwise array.
268
  *  Find the longest run of 0x00's in src[] for :: shorthanding.
269
  */
270
  memset(words, '\0', sizeof words);
271
  for (i = 0; i < NS_IN6ADDRSZ; i++)
272
    words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
273
  best.base = -1;
274
  best.len = 0;
275
  cur.base = -1;
276
  cur.len = 0;
277
  for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
278
    if (words[i] == 0) {
279
      if (cur.base == -1)
280
        cur.base = i, cur.len = 1;
281
      else
282
        cur.len++;
283
    }
284
    else {
285
      if (cur.base != -1) {
286
        if (best.base == -1 || cur.len > best.len)
287
          best = cur;
288
        cur.base = -1;
289
      }
290
    }
291
  }
292
  if (cur.base != -1) {
293
    if (best.base == -1 || cur.len > best.len)
294
      best = cur;
295
  }
296
  if (best.base != -1 && best.len < 2)
297
    best.base = -1;
298
299
  /*
300
  * Format the result.
301
  */
302
  tp = tmp;
303
  for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
304
    /* Are we inside the best run of 0x00's? */
305
    if (best.base != -1 && i >= best.base && i < (best.base + best.len)) {
306
      if (i == best.base)
307
        *tp++ = ':';
308
      continue;
309
    }
310
    /* Are we following an initial run of 0x00s or any real hex? */
311
    if (i != 0)
312
      *tp++ = ':';
313
    /* Is this address an encapsulated IPv4? */
314
    if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
315
      if (!inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
316
        return (NULL);
317
      tp += strlen(tp);
318
      break;
319
    }
320
    inc = snprintf(tp, 5, "%x", words[i]);
321
    tp += inc;
322
  }
323
  /* Was it a trailing run of 0x00's? */
324
  if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ))
325
    *tp++ = ':';
326
  *tp++ = '\0';
327
328
  /*
329
  * Check for overflow, copy, and we're done.
330
  */
331
  if ((size_t)(tp - tmp) > size) {
332
    errno = ENOSPC;
333
    return (NULL);
334
  }
335
  memcpy(dst, tmp, tp - tmp);
336
  return (dst);
337
}
338
#endif /* AF_INET6 */
339
/* End of inet_ntop() reimplementation */
340
341
342
#endif //winxp
343
344
#ifdef GPAC_BUILD_FOR_WINXP
345
#define my_inet_ntop inet_ntop_xp
346
#else
347
0
#define my_inet_ntop inet_ntop
348
#endif
349
350
351
#ifdef GPAC_HAS_IPV6
352
# ifndef IPV6_ADD_MEMBERSHIP
353
#  define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
354
# endif
355
# ifndef IPV6_DROP_MEMBERSHIP
356
#  define IPV6_DROP_MEMBERSHIP   IPV6_LEAVE_GROUP
357
# endif
358
#endif
359
360
361
#ifdef __SYMBIAN32__
362
#define SSO_CAST
363
#else
364
0
#define SSO_CAST (const char *)
365
#endif
366
367
368
#ifdef GPAC_HAS_IPV6
369
static u32 ipv6_check_state = 0;
370
#endif
371
372
#ifdef GPAC_HAS_SOCK_UN
373
#include <sys/un.h>
374
#endif
375
376
/*internal flags*/
377
enum
378
{
379
  GF_SOCK_IS_TCP = 1<<9,
380
  GF_SOCK_IS_IPV6 = 1<<10,
381
  GF_SOCK_NON_BLOCKING = 1<<11,
382
  GF_SOCK_IS_MULTICAST = 1<<12,
383
  GF_SOCK_IS_LISTENING = 1<<13,
384
  /*socket is bound to a specific dest (server) or source (client) */
385
  GF_SOCK_HAS_PEER = 1<<14,
386
  GF_SOCK_IS_UN = 1<<15,
387
  GF_SOCK_HAS_CONNECT = 1<<16
388
};
389
390
#ifndef GPAC_DISABLE_NETCAP
391
392
typedef struct __netcap_filter GF_NetcapFilter;
393
static GF_NetcapFilter *gf_net_filter_get(const char *id);
394
395
typedef struct
396
{
397
  //local host info
398
  u32 host_addr_v4;
399
  bin128 host_addr_v6;
400
  u32 host_port;
401
  //remote peer info
402
  u32 peer_addr_v4;
403
  bin128 peer_addr_v6;
404
  u32 peer_port;
405
406
  u32 pck_idx_r, pck_idx_w, next_pck_range, next_rand;
407
  u32 patch_offset, patch_val;
408
  GF_NetcapFilter *nf;
409
} NetCapInfo;
410
#endif
411
412
413
struct __tag_socket
414
{
415
  u32 flags;
416
  SOCKET socket;
417
  /*destination address for sendto/recvfrom*/
418
#ifdef GPAC_HAS_IPV6
419
  struct sockaddr_storage dest_addr;
420
#else
421
  struct sockaddr_in dest_addr;
422
#endif
423
  u32 dest_addr_len;
424
425
  u32 usec_wait;
426
#ifdef GPAC_HAS_POLL
427
  u32 poll_idx;
428
#endif
429
430
#ifndef GPAC_DISABLE_NETCAP
431
  NetCapInfo *cap_info;
432
#endif
433
};
434
435
436
437
GF_EXPORT
438
u32 gf_net_has_ipv6()
439
0
{
440
0
#ifdef GPAC_HAS_IPV6
441
0
  if (!ipv6_check_state) {
442
0
    SOCKET s;
443
#ifdef WIN32
444
    if (!wsa_init) {
445
      WSADATA Data;
446
      if (WSAStartup(0x0202, &Data)!=0) {
447
        ipv6_check_state = 1;
448
        return 0;
449
      }
450
    }
451
#endif
452
0
    s = socket(PF_INET6, SOCK_STREAM, 0);
453
0
    if (!s) ipv6_check_state = 1;
454
0
    else {
455
0
      ipv6_check_state = 2;
456
0
      closesocket(s);
457
0
    }
458
#ifdef WIN32
459
    if (!wsa_init) WSACleanup();
460
#endif
461
0
  }
462
0
  return (ipv6_check_state==2);
463
#else
464
  return 0;
465
#endif
466
0
}
467
468
GF_EXPORT
469
Bool gf_net_is_ipv6(const char *address)
470
0
{
471
0
  u32 i, nb_seps=0, nb_dseps=0, nb_dig=0, count = address ? (u32) strlen(address) : 0;
472
0
  for (i=0;i<count; i++) {
473
0
    if (address[i]==':') {
474
0
      nb_seps++;
475
0
      nb_dig=0;
476
0
      if ((i+1<count) && (address[i+1]==':')) {
477
0
        nb_dseps++;
478
0
        i++;
479
0
      }
480
0
    }
481
0
    else if (strchr("0123456789ABCDEFabcdef",address[i])==NULL) {
482
0
      return GF_FALSE;
483
0
    } else {
484
0
      nb_dig++;
485
0
      if (nb_dig>4) return GF_FALSE;
486
0
    }
487
0
  }
488
0
  if (nb_seps>7) return GF_FALSE;
489
0
  if (nb_seps==7) return GF_TRUE;
490
0
  if (nb_dseps!=1) return GF_FALSE;
491
0
  return GF_TRUE;
492
0
}
493
494
#if defined(GPAC_WIN_HAS_ADAPTER_INFO)
495
#include <iphlpapi.h>
496
#endif
497
498
#if defined(GPAC_HAS_IFADDRS)
499
#include <ifaddrs.h>
500
#include <net/if.h>
501
#endif
502
503
504
#ifdef GPAC_HAS_IPV6
505
0
#define MAX_PEER_NAME_LEN 1024
506
static struct addrinfo *gf_sk_get_ipv6_addr(const char *PeerName, u16 PortNumber, int family, int flags, int sock_type)
507
0
{
508
0
  struct  addrinfo *res=NULL;
509
0
  struct  addrinfo hints;
510
0
  char node[MAX_PEER_NAME_LEN], portstring[20];
511
0
  char *service, *dest;
512
0
  service = dest = NULL;
513
#ifdef WIN32
514
  if (!wsa_init) {
515
    WSADATA Data;
516
    if (WSAStartup(0x0202, &Data)!=0) return NULL;
517
    wsa_init = 1;
518
  }
519
#endif
520
521
0
  service = dest = NULL;
522
0
  memset(&hints, 0, sizeof(hints));
523
0
  hints.ai_socktype = sock_type;
524
0
  hints.ai_family = family;
525
0
  hints.ai_flags = flags;
526
527
0
  if (PortNumber) {
528
0
    sprintf (portstring, "%d", PortNumber);
529
0
    service = (char *)portstring;
530
0
  }
531
0
  if (PeerName) {
532
0
    gf_strlcpy(node, PeerName, MAX_PEER_NAME_LEN);
533
0
    if (node[0]=='[') {
534
0
      node[strlen(node)-1] = 0;
535
0
      memmove(node, &node[1], MAX_PEER_NAME_LEN-1);
536
0
    }
537
0
    node[MAX_PEER_NAME_LEN - 1] = 0;
538
0
    dest = (char *) node;
539
0
  }
540
0
  if (getaddrinfo((const char *)dest, (const char *)service, &hints, &res) != 0) return NULL;
541
0
  return res;
542
0
}
543
544
static struct addrinfo *gf_sk_get_ifce_ipv6_addr(const char *ifce_name_or_ip, u16 PortNumber, int family, int flags, int sock_type)
545
0
{
546
0
  char szIP[100];
547
0
  Bool force_ipv6 = GF_FALSE;
548
0
  if (!ifce_name_or_ip || !ifce_name_or_ip[0] || gf_net_is_ipv6(ifce_name_or_ip) || strchr(ifce_name_or_ip, '.'))
549
0
    return gf_sk_get_ipv6_addr(ifce_name_or_ip, PortNumber, family, flags, sock_type);
550
0
  if (ifce_name_or_ip[0]=='+') {
551
0
    force_ipv6 = GF_TRUE;
552
0
    ifce_name_or_ip+=1;
553
0
    if (!ifce_name_or_ip[0]) {
554
0
      return gf_sk_get_ipv6_addr(ifce_name_or_ip, PortNumber, AF_INET6, flags, sock_type);
555
0
    }
556
0
  }
557
0
  if (family==AF_INET6) force_ipv6 = GF_TRUE;
558
559
0
  szIP[0] = 0;
560
561
#if defined(GPAC_WIN_HAS_ADAPTER_INFO)
562
  IP_ADAPTER_ADDRESSES *AdapterInfo = malloc(sizeof(IP_ADAPTER_ADDRESSES));
563
  ULONG ulOutBufLen = sizeof(AdapterInfo);
564
  if (AdapterInfo && (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, AdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW)) {
565
    free(AdapterInfo);
566
    AdapterInfo = malloc(sizeof(IP_ADAPTER_ADDRESSES)*ulOutBufLen);
567
  }
568
  if (AdapterInfo)
569
    GetAdaptersAddresses(AF_UNSPEC, 0, NULL, AdapterInfo, &ulOutBufLen);
570
  IP_ADAPTER_ADDRESSES *ifa = AdapterInfo;
571
  while (ifa) {
572
    Bool match = GF_FALSE;
573
    if (!strcmp(ifa->AdapterName, ifce_name_or_ip)) match = GF_TRUE;
574
    char *name = gf_wcs_to_utf8(ifa->FriendlyName);
575
    if (name) {
576
      if (!strcmp(name, ifce_name_or_ip)) match = GF_TRUE;
577
      gf_free(name);
578
    }
579
    if (!match) {
580
      ifa = ifa->Next;
581
      szIP[0] = 0;
582
      continue;
583
    }
584
    IP_ADAPTER_UNICAST_ADDRESS_LH *ipadd = ifa->FirstUnicastAddress;
585
    while (ipadd) {
586
      if (!ipadd->Address.lpSockaddr) {
587
        ipadd = ipadd->Next;
588
        continue;
589
      }
590
      if (ipadd->Address.lpSockaddr->sa_family==AF_INET) {
591
        my_inet_ntop(ipadd->Address.lpSockaddr->sa_family, ipadd->Address.lpSockaddr, szIP, 100);
592
        free(AdapterInfo);
593
        return gf_sk_get_ipv6_addr(szIP, PortNumber, family, flags, sock_type);
594
      }
595
      if (ipadd->Address.lpSockaddr->sa_family == AF_INET6) {
596
        my_inet_ntop(ipadd->Address.lpSockaddr->sa_family, ipadd->Address.lpSockaddr, szIP, 100);
597
        if (force_ipv6) {
598
          free(AdapterInfo);
599
          return gf_sk_get_ipv6_addr(szIP, PortNumber, family, flags, sock_type);
600
        }
601
      }
602
      ipadd = ipadd->Next;
603
    }
604
    ifa = ifa->Next;
605
  }
606
  if (AdapterInfo)
607
    free(AdapterInfo);
608
#endif
609
610
0
#if defined(GPAC_HAS_IFADDRS)
611
0
  struct ifaddrs *ifap = NULL, *ifa;
612
0
  getifaddrs(&ifap);
613
0
  ifa = ifap;
614
0
  while (ifa) {
615
0
    if (!ifa->ifa_addr || strcmp(ifa->ifa_name, ifce_name_or_ip)) {
616
0
      ifa = ifa->ifa_next;
617
0
      continue;
618
0
    }
619
0
    if (ifa->ifa_addr->sa_family==AF_INET) {
620
0
      memset(szIP, 0, 100);
621
0
      inet_ntop(AF_INET, &( ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr), szIP, 100);
622
0
      freeifaddrs(ifap);
623
0
      return gf_sk_get_ipv6_addr(szIP, PortNumber, family, flags, sock_type);
624
0
    }
625
0
    if (ifa->ifa_addr->sa_family==AF_INET6) {
626
0
      memset(szIP, 0, 100);
627
0
      inet_ntop(AF_INET6, &( ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr), szIP, 100);
628
0
      if (force_ipv6) {
629
0
        freeifaddrs(ifap);
630
0
        return gf_sk_get_ipv6_addr(szIP, PortNumber, family, flags, sock_type);
631
0
      }
632
0
    }
633
0
    ifa = ifa->ifa_next;
634
0
  }
635
0
  freeifaddrs(ifap);
636
0
#endif
637
638
0
  if (szIP[0]) {
639
0
    return gf_sk_get_ipv6_addr(szIP, PortNumber, family, flags, sock_type);
640
0
  }
641
0
  return NULL;
642
0
}
643
#endif
644
645
646
GF_EXPORT
647
GF_Err gf_sk_get_host_name(char *buffer)
648
0
{
649
0
  s32 ret = gethostname(buffer, GF_MAX_IP_NAME_LEN);
650
0
  return (ret == SOCKET_ERROR) ? GF_IP_ADDRESS_NOT_FOUND : GF_OK;
651
0
}
652
653
GF_EXPORT
654
GF_Err gf_sk_get_local_ip(GF_Socket *sock, char buffer[GF_MAX_IP_NAME_LEN])
655
0
{
656
0
#ifdef GPAC_HAS_IPV6
657
0
  char clienthost[NI_MAXHOST];
658
0
  if (sock->flags & GF_SOCK_HAS_PEER) {
659
0
    if (getnameinfo((struct sockaddr *)&sock->dest_addr, sock->dest_addr_len, clienthost, sizeof(clienthost), NULL, 0, NI_NUMERICHOST))
660
0
      return GF_IP_NETWORK_FAILURE;
661
0
  } else {
662
0
    struct sockaddr_storage clientaddr;
663
0
    socklen_t addrlen = sizeof(clientaddr);
664
0
    if (sock->flags & GF_SOCK_IS_MULTICAST)
665
0
      return GF_BAD_PARAM;
666
0
    if (getsockname(sock->socket, (struct sockaddr *)&clientaddr, &addrlen)) return GF_IP_NETWORK_FAILURE;
667
668
0
    if (getnameinfo((struct sockaddr *)&clientaddr, addrlen, clienthost, sizeof(clienthost), NULL, 0, NI_NUMERICHOST))
669
0
      return GF_IP_NETWORK_FAILURE;
670
0
  }
671
0
  gf_strlcpy(buffer, clienthost, GF_MAX_IP_NAME_LEN);
672
#else
673
  char *ip;
674
  if (sock->flags & GF_SOCK_HAS_PEER) {
675
    ip = inet_ntoa(sock->dest_addr.sin_addr);
676
  } else {
677
    struct sockaddr_in name;
678
    u32 len = sizeof(struct sockaddr_in);
679
    if (getsockname(sock->socket, (struct sockaddr*) &name, &len)) return GF_IP_NETWORK_FAILURE;
680
    ip = inet_ntoa(name.sin_addr);
681
  }
682
  if (!ip) return GF_IP_NETWORK_FAILURE;
683
  gf_strlcpy(buffer, ip, GF_MAX_IP_NAME_LEN);
684
#endif
685
0
  return GF_OK;
686
0
}
687
688
#ifndef GPAC_DISABLE_NETCAP
689
690
#include <gpac/bitstream.h>
691
#include <gpac/list.h>
692
693
enum
694
{
695
  NETCAP_IS_MCAST = 1,
696
  NETCAP_IS_TCP = 1<<1,
697
  NETCAP_HAS_PEER = 1<<2,
698
  NETCAP_IS_IPV6 = 1<<3,
699
  NETCAP_HAS_EXT = 1<<6,
700
  NETCAP_DROP = 1<<7,
701
};
702
703
//capture mode only, target bitstream
704
u16 first_tcp_port=30000;
705
706
0
#define GF_GPC_MAGIC  GF_4CC('G','P','C', 0)
707
708
//playback vars
709
710
711
enum {
712
  NETCAP_NONE = 0,
713
  //read/write
714
  NETCAP_GPAC = 1,
715
  //read only
716
  NETCAP_PCAP = 2,
717
  NETCAP_PCAPNG = 3,
718
};
719
720
typedef struct
721
{
722
  u32 send_recv;
723
  u32 pck_start, pck_end;
724
  Bool pck_start_is_loop, pck_end_is_loop;
725
  s32 rand_every;
726
  u32 nb_pck;
727
  u32 port;
728
  s32 patch_offset, patch_val;
729
  s32 delay;
730
} NetFilterRule;
731
732
static GF_List *netcap_filters=NULL;
733
#ifdef GPAC_HAS_FD
734
GF_BitStream *gf_bs_from_fd(int fd, u32 mode);
735
#endif
736
737
struct __netcap_filter
738
{
739
  char *id;
740
  char *src;
741
  char *dst;
742
  s32 loops;
743
  Bool rt;
744
  GF_List *rules;
745
  u32 nb_rules;
746
  u32 nb_reloads;
747
748
749
  //target bitstream for read/write
750
  GF_BitStream *cap_bs;
751
  //playback mode only, set of created sockets, used to discard packets on non-bound sockets
752
  GF_List *read_socks;
753
  //playback mode only, set to socket corresponding to pending packet
754
  GF_Socket *read_sock_selected;
755
  //playback/capture, FILE pointer
756
  FILE *file;
757
#ifdef GPAC_HAS_FD
758
  //playback/capture, fd pointer
759
  int fd;
760
#endif
761
762
  //playback only, clock init value for RT regulation
763
  u64 init_time;
764
  Bool is_eos;
765
766
  u64 pck_start_offset;
767
768
  //loaded packet size in bytes - this is the payload of the UDP/TCP packet - if 0, packet fetch failed
769
  s32 pck_len;
770
  //gpac format only, flags of loaded packet
771
  u8 pck_flags;
772
  //time of loaded packet, relative to sys_clock_high_res
773
  u64 pck_time;
774
  //destination port of loaded packet - if 0, new packet needs to be loaded
775
  u16 dst_port;
776
  //ipv4 dest address or mcast address of loaded packet
777
  u32 dst_v4;
778
  //ipv6 dest address or mcast address of loaded packet
779
  bin128 dst_v6;
780
  //source port of loaded packet
781
  u16 src_port;
782
  //ipv4 source address of loaded packet
783
  u32 src_v4;
784
  //ipv6 source address of loaded packet
785
  bin128 src_v6;
786
787
  //source file type
788
  u32 cap_mode;
789
  //for pcap files, indicate if little endian
790
  Bool pcap_le;
791
  //for pcap files, indicate nano seconds are used
792
  Bool pcap_nano;
793
  //number of interfaces currently defined - for pcap, always, 1
794
  u32 pcap_num_interfaces;
795
  //all defined interfaces
796
  u32 link_types[20];
797
  //trailing bytes in pcapng packet record
798
  u32 pcapng_trail;
799
  //trailing bytes after packet in pcap (NOT in pcapng)
800
  u32 pcap_trail;
801
802
  u32 pck_idx_r;
803
  u32 pck_idx_w;
804
  u32 next_pck_range;
805
  u32 next_rand;
806
807
  u32 reorder_max_pck, reorder_nb_pck, delay_nb_pck;
808
  u64 reorder_seek_pos, reorder_resume_pos;
809
};
810
811
static GF_NetcapFilter *gf_net_filter_get(const char *id)
812
0
{
813
0
  u32 i, count;
814
0
  count = gf_list_count(netcap_filters);
815
0
  for (i=0; i<count; i++) {
816
0
    GF_NetcapFilter *f = gf_list_get(netcap_filters, i);
817
0
    if (f->id && id && !strcmp(f->id, id))
818
0
      return f;
819
820
0
    if (!f->id && !id)
821
0
      return f;
822
0
  }
823
0
  return NULL;
824
0
}
825
//end playback vars
826
827
828
829
void gf_net_close_capture()
830
0
{
831
0
  while (gf_list_count(netcap_filters)) {
832
0
    GF_NetcapFilter *nf = gf_list_pop_back(netcap_filters);
833
834
0
    if (nf->cap_bs) gf_bs_del(nf->cap_bs);
835
836
0
#ifdef GPAC_HAS_FD
837
0
    if (nf->fd>=0) close(nf->fd);
838
0
#endif
839
0
    if (nf->file) gf_fclose(nf->file);
840
0
    if (nf->read_socks) gf_list_del(nf->read_socks);
841
842
0
    if (nf->rules) {
843
0
      while (1) {
844
0
        NetFilterRule *r = gf_list_pop_back(nf->rules);
845
0
        if (!r) break;
846
0
        gf_free(r);
847
0
      }
848
0
      gf_list_del(nf->rules);
849
0
    }
850
0
    if (nf->id) gf_free(nf->id);
851
0
    if (nf->src) gf_free(nf->src);
852
0
    if (nf->dst) gf_free(nf->dst);
853
0
    gf_free(nf);
854
0
  }
855
0
  gf_list_del(netcap_filters);
856
0
  netcap_filters = NULL;
857
0
}
858
859
static GF_Err gf_netcap_record(GF_NetcapFilter *nf)
860
0
{
861
0
#ifdef GPAC_HAS_FD
862
0
  if (!gf_opts_get_bool("core", "no-fd")) {
863
    //make sure output dir exists
864
0
    gf_fopen(nf->dst, "mkdir");
865
0
    nf->fd = gf_fd_open(nf->dst, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH );
866
0
    if (nf->fd>=0) nf->cap_bs = gf_bs_from_fd(nf->fd, GF_BITSTREAM_WRITE);
867
0
  } else
868
0
#endif
869
0
  {
870
0
    nf->file = gf_fopen_ex(nf->dst, NULL, "w+b", GF_FALSE);
871
0
    if (nf->file) nf->cap_bs = gf_bs_from_file(nf->file, GF_BITSTREAM_WRITE);
872
0
  }
873
0
  if (!nf->cap_bs) {
874
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[NetCap] Failed to setup net capture\n"));
875
0
    return GF_IO_ERR;
876
0
  }
877
0
  char *ext = gf_file_ext_start(nf->dst);
878
0
  if (ext && !strcmp(ext, ".pcap")) {
879
0
    nf->cap_mode = NETCAP_PCAP;
880
0
    gf_bs_write_u32(nf->cap_bs, 0xA1B2C3D4);
881
0
    gf_bs_write_u16(nf->cap_bs, 2);
882
0
    gf_bs_write_u16(nf->cap_bs, 4);
883
0
    gf_bs_write_u32(nf->cap_bs, 0);
884
0
    gf_bs_write_u32(nf->cap_bs, 0);
885
0
    gf_bs_write_u32(nf->cap_bs, 0xFFFF); //snapLen
886
0
    gf_bs_write_u16(nf->cap_bs, 0); //FCS+f+reserved
887
0
    gf_bs_write_u16(nf->cap_bs, 0); //linktype
888
0
  } else if (ext && !strcmp(ext, ".pcapng")) {
889
0
    nf->cap_mode = NETCAP_PCAPNG;
890
    //SHB
891
0
    gf_bs_write_u32(nf->cap_bs, 0x0a0d0d0a);
892
0
    gf_bs_write_u32(nf->cap_bs, 12+16);
893
0
    gf_bs_write_u32(nf->cap_bs, 0x1A2B3C4D);
894
0
    gf_bs_write_u16(nf->cap_bs, 1);
895
0
    gf_bs_write_u16(nf->cap_bs, 0);
896
0
    gf_bs_write_u64(nf->cap_bs, 0);
897
0
    gf_bs_write_u32(nf->cap_bs, 12+16);
898
    //IDB
899
0
    gf_bs_write_u32(nf->cap_bs, 1);
900
0
    gf_bs_write_u32(nf->cap_bs, 12+8);
901
0
    gf_bs_write_u16(nf->cap_bs, 0); //linktype
902
0
    gf_bs_write_u16(nf->cap_bs, 0); //reserved
903
0
    gf_bs_write_u32(nf->cap_bs, 0); //snapLen
904
0
    gf_bs_write_u32(nf->cap_bs, 12+8);
905
0
  } else {
906
0
    nf->cap_mode = NETCAP_GPAC;
907
0
    gf_bs_write_u32(nf->cap_bs, GF_GPC_MAGIC);
908
0
    nf->init_time = gf_sys_clock_high_res();
909
0
    u32 sec, frac;
910
0
    gf_net_get_ntp(&sec, &frac);
911
    //NTP start time of capture
912
0
    gf_bs_write_u32(nf->cap_bs, sec);
913
0
    gf_bs_write_u32(nf->cap_bs, frac);
914
    //header extension size
915
0
    gf_bs_write_u32(nf->cap_bs, 0);
916
0
  }
917
0
  return GF_OK;
918
0
}
919
920
static void gf_netcap_load_pck_gpac(GF_NetcapFilter *nf)
921
0
{
922
0
  nf->pck_start_offset = gf_bs_get_position(nf->cap_bs);
923
0
  if (gf_bs_available(nf->cap_bs)>4)
924
0
    nf->pck_len = gf_bs_read_u32(nf->cap_bs);
925
0
  else
926
0
    nf->pck_len = 0;
927
928
  //we allow size to be equal to our magic for file concat
929
  //this means pck size= 1196442368 (for v0) so we should be way over captured MTU
930
0
  if (nf->pck_len == GF_GPC_MAGIC) {
931
0
    /*ntp_sec = */gf_bs_read_u32(nf->cap_bs);
932
0
    /*ntp_frac = */gf_bs_read_u32(nf->cap_bs);
933
0
    u32 hdr_len = gf_bs_read_u32(nf->cap_bs);
934
0
    gf_bs_skip_bytes(nf->cap_bs, hdr_len);
935
0
    nf->pck_flags = NETCAP_DROP;
936
0
    nf->pck_len = 0;
937
0
    nf->dst_port = 1;
938
0
    return;
939
0
  }
940
941
0
  if (nf->pck_len<1+8+4+2) {
942
0
    nf->dst_v4 = 0;
943
0
    nf->dst_port = 0;
944
0
    nf->pck_len = 0;
945
0
    nf->is_eos = GF_TRUE;
946
0
    return;
947
0
  }
948
0
  nf->pck_len -= 1+8+2;
949
  //read flags
950
0
  nf->pck_flags = gf_bs_read_u8(nf->cap_bs);
951
0
  nf->pck_time = gf_bs_read_u64(nf->cap_bs);
952
  //extensions
953
0
  if (nf->pck_flags & NETCAP_HAS_EXT) {
954
0
    u16 xlen = gf_bs_read_u16(nf->cap_bs);
955
0
    gf_bs_skip_bytes(nf->cap_bs, xlen);
956
0
    nf->pck_len -= 2 + xlen;
957
0
  }
958
959
  //init clock on first packet
960
0
  if (!nf->init_time) {
961
0
    nf->init_time = gf_sys_clock_high_res();
962
0
    nf->init_time -= nf->pck_time;
963
0
  }
964
0
  nf->pck_time += nf->init_time;
965
0
  if (nf->pck_flags & NETCAP_IS_IPV6) {
966
0
    nf->dst_v4 = 0;
967
0
    gf_bs_read_data(nf->cap_bs, nf->dst_v6, 16);
968
0
    nf->pck_len -= 16;
969
0
    if (nf->pck_flags & NETCAP_HAS_PEER) {
970
0
      gf_bs_read_data(nf->cap_bs, nf->src_v6, 16);
971
0
      nf->pck_len -= 16;
972
0
    }
973
0
  } else {
974
0
    nf->dst_v4 = gf_bs_read_u32(nf->cap_bs);
975
0
    nf->pck_len -= 4;
976
0
    if (nf->pck_flags & NETCAP_HAS_PEER) {
977
0
      nf->src_v4 = gf_bs_read_u32(nf->cap_bs);
978
0
      nf->pck_len -= 4;
979
0
    }
980
0
  }
981
0
  nf->dst_port = gf_bs_read_u16(nf->cap_bs);
982
0
  if (nf->pck_flags & NETCAP_HAS_PEER) {
983
0
    nf->src_port = gf_bs_read_u16(nf->cap_bs);
984
0
    nf->pck_len -= 2;
985
0
  } else {
986
0
    nf->src_port = 0;
987
0
  }
988
989
0
  if (gf_bs_is_overflow(nf->cap_bs)) {
990
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[NetCap] Corrupted netcap file, aborting\n"));
991
0
    nf->pck_len = -1;
992
0
  }
993
994
  //broken packet
995
0
  if (nf->pck_len <0) {
996
0
    nf->dst_v4 = 0;
997
0
    nf->dst_port = 0;
998
0
    nf->pck_len = 0;
999
0
    nf->is_eos = GF_TRUE;
1000
0
  }
1001
0
}
1002
1003
enum
1004
{
1005
  PCAP_LT_LOOPBACK=0,
1006
  PCAP_LT_ETHERNET=1,
1007
  PCAP_LT_CHAOS=5
1008
};
1009
1010
static GF_Err pcapng_load_shb(GF_NetcapFilter *nf, Bool is_init)
1011
0
{
1012
0
  u32 blen = gf_bs_read_u32(nf->cap_bs);
1013
0
  u32 le_magic = gf_bs_read_u32(nf->cap_bs);
1014
0
  if (le_magic == GF_4CC(0x1A, 0x2B, 0x3C, 0x4D)) {
1015
0
  } else if (le_magic == GF_4CC(0x4D, 0x3C, 0x2B, 0x1A)) {
1016
0
    nf->pcap_le = GF_TRUE;
1017
0
    blen = ntohl(blen);
1018
0
  } else {
1019
0
    if (is_init)
1020
0
      gf_net_close_capture();
1021
0
    else
1022
0
      nf->is_eos = GF_TRUE;
1023
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[NetCap] Corrrupted pacpng file\n"));
1024
0
    return GF_NON_COMPLIANT_BITSTREAM;
1025
0
  }
1026
0
  gf_bs_skip_bytes(nf->cap_bs, blen-12);
1027
0
  nf->pcap_num_interfaces = 0;
1028
0
  return GF_OK;
1029
0
}
1030
1031
static void pcapng_load_idb(GF_NetcapFilter *nf)
1032
0
{
1033
0
  if (nf->pcap_num_interfaces>=20) {
1034
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[NetCap] Maximum 20 concurrent interfaces supported in pacpng, skipping packets\n"));
1035
0
    return;
1036
0
  }
1037
0
  u32 blen = nf->pcap_le ? gf_bs_read_u32_le(nf->cap_bs) : gf_bs_read_u32(nf->cap_bs);
1038
0
  nf->link_types[nf->pcap_num_interfaces] = nf->pcap_le ? gf_bs_read_u16_le(nf->cap_bs) : gf_bs_read_u16(nf->cap_bs);
1039
0
  gf_bs_skip_bytes(nf->cap_bs, blen-10);
1040
1041
0
  switch (nf->link_types[nf->pcap_num_interfaces]) {
1042
0
  case PCAP_LT_LOOPBACK:
1043
0
  case PCAP_LT_ETHERNET:
1044
0
  case PCAP_LT_CHAOS:
1045
0
    break;
1046
0
  default:
1047
0
    GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[NetCap] Only ethernet and BSD-loopback pcap files are supported, skipping packets\n"));
1048
0
    break;
1049
0
  }
1050
0
  nf->pcap_num_interfaces++;
1051
0
}
1052
1053
#define SKIP_PCAP_PCK \
1054
0
  if (clen<0) {\
1055
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[NetCap] Corrupted PCAP file, aborting\n"));\
1056
0
    nf->is_eos = GF_TRUE;\
1057
0
    return;\
1058
0
  }\
1059
0
  gf_bs_skip_bytes(nf->cap_bs, clen);\
1060
0
  clen=0;\
1061
0
  goto refetch_pcap;
1062
1063
1064
static void gf_netcap_load_pck_pcap(GF_NetcapFilter *nf)
1065
0
{
1066
0
  u32 s, frac;
1067
0
  s32 clen=0, bsize=0;
1068
1069
0
refetch_pcap:
1070
0
  nf->dst_port = 0;
1071
0
  nf->pck_len = 0;
1072
0
  if (nf->pcapng_trail) {
1073
0
    gf_bs_skip_bytes(nf->cap_bs, nf->pcapng_trail);
1074
0
    nf->pcapng_trail = 0;
1075
0
  } else if (nf->pcap_trail) {
1076
0
    gf_bs_skip_bytes(nf->cap_bs, nf->pcapng_trail);
1077
0
    nf->pcap_trail = 0;
1078
0
  }
1079
1080
0
  if (gf_bs_available(nf->cap_bs)<16) {
1081
0
    nf->is_eos = GF_TRUE;
1082
0
    return;
1083
0
  }
1084
0
  nf->pck_start_offset = gf_bs_get_position(nf->cap_bs);
1085
1086
0
  u32 link_type;
1087
0
  if (nf->cap_mode==NETCAP_PCAPNG) {
1088
1089
0
    u32 btype = nf->pcap_le ? gf_bs_read_u32_le(nf->cap_bs) : gf_bs_read_u32(nf->cap_bs);
1090
0
    if (btype==GF_4CC(0x0A, 0x0D, 0x0D, 0x0A)) {
1091
0
      GF_Err e = pcapng_load_shb(nf, GF_FALSE);
1092
      //if failure, nf is destroyed by gf_net_close_capture
1093
0
      if (e) {
1094
0
        return;
1095
0
      }
1096
0
      goto refetch_pcap;
1097
0
    } else if (btype==0x00000001) {
1098
0
      pcapng_load_idb(nf);
1099
0
      goto refetch_pcap;
1100
0
    }
1101
1102
0
    bsize = nf->pcap_le ? gf_bs_read_u32_le(nf->cap_bs) : gf_bs_read_u32(nf->cap_bs);
1103
0
    if (bsize <= 8) {
1104
0
      GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[NetCap] Corrupted PCAP file, aborting\n"));
1105
0
      nf->is_eos = GF_TRUE;
1106
0
      return;
1107
0
    }
1108
0
    if (btype!=0x00000006) {
1109
0
      gf_bs_skip_bytes(nf->cap_bs, bsize-8);
1110
0
      nf->pcapng_trail = 0;
1111
0
      goto refetch_pcap;
1112
0
    }
1113
0
    u32 ifce_idx = nf->pcap_le ? gf_bs_read_u32_le(nf->cap_bs) : gf_bs_read_u32(nf->cap_bs);
1114
0
    if (ifce_idx<nf->pcap_num_interfaces)
1115
0
      link_type = nf->link_types[0];
1116
0
    else
1117
0
      link_type = 0xFF;
1118
0
  } else {
1119
0
    link_type = nf->link_types[0];
1120
0
  }
1121
1122
0
  if (nf->pcap_le) {
1123
0
    s = gf_bs_read_u32_le(nf->cap_bs);
1124
0
    frac = gf_bs_read_u32_le(nf->cap_bs);
1125
0
    clen = gf_bs_read_u32_le(nf->cap_bs);
1126
0
    /*olen = */gf_bs_read_u32_le(nf->cap_bs);
1127
0
  } else {
1128
0
    s = gf_bs_read_u32(nf->cap_bs);
1129
0
    frac = gf_bs_read_u32(nf->cap_bs);
1130
0
    clen = gf_bs_read_u32(nf->cap_bs);
1131
0
    /*olen = */gf_bs_read_u32(nf->cap_bs);
1132
0
  }
1133
0
  if (clen<0) {
1134
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[NetCap] Corrupted PCAP file, aborting\n"));
1135
0
    nf->is_eos = GF_TRUE;
1136
0
    return;
1137
0
  }
1138
1139
0
  if (nf->cap_mode==NETCAP_PCAPNG) {
1140
0
    nf->pcapng_trail = bsize - 28 - clen;
1141
0
  }
1142
1143
0
  Bool ip_v6=GF_FALSE;
1144
0
  if (link_type==0) {
1145
0
    u32 type = nf->pcap_le ? gf_bs_read_u32_le(nf->cap_bs) : gf_bs_read_u32(nf->cap_bs);
1146
0
    clen-=4;
1147
0
    if (type==2) {
1148
0
    } else if ((type==24) || (type==28) || (type==30)) {
1149
0
      ip_v6=GF_TRUE;
1150
0
    } else {
1151
0
      SKIP_PCAP_PCK
1152
0
    }
1153
0
  }
1154
  //Ethernet
1155
0
  else if (link_type==1) {
1156
0
    gf_bs_skip_bytes(nf->cap_bs, 12);
1157
0
    u32 etype = gf_bs_read_u16(nf->cap_bs);
1158
0
    clen-=14;
1159
0
    if (etype==0x0800) {
1160
0
    } else if (etype==0x86DD) {
1161
0
      ip_v6=GF_TRUE;
1162
0
    } else {
1163
0
      SKIP_PCAP_PCK
1164
0
    }
1165
0
  }
1166
  //raw IPv4
1167
0
  else if (link_type==5) {
1168
0
  }
1169
  //not supported
1170
0
  else {
1171
0
    gf_bs_skip_bytes(nf->cap_bs, clen);
1172
0
    goto refetch_pcap;
1173
0
  }
1174
1175
0
  u8 protocol_type=0;
1176
0
  if (ip_v6) {
1177
0
    gf_bs_skip_bytes(nf->cap_bs, 4);
1178
0
    /*pay_len = */gf_bs_read_u16(nf->cap_bs);
1179
0
    u32 next_hdr = gf_bs_read_u8(nf->cap_bs);
1180
0
    gf_bs_read_u8(nf->cap_bs);
1181
0
    gf_bs_read_data(nf->cap_bs, nf->src_v6, 16);
1182
0
    gf_bs_read_data(nf->cap_bs, nf->dst_v6, 16);
1183
0
    clen -= 40;
1184
0
    Bool has_hdr = 1;
1185
0
    while (has_hdr) {
1186
0
      u32 hdr_size;
1187
0
      switch (next_hdr) {
1188
0
      case 0:
1189
0
      case 60:
1190
0
      case 43:
1191
0
      case 44:
1192
0
      case 50:
1193
0
      case 51:
1194
0
      case 135:
1195
0
      case 139:
1196
0
      case 140:
1197
0
        next_hdr = gf_bs_read_u8(nf->cap_bs);
1198
0
        hdr_size = gf_bs_read_u8(nf->cap_bs);
1199
0
        gf_bs_skip_bytes(nf->cap_bs, 2 + 8*hdr_size);
1200
0
        hdr_size = 8*(hdr_size+1);
1201
0
        clen -= hdr_size;
1202
0
        break;
1203
0
      case 6:
1204
0
      case 17:
1205
0
        protocol_type=next_hdr;
1206
0
        has_hdr=0;
1207
0
        break;
1208
0
      default:
1209
0
        SKIP_PCAP_PCK
1210
0
      }
1211
0
      if (gf_bs_is_overflow(nf->cap_bs)) {
1212
0
        break;
1213
0
      }
1214
0
    }
1215
0
  } else {
1216
0
    gf_bs_skip_bytes(nf->cap_bs, 9);
1217
0
    protocol_type = gf_bs_read_u8(nf->cap_bs);
1218
0
    gf_bs_skip_bytes(nf->cap_bs, 2);
1219
0
    nf->src_v4 = gf_bs_read_u32_le(nf->cap_bs);
1220
0
    nf->dst_v4 = gf_bs_read_u32_le(nf->cap_bs);
1221
0
    clen-=20;
1222
0
  }
1223
  //UDP
1224
0
  if (protocol_type==17) {
1225
0
    nf->src_port = gf_bs_read_u16(nf->cap_bs);
1226
0
    nf->dst_port = gf_bs_read_u16(nf->cap_bs);
1227
0
    gf_bs_skip_bytes(nf->cap_bs, 4);
1228
0
    clen-=8;
1229
0
  }
1230
  //TCP
1231
0
  else if (protocol_type==6) {
1232
0
    nf->src_port = gf_bs_read_u16(nf->cap_bs);
1233
0
    nf->dst_port = gf_bs_read_u16(nf->cap_bs);
1234
0
    /*sn = */gf_bs_read_u32(nf->cap_bs);
1235
0
    /*ack = */gf_bs_read_u32(nf->cap_bs);
1236
0
    u32 data_offset = gf_bs_read_int(nf->cap_bs, 4);
1237
0
    gf_bs_read_int(nf->cap_bs, 4);
1238
0
    gf_bs_skip_bytes(nf->cap_bs, 7);
1239
0
    if (data_offset>5)
1240
0
      gf_bs_skip_bytes(nf->cap_bs, (data_offset-5)*4);
1241
0
    clen -= data_offset*4;
1242
0
  } else {
1243
    //no support
1244
0
    SKIP_PCAP_PCK
1245
0
  }
1246
1247
0
  if ((clen<0)|| gf_bs_is_overflow(nf->cap_bs)) {
1248
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[NetCap] Corrupted PCAP file, aborting\n"));
1249
0
    nf->is_eos = GF_TRUE;
1250
0
    return;
1251
0
  }
1252
  //for pcap, skip ethernet CRC
1253
0
  if ((nf->cap_mode==NETCAP_PCAP) && (link_type==1))
1254
0
    nf->pcap_trail = 4;
1255
1256
0
  if (nf->cap_mode==NETCAP_PCAP) {
1257
0
    nf->pck_time = s;
1258
0
    nf->pck_time *= 1000000;
1259
0
    if (nf->pcap_nano)
1260
0
      nf->pck_time+=frac/1000;
1261
0
    else
1262
0
      nf->pck_time+=frac;
1263
0
  } else {
1264
0
    nf->pck_time = s;
1265
0
    nf->pck_time <<= 32;
1266
0
    nf->pck_time |= frac;
1267
    //in microsec since UTC epoch
1268
0
  }
1269
0
  if (!nf->init_time) {
1270
0
    nf->init_time = gf_sys_clock_high_res();
1271
0
    nf->init_time -= nf->pck_time;
1272
0
  }
1273
0
  nf->pck_time += nf->init_time;
1274
0
  nf->pck_len = clen;
1275
0
  if (!clen) goto refetch_pcap;
1276
0
}
1277
1278
static GF_Err gf_netcap_playback(GF_NetcapFilter *nf);
1279
1280
GF_Err gf_netcap_setup(char *rules)
1281
0
{
1282
0
  char *id=NULL;
1283
0
  char *src=NULL;
1284
0
  char *dst=NULL;
1285
0
  s32 cap_loop=0;
1286
0
  Bool cap_rt=GF_TRUE;
1287
0
  char *rsep = strchr(rules, '[');
1288
0
  if (rsep) rsep[0] = 0;
1289
  //extract src or dst, nrt flag and loop flag
1290
0
  while (rules) {
1291
0
    char *sep = strchr(rules, ',');
1292
0
    if (sep) sep[0] = 0;
1293
0
    if (!strncmp(rules, "id=", 3)) {
1294
0
      id = gf_strdup(rules+3);
1295
0
    } else if (!strncmp(rules, "src=", 4)) {
1296
0
      src = gf_strdup(rules+4);
1297
0
    } else if (!strncmp(rules, "dst=", 4)) {
1298
0
      dst = gf_strdup(rules+4);
1299
0
    } else if (!strcmp(rules, "loop")) {
1300
0
      cap_loop = -1;
1301
0
    } else if (!strncmp(rules, "loop=", 5)) {
1302
0
      cap_loop = atoi(rules+5);
1303
0
    } else if (!strcmp(rules, "nrt")) {
1304
0
      cap_rt = GF_FALSE;
1305
0
    }
1306
0
    if (!sep) {
1307
0
      rules=NULL;
1308
0
      break;
1309
0
    }
1310
0
    sep[0] = ',';
1311
0
    rules = sep+1;
1312
0
    if (rules[0]=='[') break;
1313
0
  }
1314
0
  if (rsep) {
1315
0
    rsep[0] = '[';
1316
0
    rules = rsep;
1317
0
  }
1318
0
  if (!dst && !src && !rules) {
1319
0
    if (id) gf_free(id);
1320
0
    GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[NetCap] Invalid netcap rule, ignoring\n"));
1321
0
    return GF_OK;
1322
0
  }
1323
0
  if (dst && src) {
1324
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[NetCap] Invalid netcap, src and dst cannot be set at the same time\n"));
1325
0
    if (id) gf_free(id);
1326
0
    gf_free(src);
1327
0
    gf_free(dst);
1328
0
    return GF_BAD_PARAM;
1329
0
  }
1330
1331
0
  GF_NetcapFilter *nf = gf_net_filter_get(id);
1332
0
  if (nf) {
1333
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[NetCap] Several netcap filters with same IDs are not supported, ignoring\n"));
1334
0
    if (id) gf_free(id);
1335
0
    if (src) gf_free(src);
1336
0
    if (dst) gf_free(dst);
1337
0
    return GF_BAD_PARAM;
1338
0
  }
1339
1340
0
  GF_SAFEALLOC(nf, GF_NetcapFilter);
1341
0
  if (!nf) {
1342
0
    if (id) gf_free(id);
1343
0
    if (src) gf_free(src);
1344
0
    if (dst) gf_free(dst);
1345
0
    return GF_OUT_OF_MEM;
1346
0
  }
1347
0
  nf->id = id;
1348
0
  nf->src = src;
1349
0
  nf->dst = dst;
1350
0
  nf->loops = cap_loop;
1351
0
  nf->rt = cap_rt;
1352
0
  nf->rules = gf_list_new();
1353
0
  if (!nf->rules) {
1354
0
    if (id) gf_free(id);
1355
0
    if (src) gf_free(src);
1356
0
    if (dst) gf_free(dst);
1357
0
    gf_free(nf);
1358
0
    return GF_OUT_OF_MEM;
1359
0
  }
1360
0
  if (!netcap_filters) netcap_filters = gf_list_new();
1361
0
  gf_list_add(netcap_filters, nf);
1362
1363
0
#ifdef GPAC_HAS_FD
1364
0
  nf->fd = -1;
1365
0
#endif
1366
1367
0
  while (rules) {
1368
0
    u32 send_recv = 1; //default reception only
1369
0
    u32 port=0;
1370
0
    u32 num_pck=1;
1371
0
    u32 pck_start=0;
1372
0
    u32 pck_end=0;
1373
0
    s32 patch_offset=-1;
1374
0
    s32 patch_val=-1;
1375
0
    s32 rand_every = 0;
1376
0
    s32 delay = 0;
1377
0
    Bool pck_start_is_loop = GF_FALSE;
1378
0
    Bool pck_end_is_loop = GF_FALSE;
1379
1380
0
    char *rule_str;
1381
0
    char *sep = strchr(rules, '[');
1382
0
    if (!sep) break;
1383
0
    sep = strchr(sep+1, ']');
1384
0
    if (!sep) break;
1385
1386
0
    sep[0] = 0;
1387
0
    rule_str = rules+1;
1388
0
    while (rule_str[1]=='=') {
1389
0
      char *sep2 = strchr(rule_str+2, ',');
1390
0
      if (sep2) sep2[0]=0;
1391
1392
0
      switch (rule_str[0]) {
1393
0
      case 'm':
1394
0
        if (!strcmp(rule_str+2, "r")) send_recv = 1;
1395
0
        else if (!strcmp(rule_str+2, "w")) send_recv = 2;
1396
0
        else if (!strcmp(rule_str+2, "rw") || !strcmp(rule_str+2, "wr")) send_recv = 0;
1397
0
        else {
1398
0
          GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[NetCap] Unknown mode %s, using read/write\n", rule_str+2));
1399
0
          send_recv=0;
1400
0
        }
1401
0
        break;
1402
0
      case 'p':
1403
0
        port = atoi(rule_str+2);
1404
0
        break;
1405
0
      case 'S':
1406
0
        pck_start_is_loop = GF_TRUE;
1407
0
      case 's':
1408
0
        pck_start = atoi(rule_str+2);
1409
0
        break;
1410
0
      case 'E':
1411
0
        pck_end_is_loop = GF_TRUE;
1412
0
      case 'e':
1413
0
        pck_end = atoi(rule_str+2);
1414
0
        break;
1415
0
      case 'n':
1416
0
        num_pck = atoi(rule_str+2);
1417
0
        break;
1418
0
      case 'r':
1419
0
        rand_every = atoi(rule_str+2);
1420
0
        if (rand_every<0) rand_every = -rand_every;
1421
0
        break;
1422
0
      case 'f':
1423
0
        rand_every = atoi(rule_str+2);
1424
0
        if (rand_every>0) rand_every = -rand_every;
1425
0
        break;
1426
0
      case 'o':
1427
0
        patch_offset = atoi(rule_str+2);
1428
0
        break;
1429
0
      case 'v':
1430
0
        if (strchr(rule_str, '-')) patch_val =-1;
1431
0
        else patch_val = strtol(rule_str+2, NULL, 16);
1432
0
        break;
1433
0
      case 'd':
1434
0
        if (!nf->src) {
1435
0
          GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[NetCap] Reorder rule only supported from pcap playback, ignoring\n"));
1436
0
          break;
1437
0
        }
1438
0
        delay = atoi(rule_str+2);
1439
0
        break;
1440
0
      default:
1441
0
        GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[NetCap] Unknown directive %c, ignoring\n", rule_str[0]));
1442
0
      }
1443
1444
0
      if (!sep2) break;
1445
0
      sep2[0] = ',';
1446
0
      rule_str = sep2+1;
1447
0
    }
1448
1449
0
    NetFilterRule *rule;
1450
0
    GF_SAFEALLOC(rule, NetFilterRule);
1451
0
    rule->send_recv = send_recv;
1452
0
    rule->port = port;
1453
0
    rule->patch_offset = patch_offset;
1454
0
    rule->patch_val = patch_val;
1455
0
    rule->pck_start = pck_start;
1456
0
    rule->pck_end = pck_end>pck_start ? pck_end : 0;
1457
0
    rule->pck_start_is_loop = pck_start_is_loop;
1458
0
    rule->pck_end_is_loop = pck_end_is_loop;
1459
0
    rule->rand_every = rand_every;
1460
0
    rule->nb_pck = num_pck;
1461
0
    rule->delay = delay;
1462
1463
0
    gf_list_add(nf->rules, rule);
1464
0
    sep[0] = ']';
1465
0
    rules = sep+1;
1466
0
  }
1467
0
  nf->nb_rules = gf_list_count(nf->rules);
1468
1469
0
  if (nf->dst) {
1470
0
    GF_Err e = gf_netcap_record(nf);
1471
0
    if (e) return e;
1472
0
  }
1473
0
  if (nf->src) {
1474
0
    GF_Err e = gf_netcap_playback(nf);
1475
0
    if (e) return e;
1476
0
  }
1477
0
  return GF_OK;
1478
0
}
1479
1480
static Bool netcap_filter_pck(GF_Socket *sock, u32 pck_len, Bool for_send)
1481
0
{
1482
0
  u32 i=0;
1483
0
  if (!sock || !sock->cap_info) return GF_FALSE;
1484
0
  GF_NetcapFilter *nf = sock->cap_info->nf;
1485
1486
0
  if (for_send) {
1487
0
    nf->pck_idx_w++;
1488
0
    sock->cap_info->pck_idx_w++;
1489
0
  } else {
1490
0
    nf->pck_idx_r++;
1491
0
    sock->cap_info->pck_idx_r++;
1492
0
  }
1493
1494
0
  for (i=0; i<nf->nb_rules; i++) {
1495
0
    NetFilterRule *r = gf_list_get(nf->rules, i);
1496
0
    if (r->port && (r->port != nf->dst_port)) continue;
1497
0
    if (for_send) {
1498
0
      if (r->send_recv==1) continue;
1499
0
    } else {
1500
0
      if (r->send_recv==2) continue;
1501
0
    }
1502
0
    NetCapInfo *ci = r->port ? sock->cap_info : NULL;
1503
0
    u32 cur_pck;
1504
0
    if (ci) {
1505
0
      cur_pck = for_send ? ci->pck_idx_w : ci->pck_idx_r;
1506
0
    } else {
1507
0
      cur_pck = for_send ? nf->pck_idx_w : nf->pck_idx_r;
1508
0
    }
1509
    //check range
1510
0
    u32 pck_start = r->pck_start;
1511
0
    if (r->pck_start && r->pck_start_is_loop)
1512
0
      pck_start += nf->nb_reloads;
1513
0
    if (!pck_start && r->pck_start_is_loop) continue;
1514
0
    u32 pck_end = pck_start ? r->pck_end : 0;
1515
0
    if (r->pck_end && r->pck_end_is_loop)
1516
0
      pck_end += nf->nb_reloads;
1517
1518
0
    if (pck_start && (cur_pck < pck_start)) continue;
1519
0
    if (pck_end && (cur_pck >= pck_end)) continue;
1520
1521
    //not repeated pattern case
1522
0
    if (!r->rand_every) {
1523
0
      if ((cur_pck >= pck_start) && (pck_start + r->nb_pck > cur_pck)) {}
1524
0
      else continue;
1525
0
    }
1526
    //repeated pattern case
1527
0
    else {
1528
0
      u32 next_pck_range = ci ? ci->next_pck_range : nf->next_pck_range;
1529
0
      u32 next_rand = ci ? ci->next_rand : nf->next_rand;
1530
      //in range, check if we need to recompute
1531
0
      if (next_pck_range < pck_start)
1532
0
        next_pck_range = pck_start;
1533
1534
0
      if (next_pck_range <= cur_pck) {
1535
0
        if (r->rand_every>0) {
1536
0
          next_rand = next_pck_range + gf_rand() % r->rand_every;
1537
0
          next_pck_range += r->rand_every;
1538
0
        } else {
1539
0
          next_rand = next_pck_range;
1540
0
          next_pck_range += -r->rand_every;
1541
0
        }
1542
1543
0
        if (ci) {
1544
0
          ci->next_pck_range = next_pck_range;
1545
0
          ci->next_rand = next_rand;
1546
0
        } else {
1547
0
          nf->next_pck_range = next_pck_range;
1548
0
          nf->next_rand = next_rand;
1549
0
        }
1550
0
      }
1551
1552
      //ours
1553
0
      if (r->nb_pck) {
1554
0
        if ((next_rand<=cur_pck) && (next_rand+r->nb_pck>cur_pck)) {}
1555
0
        else continue;
1556
0
      } else {
1557
0
        if (next_rand==cur_pck) {}
1558
0
        else continue;
1559
0
      }
1560
0
    }
1561
1562
0
    if ((r->patch_offset==-1) && !(sock->flags & GF_SOCK_IS_TCP)) {
1563
0
      if (r->delay) {
1564
0
        if (!nf->reorder_seek_pos) {
1565
0
          nf->reorder_seek_pos = nf->pck_start_offset;
1566
0
          nf->reorder_max_pck = r->nb_pck;
1567
0
          nf->delay_nb_pck = r->delay;
1568
0
          nf->reorder_nb_pck = 0;
1569
0
        }
1570
0
        nf->reorder_nb_pck ++;
1571
0
        return GF_TRUE;
1572
0
      }
1573
0
      GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[NetCap] Dropping packet %d\n", cur_pck));
1574
0
      return GF_TRUE;
1575
0
    }
1576
0
    u32 bo = (r->patch_offset>=0) ? r->patch_offset : gf_rand();
1577
0
    bo = bo % pck_len;
1578
0
    sock->cap_info->patch_offset = 1+bo;
1579
1580
0
    u32 val = (r->patch_val>=0) ? r->patch_val : gf_rand();
1581
0
    val = val % 256;
1582
1583
0
    sock->cap_info->patch_val = val;
1584
0
    GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[NetCap] Patching packet %d byte offset %d to 0x%02X\n", cur_pck, bo, val));
1585
    // we want to patch many bytes of same packet
1586
    // return GF_FALSE;
1587
0
  }
1588
0
  return GF_FALSE;
1589
0
}
1590
1591
static void gf_netcap_load_pck(GF_NetcapFilter *nf, u64 now)
1592
0
{
1593
1594
0
refetch:
1595
  //no packet loaded
1596
0
  if (!nf->dst_port) {
1597
0
    Bool discard=GF_FALSE;
1598
0
    nf->pck_flags=0;
1599
0
    nf->read_sock_selected = NULL;
1600
1601
0
    if (nf->loops && !gf_bs_available(nf->cap_bs)) {
1602
0
      nf->nb_reloads++;
1603
0
      if (nf->loops>0)
1604
0
        nf->loops--;
1605
1606
0
      gf_bs_seek(nf->cap_bs, 0);
1607
0
      nf->init_time = 0;
1608
0
      if (nf->cap_mode==NETCAP_PCAP)
1609
0
        gf_bs_skip_bytes(nf->cap_bs, 24);
1610
0
    }
1611
1612
0
    if (nf->reorder_seek_pos) {
1613
      //we passed all packets to reorder
1614
0
      if (nf->reorder_nb_pck == nf->reorder_max_pck) {
1615
0
        if (!nf->delay_nb_pck) {
1616
          //remember pos after reorder
1617
0
          nf->reorder_resume_pos = gf_bs_get_position(nf->cap_bs);
1618
0
          gf_bs_seek(nf->cap_bs, nf->reorder_seek_pos);
1619
0
          nf->reorder_seek_pos = 0;
1620
0
          nf->pcapng_trail = nf->pcap_trail = 0;
1621
0
          nf->reorder_nb_pck = 1;
1622
0
        } else {
1623
0
          nf->delay_nb_pck--;
1624
0
        }
1625
0
      }
1626
0
    } else if (nf->reorder_resume_pos) {
1627
0
      if (nf->reorder_nb_pck == nf->reorder_max_pck) {
1628
0
        gf_bs_seek(nf->cap_bs, nf->reorder_resume_pos);
1629
0
        nf->reorder_resume_pos = 0;
1630
0
        nf->pcapng_trail = nf->pcap_trail = 0;
1631
0
        nf->reorder_nb_pck = 0;
1632
0
      } else {
1633
0
        nf->reorder_nb_pck++;
1634
0
      }
1635
0
    }
1636
0
    if (nf->cap_mode==NETCAP_GPAC)
1637
0
      gf_netcap_load_pck_gpac(nf);
1638
0
    else
1639
0
      gf_netcap_load_pck_pcap(nf);
1640
1641
    //eof
1642
0
    if (!nf->dst_port) return;
1643
    //force discard
1644
0
    if ((nf->pck_flags & NETCAP_DROP)) discard = GF_TRUE;
1645
1646
0
    if (discard) {
1647
0
      gf_bs_skip_bytes(nf->cap_bs, nf->pck_len);
1648
0
      nf->dst_port = 0;
1649
0
      goto refetch;
1650
0
    }
1651
0
  }
1652
1653
0
  if (nf->rt && now && (nf->pck_time > now)) {
1654
0
    GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[NetCap] Packet too early by %d ms\n", (u32) (nf->pck_time - now) / 1000));
1655
0
    return;
1656
0
  }
1657
1658
  //we already have the socket
1659
0
  if (nf->read_sock_selected)
1660
0
    return;
1661
1662
  //find destination socket
1663
0
  u32 i=0;
1664
0
  GF_Socket *s = NULL;
1665
0
  while ((s=gf_list_enum(nf->read_socks, &i))) {
1666
    //in pcap mode, check multicast - if enabled, match dst
1667
    //in GPC mode with multicast, only multicast address is used, in host port/addr fields
1668
0
    if ((nf->cap_mode!=NETCAP_GPAC) && (s->flags & GF_SOCK_IS_MULTICAST)) {
1669
0
      if (s->cap_info->peer_port != nf->dst_port)
1670
0
        continue;
1671
0
      if (nf->pck_flags & NETCAP_IS_IPV6) {
1672
0
        if (memcmp(s->cap_info->peer_addr_v6, nf->dst_v6, 16)) continue;
1673
0
      } else {
1674
0
        if (s->cap_info->peer_addr_v4 != nf->dst_v4) continue;
1675
0
      }
1676
0
      nf->read_sock_selected = s;
1677
0
      s->cap_info->patch_offset = 0;
1678
0
      break;
1679
0
    }
1680
0
    if (s->cap_info->host_port != nf->dst_port)
1681
0
      continue;
1682
0
    if (nf->pck_flags & NETCAP_IS_IPV6) {
1683
0
      if (memcmp(s->cap_info->host_addr_v6, nf->dst_v6, 16)) continue;
1684
0
    } else {
1685
      //accept INADDR_ANY
1686
0
      if (s->cap_info->host_addr_v4 && (s->cap_info->host_addr_v4 != nf->dst_v4)) continue;
1687
0
      if (s->flags & GF_SOCK_IS_TCP) {
1688
0
        if (s->cap_info->peer_addr_v4 != nf->src_v4) continue;
1689
0
        if (!s->cap_info->peer_port) {
1690
0
          s->cap_info->peer_port = nf->src_port;
1691
0
        } else if (s->cap_info->peer_port != nf->src_port) {
1692
0
          continue;
1693
0
        }
1694
0
      }
1695
0
    }
1696
0
    nf->read_sock_selected = s;
1697
0
    s->cap_info->patch_offset = 0;
1698
0
    break;
1699
0
  }
1700
  //apply rule(s) except when sending delayed packets
1701
0
  if (!nf->reorder_resume_pos && netcap_filter_pck(nf->read_sock_selected, nf->pck_len, GF_FALSE))
1702
0
    nf->read_sock_selected = NULL;
1703
1704
0
  if (!nf->read_sock_selected) {
1705
0
    gf_bs_skip_bytes(nf->cap_bs, nf->pck_len);
1706
0
    nf->dst_port = 0;
1707
0
    goto refetch;
1708
0
  }
1709
0
}
1710
1711
static GF_Err gf_netcap_playback(GF_NetcapFilter *nf)
1712
0
{
1713
0
#ifdef GPAC_HAS_FD
1714
0
  if (!gf_opts_get_bool("core", "no-fd")) {
1715
0
    nf->fd = gf_fd_open(nf->src, O_RDONLY | O_BINARY , S_IRUSR | S_IWUSR);
1716
0
    if (nf->fd>=0) nf->cap_bs = gf_bs_from_fd(nf->fd, GF_BITSTREAM_READ);
1717
0
  } else
1718
0
#endif
1719
0
  {
1720
0
    nf->file = gf_fopen_ex(nf->src, NULL, "rb", GF_FALSE);
1721
0
    if (nf->file) nf->cap_bs = gf_bs_from_file(nf->file, GF_BITSTREAM_READ);
1722
0
  }
1723
0
  if (!nf->cap_bs) {
1724
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[NetCap] Failed to setup capture playback\n"));
1725
0
    return GF_IO_ERR;
1726
0
  }
1727
0
  nf->read_socks = gf_list_new();
1728
1729
0
  u32 magic = gf_bs_read_u32(nf->cap_bs);
1730
0
  if (magic == GF_GPC_MAGIC) {
1731
0
    nf->cap_mode = NETCAP_GPAC;
1732
0
  } else if (magic==GF_4CC(0xD4, 0xC3, 0xB2, 0xA1)) {
1733
0
    nf->cap_mode = NETCAP_PCAP;
1734
0
    nf->pcap_le = GF_TRUE;
1735
0
  } else if (magic==GF_4CC(0xA1, 0xB2, 0xC3, 0xD4)) {
1736
0
    nf->cap_mode = NETCAP_PCAP;
1737
0
  } else if (magic==GF_4CC(0x4D, 0x3C, 0xB2, 0xA1)) {
1738
0
    nf->cap_mode = NETCAP_PCAP;
1739
0
    nf->pcap_nano = GF_TRUE;
1740
0
    nf->pcap_le = GF_TRUE;
1741
0
  } else if (magic==GF_4CC(0xA1, 0xB2, 0x3C, 0x4D)) {
1742
0
    nf->cap_mode = NETCAP_PCAP;
1743
0
    nf->pcap_nano = GF_TRUE;
1744
0
  } else if (magic==GF_4CC(0x0A, 0x0D, 0x0D, 0x0A)) {
1745
0
    nf->cap_mode = NETCAP_PCAPNG;
1746
0
    nf->pcap_nano = GF_TRUE;
1747
0
  } else {
1748
0
    gf_net_close_capture();
1749
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[NetCap] Unsupported capture file magic %s\n", gf_4cc_to_str(magic)));
1750
0
    return GF_NOT_SUPPORTED;
1751
0
  }
1752
0
  if (nf->cap_mode==NETCAP_GPAC) {
1753
0
    /*ntp_sec = */gf_bs_read_u32(nf->cap_bs);
1754
0
    /*ntp_frac = */gf_bs_read_u32(nf->cap_bs);
1755
0
    magic = gf_bs_read_u32(nf->cap_bs);
1756
0
    gf_bs_skip_bytes(nf->cap_bs, magic);
1757
0
    return GF_OK;
1758
0
  }
1759
1760
0
  if (nf->cap_mode==NETCAP_PCAP) {
1761
0
    gf_bs_skip_bytes(nf->cap_bs, 16); //we ignore snapLen
1762
0
    gf_bs_read_int(nf->cap_bs, 4);
1763
0
    nf->link_types[0] = gf_bs_read_int(nf->cap_bs, 28);
1764
0
    if (nf->pcap_le) nf->link_types[0] = ntohl(nf->link_types[0]);
1765
1766
0
    switch (nf->link_types[0]) {
1767
0
    case PCAP_LT_LOOPBACK:
1768
0
    case PCAP_LT_ETHERNET:
1769
0
    case PCAP_LT_CHAOS:
1770
0
      break;
1771
0
    default:
1772
0
      GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[NetCap] Only ethernet and BSD-loopback pcap files are supported, got %u\n", nf->link_types[0]));
1773
0
      gf_net_close_capture();
1774
0
      return GF_NOT_SUPPORTED;
1775
0
    }
1776
0
  }
1777
  //pcapng
1778
0
  else if (nf->cap_mode==NETCAP_PCAPNG) {
1779
0
    GF_Err e = pcapng_load_shb(nf, GF_TRUE);
1780
0
    if (e) return e;
1781
1782
0
    u32 btype = nf->pcap_le ? gf_bs_read_u32_le(nf->cap_bs) : gf_bs_read_u32(nf->cap_bs);
1783
0
    if (btype != 1) {
1784
0
      gf_net_close_capture();
1785
0
      GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[NetCap] Missing IDB block after pacpng header\n"));
1786
0
      return GF_NON_COMPLIANT_BITSTREAM;
1787
0
    }
1788
0
    pcapng_load_idb(nf);
1789
0
  }
1790
0
  return GF_OK;
1791
0
}
1792
1793
static GF_Err gf_netcap_send_pcap(GF_NetcapFilter *nf, GF_Socket *sock, const u8 *buffer, u32 length, u32 *written, Bool is_ng)
1794
0
{
1795
0
  u32 sec, frac, pck_len, ng_size=0, ng_trail=0;
1796
0
  if (!sock->cap_info->host_port) return GF_BAD_PARAM;
1797
1798
0
  pck_len = length;
1799
0
  pck_len += 4;
1800
0
  if (sock->flags & GF_SOCK_IS_IPV6) {
1801
0
    pck_len += 40;
1802
0
  } else {
1803
0
    pck_len += 20;
1804
0
  }
1805
0
  if (sock->flags & GF_SOCK_IS_TCP) {
1806
0
    pck_len += 20;
1807
0
  } else {
1808
0
    pck_len += 8;
1809
0
  }
1810
1811
0
  if (is_ng) {
1812
0
    ng_size = pck_len/4;
1813
0
    ng_trail = pck_len%4;
1814
0
    if (ng_trail) {
1815
0
      ng_size++;
1816
0
      ng_trail = 4-ng_trail;
1817
0
    }
1818
0
    ng_size += 5;
1819
0
    ng_size *= 4;
1820
0
    ng_size+=12;
1821
1822
0
    gf_bs_write_u32(nf->cap_bs, 6);
1823
0
    gf_bs_write_u32(nf->cap_bs, ng_size);
1824
0
    gf_bs_write_u32(nf->cap_bs, 0);
1825
0
  }
1826
1827
0
  gf_net_get_ntp(&sec, &frac);
1828
0
  gf_bs_write_u32(nf->cap_bs, sec);
1829
0
  gf_bs_write_u32(nf->cap_bs, (u32) gf_timestamp_rescale(frac, 0xFFFFFFFF, 1000000));
1830
0
  gf_bs_write_u32(nf->cap_bs, pck_len);
1831
0
  gf_bs_write_u32(nf->cap_bs, pck_len);
1832
1833
0
  gf_bs_write_u32(nf->cap_bs, (sock->flags & GF_SOCK_IS_IPV6) ? 24 : 2);
1834
0
  pck_len-=4;
1835
1836
0
  u8 protocol_type = (sock->flags & GF_SOCK_IS_TCP) ? 6 : 17;
1837
0
  if (sock->flags & GF_SOCK_IS_IPV6) {
1838
0
    gf_bs_write_int(nf->cap_bs, 6, 4);
1839
0
    gf_bs_write_int(nf->cap_bs, 0, 4);
1840
0
    gf_bs_write_u24(nf->cap_bs, 0);
1841
0
    gf_bs_write_u16(nf->cap_bs, pck_len);
1842
0
    gf_bs_write_u8(nf->cap_bs, protocol_type);
1843
0
    gf_bs_write_u8(nf->cap_bs, 10);
1844
0
    gf_bs_write_data(nf->cap_bs, sock->cap_info->host_addr_v6, 16);
1845
0
    gf_bs_write_data(nf->cap_bs, sock->cap_info->peer_addr_v6, 16);
1846
0
  } else {
1847
0
    u32 chk_sum = 0x4500;
1848
0
    gf_bs_write_int(nf->cap_bs, 4, 4);
1849
0
    gf_bs_write_int(nf->cap_bs, 5, 4);
1850
0
    gf_bs_write_u8(nf->cap_bs, 0);
1851
0
    chk_sum += pck_len;
1852
0
    gf_bs_write_u16(nf->cap_bs, pck_len);
1853
0
    gf_bs_skip_bytes(nf->cap_bs, 4);
1854
0
    gf_bs_write_u8(nf->cap_bs, 10);
1855
0
    gf_bs_write_u8(nf->cap_bs, protocol_type);
1856
0
    chk_sum += (0x0a00 | protocol_type);
1857
1858
0
    chk_sum += ((sock->cap_info->host_addr_v4&0xFF)<<8) | ((sock->cap_info->host_addr_v4>>8)&0xFF);
1859
0
    chk_sum += (((sock->cap_info->host_addr_v4>>16)&0xFF)<<8) | ((sock->cap_info->host_addr_v4>>24)&0xFF);
1860
0
    chk_sum += ((sock->cap_info->peer_addr_v4&0xFF)<<8) | ((sock->cap_info->peer_addr_v4>>8)&0xFF);
1861
0
    chk_sum += (((sock->cap_info->peer_addr_v4>>16)&0xFF)<<8) | ((sock->cap_info->peer_addr_v4>>24)&0xFF);
1862
0
    if (chk_sum>0xFFFF) {
1863
0
      u32 high = chk_sum>0xFFFF;
1864
0
      chk_sum += high;
1865
0
    }
1866
0
    gf_bs_write_u16(nf->cap_bs, ~chk_sum);
1867
0
    gf_bs_write_u32_le(nf->cap_bs, sock->cap_info->host_addr_v4);
1868
0
    gf_bs_write_u32_le(nf->cap_bs, sock->cap_info->peer_addr_v4);
1869
0
  }
1870
  //UDP
1871
0
  if (protocol_type==17) {
1872
0
    gf_bs_write_u16(nf->cap_bs, sock->cap_info->host_port);
1873
0
    gf_bs_write_u16(nf->cap_bs, sock->cap_info->peer_port);
1874
0
    gf_bs_write_u16(nf->cap_bs, 8+length);
1875
    //skip checksum
1876
0
    gf_bs_skip_bytes(nf->cap_bs, 2);
1877
0
  }
1878
  //TCP
1879
0
  else if (protocol_type==6) {
1880
0
    gf_bs_write_u16(nf->cap_bs, sock->cap_info->host_port);
1881
0
    gf_bs_write_u16(nf->cap_bs, sock->cap_info->peer_port);
1882
0
    /*sn = */gf_bs_write_u32(nf->cap_bs, 0);
1883
0
    /*ack = */gf_bs_write_u32(nf->cap_bs, 0);
1884
0
    gf_bs_write_int(nf->cap_bs, 5, 4);
1885
0
    gf_bs_write_int(nf->cap_bs, 0, 4);
1886
0
    gf_bs_skip_bytes(nf->cap_bs, 7);
1887
0
  }
1888
1889
0
  gf_bs_write_data(nf->cap_bs, buffer, length);
1890
0
  if (is_ng) {
1891
0
    if (ng_trail) gf_bs_skip_bytes(nf->cap_bs, ng_trail);
1892
0
    gf_bs_write_u32(nf->cap_bs, ng_size);
1893
0
  }
1894
0
  if (written) *written = length;
1895
0
  return GF_OK;
1896
0
}
1897
1898
1899
static GF_Err gf_netcap_send_gpac(GF_NetcapFilter *nf, GF_Socket *sock, const u8 *buffer, u32 length, u32 *written)
1900
0
{
1901
0
  u64 now = gf_sys_clock_high_res();
1902
0
  if (!sock->cap_info->host_port) return GF_BAD_PARAM;
1903
0
  if (!nf->init_time) nf->init_time = now;
1904
0
  now -= nf->init_time;
1905
1906
  //setup flags and size flags
1907
0
  u32 size = 1+8+2+length;
1908
0
  u8 flags=0;
1909
0
  if (sock->flags & GF_SOCK_IS_MULTICAST) flags |= NETCAP_IS_MCAST;
1910
0
  if (sock->flags & GF_SOCK_IS_TCP) flags |= NETCAP_IS_TCP;
1911
0
  if (sock->flags & GF_SOCK_HAS_PEER) flags |= NETCAP_HAS_PEER;
1912
0
  if (sock->flags & GF_SOCK_IS_IPV6) {
1913
0
    size += 16;
1914
0
    if (sock->flags & GF_SOCK_HAS_PEER) {
1915
0
      size += 18;
1916
0
    }
1917
0
    flags |= NETCAP_IS_IPV6;
1918
0
  } else {
1919
0
    size += 4;
1920
0
    if (sock->flags & GF_SOCK_HAS_PEER) {
1921
0
      size += 6;
1922
0
    }
1923
0
  }
1924
0
  gf_bs_write_u32(nf->cap_bs, size);
1925
0
  gf_bs_write_u8(nf->cap_bs, flags);
1926
0
  gf_bs_write_u64(nf->cap_bs, now);
1927
0
  if (sock->flags & GF_SOCK_IS_IPV6) {
1928
0
    gf_bs_write_data(nf->cap_bs, sock->cap_info->host_addr_v6, 16);
1929
0
    if (sock->flags & GF_SOCK_HAS_PEER)
1930
0
      gf_bs_write_data(nf->cap_bs, sock->cap_info->peer_addr_v6, 16);
1931
0
  } else {
1932
0
    gf_bs_write_u32(nf->cap_bs, sock->cap_info->host_addr_v4);
1933
0
    if (sock->flags & GF_SOCK_HAS_PEER)
1934
0
      gf_bs_write_u32(nf->cap_bs, sock->cap_info->peer_addr_v4);
1935
0
  }
1936
0
  gf_bs_write_u16(nf->cap_bs, sock->cap_info->host_port);
1937
0
  if (sock->flags & GF_SOCK_HAS_PEER)
1938
0
    gf_bs_write_u16(nf->cap_bs, sock->cap_info->peer_port);
1939
0
  gf_bs_write_data(nf->cap_bs, buffer, length);
1940
0
  if (written) *written = length;
1941
0
  return GF_OK;
1942
0
}
1943
1944
static GF_Err gf_netcap_send(GF_Socket *sock, const u8 *buffer, u32 length, u32 *written)
1945
0
{
1946
0
  GF_NetcapFilter *nf = sock->cap_info->nf;
1947
0
  if (nf->cap_mode==NETCAP_PCAP) {
1948
0
    return gf_netcap_send_pcap(nf, sock, buffer, length, written, GF_FALSE);
1949
0
  } else if (nf->cap_mode==NETCAP_PCAPNG) {
1950
0
    return gf_netcap_send_pcap(nf, sock, buffer, length, written, GF_TRUE);
1951
0
  } else {
1952
0
    return gf_netcap_send_gpac(nf, sock, buffer, length, written);
1953
0
  }
1954
0
}
1955
#endif //GPAC_DISABLE_NETCAP
1956
1957
Bool gf_sk_has_nrt_netcap(GF_Socket *sk)
1958
0
{
1959
0
  if (sk && sk->cap_info && !sk->cap_info->nf->rt) return GF_TRUE;
1960
0
  return GF_FALSE;
1961
0
}
1962
1963
GF_EXPORT
1964
GF_Socket *gf_sk_new_ex(u32 SocketType, const char *netcap_id)
1965
0
{
1966
0
  GF_Socket *tmp;
1967
1968
  /*init WinSock*/
1969
#ifdef WIN32
1970
  WSADATA Data;
1971
  if (!wsa_init && (WSAStartup(0x0202, &Data)!=0) ) return NULL;
1972
#endif
1973
0
  switch (SocketType) {
1974
0
  case GF_SOCK_TYPE_UDP:
1975
0
  case GF_SOCK_TYPE_TCP:
1976
0
#ifdef GPAC_HAS_SOCK_UN
1977
0
  case GF_SOCK_TYPE_UDP_UN:
1978
0
  case GF_SOCK_TYPE_TCP_UN:
1979
0
#endif
1980
0
    break;
1981
0
  default:
1982
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Socket] unsupported socket type %d\n", SocketType));
1983
0
    return NULL;
1984
0
  }
1985
1986
0
  GF_SAFEALLOC(tmp, GF_Socket);
1987
0
  if (!tmp) return NULL;
1988
0
  if (SocketType == GF_SOCK_TYPE_TCP) tmp->flags |= GF_SOCK_IS_TCP;
1989
0
#ifdef GPAC_HAS_SOCK_UN
1990
0
  else if (SocketType == GF_SOCK_TYPE_TCP_UN) tmp->flags |= GF_SOCK_IS_TCP | GF_SOCK_IS_UN;
1991
0
  else if (SocketType == GF_SOCK_TYPE_UDP_UN) tmp->flags |= GF_SOCK_IS_UN;
1992
0
#endif
1993
1994
0
#ifdef GPAC_HAS_IPV6
1995
0
  memset(&tmp->dest_addr, 0, sizeof(struct sockaddr_storage));
1996
#else
1997
  memset(&tmp->dest_addr, 0, sizeof(struct sockaddr_in));
1998
  tmp->dest_addr_len = sizeof(struct sockaddr);
1999
#endif
2000
2001
0
  tmp->usec_wait = 500;
2002
#ifdef WIN32
2003
  wsa_init ++;
2004
#endif
2005
0
  tmp->socket = INVALID_SOCKET;
2006
2007
0
#ifndef GPAC_DISABLE_NETCAP
2008
0
  GF_NetcapFilter *nf = gf_net_filter_get(netcap_id);
2009
0
  if (nf && (nf->cap_bs || nf->nb_rules)) {
2010
0
    GF_SAFEALLOC(tmp->cap_info, NetCapInfo);
2011
0
    if (!tmp->cap_info) {
2012
0
      gf_free(tmp);
2013
0
      return NULL;
2014
0
    }
2015
0
    if (nf->read_socks)
2016
0
      gf_list_add(nf->read_socks, tmp);
2017
0
    tmp->cap_info->nf = nf;
2018
0
  }
2019
0
#endif
2020
0
  return tmp;
2021
0
}
2022
2023
GF_EXPORT
2024
GF_Socket *gf_sk_new(u32 SocketType)
2025
0
{
2026
0
  return gf_sk_new_ex(SocketType, NULL);
2027
0
}
2028
2029
GF_EXPORT
2030
GF_Err gf_sk_set_buffer_size(GF_Socket *sock, Bool SendBuffer, u32 NewSize)
2031
0
{
2032
0
  u32 nsize=0, psize;
2033
0
  s32 res;
2034
0
  if (!sock || SOCKET_INVALID(sock->socket)) return GF_BAD_PARAM;
2035
2036
0
  if (SendBuffer) {
2037
0
    res = setsockopt(sock->socket, SOL_SOCKET, SO_SNDBUF, (char *) &NewSize, sizeof(u32) );
2038
0
  } else {
2039
0
    res = setsockopt(sock->socket, SOL_SOCKET, SO_RCVBUF, (char *) &NewSize, sizeof(u32) );
2040
0
  }
2041
0
  if (res<0) {
2042
0
    GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Socket] Couldn't set socket %s buffer size to %d: %s (%d)\n", SendBuffer ? "send" : "receive", NewSize, gf_errno_str(LASTSOCKERROR), LASTSOCKERROR));
2043
0
  } else {
2044
0
    GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[Socket] Set socket %s buffer size to %d\n", SendBuffer ? "send" : "receive", NewSize));
2045
0
  }
2046
0
  psize = sizeof(u32);
2047
0
  if (SendBuffer) {
2048
0
    res = getsockopt(sock->socket, SOL_SOCKET, SO_SNDBUF, (char *) &nsize, &psize );
2049
0
  } else {
2050
0
    res = getsockopt(sock->socket, SOL_SOCKET, SO_RCVBUF, (char *) &nsize, &psize );
2051
0
  }
2052
0
  if ((res>=0) && (nsize!=NewSize)) {
2053
0
    GF_LOG(nsize <= NewSize ? GF_LOG_WARNING : GF_LOG_DEBUG, GF_LOG_NETWORK, ("[Socket] Asked to set socket %s buffer size to %d but system used %d\n", SendBuffer ? "send" : "receive", NewSize, nsize));
2054
0
  }
2055
2056
0
  return GF_OK;
2057
0
}
2058
2059
GF_EXPORT
2060
GF_Err gf_sk_set_block_mode(GF_Socket *sock, Bool NonBlockingOn)
2061
0
{
2062
0
  s32 res;
2063
#ifdef WIN32
2064
  long val = NonBlockingOn;
2065
  if (!SOCKET_INVALID(sock->socket)) {
2066
    res = ioctlsocket(sock->socket, FIONBIO, &val);
2067
    if (res) return GF_SERVICE_ERROR;
2068
  }
2069
#else
2070
0
  if (!SOCKET_INVALID(sock->socket)) {
2071
0
    s32 flags = fcntl(sock->socket, F_GETFL, 0);
2072
0
    if (NonBlockingOn)
2073
0
      flags |= O_NONBLOCK;
2074
0
    else
2075
0
      flags &= ~O_NONBLOCK;
2076
2077
0
    res = fcntl(sock->socket, F_SETFL, flags);
2078
0
    if (res) return GF_SERVICE_ERROR;
2079
0
  }
2080
0
#endif
2081
0
  if (NonBlockingOn) {
2082
0
    sock->flags |= GF_SOCK_NON_BLOCKING;
2083
0
  } else {
2084
0
    sock->flags &= ~GF_SOCK_NON_BLOCKING;
2085
0
  }
2086
0
  return GF_OK;
2087
0
}
2088
2089
#include <assert.h>
2090
2091
#ifndef GPAC_DISABLE_NETCAP
2092
#define sock_close(_s) \
2093
0
  closesocket(_s->socket);\
2094
0
  _s->socket = INVALID_SOCKET;\
2095
0
  if (_s->cap_info) _s->cap_info->host_port = 0; \
2096
2097
#else
2098
2099
#define sock_close(_s) \
2100
  closesocket(_s->socket);\
2101
  _s->socket = INVALID_SOCKET;
2102
2103
#endif
2104
2105
static void gf_sk_free(GF_Socket *sock)
2106
0
{
2107
0
  gf_assert( sock );
2108
0
  if (SOCKET_INVALID(sock->socket)) return;
2109
2110
  /*leave multicast*/
2111
0
  if (sock->flags & GF_SOCK_IS_MULTICAST) {
2112
0
    struct ip_mreq mreq;
2113
0
#ifdef GPAC_HAS_IPV6
2114
0
    struct sockaddr *addr = (struct sockaddr *)&sock->dest_addr;
2115
0
    if (addr->sa_family==AF_INET6) {
2116
0
      struct ipv6_mreq mreq6;
2117
0
      memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
2118
0
      mreq6.ipv6mr_interface= 0;
2119
0
      setsockopt(sock->socket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *) &mreq6, sizeof(mreq6));
2120
0
    } else {
2121
0
      mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
2122
0
      mreq.imr_interface.s_addr = INADDR_ANY;
2123
0
      setsockopt(sock->socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *) &mreq, sizeof(mreq));
2124
0
    }
2125
#else
2126
    mreq.imr_multiaddr.s_addr = sock->dest_addr.sin_addr.s_addr;
2127
    mreq.imr_interface.s_addr = INADDR_ANY;
2128
    setsockopt(sock->socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *) &mreq, sizeof(mreq));
2129
#endif
2130
0
  }
2131
2132
0
  sock_close(sock);
2133
0
}
2134
2135
2136
GF_EXPORT
2137
void gf_sk_del(GF_Socket *sock)
2138
0
{
2139
0
  gf_assert( sock );
2140
0
  gf_sk_free(sock);
2141
#ifdef WIN32
2142
  wsa_init --;
2143
  if (!wsa_init) WSACleanup();
2144
#endif
2145
2146
0
#ifndef GPAC_DISABLE_NETCAP
2147
0
  if (sock->cap_info) {
2148
0
    if (sock->cap_info->nf->read_socks)
2149
0
      gf_list_del_item(sock->cap_info->nf->read_socks, sock);
2150
0
    gf_free(sock->cap_info);
2151
0
  }
2152
0
#endif
2153
0
  gf_free(sock);
2154
0
}
2155
2156
GF_EXPORT
2157
void gf_sk_reset(GF_Socket *sock)
2158
0
{
2159
0
  if (sock) {
2160
0
    u32 clear=0;
2161
0
    setsockopt(sock->socket, SOL_SOCKET, SO_ERROR, (char *) &clear, sizeof(u32) );
2162
0
  }
2163
0
}
2164
2165
GF_EXPORT
2166
s32 gf_sk_get_handle(GF_Socket *sock)
2167
0
{
2168
0
  return (s32) sock->socket;
2169
0
}
2170
2171
GF_EXPORT
2172
void gf_sk_set_usec_wait(GF_Socket *sock, u32 usec_wait)
2173
0
{
2174
0
  if (!sock) return;
2175
0
  sock->usec_wait = (usec_wait>=1000000) ? 500 : usec_wait;
2176
0
}
2177
2178
#ifdef GPAC_STATIC_BIN
2179
struct hostent *gf_gethostbyname(const char *PeerName)
2180
{
2181
  GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("Static GPAC build has no DNS support, cannot resolve host %s !\n", PeerName));
2182
  return NULL;
2183
}
2184
#else
2185
#define gf_gethostbyname gethostbyname
2186
#endif
2187
2188
static u32 inet_addr_from_name(const char *local_interface);
2189
2190
//connects a socket to a remote peer on a given port
2191
GF_Err gf_sk_connect_ex(GF_Socket *sock, const char *PeerName, u16 PortNumber, const char *ifce_ip_or_name, Bool use_udp_connect)
2192
0
{
2193
0
  s32 ret;
2194
0
#ifdef GPAC_HAS_IPV6
2195
0
  u32 type;
2196
0
  struct addrinfo *res, *aip, *lip;
2197
#else
2198
  struct hostent *Host = NULL;
2199
#endif
2200
2201
0
  if (sock->flags & GF_SOCK_IS_UN) {
2202
0
#ifdef GPAC_HAS_SOCK_UN
2203
0
    struct sockaddr_un server_add;
2204
0
    if (SOCKET_INVALID(sock->socket)) {
2205
0
      sock->socket = socket(AF_UNIX, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
2206
0
      if (sock->flags & GF_SOCK_NON_BLOCKING)
2207
0
        gf_sk_set_block_mode(sock, GF_TRUE);
2208
0
    }
2209
0
    server_add.sun_family = AF_UNIX;
2210
0
    gf_strcpy(server_add.sun_path, PeerName);
2211
0
    server_add.sun_path[sizeof(server_add.sun_path)-1]=0;
2212
0
    if (connect(sock->socket, (struct sockaddr *)&server_add, sizeof(struct sockaddr_un)) < 0) {
2213
0
      GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Socket] Failed to connect unix domain socket to %s\n", PeerName));
2214
0
      return GF_IP_CONNECTION_FAILURE;
2215
0
    }
2216
0
    return GF_OK;
2217
#else
2218
       return GF_NOT_SUPPORTED;
2219
#endif
2220
0
  }
2221
2222
0
#ifdef GPAC_HAS_IPV6
2223
0
  type = (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM;
2224
2225
0
  GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV6] Solving %s address\n", PeerName));
2226
0
  res = gf_sk_get_ipv6_addr(PeerName, PortNumber, AF_UNSPEC, AI_PASSIVE, type);
2227
0
  if (!res) return GF_IP_CONNECTION_FAILURE;
2228
0
  GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV6] Host %s found\n", PeerName));
2229
2230
0
  lip = NULL;
2231
0
  if (ifce_ip_or_name) {
2232
0
    lip = gf_sk_get_ifce_ipv6_addr(ifce_ip_or_name, PortNumber, AF_UNSPEC, AI_PASSIVE, type);
2233
0
    if (!lip) return GF_IP_CONNECTION_FAILURE;
2234
0
  }
2235
2236
  /*for all interfaces*/
2237
0
  for (aip=res; aip!=NULL; aip=aip->ai_next) {
2238
0
    if (type != (u32) aip->ai_socktype) continue;
2239
2240
2241
0
#ifndef GPAC_DISABLE_NETCAP
2242
0
    if (sock->cap_info) {
2243
0
      sock->cap_info->host_port = PortNumber;
2244
0
      if (lip) {
2245
0
        if (lip->ai_family==PF_INET) {
2246
0
          sock->cap_info->host_addr_v4 = inet_addr_from_name(ifce_ip_or_name);
2247
0
        } else {
2248
0
          memcpy(sock->cap_info->host_addr_v6, (u8*) &((struct sockaddr_in6 *)lip->ai_addr)->sin6_addr, sizeof(bin128));
2249
0
        }
2250
0
      }
2251
0
      if (aip->ai_family==AF_INET) {
2252
0
        sock->cap_info->peer_addr_v4 = inet_addr_from_name(PeerName);
2253
0
        sock->cap_info->peer_addr_v4 = ((struct sockaddr_in *)aip->ai_addr)->sin_addr.s_addr;
2254
0
      } else {
2255
0
        memcpy(sock->cap_info->peer_addr_v6, (u8*) &((struct sockaddr_in6 *)aip->ai_addr)->sin6_addr, sizeof(bin128));
2256
0
      }
2257
      //play/record, don't create socket
2258
0
      if (sock->cap_info->nf->cap_mode) {
2259
0
        if (sock->cap_info->nf->read_socks==NULL) {
2260
0
          sock->cap_info->peer_port = first_tcp_port;
2261
0
          first_tcp_port++;
2262
0
        }
2263
0
        sock->flags |= GF_SOCK_HAS_PEER;
2264
0
        freeaddrinfo(res);
2265
0
        if (lip) freeaddrinfo(lip);
2266
0
        return GF_OK;
2267
0
      }
2268
0
    }
2269
0
#endif
2270
0
    if (SOCKET_INVALID(sock->socket)) {
2271
0
      sock->socket = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
2272
0
      if (SOCKET_INVALID(sock->socket)) {
2273
0
        continue;
2274
0
      }
2275
0
      if (sock->flags & GF_SOCK_IS_TCP) {
2276
0
        if (sock->flags & GF_SOCK_NON_BLOCKING)
2277
0
          gf_sk_set_block_mode(sock, GF_TRUE);
2278
0
      }
2279
2280
0
      if (aip->ai_family==PF_INET6) sock->flags |= GF_SOCK_IS_IPV6;
2281
0
      else sock->flags &= ~GF_SOCK_IS_IPV6;
2282
2283
0
      if (lip) {
2284
0
        ret = bind(sock->socket, lip->ai_addr, (int) lip->ai_addrlen);
2285
0
        if (ret == SOCKET_ERROR) {
2286
0
          sock_close(sock);
2287
0
          continue;
2288
0
        }
2289
0
      }
2290
0
    }
2291
2292
2293
#if defined(WIN32) || defined(_WIN32_WCE)
2294
      //on winsock we must check writability between two connects for non-blocking sockets
2295
    if ((sock->flags & GF_SOCK_IS_TCP) &&  (sock->flags & GF_SOCK_HAS_CONNECT)) {
2296
      if (gf_sk_select(sock, GF_SK_SELECT_WRITE) == GF_IP_NETWORK_EMPTY) {
2297
        GF_Err e = gf_sk_probe(sock);
2298
        if (e && (e != GF_IP_NETWORK_EMPTY)) return e;
2299
        return GF_IP_NETWORK_EMPTY;
2300
      }
2301
    }
2302
#endif
2303
2304
0
    if (sock->flags & GF_SOCK_IS_TCP) {
2305
0
      GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV6] Connecting to %s:%d\n", PeerName, PortNumber));
2306
0
    } else if (!use_udp_connect) {
2307
0
      goto conn_ok;
2308
0
    }
2309
0
    ret = connect(sock->socket, aip->ai_addr, (int) aip->ai_addrlen);
2310
0
    if (ret == SOCKET_ERROR) {
2311
0
      int err = LASTSOCKERROR;
2312
0
      if (sock->flags & GF_SOCK_NON_BLOCKING) {
2313
0
        switch (err) {
2314
0
        case EINPROGRESS:
2315
#if defined(WIN32) || defined(_WIN32_WCE)
2316
        case WSAEWOULDBLOCK:
2317
#endif
2318
0
          freeaddrinfo(res);
2319
0
          if (lip) freeaddrinfo(lip);
2320
          //remember we issued a first connect
2321
0
          sock->flags |= GF_SOCK_HAS_CONNECT;
2322
0
          return GF_IP_NETWORK_EMPTY;
2323
2324
0
        case EISCONN:
2325
0
        case EALREADY:
2326
#if defined(WIN32) || defined(_WIN32_WCE)
2327
        case WSAEISCONN:
2328
#endif
2329
0
          if (sock->flags & GF_SOCK_IS_TCP) {
2330
0
            if (gf_sk_select(sock, GF_SK_SELECT_WRITE) == GF_OK)
2331
0
              goto conn_ok;
2332
0
          }
2333
0
          freeaddrinfo(res);
2334
0
          if (lip) freeaddrinfo(lip);
2335
0
          return GF_IP_NETWORK_EMPTY;
2336
0
        }
2337
0
      }
2338
0
      sock_close(sock);
2339
0
      GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[Sock_IPV6] Failed to connect to host %s: %s (%d) - retrying with next host address\n", PeerName, gf_errno_str(err), err ));
2340
0
      continue;
2341
0
    }
2342
2343
0
conn_ok:
2344
0
    if (sock->flags & GF_SOCK_IS_TCP) {
2345
0
      GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV6] Connected to %s:%d\n", PeerName, PortNumber));
2346
0
    } else {
2347
      //udp+connect, do not use HAS_PEER
2348
0
      sock->flags &= ~GF_SOCK_HAS_PEER;
2349
0
    }
2350
0
    sock->flags &= ~GF_SOCK_HAS_CONNECT;
2351
2352
#ifdef SO_NOSIGPIPE
2353
    int value = 1;
2354
    setsockopt(sock->socket, SOL_SOCKET, SO_NOSIGPIPE, SSO_CAST &value, sizeof(value));
2355
#endif
2356
0
    memcpy(&sock->dest_addr, aip->ai_addr, aip->ai_addrlen);
2357
0
    sock->dest_addr_len = (u32) aip->ai_addrlen;
2358
0
    freeaddrinfo(res);
2359
0
    if (lip) freeaddrinfo(lip);
2360
0
    return GF_OK;
2361
0
  }
2362
0
  freeaddrinfo(res);
2363
0
  if (lip) freeaddrinfo(lip);
2364
0
  return GF_IP_CONNECTION_FAILURE;
2365
2366
#else
2367
2368
#ifndef GPAC_DISABLE_NETCAP
2369
  if (sock->cap_info) {
2370
    sock->cap_info->host_port = PortNumber;
2371
    if (ifce_ip_or_name)
2372
      sock->cap_info->host_addr_v4 = inet_addr_from_name(ifce_ip_or_name);
2373
2374
    sock->cap_info->peer_addr_v4 = inet_addr_from_name(PeerName);
2375
    if (sock->cap_info->nf->read_socks==NULL) {
2376
      sock->cap_info->peer_port = first_tcp_port;
2377
      first_tcp_port++;
2378
    }
2379
2380
    //play/record, don't create socket
2381
    if (sock->cap_info->nf->cap_mode) {
2382
      sock->flags |= GF_SOCK_HAS_PEER;
2383
      return GF_OK;
2384
    }
2385
  }
2386
#endif
2387
2388
  if (SOCKET_INVALID(sock->socket)) {
2389
    sock->socket = socket(AF_INET, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
2390
    if (sock->flags & GF_SOCK_NON_BLOCKING)
2391
      gf_sk_set_block_mode(sock, GF_TRUE);
2392
  }
2393
2394
  /*setup the address*/
2395
  sock->dest_addr.sin_family = AF_INET;
2396
  sock->dest_addr.sin_port = htons(PortNumber);
2397
  /*get the server IP*/
2398
  sock->dest_addr.sin_addr.s_addr = inet_addr(PeerName);
2399
  if (sock->dest_addr.sin_addr.s_addr==INADDR_NONE) {
2400
    GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV4] Solving %s address\n", PeerName));
2401
    Host = gf_gethostbyname(PeerName);
2402
    if (Host == NULL) {
2403
      GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV4] Failed to retrieve host %s address: %s\n", PeerName, gf_errno_str(LASTSOCKERROR) ));
2404
      switch (LASTSOCKERROR) {
2405
#ifndef __SYMBIAN32__
2406
      case ENETDOWN:
2407
        return GF_IP_NETWORK_FAILURE;
2408
        //case ENOHOST: return GF_IP_ADDRESS_NOT_FOUND;
2409
#endif
2410
      default:
2411
        return GF_IP_NETWORK_FAILURE;
2412
      }
2413
    }
2414
    GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV4] Host %s found\n", PeerName));
2415
    memcpy(&sock->dest_addr.sin_addr, Host->h_addr_list[0], sizeof(u8)*Host->h_length);
2416
  }
2417
2418
  if (ifce_ip_or_name) {
2419
    GF_Err e = gf_sk_bind(sock, ifce_ip_or_name, PortNumber, PeerName, PortNumber, GF_SOCK_REUSE_PORT);
2420
    if (e) return e;
2421
  }
2422
2423
#if defined(WIN32) || defined(_WIN32_WCE)
2424
  //on winsock we must check writability between two connects for non-blocking sockets
2425
  if ((sock->flags & GF_SOCK_IS_TCP) && (sock->flags & GF_SOCK_HAS_CONNECT)) {
2426
    if (gf_sk_select(sock, GF_SK_SELECT_WRITE) == GF_IP_NETWORK_EMPTY)
2427
      return GF_IP_NETWORK_EMPTY;
2428
  }
2429
#endif
2430
2431
  if (sock->flags & GF_SOCK_IS_TCP) {
2432
    GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV4] Connecting to %s:%d\n", PeerName, PortNumber));
2433
  } else if (!use_udp_connect) {
2434
    return GF_OK;
2435
  }
2436
  ret = connect(sock->socket, (struct sockaddr *) &sock->dest_addr, sizeof(struct sockaddr));
2437
  if (ret == SOCKET_ERROR) {
2438
    u32 res = LASTSOCKERROR;
2439
2440
    if (sock->flags & GF_SOCK_NON_BLOCKING) {
2441
      switch (res) {
2442
      case EINPROGRESS:
2443
#if defined(WIN32) || defined(_WIN32_WCE)
2444
      case WSAEWOULDBLOCK:
2445
#endif
2446
        //remember we issued a first connect
2447
        sock->flags |= GF_SOCK_HAS_CONNECT;
2448
        return GF_IP_NETWORK_EMPTY;
2449
      case EISCONN:
2450
      case EALREADY:
2451
#if defined(WIN32) || defined(_WIN32_WCE)
2452
      case WSAEISCONN:
2453
#endif
2454
        if (sock->flags & GF_SOCK_IS_TCP) {
2455
          if (gf_sk_select(sock, GF_SK_SELECT_WRITE) == GF_OK)
2456
            return GF_OK;
2457
        }
2458
        return GF_IP_NETWORK_EMPTY;
2459
      }
2460
    }
2461
    sock->flags &= ~GF_SOCK_HAS_CONNECT;
2462
2463
    switch (res) {
2464
    case EAGAIN:
2465
    case EINTR:
2466
#if defined(WIN32) || defined(_WIN32_WCE)
2467
    case WSAEWOULDBLOCK:
2468
#endif
2469
      return GF_IP_NETWORK_EMPTY;
2470
#ifdef WIN32
2471
    case WSAEINVAL:
2472
      if (sock->flags & GF_SOCK_NON_BLOCKING)
2473
        return GF_IP_NETWORK_EMPTY;
2474
#endif
2475
    case EISCONN:
2476
      return GF_OK;
2477
    default:
2478
      GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Sock_IPV4] Couldn't connect socket: %s\n", gf_errno_str(res)));
2479
      return GF_IP_CONNECTION_FAILURE;
2480
    }
2481
  }
2482
  sock->flags &= ~GF_SOCK_HAS_CONNECT;
2483
  if (sock->flags & GF_SOCK_IS_TCP) {
2484
    GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV4] Connected to %s:%d\n", PeerName, PortNumber));
2485
  }
2486
#endif
2487
0
  return GF_OK;
2488
0
}
2489
2490
GF_EXPORT
2491
GF_Err gf_sk_connect(GF_Socket *sock, const char *PeerName, u16 PortNumber, const char *ifce_ip_or_name)
2492
0
{
2493
0
  return gf_sk_connect_ex(sock, PeerName, PortNumber, ifce_ip_or_name, GF_FALSE);
2494
2495
0
}
2496
//binds the given socket to the specified port. If ReUse is true
2497
//this will enable reuse of ports on a single machine
2498
GF_EXPORT
2499
GF_Err gf_sk_bind_ex(GF_Socket *sock, const char *ifce_ip_or_name, u16 port, const char *peer_name, u16 peer_port, u32 options,
2500
  u8 **dst_sock_addr, u32 *dst_sock_addr_len, u8 **src_sock_addr, u32 *src_sock_addr_len)
2501
0
{
2502
0
#ifdef GPAC_HAS_IPV6
2503
0
  struct addrinfo *res, *aip;
2504
0
  int af;
2505
0
  u32 type;
2506
#else
2507
  u32 ip_add;
2508
  size_t addrlen;
2509
  struct sockaddr_in LocalAdd;
2510
  struct hostent *Host = NULL;
2511
#endif
2512
0
  s32 ret = 0;
2513
0
  s32 optval;
2514
2515
0
  if (dst_sock_addr) {
2516
0
    *dst_sock_addr = NULL;
2517
0
    *dst_sock_addr_len = 0;
2518
0
  }
2519
0
  if (src_sock_addr) {
2520
0
    *src_sock_addr = NULL;
2521
0
    *src_sock_addr_len = 0;
2522
0
  }
2523
  //socket must not be created
2524
0
  if (!sock || !SOCKET_INVALID(sock->socket)) return GF_BAD_PARAM;
2525
0
  if (ifce_ip_or_name && !strcmp(ifce_ip_or_name, "127.0.0.1"))
2526
0
    ifce_ip_or_name = NULL;
2527
2528
0
  if (sock->flags & GF_SOCK_IS_UN) {
2529
0
#ifdef GPAC_HAS_SOCK_UN
2530
0
    struct sockaddr_un server_un;
2531
0
    sock->socket = socket(AF_UNIX, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
2532
0
    if (sock->flags & GF_SOCK_NON_BLOCKING)
2533
0
      gf_sk_set_block_mode(sock, GF_TRUE);
2534
0
    server_un.sun_family = AF_UNIX;
2535
0
    gf_strcpy(server_un.sun_path, peer_name);
2536
0
    ret = bind(sock->socket, (struct sockaddr *) &server_un, (int) sizeof(struct sockaddr_un));
2537
0
    if (ret == SOCKET_ERROR) {
2538
0
      if (LASTSOCKERROR == EADDRINUSE) {
2539
0
        return gf_sk_connect(sock, peer_name, peer_port, NULL);
2540
0
      }
2541
0
      GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] cannot bind socket: %s\n", gf_errno_str(LASTSOCKERROR) ));
2542
0
      return GF_IP_CONNECTION_FAILURE;
2543
0
    }
2544
0
    GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[socket] socket bound to unix domain %s\n", peer_name));
2545
0
    return GF_OK;
2546
#else
2547
      return GF_NOT_SUPPORTED;
2548
#endif
2549
0
  }
2550
2551
2552
0
#ifndef WIN32
2553
0
  if (!ifce_ip_or_name && (!peer_name || !strcmp(peer_name,"localhost"))) {
2554
0
    peer_name="127.0.0.1";
2555
0
  }
2556
0
#endif
2557
2558
0
#ifdef GPAC_HAS_IPV6
2559
0
  type = (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM;
2560
0
  af = (options & GF_SOCK_FORCE_IPV6) ? PF_INET6 : PF_UNSPEC;
2561
0
  if (!gf_net_has_ipv6()) af = PF_INET;
2562
  /*probe way to peer: is it V4 or V6? */
2563
0
  if (peer_name && peer_port) {
2564
0
    res = gf_sk_get_ipv6_addr(peer_name, peer_port, af, AI_PASSIVE, type);
2565
0
    if (!res) {
2566
0
      GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Socket] Cannot get IPV6 host name for %s:%d\n", peer_name, peer_port));
2567
0
      return GF_IP_ADDRESS_NOT_FOUND;
2568
0
    }
2569
#ifdef WIN32
2570
    /*win32 has troubles redirecting IPV4 datagrams to IPV6 sockets, so override
2571
    local family type to avoid IPV4(S)->IPV6(C) UDP*/
2572
    af = res->ai_family;
2573
#endif
2574
0
    memcpy(&sock->dest_addr, res->ai_addr, res->ai_addrlen);
2575
0
    sock->dest_addr_len = (u32) res->ai_addrlen;
2576
0
    freeaddrinfo(res);
2577
2578
0
    if (dst_sock_addr) {
2579
0
      *dst_sock_addr = gf_malloc(sizeof(u8) * sock->dest_addr_len);
2580
0
      memcpy(*dst_sock_addr, &sock->dest_addr, sock->dest_addr_len);
2581
0
      *dst_sock_addr_len = sock->dest_addr_len;
2582
0
    }
2583
0
  }
2584
2585
0
  res = gf_sk_get_ifce_ipv6_addr(ifce_ip_or_name, port, af, AI_PASSIVE, type);
2586
0
  if (!res) {
2587
0
    if (dst_sock_addr && *dst_sock_addr) {
2588
0
      gf_free(*dst_sock_addr);
2589
0
      *dst_sock_addr = NULL;
2590
0
    }
2591
0
    return GF_IP_ADDRESS_NOT_FOUND;
2592
0
  }
2593
2594
  /*for all interfaces*/
2595
0
  for (aip=res; aip!=NULL; aip=aip->ai_next) {
2596
0
    if (type != (u32) aip->ai_socktype) continue;
2597
2598
0
    if (aip->ai_next && (aip->ai_next->ai_family==PF_INET) && !gf_net_is_ipv6(peer_name)) continue;
2599
2600
0
#ifndef GPAC_DISABLE_NETCAP
2601
0
    if (sock->cap_info) {
2602
0
      sock->cap_info->host_port = port ? port : peer_port;
2603
0
      if (aip->ai_family==PF_INET) {
2604
0
        sock->cap_info->host_addr_v4 = inet_addr_from_name(peer_name ? peer_name : ifce_ip_or_name);
2605
0
      } else {
2606
0
        memcpy(sock->cap_info->host_addr_v6, (u8*) &((struct sockaddr_in6 *)aip->ai_addr)->sin6_addr, sizeof(bin128));
2607
0
      }
2608
0
      if (peer_name && peer_port) {
2609
0
        if (sock->dest_addr.ss_family==AF_INET) {
2610
0
          struct sockaddr_in *r_add = (struct sockaddr_in *) &sock->dest_addr;
2611
0
          sock->cap_info->peer_port = ntohs(r_add->sin_port);
2612
0
          sock->cap_info->peer_addr_v4 = r_add->sin_addr.s_addr;
2613
0
        } else {
2614
0
          struct sockaddr_in6 *r_add = (struct sockaddr_in6 *) &sock->dest_addr;
2615
0
          sock->cap_info->peer_port = ntohs(r_add->sin6_port);
2616
0
          memcpy(sock->cap_info->peer_addr_v6, &(r_add->sin6_addr), sizeof(bin128));
2617
0
        }
2618
0
      }
2619
      //play/record, don't create socket
2620
0
      if (sock->cap_info->nf->cap_mode) {
2621
0
        if (aip->ai_family==PF_INET6) sock->flags |= GF_SOCK_IS_IPV6;
2622
0
        else sock->flags &= ~GF_SOCK_IS_IPV6;
2623
2624
0
        freeaddrinfo(res);
2625
0
        if (dst_sock_addr && *dst_sock_addr) {
2626
0
          gf_free(*dst_sock_addr);
2627
0
          *dst_sock_addr = NULL;
2628
0
        }
2629
0
        return GF_OK;
2630
0
      }
2631
0
    }
2632
0
#endif
2633
0
    sock->socket = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
2634
0
    if (SOCKET_INVALID(sock->socket)) {
2635
0
      continue;
2636
0
    }
2637
0
    if (options & GF_SOCK_REUSE_PORT) {
2638
0
      optval = 1;
2639
0
      setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
2640
0
#ifdef SO_REUSEPORT
2641
0
      optval = 1;
2642
0
      setsockopt(sock->socket, SOL_SOCKET, SO_REUSEPORT, SSO_CAST &optval, sizeof(optval));
2643
0
#endif
2644
0
    }
2645
2646
0
    if (sock->flags & GF_SOCK_NON_BLOCKING)
2647
0
      gf_sk_set_block_mode(sock, GF_TRUE);
2648
2649
0
    if (peer_name && peer_port) {
2650
0
      sock->flags |= GF_SOCK_HAS_PEER;
2651
0
    }
2652
2653
0
#if defined(GPAC_CONFIG_LINUX) || defined(GPAC_CONFIG_DARWIN)
2654
    //we use implicit bind (assign on first sendto) - not doing so makes poll/select fail in readers lanched after the sender
2655
0
    if (peer_name && !strcmp(peer_name, "127.0.0.1") && (options & GF_SOCK_IS_SENDER)) {
2656
0
    } else
2657
0
#endif
2658
0
    {
2659
0
      ret = bind(sock->socket, aip->ai_addr, (int) aip->ai_addrlen);
2660
0
      if (ret == SOCKET_ERROR) {
2661
0
        if (dst_sock_addr && *dst_sock_addr) {
2662
0
          gf_free(*dst_sock_addr);
2663
0
          *dst_sock_addr = NULL;
2664
0
        }
2665
0
        sock_close(sock);
2666
0
        if (!(options & GF_SOCK_REUSE_PORT) && (LASTSOCKERROR == EADDRINUSE)) {
2667
0
          return GF_IP_CONNECTION_FAILURE;
2668
0
        }
2669
0
        GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] bind failed: %s\n", gf_errno_str(LASTSOCKERROR) ));
2670
0
        continue;
2671
0
      }
2672
0
    }
2673
0
    if (aip->ai_family==PF_INET6) sock->flags |= GF_SOCK_IS_IPV6;
2674
0
    else sock->flags &= ~GF_SOCK_IS_IPV6;
2675
2676
0
    if (src_sock_addr) {
2677
0
      *src_sock_addr = gf_malloc(sizeof(u8) * res->ai_addrlen);
2678
0
      memcpy(*src_sock_addr, res->ai_addr, res->ai_addrlen);
2679
0
      *src_sock_addr_len = (u32) res->ai_addrlen;
2680
0
    }
2681
2682
0
    freeaddrinfo(res);
2683
0
    return GF_OK;
2684
0
  }
2685
0
  freeaddrinfo(res);
2686
0
  if (dst_sock_addr && *dst_sock_addr) {
2687
0
    gf_free(*dst_sock_addr);
2688
0
    *dst_sock_addr = NULL;
2689
0
  }
2690
0
  GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Socket] Cannot bind to ifce %s port %d\n", ifce_ip_or_name ? ifce_ip_or_name : "any", port));
2691
0
  return GF_IP_NETWORK_FAILURE;
2692
2693
#else
2694
2695
#ifndef GPAC_DISABLE_NETCAP
2696
  if (sock->cap_info) {
2697
    sock->cap_info->host_port = port ? port : peer_port;
2698
    sock->cap_info->host_addr_v4 = inet_addr_from_name(ifce_ip_or_name);
2699
    if (peer_name && peer_port) {
2700
      sock->cap_info->peer_port = peer_port;
2701
      sock->cap_info->peer_addr_v4 = inet_addr_from_name(peer_name);
2702
      sock->flags |= GF_SOCK_HAS_PEER;
2703
    }
2704
    //play/record, don't create socket
2705
    if (sock->cap_info->nf->cap_mode) {
2706
      return GF_OK;
2707
    }
2708
  }
2709
#endif
2710
2711
  sock->socket = socket(AF_INET, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
2712
  if (sock->flags & GF_SOCK_NON_BLOCKING)
2713
    gf_sk_set_block_mode(sock, GF_TRUE);
2714
  sock->flags &= ~GF_SOCK_IS_IPV6;
2715
2716
  memset((void *) &LocalAdd, 0, sizeof(LocalAdd));
2717
2718
  /*setup the address*/
2719
  ip_add = inet_addr_from_name(ifce_ip_or_name);
2720
  if (ip_add==0xFFFFFFFF) return GF_IP_CONNECTION_FAILURE;
2721
2722
  if (peer_name && peer_port) {
2723
#ifdef WIN32
2724
    if ((inet_addr(peer_name)== ip_add) || !strcmp(peer_name, "127.0.0.1") ) {
2725
      optval = 1;
2726
      setsockopt(sock->socket, SOL_SOCKET, SO_USELOOPBACK, SSO_CAST &optval, sizeof(optval));
2727
    }
2728
#endif
2729
  }
2730
2731
  LocalAdd.sin_family = AF_INET;
2732
  LocalAdd.sin_port = htons(port);
2733
  LocalAdd.sin_addr.s_addr = ip_add;
2734
  addrlen = sizeof(struct sockaddr_in);
2735
2736
  if (src_sock_addr) {
2737
    *src_sock_addr = gf_malloc(sizeof(u8) * addrlen);
2738
    memcpy(*src_sock_addr, &LocalAdd, addrlen);
2739
    *src_sock_addr_len = addrlen;
2740
  }
2741
2742
  if (options & GF_SOCK_REUSE_PORT) {
2743
    optval = 1;
2744
    setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, SSO_CAST &optval, sizeof(optval));
2745
#ifdef SO_REUSEPORT
2746
    optval = 1;
2747
    setsockopt(sock->socket, SOL_SOCKET, SO_REUSEPORT, SSO_CAST &optval, sizeof(optval));
2748
#endif
2749
  }
2750
2751
  /*bind the socket*/
2752
#ifdef GPAC_CONFIG_LINUX
2753
  //see above comment
2754
  if (peer_name && !strcmp(peer_name, "127.0.0.1") && (options & GF_SOCK_IS_SENDER) ) {
2755
  } else
2756
#endif
2757
  {
2758
    ret = bind(sock->socket, (struct sockaddr *) &LocalAdd, (int) addrlen);
2759
    if (ret == SOCKET_ERROR) {
2760
      if (!(options & GF_SOCK_REUSE_PORT) && (LASTSOCKERROR == EADDRINUSE)) {
2761
        if (src_sock_addr && *src_sock_addr) {
2762
          gf_free(*src_sock_addr);
2763
          *src_sock_addr = NULL;
2764
        }
2765
        return GF_IP_CONNECTION_FAILURE;
2766
      }
2767
      GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] cannot bind socket: %s\n", gf_errno_str(LASTSOCKERROR) ));
2768
      ret = GF_IP_NETWORK_FAILURE;
2769
    }
2770
  }
2771
2772
  if (peer_name && peer_port) {
2773
    sock->dest_addr.sin_port = htons(peer_port);
2774
    sock->dest_addr.sin_family = AF_INET;
2775
    sock->dest_addr.sin_addr.s_addr = inet_addr(peer_name);
2776
    if (sock->dest_addr.sin_addr.s_addr == INADDR_NONE) {
2777
      Host = gf_gethostbyname(peer_name);
2778
      if (Host == NULL) ret = GF_IP_ADDRESS_NOT_FOUND;
2779
      else memcpy((char *) &sock->dest_addr.sin_addr, Host->h_addr_list[0], sizeof(u32));
2780
    }
2781
    sock->flags |= GF_SOCK_HAS_PEER;
2782
2783
    if (dst_sock_addr && !ret) {
2784
      *dst_sock_addr = gf_malloc(sizeof(u8) * sock->dest_addr_len);
2785
      memcpy(*dst_sock_addr, &sock->dest_addr, sock->dest_addr_len);
2786
      *dst_sock_addr_len = sock->dest_addr_len;
2787
    }
2788
  }
2789
  if (sock->flags & GF_SOCK_HAS_PEER) {
2790
    GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[socket] socket bound to %08X - port %d - remote peer: %s:%d\n", ip_add, port, peer_name, peer_port));
2791
  } else {
2792
    GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[socket] socket bound to %08X - port %d\n", ip_add, port));
2793
  }
2794
  return ret;
2795
#endif
2796
0
}
2797
2798
GF_EXPORT
2799
GF_Err gf_sk_bind(GF_Socket *sock, const char *ifce_ip_or_name, u16 port, const char *peer_name, u16 peer_port, u32 options)
2800
0
{
2801
0
  return gf_sk_bind_ex(sock, ifce_ip_or_name, port, peer_name, peer_port, options, NULL, NULL, NULL, NULL);
2802
0
}
2803
2804
Bool gpac_use_poll=GF_TRUE;
2805
2806
static GF_Err poll_select(GF_Socket *sock, GF_SockSelectMode mode, u32 usec, Bool force_select)
2807
0
{
2808
0
#ifndef __SYMBIAN32__
2809
0
  int ready;
2810
0
  struct timeval timeout;
2811
2812
0
#ifdef GPAC_HAS_POLL
2813
0
  if (!force_select && gpac_use_poll) {
2814
0
    struct pollfd pfd;
2815
0
    pfd.fd = sock->socket;
2816
0
    pfd.revents = 0;
2817
0
    if (mode == GF_SK_SELECT_WRITE) {
2818
      //ugly patch, poll(timeout=0) sometimes crash on arm64 linux... (M4, ubuntu24 vm)
2819
#if defined(GPAC_CONFIG_ARM) && defined(GPAC_CONFIG_LINUX)
2820
      if (usec<1000) usec = 1000;
2821
#endif
2822
0
      pfd.events = POLLOUT;
2823
0
    }
2824
0
    else if (mode == GF_SK_SELECT_READ) pfd.events = POLLIN;
2825
0
    else pfd.events = POLLIN|POLLOUT;
2826
2827
0
    ready = poll(&pfd, 1, usec/1000);
2828
0
    if (ready<0) {
2829
0
      switch (LASTSOCKERROR) {
2830
0
      case EAGAIN:
2831
0
      case EINTR:
2832
0
        return GF_IP_NETWORK_EMPTY;
2833
0
      default:
2834
0
        GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] cannot poll: %s\n", gf_errno_str(LASTSOCKERROR) ));
2835
0
        return GF_IP_NETWORK_FAILURE;
2836
0
      }
2837
0
    }
2838
0
    if (!ready)
2839
0
      return GF_IP_NETWORK_EMPTY;
2840
2841
0
    if ((mode == GF_SK_SELECT_WRITE) && !(pfd.revents & POLLOUT))
2842
0
      return GF_IP_NETWORK_EMPTY;
2843
0
    if ((mode == GF_SK_SELECT_READ) && !(pfd.revents & POLLIN))
2844
0
      return GF_IP_NETWORK_EMPTY;
2845
2846
0
    return GF_OK;
2847
0
  }
2848
0
#endif
2849
2850
0
  fd_set rgroup, wgroup;
2851
2852
  //can we write?
2853
0
  FD_ZERO(&rgroup);
2854
0
  FD_ZERO(&wgroup);
2855
0
  if (mode != GF_SK_SELECT_WRITE)
2856
0
    FD_SET(sock->socket, &rgroup);
2857
0
  if (mode != GF_SK_SELECT_READ)
2858
0
    FD_SET(sock->socket, &wgroup);
2859
0
  timeout.tv_sec = 0;
2860
0
  timeout.tv_usec = usec;
2861
2862
0
  ready = select((int) sock->socket+1,
2863
0
    (mode != GF_SK_SELECT_WRITE) ? &rgroup : NULL,
2864
0
    (mode != GF_SK_SELECT_READ) ? &wgroup : NULL,
2865
0
     NULL, &timeout);
2866
2867
0
  if (ready == SOCKET_ERROR) {
2868
0
    switch (LASTSOCKERROR) {
2869
0
    case EAGAIN:
2870
0
    case EINTR:
2871
0
      return GF_IP_NETWORK_EMPTY;
2872
0
    default:
2873
0
      GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[socket] select failure: %s\n", gf_errno_str(LASTSOCKERROR)));
2874
0
      return GF_IP_NETWORK_FAILURE;
2875
0
    }
2876
0
  }
2877
0
  if (!ready)
2878
0
    return GF_IP_NETWORK_EMPTY;
2879
0
  if ((mode == GF_SK_SELECT_WRITE) && !FD_ISSET(sock->socket, &wgroup))
2880
0
    return GF_IP_NETWORK_EMPTY;
2881
0
  if ((mode == GF_SK_SELECT_READ) && !FD_ISSET(sock->socket, &rgroup))
2882
0
    return GF_IP_NETWORK_EMPTY;
2883
  //if mode is both and we are ready, let's go
2884
0
  return GF_OK;
2885
0
#endif
2886
0
}
2887
2888
//send length bytes of a buffer
2889
static GF_Err gf_sk_send_internal(GF_Socket *sock, const u8 *buffer, u32 length, const u8 *address, u32 address_len, u32 *written)
2890
0
{
2891
0
  u32 count;
2892
0
  s32 res;
2893
2894
0
  if (written) *written = 0;
2895
0
#ifndef GPAC_DISABLE_NETCAP
2896
0
  if (netcap_filter_pck(sock, length, GF_TRUE)) {
2897
0
    if (written) *written = length;
2898
0
    return GF_OK;
2899
0
  }
2900
0
  if (sock->cap_info) {
2901
0
    if (sock->cap_info->patch_offset) {
2902
0
      ((u8*)buffer)[sock->cap_info->patch_offset-1] = sock->cap_info->patch_val;
2903
0
      sock->cap_info->patch_offset = 0;
2904
0
    }
2905
0
    if (sock->cap_info->nf->read_socks==NULL)
2906
0
      return gf_netcap_send(sock, buffer, length, written);
2907
2908
0
    if (sock->cap_info->nf->read_socks)
2909
0
      return GF_OK;
2910
0
  }
2911
0
#endif
2912
2913
  //the socket must be bound or connected
2914
0
  if (!sock || SOCKET_INVALID(sock->socket))
2915
0
    return GF_BAD_PARAM;
2916
2917
0
  if (! (sock->flags & GF_SOCK_NON_BLOCKING)) {
2918
    //check write
2919
0
    GF_Err e = poll_select(sock, GF_SK_SELECT_WRITE, sock->usec_wait, GF_FALSE);
2920
0
    if (e) return e;
2921
0
  }
2922
2923
  //direct writing
2924
0
  count = 0;
2925
0
  while (count < length) {
2926
0
    int sflags = 0;
2927
0
#ifdef MSG_NOSIGNAL
2928
0
    sflags = MSG_NOSIGNAL;
2929
0
#endif
2930
0
    if (sock->flags & GF_SOCK_HAS_PEER) {
2931
0
      res = (s32) sendto(sock->socket, (char *) buffer+count,  length - count, 0, (struct sockaddr *) &sock->dest_addr, sock->dest_addr_len);
2932
0
    } else if (address && address_len) {
2933
0
      res = (s32) sendto(sock->socket, (char *) buffer+count,  length - count, 0, (struct sockaddr *) address, address_len);
2934
0
    } else {
2935
0
      res = (s32) send(sock->socket, (char *) buffer+count, length - count, sflags);
2936
0
    }
2937
0
    if (res == SOCKET_ERROR) {
2938
0
      switch (res = LASTSOCKERROR) {
2939
0
      case EAGAIN:
2940
0
      case EINTR:
2941
0
        return GF_IP_NETWORK_EMPTY;
2942
0
#ifndef __SYMBIAN32__
2943
0
      case ENOTCONN:
2944
0
      case ECONNRESET:
2945
0
      case EPIPE:
2946
0
        GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[socket] send failure: %s\n", gf_errno_str(LASTSOCKERROR)));
2947
0
        return GF_IP_CONNECTION_CLOSED;
2948
0
#endif
2949
2950
0
#ifndef __DARWIN__
2951
0
      case EPROTOTYPE:
2952
0
        return GF_IP_NETWORK_EMPTY;
2953
0
#endif
2954
0
      case ENOBUFS:
2955
0
        GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[socket] send failure: %s\n", gf_errno_str(LASTSOCKERROR)));
2956
0
        return GF_BUFFER_TOO_SMALL;
2957
0
      default:
2958
0
        GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] send failure: %s\n", gf_errno_str(LASTSOCKERROR)));
2959
0
        return GF_IP_NETWORK_FAILURE;
2960
0
      }
2961
0
    }
2962
0
    count += res;
2963
0
    if (written) *written += res;
2964
0
    GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[socket] sent %u bytes\n", count ));
2965
0
  }
2966
0
  return GF_OK;
2967
0
}
2968
2969
GF_EXPORT
2970
GF_Err gf_sk_send_ex(GF_Socket *sock, const u8 *buffer, u32 length, u32 *written)
2971
0
{
2972
0
  return gf_sk_send_internal(sock, buffer, length, NULL, 0, written);
2973
0
}
2974
GF_EXPORT
2975
GF_Err gf_sk_send(GF_Socket *sock, const u8 *buffer, u32 length)
2976
0
{
2977
0
  return gf_sk_send_internal(sock, buffer, length, NULL, 0, NULL);
2978
0
}
2979
GF_EXPORT
2980
GF_Err gf_sk_send_to(GF_Socket *sock, const u8 *buffer, u32 length, const u8 *addr, u32 addr_len, u32 *written)
2981
0
{
2982
0
  return gf_sk_send_internal(sock, buffer, length, addr, addr_len, written);
2983
0
}
2984
2985
2986
GF_Err gf_sk_select(GF_Socket *sock, GF_SockSelectMode mode)
2987
0
{
2988
  //the socket must be bound or connected
2989
0
  if (!sock || SOCKET_INVALID(sock->socket))
2990
0
    return GF_BAD_PARAM;
2991
2992
  //check write and read
2993
0
  return poll_select(sock, mode, sock->usec_wait, GF_FALSE);
2994
0
}
2995
2996
2997
GF_EXPORT
2998
u32 gf_sk_is_multicast_address(const char *multi_IPAdd)
2999
0
{
3000
0
  if (!multi_IPAdd) return 0;
3001
0
#ifdef GPAC_HAS_IPV6
3002
0
  u32 val;
3003
0
  char *sep;
3004
0
  struct addrinfo *res;
3005
0
  if (gf_net_is_ipv6(multi_IPAdd)) {
3006
    /*IPV6 multicast address*/
3007
0
    sep = strchr(multi_IPAdd, ':');
3008
0
    if (sep) sep = strchr(multi_IPAdd, ':');
3009
0
    if (sep && !strnicmp(multi_IPAdd, "ff", 2)) return 1;
3010
    //mapped address
3011
0
    if (!strnicmp(multi_IPAdd, "::ffff:", 7)) multi_IPAdd+=7;
3012
    /*ipv4 multicast address*/
3013
0
    res = gf_sk_get_ipv6_addr((char*)multi_IPAdd, 7000, AF_UNSPEC, AI_PASSIVE, SOCK_DGRAM);
3014
0
    if (!res) return 0;
3015
0
    val = 0;
3016
0
    if (res->ai_addr->sa_family == AF_INET) {
3017
0
      val = IN_MULTICAST(ntohl(((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr));
3018
0
    } else if (res->ai_addr->sa_family == AF_INET6) {
3019
0
      val = IN6_IS_ADDR_MULTICAST(& ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr);
3020
0
    }
3021
0
    freeaddrinfo(res);
3022
0
    return val;
3023
0
  }
3024
0
#endif
3025
0
  return ((htonl(inet_addr(multi_IPAdd)) >> 8) & 0x00f00000) == 0x00e00000;
3026
0
}
3027
3028
static GF_Err sk_join_ipv4(GF_Socket *sock, struct ip_mreq *M_req, u32 TTL, const char **src_ip_inc, u32 nb_src_ip_inc, const char **src_ip_exc, u32 nb_src_ip_exc)
3029
0
{
3030
0
  s32 ret;
3031
0
  u32 flag;
3032
3033
0
  if (nb_src_ip_inc) {
3034
0
#ifdef IP_ADD_SOURCE_MEMBERSHIP
3035
0
    u32 i;
3036
0
    struct ip_mreq_source M_req_src;
3037
0
    M_req_src.imr_multiaddr = M_req->imr_multiaddr;
3038
0
    M_req_src.imr_interface = M_req->imr_interface;
3039
3040
0
    for (i=0; i<nb_src_ip_inc; i++) {
3041
0
      if (gf_net_is_ipv6(src_ip_inc[i])) {
3042
0
        GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] IPv6 SSM source on IPv4 Mcast address, ignoring\n", src_ip_inc[i]));
3043
0
        continue;
3044
0
      }
3045
0
      M_req_src.imr_sourceaddr.s_addr = inet_addr(src_ip_inc[i]);
3046
0
      ret = setsockopt(sock->socket, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, (char *) &M_req_src, sizeof(M_req_src) );
3047
0
      if (ret == SOCKET_ERROR) {
3048
0
        GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] cannot add source membership for %s: %s\n", src_ip_inc[i], gf_errno_str(LASTSOCKERROR)));
3049
0
        return GF_IP_CONNECTION_FAILURE;
3050
0
      }
3051
0
    }
3052
#else
3053
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] SSM IPv4 not supported\n"));
3054
    return GF_NOT_SUPPORTED;
3055
#endif
3056
0
  } else {
3057
0
    ret = setsockopt(sock->socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) M_req, sizeof(*M_req));
3058
0
    if (ret == SOCKET_ERROR) {
3059
0
      GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] cannot join multicast: %s\n", gf_errno_str(LASTSOCKERROR)));
3060
0
      return GF_IP_CONNECTION_FAILURE;
3061
0
    }
3062
0
  }
3063
  /*set the Time To Live*/
3064
0
  if (TTL) {
3065
0
    ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&TTL, sizeof(TTL));
3066
0
    if (ret == SOCKET_ERROR) {
3067
0
      GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[Socket] Cannot set TTL: %s\n", gf_errno_str(LASTSOCKERROR) ));
3068
0
      return GF_IP_CONNECTION_FAILURE;
3069
0
    }
3070
0
  }
3071
3072
  /*enable loopback*/
3073
0
  flag = 1;
3074
0
  ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &flag, sizeof(flag));
3075
0
  if (ret == SOCKET_ERROR) {
3076
0
    GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[Socket] Cannot enable multicast loop: %s - ignoring\n", gf_errno_str(LASTSOCKERROR) ));
3077
0
  }
3078
3079
0
#ifdef IP_BLOCK_SOURCE
3080
0
  if (nb_src_ip_exc) {
3081
0
    u32 i, j;
3082
0
    struct ip_mreq_source M_req_exc;
3083
0
    M_req_exc.imr_multiaddr = M_req->imr_multiaddr;
3084
0
    M_req_exc.imr_interface = M_req->imr_interface;
3085
0
    for (i=0; i<nb_src_ip_exc; i++) {
3086
0
      Bool match=GF_FALSE;
3087
0
      if (gf_net_is_ipv6(src_ip_exc[i])) {
3088
0
        GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] IPv6 SSM source on IPv4 Mcast address, ignoring\n", src_ip_exc[i]));
3089
0
        continue;
3090
0
      }
3091
0
      for (j=0; j<nb_src_ip_inc; j++) {
3092
0
        if (!strcmp(src_ip_inc[j], src_ip_exc[i])) match=GF_TRUE;
3093
0
      }
3094
0
      if (match) continue;
3095
3096
0
      M_req_exc.imr_sourceaddr.s_addr = inet_addr(src_ip_exc[i]);
3097
0
      ret = setsockopt(sock->socket, IPPROTO_IP, IP_BLOCK_SOURCE, (char *) &M_req_exc, sizeof(M_req_exc) );
3098
0
      if (ret == SOCKET_ERROR) {
3099
0
        GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] cannot block source membership for %s: %s\n", src_ip_exc[i], gf_errno_str(LASTSOCKERROR)));
3100
0
        return GF_IP_CONNECTION_FAILURE;
3101
0
      }
3102
0
    }
3103
0
  }
3104
#else
3105
  GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[core] SSM IPv4 not supported\n"));
3106
#endif
3107
0
  return GF_OK;
3108
0
}
3109
3110
static u32 inet_addr_from_name(const char *local_interface)
3111
0
{
3112
0
  if (!local_interface) return htonl(INADDR_ANY);
3113
3114
0
  if (strchr(local_interface, '.'))
3115
0
    return inet_addr(local_interface);
3116
3117
0
  Bool name_match = GF_FALSE;
3118
0
  u32 ret = 0;
3119
3120
#if defined(GPAC_WIN_HAS_ADAPTER_INFO)
3121
  IP_ADAPTER_ADDRESSES *AdapterInfo = malloc(sizeof(IP_ADAPTER_ADDRESSES));
3122
  IP_ADAPTER_ADDRESSES *ifa = NULL;
3123
  ULONG ulOutBufLen = sizeof(AdapterInfo);
3124
  if (AdapterInfo && (GetAdaptersAddresses(AF_INET, 0, NULL, AdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW)) {
3125
    free(AdapterInfo);
3126
    AdapterInfo = malloc(sizeof(IP_ADAPTER_ADDRESSES)*ulOutBufLen);
3127
  }
3128
  if (AdapterInfo)
3129
    GetAdaptersAddresses(AF_INET, 0, NULL, AdapterInfo, &ulOutBufLen);
3130
3131
  ifa = AdapterInfo;
3132
  while (ifa) {
3133
    Bool match = GF_FALSE;
3134
    if (!strcmp(ifa->AdapterName, local_interface)) match = GF_FALSE;
3135
    char *name = gf_wcs_to_utf8(ifa->FriendlyName);
3136
    if (name) {
3137
      if (!strcmp(name, local_interface)) match = GF_TRUE;
3138
      gf_free(name);
3139
    }
3140
    if (match) name_match = GF_TRUE;
3141
3142
    if (!match || !ifa->FirstUnicastAddress || !ifa->FirstUnicastAddress->Address.lpSockaddr) {
3143
      ifa = ifa->Next;
3144
      continue;
3145
    }
3146
    ret = ((struct sockaddr_in*)ifa->FirstUnicastAddress->Address.lpSockaddr)->sin_addr.s_addr;
3147
    break;
3148
  }
3149
  if (AdapterInfo)
3150
    free(AdapterInfo);
3151
#endif
3152
3153
0
#if defined(GPAC_HAS_IFADDRS)
3154
0
  struct ifaddrs *ifap=NULL, *res;
3155
0
  getifaddrs(&ifap);
3156
0
  res = ifap;
3157
0
  while (res) {
3158
0
    if (res->ifa_name && !strcmp(res->ifa_name, local_interface)) {
3159
0
      name_match = GF_TRUE;
3160
0
      if (res->ifa_addr && (res->ifa_addr->sa_family==AF_INET)) {
3161
0
        ret = ((struct sockaddr_in*)res->ifa_addr)->sin_addr.s_addr;
3162
0
        break;
3163
0
      }
3164
0
    }
3165
0
    res = res->ifa_next;
3166
0
  }
3167
0
  freeifaddrs(ifap);
3168
0
#endif
3169
0
  if (!name_match) {
3170
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] No such interface %s\n", local_interface));
3171
0
    return 0xFFFFFFFF;
3172
0
  }
3173
0
  if (!ret) {
3174
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] Interface %s found but has no IPv4 addressing, using INADDR_ANY\n", local_interface));
3175
0
    return htonl(INADDR_ANY);
3176
0
  }
3177
0
  return ret;
3178
0
}
3179
3180
GF_EXPORT
3181
Bool gf_net_enum_interfaces(gf_net_ifce_enum do_enum, void *enum_cbk)
3182
0
{
3183
#if defined(GPAC_WIN_HAS_ADAPTER_INFO)
3184
  IP_ADAPTER_ADDRESSES *AdapterInfo = malloc(sizeof(IP_ADAPTER_ADDRESSES));
3185
  IP_ADAPTER_ADDRESSES *ifa = NULL;
3186
  ULONG ulOutBufLen = sizeof(AdapterInfo);
3187
  if (AdapterInfo && (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, AdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW)) {
3188
    free(AdapterInfo);
3189
    AdapterInfo = malloc(sizeof(IP_ADAPTER_ADDRESSES)*ulOutBufLen);
3190
  }
3191
  if (AdapterInfo)
3192
    GetAdaptersAddresses(AF_UNSPEC, 0, NULL, AdapterInfo, &ulOutBufLen);
3193
3194
  ifa = AdapterInfo;
3195
  while (ifa) {
3196
    if (ifa->FirstUnicastAddress) {
3197
      char szIP[100];
3198
      szIP[0] = 0;
3199
      u32 flags = 0;
3200
      if (ifa->OperStatus == 1) flags |= GF_NETIF_ACTIVE;
3201
      if (ifa->Flags & IP_ADAPTER_NO_MULTICAST) flags |= GF_NETIF_NO_MCAST;
3202
      if (ifa->Flags & IP_ADAPTER_RECEIVE_ONLY) flags |= GF_NETIF_RECV_ONLY;
3203
      if (ifa->IfType == IF_TYPE_SOFTWARE_LOOPBACK) flags |= GF_NETIF_LOOPBACK;
3204
3205
      Bool abort=GF_FALSE;
3206
      IP_ADAPTER_UNICAST_ADDRESS_LH *ipadd = ifa->FirstUnicastAddress;
3207
      while (ipadd) {
3208
        u32 sa_fam = ipadd->Address.lpSockaddr ? ipadd->Address.lpSockaddr->sa_family : AF_UNSPEC;
3209
        if (ipadd->Flags & IP_ADAPTER_ADDRESS_TRANSIENT) sa_fam = AF_UNSPEC;
3210
        if ((sa_fam == AF_INET) || (sa_fam == AF_INET6)) {
3211
          my_inet_ntop(sa_fam, ipadd->Address.lpSockaddr, szIP, 100);
3212
          char *name = gf_wcs_to_utf8(ifa->FriendlyName);
3213
          Bool res = do_enum(enum_cbk, name ? name : ifa->AdapterName, szIP[0] ? szIP : NULL, flags | ((sa_fam==AF_INET6) ? GF_NETIF_IPV6 : 0));
3214
          if (name) gf_free(name);
3215
          if (res) break;
3216
        }
3217
        ipadd = ipadd->Next;
3218
      }
3219
      if (abort) break;
3220
    }
3221
    ifa = ifa->Next;
3222
  }
3223
  if (AdapterInfo)
3224
    free(AdapterInfo);
3225
  return GF_TRUE;
3226
#endif
3227
3228
0
#if defined(GPAC_HAS_IFADDRS)
3229
0
  struct ifaddrs *ifap=NULL, *res;
3230
0
  getifaddrs(&ifap);
3231
0
  res = ifap;
3232
0
  while (res) {
3233
0
    if (res->ifa_addr) {
3234
0
      char szIP[100];
3235
0
      szIP[0] = 0;
3236
0
      u32 flags=0;
3237
0
      if (res->ifa_flags & IFF_UP) flags |= GF_NETIF_ACTIVE;
3238
0
      if (res->ifa_flags & IFF_LOOPBACK) flags |= GF_NETIF_LOOPBACK;
3239
0
      if (!(res->ifa_flags & IFF_MULTICAST)) flags |= GF_NETIF_NO_MCAST;
3240
3241
0
      if (res->ifa_addr->sa_family==AF_INET) {
3242
0
        inet_ntop(AF_INET, &( ((struct sockaddr_in *)res->ifa_addr)->sin_addr), szIP, 100);
3243
0
        if (do_enum(enum_cbk, res->ifa_name, szIP[0] ? szIP : NULL, flags))
3244
0
          break;
3245
0
      }
3246
0
      if (res->ifa_addr->sa_family==AF_INET6) {
3247
0
        inet_ntop(AF_INET6, &( ((struct sockaddr_in6 *)res->ifa_addr)->sin6_addr), szIP, 100);
3248
0
        if (do_enum(enum_cbk, res->ifa_name, szIP[0] ? szIP : NULL, flags|GF_NETIF_IPV6))
3249
0
          break;
3250
0
      }
3251
0
    }
3252
0
    res = res->ifa_next;
3253
0
  }
3254
0
  freeifaddrs(ifap);
3255
0
  return GF_TRUE;
3256
0
#endif
3257
0
  return GF_FALSE;
3258
0
}
3259
3260
typedef struct
3261
{
3262
  const char *ip_or_name;
3263
  char *res_v6, *res_v4;
3264
} GetIPInfo;
3265
3266
static Bool get_ifce_enum(void *cbk, const char *name, const char *IP, u32 flags)
3267
0
{
3268
0
  GetIPInfo *info = (GetIPInfo*)cbk;
3269
0
  if (strcmp(info->ip_or_name, name) && strcmp(info->ip_or_name, IP)) return GF_FALSE;
3270
0
  if (flags & GF_NETIF_IPV6) {
3271
0
    if (!info->res_v6) info->res_v6 = gf_strdup(IP);
3272
0
  } else {
3273
0
    if (!info->res_v4) info->res_v4 = gf_strdup(IP);
3274
0
  }
3275
0
  return GF_FALSE;
3276
0
}
3277
3278
Bool gf_net_get_adapter_ip(const char *ip_or_name, char **ipv4, char **ipv6)
3279
0
{
3280
0
  GetIPInfo info;
3281
0
  info.ip_or_name = ip_or_name;
3282
0
  info.res_v4 = info.res_v6 = NULL;
3283
0
  if (ipv4) *ipv4 = NULL;
3284
0
  if (ipv6) *ipv6 = NULL;
3285
0
  if (!ip_or_name) return GF_FALSE;
3286
0
  Bool res = gf_net_enum_interfaces(get_ifce_enum, &info);
3287
0
  if (!res) return GF_FALSE;
3288
0
  if (ipv4) *ipv4 = info.res_v4;
3289
0
  else if (info.res_v4) gf_free(info.res_v4);
3290
0
  if (ipv6) *ipv6 = info.res_v6;
3291
0
  else if (info.res_v6) gf_free(info.res_v6);
3292
0
  return GF_TRUE;
3293
0
}
3294
3295
GF_EXPORT
3296
GF_Err gf_sk_setup_multicast_ex(GF_Socket *sock, const char *multi_IPAdd, u16 MultiPortNumber, u32 TTL, Bool NoBind, const char *ifce_ip_or_name,
3297
  const char **src_ip_inc, u32 nb_src_ip_inc, const char **src_ip_exc, u32 nb_src_ip_exc)
3298
0
{
3299
0
  s32 ret;
3300
0
  struct ip_mreq M_req;
3301
0
  u32 optval;
3302
0
#ifdef GPAC_HAS_IPV6
3303
0
  struct sockaddr *addr;
3304
0
  Bool mcast_ipv6 = GF_FALSE;
3305
0
  Bool ifce_ipv6 = GF_FALSE;
3306
0
  u32 type;
3307
0
#endif
3308
0
  GF_Err e;
3309
0
  u32 local_add_id;
3310
3311
  //socket must not be created
3312
0
  if (!sock || !SOCKET_INVALID(sock->socket)) return GF_BAD_PARAM;
3313
3314
0
  if (TTL > 255) TTL = 255;
3315
3316
  /*check the address*/
3317
0
  if (!gf_sk_is_multicast_address(multi_IPAdd)) return GF_BAD_PARAM;
3318
3319
3320
0
#ifdef GPAC_HAS_IPV6
3321
0
  mcast_ipv6 = gf_net_is_ipv6(multi_IPAdd);
3322
0
  ifce_ipv6 = gf_net_is_ipv6(ifce_ip_or_name);
3323
0
  if (ifce_ip_or_name && (ifce_ip_or_name[0]=='+')) {
3324
0
    ifce_ip_or_name += 1;
3325
0
    ifce_ipv6 = GF_TRUE;
3326
0
  }
3327
0
  if (ifce_ip_or_name && !ifce_ip_or_name[0])
3328
0
    ifce_ip_or_name=NULL;
3329
3330
0
  type = (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM;
3331
3332
0
  if (mcast_ipv6 || ifce_ipv6) {
3333
0
    Bool is_mapped_v4=GF_FALSE;
3334
0
    struct addrinfo *res, *aip;
3335
0
    struct ipv6_mreq M_reqV6;
3336
0
    memset(&M_reqV6, 0, sizeof(struct ipv6_mreq));
3337
3338
    //get interface index - force IPV6 when getting address and store result
3339
0
    if (ifce_ip_or_name) {
3340
#if defined(GPAC_WIN_HAS_ADAPTER_INFO)
3341
      IP_ADAPTER_ADDRESSES *AdapterInfo = malloc(sizeof(IP_ADAPTER_ADDRESSES));
3342
      ULONG ulOutBufLen = sizeof(AdapterInfo);
3343
      if (AdapterInfo && (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, AdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW)) {
3344
        free(AdapterInfo);
3345
        AdapterInfo = malloc(sizeof(IP_ADAPTER_ADDRESSES)*ulOutBufLen);
3346
      }
3347
      if (AdapterInfo)
3348
        GetAdaptersAddresses(AF_UNSPEC, 0, NULL, AdapterInfo, &ulOutBufLen);
3349
3350
      IP_ADAPTER_ADDRESSES *ifa = AdapterInfo;
3351
      while (ifa) {
3352
        //match by adapter name
3353
        if (!strcmp(ifa->AdapterName, ifce_ip_or_name)) {
3354
          M_reqV6.ipv6mr_interface = ifa->Ipv6IfIndex;
3355
          break;
3356
        }
3357
        char *name = gf_wcs_to_utf8(ifa->FriendlyName);
3358
        if (name && !strcmp(name, ifce_ip_or_name)) {
3359
          M_reqV6.ipv6mr_interface = ifa->Ipv6IfIndex;
3360
          gf_free(name);
3361
          break;
3362
        }
3363
        if (name) gf_free(name);
3364
        name = gf_wcs_to_utf8(ifa->Description);
3365
        if (!strcmp(name, ifce_ip_or_name)) {
3366
          M_reqV6.ipv6mr_interface = ifa->Ipv6IfIndex;
3367
          gf_free(name);
3368
          break;
3369
        }
3370
        if (name) gf_free(name);
3371
3372
        //match by IP
3373
        IP_ADAPTER_UNICAST_ADDRESS_LH *ipadd = ifa->FirstUnicastAddress;
3374
        while (ipadd) {
3375
          u32 sa_fam = ipadd->Address.lpSockaddr ? ipadd->Address.lpSockaddr->sa_family : AF_UNSPEC;
3376
          if ((sa_fam == AF_INET) || (sa_fam == AF_INET6)) {
3377
            char szIP[100];
3378
            my_inet_ntop(sa_fam, ipadd->Address.lpSockaddr, szIP, 100);
3379
            if (!strcmp(szIP, ifce_ip_or_name)) {
3380
              M_reqV6.ipv6mr_interface = ifa->Ipv6IfIndex;
3381
              break;
3382
            }
3383
          }
3384
          ipadd = ipadd->Next;
3385
        }
3386
3387
        ifa = ifa->Next;
3388
      }
3389
      if (AdapterInfo) free(AdapterInfo);
3390
#endif
3391
3392
0
#if defined(GPAC_HAS_IFADDRS)
3393
      //get sockaddr if this is an IP address and compare with enumerated interface
3394
0
      aip = NULL;
3395
0
      if (ifce_ip_or_name && strpbrk(ifce_ip_or_name, ".:")) {
3396
0
        aip = gf_sk_get_ipv6_addr(ifce_ip_or_name, MultiPortNumber, ifce_ipv6 ? AF_INET6 : AF_UNSPEC, AI_PASSIVE, type);
3397
0
      }
3398
0
      struct ifaddrs *ifap=NULL, *ifa;
3399
0
      getifaddrs(&ifap);
3400
0
      ifa = ifap;
3401
0
      while (ifa) {
3402
        //match by ifce name
3403
0
        if (ifa->ifa_addr && !strcmp(ifa->ifa_name, ifce_ip_or_name)
3404
0
          && ((ifa->ifa_addr->sa_family == AF_INET) || (ifa->ifa_addr->sa_family == AF_INET6))
3405
0
        ) {
3406
0
          M_reqV6.ipv6mr_interface = if_nametoindex(ifa->ifa_name);
3407
0
          break;
3408
0
        }
3409
        //match by ifce IP
3410
0
        if (aip && ifa->ifa_addr) {
3411
0
          struct sockaddr_in6 *in6_a = (struct sockaddr_in6 *)aip->ai_addr;
3412
0
          struct sockaddr_in6 *in6_b = (struct sockaddr_in6 *)ifa->ifa_addr;
3413
0
          if ((in6_a->sin6_family == in6_b->sin6_family)
3414
0
            && !memcmp(&in6_a->sin6_addr, &in6_b->sin6_addr, sizeof(struct in6_addr))
3415
0
          ) {
3416
3417
0
            M_reqV6.ipv6mr_interface = if_nametoindex(ifa->ifa_name);
3418
0
            break;
3419
0
          }
3420
0
        }
3421
0
        ifa = ifa->ifa_next;
3422
0
      }
3423
0
      if (ifap)
3424
0
        freeifaddrs(ifap);
3425
0
      if (aip)
3426
0
        freeaddrinfo(aip);
3427
0
#endif
3428
3429
0
      if (!M_reqV6.ipv6mr_interface) {
3430
0
        GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] Failed to query interface index for %s\n", ifce_ip_or_name ));
3431
0
        return GF_IP_CONNECTION_FAILURE;
3432
0
      }
3433
0
    }
3434
3435
    //do not specify local_interface_ip address
3436
0
    res = gf_sk_get_ipv6_addr(NULL, MultiPortNumber, ifce_ipv6 ? AF_INET6 : AF_UNSPEC, AI_PASSIVE, type);
3437
0
    if (!res) return GF_IP_CONNECTION_FAILURE;
3438
3439
    /*for all interfaces*/
3440
0
    for (aip=res; aip!=NULL; aip=aip->ai_next) {
3441
0
      if (type != (u32) aip->ai_socktype) continue;
3442
      //we have a v4 multicast address
3443
0
      if (!gf_net_is_ipv6(multi_IPAdd)) {
3444
        //if not v4 and next is v4, use next
3445
0
        if ((aip->ai_family!=PF_INET) && aip->ai_next && (aip->ai_next->ai_family==PF_INET)) continue;
3446
0
      } else {
3447
        //we want v6, if v4 and next is v6, use next
3448
0
        if ((aip->ai_family==PF_INET) && aip->ai_next && (aip->ai_next->ai_family==PF_INET6)) continue;
3449
0
      }
3450
0
      sock->socket = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
3451
0
      if (SOCKET_INVALID(sock->socket)) {
3452
0
        continue;
3453
0
      }
3454
3455
      /*enable address reuse*/
3456
0
      optval = 1;
3457
0
      setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
3458
0
#ifdef SO_REUSEPORT
3459
0
      optval = 1;
3460
0
      setsockopt(sock->socket, SOL_SOCKET, SO_REUSEPORT, SSO_CAST &optval, sizeof(optval));
3461
0
#endif
3462
3463
0
      if (!mcast_ipv6 && (aip->ai_family == PF_INET6)) {
3464
0
        optval = 0;
3465
0
        ret = setsockopt(sock->socket, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&optval, sizeof(optval));
3466
0
        if (ret == SOCKET_ERROR) {
3467
0
          GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[Socket] Cannot disable ipv6only: %s\n", gf_errno_str(LASTSOCKERROR)));
3468
0
        }
3469
0
      }
3470
3471
0
      if (!NoBind) {
3472
0
        ret = bind(sock->socket, (struct sockaddr *) aip->ai_addr, (int) aip->ai_addrlen);
3473
0
        if (ret == SOCKET_ERROR) {
3474
0
          GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] cannot bind socket: %s\n", gf_errno_str(LASTSOCKERROR)));
3475
0
          return GF_IP_CONNECTION_FAILURE;
3476
0
        }
3477
0
      }
3478
0
      if (aip->ai_family==PF_INET6) sock->flags |= GF_SOCK_IS_IPV6;
3479
0
      else sock->flags &= ~GF_SOCK_IS_IPV6;
3480
0
      break;
3481
0
    }
3482
0
    freeaddrinfo(res);
3483
3484
0
    if (SOCKET_INVALID(sock->socket) ) return GF_IP_CONNECTION_FAILURE;
3485
3486
    /*TODO: copy over other properties (recption buffer size & co)*/
3487
0
    if (sock->flags & GF_SOCK_NON_BLOCKING)
3488
0
      gf_sk_set_block_mode(sock, GF_TRUE);
3489
3490
0
    res = gf_sk_get_ipv6_addr(multi_IPAdd, MultiPortNumber, (sock->flags & GF_SOCK_IS_IPV6) ? AF_INET6 : AF_UNSPEC, 0, SOCK_DGRAM);
3491
0
    if (!res) {
3492
0
      if (sock->flags & GF_SOCK_IS_IPV6) {
3493
0
        char szIP[100];
3494
0
        gf_strcpy(szIP, "::ffff:");
3495
0
        gf_strcat(szIP, multi_IPAdd);
3496
0
        is_mapped_v4 = GF_TRUE;
3497
0
        res = gf_sk_get_ipv6_addr(szIP, MultiPortNumber, AF_INET6, 0, SOCK_DGRAM);
3498
0
      }
3499
0
      if (!res)
3500
0
        return GF_IP_CONNECTION_FAILURE;
3501
0
    }
3502
    //copy for sendto
3503
0
    memcpy(&sock->dest_addr, res->ai_addr, res->ai_addrlen);
3504
0
    sock->dest_addr_len = (u32) res->ai_addrlen;
3505
0
    freeaddrinfo(res);
3506
3507
0
    addr = (struct sockaddr *)&sock->dest_addr;
3508
    //ipv4
3509
0
    if (is_mapped_v4) {
3510
0
      local_add_id = inet_addr_from_name(ifce_ip_or_name);
3511
0
      if (local_add_id==0xFFFFFFFF) return GF_IP_CONNECTION_FAILURE;
3512
3513
0
      M_req.imr_multiaddr.s_addr = inet_addr(multi_IPAdd);
3514
0
      M_req.imr_interface.s_addr = local_add_id;
3515
3516
0
      e = sk_join_ipv4(sock, &M_req, TTL, src_ip_inc, nb_src_ip_inc, src_ip_exc, nb_src_ip_exc);
3517
0
      if (e) return e;
3518
      //keep sock->dest_addr untouched so that we still have a ipv6 sockaddr
3519
0
      sock->flags |= GF_SOCK_IS_MULTICAST | GF_SOCK_HAS_PEER;
3520
0
      return GF_OK;
3521
0
    }
3522
0
    else if (addr->sa_family != AF_INET6) {
3523
0
      return GF_IP_CONNECTION_FAILURE;
3524
0
    }
3525
3526
0
    memcpy(&M_reqV6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
3527
3528
    /*set send IF index*/
3529
0
    optval = M_reqV6.ipv6mr_interface;
3530
0
    ret = setsockopt(sock->socket, IPPROTO_IPV6, IPV6_MULTICAST_IF, (const char *)&optval, sizeof(optval));
3531
0
    if (ret == SOCKET_ERROR) {
3532
0
    }
3533
3534
0
    if (nb_src_ip_inc) {
3535
0
#ifdef MCAST_JOIN_SOURCE_GROUP
3536
0
      u32 i;
3537
0
      struct group_source_req M_reqV6_src;
3538
0
      memset(&M_reqV6_src, 0, sizeof(struct group_source_req));
3539
0
      M_reqV6_src.gsr_interface = 0;
3540
0
      M_reqV6_src.gsr_group = sock->dest_addr;
3541
3542
0
      for (i=0; i<nb_src_ip_inc; i++) {
3543
0
        res = gf_sk_get_ipv6_addr(src_ip_inc[i], MultiPortNumber, AF_INET6, 0, SOCK_DGRAM);
3544
0
        if (!res) {
3545
0
          GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] Failed to get address info for SSM source %s, ignoring\n", src_ip_inc[i]));
3546
0
          continue;
3547
0
        }
3548
0
        memcpy(&M_reqV6_src.gsr_source, res->ai_addr, res->ai_addrlen);
3549
0
        freeaddrinfo(res);
3550
0
        ret = setsockopt(sock->socket, IPPROTO_IPV6, MCAST_JOIN_SOURCE_GROUP, (char *) &M_reqV6_src, sizeof(M_reqV6_src) );
3551
0
        if (ret == SOCKET_ERROR) {
3552
0
          GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] cannot join source group %s: %s\n", src_ip_inc[i], gf_errno_str(LASTSOCKERROR)));
3553
0
          return GF_IP_CONNECTION_FAILURE;
3554
0
        }
3555
0
      }
3556
#else
3557
      GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] SSM IPv6 not supported\n"));
3558
      return GF_NOT_SUPPORTED;
3559
#endif
3560
3561
0
    } else {
3562
0
      ret = setsockopt(sock->socket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *) &M_reqV6, sizeof(M_reqV6));
3563
0
      if (ret == SOCKET_ERROR) {
3564
0
        GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] Failed to join multicast: %s\n", gf_errno_str(LASTSOCKERROR) ));
3565
0
        return GF_IP_CONNECTION_FAILURE;
3566
0
      }
3567
0
    }
3568
3569
    /*set TTL*/
3570
0
    if (TTL != 0) {
3571
0
      ret = setsockopt(sock->socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &TTL, sizeof(TTL));
3572
0
      if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
3573
0
    }
3574
3575
    /*enable loopback*/
3576
0
    optval = 1;
3577
0
    ret = setsockopt(sock->socket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *) &optval, sizeof(optval));
3578
0
    if (ret == SOCKET_ERROR) {
3579
0
      GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[Socket] Cannot enable multicast loop: %s\n", gf_errno_str(LASTSOCKERROR) ));
3580
0
    }
3581
3582
0
    if (nb_src_ip_exc) {
3583
0
#ifdef MCAST_BLOCK_SOURCE
3584
0
      u32 i, j;
3585
0
      struct group_source_req M_reqV6_src;
3586
0
      M_reqV6_src.gsr_interface = 0;
3587
0
      M_reqV6_src.gsr_group = sock->dest_addr;
3588
0
      for (i=0; i<nb_src_ip_exc; i++) {
3589
0
        Bool match=GF_FALSE;
3590
0
        for (j=0; j<nb_src_ip_inc; j++) {
3591
0
          if (!strcmp(src_ip_inc[j], src_ip_exc[i])) match=GF_TRUE;
3592
0
        }
3593
0
        if (match) continue;
3594
3595
0
        res = gf_sk_get_ipv6_addr(src_ip_exc[i], MultiPortNumber, AF_INET6, 0, SOCK_DGRAM);
3596
0
        if (!res) {
3597
0
          GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] Failed to get address info for SSM excluded source %s, ignoring\n", src_ip_exc[i]));
3598
0
          continue;
3599
0
        }
3600
0
        memcpy(&M_reqV6_src.gsr_source, res->ai_addr, res->ai_addrlen);
3601
0
        freeaddrinfo(res);
3602
3603
0
        ret = setsockopt(sock->socket, IPPROTO_IPV6, MCAST_BLOCK_SOURCE, (char *) &M_reqV6_src, sizeof(M_reqV6_src) );
3604
0
        if (ret == SOCKET_ERROR) {
3605
0
          GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] cannot block source membership for %s: %s\n", src_ip_exc[i], gf_errno_str(LASTSOCKERROR)));
3606
0
          return GF_IP_CONNECTION_FAILURE;
3607
0
        }
3608
0
      }
3609
#else
3610
      GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[core] SSM IPv6 not supported\n"));
3611
#endif
3612
0
    }
3613
0
    sock->flags |= GF_SOCK_IS_MULTICAST | GF_SOCK_HAS_PEER;
3614
0
    return GF_OK;
3615
0
  }
3616
0
#endif
3617
3618
0
#ifndef GPAC_DISABLE_NETCAP
3619
0
  if (sock->cap_info && sock->cap_info->nf->cap_mode) {
3620
    //in GPC mode, store in host port/addr
3621
0
    if (sock->cap_info->nf->cap_mode==NETCAP_GPAC) {
3622
0
      sock->cap_info->host_port = MultiPortNumber;
3623
0
      sock->cap_info->host_addr_v4 = inet_addr(multi_IPAdd);
3624
0
    } else {
3625
0
      sock->cap_info->host_port = MultiPortNumber;
3626
0
      sock->cap_info->host_addr_v4 = inet_addr_from_name(ifce_ip_or_name ? ifce_ip_or_name : "127.0.0.1");
3627
0
      sock->cap_info->peer_port = MultiPortNumber;
3628
0
      sock->cap_info->peer_addr_v4 = inet_addr(multi_IPAdd);
3629
0
    }
3630
0
    sock->flags &= ~GF_SOCK_IS_IPV6;
3631
0
    sock->flags |= GF_SOCK_IS_MULTICAST;
3632
0
    return GF_OK;
3633
0
  }
3634
0
#endif
3635
3636
3637
  //IPv4 setup
3638
0
  sock->socket = socket(AF_INET, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
3639
0
  if (SOCKET_INVALID(sock->socket)) return GF_IP_NETWORK_FAILURE;
3640
3641
0
  if (sock->flags & GF_SOCK_NON_BLOCKING)
3642
0
    gf_sk_set_block_mode(sock, GF_TRUE);
3643
0
  sock->flags &= ~GF_SOCK_IS_IPV6;
3644
3645
  /*enable address reuse*/
3646
0
  optval = 1;
3647
0
  ret = setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, SSO_CAST &optval, sizeof(optval));
3648
0
  if (ret == SOCKET_ERROR) {
3649
0
    GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[core] Failed to set SO_REUSEADDR: %s\n", gf_errno_str(LASTSOCKERROR) ));
3650
0
  }
3651
0
#ifdef SO_REUSEPORT
3652
0
  optval = 1;
3653
0
  ret = setsockopt(sock->socket, SOL_SOCKET, SO_REUSEPORT, SSO_CAST &optval, sizeof(optval));
3654
0
  if (ret == SOCKET_ERROR) {
3655
0
    GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[core] Failed to set SO_REUSEPORT: %s\n", gf_errno_str(LASTSOCKERROR) ));
3656
0
  }
3657
0
#endif
3658
3659
0
  local_add_id = inet_addr_from_name(ifce_ip_or_name);
3660
0
  if (local_add_id==0xFFFFFFFF) return GF_IP_CONNECTION_FAILURE;
3661
3662
0
  if (!NoBind) {
3663
0
    struct sockaddr_in local_address;
3664
3665
0
    memset(&local_address, 0, sizeof(struct sockaddr_in ));
3666
0
    local_address.sin_family = AF_INET;
3667
0
    local_address.sin_addr.s_addr = htonl(INADDR_ANY);
3668
0
    local_address.sin_port = htons( MultiPortNumber);
3669
3670
0
    ret = bind(sock->socket, (struct sockaddr *) &local_address, sizeof(local_address));
3671
0
    if (ret == SOCKET_ERROR) {
3672
0
      GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[core] Failed to bind socket: %s\n", gf_errno_str(LASTSOCKERROR) ));
3673
0
      return GF_IP_CONNECTION_FAILURE;
3674
0
    }
3675
    /*setup local interface*/
3676
0
    if (ifce_ip_or_name) {
3677
0
      ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_IF, (void *) &local_add_id, sizeof(local_add_id));
3678
0
      if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
3679
0
    }
3680
0
  }
3681
3682
  /*now join the multicast*/
3683
0
  M_req.imr_multiaddr.s_addr = inet_addr(multi_IPAdd);
3684
0
  M_req.imr_interface.s_addr = local_add_id;
3685
3686
0
  e = sk_join_ipv4(sock, &M_req, TTL, src_ip_inc, nb_src_ip_inc, src_ip_exc, nb_src_ip_exc);
3687
0
  if (e) return e;
3688
3689
0
#ifdef GPAC_HAS_IPV6
3690
0
  ((struct sockaddr_in *) &sock->dest_addr)->sin_family = AF_INET;
3691
0
  ((struct sockaddr_in *) &sock->dest_addr)->sin_addr.s_addr = M_req.imr_multiaddr.s_addr;
3692
0
  ((struct sockaddr_in *) &sock->dest_addr)->sin_port = htons( MultiPortNumber);
3693
0
  sock->dest_addr_len = sizeof(struct sockaddr);
3694
#else
3695
  sock->dest_addr.sin_family = AF_INET;
3696
  sock->dest_addr.sin_addr.s_addr = M_req.imr_multiaddr.s_addr;
3697
  sock->dest_addr.sin_port = htons( MultiPortNumber);
3698
#endif
3699
3700
0
  sock->flags |= GF_SOCK_IS_MULTICAST | GF_SOCK_HAS_PEER;
3701
0
  return GF_OK;
3702
0
}
3703
3704
GF_EXPORT
3705
GF_Err gf_sk_setup_multicast(GF_Socket *sock, const char *multi_IPAdd, u16 MultiPortNumber, u32 TTL, Bool NoBind, const char *ifce_ip_or_name)
3706
0
{
3707
0
  return gf_sk_setup_multicast_ex(sock, multi_IPAdd, MultiPortNumber, TTL, NoBind, ifce_ip_or_name, NULL, 0, NULL, 0);
3708
3709
0
}
3710
3711
#include <gpac/list.h>
3712
struct __tag_sock_group
3713
{
3714
  GF_List *sockets;
3715
  fd_set rgroup, wgroup;
3716
3717
#ifdef GPAC_HAS_POLL
3718
  u32 last_mask;
3719
  u32 nb_fds, alloc_fds;
3720
  GF_POLLFD *fds;
3721
#endif
3722
3723
#ifndef GPAC_DISABLE_NETCAP
3724
  u32 nb_nfs;
3725
  u32 nb_socks;
3726
#endif
3727
};
3728
3729
GF_SockGroup *gf_sk_group_new()
3730
0
{
3731
0
  GF_SockGroup *tmp;
3732
0
  GF_SAFEALLOC(tmp, GF_SockGroup);
3733
0
  if (!tmp) return NULL;
3734
0
  FD_ZERO(&tmp->rgroup);
3735
0
  FD_ZERO(&tmp->wgroup);
3736
3737
0
#ifdef GPAC_HAS_POLL
3738
0
  tmp->last_mask = POLLIN;
3739
0
#endif
3740
0
  return tmp;
3741
0
}
3742
3743
void gf_sk_group_del(GF_SockGroup *sg)
3744
0
{
3745
0
  gf_list_del(sg->sockets);
3746
0
#ifdef GPAC_HAS_POLL
3747
0
  if (sg->fds) gf_free(sg->fds);
3748
0
#endif
3749
0
  gf_free(sg);
3750
0
}
3751
3752
void gf_sk_group_register(GF_SockGroup *sg, GF_Socket *sk)
3753
0
{
3754
0
  if (!sg || !sk) return;
3755
0
  if (!sg->sockets) sg->sockets = gf_list_new();
3756
0
  if (gf_list_find(sg->sockets, sk)>=0) return;
3757
0
  gf_list_add(sg->sockets, sk);
3758
3759
0
#ifndef GPAC_DISABLE_NETCAP
3760
0
  if (sk->cap_info) {
3761
0
    sg->nb_nfs++;
3762
0
    sg->nb_socks = gf_list_count(sg->sockets);
3763
0
    if (sk->cap_info->nf && (gf_list_find(sk->cap_info->nf->read_socks, sk)<0))
3764
0
      gf_list_add(sk->cap_info->nf->read_socks, sk);
3765
0
    return;
3766
0
  }
3767
0
#endif
3768
3769
0
#ifdef GPAC_HAS_POLL
3770
0
  if (!sg->fds && !gpac_use_poll)
3771
0
    return;
3772
3773
0
  if (sg->nb_fds + 1 > sg->alloc_fds) {
3774
0
    sg->fds = gf_realloc(sg->fds, (sg->nb_fds+1) * sizeof(GF_POLLFD));
3775
0
    sg->alloc_fds = sg->nb_fds+1;
3776
0
  }
3777
0
  sg->fds[sg->nb_fds].fd = sk->socket;
3778
0
  sg->fds[sg->nb_fds].events = sg->last_mask;
3779
0
  sg->fds[sg->nb_fds].revents = 0;
3780
0
  sk->poll_idx = sg->nb_fds+1;
3781
0
  gf_assert(! SOCKET_INVALID(sg->fds[sg->nb_fds].fd) );
3782
0
  sg->nb_fds++;
3783
0
#endif
3784
0
}
3785
3786
void gf_sk_group_unregister(GF_SockGroup *sg, GF_Socket *sk)
3787
0
{
3788
0
  if (!sg || !sk) return;
3789
0
  s32 pidx = gf_list_del_item(sg->sockets, sk);
3790
3791
0
#ifndef GPAC_DISABLE_NETCAP
3792
0
  if (sk->cap_info && sk->cap_info->nf->read_socks) {
3793
0
    if (sg->nb_nfs && (pidx>=0))
3794
0
      sg->nb_nfs--;
3795
0
    sg->nb_socks = gf_list_count(sg->sockets);
3796
3797
0
    if (sk == sk->cap_info->nf->read_sock_selected) {
3798
0
      gf_bs_skip_bytes(sk->cap_info->nf->cap_bs, sk->cap_info->nf->pck_len);
3799
0
      sk->cap_info->nf->dst_port = 0;
3800
0
      sk->cap_info->nf->read_sock_selected=NULL;
3801
      //do not load a new packet here as this could go into infinite loop when netcap-loop=-1 ...
3802
0
    }
3803
0
    gf_list_del_item(sk->cap_info->nf->read_socks, sk);
3804
0
    return;
3805
0
  }
3806
0
#endif
3807
3808
0
  if (!gf_list_count(sg->sockets)) {
3809
0
    gf_list_del(sg->sockets);
3810
0
    sg->sockets = NULL;
3811
0
#ifdef GPAC_HAS_POLL
3812
0
    if (sg->fds) {
3813
0
      gf_free(sg->fds);
3814
0
      sg->fds = NULL;
3815
0
      sg->nb_fds = sg->alloc_fds = 0;
3816
0
    }
3817
0
#endif
3818
0
    return;
3819
0
  }
3820
0
  if (pidx<0) return;
3821
3822
0
#ifdef GPAC_HAS_POLL
3823
0
  sk->poll_idx=0;
3824
0
  if (!sg->fds) return;
3825
0
  memmove(&sg->fds[pidx], &sg->fds[pidx+1], sizeof(GF_POLLFD) * (sg->nb_fds-pidx-1));
3826
  //reassign poll file descriptors and poll index
3827
0
  sg->nb_fds--;
3828
0
  while (1) {
3829
0
    GF_Socket *asock = gf_list_get(sg->sockets, pidx);
3830
0
    if (!asock) break;
3831
0
    sg->fds[pidx].fd = asock->socket;
3832
0
    asock->poll_idx = pidx+1;
3833
0
    pidx++;
3834
0
  }
3835
0
#endif
3836
0
}
3837
3838
GF_Err gf_sk_group_select(GF_SockGroup *sg, u32 usec_wait, GF_SockSelectMode mode)
3839
0
{
3840
0
  s32 ready;
3841
0
  u32 i;
3842
0
  struct timeval timeout;
3843
0
  GF_Socket *sock;
3844
3845
0
  if (!sg->sockets)
3846
0
    return GF_IP_NETWORK_EMPTY;
3847
3848
0
#ifndef GPAC_DISABLE_NETCAP
3849
0
  if (sg->nb_nfs) {
3850
0
    u32 nb_closed=0;
3851
0
    u32 nb_write=0;
3852
0
    u32 nb_nofs=0;
3853
0
    u32 nb_tcp=0;
3854
0
    u64 now = gf_sys_clock_high_res();
3855
0
    for (i=0; i<sg->nb_socks; i++) {
3856
0
      GF_Socket *s = gf_list_get(sg->sockets, i);
3857
0
      if (!s->cap_info) {
3858
0
        nb_nofs++;
3859
0
        continue;
3860
0
      }
3861
0
      if (!s->cap_info->nf->read_socks) {
3862
0
        nb_write++;
3863
0
        continue;
3864
0
      }
3865
3866
0
      gf_netcap_load_pck(s->cap_info->nf, now);
3867
0
      if (!s->cap_info->nf->read_sock_selected) {
3868
0
        if (s->cap_info->nf->is_eos) {
3869
0
          if (s->flags & GF_SOCK_IS_TCP) nb_tcp++;
3870
0
          nb_closed++;
3871
0
        }
3872
0
        continue;
3873
0
      }
3874
3875
0
      if (s->cap_info->nf->rt && (s->cap_info->nf->pck_time > now))
3876
0
        continue; // GF_IP_NETWORK_EMPTY;
3877
3878
0
      if (s == s->cap_info->nf->read_sock_selected)
3879
0
        return GF_OK;
3880
0
    }
3881
0
    if (nb_closed==sg->nb_socks) return nb_tcp ? GF_IP_CONNECTION_CLOSED : GF_EOS;
3882
0
    if (nb_write) return GF_OK;
3883
0
    if (!nb_nofs) return GF_IP_NETWORK_EMPTY;
3884
    //fallthrough
3885
0
  }
3886
0
#endif
3887
3888
0
#ifdef GPAC_HAS_POLL
3889
0
  if (sg->fds) {
3890
0
    u32 mask = 0;
3891
0
    if (mode == GF_SK_SELECT_BOTH) mask = POLLIN | POLLOUT;
3892
0
    else if (mode == GF_SK_SELECT_READ) mask = POLLIN;
3893
0
    else mask = POLLOUT;
3894
0
    if (sg->last_mask != mask) {
3895
0
      sg->last_mask = mask;
3896
0
      for (i=0; i<sg->nb_fds; i++) {
3897
0
        sg->fds[i].events = mask;
3898
0
        gf_assert(! SOCKET_INVALID(sg->fds[i].fd) );
3899
0
      }
3900
0
    }
3901
0
    int res = poll(sg->fds, sg->nb_fds, usec_wait/1000);
3902
0
    if (res<0) {
3903
0
      switch (LASTSOCKERROR) {
3904
0
      case EAGAIN:
3905
0
      case EINTR:
3906
0
        return GF_IP_NETWORK_EMPTY;
3907
0
      default:
3908
0
        GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] cannot poll: %s\n", gf_errno_str(LASTSOCKERROR) ));
3909
0
        return GF_IP_NETWORK_FAILURE;
3910
0
      }
3911
0
    }
3912
3913
0
    if (!res)
3914
0
      return GF_IP_NETWORK_EMPTY;
3915
0
    return GF_OK;
3916
0
  }
3917
0
#endif
3918
3919
0
  i=0;
3920
0
  u32 max_fd=0;
3921
0
  fd_set *rgroup=NULL, *wgroup=NULL;
3922
3923
0
  FD_ZERO(&sg->rgroup);
3924
0
  FD_ZERO(&sg->wgroup);
3925
3926
0
  switch (mode) {
3927
0
  case GF_SK_SELECT_BOTH:
3928
0
    rgroup = &sg->rgroup;
3929
0
    wgroup = &sg->wgroup;
3930
0
    break;
3931
0
  case GF_SK_SELECT_READ:
3932
0
    rgroup = &sg->rgroup;
3933
0
    break;
3934
0
  case GF_SK_SELECT_WRITE:
3935
0
    wgroup = &sg->wgroup;
3936
0
    break;
3937
0
  }
3938
0
  while ((sock = gf_list_enum(sg->sockets, &i))) {
3939
0
    if (rgroup)
3940
0
      FD_SET(sock->socket, rgroup);
3941
3942
0
    if (wgroup)
3943
0
      FD_SET(sock->socket, wgroup);
3944
3945
0
    if (max_fd < (u32) sock->socket) max_fd = (u32) sock->socket;
3946
0
  }
3947
0
  timeout.tv_sec = 0;
3948
0
  timeout.tv_usec = usec_wait;
3949
0
  ready = select((int) max_fd+1, rgroup, wgroup, NULL, &timeout);
3950
3951
0
  if (ready == SOCKET_ERROR) {
3952
0
    switch (LASTSOCKERROR) {
3953
0
    case EBADF:
3954
0
      GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] cannot select, BAD descriptor\n"));
3955
0
      return GF_IP_CONNECTION_CLOSED;
3956
0
    case EAGAIN:
3957
0
    case EINTR:
3958
0
      return GF_IP_NETWORK_EMPTY;
3959
0
    default:
3960
0
      GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] cannot select: %s\n", gf_errno_str(LASTSOCKERROR) ));
3961
0
      return GF_IP_NETWORK_FAILURE;
3962
0
    }
3963
0
  }
3964
0
  if (!ready) {
3965
0
    GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[socket] nothing to be read - ready %d\n", ready));
3966
0
    return GF_IP_NETWORK_EMPTY;
3967
0
  }
3968
0
  return GF_OK;
3969
0
}
3970
3971
Bool gf_sk_group_sock_is_set(GF_SockGroup *sg, GF_Socket *sk, GF_SockSelectMode mode)
3972
0
{
3973
0
  if (!sg || !sk) return GF_FALSE;
3974
3975
0
#ifndef GPAC_DISABLE_NETCAP
3976
0
  if (sk->cap_info) {
3977
    //write, always true
3978
0
    if (!sk->cap_info->nf->read_socks) return GF_TRUE;
3979
    //read
3980
0
    if (sk->cap_info->nf->read_sock_selected != sk) return GF_FALSE;
3981
0
    if (sk->cap_info->nf->rt && (sk->cap_info->nf->pck_time > gf_sys_clock_high_res()))
3982
0
      return GF_FALSE;
3983
3984
0
    return GF_TRUE;
3985
0
  }
3986
0
#endif
3987
3988
0
#ifdef GPAC_HAS_POLL
3989
0
  if (sg->fds && sk->poll_idx) {
3990
0
    GF_POLLFD *pfd = &sg->fds[sk->poll_idx-1];
3991
    //disconnected, consider ready to read/write
3992
0
    if (pfd->revents & POLLHUP)
3993
0
      return GF_TRUE;
3994
3995
0
    if ((mode!=GF_SK_SELECT_WRITE) && (pfd->revents & POLLIN))
3996
0
      return GF_TRUE;
3997
3998
0
    if ((mode!=GF_SK_SELECT_READ) && (pfd->revents & POLLOUT))
3999
0
      return GF_TRUE;
4000
4001
//    if (gf_sk_probe(sk) == GF_IP_CONNECTION_CLOSED)
4002
//      return GF_TRUE;
4003
0
    return GF_FALSE;
4004
0
  }
4005
0
#endif
4006
4007
0
  if ((mode!=GF_SK_SELECT_WRITE) && FD_ISSET(sk->socket, &sg->rgroup))
4008
0
    return GF_TRUE;
4009
0
  if ((mode!=GF_SK_SELECT_READ) && FD_ISSET(sk->socket, &sg->wgroup))
4010
0
    return GF_TRUE;
4011
4012
0
  return GF_FALSE;
4013
0
}
4014
4015
//fetch nb bytes on a socket and fill the buffer from startFrom
4016
//length is the allocated size of the receiving buffer
4017
//BytesRead is the number of bytes read from the network
4018
GF_Err gf_sk_receive_internal(GF_Socket *sock, char *buffer, u32 length, u32 *BytesRead, Bool do_select)
4019
0
{
4020
0
  s32 res;
4021
4022
0
  if (BytesRead) *BytesRead = 0;
4023
0
  if (!sock) return GF_BAD_PARAM;
4024
4025
0
#ifndef GPAC_DISABLE_NETCAP
4026
0
  if (sock->cap_info) {
4027
0
    if (!sock->cap_info->nf->read_socks) return GF_IP_NETWORK_EMPTY;
4028
4029
0
    GF_NetcapFilter *nf = sock->cap_info->nf;
4030
0
    if (do_select && !(sock->flags & GF_SOCK_NON_BLOCKING)) {
4031
0
      gf_netcap_load_pck(nf, gf_sys_clock_high_res() );
4032
0
      if (!nf->read_sock_selected) return nf->is_eos ? GF_IP_CONNECTION_CLOSED : GF_IP_NETWORK_EMPTY;
4033
4034
0
      if (nf->rt && (nf->pck_time > gf_sys_clock_high_res()))
4035
0
        return GF_IP_NETWORK_EMPTY;
4036
0
    }
4037
0
    if (!buffer) return GF_OK;
4038
4039
0
    if (sock!=nf->read_sock_selected) return GF_IP_NETWORK_EMPTY;
4040
0
    u32 to_read = length;
4041
0
    if ((s32) to_read > nf->pck_len) to_read = nf->pck_len;
4042
0
    u32 res = gf_bs_read_data(nf->cap_bs, buffer, to_read);
4043
0
    if (nf->read_sock_selected->cap_info->patch_offset) {
4044
0
      if (nf->read_sock_selected->cap_info->patch_offset-1<res) {
4045
0
        buffer[nf->read_sock_selected->cap_info->patch_offset-1] = nf->read_sock_selected->cap_info->patch_val;
4046
0
        nf->read_sock_selected->cap_info->patch_offset = 0;
4047
0
      } else {
4048
0
        nf->read_sock_selected->cap_info->patch_offset -= res;
4049
0
      }
4050
0
    }
4051
0
    nf->pck_len -= res;
4052
0
    if (!nf->pck_len) {
4053
0
      nf->dst_port = 0;
4054
      //do not load packet once done as this could lead to packet drop if the target socket is not yet created
4055
      //gf_netcap_load_pck(nf, 0);
4056
0
    }
4057
4058
0
    if (BytesRead)
4059
0
      *BytesRead = res;
4060
0
    if (!res) return GF_IP_NETWORK_EMPTY;
4061
0
    return GF_OK;
4062
0
  }
4063
0
#endif
4064
0
  if (SOCKET_INVALID(sock->socket)) return GF_BAD_PARAM;
4065
4066
0
  if (do_select && !(sock->flags & GF_SOCK_NON_BLOCKING)) {
4067
    //check read
4068
0
    GF_Err e = poll_select(sock, GF_SK_SELECT_READ, sock->usec_wait, GF_FALSE);
4069
0
    if (e) return e;
4070
0
  }
4071
0
  if (!buffer) return GF_OK;
4072
4073
0
  if ((sock->flags & GF_SOCK_HAS_PEER) || sock->dest_addr_len) {
4074
0
    res = (s32) recvfrom(sock->socket, (char *) buffer, length, 0, (struct sockaddr *)&sock->dest_addr, &sock->dest_addr_len);
4075
0
  } else {
4076
0
    res = (s32) recv(sock->socket, (char *) buffer, length, 0);
4077
0
  }
4078
0
  if (!do_select && (res == 0))
4079
0
    return GF_IP_CONNECTION_CLOSED;
4080
4081
0
  if (res == SOCKET_ERROR) {
4082
0
    res = LASTSOCKERROR;
4083
0
    switch (res) {
4084
0
    case EAGAIN:
4085
0
    case EINTR:
4086
0
    case ECONNREFUSED:
4087
0
      return GF_IP_NETWORK_EMPTY;
4088
4089
#if defined(WIN32) || defined(_WIN32_WCE)
4090
    //may happen if no select
4091
    case WSAEWOULDBLOCK:
4092
      return GF_IP_NETWORK_EMPTY;
4093
#endif
4094
4095
0
#ifndef __SYMBIAN32__
4096
0
    case EMSGSIZE:
4097
0
      GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] error reading: %s\n", gf_errno_str(LASTSOCKERROR)));
4098
0
      return GF_OUT_OF_MEM;
4099
0
    case ENOTCONN:
4100
0
    case ECONNRESET:
4101
0
    case ECONNABORTED:
4102
#if defined(WIN32) || defined(_WIN32_WCE)
4103
    case WSAECONNRESET:
4104
#endif
4105
      //log as debug, let higher level decide if this is an error or not
4106
0
      GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[socket] error reading: %s\n", gf_errno_str(LASTSOCKERROR)));
4107
0
      return GF_IP_CONNECTION_CLOSED;
4108
0
#endif
4109
0
    default:
4110
0
      GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] error reading: %s\n", gf_errno_str(LASTSOCKERROR) ));
4111
0
      return GF_IP_NETWORK_FAILURE;
4112
0
    }
4113
0
  }
4114
4115
0
#ifndef GPAC_DISABLE_NETCAP
4116
0
  if (netcap_filter_pck(sock, res, GF_FALSE)) {
4117
0
    res = 0;
4118
0
  } else if (sock->cap_info && sock->cap_info->patch_offset) {
4119
0
    buffer[sock->cap_info->patch_offset-1] = sock->cap_info->patch_val;
4120
0
    sock->cap_info->patch_offset = 0;
4121
0
  }
4122
0
#endif
4123
4124
0
  if (!res) return GF_IP_NETWORK_EMPTY;
4125
0
  GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[socket] read %u bytes\n", res ));
4126
4127
0
  if (BytesRead)
4128
0
    *BytesRead = res;
4129
0
  return GF_OK;
4130
0
}
4131
4132
GF_EXPORT
4133
GF_Err gf_sk_receive(GF_Socket *sock, u8 *buffer, u32 length, u32 *BytesRead)
4134
0
{
4135
0
  return gf_sk_receive_internal(sock, buffer, length, BytesRead, GF_TRUE);
4136
0
}
4137
4138
GF_EXPORT
4139
GF_Err gf_sk_receive_no_select(GF_Socket *sock, u8 *buffer, u32 length, u32 *BytesRead)
4140
0
{
4141
0
  return gf_sk_receive_internal(sock, buffer, length, BytesRead, GF_FALSE);
4142
0
}
4143
4144
GF_EXPORT
4145
GF_Err gf_sk_listen(GF_Socket *sock, u32 MaxConnection)
4146
0
{
4147
0
  s32 i;
4148
0
  if (!sock || SOCKET_INVALID(sock->socket)) return GF_BAD_PARAM;
4149
4150
0
#ifndef GPAC_DISABLE_NETCAP
4151
0
  if (sock->cap_info && sock->cap_info->nf->cap_mode) {
4152
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] Listening on socket is not supported when using network capture\n"));
4153
0
    return GF_NOT_SUPPORTED;
4154
0
  }
4155
0
#endif
4156
4157
0
  if (!MaxConnection || (MaxConnection >= SOMAXCONN)) {
4158
0
    MaxConnection = SOMAXCONN;
4159
0
  }
4160
0
  i = listen(sock->socket, MaxConnection);
4161
0
  if (i == SOCKET_ERROR)
4162
0
    return GF_IP_NETWORK_FAILURE;
4163
0
  sock->flags |= GF_SOCK_IS_LISTENING;
4164
0
  return GF_OK;
4165
0
}
4166
4167
GF_EXPORT
4168
GF_Err gf_sk_accept(GF_Socket *sock, GF_Socket **newConnection)
4169
0
{
4170
0
  u32 client_address_size;
4171
0
  SOCKET sk;
4172
0
  *newConnection = NULL;
4173
0
  if (!sock || !(sock->flags & GF_SOCK_IS_LISTENING) ) return GF_BAD_PARAM;
4174
4175
  //check read
4176
0
  GF_Err e = poll_select(sock, GF_SK_SELECT_READ, sock->usec_wait, GF_FALSE);
4177
0
  if (e) return e;
4178
4179
0
#ifdef GPAC_HAS_IPV6
4180
0
  client_address_size = sizeof(struct sockaddr_in6);
4181
#else
4182
  client_address_size = sizeof(struct sockaddr_in);
4183
#endif
4184
0
  sk = accept(sock->socket, (struct sockaddr *) &sock->dest_addr, &client_address_size);
4185
4186
  //we either have an error or we have no connections
4187
0
  if (SOCKET_INVALID(sk)) {
4188
0
    switch (LASTSOCKERROR) {
4189
0
    case EAGAIN:
4190
0
    case EINTR:
4191
0
      return GF_IP_NETWORK_EMPTY;
4192
0
    default:
4193
0
      GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] accept error: %s\n", gf_errno_str(LASTSOCKERROR)));
4194
0
      return GF_IP_NETWORK_FAILURE;
4195
0
    }
4196
0
  }
4197
4198
0
  GF_SAFEALLOC((*newConnection), GF_Socket);
4199
0
  (*newConnection)->socket = sk;
4200
0
  (*newConnection)->flags = sock->flags & ~GF_SOCK_IS_LISTENING;
4201
0
  (*newConnection)->usec_wait = sock->usec_wait;
4202
0
#ifdef GPAC_HAS_IPV6
4203
0
  memcpy( &(*newConnection)->dest_addr, &sock->dest_addr, client_address_size);
4204
0
  memset(&sock->dest_addr, 0, sizeof(struct sockaddr_in6));
4205
#else
4206
  memcpy( &(*newConnection)->dest_addr, &sock->dest_addr, client_address_size);
4207
  memset(&sock->dest_addr, 0, sizeof(struct sockaddr_in));
4208
#endif
4209
4210
#ifdef SO_NOSIGPIPE
4211
  int value = 1;
4212
  setsockopt((*newConnection)->socket, SOL_SOCKET, SO_NOSIGPIPE, SSO_CAST &value, sizeof(value));
4213
#endif
4214
4215
#if defined(WIN32) || defined(_WIN32_WCE)
4216
  wsa_init++;
4217
#endif
4218
4219
0
  (*newConnection)->dest_addr_len = client_address_size;
4220
0
  return GF_OK;
4221
0
}
4222
4223
GF_EXPORT
4224
GF_Err gf_sk_get_local_info(GF_Socket *sock, u16 *Port, u32 *Familly)
4225
0
{
4226
0
#ifdef GPAC_HAS_IPV6
4227
0
  struct sockaddr_in6 the_add;
4228
#else
4229
  struct sockaddr_in the_add;
4230
#endif
4231
0
  u32 size;
4232
4233
0
  if (!sock || SOCKET_INVALID(sock->socket)) return GF_BAD_PARAM;
4234
4235
0
  if (Port) {
4236
0
#ifdef GPAC_HAS_IPV6
4237
0
    size = sizeof(struct sockaddr_in6);
4238
0
    if (getsockname(sock->socket, (struct sockaddr *) &the_add, &size) == SOCKET_ERROR) return GF_IP_NETWORK_FAILURE;
4239
0
    *Port = (u32) ntohs(the_add.sin6_port);
4240
#else
4241
    size = sizeof(struct sockaddr_in);
4242
    if (getsockname(sock->socket, (struct sockaddr *) &the_add, &size) == SOCKET_ERROR) return GF_IP_NETWORK_FAILURE;
4243
    *Port = (u32) ntohs(the_add.sin_port);
4244
#endif
4245
0
  }
4246
0
  if (Familly) {
4247
    /*    size = 4;
4248
        if (getsockopt(sock->socket, SOL_SOCKET, SO_TYPE, (char *) &fam, &size) == SOCKET_ERROR)
4249
          return GF_IP_NETWORK_FAILURE;
4250
        *Familly = fam;
4251
    */
4252
0
    if (sock->flags & GF_SOCK_IS_TCP) *Familly = GF_SOCK_TYPE_TCP;
4253
0
    else  *Familly = GF_SOCK_TYPE_UDP;
4254
0
  }
4255
0
  return GF_OK;
4256
0
}
4257
4258
//we have to do this for the server sockets as we use only one thread
4259
GF_EXPORT
4260
GF_Err gf_sk_server_mode(GF_Socket *sock, Bool serverOn)
4261
0
{
4262
0
  u32 one;
4263
4264
0
  if (!sock || SOCKET_INVALID(sock->socket))
4265
0
    return GF_BAD_PARAM;
4266
4267
0
  if (!(sock->flags & GF_SOCK_IS_TCP)) {
4268
0
#if defined(IPV6_MTU_DISCOVER) || defined(IPV6_PMTUDISC_DO) || defined(IPV6_DONTFRAG) || defined(IP_MTU_DISCOVER) || defined(IP_DONTFRAG)
4269
0
    int val;
4270
0
#endif
4271
0
#ifdef GPAC_HAS_IPV6
4272
0
    sock->dest_addr_len = sizeof(struct sockaddr_storage);
4273
#else
4274
    sock->dest_addr_len = sizeof(struct sockaddr);
4275
#endif
4276
0
    if (sock->flags & GF_SOCK_IS_IPV6) {
4277
0
#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
4278
0
      val = IPV6_PMTUDISC_DO;
4279
0
      if (setsockopt(sock->socket, IPPROTO_IPV6, IPV6_MTU_DISCOVER, SSO_CAST &val, sizeof(val)) == -1) {
4280
0
        GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] Failed to set IPV6_MTU_DISCOVER: %s\n", gf_errno_str(LASTSOCKERROR) ));
4281
0
      }
4282
0
#endif
4283
0
#ifdef IPV6_DONTFRAG
4284
0
      val = 1;
4285
0
      if (setsockopt(sock->socket, IPPROTO_IPV6, IPV6_DONTFRAG, SSO_CAST &val, sizeof(val) ) == -1) {
4286
0
        GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] Failed to set IPV6_DONTFRAG: %s\n", gf_errno_str(LASTSOCKERROR) ));
4287
0
      }
4288
0
#endif
4289
0
    } else {
4290
0
#ifdef IP_MTU_DISCOVER
4291
0
      val = IP_PMTUDISC_DO;
4292
0
      if (setsockopt(sock->socket, IPPROTO_IP, IP_MTU_DISCOVER, SSO_CAST &val, sizeof(val)) == -1) {
4293
0
        GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] Failed to set IP_MTU_DISCOVER: %s\n", gf_errno_str(LASTSOCKERROR) ));
4294
0
        return GF_OK;
4295
0
      }
4296
0
#endif
4297
#ifdef IP_DONTFRAG
4298
      val = 1;
4299
      if (setsockopt(sock->socket, IPPROTO_IP, IP_DONTFRAG, SSO_CAST &val, sizeof(val) ) == -1) {
4300
        GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] Failed to set IP_DONTFRAG: %s\n", gf_errno_str(LASTSOCKERROR) ));
4301
      }
4302
#endif
4303
0
    }
4304
0
    return GF_OK;
4305
0
  }
4306
4307
0
  one = serverOn ? 1 : 0;
4308
0
  setsockopt(sock->socket, IPPROTO_TCP, TCP_NODELAY, SSO_CAST &one, sizeof(u32));
4309
0
#ifndef __SYMBIAN32__
4310
0
  setsockopt(sock->socket, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(u32));
4311
0
#endif
4312
0
  return GF_OK;
4313
0
}
4314
4315
GF_EXPORT
4316
GF_Err gf_sk_get_remote_address_port(GF_Socket *sock, char buf[GF_MAX_IP_NAME_LEN], u32 *port)
4317
0
{
4318
0
#ifdef GPAC_HAS_IPV6
4319
0
  char clienthost[NI_MAXHOST];
4320
0
  char servname[NI_MAXHOST];
4321
0
  struct sockaddr_in6 * addrptr = (struct sockaddr_in6 *)(&sock->dest_addr);
4322
0
  if (!sock || SOCKET_INVALID(sock->socket)) return GF_BAD_PARAM;
4323
0
  my_inet_ntop(AF_INET, addrptr, clienthost, NI_MAXHOST);
4324
0
  gf_strlcpy(buf, clienthost, GF_MAX_IP_NAME_LEN);
4325
0
  if (port) {
4326
0
    *port = ntohs(addrptr->sin6_port);
4327
0
  }
4328
0
  if (getnameinfo((struct sockaddr *)addrptr, sock->dest_addr_len, clienthost, NI_MAXHOST, servname, NI_MAXHOST, NI_NUMERICHOST) == 0) {
4329
0
    gf_strlcpy(buf, clienthost, GF_MAX_IP_NAME_LEN);
4330
0
  }
4331
#else
4332
  if (!sock || SOCKET_INVALID(sock->socket)) return GF_BAD_PARAM;
4333
  gf_strlcpy(buf, inet_ntoa(sock->dest_addr.sin_addr), GF_MAX_IP_NAME_LEN);
4334
  if (port) {
4335
    *port = ntohs(sock->dest_addr.sin_port);
4336
  }
4337
#endif
4338
0
  return GF_OK;
4339
0
}
4340
GF_EXPORT
4341
GF_Err gf_sk_get_remote_address(GF_Socket *sock, char *buf)
4342
0
{
4343
0
  return gf_sk_get_remote_address_port(sock, buf, NULL);
4344
0
}
4345
4346
const u8 *gf_sk_get_address(GF_Socket *sock, u32 *addr_size)
4347
0
{
4348
0
  if (!sock || !addr_size) return NULL;
4349
0
  *addr_size = sock->dest_addr_len;
4350
0
  return (const u8 *) &sock->dest_addr;
4351
0
}
4352
4353
4354
#if 0 //unused
4355
4356
//send length bytes of a buffer
4357
GF_Err gf_sk_send_to(GF_Socket *sock, const char *buffer, u32 length, char *remoteHost, u16 remotePort)
4358
{
4359
  u32 count, remote_add_len;
4360
  s32 res;
4361
#ifdef GPAC_HAS_IPV6
4362
  struct sockaddr_storage remote_add;
4363
#else
4364
  struct sockaddr_in remote_add;
4365
  struct hostent *Host;
4366
#endif
4367
4368
  //the socket must be bound or connected
4369
  if (!sock || SOCKET_INVALID(sock->socket)) return GF_BAD_PARAM;
4370
  if (remoteHost && !remotePort) return GF_BAD_PARAM;
4371
4372
  //check write
4373
  GF_Err e = poll_select(sock, GF_SK_SELECT_WRITE, sock->usec_wait, GF_FALSE);
4374
  if (e) return e;
4375
4376
  /*setup the address*/
4377
#ifdef GPAC_HAS_IPV6
4378
  remote_add.ss_family = AF_INET6;
4379
  //if a remote host is specified, use it. Otherwise use the default host
4380
  if (remoteHost) {
4381
    //setup the address
4382
    struct addrinfo *res = gf_sk_get_ipv6_addr(remoteHost, remotePort, AF_UNSPEC, 0, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM);
4383
    if (!res) return GF_IP_ADDRESS_NOT_FOUND;
4384
    memcpy(&remote_add, res->ai_addr, res->ai_addrlen);
4385
    remote_add_len = (u32) res->ai_addrlen;
4386
    freeaddrinfo(res);
4387
  } else {
4388
    struct sockaddr_in6 *remotePtr = (struct sockaddr_in6 *)&remote_add;
4389
    struct sockaddr_in6 * addrptr = (struct sockaddr_in6 *)(&sock->dest_addr);
4390
    remotePtr->sin6_port = addrptr->sin6_port;
4391
    remotePtr->sin6_addr = addrptr->sin6_addr;
4392
    remote_add_len = sock->dest_addr_len;
4393
  }
4394
#else
4395
  remote_add_len = sizeof(struct sockaddr_in);
4396
  remote_add.sin_family = AF_INET;
4397
  //if a remote host is specified, use it. Otherwise use the default host
4398
  if (remoteHost) {
4399
    //setup the address
4400
    remote_add.sin_port = htons(remotePort);
4401
    //get the server IP
4402
    Host = gf_gethostbyname(remoteHost);
4403
    if (Host == NULL) return GF_IP_ADDRESS_NOT_FOUND;
4404
    memcpy((char *) &remote_add.sin_addr, Host->h_addr_list[0], sizeof(u32));
4405
  } else {
4406
    remote_add.sin_port = sock->dest_addr.sin_port;
4407
    remote_add.sin_addr.s_addr = sock->dest_addr.sin_addr.s_addr;
4408
  }
4409
#endif
4410
  count = 0;
4411
  while (count < length) {
4412
    res = (s32) sendto(sock->socket, (char *) buffer+count, length - count, 0, (struct sockaddr *) &remote_add, remote_add_len);
4413
    if (res == SOCKET_ERROR) {
4414
      switch (LASTSOCKERROR) {
4415
      case EAGAIN:
4416
      case EINTR:
4417
        return GF_IP_NETWORK_EMPTY;
4418
      default:
4419
        GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] sendto error: %s\n", gf_errno_str(LASTSOCKERROR)));
4420
        return GF_IP_NETWORK_FAILURE;
4421
      }
4422
    }
4423
    count += res;
4424
  }
4425
  return GF_OK;
4426
}
4427
#endif
4428
4429
GF_EXPORT
4430
GF_Err gf_sk_probe(GF_Socket *sock)
4431
0
{
4432
0
  s32 res;
4433
0
  u8 buffer[1];
4434
0
  if (!sock) return GF_BAD_PARAM;
4435
4436
0
#ifndef GPAC_DISABLE_NETCAP
4437
0
  if (sock->cap_info && sock->cap_info->nf->read_socks && sock->cap_info->nf->is_eos) return GF_IP_CONNECTION_CLOSED;
4438
0
#endif
4439
4440
  //check read - force using select at least for windows, for which poll returns nothing on connection abort
4441
0
  GF_Err e = poll_select(sock, GF_SK_SELECT_READ, 100, GF_TRUE);
4442
0
  if (e) return e;
4443
4444
  //peek message
4445
0
  res = (s32) recv(sock->socket, buffer, 1, MSG_PEEK);
4446
0
  if (res > 0) return GF_OK;
4447
#if 0
4448
  res = LASTSOCKERROR;
4449
  switch (res) {
4450
  case 0:
4451
  case EAGAIN:
4452
  case EINTR:
4453
    return GF_IP_NETWORK_EMPTY;
4454
  default:
4455
    GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] probe error: %s\n", gf_errno_str(res)));
4456
    return GF_IP_CONNECTION_CLOSED;
4457
  }
4458
#else
4459
0
  return GF_IP_CONNECTION_CLOSED;
4460
0
#endif
4461
4462
0
  return GF_OK;
4463
0
}
4464
4465
4466
GF_EXPORT
4467
char *gf_net_bump_ip_address(const char *in_ip, u32 increment)
4468
0
{
4469
0
  if (!in_ip) return NULL;
4470
0
  if (!gf_sk_is_multicast_address(in_ip)) return NULL;
4471
0
  if (!increment) return gf_strdup(in_ip);
4472
4473
0
  u32 new_range=0;
4474
4475
0
  char *alloc_ip=NULL;
4476
0
  if (!strnicmp(in_ip, "ff", 2)) {
4477
0
    char *add_end = strstr(in_ip, "::");
4478
0
    if (!add_end) add_end = 1 + strrchr(in_ip, ':');
4479
0
    else add_end+=2;
4480
0
    char *sep2 = strrchr(add_end, '/');
4481
0
    if (sep2) sep2[0] = 0;
4482
0
    u32 inc;
4483
0
    if (!add_end[0]) {
4484
0
      inc = 0;
4485
0
      gf_dynstrcat(&alloc_ip, in_ip, NULL);
4486
0
    } else {
4487
0
      char c = add_end[0];
4488
0
      add_end[0] = 0;
4489
0
      gf_dynstrcat(&alloc_ip, in_ip, NULL);
4490
0
      add_end[0] = c;
4491
0
      inc = atoi(add_end);
4492
0
    }
4493
0
    new_range = inc + increment;
4494
0
    char val[10];
4495
0
    sprintf(val, ".%u", new_range);
4496
0
    add_end[0] = 0;
4497
0
    gf_dynstrcat(&alloc_ip, val, NULL);
4498
0
    if (sep2) {
4499
0
      sep2[0] = '/';
4500
0
      gf_dynstrcat(&alloc_ip, sep2, NULL);
4501
0
    }
4502
0
  } else {
4503
0
    char *sep = strrchr(in_ip, '.');
4504
0
    sep[0]  =0;
4505
0
    u32 inc = atoi(sep+1);
4506
0
    new_range = inc + increment;
4507
0
    char val[10];
4508
0
    sep[0] = 0;
4509
0
    gf_dynstrcat(&alloc_ip, in_ip, NULL);
4510
0
    sep[0] = '.';
4511
0
    sprintf(val, ".%u", new_range);
4512
0
    gf_dynstrcat(&alloc_ip, val, NULL);
4513
0
  }
4514
0
  if (!alloc_ip) return NULL;
4515
0
  if (new_range>0xFF) {
4516
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[IP] Dumping IP address beyond 0xFF is not supported\n"));
4517
0
    gf_free(alloc_ip);
4518
0
    return NULL;
4519
0
  }
4520
0
  return alloc_ip;
4521
0
}
4522
4523
#else
4524
//for ntoh/hton
4525
#include <arpa/inet.h>
4526
#endif //GPAC_DISABLE_NETWORK
4527
4528
GF_EXPORT
4529
GF_Err gf_net_reload_netcap()
4530
0
{
4531
0
#if !defined(GPAC_DISABLE_NETWORK) && !defined(GPAC_DISABLE_NETCAP)
4532
0
  u32 i, count = gf_list_count(netcap_filters);
4533
0
  for (i=0; i<count; i++) {
4534
0
    GF_NetcapFilter *nf = gf_list_get(netcap_filters, i);
4535
4536
0
    if (nf->cap_bs) gf_bs_del(nf->cap_bs);
4537
0
#ifdef GPAC_HAS_FD
4538
0
    if (nf->fd>=0) close(nf->fd);
4539
0
#endif
4540
0
    if (nf->file) gf_fclose(nf->file);
4541
0
    gf_list_del(nf->read_socks);
4542
0
    nf->read_socks = NULL;
4543
0
    nf->nb_reloads++;
4544
0
    nf->init_time = 0;
4545
0
    nf->is_eos = GF_FALSE;
4546
0
    nf->pck_start_offset = 0;
4547
0
    nf->pck_len = 0;
4548
0
    nf->pck_flags = 0;
4549
0
    nf->pck_time = 0;
4550
0
    nf->pcap_num_interfaces = 0;
4551
0
    nf->pcapng_trail = 0;
4552
0
    nf->pcap_trail = 0;
4553
0
    nf->pck_idx_r = 0;
4554
0
    nf->pck_idx_w = 0;
4555
0
    nf->next_pck_range = 0;
4556
0
    nf->next_rand = 0;
4557
0
    nf->reorder_max_pck = 0;
4558
0
    nf->reorder_nb_pck = 0;
4559
0
    nf->delay_nb_pck = 0;
4560
0
    nf->reorder_seek_pos = 0;
4561
0
    nf->reorder_resume_pos = 0;
4562
0
    GF_Err e = GF_OK;
4563
0
    if (nf->dst) {
4564
0
      e = gf_netcap_record(nf);
4565
0
    }
4566
0
    else if (nf->src) {
4567
0
      e = gf_netcap_playback(nf);
4568
0
    }
4569
0
    if (e) return e;
4570
0
  }
4571
0
#endif
4572
0
  return GF_OK;
4573
0
}
4574
4575
GF_EXPORT
4576
u32 gf_htonl(u32 val)
4577
0
{
4578
0
  return htonl(val);
4579
0
}
4580
4581
4582
GF_EXPORT
4583
u32 gf_ntohl(u32 val)
4584
0
{
4585
0
  return ntohl(val);
4586
0
}
4587
4588
GF_EXPORT
4589
u16 gf_htons(u16 val)
4590
0
{
4591
0
  return htons(val);
4592
0
}
4593
4594
4595
GF_EXPORT
4596
u16 gf_ntohs(u16 val)
4597
0
{
4598
0
  return ntohs(val);
4599
0
}
4600
4601
GF_EXPORT
4602
const char *gf_errno_str(int errnoval)
4603
0
{
4604
0
  return strerror(errnoval);
4605
0
}