void PassiveServerMediaSubsession::startStream(unsigned clientSessionId,
					       void* /*streamToken*/,
					       TaskFunc* rtcpRRHandler,
					       void* rtcpRRHandlerClientData,
					       unsigned short& rtpSeqNum,
					       unsigned& rtpTimestamp,
					       ServerRequestAlternativeByteHandler* /*serverRequestAlternativeByteHandler*/,
					       void* /*serverRequestAlternativeByteHandlerClientData*/) {
  rtpSeqNum = fRTPSink.currentSeqNo();
  rtpTimestamp = fRTPSink.presetNextTimestamp();

  // Try to use a big send buffer for RTP -  at least 0.1 second of
  // specified bandwidth and at least 50 KB
  unsigned streamBitrate = fRTCPInstance == NULL ? 50 : fRTCPInstance->totSessionBW(); // in kbps
  unsigned rtpBufSize = streamBitrate * 25 / 2; // 1 kbps * 0.1 s = 12.5 bytes
  if (rtpBufSize < 50 * 1024) rtpBufSize = 50 * 1024;
  increaseSendBufferTo(envir(), fRTPSink.groupsockBeingUsed().socketNum(), rtpBufSize);

  // Set up the handler for incoming RTCP "RR" packets from this client:
  if (fRTCPInstance != NULL) {
    RTCPSourceRecord* source = (RTCPSourceRecord*)(fClientRTCPSourceRecords->Lookup((char const*)clientSessionId));
    if (source != NULL) {
      fRTCPInstance->setSpecificRRHandler(source->addr, source->port,
					  rtcpRRHandler, rtcpRRHandlerClientData);
    }
  }
}
Exemplo n.º 2
0
int HTTPSink::setUpOurSocket(UsageEnvironment& env, Port& ourPort) {
  int ourSocket = -1;

  do {
    ourSocket = setupStreamSocket(env, ourPort);
    if (ourSocket < 0) break;

    // Make sure we have a big send buffer:
    if (!increaseSendBufferTo(env, ourSocket, 50*1024)) break;

    if (listen(ourSocket, 1) < 0) { // we allow only one connection
      env.setResultErrMsg("listen() failed: ");
      break;
    }

    if (ourPort.num() == 0) {
      // bind() will have chosen a port for us; return it also:
      if (!getSourcePort(env, ourSocket, ourPort)) break;
    }

    return ourSocket;
  } while (0);

  if (ourSocket != -1) ::closeSocket(ourSocket);
  return -1;
}
Exemplo n.º 3
0
int GenericMediaServer::setUpOurSocket(UsageEnvironment& env, Port& ourPort) {
  int ourSocket = -1;

  do {
    // The following statement is enabled by default.
    // Don't disable it (by defining ALLOW_SERVER_PORT_REUSE) unless you know what you're doing.
#if !defined(ALLOW_SERVER_PORT_REUSE) && !defined(ALLOW_RTSP_SERVER_PORT_REUSE)
    // ALLOW_RTSP_SERVER_PORT_REUSE is for backwards-compatibility #####
    NoReuse dummy(env); // Don't use this socket if there's already a local server using it
#endif

    ourSocket = setupStreamSocket(env, ourPort);
    if (ourSocket < 0) break;

    // Make sure we have a big send buffer:
    if (!increaseSendBufferTo(env, ourSocket, 50*1024)) break;

    // Allow multiple simultaneous connections:
    if (listen(ourSocket, LISTEN_BACKLOG_SIZE) < 0) {
      env.setResultErrMsg("listen() failed: ");
      break;
    }

    if (ourPort.num() == 0) {
      // bind() will have chosen a port for us; return it also:
      if (!getSourcePort(env, ourSocket, ourPort)) break;
    }

    return ourSocket;
  } while (0);

  if (ourSocket != -1) ::closeSocket(ourSocket);
  return -1;
}
Exemplo n.º 4
0
void RTSPServer::incomingConnectionHandler1() {
  struct sockaddr_in clientAddr;
  SOCKLEN_T clientAddrLen = sizeof clientAddr;
//  printf("incomingConnectionHandler1\n");	//jay
  int clientSocket = accept(fServerSocket, (struct sockaddr*)&clientAddr,
					&clientAddrLen);
  if (clientSocket < 0) {
	  int err = envir().getErrno();
	  if (err != EWOULDBLOCK) {
			  envir().setResultErrMsg("accept() failed: ");
		}
	  return;
	}
  makeSocketNonBlocking(clientSocket);
  increaseSendBufferTo(envir(), clientSocket, 50*1024);

#if defined(DEBUG) || defined(DEBUG_CONNECTIONS)
  envir() << "accept()ed connection from " << our_inet_ntoa(clientAddr.sin_addr) << '\n';
#endif

	// Create a new object for this RTSP session.
	// (Choose a random 32-bit integer for the session id (it will be encoded as a 8-digit hex number).  We don't bother checking for
	//  a collision; the probability of two concurrent sessions getting the same session id is very low.)
  unsigned sessionId = (unsigned)our_random();
	(void)createNewClientSession(sessionId, clientSocket, clientAddr);
}
Exemplo n.º 5
0
int RTSPServer::setUpOurSocket(UsageEnvironment& env, Port& ourPort) {
  int ourSocket = -1;

  do {
	  ourSocket = setupStreamSocket(env, ourPort);
	  if (ourSocket < 0) break;

		// Make sure we have a big send buffer:
	  if (!increaseSendBufferTo(env, ourSocket, 50*1024)) break;

		// Allow multiple simultaneous connections:
	  if (listen(ourSocket, LISTEN_BACKLOG_SIZE) < 0) {
		  env.setResultErrMsg("listen() failed: ");
		  break;
		}

	  if (ourPort.num() == 0) {
			// bind() will have chosen a port for us; return it also:
		  if (!getSourcePort(env, ourSocket, ourPort)) break;
		}

	  return ourSocket;
	} while (0);

  if (ourSocket != -1) ::closeSocket(ourSocket);
  return -1;
}
Exemplo n.º 6
0
void GenericMediaServer::incomingConnectionHandlerOnSocket(int serverSocket) {
  struct sockaddr_in clientAddr;
  SOCKLEN_T clientAddrLen = sizeof clientAddr;
  int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrLen);
  if (clientSocket < 0) {
    int err = envir().getErrno();
    if (err != EWOULDBLOCK) {
      envir().setResultErrMsg("accept() failed: ");
    }
    return;
  }
  ignoreSigPipeOnSocket(clientSocket); // so that clients on the same host that are killed don't also kill us
  makeSocketNonBlocking(clientSocket);
  increaseSendBufferTo(envir(), clientSocket, 50*1024);

#ifdef DEBUG
  envir() << "accept()ed connection from " << AddressString(clientAddr).val() << "\n";
#endif

  // Create a new object for handling this connection:
  (void)createNewClientConnection(clientSocket, clientAddr);
}
Exemplo n.º 7
0
void RTSPServer::incomingConnectionHandler1() {
  struct sockaddr_in clientAddr;
  SOCKLEN_T clientAddrLen = sizeof clientAddr;
  int clientSocket = accept(fServerSocket, (struct sockaddr*)&clientAddr,
			    &clientAddrLen);
  if (clientSocket < 0) {
    int err = envir().getErrno();
    if (err != EWOULDBLOCK) {
        envir().setResultErrMsg("accept() failed: ");
    }
    return;
  }
  makeSocketNonBlocking(clientSocket);
  increaseSendBufferTo(envir(), clientSocket, 50*1024);

#if defined(DEBUG) || defined(DEBUG_CONNECTIONS)
  fprintf(stderr, "accept()ed connection from %s\n", our_inet_ntoa(clientAddr.sin_addr));
#endif

  // Create a new object for this RTSP session:
  new RTSPClientSession(*this, ++fSessionIdCounter,
			clientSocket, clientAddr);
}
Exemplo n.º 8
0
  void handleResponse(int resultCode, char* resultString) {
    if (resultCode == 0) {
      // The "REGISTER" request succeeded, so use the still-open RTSP socket to await incoming commands from the remote endpoint:
      int sock;
      struct sockaddr_in remoteAddress;

      grabConnection(sock, remoteAddress);
      if (sock >= 0) {
	increaseSendBufferTo(envir(), sock, 50*1024); // in anticipation of streaming over it
	(void)fOurServer.createNewClientConnection(sock, remoteAddress);
      }
    }

    if (fResponseHandler != NULL) {
      // Call our (REGISTER-specific) response handler now:
      (*fResponseHandler)(&fOurServer, fRequestId, resultCode, resultString);
    } else {
      // We need to delete[] "resultString" before we leave:
      delete[] resultString;
    }

    // We're completely done with the REGISTER command now, so delete ourself now:
    delete this;
  }
void OnDemandServerMediaSubsession
::getStreamParameters(unsigned clientSessionId,
		      netAddressBits clientAddress,
		      Port const& clientRTPPort,
		      Port const& clientRTCPPort,
		      int tcpSocketNum,
		      unsigned char rtpChannelId,
		      unsigned char rtcpChannelId,
		      netAddressBits& destinationAddress,
		      u_int8_t& /*destinationTTL*/,
		      Boolean& isMulticast,
		      Port& serverRTPPort,
		      Port& serverRTCPPort,
		      void*& streamToken) {
  if (destinationAddress == 0) destinationAddress = clientAddress;
  struct in_addr destinationAddr; destinationAddr.s_addr = destinationAddress;
  isMulticast = False;

  if (fLastStreamToken != NULL && fReuseFirstSource) {
    // Special case: Rather than creating a new 'StreamState',
    // we reuse the one that we've already created:
    serverRTPPort = ((StreamState*)fLastStreamToken)->serverRTPPort();
    serverRTCPPort = ((StreamState*)fLastStreamToken)->serverRTCPPort();
    ++((StreamState*)fLastStreamToken)->referenceCount();
    streamToken = fLastStreamToken;
  } else {
    // Normal case: Create a new media source:
    unsigned streamBitrate;
    FramedSource* mediaSource
      = createNewStreamSource(clientSessionId, streamBitrate);

    // Create 'groupsock' and 'sink' objects for the destination,
    // using previously unused server port numbers:
    RTPSink* rtpSink;
    BasicUDPSink* udpSink;
    Groupsock* rtpGroupsock;
    Groupsock* rtcpGroupsock;
    portNumBits serverPortNum;
    if (clientRTCPPort.num() == 0) {
      // We're streaming raw UDP (not RTP). Create a single groupsock:
      NoReuse dummy(envir()); // ensures that we skip over ports that are already in use
      for (serverPortNum = fInitialPortNum; ; ++serverPortNum) {
	struct in_addr dummyAddr; dummyAddr.s_addr = 0;

	serverRTPPort = serverPortNum;
	rtpGroupsock = new Groupsock(envir(), dummyAddr, serverRTPPort, 255);
	if (rtpGroupsock->socketNum() >= 0) break; // success
      }

      rtcpGroupsock = NULL;
      rtpSink = NULL;
      udpSink = BasicUDPSink::createNew(envir(), rtpGroupsock);
    } else {
      // Normal case: We're streaming RTP (over UDP or TCP).  Create a pair of
      // groupsocks (RTP and RTCP), with adjacent port numbers (RTP port number even):
      NoReuse dummy(envir()); // ensures that we skip over ports that are already in use
      for (portNumBits serverPortNum = fInitialPortNum; ; serverPortNum += 2) {
	struct in_addr dummyAddr; dummyAddr.s_addr = 0;

	serverRTPPort = serverPortNum;
	rtpGroupsock = new Groupsock(envir(), dummyAddr, serverRTPPort, 255);
	if (rtpGroupsock->socketNum() < 0) {
	  delete rtpGroupsock;
	  continue; // try again
	}

	serverRTCPPort = serverPortNum+1;
	rtcpGroupsock = new Groupsock(envir(), dummyAddr, serverRTCPPort, 255);
	if (rtcpGroupsock->socketNum() < 0) {
	  delete rtpGroupsock;
	  delete rtcpGroupsock;
	  continue; // try again
	}

	break; // success
      }

      unsigned char rtpPayloadType = 96 + trackNumber()-1; // if dynamic
      rtpSink = createNewRTPSink(rtpGroupsock, rtpPayloadType, mediaSource);
      udpSink = NULL;
    }

    // Turn off the destinations for each groupsock.  They'll get set later
    // (unless TCP is used instead):
    if (rtpGroupsock != NULL) rtpGroupsock->removeAllDestinations();
    if (rtcpGroupsock != NULL) rtcpGroupsock->removeAllDestinations();

    if (rtpGroupsock != NULL) {
      // Try to use a big send buffer for RTP -  at least 0.1 second of
      // specified bandwidth and at least 50 KB
      unsigned rtpBufSize = streamBitrate * 25 / 2; // 1 kbps * 0.1 s = 12.5 bytes
      if (rtpBufSize < 50 * 1024) rtpBufSize = 50 * 1024;
      increaseSendBufferTo(envir(), rtpGroupsock->socketNum(), rtpBufSize);
    }

    // Set up the state of the stream.  The stream will get started later:
    streamToken = fLastStreamToken
      = new StreamState(*this, serverRTPPort, serverRTCPPort, rtpSink, udpSink,
			streamBitrate, mediaSource,
			rtpGroupsock, rtcpGroupsock);
  }

  // Record these destinations as being for this client session id:
  Destinations* destinations;
  if (tcpSocketNum < 0) { // UDP
    destinations = new Destinations(destinationAddr, clientRTPPort, clientRTCPPort);
  } else { // TCP
    destinations = new Destinations(tcpSocketNum, rtpChannelId, rtcpChannelId);
  }
  fDestinationsHashTable->Add((char const*)clientSessionId, destinations);
}
Exemplo n.º 10
0
Boolean DarwinInjector
::setDestination(char const* remoteRTSPServerNameOrAddress,
		 char const* remoteFileName,
		 char const* sessionName,
		 char const* sessionInfo,
		 portNumBits remoteRTSPServerPortNumber,
		 char const* remoteUserName,
		 char const* remotePassword,
		 char const* sessionAuthor,
		 char const* sessionCopyright,
		 int timeout) {
  char* sdp = NULL;
  char* url = NULL;
  Boolean success = False; // until we learn otherwise

  do {
    // Construct a RTSP URL for the remote stream:
    char const* const urlFmt = "rtsp://%s:%u/%s";
    unsigned urlLen
      = strlen(urlFmt) + strlen(remoteRTSPServerNameOrAddress) + 5 /* max short len */ + strlen(remoteFileName);
    url = new char[urlLen];
    sprintf(url, urlFmt, remoteRTSPServerNameOrAddress, remoteRTSPServerPortNumber, remoteFileName);

    // Begin by creating our RTSP client object:
    fRTSPClient = new RTSPClientForDarwinInjector(envir(), url, fVerbosityLevel, fApplicationName, this);
    if (fRTSPClient == NULL) break;

    // Get the remote RTSP server's IP address:
    struct in_addr addr;
    {
      NetAddressList addresses(remoteRTSPServerNameOrAddress);
      if (addresses.numAddresses() == 0) break;
      NetAddress const* address = addresses.firstAddress();
      addr.s_addr = *(unsigned*)(address->data());
    }
    AddressString remoteRTSPServerAddressStr(addr);

    // Construct a SDP description for the session that we'll be streaming:
    char const* const sdpFmt =
      "v=0\r\n"
      "o=- %u %u IN IP4 127.0.0.1\r\n"
      "s=%s\r\n"
      "i=%s\r\n"
      "c=IN IP4 %s\r\n"
      "t=0 0\r\n"
      "a=x-qt-text-nam:%s\r\n"
      "a=x-qt-text-inf:%s\r\n"
      "a=x-qt-text-cmt:source application:%s\r\n"
      "a=x-qt-text-aut:%s\r\n"
      "a=x-qt-text-cpy:%s\r\n";
      // plus, %s for each substream SDP
    unsigned sdpLen = strlen(sdpFmt)
      + 20 /* max int len */ + 20 /* max int len */
      + strlen(sessionName)
      + strlen(sessionInfo)
      + strlen(remoteRTSPServerAddressStr.val())
      + strlen(sessionName)
      + strlen(sessionInfo)
      + strlen(fApplicationName)
      + strlen(sessionAuthor)
      + strlen(sessionCopyright)
      + fSubstreamSDPSizes;
    unsigned const sdpSessionId = our_random32();
    unsigned const sdpVersion = sdpSessionId;
    sdp = new char[sdpLen];
    sprintf(sdp, sdpFmt,
	    sdpSessionId, sdpVersion, // o= line
	    sessionName, // s= line
	    sessionInfo, // i= line
	    remoteRTSPServerAddressStr.val(), // c= line
	    sessionName, // a=x-qt-text-nam: line
	    sessionInfo, // a=x-qt-text-inf: line
	    fApplicationName, // a=x-qt-text-cmt: line
	    sessionAuthor, // a=x-qt-text-aut: line
	    sessionCopyright // a=x-qt-text-cpy: line
	    );
    char* p = &sdp[strlen(sdp)];
    SubstreamDescriptor* ss;
    for (ss = fHeadSubstream; ss != NULL; ss = ss->next()) {
      sprintf(p, "%s", ss->sdpLines());
      p += strlen(p);
    }

    // Do a RTSP "ANNOUNCE" with this SDP description:
    Authenticator auth;
    Authenticator* authToUse = NULL;
    if (remoteUserName[0] != '\0' || remotePassword[0] != '\0') {
      auth.setUsernameAndPassword(remoteUserName, remotePassword);
      authToUse = &auth;
    }
    fWatchVariable = 0;
    (void)fRTSPClient->sendAnnounceCommand(sdp, genericResponseHandler, authToUse);

    // Now block (but handling events) until we get a response:
    envir().taskScheduler().doEventLoop(&fWatchVariable);

    delete[] fResultString;
    if (fResultCode != 0) break; // an error occurred with the RTSP "ANNOUNCE" command

    // Next, tell the remote server to start receiving the stream from us.
    // (To do this, we first create a "MediaSession" object from the SDP description.)
    fSession = MediaSession::createNew(envir(), sdp);
    if (fSession == NULL) break;

    ss = fHeadSubstream;
    MediaSubsessionIterator iter(*fSession);
    MediaSubsession* subsession;
    ss = fHeadSubstream;
    unsigned streamChannelId = 0;
    while ((subsession = iter.next()) != NULL) {
      if (!subsession->initiate()) break;

      fWatchVariable = 0;
      (void)fRTSPClient->sendSetupCommand(*subsession, genericResponseHandler,
					  True /*streamOutgoing*/,
					  True /*streamUsingTCP*/);
      // Now block (but handling events) until we get a response:
      envir().taskScheduler().doEventLoop(&fWatchVariable);

      delete[] fResultString;
      if (fResultCode != 0) break; // an error occurred with the RTSP "SETUP" command

      // Tell this subsession's RTPSink and RTCPInstance to use
      // the RTSP TCP connection:
      ss->rtpSink()->setStreamSocket(fRTSPClient->socketNum(), streamChannelId++);
      if (ss->rtcpInstance() != NULL) {
	ss->rtcpInstance()->setStreamSocket(fRTSPClient->socketNum(),
					    streamChannelId++);
      }
      ss = ss->next();
    }
    if (subsession != NULL) break; // an error occurred above

    // Tell the RTSP server to start:
    fWatchVariable = 0;
    (void)fRTSPClient->sendPlayCommand(*fSession, genericResponseHandler);

    // Now block (but handling events) until we get a response:
    envir().taskScheduler().doEventLoop(&fWatchVariable);

    delete[] fResultString;
    if (fResultCode != 0) break; // an error occurred with the RTSP "PLAY" command

    // Finally, make sure that the output TCP buffer is a reasonable size:
    increaseSendBufferTo(envir(), fRTSPClient->socketNum(), 100*1024);

    success = True;
  } while (0);

  delete[] sdp;
  delete[] url;
  return success;
}