Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to forward to another client and reply from server #228

Open
5secorg opened this issue Sep 24, 2024 · 3 comments
Open

How to forward to another client and reply from server #228

5secorg opened this issue Sep 24, 2024 · 3 comments
Labels
question Further information is requested

Comments

@5secorg
Copy link

5secorg commented Sep 24, 2024

Hi everyone, I am having trouble forwarding to every client that I send. Can you help me or suggest a way to get the data from RTP server?

My other question is: Can RTP respond to the Client? (I'm new to this) I want to create a Basic audio voice chat and this Framework has Opus support so it's of interest to me.

#include <uvgrtp/lib.hh>
#include <climits>
#include <cstring>
#include <vector>
#include <iostream>

 // Network parameters of this example
constexpr char      SEND_ADDR[] = "127.0.0.1";
constexpr char      RECV_ADDR[] = "0.0.0.0";
constexpr uint16_t  SEND_PORT   = 9930;
constexpr uint16_t  RECV_PORT   = 9932;

/* Save audio and video ssrcs for telling streams from each other */
uint32_t audio_ssrc = 0;

void rtp_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame)
{
    uvgrtp::media_stream* receiver_stream = static_cast<uvgrtp::media_stream*>(arg);

    /* Check which ssrcs belong to which streams */
    if (frame->header.payload == RTP_FORMAT_OPUS) {
        if (audio_ssrc == 0) {
            audio_ssrc = frame->header.ssrc;
        }

        if (receiver_stream->push_frame(frame->payload, frame->payload_len, RTP_NO_FLAGS) != RTP_OK)
            std::cout << "Failed to forward data" << std::endl;
        else
            std::cout << "Forward audio data..." << std::endl;
    }

    (void)uvgrtp::frame::dealloc_frame(frame);
}

void sender_hook(uvgrtp::frame::rtcp_sender_report* frame)
{
    uint64_t current_ntp = uvgrtp::clock::ntp::now();
    uint32_t msw = frame->sender_info.ntp_msw;
    uint32_t lsw = frame->sender_info.ntp_lsw;
    uint64_t ntp_ts = (uint64_t(msw) << 32) | lsw;
    uint64_t diff_ms = uvgrtp::clock::ntp::diff(ntp_ts, current_ntp);

    if (frame->ssrc == audio_ssrc) {
        std::cout << "Audio stream RTCP sender report! ----------" << std::endl;
    }

    /* This pair can be used to synchronize the streams */
    std::cout << "---RTP timestamp: " << frame->sender_info.rtp_ts << std::endl;
    std::cout << "---NTP timestamp: " << ntp_ts << std::endl;

    /* Latency between sending and receiving in milliseconds */
    std::cout << "---Difference between SR generation and current NTP time (ms): " << diff_ms << std::endl;

    /* RTCP frames can be deallocated using delete */
    delete frame;
}

void receive_function(uvgrtp::session* receiver_session, int flags,
    std::shared_ptr<std::mutex> print_mutex,
    RTP_FORMAT format, uint16_t receiver_port, uint16_t sender_port)
{

    print_mutex->lock();
    std::cout << "Receiver thread port: " << receiver_port << "<-" << sender_port << std::endl;
    print_mutex->unlock();

    uvgrtp::media_stream* stream_recv =
        receiver_session->create_stream(receiver_port, sender_port, format, flags);

    uvgrtp::media_stream* stream_send =
        receiver_session->create_stream(sender_port, receiver_port, format, flags);

    if (!stream_recv || stream_recv->get_rtcp()->install_sender_hook(sender_hook) != RTP_OK)
    {
        std::cerr << "Failed to install RTCP sender report hook" << std::endl;
    }

    if (!stream_recv || stream_recv->install_receive_hook(stream_recv, rtp_receive_hook) != RTP_OK)
    {
        std::cerr << "Failed to install RTP reception hook";
        return;
    }
}

int main(void)
{
    std::cout << "Starting uvgRTP RTCP stream synchronization example" << std::endl;

    std::shared_ptr<std::mutex> print_mutex = std::shared_ptr<std::mutex>(new std::mutex);
    unsigned rce_dh_flags = RCE_RTCP;
    unsigned rce_multistream_flags = RCE_RTCP;

    std::cout << "Initializing receivers" << std::endl;
    uvgrtp::context receiver_ctx;
    uvgrtp::session* receiver_session = receiver_ctx.create_session(
        SEND_ADDR/*remote address*/,
        RECV_ADDR/*local address*/
    );

    // start the audio and video receivers in different threads
    std::thread a_receiver(receive_function, receiver_session, rce_dh_flags, print_mutex,
        RTP_FORMAT_OPUS, RECV_PORT, SEND_PORT);


    std::cout << "Press 'enter' to continue" << std::endl;

    std::cin.get();

    // wait until all threads have ended
    if (a_receiver.joinable())
        a_receiver.join();



    if (receiver_session)
        receiver_ctx.destroy_session(receiver_session);

    std::cout << "RTCP stream synchronization example finished" << std::endl;
    return EXIT_SUCCESS;
}

If I want to send data from Server to Client, how should I do it? Please help me. Thank you.

@jrsnen
Copy link
Member

jrsnen commented Sep 25, 2024

Hello @5secorg

Clients should send their IP address to the sender somehow (outside the scope of uvgRTP, any method will do). Once the server has the IP address, it can start sending data there. To bypass firewalls, the client needs to send something in the opposite direction. You can use the RCE_HOLEPUNCH_KEEPALIVE enable flag for this, just make sure the session address and media_stream ports are exactly the same (but reversed) in the client and the server.

Hope this helps,
Joni Räsänen

@jrsnen jrsnen added the question Further information is requested label Sep 25, 2024
@5secorg
Copy link
Author

5secorg commented Sep 25, 2024

@jrsnen Do you mean creating a UDP Socket yourself and just forwarding the frame to the Client?

@jrsnen
Copy link
Member

jrsnen commented Sep 25, 2024

For getting the IP address, I would recommend TCP or TLS.

For forwarding the packets you can either create the sockets yourself and just forward the packets or you can use uvgRTP for receiving and sending. Both methods should work and have their own upsides and downsides.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants