@@ -121,30 +121,10 @@ impl ClientInviteDialog {
121121 pub fn cancel_token ( & self ) -> & CancellationToken {
122122 & self . inner . cancel_token
123123 }
124- /// Hang up the call
125- ///
126- /// If the dialog is confirmed, send a BYE request to terminate the call.
127- /// If the dialog is not confirmed, send a CANCEL request to cancel the call.
128- pub async fn hangup ( & self ) -> Result < ( ) > {
129- if self . inner . can_cancel ( ) {
130- self . cancel ( ) . await
131- } else {
132- self . bye ( ) . await
133- }
134- }
135124
136- /// Send a BYE request to terminate the dialog
125+ /// Send a BYE request to terminate the dialog.
137126 ///
138- /// Sends a BYE request to gracefully terminate an established dialog.
139- /// This should only be called for confirmed dialogs. If the dialog
140- /// is not confirmed, this method returns immediately without error.
141- ///
142- /// # Returns
143- ///
144- /// * `Ok(())` - BYE was sent successfully or dialog not confirmed
145- /// * `Err(Error)` - Failed to send BYE request
146- ///
147- /// # Examples
127+ /// Thin wrapper over `bye_with_headers(None)`.
148128 ///
149129 /// ```rust,no_run
150130 /// # use rsipstack::dialog::client_dialog::ClientInviteDialog;
@@ -156,24 +136,102 @@ impl ClientInviteDialog {
156136 /// # }
157137 /// ```
158138 pub async fn bye ( & self ) -> Result < ( ) > {
139+ self . bye_with_headers ( None ) . await
140+ }
141+
142+ /// Send a BYE request with custom headers to terminate the dialog.
143+ ///
144+ /// This is the low-level variant used to add SIP headers (e.g. `Reason`)
145+ /// to the outgoing BYE request.
146+ ///
147+ /// The dialog must be in `Confirmed` state for BYE to be sent; otherwise
148+ /// this method is a no-op.
149+ ///
150+ /// # Parameters
151+ /// * `headers` - Optional extra SIP headers to include in the BYE request.
152+ ///
153+ /// # Returns
154+ /// * `Ok(())` - BYE was sent successfully or dialog is not confirmed.
155+ /// * `Err(Error)` - Failed to build/send BYE request.
156+ pub async fn bye_with_headers ( & self , headers : Option < Vec < rsip:: Header > > ) -> Result < ( ) > {
159157 if !self . inner . is_confirmed ( ) {
160158 return Ok ( ( ) ) ;
161159 }
162- let request = self
163- . inner
164- . make_request ( rsip:: Method :: Bye , None , None , None , None , None ) ?;
165160
166- match self . inner . do_request ( request) . await {
167- Ok ( _) => { }
168- Err ( e) => {
169- info ! ( error = %e, "bye error" ) ;
170- }
171- } ;
161+ let request =
162+ self . inner
163+ . make_request ( rsip:: Method :: Bye , None , None , None , headers, None ) ?;
164+
165+ if let Err ( e) = self . inner . do_request ( request) . await {
166+ info ! ( error = %e, "bye error" ) ;
167+ }
168+
172169 self . inner
173170 . transition ( DialogState :: Terminated ( self . id ( ) , TerminatedReason :: UacBye ) ) ?;
174171 Ok ( ( ) )
175172 }
176173
174+ /// Send a BYE request with a SIP `Reason` header.
175+ ///
176+ /// Convenience wrapper over `bye_with_headers()` that adds:
177+ /// `Reason: <reason>`.
178+ ///
179+ /// Typical values:
180+ /// * `SIP;cause=804;text="MEDIA_TIMEOUT"`
181+ /// * `Q.850;cause=16;text="Normal call clearing"`
182+ ///
183+ /// # Parameters
184+ /// * `reason` - Value of the `Reason` header (without the `Reason:` name).
185+ pub async fn bye_with_reason ( & self , reason : String ) -> Result < ( ) > {
186+ self . bye_with_headers ( Some ( vec ! [ rsip:: Header :: Other (
187+ "Reason" . into( ) ,
188+ reason. into( ) ,
189+ ) ] ) )
190+ . await
191+ }
192+
193+ /// Hang up the call
194+ ///
195+ /// If the dialog is confirmed, send a BYE request to terminate the call.
196+ /// If the dialog is not confirmed, send a CANCEL request to cancel the call.
197+ ///
198+ /// Thin wrapper over `hangup_with_headers(None)`.
199+ pub async fn hangup ( & self ) -> Result < ( ) > {
200+ self . hangup_with_headers ( None ) . await
201+ }
202+
203+ /// Hang up the call with custom headers.
204+ ///
205+ /// If the dialog is still in early phase and can be canceled, this sends `CANCEL`.
206+ /// Headers are not attached to the CANCEL request by default.
207+ ///
208+ /// If the dialog is confirmed, this sends `BYE` and attaches the provided headers.
209+ ///
210+ /// # Parameters
211+ /// * `headers` - Optional extra SIP headers to include when BYE is used.
212+ pub async fn hangup_with_headers ( & self , headers : Option < Vec < rsip:: Header > > ) -> Result < ( ) > {
213+ if self . inner . can_cancel ( ) {
214+ self . cancel ( ) . await
215+ } else {
216+ self . bye_with_headers ( headers) . await
217+ }
218+ }
219+
220+ /// Hang up the call and attach a SIP `Reason` header when BYE is used.
221+ ///
222+ /// Convenience wrapper over `hangup_with_headers()` that adds:
223+ /// `Reason: <reason>`.
224+ ///
225+ /// # Parameters
226+ /// * `reason` - Value of the `Reason` header used for BYE.
227+ pub async fn hangup_with_reason ( & self , reason : String ) -> Result < ( ) > {
228+ self . hangup_with_headers ( Some ( vec ! [ rsip:: Header :: Other (
229+ "Reason" . into( ) ,
230+ reason. into( ) ,
231+ ) ] ) )
232+ . await
233+ }
234+
177235 /// Send a CANCEL request to cancel an ongoing INVITE
178236 ///
179237 /// Sends a CANCEL request to cancel an INVITE transaction that has not
0 commit comments