コード例 #1
0
ファイル: elcrtspserver.cpp プロジェクト: wyrover/DESKTOP-1
bool ElcRTSPServer::setSource(const string& url, const string& iname)
{
	LOG_INFO("ElcRTSPServer::setSource -url="<<url<<" -name="<<iname);
	mUrl = url;
	mName = iname;
	Boolean reuseFirstSource = true;
	if(!rtspServer)
	{
		LOG_ERROR("ElcRTSPServer::setSource failed! Rtspserver does not created propertly");
		return false;
	}
	mediaSession = ServerMediaSession::createNew(*mEnv, mName.c_str(), mName.c_str(), "ELC");
	if(!mediaSession)
		return false;

	// if multicast streaming
	if(Config::isMulticast)
	{
		struct in_addr destinationAddress;
		if(Config::streamingDestinationIp == "default" || Config::streamingDestinationIp =="")
			destinationAddress.s_addr = chooseRandomIPv4SSMAddress(*mEnv);
		else
			destinationAddress.s_addr = our_inet_addr(Config::streamingDestinationIp.c_str());

		Port rtpPort(Config::rtpPortNum);
		Port rtcpPort(Config::rtcpPortNum);

		rtpGroupsock = new Groupsock(*mEnv, destinationAddress, rtpPort, 255/*Config::ttl*/);
		rtpGroupsock->multicastSendOnly(); // we're a SSM source
		rtcpGroupsock = new Groupsock(*mEnv, destinationAddress, rtcpPort, 255/*Config::ttl*/);
		rtcpGroupsock->multicastSendOnly(); // we're a SSM source

		videoSink = MPEG4ESVideoRTPSink::createNew(*mEnv, rtpGroupsock, 96);

		const unsigned estimatedSessionBandwidth = 500; // in kbps; for RTCP b/w share
		const unsigned maxCNAMElen = 100;
		unsigned char CNAME[maxCNAMElen+1];
		gethostname((char*)CNAME, maxCNAMElen);
		CNAME[maxCNAMElen] = '\0'; // just in case

		rtcp = RTCPInstance::createNew(*mEnv, rtcpGroupsock,
						estimatedSessionBandwidth, CNAME,
						videoSink, NULL /* we're a server*/ ,
						True /* we're a SSM source */);

		mediaSession->addSubsession(PassiveServerMediaSubsession::createNew(*videoSink, rtcp));
		rtspServer->addServerMediaSession(mediaSession);

		LOG_INFO("ElcRTSPServer::setSource OK");
	}
	else // unicast streaming
	{
		mediaSubSession = Mpeg4LiveServerMediaSubSession::createNew(*mEnv, reuseFirstSource, mUrl);
		mediaSession->addSubsession(mediaSubSession);
		rtspServer->addServerMediaSession(mediaSession);
		LOG_INFO("ElcRTSPServer::setSource OK");
	}

	return true;
}
コード例 #2
0
NetAddressList::NetAddressList(char const* hostname)
	: fNumAddresses(0), fAddressArray(NULL) {
	  struct hostent* host;

		// Check first whether "hostname" is an IP address string:
	  netAddressBits addr = our_inet_addr((char*)hostname);
	  if (addr != INADDR_NONE) { // yes it was an IP address string
			//##### host = gethostbyaddr((char*)&addr, sizeof (netAddressBits), AF_INET);
		  host = NULL; // don't bother calling gethostbyaddr(); we only want 1 addr

		  if (host == NULL) {
	// For some unknown reason, gethostbyaddr() failed, so just
	// return a 1-element list with the address we were given:
	fNumAddresses = 1;
	fAddressArray = new NetAddress*[fNumAddresses];
	if (fAddressArray == NULL) return;

	fAddressArray[0] = new NetAddress((u_int8_t*)&addr,
					  sizeof (netAddressBits));
	return;
			}
		} else { // Try resolving "hostname" as a real host name

#if defined(VXWORKS)
		  char hostentBuf[512];
		  host = (struct hostent*)resolvGetHostByName((char*)hostname,(char*)&hostentBuf,sizeof hostentBuf);
#else
		  host = our_gethostbyname((char*)hostname);
#endif

		  if (host == NULL) {
	// It was a host name, and we couldn't resolve it.  We're SOL.
	return;
			}
		}

	  u_int8_t const** const hAddrPtr
			= (u_int8_t const**)host->h_addr_list;
	  if (hAddrPtr != NULL) {
			// First, count the number of addresses:
		  u_int8_t const** hAddrPtr1 = hAddrPtr;
		  while (*hAddrPtr1 != NULL) {
	++fNumAddresses;
	++hAddrPtr1;
			}

			// Next, set up the list:
		  fAddressArray = new NetAddress*[fNumAddresses];
		  if (fAddressArray == NULL) return;

		  for (unsigned i = 0; i < fNumAddresses; ++i) {
	fAddressArray[i]
		= new NetAddress(hAddrPtr[i], host->h_length);
			}
		}
}
コード例 #3
0
int main(int argc, char** argv) {
  // Begin by setting up our usage environment:
  TaskScheduler* scheduler = BasicTaskScheduler::createNew();
  UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler);


  // Create a 'groupsock' for the input multicast group,port:
  char const* sessionAddressStr = "224.2.127.254";
  struct in_addr sessionAddress;
  sessionAddress.s_addr = our_inet_addr(sessionAddressStr);

  const Port port(9875);
  const unsigned char ttl = 0; // we're only reading from this mcast group

  Groupsock inputGroupsock(*env, sessionAddress, port, ttl);

  // Start reading and printing incoming packets
  // (Because this is the only thing we do, we can just do this
  // synchronously, in a loop, so we don't need to set up an asynchronous
  // event handler like we do in most of the other test programs.)
  unsigned packetSize;
  struct sockaddr_in fromAddress;
  while (inputGroupsock.handleRead(packet, maxPacketSize,
				   packetSize, fromAddress)) {
    printf("\n[packet from %s (%d bytes)]\n",
	   our_inet_ntoa(fromAddress.sin_addr), packetSize);

    // Ignore the first 8 bytes (SAP header).
    if (packetSize < 8) {
      *env << "Ignoring short packet from "
	   << our_inet_ntoa(fromAddress.sin_addr) << "%s!\n";
      continue;
    }

    // convert "application/sdp\0" -> "application/sdp\0x20"
    // or all other nonprintable characters to blank, except new line
    unsigned idx = 8;
    while (idx < packetSize) {
      if (packet[idx] < 0x20 && packet[idx] != '\n') packet[idx] = 0x20;
      idx++;
    }

    packet[packetSize] = '\0'; // just in case
    printf((char*)(packet+8));
  }

  return 0; // only to prevent compiler warning
}
コード例 #4
0
FramedSource* MPEG2TransportUDPServerMediaSubsession
::createNewStreamSource(unsigned/* clientSessionId*/, unsigned& estBitrate) {
  estBitrate = 5000; // kbps, estimate

  if (fInputGroupsock == NULL) {
    // Create a 'groupsock' object for receiving the input stream:
    struct in_addr inputAddress;
    inputAddress.s_addr = fInputAddressStr == NULL ? 0 : our_inet_addr(fInputAddressStr);
    fInputGroupsock = new Groupsock(envir(), inputAddress, fInputPort, 255);
  }

  FramedSource* transportStreamSource;
  if (fInputStreamIsRawUDP) {
    transportStreamSource = BasicUDPSource::createNew(envir(), fInputGroupsock);
  } else {
    transportStreamSource = SimpleRTPSource::createNew(envir(), fInputGroupsock, 33, 90000, "video/MP2T", 0, False /*no 'M' bit*/);
  }
  return MPEG2TransportStreamFramer::createNew(envir(), transportStreamSource);
}
コード例 #5
0
void CCreateRTPServer::createGroupsock()
{
    m_prtcpGroupsockAudio = NULL;
    m_prtpGroupsockAudio = NULL;
    m_prtcpGroupsockVideo = NULL;
    m_prtpGroupsockVideo = NULL;

    struct in_addr destAddress;
    //destAddress.s_addr = our_inet_addr(m_destAddressStr.c_str());
    if(!m_rtpDestAddressStr.empty())
        destAddress.s_addr = our_inet_addr(m_rtpDestAddressStr.c_str());
    else
        destAddress.s_addr = chooseRandomIPv4SSMAddress(*env);

    if(m_pAudioSourceQueue != NULL)
    {
        const unsigned short rtpPortNumAudio = m_rtpPortNum;
        const unsigned short rtcpPortNumAudio = rtpPortNumAudio + 1;
        const Port rtpPortAudio(rtpPortNumAudio);
        const Port rtcpPortAudio(rtcpPortNumAudio);
        m_prtpGroupsockAudio = new Groupsock(*env, destAddress, rtpPortAudio, m_ttl);
        m_prtcpGroupsockAudio = new Groupsock(*env, destAddress, rtcpPortAudio, m_ttl);
        if(m_prtpGroupsockAudio && m_prtcpGroupsockAudio)
        {
            m_rtpPortNum += 2;
        }
    }

    if(m_pVideoSourceQueue != NULL)
    {
        const unsigned short rtpPortNumVideo = m_rtpPortNum;
        const unsigned short rtcpPortNumVideo = rtpPortNumVideo + 1;
        const Port rtpPortVideo(rtpPortNumVideo);
        const Port rtcpPortVideo(rtcpPortNumVideo);
        m_prtpGroupsockVideo = new Groupsock(*env, destAddress, rtpPortVideo, m_ttl);
        m_prtcpGroupsockVideo = new Groupsock(*env, destAddress, rtcpPortVideo, m_ttl);
    }
}
コード例 #6
0
  char const* destinationAddressStr
#ifdef USE_SSM
    = "232.255.42.42";
#else
    = "239.255.42.42";
  // Note: This is a multicast address.  If you wish to stream using
  // unicast instead, then replace this string with the unicast address
  // of the (single) destination.  (You may also need to make a similar
  // change to the receiver program.)
#endif
  const unsigned short rtpPortNum = 8888;
  const unsigned short rtcpPortNum = rtpPortNum+1;
  const unsigned char ttl = 7; // low, in case routers don't admin scope

  struct in_addr destinationAddress;
  destinationAddress.s_addr = our_inet_addr(destinationAddressStr);
  const Port rtpPort(rtpPortNum);
  const Port rtcpPort(rtcpPortNum);

  Groupsock rtpGroupsock(*env, destinationAddress, rtpPort, ttl);
  Groupsock rtcpGroupsock(*env, destinationAddress, rtcpPort, ttl);
#ifdef USE_SSM
  rtpGroupsock.multicastSendOnly();
  rtcpGroupsock.multicastSendOnly();
#endif

  // Create a 'MPEG Video RTP' sink from the RTP 'groupsock':
  videoSink = MPEG1or2VideoRTPSink::createNew(*env, &rtpGroupsock);

  // Create (and start) a 'RTCP instance' for this RTP sink:
  const unsigned estimatedSessionBandwidth = 4500; // in kbps; for RTCP b/w share
コード例 #7
0
ファイル: NetAddress.cpp プロジェクト: dongkc/live
NetAddressList::NetAddressList(char const* hostname)
  : fNumAddresses(0), fAddressArray(NULL) {
  // First, check whether "hostname" is an IP address string:
  netAddressBits addr = our_inet_addr((char*)hostname);
  if (addr != INADDR_NONE) {
    // Yes, it was an IP address string.  Return a 1-element list with this address:
    fNumAddresses = 1;
    fAddressArray = new NetAddress*[fNumAddresses];
    if (fAddressArray == NULL) return;

    fAddressArray[0] = new NetAddress((u_int8_t*)&addr, sizeof (netAddressBits));
    return;
  }
    
  // "hostname" is not an IP address string; try resolving it as a real host name instead:
#if defined(USE_GETHOSTBYNAME) || defined(VXWORKS)
  struct hostent* host;
#if defined(VXWORKS)
  char hostentBuf[512];

  host = (struct hostent*)resolvGetHostByName((char*)hostname, (char*)&hostentBuf, sizeof hostentBuf);
#else
  host = gethostbyname((char*)hostname);
#endif
  if (host == NULL || host->h_length != 4 || host->h_addr_list == NULL) return; // no luck

  u_int8_t const** const hAddrPtr = (u_int8_t const**)host->h_addr_list;
  // First, count the number of addresses:
  u_int8_t const** hAddrPtr1 = hAddrPtr;
  while (*hAddrPtr1 != NULL) {
    ++fNumAddresses;
    ++hAddrPtr1;
  }

  // Next, set up the list:
  fAddressArray = new NetAddress*[fNumAddresses];
  if (fAddressArray == NULL) return;

  for (unsigned i = 0; i < fNumAddresses; ++i) {
    fAddressArray[i] = new NetAddress(hAddrPtr[i], host->h_length);
  }
#else
  // Use "getaddrinfo()" (rather than the older, deprecated "gethostbyname()"):
  struct addrinfo addrinfoHints;
  memset(&addrinfoHints, 0, sizeof addrinfoHints);
  addrinfoHints.ai_family = AF_INET; // For now, we're interested in IPv4 addresses only
  struct addrinfo* addrinfoResultPtr = NULL;
  int result = getaddrinfo(hostname, NULL, &addrinfoHints, &addrinfoResultPtr);
  if (result != 0 || addrinfoResultPtr == NULL) return; // no luck

  // First, count the number of addresses:
  const struct addrinfo* p = addrinfoResultPtr;
  while (p != NULL) {
    if (p->ai_addrlen < 4) continue; // sanity check: skip over addresses that are too small
    ++fNumAddresses;
    p = p->ai_next;
  }

  // Next, set up the list:
  fAddressArray = new NetAddress*[fNumAddresses];
  if (fAddressArray == NULL) return;

  unsigned i = 0;
  p = addrinfoResultPtr;
  while (p != NULL) {
    if (p->ai_addrlen < 4) continue;
    fAddressArray[i++] = new NetAddress((u_int8_t const*)&(((struct sockaddr_in*)p->ai_addr)->sin_addr.s_addr), 4);
    p = p->ai_next;
  }

  // Finally, free the data that we had allocated by calling "getaddrinfo()":
  freeaddrinfo(addrinfoResultPtr);
#endif
}
コード例 #8
0
JNIEXPORT void JNICALL Java_com_parizene_streamer_Streamer_loop(JNIEnv *env,
		jobject obj, jstring addr) {
	// Begin by setting up our usage environment:
	TaskScheduler* scheduler = BasicTaskScheduler::createNew();
	uEnv = BasicUsageEnvironment::createNew(*scheduler);

	// Create 'groupsocks' for RTP and RTCP:
	struct in_addr destinationAddress;
	const char *_addr = env->GetStringUTFChars(addr, NULL);
	destinationAddress.s_addr = our_inet_addr(_addr); /*chooseRandomIPv4SSMAddress(*uEnv);*/
	env->ReleaseStringUTFChars(addr, _addr);
	// Note: This is a multicast address.  If you wish instead to stream
	// using unicast, then you should use the "testOnDemandRTSPServer"
	// test program - not this test program - as a model.

	const unsigned short rtpPortNum = 18888;
	const unsigned short rtcpPortNum = rtpPortNum + 1;
	const unsigned char ttl = 255;

	const Port rtpPort(rtpPortNum);
	const Port rtcpPort(rtcpPortNum);

	Groupsock rtpGroupsock(*uEnv, destinationAddress, rtpPort, ttl);
	Groupsock rtcpGroupsock(*uEnv, destinationAddress, rtcpPort, ttl);

	// Create a 'H264 Video RTP' sink from the RTP 'groupsock':
	OutPacketBuffer::maxSize = 100000;
	videoSink = H264VideoRTPSink::createNew(*uEnv, &rtpGroupsock, 96);

	// Create (and start) a 'RTCP instance' for this RTP sink:
	const unsigned estimatedSessionBandwidth = 500; // in kbps; for RTCP b/w share
	const unsigned maxCNAMElen = 100;
	unsigned char CNAME[maxCNAMElen + 1];
	gethostname((char*) CNAME, maxCNAMElen);
	CNAME[maxCNAMElen] = '\0'; // just in case
	RTCPInstance* rtcp = RTCPInstance::createNew(*uEnv, &rtcpGroupsock,
			estimatedSessionBandwidth, CNAME, videoSink,
			NULL /* we're a server */, True /* we're a SSM source */);
	// Note: This starts RTCP running automatically

	RTSPServer* rtspServer = RTSPServer::createNew(*uEnv, 8554);
	if (rtspServer == NULL) {
		LOGE("Failed to create RTSP server: %s", uEnv->getResultMsg());
		exit(1);
	}
	ServerMediaSession* sms = ServerMediaSession::createNew(*uEnv, "streamer",
			inputFilename, "Session streamed by \"testH264VideoStreamer\"",
			True /*SSM*/);
	sms->addSubsession(
			PassiveServerMediaSubsession::createNew(*videoSink, rtcp));
	rtspServer->addServerMediaSession(sms);

	char* url = rtspServer->rtspURL(sms);
	LOGI("Play this stream using the URL \"%s\"", url);
	delete[] url;

	// Start the streaming:
	LOGI("Beginning streaming...\n");
	play();

	uEnv->taskScheduler().doEventLoop(); // does not return
}
コード例 #9
0
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;
}
コード例 #10
0
ファイル: iptvfeederrtp.cpp プロジェクト: Olti/mythtv
bool IPTVFeederRTP::Open(const QString &url)
{
    LOG(VB_RECORD, LOG_INFO, LOC + QString("Open(%1) -- begin").arg(url));

    QMutexLocker locker(&_lock);

    if (_source)
    {
        LOG(VB_RECORD, LOG_INFO, LOC + "Open() -- end 1");
        return true;
    }

    QUrl parse(url);
    if (!parse.isValid() || parse.host().isEmpty() || (-1 == parse.port()))
    {
        LOG(VB_RECORD, LOG_INFO, LOC + "Open() -- end 2");
        return false;
    }

    struct in_addr addr;
    QByteArray host = parse.host().toLatin1();
    addr.s_addr = our_inet_addr(host.constData());

    // Begin by setting up our usage environment:
    if (!InitEnv())
        return false;

    ReceivingSocketAddr = our_inet_addr(parse.host().toLatin1());

    Groupsock *socket = new Groupsock(*_live_env, addr, parse.port(), 0);
    if (!socket)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Live RTP Socket.");
        FreeEnv();
        return false;
    }

    _source = SimpleRTPSource::createNew(*_live_env, socket, 33, 90000,
                                         "video/MP2T", 0, False);
    if (!_source)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Live RTP Source.");

        if (socket)
            delete socket;

        FreeEnv();
        return false;
    }

    _sink = IPTVMediaSink::CreateNew(*_live_env, TSPacket::kSize * 128*1024);
    if (!_sink)
    {
        LOG(VB_GENERAL, LOG_ERR, QString("IPTV # Failed to create sink: %1")
                .arg(_live_env->getResultMsg()));

        Medium::close(_source);
        _source = NULL;
        if (socket)
            delete socket;
        FreeEnv();

        return false;
    }

    _sink->startPlaying(*_source, NULL, NULL);
    vector<TSDataListener*>::iterator it = _listeners.begin();
    for (; it != _listeners.end(); ++it)
        _sink->AddListener(*it);

    LOG(VB_RECORD, LOG_INFO, LOC + "Open() -- end");

    return true;
}
コード例 #11
0
ファイル: MPIPTV_RTSP.cpp プロジェクト: BMOTech/MediaPortal-1
int CMPIPTV_RTSP::OpenConnection(void)
{
  this->logger.Log(LOGGER_INFO, METHOD_START_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME);
  int result = STATUS_OK;

  this->rtspClient = RTSPClient::createNew(*this->rtspEnvironment);
  result |= (this->rtspClient == NULL);

  if (result == STATUS_OK)
  {
    // RTSPClient works with char, not with TCHAR
    char *tempRtspUrl = ConvertToMultiByte(this->rtspUrl);
    result |= (tempRtspUrl == NULL);
    if (result == STATUS_OK)
    {
      char* optionsResult = this->rtspClient->sendOptionsCmd(tempRtspUrl, NULL, NULL, NULL, this->receiveDataTimeout / 2000);
      result |= (optionsResult == NULL);

      if (result != STATUS_OK)
      {
        TCHAR *message = FormatString(METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("error occured while sending OPTIONS command"));
        this->LogRtspMessage(LOGGER_ERROR, message);
        FREE_MEM(message);
      }
      else
      {
        TCHAR *message = FormatString(METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("OPTIONS result"));
        this->LogFullRtspMessage(LOGGER_VERBOSE, message, optionsResult);
        FREE_MEM(message);

        char *describeResult = this->rtspClient->describeURL(tempRtspUrl, NULL, FALSE, this->receiveDataTimeout / 2000);
        result |= (describeResult == NULL);

        if (result != STATUS_OK)
        {
          TCHAR *message = FormatString(METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("error occured while sending DESCRIBE command"));
          this->LogRtspMessage(LOGGER_ERROR, message);
          FREE_MEM(message);
        }
        else
        {
          TCHAR *message = FormatString(METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("DESCRIBE result"));
          this->LogFullRtspMessage(LOGGER_VERBOSE, message, describeResult);
          FREE_MEM(message);

          this->rtspSession = MediaSession::createNew(*this->rtspEnvironment, describeResult);
          result |= (this->rtspSession == NULL);

          if (result != STATUS_OK)
          {
            TCHAR *message = FormatString(METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("error occured while creating new session"));
            this->LogRtspMessage(LOGGER_ERROR, message);
            FREE_MEM(message);
          }
          else
          {
            result |= (!this->rtspSession->hasSubsessions());
            if (result != STATUS_OK)
            {
              this->logger.Log(LOGGER_ERROR, METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("session doesn't have subsessions"));
            }
            else
            {
              // Then, setup the "RTPSource"s for the session:
              MediaSubsessionIterator iter(*this->rtspSession);
              MediaSubsession *subsession = NULL;

              while ((result == STATUS_OK) && ((subsession = iter.next()) != NULL))
              {
                char *tempSubSessionName = (char *)subsession->mediumName();
                char *tempSubSessionCodecName = (char *)subsession->codecName();
#ifdef _MBCS
                TCHAR *subSessionName = ConvertToMultiByteA(tempSubSessionName);
                TCHAR *subSessionCodecName = ConvertToMultiByteA(tempSubSessionCodecName);
#else
                TCHAR *subSessionName = ConvertToUnicodeA(tempSubSessionName);
                TCHAR *subSessionCodecName = ConvertToUnicodeA(tempSubSessionCodecName);
#endif
                if (!subsession->initiate())
                {
                  result = STATUS_ERROR;
                  TCHAR *message = FormatString(_T("%s: %s: unable to create receiver for subsession '%s', codec '%s'"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, subSessionName, subSessionCodecName);
                  this->LogRtspMessage(LOGGER_ERROR, message);
                  FREE_MEM(message);
                }
                else
                {
                  this->logger.Log(LOGGER_VERBOSE, _T("%s: %s: created receiver for subsession '%s', codec '%s'"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, subSessionName, subSessionCodecName);

                  // set session ID, doesn't matter what
                  subsession->sessionId = tempSubSessionName;

                  if (subsession->rtpSource() != NULL)
                  {
                    // because we're saving the incoming data, rather than playing
                    // it in real time, allow an especially large time threshold
                    // (1 second) for reordering misordered incoming packets:
                    unsigned const thresh = 1000000; // 1 second
                    subsession->rtpSource()->setPacketReorderingThresholdTime(thresh);

                    // set the RTP source's OS socket buffer size as appropriate
                    int socketNum = subsession->rtpSource()->RTPgs()->socketNum();
                    unsigned int currentBufferSize = getReceiveBufferSize(*this->rtspEnvironment, socketNum);

                    if (this->defaultBufferSize > currentBufferSize)
                    {
                      setReceiveBufferTo(*this->rtspEnvironment, socketNum, this->defaultBufferSize);
                      unsigned setBufferSize = getReceiveBufferSize(*this->rtspEnvironment, socketNum);

                      if (setBufferSize == this->defaultBufferSize)
                      {
                        this->logger.Log(LOGGER_VERBOSE, _T("%s: %s: set buffer size for subsession '%s' successful, previous size: %i, requested size: %i, current size: %i"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, subSessionName, currentBufferSize, this->defaultBufferSize, setBufferSize);
                      }
                      else
                      {
                        result = STATUS_ERROR;
                        this->logger.Log(LOGGER_ERROR, _T("%s: %s: set buffer size for subsession '%s' failed, previous size: %i, requested size: %i, current size: %i"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, subSessionName, currentBufferSize, this->defaultBufferSize, setBufferSize);
                      }
                    }

                    if (_tcsncicmp(subSessionName, _T("audio"), 5) == 0)
                    {
                      // audio
                      this->logger.Log(LOGGER_VERBOSE, _T("%s: %s: audio subsession '%s'"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, subSessionName);
                      result |= (!rtspClient->setupMediaSubsession(*subsession));

                      if (result != STATUS_OK)
                      {
                        // error occured
                        TCHAR *message = FormatString(METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("error while setup subsession"));
                        this->LogRtspMessage(LOGGER_ERROR, message);
                        FREE_MEM(message);
                      }
                      else
                      {
                        this->logger.Log(LOGGER_WARNING, METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("subsession audio codec not supported"));
                      }
                    }
                    else if (_tcsncicmp(subSessionName, _T("video"), 5) == 0)
                    {
                      // video
                      this->logger.Log(LOGGER_VERBOSE, _T("%s: %s: video subsession '%s'"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, subSessionName);
                      result |= (!rtspClient->setupMediaSubsession(*subsession));

                      if (result != STATUS_OK)
                      {
                        // error occured
                        TCHAR *message = FormatString(METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("error while setup subsession"));
                        this->LogRtspMessage(LOGGER_ERROR, message);
                        FREE_MEM(message);
                      }
                      else
                      {
                        if (_tcsncicmp(subSessionCodecName, _T("MP2T"), 4) == 0)
                        {
                          // MPEG2 Transport Stream
                          // set new RTSP source
                          this->rtspSource = subsession->rtpSource();

                          if (subsession->rtcpInstance() != NULL)
                          {
                            this->logger.Log(LOGGER_VERBOSE, METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("set subsession 'Bye' handler"));
                            subsession->rtcpInstance()->setByeHandler(SubsessionByeHandler, this);
                          }
                        }
                        else if (_tcsncicmp(subSessionCodecName, _T("H264"), 4) == 0)
                        {
                          // H264 codec, HD TV
                          this->logger.Log(LOGGER_ERROR, METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("H264 not supported"));
                          result = STATUS_ERROR;
                        }
                        else
                        {
                          // SD TV
                          this->logger.Log(LOGGER_ERROR, METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("other subsession video codec than MP2T not supported"));
                          result = STATUS_ERROR;
                        }
                      }
                    }
                    else
                    {
                      this->logger.Log(LOGGER_WARNING, _T("%s: %s: unknown subsession '%s', ignored"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, subSessionName);
                    }
                  }
                  else
                  {
                    this->logger.Log(LOGGER_WARNING, _T("%s: %s: subsession '%s' doesn't have RTP source"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, subSessionName);
                  }
                }

                // free subsession name and codec name
                FREE_MEM(subSessionName);
                FREE_MEM(subSessionCodecName);
              }

              // we should have some RTSP source
              result |= (this->rtspSource == NULL);

              if (result == STATUS_OK)
              {
                result |= (!this->rtspClient->playMediaSession(*this->rtspSession));

                if (result != STATUS_OK)
                {
                  // error occured
                  TCHAR *message = FormatString(METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("error while playing session"));
                  this->LogRtspMessage(LOGGER_ERROR, message);
                  FREE_MEM(message);
                }
                else
                {
                  // create UDP socket and start playing
                  struct in_addr destinationAddress;
                  destinationAddress.s_addr = our_inet_addr("127.0.0.1");

                  unsigned int port = this->rtspUdpPortRangeStart;
                  do
                  {
                    this->logger.Log(LOGGER_VERBOSE, _T("%s: %s: UDP port %u"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, port);

                    // special construction force not reuse same UDP port
                    {
                      NoReuse noReuse;
                      this->rtspUdpGroupsock = new Groupsock(*this->rtspEnvironment, destinationAddress, port, 1);
                    }

                    if (this->rtspUdpGroupsock->socketNum() == (-1))
                    {
                      this->logger.Log(LOGGER_ERROR, _T("%s: %s: UDP port %u occupied, trying another port"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, port);
                      port++;
                      delete this->rtspUdpGroupsock;
                      this->rtspUdpGroupsock = NULL;
                    }
                  }
                  while ((this->rtspUdpGroupsock == NULL) && (port <= this->rtspUdpPortRangeEnd));

                  result |= (this->rtspUdpGroupsock == NULL);
                  if (result != STATUS_OK)
                  {
                    this->logger.Log(LOGGER_ERROR, METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("cannot create UDP sink, no free port"));
                  }
                  else
                  {
                    this->rtspUdpSink = BasicUDPSink::createNew(*this->rtspEnvironment, this->rtspUdpGroupsock, this->rtspUdpSinkMaxPayloadSize);
                    result |= (this->rtspUdpSink == NULL);

                    if (result != STATUS_OK)
                    {
                      TCHAR *message = FormatString(METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("cannot create UDP sink"));
                      this->LogRtspMessage(LOGGER_ERROR, message);
                      FREE_MEM(message);
                    }
                    else
                    {
                      if (this->rtspUdpSink->startPlaying(*this->rtspSource, NULL, NULL))
                      {
                        this->logger.Log(LOGGER_INFO, METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("playing started"));

                        // now create UDP connection
                        TCHAR *url = FormatString(_T("udp://@127.0.0.1:%u"), port);
                        result |= (url == NULL);

                        if (result == STATUS_OK)
                        {
                          // parse UDP url
                          // ParseURL calls ClearSession and IsConnected must return FALSE
                          // in another case will be current RTSP connection closed
                          result = this->CMPIPTV_UDP::ParseUrl(url, NULL);

                          if (result == STATUS_OK)
                          {
                            // connect to UDP url
                            result = this->CMPIPTV_UDP::OpenConnection();
                          }
                        }
                        FREE_MEM(url);
                      }
                      else
                      {
                        result = STATUS_ERROR;
                        TCHAR *message = FormatString(METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("error occured while starting playing"));
                        this->LogRtspMessage(LOGGER_ERROR, message);
                        FREE_MEM(message);
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }

      if (optionsResult != NULL)
      {
        delete[] optionsResult;
        optionsResult = NULL;
      }
    }
    FREE_MEM(tempRtspUrl);
  }

  if (result == STATUS_OK)
  {
    // start winsock worker thread
    this->rtspSchedulerThreadHandle = CreateThread( 
      NULL,                                   // default security attributes
      0,                                      // use default stack size  
      &CMPIPTV_RTSP::RtspSchedulerWorker,     // thread function name
      this,                                   // argument to thread function 
      0,                                      // use default creation flags 
      &this->rtspSchedulerThreadId);          // returns the thread identifier

    if (this->rtspSchedulerThreadHandle == NULL)
    {
      // thread not created
      result = STATUS_ERROR;
      this->logger.Log(LOGGER_ERROR, _T("%s: %s: cannot create RTSP scheduler thread, error: %i"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, GetLastError());
    }
  }

  if (result != STATUS_OK)
  {
    // if failed opening connection, than close connection
    this->CloseConnection();
  }

  this->logger.Log(LOGGER_INFO, (result == STATUS_OK) ? METHOD_END_FORMAT : METHOD_END_FAIL_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME);
  return (result == STATUS_OK) ? STATUS_OK : STATUS_ERROR;
}
コード例 #12
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;
}
コード例 #13
0
void RTSPServer::RTSPClientSession
::handleCmd_SETUP(char const* cseq,
		  char const* urlPreSuffix, char const* urlSuffix,
		  char const* fullRequestStr) {
	// "urlPreSuffix" should be the session (stream) name, and
	// "urlSuffix" should be the subsession (track) name.
  char const* streamName = urlPreSuffix;
  char const* trackId = urlSuffix;

	// Check whether we have existing session state, and, if so, whether it's
	// for the session that's named in "streamName".	(Note that we don't
	// support more than one concurrent session on the same client connection.) #####
  if (fOurServerMediaSession != NULL
			&& strcmp(streamName, fOurServerMediaSession->streamName()) != 0) {
	  fOurServerMediaSession = NULL;
	}
  if (fOurServerMediaSession == NULL) {
		// Set up this session's state.

		// Look up the "ServerMediaSession" object for the specified stream:
	  if (streamName[0] != '\0' ||
	fOurServer.lookupServerMediaSession("") != NULL) { // normal case
		} else { // weird case: there was no track id in the URL
		  streamName = urlSuffix;
		  trackId = NULL;
		}
	  fOurServerMediaSession = fOurServer.lookupServerMediaSession(streamName);
	  if (fOurServerMediaSession == NULL) {
		  handleCmd_notFound(cseq);
		  return;
		}

	  fOurServerMediaSession->incrementReferenceCount();

		// Set up our array of states for this session's subsessions (tracks):
	  reclaimStreamStates();
	  ServerMediaSubsessionIterator iter(*fOurServerMediaSession);
	  for (fNumStreamStates = 0; iter.next() != NULL; ++fNumStreamStates) {}
	  fStreamStates = new struct streamState[fNumStreamStates];
	  iter.reset();
	  ServerMediaSubsession* subsession;
	  for (unsigned i = 0; i < fNumStreamStates; ++i) {
		  subsession = iter.next();
		  fStreamStates[i].subsession = subsession;
		  fStreamStates[i].streamToken = NULL; // for now; reset by SETUP later
		}
	}

	// Look up information for the specified subsession (track):
  ServerMediaSubsession* subsession = NULL;
  unsigned streamNum;
  if (trackId != NULL && trackId[0] != '\0') { // normal case
	  for (streamNum = 0; streamNum < fNumStreamStates; ++streamNum) {
		  subsession = fStreamStates[streamNum].subsession;
		  if (subsession != NULL && strcmp(trackId, subsession->trackId()) == 0) break;
		}
	  if (streamNum >= fNumStreamStates) {
			// The specified track id doesn't exist, so this request fails:
		  handleCmd_notFound(cseq);
		  return;
		}
	} else {
		// Weird case: there was no track id in the URL.
		// This works only if we have only one subsession:
	  if (fNumStreamStates != 1) {
		  handleCmd_bad(cseq);
		  return;
		}
	  streamNum = 0;
	  subsession = fStreamStates[streamNum].subsession;
	}
	// ASSERT: subsession != NULL

	// Look for a "Transport:" header in the request string,
	// to extract client parameters:
  StreamingMode streamingMode;
  char* streamingModeString = NULL; // set when RAW_UDP streaming is specified
  char* clientsDestinationAddressStr;
  u_int8_t clientsDestinationTTL;
  portNumBits clientRTPPortNum, clientRTCPPortNum;
  unsigned char rtpChannelId, rtcpChannelId;
  parseTransportHeader(fullRequestStr, streamingMode, streamingModeString, fIsMulticast,
					 clientsDestinationAddressStr, clientsDestinationTTL,
					 clientRTPPortNum, clientRTCPPortNum,
					 rtpChannelId, rtcpChannelId);
  if (streamingMode == RTP_TCP && rtpChannelId == 0xFF) {
		// TCP streaming was requested, but with no "interleaving=" fields.
		// (QuickTime Player sometimes does this.)  Set the RTP and RTCP channel ids to
		// proper values:
	  rtpChannelId = fTCPStreamIdCount; rtcpChannelId = fTCPStreamIdCount+1;
	}
  fTCPStreamIdCount += 2;

  Port clientRTPPort(clientRTPPortNum);
  Port clientRTCPPort(clientRTCPPortNum);

	// Next, check whether a "Range:" header is present in the request.
	// This isn't legal, but some clients do this to combine "SETUP" and "PLAY":
  double rangeStart = 0.0, rangeEnd = 0.0;
  fStreamAfterSETUP = parseRangeHeader(fullRequestStr, rangeStart, rangeEnd) ||
										  parsePlayNowHeader(fullRequestStr);

	// Then, get server parameters from the 'subsession':
  int tcpSocketNum = streamingMode == RTP_TCP ? fClientSocket : -1;
  netAddressBits destinationAddress = 0;
  u_int8_t destinationTTL = 5;
#ifdef RTSP_ALLOW_CLIENT_DESTINATION_SETTING
  if (clientsDestinationAddressStr != NULL) {
		// Use the client-provided "destination" address.
		// Note: This potentially allows the server to be used in denial-of-service
		// attacks, so don't enable this code unless you're sure that clients are
		// trusted.
	  destinationAddress = our_inet_addr(clientsDestinationAddressStr);
	}
	// Also use the client-provided TTL.
  destinationTTL = clientsDestinationTTL;
#endif
  delete[] clientsDestinationAddressStr;
  Port serverRTPPort(0);
  Port serverRTCPPort(0);
  subsession->getStreamParameters(fOurSessionId, fClientAddr.sin_addr.s_addr,
				  clientRTPPort, clientRTCPPort,
				  tcpSocketNum, rtpChannelId, rtcpChannelId,
				  destinationAddress, destinationTTL, fIsMulticast,
				  serverRTPPort, serverRTCPPort,
				  fStreamStates[streamNum].streamToken);
  struct in_addr destinationAddr; destinationAddr.s_addr = destinationAddress;
  char* destAddrStr = strDup(our_inet_ntoa(destinationAddr));
  struct sockaddr_in sourceAddr; SOCKLEN_T namelen = sizeof sourceAddr;
  getsockname(fClientSocket, (struct sockaddr*)&sourceAddr, &namelen);
  char* sourceAddrStr = strDup(our_inet_ntoa(sourceAddr.sin_addr));
  if (fIsMulticast) {
	  switch (streamingMode) {
	  case RTP_UDP:
			  snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
								 "RTSP/1.0 200 OK\r\n"
								 "CSeq: %s\r\n"
								 "%s"
								 "Transport: RTP/AVP;multicast;destination=%s;source=%s;port=%d-%d;ttl=%d\r\n"
								 "Session: %08X\r\n\r\n",
								 cseq,
								 dateHeader(),
								 destAddrStr, sourceAddrStr, ntohs(serverRTPPort.num()), ntohs(serverRTCPPort.num()), destinationTTL,
								 fOurSessionId);
			  break;
	  case RTP_TCP:
				// multicast streams can't be sent via TCP
			  handleCmd_unsupportedTransport(cseq);
			  break;
	  case RAW_UDP:
			  snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
								 "RTSP/1.0 200 OK\r\n"
								 "CSeq: %s\r\n"
								 "%s"
								 "Transport: %s;multicast;destination=%s;source=%s;port=%d;ttl=%d\r\n"
								 "Session: %08X\r\n\r\n",
								 cseq,
								 dateHeader(),
								 streamingModeString, destAddrStr, sourceAddrStr, ntohs(serverRTPPort.num()), destinationTTL,
								 fOurSessionId);
			  break;
		}
	} else {
	  switch (streamingMode) {
	  case RTP_UDP: {
		  snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
				 "RTSP/1.0 200 OK\r\n"
				 "CSeq: %s\r\n"
				 "%s"
				 "Transport: RTP/AVP;unicast;destination=%s;source=%s;client_port=%d-%d;server_port=%d-%d\r\n"
				 "Session: %08X\r\n\r\n",
				 cseq,
				 dateHeader(),
				 destAddrStr, sourceAddrStr, ntohs(clientRTPPort.num()), ntohs(clientRTCPPort.num()), ntohs(serverRTPPort.num()), ntohs(serverRTCPPort.num()),
				 fOurSessionId);
		  break;
		}
	  case RTP_TCP: {
		  snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
				 "RTSP/1.0 200 OK\r\n"
				 "CSeq: %s\r\n"
				 "%s"
				 "Transport: RTP/AVP/TCP;unicast;destination=%s;source=%s;interleaved=%d-%d\r\n"
				 "Session: %08X\r\n\r\n",
				 cseq,
				 dateHeader(),
				 destAddrStr, sourceAddrStr, rtpChannelId, rtcpChannelId,
				 fOurSessionId);
		  break;
		}
	  case RAW_UDP: {
		  snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
				 "RTSP/1.0 200 OK\r\n"
				 "CSeq: %s\r\n"
				 "%s"
				 "Transport: %s;unicast;destination=%s;source=%s;client_port=%d;server_port=%d\r\n"
				 "Session: %08X\r\n\r\n",
				 cseq,
				 dateHeader(),
				 streamingModeString, destAddrStr, sourceAddrStr, ntohs(clientRTPPort.num()), ntohs(serverRTPPort.num()),
				 fOurSessionId);
		  break;
		}
		}
	}
  delete[] destAddrStr; delete[] sourceAddrStr; delete[] streamingModeString;
}
コード例 #14
0
ファイル: MPIPTV_RTSP.cpp プロジェクト: Azzuro/MediaPortal-1
int CMPIPTV_RTSP::OpenConnection(void)
{
  this->logger.Log(LOGGER_INFO, METHOD_START_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME);
  this->isRtspSessionSetup = false;

  // LIVE555 works with char, not with TCHAR
  char *tempRtspUrl = ConvertToMultiByte(this->rtspUrl);
  if (tempRtspUrl == NULL)
  {
    return STATUS_ERROR;
  }

  // start LIVE555 worker thread
  this->rtspSchedulerThreadHandle = CreateThread( 
    NULL,                                   // default security attributes
    0,                                      // use default stack size  
    &CMPIPTV_RTSP::RtspSchedulerWorker,     // thread function name
    this,                                   // argument to thread function 
    0,                                      // use default creation flags 
    &this->rtspSchedulerThreadId);          // returns the thread identifier
  if (this->rtspSchedulerThreadHandle == NULL)
  {
    this->logger.Log(LOGGER_ERROR, _T("%s: %s: failed to create RTSP scheduler thread, error = %i"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, GetLastError());
    return STATUS_ERROR;
  }

  this->rtspClient = MPRTSPClient::createNew(this, *this->rtspEnvironment, tempRtspUrl);
  FREE_MEM(tempRtspUrl);
  if (
    this->rtspClient == NULL ||
    SendRtspCommand(METHOD_OPEN_CONNECTION_NAME, _T("OPTIONS")) != STATUS_OK ||
    SendRtspCommand(METHOD_OPEN_CONNECTION_NAME, _T("DESCRIBE")) != STATUS_OK
  )
  {
    CloseConnection();
    return STATUS_ERROR;
  }

  this->rtspSession = MediaSession::createNew(*this->rtspEnvironment, this->rtspResponseResultString);
  if (this->rtspSession == NULL || !this->rtspSession->hasSubsessions())
  {
    this->LogRtspMessage(LOGGER_ERROR, METHOD_OPEN_CONNECTION_NAME, this->rtspSession == NULL ? _T("failed to create session") : _T("session doesn't have sub-sessions"));
    CloseConnection();
    return STATUS_ERROR;
  }

  // Setup the RTP source for the session. Only one sub-session expected/supported.
  MediaSubsessionIterator iter(*this->rtspSession);
  MediaSubsession *subsession = NULL;
  FramedSource *rtspSource = NULL;
  while ((subsession = iter.next()) != NULL)
  {
#ifdef _MBCS
    TCHAR *subSessionName = ConvertToMultiByteA(subsession->mediumName());
    TCHAR *subSessionCodecName = ConvertToMultiByteA(subsession->codecName());
#else
    TCHAR *subSessionName = ConvertToUnicodeA(subsession->mediumName());
    TCHAR *subSessionCodecName = ConvertToUnicodeA(subsession->codecName());
#endif

    if (_tcsncicmp(subSessionName, _T("video"), 5) != 0 || _tcsncicmp(subSessionCodecName, _T("MP2T"), 4) != 0)
    {
      TCHAR *message = FormatString(_T("sub-session medium or codec not supported, medium = %s, codec = %s"), subSessionName, subSessionCodecName);
      this->LogRtspMessage(LOGGER_ERROR, METHOD_OPEN_CONNECTION_NAME, message);
      FREE_MEM(message);
      FREE_MEM(subSessionName);
      FREE_MEM(subSessionCodecName);
      continue;
    }

    // If a client port is configured, find a free pair of ports in the range.
    // The first port is used for RTP; the second port is used for RTCP. Once
    // we find one free port, we assume the next one is also free.
    if (this->rtspRtpClientPortRangeStart > 0)
    {
      struct in_addr destinationAddress;
      destinationAddress.s_addr = our_inet_addr("127.0.0.1");
      unsigned int port = this->rtspRtpClientPortRangeStart;
      Groupsock *groupsock = NULL;
      do
      {
        this->logger.Log(LOGGER_VERBOSE, _T("%s: %s: RTP client port %u"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, port);

        // special construction force not reuse same UDP port
        {
          NoReuse noReuse(*this->rtspEnvironment);
          groupsock = new Groupsock(*this->rtspEnvironment, destinationAddress, port, 1);
        }

        if (groupsock == NULL || groupsock->socketNum() == -1)
        {
          this->logger.Log(LOGGER_WARNING, _T("%s: %s: RTP client port %u occupied, trying next even port"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, port);
          port += 2;
          if (groupsock != NULL)
          {
            delete groupsock;
            groupsock = NULL;
          }
        }
      }
      while ((groupsock == NULL) && (port <= this->rtspRtpClientPortRangeEnd));
      // Did we find a free port? If not, we fall back to a random port chosen
      // by LIVE555.
      if (groupsock != NULL)
      {
        delete groupsock;
        groupsock = NULL;
        subsession->setClientPortNum(port);
      }
    }

    if (!subsession->initiate() || subsession->rtpSource() == NULL)
    {
      TCHAR *message = FormatString(_T("failed to create receiver for sub-session, medium = %s, codec = %s"), subSessionName, subSessionCodecName);
      this->LogRtspMessage(LOGGER_ERROR, METHOD_OPEN_CONNECTION_NAME, message);
      FREE_MEM(message);
      FREE_MEM(subSessionName);
      FREE_MEM(subSessionCodecName);
      continue;
    }

    this->logger.Log(LOGGER_VERBOSE, _T("%s: %s: created receiver for sub-session, medium = %s, codec = %s"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, subSessionName, subSessionCodecName);
    FREE_MEM(subSessionName);
    FREE_MEM(subSessionCodecName);

    // set session ID, doesn't matter what
    subsession->setSessionId(subsession->mediumName());

    // because we're saving the incoming data, rather than playing
    // it in real time, allow an especially large time threshold
    // for reordering misordered incoming packets:
    subsession->rtpSource()->setPacketReorderingThresholdTime(1000000); // 1 second

    // set the RTP source's OS socket buffer size as appropriate
    int socketNum = subsession->rtpSource()->RTPgs()->socketNum();
    unsigned int currentBufferSize = getReceiveBufferSize(*this->rtspEnvironment, socketNum);
    if (this->defaultBufferSize > currentBufferSize)
    {
      setReceiveBufferTo(*this->rtspEnvironment, socketNum, this->defaultBufferSize);
      unsigned setBufferSize = getReceiveBufferSize(*this->rtspEnvironment, socketNum);
      if (setBufferSize == this->defaultBufferSize)
      {
        this->logger.Log(LOGGER_VERBOSE, _T("%s: %s: set buffer size for sub-session, previous size = %i, requested size = %i, current size = %i"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, subSessionName, currentBufferSize, this->defaultBufferSize, setBufferSize);
      }
      else
      {
        this->logger.Log(LOGGER_WARNING, _T("%s: %s: failed to set buffer size for sub-session, previous size = %i, requested size = %i, current size = %i"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, subSessionName, currentBufferSize, this->defaultBufferSize, setBufferSize);
      }
    }

    if (SendRtspCommand(METHOD_OPEN_CONNECTION_NAME, _T("SETUP"), subsession) != STATUS_OK)
    {
      CloseConnection();
      return STATUS_ERROR;
    }
    rtspSource = subsession->rtpSource();
    break;
  }

  // If we don't have an RTSP source then we can't continue.
  if (rtspSource == NULL)
  {
    CloseConnection();
    return STATUS_ERROR;
  }

  this->isRtspSessionSetup = true;
  if (SendRtspCommand(METHOD_OPEN_CONNECTION_NAME, _T("PLAY")) != STATUS_OK)
  {
    CloseConnection();
    return STATUS_ERROR;
  }

  // create UDP socket and start playing
  struct in_addr destinationAddress;
  destinationAddress.s_addr = our_inet_addr("127.0.0.1");

  unsigned int port = this->rtspUdpPortRangeStart;
  do
  {
    this->logger.Log(LOGGER_VERBOSE, _T("%s: %s: UDP port %u"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, port);

    // special construction force not reuse same UDP port
    {
      NoReuse noReuse(*this->rtspEnvironment);
      this->rtspUdpGroupsock = new Groupsock(*this->rtspEnvironment, destinationAddress, port, 1);
    }

    if (this->rtspUdpGroupsock == NULL || this->rtspUdpGroupsock->socketNum() == -1)
    {
      this->logger.Log(LOGGER_WARNING, _T("%s: %s: UDP port %u occupied, trying another port"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, port);
      port++;
      if (this->rtspUdpGroupsock != NULL)
      {
        delete this->rtspUdpGroupsock;
        this->rtspUdpGroupsock = NULL;
      }
    }
  }
  while ((this->rtspUdpGroupsock == NULL) && (port <= this->rtspUdpPortRangeEnd));

  if (this->rtspUdpGroupsock == NULL)
  {
    this->logger.Log(LOGGER_ERROR, METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("failed to create UDP socket, no free port"));
    CloseConnection();
    return STATUS_ERROR;
  }

  this->rtspUdpSink = BasicUDPSink::createNew(*this->rtspEnvironment, this->rtspUdpGroupsock, this->rtspUdpSinkMaxPayloadSize);
  if (this->rtspUdpSink == NULL)
  {
    this->logger.Log(LOGGER_ERROR, METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("failed to create UDP sink"));
    CloseConnection();
    return STATUS_ERROR;
  }

  if (!this->rtspUdpSink->startPlaying(*rtspSource, NULL, NULL))
  {
    this->LogRtspMessage(LOGGER_ERROR, METHOD_OPEN_CONNECTION_NAME, _T("failed to start UDP sink"));
    CloseConnection();
    return STATUS_ERROR;
  }

  this->logger.Log(LOGGER_INFO, METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("streaming started"));

  // create a UDP connection to the local stream
  TCHAR *url = FormatString(_T("udp://@127.0.0.1:%u"), port);
  if (
    url == NULL ||
    this->CMPIPTV_UDP::ParseUrl(url, NULL) != STATUS_OK ||
    this->CMPIPTV_UDP::OpenConnection() != STATUS_OK
  )
  {
    FREE_MEM(url);
    this->logger.Log(LOGGER_INFO, METHOD_END_FAIL_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME);
    CloseConnection();
    return STATUS_ERROR;
  }

  FREE_MEM(url);
  this->logger.Log(LOGGER_INFO, METHOD_END_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME);
  return STATUS_OK;
}
コード例 #15
0
void startReplicaFileSink(StreamReplicator* replicator, char const* outputFileName); // forward

int main(int argc, char** argv) {
  // Begin by setting up our usage environment:
  TaskScheduler* scheduler = BasicTaskScheduler::createNew();
  env = BasicUsageEnvironment::createNew(*scheduler);

  // Create a 'groupsock' for the input multicast group,port:
  char const* inputAddressStr
#ifdef USE_SSM
    = "232.255.42.42";
#else
    = "239.255.42.42";
#endif
  struct in_addr inputAddress;
  inputAddress.s_addr = our_inet_addr(inputAddressStr);

  Port const inputPort(8888);
  unsigned char const inputTTL = 0; // we're only reading from this mcast group

#ifdef USE_SSM
  char* sourceAddressStr = "aaa.bbb.ccc.ddd";
                           // replace this with the real source address
  struct in_addr sourceFilterAddress;
  sourceFilterAddress.s_addr = our_inet_addr(sourceAddressStr);

  Groupsock inputGroupsock(*env, inputAddress, sourceFilterAddress, inputPort);
#else
  Groupsock inputGroupsock(*env, inputAddress, inputPort, inputTTL);
#endif