コード例 #1
0
ファイル: QoS_UDP.cpp プロジェクト: binary42/OCI
ACE_QoS_Session *
TAO_AV_UDP_QoS_Session_Helper::open_qos_session (TAO_AV_UDP_QoS_Flow_Handler *handler,
        ACE_INET_Addr &addr)
{
    ACE_QoS_Params qos_params;

    ACE_QoS* ace_qos = 0;

    FillQoSParams (qos_params,
                   0,
                   ace_qos);


    // Create a QoS Session Factory.
    ACE_QoS_Session_Factory session_factory;

    // Ask the factory to create a QoS session.
    ACE_QoS_Session *qos_session = session_factory.create_session ();

    // Create a destination address for the QoS session. The same
    // address should be used for the subscribe call later. A copy
    // is made below only to distinguish the two usages of the dest
    // address.
    ACE_INET_Addr dest_addr (addr);

    // A QoS session is defined by the 3-tuple [DestAddr, DestPort,
    // Protocol]. Initialize the QoS session.
    if (qos_session->open (dest_addr,
                           IPPROTO_UDP) == -1)
        ORBSVCS_ERROR_RETURN ((LM_ERROR,
                               "Error in opening the QoS session\n"),
                              0);
    else
        ORBSVCS_DEBUG ((LM_DEBUG,
                        "QoS session opened successfully\n"));

    if (handler->flowspec_entry ()->role () == TAO_FlowSpec_Entry::TAO_AV_PRODUCER)
    {
        // This is a sender
        qos_session->flags (ACE_QoS_Session::ACE_QOS_SENDER);
    }
    else if (handler->flowspec_entry ()->role () == TAO_FlowSpec_Entry::TAO_AV_CONSUMER)
    {
        // This is a receiver
        qos_session->flags (ACE_QoS_Session::ACE_QOS_RECEIVER);
    }

    return qos_session;
}
コード例 #2
0
  address generate_atomic_xchg() {
    StubCodeMark mark(this, "StubRoutines", "atomic_xchg");
    address start = __ pc();

    __ pushl(edx);
    Address exchange(esp, 2 * wordSize);
    Address dest_addr(esp, 3 * wordSize);
    __ movl(eax, exchange);
    __ movl(edx, dest_addr);    
    __ xchg(eax, Address(edx, 0));
    __ popl(edx);
    __ ret(0);

    return start;
  }
コード例 #3
0
ファイル: icmpv6.cpp プロジェクト: JeanJoskin/libtins
ICMPv6::ICMPv6(const uint8_t *buffer, uint32_t total_sz) 
: _options_size(), reach_time(0), retrans_timer(0)
{
    if(total_sz < sizeof(_header))
        throw malformed_packet();
    std::memcpy(&_header, buffer, sizeof(_header));
    buffer += sizeof(_header);
    total_sz -= sizeof(_header);
    if(has_target_addr()) {
        if(total_sz < ipaddress_type::address_size)
            throw malformed_packet();
        target_addr(buffer);
        buffer += ipaddress_type::address_size;
        total_sz -= ipaddress_type::address_size;
    }
    if(has_dest_addr()) {
        if(total_sz < ipaddress_type::address_size)
            throw malformed_packet();
        dest_addr(buffer);
        buffer += ipaddress_type::address_size;
        total_sz -= ipaddress_type::address_size;
    }
    if(type() == ROUTER_ADVERT) {
        if(total_sz < sizeof(uint32_t) * 2)
            throw malformed_packet();
        const uint32_t *ptr_32 = (const uint32_t*)buffer;
        reach_time = *ptr_32++;
        retrans_timer = *ptr_32++;
        
        buffer += sizeof(uint32_t) * 2;
        total_sz -= sizeof(uint32_t) * 2;
    }
    if(has_options())
        parse_options(buffer, total_sz);
    if(total_sz > 0)
        inner_pdu(new RawPDU(buffer, total_sz));
}
コード例 #4
0
ファイル: receiver.cpp プロジェクト: DOCGroup/ACE_TAO
int
ACE_TMAIN (int argc, ACE_TCHAR * argv[])
{

  QoS_Util qos_util(argc, argv);

  if (qos_util.parse_args () == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "Error in parsing args\n"),
                      -1);

  // This is a multicast application.
  if (qos_util.multicast_flag ())
    {
       Fill_ACE_QoS  fill_ace_qos;

       // The application adds the flow specs that it wants into the
       // Fill_ACE_QoS. The Fill_ACE_QoS indexes the flow specs by the
       // flow spec names. Here the new flowspec being added is g_711.
       ACE_CString g_711 ("g_711");

       switch (fill_ace_qos.map ().bind (g_711,
                                         new ACE_Flow_Spec (9200,
                                                            708,
                                                            18400,
                                                            0,
                                                            0,
                                                            ACE_SERVICETYPE_CONTROLLEDLOAD,
                                                            368,
                                                            368,
                                                            25,
                                                            1)))
         {
         case 1 :
           ACE_ERROR_RETURN ((LM_ERROR,
                              "Unable to bind the new flow spec\n"
                              "The Flow Spec name already exists\n"),
                             -1);
           break;
         case -1 :
           ACE_ERROR_RETURN ((LM_ERROR,
                              "Unable to bind the new flow spec\n"),
                             -1);
           break;
         }

       ACE_DEBUG ((LM_DEBUG,
                   "g_711 Flow Spec bound successfully\n"));

       // This is a receiver. So we fill in the receiving QoS parameters.
       ACE_QoS ace_qos_receiver;
       if (fill_ace_qos.fill_simplex_receiver_qos (ace_qos_receiver,
                                                   g_711) !=0)
         ACE_ERROR_RETURN ((LM_ERROR,
                            "Unable to fill simplex receiver qos\n"),
                           -1);
       else
         ACE_DEBUG ((LM_DEBUG,
                     "Filled up the Receiver QoS parameters\n"));

      // Opening a new Multicast Datagram.
      ACE_SOCK_Dgram_Mcast_QoS dgram_mcast_qos;

      // Multicast Session Address specified by user at command line.
      // If this address is not specified,
      // <localhost:ACE_DEFAULT_MULTICAST_PORT> is assumed.
      ACE_INET_Addr mult_addr (*(qos_util.mult_session_addr ()));

      // Fill the ACE_QoS_Params to be passed to the <ACE_OS::join_leaf>
      // through subscribe.

      ACE_QoS_Params qos_params;
      FillQoSParams (qos_params, 0, &ace_qos_receiver);

      // Create a QoS Session Factory.
      ACE_QoS_Session_Factory session_factory;

      // Ask the factory to create a QoS session.
      ACE_QoS_Session *qos_session =
        session_factory.create_session ();

      // Create a destination address for the QoS session. The same
      // address should be used for the subscribe call later. A copy
      // is made below only to distinguish the two usages of the dest
      // address.

      ACE_INET_Addr dest_addr (mult_addr);

      // A QoS session is defined by the 3-tuple [DestAddr, DestPort,
      // Protocol]. Initialize the QoS session.
      if (qos_session->open (mult_addr,
                             IPPROTO_UDP) == -1)
        ACE_ERROR_RETURN ((LM_ERROR,
                           "Error in opening the QoS session\n"),
                          -1);
      else
        ACE_DEBUG ((LM_DEBUG,
                    "QoS session opened successfully\n"));

      // The following call opens the Dgram_Mcast and calls the
      // <ACE_OS::join_leaf> with the qos_params supplied here. Note
      // the QoS session object is passed into this call. This
      // subscribes the underlying socket to the passed in QoS
      // session. For joining multiple multicast sessions, the
      // following subscribe call should be made with different
      // multicast addresses and a new QoS session object should be
      // passed in for each such call. The QoS session objects can be
      // created only through the session factory. Care should be
      // taken that the mult_addr for the subscribe() call matches the
      // dest_addr of the QoS session object. If this is not done, the
      // subscribe call will fail. A more abstract version of
      // subscribe will be added that constrains the various features
      // of GQoS like different flags etc.

      if (dgram_mcast_qos.subscribe (mult_addr,
                                     qos_params,
                                     1,
                                     0,
                                     AF_INET,
                                     // ACE_FROM_PROTOCOL_INFO,
                                     0,
                                     0, // ACE_Protocol_Info,
                                     0,
                                     ACE_OVERLAPPED_SOCKET_FLAG
                                     | ACE_FLAG_MULTIPOINT_C_LEAF
                                     | ACE_FLAG_MULTIPOINT_D_LEAF,
                                     qos_session) == -1)
        ACE_ERROR_RETURN ((LM_ERROR,
                           "Error in subscribe\n"),
                          -1);
      else
        ACE_DEBUG ((LM_DEBUG,
                    "Dgram_Mcast subscribe succeeds\n"));

      int nIP_TTL = 25;
      char achInBuf [BUFSIZ];
      u_long dwBytes;

      // Should this be abstracted into QoS objects ?? Doesnt seem to have
      // to do anything directly with QoS.
      if (ACE_OS::ioctl (dgram_mcast_qos.get_handle (), // Socket.
                         ACE_SIO_MULTICAST_SCOPE, // IO control code.
                         &nIP_TTL, // In buffer.
                         sizeof (nIP_TTL), // Length of in buffer.
                         achInBuf, // Out buffer.
                         BUFSIZ, // Length of Out buffer.
                         &dwBytes, // bytes returned.
                         0, // Overlapped.
                         0) == -1) // Func.
        ACE_ERROR ((LM_ERROR,
                    "Error in Multicast scope ACE_OS::ioctl()\n"));
      else
        ACE_DEBUG ((LM_DEBUG,
                    "Setting TTL with Multicast scope ACE_OS::ioctl call succeeds\n"));

      int bFlag = 0;

      // Should this be abstracted into QoS objects ?? Doesnt seem to have
      // to do anything directly with QoS.
      if (ACE_OS::ioctl (dgram_mcast_qos.get_handle (), // Socket.
                         ACE_SIO_MULTIPOINT_LOOPBACK, // IO control code.
                         &bFlag, // In buffer.
                         sizeof (bFlag), // Length of in buffer.
                         achInBuf, // Out buffer.
                         BUFSIZ, // Length of Out buffer.
                         &dwBytes, // bytes returned.
                         0, // Overlapped.
                         0) == -1) // Func.
        ACE_ERROR ((LM_ERROR,
                    "Error in Loopback ACE_OS::ioctl()\n"));
      else
        ACE_DEBUG ((LM_DEBUG,
                    "Disable Loopback with ACE_OS::ioctl call succeeds\n"));

      // This is a receiver.
      qos_session->flags (ACE_QoS_Session::ACE_QOS_RECEIVER);

      ACE_QoS_Manager qos_manager = dgram_mcast_qos.qos_manager ();

      // Set the QoS for the session. Replaces the ioctl () call that
      // was being made previously.
      if (qos_session->qos (&dgram_mcast_qos,
                            &qos_manager,
                            ace_qos_receiver) == -1)
        ACE_ERROR_RETURN ((LM_ERROR,
                           "Unable to set QoS\n"),
                          -1);
      else
        ACE_DEBUG ((LM_DEBUG,
                    "Setting QOS succeeds.\n"));

      // Register a signal handler that helps to gracefully close the
      // open QoS sessions.
      QoS_Signal_Handler qos_signal_handler (qos_session);

      // Register the usual SIGINT signal handler with the Reactor for
      // the application to gracefully release the QoS session and
      // shutdown.
      if (ACE_Reactor::instance ()->register_handler
          (SIGINT, &qos_signal_handler) == -1)
        ACE_ERROR_RETURN ((LM_ERROR,
                           "Error in registering the Signal Handler.\n"),
                          -1);

      // Handler to process QoS and Data events for the reciever.
      Receiver_QoS_Event_Handler qos_event_handler (dgram_mcast_qos,
                                                    qos_session);

      // Decorate the above handler with QoS functionality.
      ACE_QoS_Decorator qos_decorator (&qos_event_handler,
                                       qos_session);

      // Initialize the Decorator.
      if (qos_decorator.init () != 0)
        ACE_ERROR_RETURN ((LM_ERROR,
                           "QoS Decorator init () failed.\n"),
                          -1);

      // Register the decorated Event Handler with the Reactor.
      if (ACE_Reactor::instance ()->register_handler (&qos_decorator,
                                                      ACE_Event_Handler::QOS_MASK |
                                                      ACE_Event_Handler::READ_MASK) == -1)
        ACE_ERROR_RETURN ((LM_ERROR,
                           "Error in registering the Decorator with the Reactor\n"),
                          -1);

//        // Register the RAPI Event Handler with the Reactor. This
//        // handles the QoS events.
//        if (ACE_Reactor::instance ()->register_handler
//            (&rapi_event_handler,
//             ACE_Event_Handler::QOS_MASK | ACE_Event_Handler::READ_MASK) == -1)
//          ACE_ERROR_RETURN ((LM_ERROR,
//                             "Error in registering the RAPI Event Handler\n"),
//                            -1);

//        // The following event handler handles the data.
//        ACE_QoS_Event_Handler data_event_handler (dgram_mcast_qos,
//                                                  qos_session);

//        // Register the Data Event Handler with the Reactor.
//        if (ACE_Reactor::instance ()->register_handler
//            (&data_event_handler,ACE_Event_Handler::READ_MASK) == -1)
//          ACE_ERROR_RETURN ((LM_ERROR,
//                             "Error in registering Data Event Handler\n"),
//                            -1);

      // Start the event loop.
      ACE_DEBUG ((LM_DEBUG,
                  "Running the Event Loop ...\n"));

      ACE_Reactor::instance ()->run_event_loop ();

      ACE_DEBUG ((LM_DEBUG,
                  "(%P|%t) shutting down server logging daemon\n"));
    }
  else
    ACE_DEBUG ((LM_DEBUG,
                "Specify a -m option for multicast application\n"));
  return 0;
}
コード例 #5
0
void IPTVStreamHandler::run(void)
{
    RunProlog();

    LOG(VB_GENERAL, LOG_INFO, LOC + "run()");

    SetRunning(true, false, false);

    // TODO Error handling..

    // Setup
    CetonRTSP *rtsp = NULL;
    IPTVTuningData tuning = m_tuning;
    if (m_tuning.GetURL(0).scheme().toLower() == "rtsp")
    {
        rtsp = new CetonRTSP(m_tuning.GetURL(0));

        // Check RTSP capabilities
        QStringList options;
        if (!(rtsp->GetOptions(options)     && options.contains("OPTIONS")  &&
              options.contains("DESCRIBE")  && options.contains("SETUP")    &&
              options.contains("PLAY")      && options.contains("TEARDOWN")))
        {
            LOG(VB_RECORD, LOG_ERR, LOC +
                "RTSP interface did not support the necessary options");
            delete rtsp;
            SetRunning(false, false, false);
            RunEpilog();
            return;
        }

        if (!rtsp->Describe())
        {
            LOG(VB_RECORD, LOG_ERR, LOC +
                "RTSP Describe command failed");
            delete rtsp;
            SetRunning(false, false, false);
            RunEpilog();
            return;
        }

        tuning = IPTVTuningData(
            QString("rtp://%1@%2:0")
            .arg(m_tuning.GetURL(0).host())
            .arg(QHostAddress(QHostAddress::Any).toString()), 0,
            IPTVTuningData::kNone,
            QString("rtp://%1@%2:0")
            .arg(m_tuning.GetURL(0).host())
            .arg(QHostAddress(QHostAddress::Any).toString()), 0,
            "", 0);
    }

    for (uint i = 0; i < IPTV_SOCKET_COUNT; i++)
    {
        QUrl url = tuning.GetURL(i);
        if (url.port() < 0)
            continue;

        m_sockets[i] = new QUdpSocket();
        m_read_helpers[i] = new IPTVStreamHandlerReadHelper(
            this, m_sockets[i], i);

        // we need to open the descriptor ourselves so we
        // can set some socket options
        int fd = socket(AF_INET, SOCK_DGRAM, 0); // create IPv4 socket
        if (fd < 0)
        {
            LOG(VB_GENERAL, LOG_ERR, LOC +
                "Unable to create socket " + ENO);
            continue;
        }
        int buf_size = 2 * 1024 * max(tuning.GetBitrate(i)/1000, 500U);
        if (!tuning.GetBitrate(i))
            buf_size = 2 * 1024 * 1024;
        int ok = setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
                            (char *)&buf_size, sizeof(buf_size));
        if (ok)
        {
            LOG(VB_GENERAL, LOG_INFO, LOC +
                QString("Increasing buffer size to %1 failed")
                .arg(buf_size) + ENO);
        }
        /*
          int broadcast = 1;
          ok = setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
          (char *)&broadcast, sizeof(broadcast));
          if (ok)
          {
          LOG(VB_GENERAL, LOG_INFO, LOC +
          QString("Enabling broadcast failed") + ENO);
          }
        */
        m_sockets[i]->setSocketDescriptor(
            fd, QAbstractSocket::UnconnectedState, QIODevice::ReadOnly);

        m_sockets[i]->bind(QHostAddress::Any, url.port());

        QHostAddress dest_addr(tuning.GetURL(i).host());

        if (dest_addr != QHostAddress::Any)
        {
            //m_sockets[i]->joinMulticastGroup(dest_addr); // needs Qt 4.8
            LOG(VB_GENERAL, LOG_INFO, LOC + QString("Joining %1")
                .arg(dest_addr.toString()));
            struct ip_mreq imr;
            memset(&imr, 0, sizeof(struct ip_mreq));
            imr.imr_multiaddr.s_addr = inet_addr(
                dest_addr.toString().toLatin1().constData());
            imr.imr_interface.s_addr = htonl(INADDR_ANY);
            if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
				(const char *)&imr, sizeof(imr)) < 0)
            {
                LOG(VB_GENERAL, LOG_ERR, LOC +
                    "setsockopt - IP_ADD_MEMBERSHIP " + ENO);
            }
        }

        if (!url.userInfo().isEmpty())
            m_sender[i] = QHostAddress(url.userInfo());
    }
    if (m_use_rtp_streaming)
        m_buffer = new RTPPacketBuffer(tuning.GetBitrate(0));
    else
        m_buffer = new UDPPacketBuffer(tuning.GetBitrate(0));
    m_write_helper = new IPTVStreamHandlerWriteHelper(this);
    m_write_helper->Start();

    bool error = false;
    if (rtsp)
    {
        // Start Streaming
        if (!rtsp->Setup(m_sockets[0]->localPort(),
                         m_sockets[1]->localPort()) ||
            !rtsp->Play())
        {
            LOG(VB_RECORD, LOG_ERR, LOC +
                "Starting recording (RTP initialization failed). Aborting.");
            error = true;
        }
    }

    if (!error)
    {
        // Enter event loop
        exec();
    }

    // Clean up
    for (uint i = 0; i < IPTV_SOCKET_COUNT; i++)
    {
        if (m_sockets[i])
        {
            delete m_sockets[i];
            m_sockets[i] = NULL;
            delete m_read_helpers[i];
            m_read_helpers[i] = NULL;
        }
    }
    delete m_buffer;
    m_buffer = NULL;
    delete m_write_helper;
    m_write_helper = NULL;

    if (rtsp)
    {
        rtsp->Teardown();
        delete rtsp;
    }

    SetRunning(false, false, false);
    RunEpilog();
}
コード例 #6
0
void IPTVStreamHandler::run(void)
{
    RunProlog();

    LOG(VB_GENERAL, LOG_INFO, LOC + "run()");

    SetRunning(true, false, false);

    // TODO Error handling..

    // Setup
    CetonRTSP *rtsp = nullptr;
    IPTVTuningData tuning = m_tuning;
    if(m_tuning.IsRTSP())
    {
        rtsp = new CetonRTSP(m_tuning.GetURL(0));

        // Check RTSP capabilities
        QStringList options;
        if (!(rtsp->GetOptions(options)     && options.contains("DESCRIBE") &&
              options.contains("SETUP")     && options.contains("PLAY")     &&
              options.contains("TEARDOWN")))
        {
            LOG(VB_RECORD, LOG_ERR, LOC +
                "RTSP interface did not support the necessary options");
            delete rtsp;
            SetRunning(false, false, false);
            RunEpilog();
            return;
        }

        if (!rtsp->Describe())
        {
            LOG(VB_RECORD, LOG_ERR, LOC +
                "RTSP Describe command failed");
            delete rtsp;
            SetRunning(false, false, false);
            RunEpilog();
            return;
        }

        m_use_rtp_streaming = true;

        QUrl urltuned = m_tuning.GetURL(0);
        urltuned.setScheme("rtp");
        urltuned.setPort(0);
        tuning = IPTVTuningData(urltuned.toString(), 0, IPTVTuningData::kNone,
                                urltuned.toString(), 0, "", 0);
    }

    bool error = false;

    int start_port = 0;
    for (uint i = 0; i < IPTV_SOCKET_COUNT; i++)
    {
        QUrl url = tuning.GetURL(i);
        if (url.port() < 0)
            continue;

        LOG(VB_RECORD, LOG_DEBUG, LOC +
            QString("setting up url[%1]:%2").arg(i).arg(url.toString()));

        // always ensure we use consecutive port numbers
        int port = start_port ? start_port + 1 : url.port();
        QString host = url.host();
        QHostAddress dest_addr(host);

        if (!host.isEmpty() && dest_addr.isNull())
        {
            // address is a hostname, attempts to resolve it
            QHostInfo info = QHostInfo::fromName(host);
            QList<QHostAddress> list = info.addresses();

            if (list.isEmpty())
            {
                LOG(VB_RECORD, LOG_ERR, LOC +
                    QString("Can't resolve hostname:'%1'").arg(host));
            }
            else
            {
                for (int j=0; j < list.size(); j++)
                {
                    dest_addr = list[j];
                    if (list[j].protocol() == QAbstractSocket::IPv6Protocol)
                    {
                        // We prefer first IPv4
                        break;
                    }
                }
                LOG(VB_RECORD, LOG_DEBUG, LOC +
                    QString("resolved %1 as %2").arg(host).arg(dest_addr.toString()));
            }
        }
        bool ipv6 = dest_addr.protocol() == QAbstractSocket::IPv6Protocol;
        bool is_multicast = ipv6 ?
            dest_addr.isInSubnet(QHostAddress::parseSubnet("ff00::/8")) :
            (dest_addr.toIPv4Address() & 0xf0000000) == 0xe0000000;

        m_sockets[i] = new QUdpSocket();
        if (!is_multicast)
        {
            // this allow to filter incoming traffic, and make sure it's from
            // the requested server
            m_sender[i] = dest_addr;
        }
        m_read_helpers[i] = new IPTVStreamHandlerReadHelper(
            this, m_sockets[i], i);

        // we need to open the descriptor ourselves so we
        // can set some socket options
        int fd = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_DGRAM, 0); // create IPv4 socket
        if (fd < 0)
        {
            LOG(VB_GENERAL, LOG_ERR, LOC +
                "Unable to create socket " + ENO);
            continue;
        }
        int buf_size = 2 * 1024 * max(tuning.GetBitrate(i)/1000, 500U);
        if (!tuning.GetBitrate(i))
            buf_size = 2 * 1024 * 1024;
        int err = setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
                            (char *)&buf_size, sizeof(buf_size));
        if (err)
        {
            LOG(VB_GENERAL, LOG_INFO, LOC +
                QString("Increasing buffer size to %1 failed")
                .arg(buf_size) + ENO);
        }

        m_sockets[i]->setSocketDescriptor(
            fd, QAbstractSocket::UnconnectedState, QIODevice::ReadOnly);

        // we bind to destination address if it's a multicast address, or
        // the local ones otherwise
        if (!m_sockets[i]->bind(is_multicast ?
                                dest_addr :
                                (ipv6 ? QHostAddress::AnyIPv6 : QHostAddress::Any),
                                port))
        {
            LOG(VB_GENERAL, LOG_ERR, LOC + "Binding to port failed.");
            error = true;
        }
        else
        {
            start_port = m_sockets[i]->localPort();
        }

        if (is_multicast)
        {
            m_sockets[i]->joinMulticastGroup(dest_addr);
            LOG(VB_GENERAL, LOG_INFO, LOC + QString("Joining %1")
                .arg(dest_addr.toString()));
        }

        if (!is_multicast && rtsp && i == 1)
        {
            m_rtcp_dest = dest_addr;
        }
    }

    if (!error)
    {
        if (m_tuning.IsRTP() || m_tuning.IsRTSP())
            m_buffer = new RTPPacketBuffer(tuning.GetBitrate(0));
        else
            m_buffer = new UDPPacketBuffer(tuning.GetBitrate(0));
        m_write_helper =
            new IPTVStreamHandlerWriteHelper(this);
        m_write_helper->Start();
    }

    if (!error && rtsp)
    {
        // Start Streaming
        if (!rtsp->Setup(m_sockets[0]->localPort(), m_sockets[1]->localPort(),
                         m_rtsp_rtp_port, m_rtsp_rtcp_port, m_rtsp_ssrc) ||
            !rtsp->Play())
        {
            LOG(VB_RECORD, LOG_ERR, LOC +
                "Starting recording (RTP initialization failed). Aborting.");
            error = true;
        }
        if (m_rtsp_rtcp_port > 0)
        {
            m_write_helper->SendRTCPReport();
            m_write_helper->StartRTCPRR();
        }
    }

    if (!error)
    {
        // Enter event loop
        exec();
    }

    // Clean up
    for (uint i = 0; i < IPTV_SOCKET_COUNT; i++)
    {
        if (m_sockets[i])
        {
            delete m_sockets[i];
            m_sockets[i] = nullptr;
            delete m_read_helpers[i];
            m_read_helpers[i] = nullptr;
        }
    }
    delete m_buffer;
    m_buffer = nullptr;
    delete m_write_helper;
    m_write_helper = nullptr;

    if (rtsp)
    {
        rtsp->Teardown();
        delete rtsp;
    }

    SetRunning(false, false, false);
    RunEpilog();
}