⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 groupsock.cpp

📁 流媒体传输协议的实现代码,非常有用.可以支持rtsp mms等流媒体传输协议
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/**********This library is free software; you can redistribute it and/or modify it underthe terms of the GNU Lesser General Public License as published by theFree Software Foundation; either version 2.1 of the License, or (at youroption) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)This library is distributed in the hope that it will be useful, but WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License formore details.You should have received a copy of the GNU Lesser General Public Licensealong with this library; if not, write to the Free Software Foundation, Inc.,59 Temple Place, Suite 330, Boston, MA  02111-1307  USA**********/// LIVE.COM Streaming Media Libraries// Copyright (c) 1996-1999 Live Networks, Inc.  All rights reserved.// 'Group sockets'// Implementation#include "Groupsock.hh"#include "GroupsockHelper.hh"//##### Eventually fix the following #include; we shouldn't know about tunnels#include "TunnelEncaps.hh"#ifndef NO_STRSTREAM#if (defined(__WIN32__) || defined(_WIN32)) && !defined(__MINGW32__)#include <strstrea.h>#else#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)#include <strstream>#else#include <strstream.h>#endif#endif#endif#include <stdio.h>///////// OutputSocket //////////OutputSocket::OutputSocket(UsageEnvironment& env)  : Socket(env, 0 /* let kernel choose port */),    fSourcePort(0), fLastSentTTL(0) {}OutputSocket::OutputSocket(UsageEnvironment& env, Port port)  : Socket(env, port),    fSourcePort(0), fLastSentTTL(0) {}OutputSocket::~OutputSocket() {}Boolean OutputSocket::write(netAddressBits address, Port port, u_int8_t ttl,			    unsigned char* buffer, unsigned bufferSize) {  if (ttl == fLastSentTTL) {    // Optimization: So we don't do a 'set TTL' system call again    ttl = 0;  } else {    fLastSentTTL = ttl;  }  struct in_addr destAddr; destAddr.s_addr = address;  if (!writeSocket(env(), socketNum(), destAddr, port, ttl,		   buffer, bufferSize))    return False;    if (sourcePortNum() == 0) {    // Now that we've sent a packet, we can find out what the    // kernel chose as our ephemeral source port number:    if (!getSourcePort(env(), socketNum(), fSourcePort)) {      if (DebugLevel >= 1)	env() << *this	     << ": failed to get source port: "	     << env().getResultMsg() << "\n";      return False;    }  }    return True;}// By default, we don't do reads:Boolean OutputSocket::handleRead(unsigned char* /*buffer*/, unsigned /*bufferMaxSize*/,	     unsigned& /*bytesRead*/, struct sockaddr_in& /*fromAddress*/) {  return True;}///////// destRecord //////////destRecord::destRecord(struct in_addr const& addr, Port const& port, u_int8_t ttl,	     destRecord* next)  : fNext(next), fGroupEId(addr, port.num(), ttl), fPort(port) {}destRecord::~destRecord() {  delete fNext;}///////// Groupsock //////////NetInterfaceTrafficStats Groupsock::statsIncoming;NetInterfaceTrafficStats Groupsock::statsOutgoing;NetInterfaceTrafficStats Groupsock::statsRelayedIncoming;NetInterfaceTrafficStats Groupsock::statsRelayedOutgoing;// Constructor for a source-independent multicast groupGroupsock::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);  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 (ourSourceAddressForMulticast(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";}// Constructor for a source-specific multicast groupGroupsock::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";}Groupsock::~Groupsock() {  if (isSSM()) {    if (!socketLeaveGroupSSM(env(), socketNum(), groupAddress().s_addr,			     sourceFilterAddress().s_addr)) {      socketLeaveGroup(env(), socketNum(), groupAddress().s_addr);    }  } else {    socketLeaveGroup(env(), socketNum(), groupAddress().s_addr);  }    delete fDests;  if (DebugLevel >= 2) env() << *this << ": deleting\n";}voidGroupsock::changeDestinationParameters(struct in_addr const& newDestAddr,				       Port newDestPort, int newDestTTL) {  if (fDests == NULL) return;  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) {    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);}void Groupsock::addDestination(struct in_addr const& addr, Port const& port) {  // Check whether this destination is already known:  for (destRecord* dests = fDests; dests != NULL; dests = dests->fNext) {    if (addr.s_addr == dests->fGroupEId.groupAddress().s_addr	&& port.num() == dests->fPort.num()) {      return;    }  }  fDests = new destRecord(addr, port, ttl(), fDests);}void Groupsock::removeDestination(struct in_addr const& addr, Port const& port) {  for (destRecord** destsPtr = &fDests; *destsPtr != NULL;       destsPtr = &((*destsPtr)->fNext)) {    if (addr.s_addr == (*destsPtr)->fGroupEId.groupAddress().s_addr	&& port.num() == (*destsPtr)->fPort.num()) {      // Remove the record pointed to by *destsPtr :      destRecord* next = (*destsPtr)->fNext;      (*destsPtr)->fNext = NULL;      delete (*destsPtr);      *destsPtr = next;      return;    }  }}void Groupsock::removeAllDestinations() {  delete fDests; fDests = NULL;}void Groupsock::multicastSendOnly() {  socketLeaveGroup(env(), socketNum(), fIncomingGroupEId.groupAddress().s_addr);  for (destRecord* dests = fDests; dests != NULL; dests = dests->fNext) {    socketLeaveGroup(env(), socketNum(), dests->fGroupEId.groupAddress().s_addr);  }}Boolean Groupsock::output(UsageEnvironment& env, u_int8_t ttlToSend,			  unsigned char* buffer, unsigned bufferSize,			  DirectedNetInterface* interfaceNotToFwdBackTo) {  do {    // First, do the datagram send, to each destination:    Boolean writeSuccess = True;    for (destRecord* dests = fDests; dests != NULL; dests = dests->fNext) {      if (!write(dests->fGroupEId.groupAddress().s_addr, dests->fPort, ttlToSend,		 buffer, bufferSize)) {	writeSuccess = False;	break;      }    }    if (!writeSuccess) break;    statsOutgoing.countPacket(bufferSize);    statsGroupOutgoing.countPacket(bufferSize);        // Then, forward to our members:    int numMembers =      outputToAllMembersExcept(interfaceNotToFwdBackTo,			       ttlToSend, buffer, bufferSize,			       ourSourceAddressForMulticast(env));    if (numMembers < 0) break;        if (DebugLevel >= 3) {      env << *this << ": wrote " << bufferSize << " bytes, ttl "	  << (unsigned)ttlToSend;      if (numMembers > 0) {	env << "; relayed to " << numMembers << " members";      }      env << "\n";    }    return True;  } while (0);    if (DebugLevel >= 0) { // this is a fatal error    env.setResultMsg("Groupsock write failed: ", env.getResultMsg());  }  return False;}Boolean Groupsock::handleRead(unsigned char* buffer, unsigned bufferMaxSize,			      unsigned& bytesRead,			      struct sockaddr_in& fromAddress) {  // Read data from the socket, and relay it across any attached tunnels  //##### later make this code more general - independent of tunnels    bytesRead = 0;    int maxBytesToRead = bufferMaxSize - TunnelEncapsulationTrailerMaxSize;  int numBytes = readSocket(env(), socketNum(),			    buffer, maxBytesToRead, fromAddress);  if (numBytes < 0) {    if (DebugLevel >= 0) { // this is a fatal error      env().setResultMsg("Groupsock read failed: ",			 env().getResultMsg());    }    return False;  }    // If we're a SSM group, make sure the source address matches:  if (isSSM()      && fromAddress.sin_addr.s_addr != sourceFilterAddress().s_addr) {    return True;  }    // We'll handle this data.  // Also write it (with the encapsulation trailer) to each member,  // unless the packet was originally sent by us to begin with.  bytesRead = numBytes;    int numMembers = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -