The Assimilation Project  based on Assimilation version 1.1.6.1462601511
netio.c
Go to the documentation of this file.
1 
25 #include <projectcommon.h>
26 #include <errno.h>
27 #include <memory.h>
28 #ifdef HAVE_UNISTD_H
29 # include <unistd.h>
30 #endif
31 #include <stdlib.h>
32 #include <fcntl.h>
33 #include <sys/types.h>
34 #ifdef _MSC_VER
35 # include <winsock2.h>
36 # include <ws2tcpip.h>
37 #include <ws2ipdef.h>
38 #define ip_mreqn ip_mreq
39 #define imr_address imr_multiaddr
40 #define s6_addr16 u.Word
41 #define close closesocket
42 #else
43 # include <sys/socket.h>
44 # include <netinet/in.h>
45 #endif
46 #include <glib.h>
47 #include <packetdecoder.h>
48 #include <address_family_numbers.h>
49 #include <proj_classes.h>
50 #include <netio.h>
51 #include <frameset.h>
52 #include <frametypes.h>
53 #include <misc.h>
54 FSTATIC gint _netio_getfd(const NetIO* self);
55 FSTATIC int _netio_getsockbufsize(const NetIO* self, gboolean forinput);
56 FSTATIC int _netio_setsockbufsize(const NetIO* self, gboolean forinput, gsize bufsize);
57 FSTATIC void _netio_maximize_sockbufsize(const NetIO* self, gboolean forinput, int desiredsize);
58 FSTATIC void _netio_setblockio(const NetIO* self, gboolean blocking);
59 FSTATIC gboolean _netio_bindaddr(NetIO* self, const NetAddr* src, gboolean silent);
60 FSTATIC gboolean _netio_bindaddr_v4(NetIO* self, const NetAddr* src, gboolean silent);
61 FSTATIC gboolean _netio_input_queued(const NetIO* self);
63 FSTATIC void _netio_sendframesets(NetIO* self, const NetAddr* destaddr, GSList* framesets);
64 FSTATIC void _netio_sendaframeset(NetIO* self, const NetAddr* destaddr, FrameSet* frameset);
65 FSTATIC void _netio_finalize(AssimObj* self);
66 FSTATIC void _netio_sendapacket(NetIO* self, gconstpointer packet, gconstpointer pktend, const NetAddr* destaddr);
67 FSTATIC void _netio_sendapacket_v4(NetIO* self, gconstpointer packet, gconstpointer pktend, const NetAddr* destaddr);
68 FSTATIC gpointer _netio_recvapacket(NetIO*, gpointer*, struct sockaddr_in6*, socklen_t*addrlen);
69 FSTATIC gsize _netio_getmaxpktsize(const NetIO* self);
70 FSTATIC gsize _netio_setmaxpktsize(NetIO* self, gsize maxpktsize);
71 FSTATIC GSList* _netio_recvframesets(NetIO*self , NetAddr** src);
74 FSTATIC gboolean _netio_mcastjoin(NetIO* self, const NetAddr* src, const NetAddr*localaddr);
75 FSTATIC gboolean _netio_setmcast_ttl(NetIO* self, guint8 ttl);
76 FSTATIC void _netio_enablepktloss(NetIO* self, gboolean enable);
77 FSTATIC void _netio_setpktloss(NetIO* self, double rcvloss, double xmitloss);
78 FSTATIC gboolean _netio_sendareliablefs(NetIO*self, NetAddr*dest, guint16 queueid, FrameSet* frameset);
79 FSTATIC gboolean _netio_sendreliablefs(NetIO*self, NetAddr* dest, guint16 queueid, GSList* fslist);
80 FSTATIC gboolean _netio_ackmessage(NetIO* self, NetAddr* dest, FrameSet* frameset);
81 FSTATIC gboolean _netio_supportsreliable(NetIO* self);
82 FSTATIC void _netio_closeconn(NetIO* self, guint16 qid, const NetAddr* destaddr);
83 FSTATIC void _netio_netaddr_destroy(gpointer addrptr);
84 FSTATIC void _netio_addalias(NetIO* self, NetAddr * fromaddr, NetAddr* toaddr);
85 
87 
94 
96 FSTATIC gint
97 _netio_getfd(const NetIO* self)
98 {
99  g_return_val_if_fail(NULL != self, -1);
100  g_return_val_if_fail(NULL != self->giosock, -1);
101  return g_io_channel_unix_get_fd(self->giosock);
102 }
103 
105 FSTATIC void
106 _netio_setblockio(const NetIO* self, gboolean blocking)
107 {
108  int chanflags = g_io_channel_get_flags(self->giosock);
109 #ifndef WIN32
110  int fcntlflags = fcntl (self->getfd(self), F_GETFL, 0);
111  if (blocking) {
112  fcntlflags |= O_NONBLOCK;
113  }else{
114  fcntlflags &= ~O_NONBLOCK;
115  }
116  if (fcntl(self->getfd(self), F_SETFL, fcntlflags) < 0) {
117  g_critical("%s.%d: fcntl(F_SETFL, 0x%x) failed: %s", __FUNCTION__, __LINE__
118  , fcntlflags, g_strerror(errno));
119  return;
120  }
121 #endif
122  if (blocking) {
123  chanflags |= G_IO_FLAG_NONBLOCK;
124  }else{
125  chanflags &= ~G_IO_FLAG_NONBLOCK;
126  }
127  g_io_channel_set_flags(self->giosock, chanflags, NULL);
128 }
129 
130 
132 FSTATIC gboolean
133 _netio_mcastjoin(NetIO* self, const NetAddr* src, const NetAddr*localaddr)
134 {
135  int rc = -1;
136  NetAddr* genlocal = NULL;
137 
138 
139  errno = 0;
140 
141  if (!src->ismcast(src)) {
142  g_warning("%s: Cannot join multicast group with non-multicast address"
143  , __FUNCTION__);
144  goto getout;
145  }
146  if (localaddr != NULL && src->_addrtype != localaddr->_addrtype) {
147  g_warning("%s: Cannot join multicast group with differing address types"
148  , __FUNCTION__);
149  goto getout;
150  }
151 
152  if (ADDR_FAMILY_IPV6 == src->_addrtype ) {
153  struct ipv6_mreq multicast_request;
154  struct sockaddr_in6 saddr;
155  saddr = src->ipv6sockaddr(src);
156  memset(&multicast_request, 0, sizeof(multicast_request));
157  memcpy(&multicast_request.ipv6mr_multiaddr, &saddr
158  , sizeof(multicast_request.ipv6mr_multiaddr));
159 
160  if (localaddr == NULL) {
161  genlocal = self->boundaddr(self);
162  localaddr = genlocal;
163  if (localaddr->addrtype(localaddr) != ADDR_FAMILY_IPV6) {
164  localaddr = NULL;
165  }
166  }
167 
168  if (localaddr != NULL) {
169  struct sockaddr_in6 laddr;
170  laddr = localaddr->ipv6sockaddr(localaddr);
171  memcpy(&multicast_request.ipv6mr_interface, &laddr.sin6_addr
172  , sizeof(multicast_request.ipv6mr_interface));
173  }
174  if (localaddr && localaddr->addrtype(localaddr) != ADDR_FAMILY_IPV6) {
175  g_warning("%s: Cannot join v6 multicast group - local address not IPv6"
176  , __FUNCTION__);
177  goto getout;
178  }
179 
180  rc = setsockopt(self->getfd(self), IPPROTO_IPV6, IPV6_JOIN_GROUP
181  , (gpointer)&multicast_request, sizeof(multicast_request));
182  if (rc != 0) {
183  g_warning("%s: Cannot join v6 multicast group [%s (errno:%d)]"
184  , __FUNCTION__, g_strerror(errno), errno);
185  }
186  }else if (ADDR_FAMILY_IPV4 == src->_addrtype) {
187  struct ip_mreqn multicast_request;
188  struct sockaddr_in saddr;
189  memset(&multicast_request, 0, sizeof(multicast_request));
190  saddr = src->ipv4sockaddr(src);
191  memcpy(&multicast_request.imr_multiaddr, &saddr.sin_addr
192  , sizeof(multicast_request.imr_multiaddr));
193 
194  if (localaddr == NULL) {
195  genlocal = self->boundaddr(self);
196  localaddr = genlocal;
197  if (localaddr->addrtype(localaddr) != ADDR_FAMILY_IPV4) {
198  localaddr = NULL;
199  }
200  }
201  if (localaddr && localaddr->addrtype(localaddr) != ADDR_FAMILY_IPV4) {
202  g_warning("%s: Cannot join v4 multicast group - local address not IPv4"
203  , __FUNCTION__);
204  goto getout;
205  }
206 
207  if (localaddr != NULL) {
208  struct sockaddr_in laddr;
209  laddr = localaddr->ipv4sockaddr(localaddr);
210  memcpy(&multicast_request.imr_address, &laddr.sin_addr
211  , sizeof(multicast_request.imr_address));
212  }
213 
214  rc = setsockopt(self->getfd(self), IPPROTO_IP, IP_ADD_MEMBERSHIP
215  , (gpointer)&multicast_request, sizeof(multicast_request));
216  if (rc != 0) {
217  g_warning("%s: Cannot join v4 multicast group [%s (errno:%d)]"
218  , __FUNCTION__, g_strerror(errno), errno);
219  }else{
220  // Default to the largest organizational scope defined...
221  self->setmcast_ttl(self, 31);
222  }
223  }
224 getout:
225  if (genlocal) {
226  UNREF(genlocal);
227  genlocal = NULL;
228  }
229 
230  return (rc == 0);
231 }
232 
234 gboolean
236  guint8 ttlin)
237 {
245  int ttl = ttlin;
246  return setsockopt(self->getfd(self), IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl) == 0);
247 }
248 
250 FSTATIC int
251 _netio_getsockbufsize(const NetIO* self, gboolean forinput)
252 {
253  int optname = (forinput ? SO_RCVBUF : SO_SNDBUF);
254  int retval;
255  socklen_t retvalsize = sizeof(retval);
256 
257  errno = 0;
258  if (getsockopt(self->getfd(self), SOL_SOCKET, optname, &retval, &retvalsize) < 0
259  || retvalsize != sizeof(retval)) {
260  g_warning("%s.%d: getsockopt(%d, IPPROTO_UDP, %d, &retval, %d) failed [%s]"
261  , __FUNCTION__, __LINE__
262  , self->getfd(self), optname, retvalsize, g_strerror(errno));
263  return -1;
264  }
265  return (gsize)retval;
266 }
269 FSTATIC int
270 _netio_setsockbufsize(const NetIO* self, gboolean forinput, gsize bufsize)
271 {
272  int optname = (forinput ? SO_RCVBUF : SO_SNDBUF);
273  int retval;
274  socklen_t retvalsize = sizeof(retval);
275 
276  retval = bufsize;
277  DEBUGMSG2("%s.%d: trying to set %sput buffer size to %d", __FUNCTION__, __LINE__
278  , (forinput ? "in" : "out"), retval);
279 
280  if (setsockopt(self->getfd(self), SOL_SOCKET, optname, &retval, retvalsize) < 0) {
281 #ifdef SO_RCVBUFFORCE
282  int forcename = (forinput ? SO_RCVBUFFORCE : SO_SNDBUFFORCE);
283 
284  if (setsockopt(self->getfd(self), SOL_SOCKET, forcename, &retval, retvalsize) >= 0) {
285  return _netio_getsockbufsize(self, forinput);
286  }
287 #endif
288  }
289  retval = _netio_getsockbufsize(self, forinput);
290  if (retval < (int)bufsize) {
291  _netio_maximize_sockbufsize(self, forinput, bufsize);
292  retval = _netio_getsockbufsize(self, forinput);
293  }
294  return retval;
295 }
296 
298 FSTATIC void
299 _netio_maximize_sockbufsize(const NetIO* self, gboolean forinput, int desiredsize)
300 {
301  int optname = (forinput ? SO_RCVBUF : SO_SNDBUF);
302  int lowval = _netio_getsockbufsize(self, forinput)/2;
303  int highval = desiredsize;
304 
305  if (lowval >= desiredsize) {
306  return;
307  }
308  // This is your basic binary search...
309  while (lowval < highval) {
310  int midpoint = (lowval + highval) / 2;
311  int retval;
312  const socklen_t retvalsize = sizeof(retval);
313  if (midpoint == lowval) {
314  break;
315  }
316  retval = midpoint;
317  DEBUGMSG2("%s.%d: trying %sput buffer size %d", __FUNCTION__, __LINE__
318  , (forinput ? "in" : "out"), retval);
319  if (setsockopt(self->getfd(self), IPPROTO_UDP, optname, &retval, retvalsize) < 0) {
320 #ifdef SO_RCVBUFFORCE
321  int forcename = (forinput ? SO_RCVBUFFORCE : SO_SNDBUFFORCE);
322  if (setsockopt(self->getfd(self), SOL_SOCKET, forcename, &retval, retvalsize) >= 0){
323  lowval = midpoint;
324  continue;
325  }
326 #endif
327  highval = midpoint;
328  }else{
329  lowval = midpoint;
330  }
331  }
332 }
333 
334 
336 FSTATIC gboolean
338 {
339  (void)self;
340  return FALSE; // By default we don't have any input queues
341 }
342 
344 FSTATIC gboolean
346  const NetAddr* src,
347  gboolean silent)
348 {
349  gint sockfd;
350  struct sockaddr_in6 saddr;
351  int rc;
352  if (self->v4only) {
353  return _netio_bindaddr_v4(self, src, silent);
354  }
355  g_return_val_if_fail(NULL != self, FALSE);
356  g_return_val_if_fail(NULL != self->giosock, FALSE);
357  sockfd = self->getfd(self);
358 
359  if (src->ismcast(src)) {
360  g_warning("%s: Attempt to bind to multicast address.", __FUNCTION__);
361  return FALSE;
362  }
363  g_return_val_if_fail(src->addrtype(src) == ADDR_FAMILY_IPV4 || src->addrtype(src) == ADDR_FAMILY_IPV6, FALSE);
364 
365  saddr = src->ipv6sockaddr(src);
366  rc = bind(sockfd, (struct sockaddr*)&saddr, sizeof(saddr));
367  if (rc != 0 && !silent) {
368  g_warning("%s: Cannot bind to address [%s (errno:%d)]"
369  , __FUNCTION__, g_strerror(errno), errno);
370  }
371  return rc == 0;
372 }
374 FSTATIC gboolean
376  const NetAddr* src,
377  gboolean silent)
378 {
379  gint sockfd;
380  struct sockaddr_in saddr;
381  int rc;
382  NetAddr* v4src;
383  g_return_val_if_fail(NULL != self, FALSE);
384  g_return_val_if_fail(NULL != self->giosock, FALSE);
385  sockfd = self->getfd(self);
386  if (src->ismcast(src)) {
387  g_warning("%s: Attempt to bind to multicast address.", __FUNCTION__);
388  return FALSE;
389  }
390  v4src = src->toIPv4(src);
391  if (NULL == v4src) {
392  char * srcstr = src->baseclass.toString(src);
393  g_warning("%s.%d: Could not convert address %s to IPv4 for IPv4-only socket."
394  , __FUNCTION__, __LINE__, srcstr);
395  FREE(srcstr);
396  return FALSE;
397  }
398  saddr = v4src->ipv4sockaddr(v4src);
399  UNREF(v4src);
400 
401  rc = bind(sockfd, (struct sockaddr*)&saddr, sizeof(saddr));
402  if (rc != 0 && !silent) {
403  g_warning("%s: Cannot bind to address for socket %d [%s (errno:%d)]"
404  , __FUNCTION__, sockfd, g_strerror(errno), errno);
405  }
406  return rc == 0;
407 }
408 
411 _netio_boundaddr(const NetIO* self)
412 {
413  gint sockfd = self->getfd(self);
414  struct sockaddr_in6 saddr;
415  socklen_t saddrlen = sizeof(saddr);
416  socklen_t retsize = saddrlen;
417 
418 
419  if (getsockname(sockfd, (struct sockaddr*)&saddr, &retsize) < 0) {
420  g_warning("%s: Cannot retrieve bound address [%s]", __FUNCTION__, g_strerror(errno));
421  return NULL;
422  }
423  if (retsize != saddrlen && (!self->v4only || retsize != sizeof(struct sockaddr_in))) {
424  g_warning("%s: Truncated getsockname() return [%d/%d bytes]", __FUNCTION__, retsize, saddrlen);
425  return NULL;
426  }
427  return netaddr_sockaddr_new(&saddr, saddrlen);
428 
429 }
430 
432 FSTATIC void
434 {
435  NetIO* self = CASTTOCLASS(NetIO, aself);
436  if (self->giosock) {
437  g_io_channel_shutdown(self->giosock, TRUE, NULL);
438  g_io_channel_unref(self->giosock);
439  self->giosock = NULL;
440  }
441  if (self->_signframe) {
442  UNREF2(self->_signframe);
443  }
444  if (self->_compressframe) {
445  UNREF2(self->_compressframe);
446  }
447  if (self->_decoder) {
448  UNREF(self->_decoder);
449  }
450 
451  // Free up our hash table of aliases
452  if (self->aliases) {
453  g_hash_table_destroy(self->aliases); // It will free the NetAddrs contained therein
454  self->aliases = NULL;
455  }
456  _assimobj_finalize(aself); self = NULL; aself = NULL;
457 }
458 
460 FSTATIC gsize
462 {
463  return self->_maxpktsize;
464 }
465 
467 FSTATIC gsize
469  gsize maxpktsize)
470 {
471  self->_maxpktsize = maxpktsize;
472  return self->getmaxpktsize(self);
473 }
476 {
477  return self->_compressframe;
478 }
479 
482 {
483  return self->_signframe;
484 }
485 
487 NetIO*
488 netio_new(gsize objsize
490  , PacketDecoder*decoder)
491 {
492  NetIO* ret;
493  Frame* f;
494 
495  BINDDEBUG(NetIO);
496  if (objsize < sizeof(NetIO)) {
497  objsize = sizeof(NetIO);
498  }
499  ret = NEWSUBCLASS(NetIO, assimobj_new(objsize));
501  ret->getfd = _netio_getfd;
504  ret->bindaddr = _netio_bindaddr;
520  ret->supportsreliable = _netio_supportsreliable; // It just returns FALSE
521  ret->outputpending = _netio_supportsreliable; // It just returns FALSE
522  ret->addalias = _netio_addalias;
526  ret->_maxpktsize = 65300;
527  ret->_configinfo = config;
528  ret->_decoder = decoder;
529  REF(decoder);
530  f = config->getframe(config, CONFIGNAME_OUTSIG);
531  g_return_val_if_fail(f != NULL, NULL);
532  REF(f);
533  ret->_signframe = CASTTOCLASS(SignFrame, f);
535  if (ret->_compressframe) {
536  REF2(ret->_compressframe);
537  }
538  ret->v4only = FALSE;
539  ret->aliases = g_hash_table_new_full(netaddr_g_hash_hash, netaddr_g_hash_equal
540  , _netio_netaddr_destroy, _netio_netaddr_destroy); // Keys and data are same type...
541  memset(&ret->stats, 0, sizeof(ret->stats));
542  return ret;
543 }
544 
546 FSTATIC void
548  gconstpointer packet,
549  gconstpointer pktend,
550  const NetAddr* destaddr)
551 {
552  struct sockaddr_in6 v6addr = destaddr->ipv6sockaddr(destaddr);
553  gssize length = (const guint8*)pktend - (const guint8*)packet;
554  gssize rc;
555  guint flags = 0x00;
556  g_return_if_fail(length > 0);
557  DUMP3(__FUNCTION__, &destaddr->baseclass, " is destination address");
558  DUMP3(__FUNCTION__, &self->baseclass, " is NetIO object");
559  if (self->v4only) {
560  return _netio_sendapacket_v4(self, packet, pktend, destaddr);
561  }
562  if (self->_shouldlosepkts) {
563  if (g_random_double() < self->_xmitloss) {
564  g_message("%s.%d: Threw away %"G_GSSIZE_FORMAT" byte output packet"
565  , __FUNCTION__, __LINE__, length);
566  return;
567  }
568  }
569 
570  rc = sendto(self->getfd(self), packet, (size_t)length, flags, (const struct sockaddr*)&v6addr, sizeof(v6addr));
571  if (rc < 0 && errno == EADDRNOTAVAIL) {
572  self->v4only = TRUE;
573  return _netio_sendapacket_v4(self, packet, pktend, destaddr);
574  }
575  DEBUGMSG3("%s.%d: sendto(%d, %ld, [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x], port=%d) returned %ld"
576  , __FUNCTION__, __LINE__, self->getfd(self), (long)length
577  , ntohs(v6addr.sin6_addr.s6_addr16[0])
578  , ntohs(v6addr.sin6_addr.s6_addr16[1])
579  , ntohs(v6addr.sin6_addr.s6_addr16[2])
580  , ntohs(v6addr.sin6_addr.s6_addr16[3])
581  , ntohs(v6addr.sin6_addr.s6_addr16[4])
582  , ntohs(v6addr.sin6_addr.s6_addr16[5])
583  , ntohs(v6addr.sin6_addr.s6_addr16[6])
584  , ntohs(v6addr.sin6_addr.s6_addr16[7])
585  , ntohs(v6addr.sin6_port)
586  , (long)rc);
587  self->stats.sendcalls ++;
588  self->stats.pktswritten ++;
589  if (rc == -1 && errno == EPERM) {
590  g_info("%s.%d: Got a weird sendto EPERM error for %"G_GSSIZE_FORMAT" byte packet."
591  , __FUNCTION__, __LINE__, (gssize)length);
592  g_info("%s.%d: This only seems to happen under Docker..."
593  , __FUNCTION__, __LINE__);
594  return;
595  }
596  if (rc != length) {
597  char * tostring = destaddr->baseclass.toString(destaddr);
598  g_warning(
599  "%s: sendto returned %"G_GSSIZE_FORMAT " vs %"G_GSSIZE_FORMAT" with errno %s"
600  , __FUNCTION__, rc, (gssize)length, g_strerror(errno));
601  g_warning("%s: destaddr:[%s] ", __FUNCTION__, tostring);
602  g_free(tostring); tostring = NULL;
603  }
604  //g_return_if_fail(rc == length);
605  g_warn_if_fail(rc == length);
606 }
607 
609 FSTATIC void
611  gconstpointer packet,
612  gconstpointer pktend,
613  const NetAddr* destaddr)
614 {
615  struct sockaddr_in v4addr = destaddr->ipv4sockaddr(destaddr);
616  gssize length = (const guint8*)pktend - (const guint8*)packet;
617  gssize rc;
618  guint flags = 0x00;
619  g_return_if_fail(length > 0);
620 
621  DUMP3(__FUNCTION__, &destaddr->baseclass, " is destination address");
622  DUMP3(__FUNCTION__, &self->baseclass, " is NetIO object");
623  if (self->_shouldlosepkts) {
624  if (g_random_double() < self->_xmitloss) {
625  g_message("%s.%d: Threw away %"G_GSSIZE_FORMAT" byte output packet"
626  , __FUNCTION__, __LINE__, length);
627  return;
628  }
629  }
630 
631  rc = sendto(self->getfd(self), packet, (size_t)length, flags, (const struct sockaddr*)&v4addr, sizeof(v4addr));
632  DEBUGMSG3("%s.%d: sendto(%d, %ld, [%08x], port=%d) returned %ld"
633  , __FUNCTION__, __LINE__, self->getfd(self), (long)length
634  , ntohs(v4addr.sin_addr.s_addr)
635  , ntohs(v4addr.sin_port)
636  , (long)rc);
637  self->stats.sendcalls ++;
638  self->stats.pktswritten ++;
639  if (rc == -1 && errno == EPERM) {
640  g_info("%s.%d: Got a weird sendto EPERM error for %"G_GSSIZE_FORMAT" byte packet."
641  , __FUNCTION__, __LINE__, (gssize)length);
642  g_info("%s.%d: This only seems to happen under Docker..."
643  , __FUNCTION__, __LINE__);
644  return;
645  }
646  if (rc != length) {
647  char * tostring = destaddr->baseclass.toString(destaddr);
648  g_warning(
649  "%s: sendto returned %"G_GSSIZE_FORMAT " vs %"G_GSSIZE_FORMAT" with errno %s"
650  , __FUNCTION__, rc, (gssize)length, g_strerror(errno));
651  g_warning("%s: destaddr:[%s] ", __FUNCTION__, tostring);
652  g_free(tostring); tostring = NULL;
653  }
654  //g_return_if_fail(rc == length);
655  g_warn_if_fail(rc == length);
656 }
657 
662 FSTATIC void
664  const NetAddr* destaddr,
665  GSList* framesets)
666 {
667  GSList* curfsl;
668  g_return_if_fail(self != NULL);
669  g_return_if_fail(framesets != NULL);
670  g_return_if_fail(destaddr != NULL);
671  g_return_if_fail(self->_signframe != NULL);
672 
676  for (curfsl=framesets; curfsl != NULL; curfsl=curfsl->next) {
677  FrameSet* curfs = CASTTOCLASS(FrameSet, curfsl->data);
678  SignFrame* signframe = self->signframe(self);
679  CryptFrame* cryptframe = NULL;
680  CompressFrame* compressframe = self->compressframe(self);
681  if (compressframe) {
682  REF2(compressframe);
683  }
684  cryptframe = cryptframe_new_by_destaddr(destaddr);
685  DEBUGMSG3("%s.%d: cryptframe: %p", __FUNCTION__, __LINE__, cryptframe);
686  frameset_construct_packet(curfs, signframe, cryptframe, compressframe);
687  if (cryptframe) {
688  DEBUGMSG3("%s.%d: Sending encrypted packet.", __FUNCTION__, __LINE__);
689  UNREF2(cryptframe);
690  }
691  DUMP3(__FUNCTION__, &curfs->baseclass, "is the frameset being sent");
692  _netio_sendapacket(self, curfs->packet, curfs->pktend, destaddr);
693  self->stats.fswritten++;
694  }
695 }
696 FSTATIC void
698  const NetAddr* destaddr,
699  FrameSet* frameset)
700 {
701  SignFrame* signframe = self->signframe(self);
702  CryptFrame* cryptframe;
703  CompressFrame* compressframe = self->compressframe(self);
704  g_return_if_fail(self != NULL);
705  g_return_if_fail(self->_signframe != NULL);
706  g_return_if_fail(frameset != NULL);
707  g_return_if_fail(destaddr != NULL);
708 
709  cryptframe = cryptframe_new_by_destaddr(destaddr);
710  DEBUGMSG3("%s.%d: cryptframe: %p", __FUNCTION__, __LINE__, cryptframe);
711  frameset_construct_packet(frameset, signframe, cryptframe, compressframe);
712  DEBUGMSG3("%s.%d: packet constructed (marshalled)", __FUNCTION__, __LINE__);
713  if (cryptframe) {
714  DEBUGMSG3("%s.%d: Sending encrypted packet.", __FUNCTION__, __LINE__);
715  UNREF2(cryptframe);
716  }
717  DEBUGMSG3("%s.%d: sending %ld byte packet", __FUNCTION__, __LINE__
718  , (long)(((guint8*)frameset->pktend-(guint8*)frameset->packet)));
719  DUMP3(__FUNCTION__, &frameset->baseclass, "is the frameset being sent");
720  _netio_sendapacket(self, frameset->packet, frameset->pktend, destaddr);
721 }
722 
730 #include <stdlib.h>
731 #include <memory.h>
732 FSTATIC gpointer
734  gpointer* pktend,
735  struct sockaddr_in6* srcaddr,
736  socklen_t* addrlen)
737 {
738  char dummy[8]; // Make GCC stack protection happy...
739 #ifndef __FUNCTION__
740 # define __FUNCTION__ "_netio_recvapacket"
741 #endif
742  gssize msglen;
743  gssize msglen2;
744  guint8* msgbuf;
745  const guint8 v4any[16] = CONST_IPV6_IPV4START;
746 
747  // First we peek and see how long the message is...
748  *addrlen = sizeof(*srcaddr);
749  memset(srcaddr, 0, sizeof(*srcaddr));
750  msglen = recvfrom(self->getfd(self), dummy, 1, MSG_DONTWAIT|MSG_PEEK|MSG_TRUNC,
751  (struct sockaddr*)srcaddr, addrlen);
752  self->stats.recvcalls ++;
753  if (msglen < 0) {
754  if (errno != EAGAIN) {
755  g_warning("recvfrom(%d, ... MSG_PEEK) failed: %s (in %s:%s:%d)",
756  self->getfd(self), g_strerror(errno), __FILE__, __FUNCTION__, __LINE__);
757  }
758  return NULL;
759  }
760  if (msglen == 0) {
761  g_warning("recvfrom(%d, ... MSG_PEEK) returned zero: %s (in %s:%s:%d)"
762  , self->getfd(self), g_strerror(errno), __FILE__, __FUNCTION__, __LINE__);
763  return NULL;
764  }
765 
766  // Allocate the right amount of memory
767  msgbuf = MALLOC(msglen);
768 
769  // Receive the message
770  *addrlen = sizeof(*srcaddr);
771  msglen2 = recvfrom(self->getfd(self), msgbuf, msglen, MSG_DONTWAIT|MSG_TRUNC,
772  (struct sockaddr *)srcaddr, addrlen);
773  self->stats.recvcalls ++;
774 
775  // Was there an error?
776  if (msglen2 < 0) {
777  g_warning("recvfrom(%d, ... MSG_DONTWAIT) failed: %s (in %s:%s:%d)"
778  , self->getfd(self), g_strerror(errno), __FILE__, __FUNCTION__, __LINE__);
779  FREE(msgbuf); msgbuf = NULL;
780  return NULL;
781  }
782  // Does everything look good?
783  if (msglen2 != msglen) {
784  g_warning("recvfrom(%d, ... MSG_DONTWAIT) returned %"G_GSSIZE_FORMAT" instead of %"G_GSSIZE_FORMAT" (in %s:%s:%d)"
785  , self->getfd(self), msglen2, msglen, __FILE__, __FUNCTION__ , __LINE__);
786  FREE(msgbuf); msgbuf = NULL;
787  return NULL;
788  }
789 
790 #ifdef WIN32
791 #define __in6_u u
792 #define __u6_addr8 Byte
793 #endif
794 
795  if (memcmp(srcaddr->sin6_addr.__in6_u.__u6_addr8, v4any, sizeof(v4any)) == 0) {
796  //const guint8 localhost[16] = CONST_IPV6_LOOPBACK;
797  const guint8 localhost[16] = {CONST_IPV6_IPV4SPACE, 127, 0, 0, 1};
798  // Both experience and RFC5735 say that this is basically "localhost"
799  memcpy(srcaddr->sin6_addr.__in6_u.__u6_addr8, localhost, sizeof(localhost));
800  }
801 
802  // Hah! Looks good!
803  *pktend = (void*) (msgbuf + msglen);
804  DEBUGMSG3("%s.%d: Received %zd byte message", __FUNCTION__, __LINE__, msglen);
805  if (self->_shouldlosepkts) {
806  if (g_random_double() < self->_rcvloss) {
807  g_message("%s: Threw away %"G_GSSIZE_FORMAT" byte input packet"
808  , __FUNCTION__, msglen);
809  FREE(msgbuf);
810  msgbuf = NULL;
811  }
812  }
813  self->stats.pktsread ++;
814  return msgbuf;
815 }
817 FSTATIC GSList*
819  NetAddr** src)
821 {
822  GSList* ret = NULL;
823  gpointer pkt;
824  gpointer pktend;
825  socklen_t addrlen;
826  struct sockaddr_in6 srcaddr;
827 
828  *src = NULL; // Make python happy in case we fail...
829  pkt = _netio_recvapacket(self, &pktend, &srcaddr, &addrlen);
830 
831  if (NULL != pkt) {
832  ret = self->_decoder->pktdata_to_framesetlist(self->_decoder, pkt, pktend);
833  if (NULL != ret) {
834  NetAddr* aliasaddr;
835  *src = netaddr_sockaddr_new(&srcaddr, addrlen);
836  // Some addresses can confuse our clients -- let's check our alias table...
837  if (NULL != (aliasaddr = g_hash_table_lookup(self->aliases, *src))) {
838  // This is a good-enough way to make a copy.
839  NetAddr* aliascopy = aliasaddr->toIPv6(aliasaddr);
840  // Keep the incoming port - since that's always right...
841  aliascopy->_addrport = (*src)->_addrport;
842  UNREF(*src);
843  *src = aliascopy;
844  }
845  if (DEBUG >= 3) {
846  char * srcstr = (*src)->baseclass.toString(&(*src)->baseclass);
847  DEBUGMSG("%s.%d: Received %d bytes making %d FrameSets from %s"
848  , __FUNCTION__, __LINE__, (int)((guint8*)pktend-(guint8*)pkt)
849  , g_slist_length(ret), srcstr);
850  FREE(srcstr); srcstr = NULL;
851  }
852  }else{
853  NetAddr* badsrc = netaddr_sockaddr_new(&srcaddr, addrlen);
854  char* srcstr = badsrc->baseclass.toString(badsrc);
855  g_warning("%s.%d: Received a %lu byte packet from %s that didn't make any FrameSets"
856  , __FUNCTION__, __LINE__, (unsigned long)((guint8*)pktend-(guint8*)pkt)
857  , srcstr);
858  FREE(srcstr);
859  UNREF(badsrc);
860  goto badret;
861  }
862  FREE(pkt);
863  }
864  if (ret && *src) {
865  self->stats.fsreads += g_slist_length(ret);
866  }
867  return ret;
868 badret:
870  ret = NULL;
871  return ret;
872 }
874 FSTATIC void
875 _netio_setpktloss (NetIO* self, double rcvloss, double xmitloss)
876 {
877  self->_rcvloss = rcvloss;
878  self->_xmitloss = xmitloss;
879 }
880 
882 FSTATIC void
883 _netio_enablepktloss (NetIO* self, gboolean enable)
884 {
885  self->_shouldlosepkts = enable;
886 }
887 
888 
889 
890 #ifdef IPV6_V6ONLY
891 #ifndef _MSC_VER
892 # include <netdb.h>
893 #endif
894 
898 gboolean
900 {
901  static gboolean computed_yet = FALSE;
902  static gboolean retval = FALSE;
903  gboolean optval;
904  int sockfd;
905  socklen_t optlen;
906  struct protoent*proto;
907 
908  if (computed_yet) {
909  return retval;
910  }
911  proto = getprotobyname("ipv6");
912 #ifdef HAVE_ENDPROTOENT
913  endprotoent();
914 #endif
915  g_return_val_if_fail(proto != NULL, FALSE);
916 
917  sockfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
918  g_return_val_if_fail(sockfd >= 0, FALSE);
919 
920  optlen = sizeof(retval);
921  optval = TRUE;
922  if (getsockopt(sockfd, proto->p_proto, IPV6_V6ONLY, (char *)&optval, &optlen) < 0) {
923  g_warning("%s.%d: getsockopt failed: %s", __FUNCTION__, __LINE__
924  , g_strerror(errno));
925  close(sockfd);
926  return FALSE;
927  }
928  if (optlen != sizeof(retval)) {
929  // Should never happen...
930  g_warning("%s.%d: getsockopt returned incorrect optlen: %d vs %zd"
931  , __FUNCTION__, __LINE__, optlen, sizeof(retval));
932  close(sockfd);
933  return FALSE;
934  }
935 #ifdef WIN32
936  // See http://msdn.microsoft.com/en-us/library/windows/desktop/bb513665%28v=vs.85%29.aspx
937  // This might be OK for other OSes too...
938  if (optval) {
939  optval = FALSE;
940  if (setsockopt(sockfd, proto->p_proto, IPV6_V6ONLY, (char *)&optval, optlen) < 0) {
943  optval = TRUE;
944  }
945  }
946 #endif
947  close(sockfd);
948  computed_yet = TRUE;
949  retval = !optval;
950  return retval;
951 }
952 #else /* IPV6_V6ONLY */
953 gboolean
955 {
956  return FALSE;
957 }
958 #endif
959 FSTATIC gboolean
960 _netio_sendareliablefs(NetIO*self, NetAddr*dest, guint16 queueid, FrameSet* frameset)
961 {
962  (void)self; (void)dest; (void)queueid; (void)frameset;
963  g_warn_if_reached();
964  return FALSE;
965 }
966 FSTATIC gboolean
967 _netio_sendreliablefs(NetIO*self, NetAddr* dest, guint16 queueid, GSList* fslist)
968 {
969  (void)self; (void)dest; (void)queueid; (void)fslist;
970  g_warn_if_reached();
971  return FALSE;
972 }
973 FSTATIC gboolean
975 {
976  (void)self; (void)dest; (void)frameset;
977  g_warning("%s.%d: Object does not support ACKing of messages", __FUNCTION__, __LINE__);
978  return FALSE;
979 }
980 FSTATIC gboolean
982 {
983  (void)self;
984  return FALSE;
985 }
986 FSTATIC void
987  _netio_closeconn(NetIO* self, guint16 qid, const NetAddr* destaddr)
988 {
989  (void)self; (void)destaddr; (void)qid;
990  return;
991 }
993 FSTATIC void
994 _netio_netaddr_destroy(gpointer addrptr)
995 {
996  NetAddr* self = CASTTOCLASS(NetAddr, addrptr);
997  UNREF(self);
998 }
999 
1001 FSTATIC void
1003 , NetAddr * fromaddr
1004 , NetAddr* toaddr)
1005 {
1006  DUMP3("Aliasing from this address", &fromaddr->baseclass, " to the next address");
1007  DUMP3("Aliasing to this address", &toaddr->baseclass, " from the previous address");
1008  REF(fromaddr);
1009  REF(toaddr);
1010  g_hash_table_insert(self->aliases, fromaddr, toaddr);
1011 }
1012 
int setsockbufsize(const NetIO *self, gboolean forinput, gsize bufsize)
< Set socket buffer size - return new size or -1
void _assimobj_finalize(AssimObj *self)
Definition: assimobj.c:61
void setblockio(const NetIO *self, gboolean blocking)
< Set blocking/non-blocking mode
AssimObj baseclass
Definition: frameset.h:47
NetAddr *(* boundaddr)(const NetIO *self)
[in] Object to return bound address/port of
Definition: netio.h:79
IETF/IANA Address family assignments.
Frame *(* getframe)(const ConfigContext *, const char *)
Get Frame value.
Definition: configcontext.h:90
gboolean v4only
True if giosock is an IPv4 socket.
Definition: netio.h:62
Defines miscellaneous interfaces.
NetAddr * destaddr
Definition: nanomain.c:75
gboolean sendreliablefs(NetIO *self, NetAddr *dest, guint16 queueid, GSList *fslist)
< Reliably send multiple FrameSets (if possible)
#define REF2(obj)
Definition: assimobj.h:40
FSTATIC GSList * _netio_recvframesets(NetIO *self, NetAddr **src)
Member function to receive a collection of FrameSets (GSList*) out of our NetIO object.
Definition: netio.c:818
gboolean outputpending(NetIO *self)
< return TRUE if this object has output pending
FSTATIC void _netio_addalias(NetIO *self, NetAddr *fromaddr, NetAddr *toaddr)
Add an alias to our alias table.
Definition: netio.c:1002
void setpktloss(NetIO *self, double rcv, double xmit)
< Set desired fraction of packet loss - TESTING ONLY!
FSTATIC void _netio_finalize(AssimObj *self)
Member function to free this NetIO object.
Definition: netio.c:433
#define DEBUGMSG(...)
Definition: proj_classes.h:87
FSTATIC void _netio_maximize_sockbufsize(const NetIO *self, gboolean forinput, int desiredsize)
Maximize the socket buffer size as requested - as best we can...
Definition: netio.c:299
Implements minimal client-oriented Frame and Frameset capabilities.
This is the base Frame class object (in-memory TLV (type, length, value)) for every general component...
Definition: frame.h:43
FSTATIC gboolean _netio_setmcast_ttl(NetIO *self, guint8 ttl)
Set up the multicast TTL for this NetIO object.
Definition: netio.c:235
#define CONFIGNAME_OUTSIG
SignFrame to use to sign/verify packets.
FSTATIC gboolean _netio_supportsreliable(NetIO *self)
Definition: netio.c:981
gboolean ackmessage(NetIO *self, NetAddr *dest, FrameSet *frameset)
< User-level ACK of a message sent reliably
FSTATIC gpointer _netio_recvapacket(NetIO *, gpointer *, struct sockaddr_in6 *, socklen_t *addrlen)
Internal function to receive a packet from our NetIO object General method:
Definition: netio.c:733
gboolean input_queued(const NetIO *self)
<[in] TRUE if input is queued ready to be read
void(* addalias)(NetIO *, NetAddr *, NetAddr *)
Add an alias to our received address alias table.
Definition: netio.h:88
AssimObj baseclass
Definition: netaddr.h:44
guint16 _addrport
private: Address port (if applicable)
Definition: netaddr.h:62
FSTATIC gsize _netio_getmaxpktsize(const NetIO *self)
Get the max packet size for this NetIO transport.
Definition: netio.c:461
gboolean bindaddr(NetIO *self, const NetAddr *, gboolean silent)
<[in] Bind this NetIO to the given address
The SignFrame class object - implements digital signatures for FrameSets.
Definition: signframe.h:47
NetAddr *(* toIPv6)(const NetAddr *)
Convert this NetAddr to the IPv6 equivalent.
Definition: netaddr.h:56
NetAddr *(* toIPv4)(const NetAddr *)
Convert this NetAddr to the IPv4 equivalent if possible It always returns a new object.
Definition: netaddr.h:57
gpointer pktend
Last byte past the end of the packet.
Definition: frameset.h:51
struct sockaddr_in(* ipv4sockaddr)(const NetAddr *self)
Return the ipv4 sockaddr corresponding to this address.
Definition: netaddr.h:52
#define FSTATIC
Definition: projectcommon.h:31
#define DEBUGMSG3(...)
Definition: proj_classes.h:91
NetAddr * netaddr_sockaddr_new(const struct sockaddr_in6 *sa_in6, socklen_t length)
Create new NetAddr from a struct sockaddr
Definition: netaddr.c:1104
Defines an abstract Network I/O class.
FSTATIC gboolean _netio_ackmessage(NetIO *self, NetAddr *dest, FrameSet *frameset)
Definition: netio.c:974
guint16(* addrtype)(const NetAddr *self)
Return IANA Address Family Numbers address type.
Definition: netaddr.h:47
FSTATIC void _netio_sendaframeset(NetIO *self, const NetAddr *destaddr, FrameSet *frameset)
Definition: netio.c:697
ConfigContext * _configinfo
I/O and other configuration information.
Definition: netio.h:64
WINEXPORT CryptFrame * cryptframe_new_by_destaddr(const NetAddr *destaddr)
Construct a CryptFrame class appropriate for encrypting messages to destaddr
Definition: cryptframe.c:488
#define BINDDEBUG(Cclass)
BINDDEBUG is for telling the class system where the debug variable for this class is - put it in the ...
Definition: proj_classes.h:82
void closeconn(NetIO *self, guint16 qid, const NetAddr *destaddr)
< Flush packets in queues to this address
CompressFrame * _compressframe
Compression frame to use in compressing FrameSets.
Definition: netio.h:67
AssimObj baseclass
Definition: netio.h:59
#define DEBUG
Definition: proj_classes.h:85
This is our CompressFrame class object - used for representing a compression method.
Definition: compressframe.h:41
WINEXPORT void assim_g_notify_unref(gpointer assimobj)
Unref for glib notify.
Definition: misc.c:753
FSTATIC void _netio_sendframesets(NetIO *self, const NetAddr *destaddr, GSList *framesets)
NetIO member function to send a GSList of FrameSets.
Definition: netio.c:663
#define DUMP3(prefix, obj, suffix)
Definition: proj_classes.h:97
FSTATIC NetAddr * _netio_boundaddr(const NetIO *self)
Member function to return the bound NetAddr (with port) of this NetIO object.
Definition: netio.c:411
GHashTable * aliases
IP address aliases for received packets.
Definition: netio.h:68
FSTATIC gboolean _netio_bindaddr(NetIO *self, const NetAddr *src, gboolean silent)
Member function to bind this NewIO object to a NetAddr address.
Definition: netio.c:345
FSTATIC void _netio_sendapacket_v4(NetIO *self, gconstpointer packet, gconstpointer pktend, const NetAddr *destaddr)
NetIO internal function to send a packet (datagram)
Definition: netio.c:610
gboolean netio_is_dual_ipv4v6_stack(void)
Definition: netio.c:954
void sendaframeset(NetIO *self, const NetAddr *dest, FrameSet *frameset)
< Send a FrameSet list to a NetIO class
#define FREE(m)
Our interface to free.
Definition: projectcommon.h:29
#define REF(obj)
Definition: assimobj.h:39
FSTATIC void _netio_netaddr_destroy(gpointer addrptr)
g_hash_table destructor for a NetAddr
Definition: netio.c:994
gint getfd(const NetIO *self)
< Return file/socket descriptor
FSTATIC gint _netio_getfd(const NetIO *self)
Member function to return the file descriptor underlying this NetIO object.
Definition: netio.c:97
gpointer packet
Pointer to packet (when constructed)
Definition: frameset.h:50
const char * localaddr
Definition: nanomain.c:68
NetIOstats stats
Net I/O stats.
Definition: netio.h:60
FSTATIC void _netio_enablepktloss(NetIO *self, gboolean enable)
Enable (or disable) packet loss as requested.
Definition: netio.c:883
WINEXPORT gboolean netaddr_g_hash_equal(gconstpointer lhs, gconstpointer rhs)
g_hash_table equal comparator for a NetAddr
Definition: netaddr.c:426
gchar *(* toString)(gconstpointer)
Produce malloc-ed string representation.
Definition: assimobj.h:58
#define ADDR_FAMILY_IPV6
IPv6.
CompressFrame * compressframe(NetIO *self)
< return a copied compression frame for sending
Project common header file.
Header file defining the data layouts for our Frames.
gboolean(* ismcast)(const NetAddr *self)
Return TRUE if this address is a multicast address.
Definition: netaddr.h:48
#define CONST_IPV6_IPV4SPACE
Definition: netaddr.h:79
FSTATIC gboolean _netio_sendareliablefs(NetIO *self, NetAddr *dest, guint16 queueid, FrameSet *frameset)
Definition: netio.c:960
FSTATIC gboolean _netio_mcastjoin(NetIO *self, const NetAddr *src, const NetAddr *localaddr)
Set up a NetIO object to listen to (join) a particular multicast group.
Definition: netio.c:133
#define CONFIGNAME_COMPRESS
Frame to use for compressing/decompressing.
SignFrame * _signframe
Signature frame to use in signing FrameSets.
Definition: netio.h:66
FSTATIC SignFrame * _netio_signframe(NetIO *self)
Definition: netio.c:481
AssimObj * assimobj_new(guint objsize)
Definition: assimobj.c:74
gboolean sendareliablefs(NetIO *self, NetAddr *dest, guint16 queueid, FrameSet *frameset)
[out] source address of return result
void enablepktloss(NetIO *self, gboolean enable)
< enable packet loss (as set above)
int getsockbufsize(const NetIO *self, gboolean forinput)
< Return socket buffer size: -1 on failure
FSTATIC CompressFrame * _netio_compressframe(NetIO *self)
Definition: netio.c:475
PacketDecoder * _decoder
Decodes packets into FrameSets.
Definition: netio.h:65
The NetAddr class class represents a general network address - whether IP, MAC, or any other type of ...
Definition: netaddr.h:43
FSTATIC void _netio_setblockio(const NetIO *self, gboolean blocking)
Member function to set blocking/non-blocking mode on our sockets.
Definition: netio.c:106
gsize setmaxpktsize(NetIO *, gsize)
< Set maximum packet size
#define g_slist_free_full
Definition: projectcommon.h:73
#define MALLOC(nbytes)
should it just call g_malloc?
Definition: projectcommon.h:26
#define g_info(...)
Definition: projectcommon.h:66
Defines interfaces a project Class system for class hierarchies in 'C'.
FSTATIC gboolean _netio_input_queued(const NetIO *self)
Member function that returns TRUE if input is ready to be read.
Definition: netio.c:337
void frameset_construct_packet(FrameSet *fs, SignFrame *sigframe, CryptFrame *cryptframe, CompressFrame *compressframe)
Construct packet to go correspond to this frameset.
Definition: frameset.c:159
FSTATIC void _netio_setpktloss(NetIO *self, double rcvloss, double xmitloss)
Set the desired level of packet loss - doesn't take effect from this call alone.
Definition: netio.c:875
FrameSet class - used for collecting Frames when not on the wire, and for marshalling/demarshalling t...
Definition: frameset.h:46
FSTATIC gsize _netio_setmaxpktsize(NetIO *self, gsize maxpktsize)
Set the max packet size for this NetIO transport.
Definition: netio.c:468
#define CONST_IPV6_IPV4START
Definition: netaddr.h:80
gboolean supportsreliable(NetIO *self)
< return TRUE if this object supports reliable transport
NetIO * netio_new(gsize objsize, ConfigContext *config, PacketDecoder *decoder)
NetIO constructor.
Definition: netio.c:488
WINEXPORT guint netaddr_g_hash_hash(gconstpointer addrptr)
g_hash_table hash function for a NetAddr
Definition: netaddr.c:435
GSList * recvframesets(NetIO *, NetAddr **src)
< Receive a single datagram's framesets
#define __FUNCTION__
struct _NetIO NetIO
Definition: netio.h:53
gint _maxpktsize
Maximum packet size for this transport.
Definition: netio.h:63
#define DEBUGDECLARATIONS
Definition: proj_classes.h:79
gsize getmaxpktsize(const NetIO *self)
< Return maximum packet size for this NetIO
#define DEBUGMSG2(...)
Definition: proj_classes.h:90
This is our CryptFrame class object - representing an encryption method.
Definition: cryptframe.h:53
void(* _finalize)(AssimObj *)
Free object (private)
Definition: assimobj.h:55
guint16 _addrtype
private: Address type
Definition: netaddr.h:60
FSTATIC gboolean _netio_bindaddr_v4(NetIO *self, const NetAddr *src, gboolean silent)
Member function to bind this NewIO object to an IPv4 NetAddr address.
Definition: netio.c:375
FSTATIC void _netio_sendapacket(NetIO *self, gconstpointer packet, gconstpointer pktend, const NetAddr *destaddr)
NetIO internal function to send a packet (datagram)
Definition: netio.c:547
#define ADDR_FAMILY_IPV4
IPv4.
FSTATIC void _netio_closeconn(NetIO *self, guint16 qid, const NetAddr *destaddr)
Definition: netio.c:987
gboolean mcastjoin(NetIO *self, const NetAddr *, const NetAddr *)
This file defines a few functions and interfaces for unmarshalling packet data into FrameSets...
SignFrame * signframe(NetIO *self)
< return a copied SignFrame for use in sending
#define UNREF2(obj)
Definition: assimobj.h:36
#define CASTTOCLASS(Cclass, obj)
Safely cast 'obj' to C-class 'class' - verifying that it was registerd as being of type class ...
Definition: proj_classes.h:66
#define UNREF(obj)
Definition: assimobj.h:35
This is a basic NetIO class abstract class for doing network I/O.
Definition: netio.h:58
FSTATIC int _netio_getsockbufsize(const NetIO *self, gboolean forinput)
Return the kernel's idea of what our input or output socket buffer size is.
Definition: netio.c:251
FSTATIC gboolean _netio_sendreliablefs(NetIO *self, NetAddr *dest, guint16 queueid, GSList *fslist)
Definition: netio.c:967
#define NEWSUBCLASS(Cclass, obj)
Definition: proj_classes.h:67
struct sockaddr_in6(* ipv6sockaddr)(const NetAddr *self)
Return the ipv6 sockaddr corresponding to this address.
Definition: netaddr.h:51
gboolean setmcast_ttl(NetIO *self, guint8 ttl)
< Set ipv4 multicast TTL
void sendframesets(NetIO *self, const NetAddr *dest, GSList *framesets)
< Send a FrameSet list to a NetIO class
FSTATIC int _netio_setsockbufsize(const NetIO *self, gboolean forinput, gsize bufsize)
Set the kernel's idea of what our input or output socket buffer size as close as we can We'll even do...
Definition: netio.c:270