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

Segfault with invalid RTP #3677

Closed
2 of 13 tasks
obinnaokechukwu opened this issue Aug 22, 2024 · 1 comment · Fixed by bluenviron/gortsplib#604
Closed
2 of 13 tasks

Segfault with invalid RTP #3677

obinnaokechukwu opened this issue Aug 22, 2024 · 1 comment · Fixed by bluenviron/gortsplib#604
Labels
bug Something isn't working rtsp

Comments

@obinnaokechukwu
Copy link

obinnaokechukwu commented Aug 22, 2024

Which version are you using?

v1.8.5

Which operating system are you using?

  • Linux amd64 standard
  • Linux amd64 Docker
  • Linux arm64 standard
  • Linux arm64 Docker
  • Linux arm7 standard
  • Linux arm7 Docker
  • Linux arm6 standard
  • Linux arm6 Docker
  • Windows amd64 standard
  • Windows amd64 Docker (WSL backend)
  • macOS amd64 standard
  • macOS amd64 Docker
  • Other (please describe)

Describe the issue

Description

Describe how to replicate the issue

  1. start the server
  2. publish rtp with the code below
  3. server crashes
import socket
import time
import random
import threading

# MediaMTX server details
MEDIAMTX_IP = '127.0.0.1'
MEDIAMTX_PORT = 8554

# RTSP parameters
STREAM_NAME = 'mystream'
RTSP_URL = f'rtsp://{MEDIAMTX_IP}:{MEDIAMTX_PORT}/{STREAM_NAME}'

# RTP parameters
RTP_PAYLOAD_TYPE = 96  # Dynamic payload type
TIMESTAMP = 0  # Fixed timestamp as requested

def create_rtsp_request(method, url, seq, session=None, content=None, headers=None):
    request = f"{method} {url} RTSP/1.0\r\n"
    request += f"CSeq: {seq}\r\n"
    if session:
        request += f"Session: {session}\r\n"
    if headers:
        for key, value in headers.items():
            request += f"{key}: {value}\r\n"
    if content:
        request += f"Content-Length: {len(content)}\r\n"
    request += "\r\n"
    if content:
        request += content
    return request.encode()

def create_rtp_packet(payload, seq_num):
    version = 2
    padding = 0
    extension = 0
    csrc_count = 0
    marker = 0
    ssrc = random.randint(0, 0xFFFFFFFF)

    header = bytearray(12)
    header[0] = (version << 6) | (padding << 5) | (extension << 4) | csrc_count
    header[1] = (marker << 7) | RTP_PAYLOAD_TYPE
    header[2:4] = seq_num.to_bytes(2, byteorder='big')
    header[4:8] = TIMESTAMP.to_bytes(4, byteorder='big')
    header[8:12] = ssrc.to_bytes(4, byteorder='big')

    return header + payload

def send_rtcp(sock, dest):
    # Simplified RTCP sender report
    rtcp_packet = bytearray(28)
    rtcp_packet[0] = 0x80  # Version 2, no padding, report count 0
    rtcp_packet[1] = 200  # Packet type: Sender Report
    rtcp_packet[2:4] = (6).to_bytes(2, byteorder='big')  # Length
    # SSRC, NTP timestamp, RTP timestamp, packet count, and octet count are set to 0 for simplicity
    sock.sendto(rtcp_packet, dest)

def keep_alive(rtsp_socket, session_id, seq):
    while True:
        time.sleep(50)  # Send keep-alive every 50 seconds
        seq[0] += 1
        request = create_rtsp_request("GET_PARAMETER", RTSP_URL, seq[0], session_id)
        rtsp_socket.send(request)
        response = rtsp_socket.recv(1024)
        print("Keep-alive response:", response.decode())

def main():
    rtsp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    rtsp_socket.connect((MEDIAMTX_IP, MEDIAMTX_PORT))

    seq = [1]  # Use a list so it can be modified in the keep_alive function

    # OPTIONS
    rtsp_socket.send(create_rtsp_request("OPTIONS", RTSP_URL, seq[0]))
    response = rtsp_socket.recv(1024)
    print("OPTIONS response:", response.decode())

    # ANNOUNCE
    seq[0] += 1
    sdp_content = (
        "v=0\r\n"
        "o=- 0 0 IN IP4 127.0.0.1\r\n"
        "s=My Stream\r\n"
        "c=IN IP4 127.0.0.1\r\n"
        "t=0 0\r\n"
        "m=video 0 RTP/AVP 96\r\n"
        "a=rtpmap:96 H264/90000\r\n"
        "a=control:streamid=0\r\n"
    )
    headers = {"Content-Type": "application/sdp"}
    rtsp_socket.send(create_rtsp_request("ANNOUNCE", RTSP_URL, seq[0], content=sdp_content, headers=headers))
    response = rtsp_socket.recv(1024)
    print("ANNOUNCE response:", response.decode())

    # SETUP
    seq[0] += 1
    rtp_port = random.randint(10000, 65000)
    rtcp_port = rtp_port + 1
    headers = {"Transport": f"RTP/AVP;unicast;client_port={rtp_port}-{rtcp_port}"}
    rtsp_socket.send(create_rtsp_request("SETUP", f"{RTSP_URL}/streamid=0", seq[0], headers=headers))
    response = rtsp_socket.recv(1024)
    print("SETUP response:", response.decode())
    session_id = response.decode().split("Session: ")[1].split("\r\n")[0].split(";")[0]

    # Create UDP sockets for RTP and RTCP
    rtp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    rtp_socket.bind(('0.0.0.0', rtp_port))
    rtcp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    rtcp_socket.bind(('0.0.0.0', rtcp_port))

    # Extract server ports from SETUP response
    transport_line = [line for line in response.decode().split('\r\n') if line.startswith('Transport:')][0]
    server_ports = transport_line.split('server_port=')[1].split('-')
    server_rtp_port, server_rtcp_port = map(int, server_ports)

    # PLAY
    seq[0] += 1
    headers = {"Range": "npt=0.000-"}
    rtsp_socket.send(create_rtsp_request("PLAY", RTSP_URL, seq[0], session_id, headers=headers))
    response = rtsp_socket.recv(1024)
    print("PLAY response:", response.decode())

    # Start keep-alive thread
    keep_alive_thread = threading.Thread(target=keep_alive, args=(rtsp_socket, session_id, seq))
    keep_alive_thread.daemon = True
    keep_alive_thread.start()

    # RTP Streaming
    rtp_seq_num = 0
    try:
        while True:
            # Generate some dummy payload
            payload = b"Dummy RTP payload"
            rtp_packet = create_rtp_packet(payload, rtp_seq_num)
            
            rtp_socket.sendto(rtp_packet, (MEDIAMTX_IP, server_rtp_port))
            
            if rtp_seq_num % 100 == 0:  # Send RTCP packet every 100 RTP packets
                send_rtcp(rtcp_socket, (MEDIAMTX_IP, server_rtcp_port))
            
            rtp_seq_num = (rtp_seq_num + 1) % 65536
            time.sleep(0.04)  # 25 fps
    except KeyboardInterrupt:
        print("Streaming interrupted. Sending TEARDOWN request.")
    finally:
        # TEARDOWN
        seq[0] += 1
        rtsp_socket.send(create_rtsp_request("TEARDOWN", RTSP_URL, seq[0], session_id))
        response = rtsp_socket.recv(1024)
        print("TEARDOWN response:", response.decode())
        
        rtsp_socket.close()
        rtp_socket.close()
        rtcp_socket.close()

if __name__ == "__main__":
    main()

Did you attach the server logs?

yes

2024/08/22 00:39:33 INF MediaMTX v1.8.5
2024/08/22 00:39:33 INF configuration loaded from /mediamtx.yml
2024/08/22 00:39:33 INF [RTSP] listener opened on :8554 (TCP), :8000 (UDP/RTP), :8001 (UDP/RTCP)
2024/08/22 00:39:33 INF [RTMP] listener opened on :1935
2024/08/22 00:39:33 INF [HLS] listener opened on :8888
2024/08/22 00:39:33 INF [WebRTC] listener opened on :8889 (HTTP), :8189 (ICE/UDP)
2024/08/22 00:39:33 INF [SRT] listener opened on :8890 (UDP)
2024/08/22 00:39:39 INF [RTSP] [conn xxx.xxx.xxx.xxx:47005] opened
2024/08/22 00:39:39 INF [RTSP] [session fa657109] created by xxx.xxx.xxx.xxx:47005
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x81c5b3]

goroutine 32 [running]:
github.com/bluenviron/gortsplib/v4.(*ServerSession).handleRequestInner(0xc00011e000, 0xc0000b0480, 0xc0001fe700)
	/go/pkg/mod/github.com/bluenviron/gortsplib/v4@v4.10.3/server_session.go:744 +0x1853
github.com/bluenviron/gortsplib/v4.(*ServerSession).runInner(0xc00011e000)
	/go/pkg/mod/github.com/bluenviron/gortsplib/v4@v4.10.3/server_session.go:403 +0x2f5
github.com/bluenviron/gortsplib/v4.(*ServerSession).run(0xc00011e000)
	/go/pkg/mod/github.com/bluenviron/gortsplib/v4@v4.10.3/server_session.go:356 +0x125
created by github.com/bluenviron/gortsplib/v4.(*ServerSession).initialize in goroutine 11
	/go/pkg/mod/github.com/bluenviron/gortsplib/v4@v4.10.3/server_session.go:232 +0x3c5

Did you attach a network dump?

yes / no

@aler9
Copy link
Member

aler9 commented Aug 23, 2024

Hello, thank you very much for reporting the panic, this is fixed by bluenviron/gortsplib#604

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working rtsp
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants