[Sumover-dev] [svn commit] r4080 - vic/branches/mpeg4/net
sumover-dev at cs.ucl.ac.uk
sumover-dev at cs.ucl.ac.uk
Tue Jul 17 15:24:55 BST 2007
Author: piers
Date: Tue Jul 17 15:24:25 2007
New Revision: 4080
Modified:
vic/branches/mpeg4/net/net-ip.cpp
Log:
Altered operation of openssock() so that it no longer calls connect() on the
socket - instead the sockaddr structure is used by sendto() in the the newly
reimplemented dosend() method. This gets around a problem on OSX where one can
bind to multiple sockets on the same address (when using REUSERADDR) but you
can't call connect() on them.
Modified: vic/branches/mpeg4/net/net-ip.cpp
==============================================================================
--- vic/branches/mpeg4/net/net-ip.cpp (original)
+++ vic/branches/mpeg4/net/net-ip.cpp Tue Jul 17 15:24:25 2007
@@ -112,12 +112,14 @@
return (result);
}
protected:
+ struct sockaddr_in sin;
virtual int dorecv(u_char* buf, int len, Address &from, int fd);
int open(const char * host, int port, int ttl);
int close();
int localname(sockaddr_in*);
int openssock(Address & addr, u_short port, int ttl);
int openrsock(Address & g_addr, Address & s_addr_ssm, u_short port, Address & local);
+ void dosend(u_char* buf, int len, int fd);
time_t last_reset_;
};
@@ -466,7 +468,7 @@
int IPNetwork::openssock(Address & addr, u_short port, int ttl)
{
int fd;
- struct sockaddr_in sin;
+// struct sockaddr_in sin;
u_int32_t addri = (IPAddress&)addr;
@@ -484,6 +486,14 @@
perror("SO_REUSEADDR");
}
}
+#ifdef SO_REUSEPORT
+ int on = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *)&on,
+ sizeof(on)) < 0) {
+ perror("SO_REUSEPORT");
+ exit(1);
+ }
+#endif
memset((char *)&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
@@ -501,10 +511,14 @@
sin.sin_family = AF_INET;
sin.sin_port = port;
sin.sin_addr.s_addr = addri;
- if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+
+/* Got rid of connect and vic then uses sin in the sendto() function in
+ * the dosend() method
+ *
+ * if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
perror("connect");
exit(1);
- }
+ }*/
if (IN_CLASSD(ntohl(addri))) {
#ifdef IP_ADD_MEMBERSHIP
char c;
@@ -590,3 +604,71 @@
return (cc);
}
+
+void IPNetwork::dosend(u_char* buf, int len, int fd)
+{
+ int cc = ::sendto(fd, (char*)buf, len, 0, (struct sockaddr *)&sin, sizeof(sin));
+ if (cc < 0) {
+ switch (errno) {
+ case ECONNREFUSED:
+ /* no one listening at some site - ignore */
+#if defined(__osf__) || defined(_AIX)
+ /*
+ * Due to a bug in kern/uipc_socket.c, on several
+ * systems, datagram sockets incorrectly persist
+ * in an error state on receipt of an ICMP
+ * port-unreachable. This causes unicast connection
+ * rendezvous problems, and worse, multicast
+ * transmission problems because several systems
+ * incorrectly send port unreachables for
+ * multicast destinations. Our work around
+ * is to simply close and reopen the socket
+ * (by calling reset() below).
+ *
+ * This bug originated at CSRG in Berkeley
+ * and was present in the BSD Reno networking
+ * code release. It has since been fixed
+ * in 4.4BSD and OSF-3.x. It is know to remain
+ * in AIX-4.1.3.
+ *
+ * A fix is to change the following lines from
+ * kern/uipc_socket.c:
+ *
+ * if (so_serror)
+ * snderr(so->so_error);
+ *
+ * to:
+ *
+ * if (so->so_error) {
+ * error = so->so_error;
+ * so->so_error = 0;
+ * splx(s);
+ * goto release;
+ * }
+ *
+ */
+ reset();
+#endif
+ break;
+
+ case ENETUNREACH:
+ case EHOSTUNREACH:
+ /*
+ * These "errors" are totally meaningless.
+ * There is some broken host sending
+ * icmp unreachables for multicast destinations.
+ * UDP probably aborted the send because of them --
+ * try exactly once more. E.g., the send we
+ * just did cleared the errno for the previous
+ * icmp unreachable, so we should be able to
+ * send now.
+ */
+ (void)::send(ssock_, (char*)buf, len, 0);
+ break;
+
+ default:
+ /*perror("send");*/
+ return;
+ }
+ }
+}
More information about the Sumover-dev
mailing list