rvoip_sip_core/lib.rs
1//! # rvoip-sip-core
2//!
3//! Core SIP protocol implementation for the rvoip VoIP stack.
4//!
5//! This crate provides a complete, RFC-compliant implementation of the Session Initiation Protocol (SIP),
6//! including message parsing, serialization, and manipulation. It serves as the foundation for building
7//! SIP-based communication systems like VoIP clients, proxies, and servers.
8//!
9//! ## Overview
10//!
11//! The crate is structured around the following key components:
12//!
13//! - **Message Types**: Core SIP message abstractions ([`Request`], [`Response`], [`Message`])
14//! - **Header Types**: Strongly-typed SIP headers with parsing and serialization
15//! - **URI Handling**: Comprehensive SIP URI parsing and manipulation
16//! - **SDP Support**: Session Description Protocol integration
17//! - **Parsing**: Robust, efficient, and RFC-compliant message parsing
18//! - **Builder Patterns**: Fluent APIs for constructing SIP and SDP messages
19//! - **Macros**: Convenient macros for creating SIP requests and responses
20//!
21//! ## Getting Started
22//!
23//! ### Creating SIP Messages
24//!
25//! The recommended way to create SIP messages is to use either the builder pattern or macros:
26//!
27//! #### Using the Builder Pattern (recommended for complex messages)
28//!
29//! ```rust
30//! use rvoip_sip_core::prelude::*;
31//!
32//! // Create a SIP request with the RequestBuilder
33//! let request = RequestBuilder::new(Method::Invite, "sip:bob@example.com").unwrap()
34//! .from("Alice", "sip:alice@example.com", Some("1928301774"))
35//! .to("Bob", "sip:bob@example.com", None)
36//! .call_id("a84b4c76e66710@pc33.atlanta.com")
37//! .cseq(314159)
38//! .via("pc33.atlanta.com", "UDP", Some("z9hG4bK776asdhds"))
39//! .max_forwards(70)
40//! .contact("sip:alice@pc33.atlanta.com", None)
41//! .content_type("application/sdp")
42//! .body("v=0\r\no=alice 123 456 IN IP4 127.0.0.1\r\ns=A call\r\nt=0 0\r\n")
43//! .build();
44//!
45//! // Create a SIP response with the ResponseBuilder
46//! let response = ResponseBuilder::new(StatusCode::Ok, Some("OK"))
47//! .from("Alice", "sip:alice@example.com", Some("1928301774"))
48//! .to("Bob", "sip:bob@example.com", Some("a6c85cf"))
49//! .call_id("a84b4c76e66710@pc33.atlanta.com")
50//! .cseq(1, Method::Invite)
51//! .via("pc33.atlanta.com", "UDP", Some("z9hG4bK776asdhds"))
52//! .contact("sip:bob@192.168.1.2", None)
53//! .content_type("application/sdp")
54//! .body("v=0\r\no=bob 123 456 IN IP4 192.168.1.2\r\ns=A call\r\nt=0 0\r\n")
55//! .build();
56//! ```
57//!
58//! #### Using Macros (recommended for simple messages)
59//!
60//! ```ignore
61//! use rvoip_sip_core::prelude::*;
62//! use rvoip_sip_core::{sip_request, sip_response};
63//!
64//! // Create a SIP request with the sip_request! macro
65//! let request = sip_request! {
66//! method: Method::Invite,
67//! uri: "sip:bob@example.com",
68//! from_name: "Alice",
69//! from_uri: "sip:alice@example.com",
70//! from_tag: "1928301774",
71//! call_id: "a84b4c76e66710",
72//! cseq: 1
73//! };
74//!
75//! // Create a SIP response with the sip_response! macro
76//! let response = sip_response! {
77//! status: StatusCode::Ok,
78//! reason: "OK",
79//! from_name: "Alice",
80//! from_uri: "sip:alice@example.com",
81//! to_name: "Bob",
82//! to_uri: "sip:bob@example.com",
83//! call_id: "a84b4c76e66710",
84//! cseq: 1,
85//! cseq_method: Method::Invite
86//! };
87//! ```
88//!
89//! ### Creating SDP Messages
90//!
91//! For SDP messages, you can use either the SdpBuilder (for programmatic creation) or the sdp! macro (for declarative creation):
92//!
93//! #### Using the SdpBuilder Pattern
94//!
95//! ```rust
96//! use rvoip_sip_core::sdp_prelude::*;
97//!
98//! // Create an SDP session with the SdpBuilder
99//! let sdp = SdpBuilder::new("My Session")
100//! .origin("-", "1234567890", "2", "IN", "IP4", "127.0.0.1")
101//! .time("0", "0") // Time 0-0 means permanent session
102//! .media_audio(49170, "RTP/AVP")
103//! .formats(&["0", "8"])
104//! .direction(MediaDirection::SendRecv)
105//! .rtpmap("0", "PCMU/8000")
106//! .rtpmap("8", "PCMA/8000")
107//! .done()
108//! .build();
109//! ```
110//!
111//! #### Using the sdp! Macro (recommended for simple messages)
112//!
113//! ```rust
114//! use rvoip_sip_core::sdp;
115//! use rvoip_sip_core::sdp_prelude::*;
116//!
117//! // Create an SDP session with the sdp! macro
118//! let sdp_result = sdp! {
119//! origin: ("-", "1234567890", "2", "IN", "IP4", "192.168.1.100"),
120//! session_name: "Audio Call",
121//! connection: ("IN", "IP4", "192.168.1.100"),
122//! time: ("0", "0"),
123//! media: {
124//! type: "audio",
125//! port: 49170,
126//! protocol: "RTP/AVP",
127//! formats: ["0", "8"],
128//! rtpmap: ("0", "PCMU/8000"),
129//! rtpmap: ("8", "PCMA/8000"),
130//! direction: "sendrecv"
131//! }
132//! };
133//!
134//! let sdp = sdp_result.expect("Valid SDP");
135//! ```
136//!
137//! ### Parsing SIP Messages
138//!
139//! The library provides robust parsing for SIP messages:
140//!
141//! ```rust
142//! use rvoip_sip_core::prelude::*;
143//! use bytes::Bytes;
144//!
145//! // Parse a SIP message from bytes
146//! let data = Bytes::from(
147//! "INVITE sip:bob@example.com SIP/2.0\r\n\
148//! Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds\r\n\
149//! Max-Forwards: 70\r\n\
150//! To: Bob <sip:bob@example.com>\r\n\
151//! From: Alice <sip:alice@atlanta.com>;tag=1928301774\r\n\
152//! Call-ID: a84b4c76e66710@pc33.atlanta.com\r\n\
153//! CSeq: 314159 INVITE\r\n\
154//! Contact: <sip:alice@pc33.atlanta.com>\r\n\
155//! Content-Type: application/sdp\r\n\
156//! Content-Length: 0\r\n\r\n"
157//! );
158//!
159//! let message = parse_message(&data).expect("Valid SIP message");
160//!
161//! // Access message components
162//! if let Message::Request(request) = message {
163//! assert_eq!(request.method(), Method::Invite);
164//! assert_eq!(request.uri().to_string(), "sip:bob@example.com");
165//!
166//! // Get headers and display them
167//! if let Some(from_header) = request.header(&HeaderName::From) {
168//! println!("From: {}", from_header);
169//! }
170//! if let Some(to_header) = request.header(&HeaderName::To) {
171//! println!("To: {}", to_header);
172//! }
173//! }
174//! ```
175//!
176//! ## Parsing Modes
177//!
178//! The library supports different parsing modes to handle various levels of RFC compliance:
179//!
180//! ```rust
181//! use rvoip_sip_core::prelude::*;
182//! use bytes::Bytes;
183//!
184//! let data = Bytes::from("SIP message data...");
185//!
186//! // Standard parsing mode
187//! let message = parse_message(&data);
188//!
189//! // Custom parsing mode
190//! let strict_message = parse_message_with_mode(&data, ParseMode::Strict);
191//! ```
192//!
193//! ## Feature Flags
194//!
195//! - `lenient_parsing` - Enables more lenient parsing mode for torture tests and handling of non-compliant messages
196
197// Re-export core types and parsers
198
199// Declare modules
200pub mod error;
201pub mod types;
202pub mod builder;
203pub mod parser;
204pub mod macros;
205#[cfg(feature = "sdp")]
206pub mod sdp;
207/// JSON representation and access layer for SIP types
208pub mod json;
209/// Prelude module that exports commonly used types and traits
210pub mod prelude;
211/// SDP prelude module that exports SDP-related types and traits
212#[cfg(feature = "sdp")]
213pub mod sdp_prelude;
214
215// Re-export key public items
216pub use error::{Error, Result};
217pub use types::header::{Header, HeaderValue, TypedHeader, TypedHeaderTrait};
218pub use types::headers::HeaderName;
219pub use types::Method;
220pub use parser::parse_message;
221pub use parser::message::parse_message_with_mode;
222pub use parser::message::ParseMode;
223pub use types::StatusCode;
224pub use types::{
225 Address,
226 CallId,
227 Contact,
228 ContentDisposition,
229 ContentLength,
230 ContentType,
231 CSeq,
232 Expires,
233 From,
234 MaxForwards,
235 MediaType,
236 sip_message::Message,
237 sip_request::Request,
238 sip_response::Response,
239 sdp::SdpSession,
240 Via, // Changed from via::Via
241 Warning,
242 warning::{WarnAgent, WarningValue},
243 sdp::MediaDescription,
244 sdp::Origin,
245 sdp::ConnectionData,
246 sdp::TimeDescription,
247 auth::*,
248 sdp::ParsedAttribute,
249 sdp::RtpMapAttribute,
250 sdp::FmtpAttribute,
251 sdp::CandidateAttribute,
252 sdp::SsrcAttribute,
253 sdp::RepeatTime,
254 Version,
255 Allow,
256 Accept,
257 Subject,
258 CallInfo,
259};
260pub use types::uri::{Uri, Host};
261#[cfg(feature = "sdp")]
262pub use sdp::attributes::MediaDirection;
263#[cfg(feature = "sdp")]
264pub use sdp::parser::{
265 validate_sdp,
266 validate_network_type,
267 validate_address_type,
268 is_valid_address,
269 is_valid_ipv4,
270 is_valid_ipv6,
271 is_valid_hostname,
272 parse_bandwidth_line,
273 parse_sdp
274};
275pub use builder::{SimpleRequestBuilder as RequestBuilder, SimpleResponseBuilder as ResponseBuilder};
276pub use macros::*;
277
278#[cfg(test)]
279mod tests {
280 #[test]
281 fn it_works() {
282 let result = 2 + 2;
283 assert_eq!(result, 4);
284 }
285}