Esempio n. 1
1
  /**
   * {@inheritDoc}
   *
   * @param format unused, since this implementation records multiple streams using potentially
   *     different formats.
   * @param dirname the path to the directory into which this <tt>Recorder</tt> will store the
   *     recorded media files.
   */
  @Override
  public void start(String format, String dirname) throws IOException, MediaException {
    if (logger.isInfoEnabled()) logger.info("Starting, format=" + format + " " + hashCode());
    path = dirname;

    MediaService mediaService = LibJitsi.getMediaService();

    /*
     * Note that we use only one RTPConnector for both the RTPTranslator
     * and the RTPManager instances. The this.translator will write to its
     * output streams, and this.rtpManager will read from its input streams.
     */
    rtpConnector = new RTPConnectorImpl(redPayloadType, ulpfecPayloadType);

    rtpManager = RTPManager.newInstance();

    /*
     * Add the formats that we know about.
     */
    rtpManager.addFormat(vp8RtpFormat, vp8PayloadType);
    rtpManager.addFormat(opusFormat, opusPayloadType);
    rtpManager.addReceiveStreamListener(this);

    /*
     * Note: When this.rtpManager sends RTCP sender/receiver reports, they
     * will end up being written to its own input stream. This is not
     * expected to cause problems, but might be something to keep an eye on.
     */
    rtpManager.initialize(rtpConnector);

    /*
     * Register a fake call participant.
     * TODO: can we use a more generic MediaStream here?
     */
    streamRTPManager =
        new StreamRTPManager(
            mediaService.createMediaStream(
                new MediaDeviceImpl(new CaptureDeviceInfo(), MediaType.VIDEO)),
            translator);

    streamRTPManager.initialize(rtpConnector);

    rtcpFeedbackSender = translator.getRtcpFeedbackMessageSender();

    translator.addFormat(streamRTPManager, opusFormat, opusPayloadType);

    // ((RTPTranslatorImpl)videoRTPTranslator).addFormat(streamRTPManager, redFormat,
    // redPayloadType);
    // ((RTPTranslatorImpl)videoRTPTranslator).addFormat(streamRTPManager, ulpfecFormat,
    // ulpfecPayloadType);
    // ((RTPTranslatorImpl)videoRTPTranslator).addFormat(streamRTPManager,
    // mediaFormatImpl.getFormat(), vp8PayloadType);

    started = true;
  }
Esempio n. 2
0
  static {
    ConfigurationService cfg = LibJitsi.getConfigurationService();
    boolean dropUnencryptedPkts = false;

    if (cfg == null) {
      String s = System.getProperty(DROP_UNENCRYPTED_PKTS_PNAME);

      if (s != null) dropUnencryptedPkts = Boolean.parseBoolean(s);
    } else {
      dropUnencryptedPkts = cfg.getBoolean(DROP_UNENCRYPTED_PKTS_PNAME, dropUnencryptedPkts);
    }
    DROP_UNENCRYPTED_PKTS = dropUnencryptedPkts;
  }
  private void runOnDtlsTransport(StreamConnector connector) throws IOException {
    DtlsControlImpl dtlsControl = (DtlsControlImpl) getTransportManager().getDtlsControl(this);
    DtlsTransformEngine engine = dtlsControl.getTransformEngine();
    final DtlsPacketTransformer transformer = (DtlsPacketTransformer) engine.getRTPTransformer();

    byte[] receiveBuffer = new byte[SCTP_BUFFER_SIZE];

    if (LOG_SCTP_PACKETS) {
      System.setProperty(
          ConfigurationService.PNAME_SC_HOME_DIR_LOCATION, System.getProperty("java.io.tmpdir"));
      System.setProperty(
          ConfigurationService.PNAME_SC_HOME_DIR_NAME, SctpConnection.class.getName());
    }

    synchronized (this) {
      // FIXME local SCTP port is hardcoded in bridge offer SDP (Jitsi
      // Meet)
      sctpSocket = Sctp.createSocket(5000);
      assocIsUp = false;
      acceptedIncomingConnection = false;
    }

    // Implement output network link for SCTP stack on DTLS transport
    sctpSocket.setLink(
        new NetworkLink() {
          @Override
          public void onConnOut(SctpSocket s, byte[] packet) throws IOException {
            if (LOG_SCTP_PACKETS) {
              LibJitsi.getPacketLoggingService()
                  .logPacket(
                      PacketLoggingService.ProtocolName.ICE4J,
                      new byte[] {0, 0, 0, (byte) debugId},
                      5000,
                      new byte[] {0, 0, 0, (byte) (debugId + 1)},
                      remoteSctpPort,
                      PacketLoggingService.TransportName.UDP,
                      true,
                      packet);
            }

            // Send through DTLS transport
            transformer.sendApplicationData(packet, 0, packet.length);
          }
        });

    if (logger.isDebugEnabled()) {
      logger.debug("Connecting SCTP to port: " + remoteSctpPort + " to " + getEndpoint().getID());
    }

    sctpSocket.setNotificationListener(this);
    sctpSocket.listen();

    // FIXME manage threads
    threadPool.execute(
        new Runnable() {
          @Override
          public void run() {
            SctpSocket sctpSocket = null;
            try {
              // sctpSocket is set to null on close
              sctpSocket = SctpConnection.this.sctpSocket;
              while (sctpSocket != null) {
                if (sctpSocket.accept()) {
                  acceptedIncomingConnection = true;
                  break;
                }
                Thread.sleep(100);
                sctpSocket = SctpConnection.this.sctpSocket;
              }
              if (isReady()) {
                notifySctpConnectionReady();
              }
            } catch (Exception e) {
              logger.error("Error accepting SCTP connection", e);
            }

            if (sctpSocket == null && logger.isInfoEnabled()) {
              logger.info(
                  "SctpConnection " + getID() + " closed" + " before SctpSocket accept()-ed.");
            }
          }
        });

    // Notify that from now on SCTP connection is considered functional
    sctpSocket.setDataCallback(this);

    // Setup iceSocket
    DatagramSocket datagramSocket = connector.getDataSocket();
    if (datagramSocket != null) {
      this.iceSocket = new IceUdpSocketWrapper(datagramSocket);
    } else {
      this.iceSocket = new IceTcpSocketWrapper(connector.getDataTCPSocket());
    }

    DatagramPacket rcvPacket = new DatagramPacket(receiveBuffer, 0, receiveBuffer.length);

    // Receive loop, breaks when SCTP socket is closed
    try {
      do {
        iceSocket.receive(rcvPacket);

        RawPacket raw =
            new RawPacket(rcvPacket.getData(), rcvPacket.getOffset(), rcvPacket.getLength());

        raw = transformer.reverseTransform(raw);
        // Check for app data
        if (raw == null) continue;

        if (LOG_SCTP_PACKETS) {
          LibJitsi.getPacketLoggingService()
              .logPacket(
                  PacketLoggingService.ProtocolName.ICE4J,
                  new byte[] {0, 0, 0, (byte) (debugId + 1)},
                  remoteSctpPort,
                  new byte[] {0, 0, 0, (byte) debugId},
                  5000,
                  PacketLoggingService.TransportName.UDP,
                  false,
                  raw.getBuffer(),
                  raw.getOffset(),
                  raw.getLength());
        }

        // Pass network packet to SCTP stack
        sctpSocket.onConnIn(raw.getBuffer(), raw.getOffset(), raw.getLength());
      } while (true);
    } finally {
      // Eventually, close the socket although it should happen from
      // expire().
      synchronized (this) {
        assocIsUp = false;
        acceptedIncomingConnection = false;
        if (sctpSocket != null) {
          sctpSocket.close();
          sctpSocket = null;
        }
      }
    }
  }