This is a simple SIP echo server written in Rust. It listens for incoming SIP calls, establishes an RTP session, and echoes back any received RTP media packets after a short delay.
The application is designed with a modular architecture to separate concerns.
The main components are:
main.rs: The application entry point. It initializes the server, sets up the SIP endpoint, and dispatches incoming SIP transactions.config.rs: Stores all static configuration values, such as IP addresses, ports, and echo delay.sip.rs: Contains the core SIP signaling logic. It handles different SIP methods like INVITE, ACK, and BYE.sdp.rs: Responsible for parsing incoming SDP offers and generating SDP answers to negotiate media sessions.rtp_session.rs: Manages the RTP media stream. It binds to an RTP port, receives packets, buffers them, and sends them back to the caller.
graph TD
subgraph Application
A[main.rs] --> B{SIP Endpoint};
B -- SIP Transaction --> C[sip.rs];
C -- Needs SDP --> D[sdp.rs];
C -- Needs RTP Session --> E[rtp_session.rs];
E -- Needs Config --> F[config.rs];
D -- Needs Config --> F;
end
The following sequence diagram illustrates the flow of a typical call:
sequenceDiagram
participant Client
participant Server
Client->>Server: INVITE (with SDP Offer)
Server->>Server: sip.rs: handle_invite()
Server->>Server: sdp.rs: parse_sdp_offer()
Server->>Server: rtp_session.rs: RtpSession::new()
Server->>Server: sdp.rs: create_sdp_answer()
Server-->>Client: 200 OK (with SDP Answer)
Client->>Server: ACK
Server->>Server: sip.rs: handle_transaction(ACK)
loop Media Exchange
Client->>Server: RTP Media Packets
Server->>Server: rtp_session.rs: Echoes packets after delay
Server-->>Client: Echoed RTP Media Packets
end
Client->>Server: BYE
Server->>Server: sip.rs: handle_transaction(BYE)
Server-->>Client: 200 OK