void
AudioStream::stateChanged(pa_stream* s)
{
    UNUSED char str[PA_SAMPLE_SPEC_SNPRINT_MAX];

    switch (pa_stream_get_state(s)) {
        case PA_STREAM_CREATING:
            RING_DBG("Stream is creating...");
            break;

        case PA_STREAM_TERMINATED:
            RING_DBG("Stream is terminating...");
            break;

        case PA_STREAM_READY:
            RING_DBG("Stream successfully created, connected to %s", pa_stream_get_device_name(s));
            //RING_DBG("maxlength %u", pa_stream_get_buffer_attr(s)->maxlength);
            //RING_DBG("tlength %u", pa_stream_get_buffer_attr(s)->tlength);
            //RING_DBG("prebuf %u", pa_stream_get_buffer_attr(s)->prebuf);
            //RING_DBG("minreq %u", pa_stream_get_buffer_attr(s)->minreq);
            //RING_DBG("fragsize %u", pa_stream_get_buffer_attr(s)->fragsize);
            //RING_DBG("samplespec %s", pa_sample_spec_snprint(str, sizeof(str), pa_stream_get_sample_spec(s)));
            break;

        case PA_STREAM_UNCONNECTED:
            RING_DBG("Stream unconnected");
            break;

        case PA_STREAM_FAILED:
        default:
            RING_ERR("Stream failure: %s" , pa_strerror(pa_context_errno(pa_stream_get_context(s))));
            break;
    }
}
SipIceTransport::~SipIceTransport()
{
    RING_DBG("~SipIceTransport@%p", this);
    Manager::instance().unregisterEventHandler((uintptr_t)this);
    pj_lock_destroy(trData_.base.lock);
    pj_atomic_destroy(trData_.base.ref_cnt);
    RING_DBG("destroying SipIceTransport@%p", this);
}
SipTransportBroker::~SipTransportBroker()
{
    RING_DBG("~SipTransportBroker@%p", this);

    shutdown();

    udpTransports_.clear();
    transports_.clear();

    RING_DBG("destroying SipTransportBroker@%p", this);
}
void
SipTransportBroker::transportStateChanged(pjsip_transport* tp,
                                          pjsip_transport_state state,
                                          const pjsip_transport_state_info* info)
{
    RING_DBG("pjsip transport@%p %s -> %s",
             tp, tp->info, SipTransport::stateToStr(state));

    // First make sure that this transport is handled by us
    // and remove it from any mapping if destroy pending or done.

    std::shared_ptr<SipTransport> sipTransport;

    {
        std::lock_guard<std::mutex> lock(transportMapMutex_);
        auto key = transports_.find(tp);
        if (key == transports_.end()) {
            RING_WARN("spurious pjsip transport state change");
            return;
        }

        sipTransport = key->second.lock();

#if PJ_VERSION_NUM > (2 << 24 | 1 << 16)
        bool destroyed = state == PJSIP_TP_STATE_DESTROY;
#else
        bool destroyed = tp->is_destroying;
#endif

        // maps cleanup
        if (destroyed) {
            RING_DBG("unmap pjsip transport@%p {SipTransport@%p}",
                     tp, sipTransport.get());
            transports_.erase(key);

            // If UDP
            const auto type = tp->key.type;
            if (type == PJSIP_TRANSPORT_UDP or type == PJSIP_TRANSPORT_UDP6) {
                const auto updKey = std::find_if(
                    udpTransports_.cbegin(), udpTransports_.cend(),
                    [tp](const std::pair<SipTransportDescr, pjsip_transport*>& pair) {
                        return pair.second == tp;
                    });
                if (updKey != udpTransports_.cend())
                    udpTransports_.erase(updKey);
            }
        }
    }

    // Propagate the event to the appropriate transport
    // Note the SipTransport may not be in our mappings if marked as dead
    if (sipTransport)
        sipTransport->stateCallback(state, info);
}
void
AccountFactory::removeAccount(Account& account)
{
    const auto account_type = account.getAccountType();

    std::lock_guard<std::recursive_mutex> lock(mutex_);
    const auto& id = account.getAccountID();
    RING_DBG("Removing account %s", id.c_str());
    auto& map = accountMaps_.at(account.getAccountType());
    map.erase(id);
    RING_DBG("Remaining %zu %s account(s)", map.size(), account_type);
}
int VideoInput::allocateOneBuffer(struct VideoFrameBuffer& b, int length)
{
    b.data = std::malloc(length);
    if (b.data) {
        b.status = BUFFER_AVAILABLE;
        b.length = length;
        RING_DBG("Allocated buffer [%p]", b.data);
        return 0;
    }

    RING_DBG("Failed to allocate memory for one buffer");
    return -ENOMEM;
}
Beispiel #7
0
void HistoryTest::test_get_serialized()
{
    RING_DBG("-------------------- HistoryTest::test_get_serialized --------------------\n");
    bool res = history_->load(HISTORY_LIMIT);
    CPPUNIT_ASSERT(res);
    CPPUNIT_ASSERT(history_->getSerialized().size() == HISTORY_SAMPLE_SIZE);
}
Beispiel #8
0
void HistoryTest::test_load_items()
{
    RING_DBG("-------------------- HistoryTest::test_load_items --------------------\n");
    bool res = history_->load(HISTORY_LIMIT);
    CPPUNIT_ASSERT(res);
    CPPUNIT_ASSERT(history_->numberOfItems() == HISTORY_SAMPLE_SIZE);
}
Beispiel #9
0
void HistoryTest::test_load_from_file()
{
    RING_DBG("-------------------- HistoryTest::test_load_from_file --------------------\n");

    bool res = history_->load(HISTORY_LIMIT);
    CPPUNIT_ASSERT(res);
}
Beispiel #10
0
void HistoryTest::test_create_path()
{
    RING_DBG("-------------------- HistoryTest::test_set_path --------------------\n");

    std::string path(HISTORY_SAMPLE);
    CPPUNIT_ASSERT(history_->path_ == path);
}
bool
AudioSender::setup(SocketPair& socketPair)
{
    audioEncoder_.reset(new MediaEncoder);
    muxContext_.reset(socketPair.createIOContext(mtu_));

    try {
        /* Encoder setup */
        RING_DBG("audioEncoder_->openOutput %s", dest_.c_str());
        audioEncoder_->setMuted(muteState_);
        audioEncoder_->openOutput(dest_.c_str(), args_);
        audioEncoder_->setInitSeqVal(seqVal_);
        audioEncoder_->setIOContext(muxContext_);
        audioEncoder_->startIO();
    } catch (const MediaEncoderException &e) {
        RING_ERR("%s", e.what());
        return false;
    }

#ifdef DEBUG_SDP
    audioEncoder_->print_sdp();
#endif

    return true;
}
std::shared_ptr<RingBuffer>
RingBufferPool::createRingBuffer(const std::string& id)
{
    std::lock_guard<std::recursive_mutex> lk(stateLock_);

    auto rbuf = getRingBuffer(id);
    if (rbuf) {
        RING_DBG("Ringbuffer already exists for id '%s'", id.c_str());
        return rbuf;
    }

    rbuf.reset(new RingBuffer(id, SIZEBUF));
    RING_DBG("Ringbuffer created with id '%s'", id.c_str());
    ringBufferMap_.insert(std::make_pair(id, std::weak_ptr<RingBuffer>(rbuf)));
    return rbuf;
}
Beispiel #13
0
void
SIPCall::hangup(int reason)
{
    // Stop all RTP streams
    stopAllMedia();

    if (not inv or not inv->dlg) {
        removeCall();
        throw VoipLinkException("No invite session for this call");
    }

    pjsip_route_hdr *route = inv->dlg->route_set.next;
    while (route and route != &inv->dlg->route_set) {
        char buf[1024];
        int printed = pjsip_hdr_print_on(route, buf, sizeof(buf));

        if (printed >= 0) {
            buf[printed] = '\0';
            RING_DBG("[call:%s] Route header %s", getCallId().c_str(), buf);
        }

        route = route->next;
    }

    const int status = reason ? reason :
                       inv->state <= PJSIP_INV_STATE_EARLY and inv->role != PJSIP_ROLE_UAC ?
                       PJSIP_SC_CALL_TSX_DOES_NOT_EXIST :
                       inv->state >= PJSIP_INV_STATE_DISCONNECTED ? PJSIP_SC_DECLINE : 0;

    // Notify the peer
    terminateSipSession(status);

    setState(Call::ConnectionState::DISCONNECTED, reason);
    removeCall();
}
Beispiel #14
0
pjsip_route_hdr *
createRouteSet(const std::string &route, pj_pool_t *hdr_pool)
{
    pjsip_route_hdr *route_set = pjsip_route_hdr_create(hdr_pool);

    std::string host;
    int port = 0;
    size_t found = route.find(":");
    if (found != std::string::npos) {
        host = route.substr(0, found);
        port = atoi(route.substr(found + 1, route.length() - found).c_str());
    } else
        host = route;

    pjsip_route_hdr *routing = pjsip_route_hdr_create(hdr_pool);
    pjsip_sip_uri *url = pjsip_sip_uri_create(hdr_pool, 0);
    url->lr_param = 1;
    routing->name_addr.uri = (pjsip_uri*) url;
    pj_strdup2(hdr_pool, &url->host, host.c_str());
    url->port = port;

    RING_DBG("Adding route %s", host.c_str());
    pj_list_push_back(route_set, pjsip_hdr_clone(hdr_pool, routing));

    return route_set;
}
std::shared_ptr<SipTransport>
SipTransportBroker::createUdpTransport(const SipTransportDescr& d)
{
    RETURN_IF_FAIL(d.listenerPort != 0, nullptr, "Could not determine port for this transport");
    auto family = pjsip_transport_type_get_af(d.type);

    IpAddr listeningAddress = (d.interface == ip_utils::DEFAULT_INTERFACE) ?
        ip_utils::getAnyHostAddr(family) :
        ip_utils::getInterfaceAddr(d.interface, family);
    listeningAddress.setPort(d.listenerPort);

    RETURN_IF_FAIL(listeningAddress, nullptr, "Could not determine IP address for this transport");
    pjsip_transport *transport = nullptr;
    pj_status_t status = listeningAddress.isIpv4()
        ? pjsip_udp_transport_start (endpt_, &static_cast<const pj_sockaddr_in&>(listeningAddress),  nullptr, 1, &transport)
        : pjsip_udp_transport_start6(endpt_, &static_cast<const pj_sockaddr_in6&>(listeningAddress), nullptr, 1, &transport);
    if (status != PJ_SUCCESS) {
        RING_ERR("pjsip_udp_transport_start* failed with error %d: %s", status,
                 sip_utils::sip_strerror(status).c_str());
        RING_ERR("UDP IPv%s Transport did not start on %s",
            listeningAddress.isIpv4() ? "4" : "6",
            listeningAddress.toString(true).c_str());
        return nullptr;
    }

    RING_DBG("Created UDP transport on %s : %s", d.interface.c_str(), listeningAddress.toString(true).c_str());
    auto ret = std::make_shared<SipTransport>(transport);
    // dec ref because the refcount starts at 1 and SipTransport increments it ?
    // pjsip_transport_dec_ref(transport);
    return ret;
}
AccountFactory::AccountFactory()
{
    auto sipfunc = [](const std::string& id){ return std::make_shared<SIPAccount>(id, true); };
    generators_.insert(std::make_pair(SIPAccount::ACCOUNT_TYPE, sipfunc));
    RING_DBG("registered %s account", SIPAccount::ACCOUNT_TYPE);
#if HAVE_IAX
    auto iaxfunc = [](const std::string& id){ return std::make_shared<IAXAccount>(id); };
    generators_.insert(std::make_pair(IAXAccount::ACCOUNT_TYPE, iaxfunc));
    RING_DBG("registered %s account", IAXAccount::ACCOUNT_TYPE);
#endif
#if HAVE_DHT
    auto dhtfunc = [](const std::string& id){ return std::make_shared<RingAccount>(id, false); };
    generators_.insert(std::make_pair(RingAccount::ACCOUNT_TYPE, dhtfunc));
    RING_DBG("registered %s account", RingAccount::ACCOUNT_TYPE);
#endif
}
std::shared_ptr<SipTransport>
SipTransportBroker::getUdpTransport(const SipTransportDescr& descr)
{
    std::lock_guard<std::mutex> lock(transportMapMutex_);
    auto itp = udpTransports_.find(descr);
    if (itp != udpTransports_.end()) {
        auto it = transports_.find(itp->second);
        if (it != transports_.end()) {
            if (auto spt = it->second.lock()) {
                RING_DBG("Reusing transport %s", descr.toString().c_str());
                return spt;
            }
            else {
                // Transport still exists but have not been destroyed yet.
                RING_WARN("Recycling transport %s", descr.toString().c_str());
                auto ret = std::make_shared<SipTransport>(itp->second);
                it->second = ret;
                return ret;
            }
        } else {
            RING_WARN("Cleaning up UDP transport %s", descr.toString().c_str());
            udpTransports_.erase(itp);
        }
    }
    auto ret = createUdpTransport(descr);
    if (ret) {
        udpTransports_[descr] = ret->get();
        transports_[ret->get()] = ret;
    }
    return ret;
}
Beispiel #18
0
void
PortAudioLayer::init()
{
    RING_DBG("Init PortAudioLayer");
    const auto err = Pa_Initialize();
    if (err != paNoError) {
        this->handleError(err);
        this->terminate();
    }

    indexOut_ = indexRing_ = Pa_GetDefaultOutputDevice();
    indexIn_ = Pa_GetDefaultInputDevice();

    if (indexOut_ != paNoDevice) {
        const auto outputDeviceInfo = Pa_GetDeviceInfo(indexOut_);
        audioFormat_.nb_channels = outputDeviceInfo->maxOutputChannels;
        audioFormat_.sample_rate = outputDeviceInfo->defaultSampleRate;
        hardwareFormatAvailable(audioFormat_);
    }

    if (indexIn_ != paNoDevice) {
        const auto inputDeviceInfo = Pa_GetDeviceInfo(indexIn_);
        audioInputFormat_.nb_channels = inputDeviceInfo->maxInputChannels;
        audioInputFormat_.sample_rate = inputDeviceInfo->defaultSampleRate;
        hardwareInputFormatAvailable(audioInputFormat_);
    }
}
Beispiel #19
0
void
PortAudioLayer::stopStream()
{
    if (status_ != Status::Started)
        return;

    RING_DBG("Stop PortAudio Streams");

    for (int i = 0; i < Direction::End; i++) {
        auto err = Pa_StopStream(streams[i]);
        if(err != paNoError)
            this->handleError(err);

        err = Pa_CloseStream(streams[i]);
        if (err != paNoError)
            this->handleError(err);
    }

    {
        std::lock_guard<std::mutex> lock(mutex_);
        status_ = Status::Idle;
    }

    /* Flush the ring buffers */
    flushUrgent();
    flushMain();
}
Beispiel #20
0
bool
AudioRecord::openFile()
{
#ifndef RING_UWP
    fileHandle_.reset(); // do it before calling fileExists()

    const bool doAppend = fileExists();
    const int access = doAppend ? SFM_RDWR : SFM_WRITE;

    RING_DBG("Opening file %s with format %s", getFilename().c_str(), sndFormat_.toString().c_str());
    fileHandle_.reset(new SndfileHandle (getFilename().c_str(),
                                         access,
                                         SF_FORMAT_WAV | SF_FORMAT_PCM_16,
                                         sndFormat_.nb_channels,
                                         sndFormat_.sample_rate));

    // check overloaded boolean operator
    if (!*fileHandle_) {
        RING_WARN("Could not open WAV file!");
        fileHandle_.reset();
        return false;
    }

    if (doAppend and fileHandle_->seek(0, SEEK_END) < 0)
        RING_WARN("Couldn't seek to the end of the file ");

    return true;
#else
    return false;
#endif
}
Beispiel #21
0
AudioRecord::AudioRecord()
    : sndFormat_(AudioFormat::MONO())
    , filename_(createFilename())
    , savePath_()
    , recorder_(this, Manager::instance().getRingBufferPool())
{
    RING_DBG("Generate filename for this call %s ", filename_.c_str());
}
void
VideoInput::cleanup()
{
    deleteDecoder(); // do it first to let a chance to last frame to be displayed
    detach(sink_.get());
    sink_->stop();
    RING_DBG("VideoInput closed");
}
void VideoInput::freeOneBuffer(struct VideoFrameBuffer& b)
{
    RING_DBG("Free buffer [%p]", b.data);
    std::free(b.data);
    b.data = nullptr;
    b.length = 0;
    b.status = BUFFER_NOT_ALLOCATED;
}
Beispiel #24
0
void
PortAudioLayer::terminate() const
{
    RING_DBG("PortAudioLayer terminate.");
    const auto err = Pa_Terminate();
    if (err != paNoError)
        this->handleError(err);
}
SipTransportBroker::SipTransportBroker(pjsip_endpoint *endpt,
                                       pj_caching_pool& cp, pj_pool_t& pool) :
cp_(cp), pool_(pool), endpt_(endpt)
{
/*#if HAVE_DHT
    pjsip_transport_register_type(PJSIP_TRANSPORT_DATAGRAM, "ICE",
                                  pjsip_transport_get_default_port_for_type(PJSIP_TRANSPORT_UDP),
                                  &ice_pj_transport_type_);
#endif*/
    RING_DBG("SipTransportBroker@%p", this);
}
/**
 * Make given call ID a reader of given ring buffer
 */
void
RingBufferPool::addReaderToRingBuffer(std::shared_ptr<RingBuffer> rbuf,
                                  const std::string& call_id)
{
    if (call_id != DEFAULT_ID and rbuf->id == call_id)
        RING_WARN("RingBuffer has a readoffset on itself");

    rbuf->createReadOffset(call_id);
    readBindingsMap_[call_id].insert(rbuf); // bindings list created if not existing
    RING_DBG("Bind rbuf '%s' to callid '%s'", rbuf->id.c_str(), call_id.c_str());
}
Beispiel #27
0
void AudioRecord::initFilename(const std::string &peerNumber)
{
    RING_DBG("Initialize audio record for peer  : %s", peerNumber.c_str());
    // if savePath_ don't contains filename
    if (savePath_.find(".wav") == std::string::npos) {
        filename_ = createFilename();
        filename_.append("-" + sanitize(peerNumber) + "-" PACKAGE);
        filename_.append(".wav");
    } else {
        filename_ = "";
    }
}
SipTransport::SipTransport(pjsip_transport* t)
    : transport_(nullptr, deleteTransport)
{
    if (not t or pjsip_transport_add_ref(t) != PJ_SUCCESS)
        throw std::runtime_error("invalid transport");

    // Set pointer here, right after the successful pjsip_transport_add_ref
    transport_.reset(t);

    RING_DBG("SipTransport@%p {tr=%p {rc=%ld}}",
             this, transport_.get(), pj_atomic_get(transport_->ref_cnt));
}
std::shared_ptr<TlsListener>
SipTransportBroker::getTlsListener(const SipTransportDescr& d, const pjsip_tls_setting* settings)
{
    RETURN_IF_FAIL(settings, nullptr, "TLS settings not specified");
    auto family = pjsip_transport_type_get_af(d.type);

    IpAddr listeningAddress = (d.interface == ip_utils::DEFAULT_INTERFACE) ?
        ip_utils::getAnyHostAddr(family) :
        ip_utils::getInterfaceAddr(d.interface, family);
    listeningAddress.setPort(d.listenerPort);

    RETURN_IF_FAIL(listeningAddress, nullptr, "Could not determine IP address for this transport");
    RING_DBG("Creating TLS listener %s on %s...", d.toString().c_str(), listeningAddress.toString(true).c_str());
#if 0
    RING_DBG(" ca_list_file : %s", settings->ca_list_file.ptr);
    RING_DBG(" cert_file    : %s", settings->cert_file.ptr);
    RING_DBG(" ciphers_num    : %d", settings->ciphers_num);
    RING_DBG(" verify server %d client %d client_cert %d", settings->verify_server, settings->verify_client, settings->require_client_cert);
    RING_DBG(" reuse_addr    : %d", settings->reuse_addr);
#endif

    pjsip_tpfactory *listener = nullptr;
    const pj_status_t status = pjsip_tls_transport_start2(endpt_, settings, listeningAddress.pjPtr(), nullptr, 1, &listener);
    if (status != PJ_SUCCESS) {
        RING_ERR("TLS listener did not start: %s", sip_utils::sip_strerror(status).c_str());
        return nullptr;
    }
    return std::make_shared<TlsListener>(listener);
}
bool VideoInput::setup()
{
    if (not attach(sink_.get())) {
        RING_ERR("attach sink failed");
        return false;
    }

    if (!sink_->start())
        RING_ERR("start sink failed");

    RING_DBG("VideoInput ready to capture");
    return true;
}