Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 60 additions & 19 deletions baresipy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@


class BareSIP(Thread):
def __init__(self, user, pwd, gateway, transport="udp", tts=None, debug=False,
block=True, config_path=None, sounds_path=None):
def __init__(self, user, pwd, gateway, transport="udp", other_sip_configs="", tts=None, debug=False,
block=True, config_path=None, sounds_path=None, auto_start_process=True):
config_path = config_path or join("~", ".baresipy")
self.config_path = expanduser(config_path)
if not isdir(self.config_path):
Expand Down Expand Up @@ -62,12 +62,8 @@ def __init__(self, user, pwd, gateway, transport="udp", tts=None, debug=False,
self.pwd = pwd
self.gateway = gateway
self.transport = transport
if tts:
self.tts = tts
else:
self.tts = ResponsiveVoice(gender=ResponsiveVoice.MALE)
self._login = "sip:{u}@{g};transport={t};auth_pass={p}".format(u=self.user, p=self.pwd,
g=self.gateway, t=self.transport)
self.block = block
self.started_once = False
self._prev_output = ""
self.running = False
self.ready = False
Expand All @@ -77,10 +73,28 @@ def __init__(self, user, pwd, gateway, transport="udp", tts=None, debug=False,
self._call_status = None
self.audio = None
self._ts = None
self.baresip = pexpect.spawn('baresip -f ' + self.config_path)
self.baresip = None

if tts:
self.tts = tts
else:
self.tts = ResponsiveVoice(gender=ResponsiveVoice.MALE)
self._server = "sip:{u}@{g}".format(u=self.user, g=self.gateway)
self._login = self._server + ";transport={t};auth_pass={p};{o};".format(
p=self.pwd, t=self.transport, o=other_sip_configs
).replace(';;', ';').rstrip(';')

if auto_start_process:
self.start_process()

def start_process(self):
if self.started_once:
LOG.error('Python Thread Instance cannot be started more than once. Please create a new BareSIP instance')
return
self.started_once = True
super().__init__()
self.start()
if block:
if self.block:
self.wait_until_ready()

# properties
Expand All @@ -104,6 +118,10 @@ def do_command(self, action):
def login(self):
LOG.info("Adding account: " + self.user)
self.baresip.sendline("/uanew " + self._login)

def logout(self):
LOG.info("Removing account: " + self.user)
self.baresip.sendline("/uadelall")

def call(self, number):
LOG.info("Dialling: " + number)
Expand Down Expand Up @@ -165,23 +183,34 @@ def check_call_status(self):
self.do_command("/callstat")
sleep(0.1)
return self.call_status

def killBareSIPSubProcess(self):
if self.baresip != None and self.baresip.isalive():
LOG.info("Killing BareSip process")
self.baresip.sendline("/quit")
self.baresip.close()
self.baresip.kill(signal.SIGKILL)
self.baresip = None # this would prompt the run() loop to call startBareSIPProcess

def startBareSIPSubProcess(self):
LOG.info("Starting BareSip process")
self.baresip = pexpect.spawn('baresip -f ' + self.config_path)

def quit(self):
if self.updated_config:
LOG.info("restoring original config")
with open(join(self.config_path, "config"), "w") as f:
f.write(self._original_config)
LOG.info("Exiting")
LOG.info("Closing BareSIP instance")
if self.running:
if self.current_call:
self.hang()
self.baresip.sendline("/quit")
self.running = False
self.current_call = None
self._call_status = None
self.abort = True
self.baresip.close()
self.baresip.kill(signal.SIGKILL)

self.killBareSIPSubProcess()
self.current_call = None
self._call_status = None
self.abort = True
self.running = False

def send_dtmf(self, number):
number = str(number)
Expand Down Expand Up @@ -334,6 +363,14 @@ def run(self):
self.running = True
while self.running:
try:
if self.baresip == None:
self.startBareSIPSubProcess()
continue
if not self.baresip.isalive():
self.killBareSIPSubProcess()
sleep(0.5)
continue

out = self.baresip.readline().decode("utf-8")

if out != self._prev_output:
Expand All @@ -344,7 +381,8 @@ def run(self):
self.handle_ready()
elif "account: No SIP accounts found" in out:
self._handle_no_accounts()
elif "All 1 useragent registered successfully!" in out:
# elif "All 1 useragent registered successfully!" in out or\
elif "200 OK" in out:
self.ready = True
self.handle_login_success()
elif "ua: SIP register failed:" in out or\
Expand Down Expand Up @@ -445,6 +483,9 @@ def run(self):
pass
except KeyboardInterrupt:
self.running = False
except:
# Uncaught Exception. Gracefully quit
self.running = False
Comment on lines +486 to +488
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace bare except with more specific exception handling.

The bare except: clause can hide programming errors and make debugging difficult. Consider catching Exception instead to allow system exits and keyboard interrupts to propagate properly.

Apply this diff to improve exception specificity:

-            except:
+            except Exception as e:
+                LOG.exception("Unexpected error in event loop: %s", e)
                # Uncaught Exception. Gracefully quit
                self.running = False
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
except:
# Uncaught Exception. Gracefully quit
self.running = False
except Exception as e:
LOG.exception("Unexpected error in event loop: %s", e)
# Uncaught Exception. Gracefully quit
self.running = False
🧰 Tools
🪛 Ruff (0.11.9)

467-467: Do not use bare except

(E722)

🪛 Flake8 (7.2.0)

[error] 467-467: do not use bare 'except'

(E722)

🪛 Pylint (3.3.7)

[refactor] 354-469: Too many nested blocks (6/5)

(R1702)

🤖 Prompt for AI Agents
In baresipy/__init__.py around lines 467 to 469, replace the bare except clause
with except Exception to avoid catching system-exiting exceptions like
KeyboardInterrupt and SystemExit. Change the except line to except Exception: so
that only regular exceptions are caught, allowing proper propagation of system
exit signals.


self.quit()

Expand Down