[Sumover-dev] [svn commit] r4704 - vic/branches/cc/net

sumover-dev at cs.ucl.ac.uk sumover-dev at cs.ucl.ac.uk
Sun Mar 21 23:54:07 GMT 2010


Author: soohyunc
Date: Sun Mar 21 23:54:07 2010
New Revision: 4704

Modified:
   vic/branches/cc/net/net-ip.cpp

Log:
This commit reflects Revision 4699 from the mpeg4 branch.

copied comments follows:
Fixed bug when trying to send in unicast and hopefully on Win7 too. In my
connect/disconnect() fix I also 'cleaned' up the sockaddr declarations (sin) -
This was an error as the sin structure was being used by ::sendto() in dosend()
- and relying on it being setup in ssock(). I renamed the sin member variable to
  sin_ (and anotheri(local_preset) so the member variables are '_' postfixed -
good idea in general), and added local declarations of sin as and where needed.




Modified: vic/branches/cc/net/net-ip.cpp
==============================================================================
--- vic/branches/cc/net/net-ip.cpp	(original)
+++ vic/branches/cc/net/net-ip.cpp	Sun Mar 21 23:54:07 2010
@@ -97,7 +97,7 @@
 
 class IPNetwork : public Network {
     public:
-		IPNetwork() : Network(*(new IPAddress), *(new IPAddress), *(new IPAddress)) {;}
+		IPNetwork() : Network(*(new IPAddress), *(new IPAddress), *(new IPAddress)), local_preset_(0) {;}
 	virtual int command(int argc, const char*const* argv);
 	virtual void reset();
 	virtual Address* alloc(const char* name) { 
@@ -113,15 +113,17 @@
   	}
 	u_int8_t recv_tos() { return recv_tos_;}
     protected:
-	struct sockaddr_in sin;
+	struct sockaddr_in sin_; // sockaddr setup in ssock, used by sendto in dosend
+	time_t last_reset_;
+	int local_preset_; // indicates if local_ has been set on cmd line
 	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 disconnect_sock(int fd);
 	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_;
 	u_int8_t recv_tos_;
 };
 
@@ -209,8 +211,10 @@
 		if (strcmp(argv[1], "open") == 0) {
 			int port = htons(atoi(argv[3]));
 			int ttl = atoi(argv[4]);
-			if (strlen(tcl.attr("ifAddr"))>1)
+			if (strlen(tcl.attr("ifAddr"))>1) {
 				(IPAddress&)local_ = tcl.attr("ifAddr");
+				local_preset_ = 1;
+			}
 			if (open(argv[2], port, ttl) < 0)
 				tcl.result("0");
 			else
@@ -253,9 +257,18 @@
 	 */
 	sockaddr_in local;
 	if (localname(&local) < 0) {
-		return (-1);
-	}
-	(IPAddress&)local_ = local.sin_addr;
+#ifdef WIN32
+		(IPAddress&)local_ = find_win32_interface(g_addr_, ttl);
+		debug_msg("find_win32_interface localname:%s\n",(const char*)local_);
+#endif
+		if (local.sin_addr.s_addr == 0) {
+			(IPAddress&)local_ = "127.0.0.1";
+			printf("Can NOT determine local IP address - using loopback address. If you want to be able to receive packets from other machines add this command line option: -i local_ip_addr \n");
+		}
+	} else
+		(IPAddress&)local_ = local.sin_addr;
+
+	disconnect_sock(ssock_);
 	rsock_ = openrsock(g_addr_, s_addr_ssm_, port, local_);
 	if (rsock_ < 0) {
 		rsock_ = ssock_;
@@ -292,7 +305,7 @@
 		p->sin_port = 0;
 	}
 	// Use Local interface name if already set via command line
-	if (local_.is_set()) {
+	if (local_preset_) {
 		p->sin_addr.s_addr=(IPAddress&)local_;
 		return (0);
 	}
@@ -313,6 +326,7 @@
 		last_reset_ = t;
 		(void)::close(ssock_);
 		ssock_ = openssock(g_addr_, port_, ttl_);
+		disconnect_sock(ssock_);
 	}
 }
 
@@ -420,11 +434,21 @@
 				struct ip_mreq mr;
 
 				mr.imr_multiaddr.s_addr = g_addri;
-				mr.imr_interface.s_addr = INADDR_ANY;
-				if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, 
-						(char *)&mr, sizeof(mr)) < 0) {
-					perror("IP_ADD_MEMBERSHIP");
-					exit(1);
+				if (local_preset_) {
+					mr.imr_interface.s_addr = locali;
+					if (setsockopt(fd, IPPROTO_IP,IP_ADD_MEMBERSHIP,
+								(char *)&mr, sizeof(mr)) < 0) {
+						perror("IP_ADD_MEMBERSHIP");
+						debug_msg("Failed to join multicast group using preset local addr?\n");
+					}
+				} else {
+					mr.imr_interface.s_addr = INADDR_ANY;
+					if (setsockopt(fd, IPPROTO_IP,IP_ADD_MEMBERSHIP,
+								(char *)&mr, sizeof(mr)) < 0) {
+						perror("IP_ADD_MEMBERSHIP");
+						debug_msg("Failed to join multicast group- exiting\n");
+						exit(1);
+					}
 				}
 		}
 	} else
@@ -504,13 +528,13 @@
 	}
 #endif
 
-	memset((char *)&sin, 0, sizeof(sin));
-	sin.sin_family = AF_INET;
-	sin.sin_port = port;
-	sin.sin_addr.s_addr = INADDR_ANY;
-	if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
-        sin.sin_port = 0;
-        if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+	memset((char *)&sin_, 0, sizeof(sin_));
+	sin_.sin_family = AF_INET;
+	sin_.sin_port = port;
+	sin_.sin_addr.s_addr = INADDR_ANY;
+	if (bind(fd, (struct sockaddr *)&sin_, sizeof(sin_)) < 0) {
+        sin_.sin_port = 0;
+        if (bind(fd, (struct sockaddr *)&sin_, sizeof(sin_)) < 0) {
             perror("bind");
             exit(1);
         }
@@ -520,18 +544,19 @@
     debug_msg("set TOS:%d\n", 
 		setsockopt(fd, IPPROTO_IP, IP_TOS, (char*)&c, sizeof(c)));
 
-	memset((char *)&sin, 0, sizeof(sin));
-	sin.sin_family = AF_INET;
-	sin.sin_port = port;
-	sin.sin_addr.s_addr = addri;
-
-/*	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) {
+	memset((char *)&sin_, 0, sizeof(sin_));
+	sin_.sin_family = AF_INET;
+	sin_.sin_port = port;
+	sin_.sin_addr.s_addr = addri;
+
+    /* Connect() is useful for localname() to find the interface addr
+	 * being used. Also because of a problem with OSX we disconnect
+	 * this socket once localname() has found out the ip addr of the iface 
+	 */
+	if (connect(fd, (struct sockaddr *)&sin_, sizeof(sin_)) < 0) {
 		perror("connect");
 		exit(1);
-	}*/
+	}
 	if (IN_CLASSD(ntohl(addri))) {
 #ifdef IP_ADD_MEMBERSHIP
 		char c;
@@ -563,7 +588,7 @@
 		/* Slightly nasty one here - set Mcast iface if local inteface
 		 * is specified on command line
 		 */
-		if (((const char*)local_)[0]!='\0') {
+		if (local_preset_) {
 			u_int32_t locali = (IPAddress&)local_;
 			if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
 						   (char*)&locali, sizeof(locali)) < 0) {
@@ -593,6 +618,14 @@
 	return (fd);
 }
 
+int IPNetwork::disconnect_sock(int fd)
+{
+	struct sockaddr_in sin;
+
+	memset((char *)&sin, 0, sizeof(sin));
+	sin.sin_family = AF_UNSPEC;
+	return connect(fd, (struct sockaddr *)&sin, sizeof(sin));
+}
 
 
 int IPNetwork::dorecv(u_char* buf, int len, Address & from, int fd)
@@ -664,7 +697,7 @@
 
 void IPNetwork::dosend(u_char* buf, int len, int fd)
 {
-	int cc = ::sendto(fd, (char*)buf, len, 0, (struct sockaddr *)&sin, sizeof(sin));
+	int cc = ::sendto(fd, (char*)buf, len, 0, (struct sockaddr *)&sin_, sizeof(sin_));
 	if (cc < 0) {
 		switch (errno) {
 		case ECONNREFUSED:



More information about the Sumover-dev mailing list