FreeSIP-SIP/VoIP Hub


SIP Projects

SIPp Media Handling

By admin  |  11 May, 2026  |  Comments Off on SIPp Media Handling


SIPp Media Handling Workflow

SIPp’s four media handling modes: RTP Streaming [1a-1f] for file playback, PCAP Playback [2a-2f] for replaying captures, RTP Echo [3a-3e] for reflecting media, and DTMF Generation [4a-4e] for RFC 4733 tones. Key entry points are scenario parsing in scenario.cpp [1a,2a,4a], SDP parsing in call.cpp [2b], and the core engines in rtpstream.cpp [1c-1f,3a-3e], prepare_pcap.c [2c,4b-4d], and send_packets.c [2d-2f,4e].

1. RTP Streaming File Playback

Triggers when scenario executes – plays audio files over RTP using threaded playback engine

1a. Parse rtp_stream XML action (scenario.cpp:1686)

Scenario parser extracts rtp_stream action and sets action type based on command (play, pause, resume, pattern)

else if ((cptr = xp_get_value("rtp_stream"))) {

1b. Cache audio file in memory (actions.cpp:885)

Action execution loads file into global cache once, configures codec parameters based on payload type

if (rtpstream_cache_file(
            M_rtpstream_actinfo.filename,
            pattern_mode /* 0: FILE - 1: PATTERN */,
            M_rtpstream_actinfo.pattern_id,
            M_rtpstream_actinfo.bytes_per_packet,
            stream_type) < 0) {

1c. Bind local RTP socket (rtpstream.cpp:2414)

rtpstream_play() allocates UDP port from min_rtp_port range, binds RTP/RTCP sockets

rtpstream_get_local_audioport(callinfo);

1d. Signal playback start (rtpstream.cpp:2436)

Sets TI_PLAYFILE flag to trigger playback thread to begin sending packets

taskinfo->flags |= TI_PLAYFILE;

1e. Create playback thread (rtpstream.cpp:1456)

rtpstream_start_task() spawns new pthread if no threads have capacity, adds task to thread pool

if (pthread_create(&threadID, nullptr, rtpstream_playback_thread, threaddata)) {

1f. Send RTP packet (rtpstream.cpp:728)

Playback thread builds RTP header with seq/timestamp/SSRC, copies payload, sends via UDP socket

rc = send(taskinfo->audio_rtp_socket, audio_out.data(), audio_out.size(), 0);

2. PCAP Playback

Triggers when scenario executes – replays pre-recorded RTP using raw sockets

2a. Parse play_pcap_audio action (scenario.cpp:1657)

Scenario parser sets E_AT_PLAY_PCAP_AUDIO action type with PCAP filename

} else if ((ptr = xp_get_keyword_value("play_pcap_audio"))) {
                tmpAction->setPcapArgs(ptr);
                tmpAction->setActionType(CAction::E_AT_PLAY_PCAP_AUDIO);

2b. Extract remote media address (call.cpp:198)

get_remote_media_addr() parses SDP from 200 OK to extract destination IP and audio port

std::string port = find_in_sdp("m=audio ", msg);
    if (!port.empty()) {
        gai_getsockaddr(&play_args_a.to, host.c_str(), port.c_str(),
                        AI_NUMERICHOST | AI_NUMERICSERV, family);

2c. Parse PCAP file (prepare_pcap.c:213)

prepare_pkts() opens PCAP, extracts UDP/RTP frames, pre-computes partial checksums

pcap = pcap_open_offline(file, errbuf);
    if (!pcap)
        ERROR("Can't open PCAP file '%s': %s", file, errbuf);

2d. Create raw socket (send_packets.c:177)

send_packets() creates raw UDP socket (requires root privileges) for PCAP replay

sock = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
        if (sock < 0) {
            ERROR("Can't create raw IPv4 socket (need to run as root?): %s", strerror(errno));

2e. Adjust UDP ports (send_packets.c:234)

Modifies source/destination ports relative to SDP-negotiated base port from original capture

udp->uh_sport = htons(port_diff + ntohs(*from_port));
        udp->uh_dport = htons(port_diff + ntohs(*to_port));

2f. Send with original timing (send_packets.c:256)

Sleeps to match inter-packet timing from capture, then sends packet via raw socket

do_sleep ((struct timeval *) &pkt_index->ts, &last, &didsleep,
                  &start);
        ret = sendto(sock, buffer, pkt_index->pktlen, MSG_DONTWAIT,

3. RTP Echo

Triggers when -rtp_echo flag is set – reflects incoming RTP back to sender via dedicated echo threads

3a. Spawn echo thread (rtpstream.cpp:3180)

rtpstream_rtpecho_startaudio() creates pthread for audio echo, sets up SRTP contexts if USE_TLS

if (pthread_create(&pthread_audioecho_id, nullptr, (void *(*) (void *)) rtpstream_audioecho_thread, p.p) == -1) {

3b. Receive RTP packet (rtpstream.cpp:2695)

Echo thread loops on recvfrom() to receive incoming RTP packets on media port

nr = recvfrom(sock, audio_packet_in.data(), audio_packet_in.size(), MSG_DONTWAIT /* NON-BLOCKING */, (sockaddr *) (void *) &remote_rtp_addr, &len);

3c. Decrypt SRTP (if enabled) (rtpstream.cpp:2726)

If SRTP is active, decrypts incoming packet using JLSRTP library

rc = g_rxUASAudio.processIncomingPacket(seq_num, audio_packet_in, rtp_header, payload_data);

3d. Encrypt for echo (if enabled) (rtpstream.cpp:2768)

Re-encrypts packet for transmission back to sender using SRTP

rc = g_txUASAudio.processOutgoingPacket(seq_num, rtp_header, payload_data, audio_packet_out);

3e. Echo packet back (rtpstream.cpp:2777)

Sends packet back to source address, completing echo loop

ns = sendto(sock, audio_packet_out.data(), sizeof(rtp_header_t) + g_txUASAudio.getSrtpPayloadSize() + g_txUASAudio.getAuthenticationTagSize(), MSG_DONTWAIT, (sockaddr *) (void *) &remote_rtp_addr, len);

4. DTMF Generation

Triggers when scenario executes – generates RFC 4733 DTMF event packets

4a. Parse play_dtmf action (scenario.cpp:1672)

Scenario parser sets E_AT_PLAY_DTMF action type with DTMF digit string

} else if ((cptr = xp_get_value("play_dtmf"))) {
                tmpAction->setMessage(cptr);
                tmpAction->setActionType(CAction::E_AT_PLAY_DTMF);

4b. Generate DTMF start packets (prepare_pcap.c:452)

prepare_dtmf_digit_start() builds RFC 4733 event packets with marker bit set for each digit

fill_default_dtmf(dtmfpacket, !marked,
                          *n_pkts + start_seq_no, n_digits * tone_len * 2 + timestamp_start,
                          uc_digit, 0, cur_tone_len);

4c. Generate DTMF end packets (prepare_pcap.c:492)

prepare_dtmf_digit_end() creates 3 packets with end-of-event flag set per RFC 4733

fill_default_dtmf(dtmfpacket, 0,
                          *n_pkts + start_seq_no, n_digits * tone_len * 2 + timestamp_start,
                          uc_digit, 1, tone_len);

4d. Build packet list (prepare_pcap.c:436)

Dynamically allocates packet list and stores generated DTMF packets with timestamps

pkts->pkts = realloc(pkts->pkts, sizeof(*pkts->pkts) * (*n_pkts + 1));
        pkt_index->data = malloc(pktlen);

4e. Send DTMF packets (send_packets.c:260)

send_packets() sends DTMF packets using same raw socket path as PCAP playback with timing

ret = sendto(sock, buffer, pkt_index->pktlen, MSG_DONTWAIT,
admin
admin