@@ -231,7 +231,7 @@ def __init__(self, sdp_info: SdpInfo) -> None:
231
231
232
232
def outgoing_call (
233
233
self , source : SipEndpoint , destination : SipEndpoint , rtp_port : int
234
- ):
234
+ ) -> CallInfo :
235
235
"""Make an outgoing call from the given source endpoint to the destination endpoint, using the rtp_port for the local RTP port of the call."""
236
236
if self .transport is None :
237
237
raise RuntimeError ("No transport available for outgoing call." )
@@ -289,6 +289,14 @@ def outgoing_call(
289
289
(destination .host , destination .port ),
290
290
)
291
291
292
+ return CallInfo (
293
+ caller_endpoint = destination ,
294
+ local_endpoint = source ,
295
+ caller_rtp_port = rtp_port ,
296
+ server_ip = source .host ,
297
+ headers = {"call-id" : call_id },
298
+ )
299
+
292
300
def hang_up (self , call_info : CallInfo ):
293
301
"""Hang up the call when finished"""
294
302
if self .transport is None :
@@ -315,6 +323,33 @@ def hang_up(self, call_info: CallInfo):
315
323
self ._end_outgoing_call (call_info .headers ["call-id" ])
316
324
self .on_hangup (call_info )
317
325
326
+ def cancel_call (self , call_info : CallInfo ):
327
+ """Cancel an outgoing call while it's still ringing."""
328
+ if self .transport is None :
329
+ raise RuntimeError ("No transport available for sending cancel." )
330
+
331
+ cancel_lines = [
332
+ f"CANCEL { call_info .caller_endpoint .uri } SIP/2.0" ,
333
+ f"Via: SIP/2.0/UDP { call_info .local_endpoint .host } :{ call_info .local_endpoint .port } " ,
334
+ f"From: { call_info .local_endpoint .sip_header } " ,
335
+ f"To: { call_info .caller_endpoint .sip_header } " ,
336
+ f"Call-ID: { call_info .headers ['call-id' ]} " ,
337
+ "CSeq: 51 CANCEL" ,
338
+ f"User-Agent: { VOIP_UTILS_AGENT } 1.0" ,
339
+ "Content-Length: 0" ,
340
+ "" ,
341
+ ]
342
+ _LOGGER .debug ("Canceling call..." )
343
+ cancel_text = _CRLF .join (cancel_lines ) + _CRLF
344
+ cancel_bytes = cancel_text .encode ("utf-8" )
345
+ self .transport .sendto (
346
+ cancel_bytes ,
347
+ (call_info .caller_endpoint .host , call_info .caller_endpoint .port ),
348
+ )
349
+
350
+ self ._end_outgoing_call (call_info .headers ["call-id" ])
351
+ self .on_hangup (call_info )
352
+
318
353
def _register_outgoing_call (self , call_id : str , rtp_port : int ):
319
354
"""Register the RTP port associated with an outgoing call."""
320
355
self ._outgoing_calls [call_id ] = rtp_port
0 commit comments