Esempio n. 1
0
// Constructor for a source-independent multicast group
Groupsock::Groupsock(UsageEnvironment& env, struct in_addr const& groupAddr,
				 Port port, u_int8_t ttl)
	: OutputSocket(env, port),
	  deleteIfNoMembers(False), isSlave(False),
	  fIncomingGroupEId(groupAddr, port.num(), ttl), fDests(NULL), fTTL(ttl) {
  addDestination(groupAddr, port);
  
//  printf("Groupsock: grpaddr %s\n", inet_ntoa(groupAddr));   //jay
  if (!socketJoinGroup(env, socketNum(), groupAddr.s_addr)) {
	  if (DebugLevel >= 1) {
		  env << *this << ": failed to join group: "
		<< env.getResultMsg() << "\n";
		}
	}

	// Make sure we can get our source address:
  if (ourIPAddress(env) == 0) {
	  if (DebugLevel >= 0) { // this is a fatal error
		  env << "Unable to determine our source address: "
		<< env.getResultMsg() << "\n";
		}
	}

  if (DebugLevel >= 2) env << *this << ": created\n";
}
Esempio n. 2
0
// Constructor for a source-specific multicast group
Groupsock::Groupsock(UsageEnvironment& env, struct in_addr const& groupAddr,
		     struct in_addr const& sourceFilterAddr,
		     Port port)
  : OutputSocket(env, port),
    deleteIfNoMembers(False), isSlave(False),
    fIncomingGroupEId(groupAddr, sourceFilterAddr, port.num()),
    fDests(NULL), fTTL(255) {
  addDestination(groupAddr, port);

  // First try a SSM join.  If that fails, try a regular join:
  if (!socketJoinGroupSSM(env, socketNum(), groupAddr.s_addr,
			  sourceFilterAddr.s_addr)) {
    if (DebugLevel >= 3) {
      env << *this << ": SSM join failed: "
	  << env.getResultMsg();
      env << " - trying regular join instead\n";
    }
    if (!socketJoinGroup(env, socketNum(), groupAddr.s_addr)) {
      if (DebugLevel >= 1) {
	env << *this << ": failed to join group: "
	     << env.getResultMsg() << "\n";
      }
    }
  }

  if (DebugLevel >= 2) env << *this << ": created\n";
}
Esempio n. 3
0
void
Groupsock::changeDestinationParameters(struct in_addr const& newDestAddr,
				       Port newDestPort, int newDestTTL, unsigned sessionId) {
  destRecord* dest;
  for (dest = fDests; dest != NULL && dest->fSessionId != sessionId; dest = dest->fNext) {}

  if (dest == NULL) { // There's no existing 'destRecord' for this "sessionId"; add a new one:
    fDests = createNewDestRecord(newDestAddr, newDestPort, newDestTTL, sessionId, fDests);
    return;
  }

  // "dest" is an existing 'destRecord' for this "sessionId"; change its values to the new ones:
  struct in_addr destAddr = dest->fGroupEId.groupAddress();
  if (newDestAddr.s_addr != 0) {
    if (newDestAddr.s_addr != destAddr.s_addr
	&& IsMulticastAddress(newDestAddr.s_addr)) {
      // If the new destination is a multicast address, then we assume that
      // we want to join it also.  (If this is not in fact the case, then
      // call "multicastSendOnly()" afterwards.)
      socketLeaveGroup(env(), socketNum(), destAddr.s_addr);
      socketJoinGroup(env(), socketNum(), newDestAddr.s_addr);
    }
    destAddr.s_addr = newDestAddr.s_addr;
  }

  portNumBits destPortNum = dest->fGroupEId.portNum();
  if (newDestPort.num() != 0) {
    if (newDestPort.num() != destPortNum
	&& IsMulticastAddress(destAddr.s_addr)) {
      // Also bind to the new port number:
      changePort(newDestPort);
      // And rejoin the multicast group:
      socketJoinGroup(env(), socketNum(), destAddr.s_addr);
    }
    destPortNum = newDestPort.num();
  }

  u_int8_t destTTL = ttl();
  if (newDestTTL != ~0) destTTL = (u_int8_t)newDestTTL;

  dest->fGroupEId = GroupEId(destAddr, destPortNum, destTTL);

  // Finally, remove any other 'destRecord's that might also have this "sessionId":
  removeDestinationFrom(dest->fNext, sessionId);
}
Esempio n. 4
0
void
Groupsock::changeDestinationParameters(struct in_addr const& newDestAddr,
							 Port newDestPort, int newDestTTL) {
  if (fDests == NULL) return;
	printf("changeDestinationParameters: %s:%d\n", inet_ntoa(newDestAddr), ntohs(newDestPort.num()));	//jay

  struct in_addr destAddr = fDests->fGroupEId.groupAddress();
  if (newDestAddr.s_addr != 0) {
	  if (newDestAddr.s_addr != destAddr.s_addr
	&& IsMulticastAddress(newDestAddr.s_addr)) {
			// If the new destination is a multicast address, then we assume that
			// we want to join it also.	(If this is not in fact the case, then
			// call "multicastSendOnly()" afterwards.)
		  socketLeaveGroup(env(), socketNum(), destAddr.s_addr);
		  socketJoinGroup(env(), socketNum(), newDestAddr.s_addr);
		}
	  destAddr.s_addr = newDestAddr.s_addr;
	}

  portNumBits destPortNum = fDests->fGroupEId.portNum();
  if (newDestPort.num() != 0) {
	  if (newDestPort.num() != destPortNum
	&& IsMulticastAddress(destAddr.s_addr)) {
			// Also bind to the new port number:
		  changePort(newDestPort);
			// And rejoin the multicast group:
		  socketJoinGroup(env(), socketNum(), destAddr.s_addr);
		}
	  destPortNum = newDestPort.num();
	  fDests->fPort = newDestPort;
	}

  u_int8_t destTTL = ttl();
  if (newDestTTL != ~0) destTTL = (u_int8_t)newDestTTL;

  fDests->fGroupEId = GroupEId(destAddr, destPortNum, destTTL);
}
netAddressBits ourIPAddress(UsageEnvironment& env) {
  static netAddressBits ourAddress = 0;
  int sock = -1;
  struct in_addr testAddr;

  if (ourAddress == 0) {
		// We need to find our source address
	  struct sockaddr_in fromAddr;
	  fromAddr.sin_addr.s_addr = 0;

		// Get our address by sending a (0-TTL) multicast packet,
		// receiving it, and looking at the source address used.
		// (This is kinda bogus, but it provides the best guarantee
		// that other nodes will think our address is the same as we do.)
	  do {
		  loopbackWorks = 0; // until we learn otherwise

		  testAddr.s_addr = our_inet_addr("228.67.43.91"); // arbitrary
		  Port testPort(15947); // ditto

		  sock = setupDatagramSocket(env, testPort);
		  if (sock < 0) break;

		  if (!socketJoinGroup(env, sock, testAddr.s_addr)) break;

		  unsigned char testString[] = "hostIdTest";
		  unsigned testStringLength = sizeof testString;

		  if (!writeSocket(env, sock, testAddr, testPort, 0,
					 testString, testStringLength)) break;

		  unsigned char readBuffer[20];
		  struct timeval timeout;
		  timeout.tv_sec = 5;
		  timeout.tv_usec = 0;
		  int bytesRead = readSocket(env, sock,
				 readBuffer, sizeof readBuffer,
				 fromAddr, &timeout);
		  if (bytesRead == 0 // timeout occurred
		|| bytesRead != (int)testStringLength
		|| strncmp((char*)readBuffer, (char*)testString,
				 testStringLength) != 0) {
	break;
			}

		  loopbackWorks = 1;
		} while (0);

	  if (!loopbackWorks) do {
			// We couldn't find our address using multicast loopback
			// so try instead to look it up directly.
		  char hostname[100];
		  hostname[0] = '\0';
#ifndef CRIS
		  gethostname(hostname, sizeof hostname);
#endif
		  if (hostname[0] == '\0') {
	env.setResultErrMsg("initial gethostname() failed");
	break;
			}

#if defined(VXWORKS)
#include <hostLib.h>
		  if (ERROR == (ourAddress = hostGetByName( hostname ))) break;
#else
		  struct hostent* hstent
	= (struct hostent*)gethostbyname(hostname);
		  if (hstent == NULL || hstent->h_length != 4) {
	env.setResultErrMsg("initial gethostbyname() failed");
	break;
			}
			// Take the first address that's not bad
			// (This code, like many others, won't handle IPv6)
		  netAddressBits addr = 0;
		  for (unsigned i = 0; ; ++i) {
	char* addrPtr = hstent->h_addr_list[i];
	if (addrPtr == NULL) break;

	netAddressBits a = *(netAddressBits*)addrPtr;
	if (!badAddress(a)) {
	  addr = a;
	  break;
	}
			}
		  if (addr != 0) {
	fromAddr.sin_addr.s_addr = addr;
			} else {
	env.setResultMsg("no address");
	break;
			}
		} while (0);

		// Make sure we have a good address:
	  netAddressBits from = fromAddr.sin_addr.s_addr;
	  if (badAddress(from)) {
		  char tmp[100];
		  sprintf(tmp,
				"This computer has an invalid IP address: 0x%x",
				(netAddressBits)(ntohl(from)));
		  env.setResultMsg(tmp);
		  from = 0;
		}

	  ourAddress = from;
#endif

	  if (sock >= 0) {
		  socketLeaveGroup(env, sock, testAddr.s_addr);
		  closeSocket(sock);
		}

		// Use our newly-discovered IP address, and the current time,
		// to initialize the random number generator's seed:
	  struct timeval timeNow;
	  gettimeofday(&timeNow, NULL);
	  unsigned seed = ourAddress^timeNow.tv_sec^timeNow.tv_usec;
	  our_srandom(seed);
	}
  return ourAddress;
}
Esempio n. 6
0
void Groupsock::joinGroup(netAddressBits groupAddress)
{
	socketJoinGroup(env(), socketNum(), groupAddress);
}
Esempio n. 7
0
netAddressBits ourIPAddress(UsageEnvironment& env) {
  static netAddressBits ourAddress = 0;
  int sock = -1;
  struct in_addr testAddr;

  if (ReceivingInterfaceAddr != INADDR_ANY) {
    // Hack: If we were told to receive on a specific interface address, then 
    // define this to be our ip address:
    ourAddress = ReceivingInterfaceAddr;
  }

  if (ourAddress == 0) {
    // We need to find our source address
    struct sockaddr_in fromAddr;
    fromAddr.sin_addr.s_addr = 0;

    // Get our address by sending a (0-TTL) multicast packet,
    // receiving it, and looking at the source address used.
    // (This is kinda bogus, but it provides the best guarantee
    // that other nodes will think our address is the same as we do.)
    do {
      loopbackWorks = 0; // until we learn otherwise

      testAddr.s_addr = our_inet_addr("228.67.43.91"); // arbitrary
      Port testPort(15947); // ditto

      sock = setupDatagramSocket(env, testPort);
      if (sock < 0) break;

      if (!socketJoinGroup(env, sock, testAddr.s_addr)) break;

      unsigned char testString[] = "hostIdTest";
      unsigned testStringLength = sizeof testString;

      if (!writeSocket(env, sock, testAddr, testPort.num(), 0,
		       testString, testStringLength)) break;

      // Block until the socket is readable (with a 5-second timeout):
      fd_set rd_set;
      FD_ZERO(&rd_set);
      FD_SET((unsigned)sock, &rd_set);
      const unsigned numFds = sock+1;
      struct timeval timeout;
      timeout.tv_sec = 5;
      timeout.tv_usec = 0;
      int result = select(numFds, &rd_set, NULL, NULL, &timeout);
      if (result <= 0) break;

      unsigned char readBuffer[20];
      int bytesRead = readSocket(env, sock,
				 readBuffer, sizeof readBuffer,
				 fromAddr);
      if (bytesRead != (int)testStringLength
	  || strncmp((char*)readBuffer, (char*)testString, testStringLength) != 0) {
	break;
      }

      // We use this packet's source address, if it's good:
      loopbackWorks = !badAddressForUs(fromAddr.sin_addr.s_addr);
    } while (0);

    if (sock >= 0) {
      socketLeaveGroup(env, sock, testAddr.s_addr);
      closeSocket(sock);
    }

    if (!loopbackWorks) do {
      // We couldn't find our address using multicast loopback,
      // so try instead to look it up directly - by first getting our host name, and then resolving this host name
      char hostname[100];
      hostname[0] = '\0';
      int result = gethostname(hostname, sizeof hostname);
      if (result != 0 || hostname[0] == '\0') {
	env.setResultErrMsg("initial gethostname() failed");
	break;
      }

      // Try to resolve "hostname" to an IP address:
      NetAddressList addresses(hostname);
      NetAddressList::Iterator iter(addresses);
      NetAddress const* address;

      // Take the first address that's not bad:
      netAddressBits addr = 0;
      while ((address = iter.nextAddress()) != NULL) {
	netAddressBits a = *(netAddressBits*)(address->data());
	if (!badAddressForUs(a)) {
	  addr = a;
	  break;
	}
      }

      // Assign the address that we found to "fromAddr" (as if the 'loopback' method had worked), to simplify the code below: 
      fromAddr.sin_addr.s_addr = addr;
    } while (0);

    // Make sure we have a good address:
    netAddressBits from = fromAddr.sin_addr.s_addr;
    if (badAddressForUs(from)) {
      char tmp[100];
      sprintf(tmp, "This computer has an invalid IP address: %s", AddressString(from).val());
      env.setResultMsg(tmp);
      from = 0;
    }

    ourAddress = from;

    // Use our newly-discovered IP address, and the current time,
    // to initialize the random number generator's seed:
    struct timeval timeNow;
    gettimeofday(&timeNow, NULL);
    unsigned seed = ourAddress^timeNow.tv_sec^timeNow.tv_usec;
    our_srandom(seed);
  }
  return ourAddress;
}