Skip to content

Commit ce138c8

Browse files
authored
Fix PPP Errors with disconnect and routing (#32)
Fix #30 and #31
1 parent 535e359 commit ce138c8

File tree

5 files changed

+71
-17
lines changed

5 files changed

+71
-17
lines changed

Hologram/Network/Cellular.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ def connect(self, timeout = DEFAULT_CELLULAR_TIMEOUT):
7373
self.logger.info('Successfully connected to cell network')
7474
# Disable at sockets mode since we're already establishing PPP.
7575
# This call is needed in certain modems that have limited interfaces to work with.
76+
time.sleep(2)
77+
# give the device a little time to enumerate
7678
self.disable_at_sockets_mode()
7779
self.__configure_routing()
7880
self._connection_status = CLOUD_CONNECTED
@@ -85,6 +87,7 @@ def connect(self, timeout = DEFAULT_CELLULAR_TIMEOUT):
8587

8688
def disconnect(self):
8789
self.logger.info('Disconnecting from cell network')
90+
self.__remove_routing()
8891
success = self.modem.disconnect()
8992
if success:
9093
self.logger.info('Successfully disconnected from cell network')
@@ -166,13 +169,23 @@ def __reconnect_after_forced_disconnect(self):
166169
self.logger.info('Ready to receive data on port %s', self.__receive_port)
167170

168171
def __configure_routing(self):
172+
# maybe we don't have to tear down the routes but we probably should
169173
self.logger.info('Adding routes to Hologram cloud')
170174
self._route.add('10.176.0.0/16', self.localIPAddress)
171175
self._route.add('10.254.0.0/16', self.localIPAddress)
172176
if self.scope == NetworkScope.SYSTEM:
173177
self.logger.info('Adding system-wide default route to cellular interface')
174178
self._route.add_default(self.localIPAddress)
175179

180+
def __remove_routing(self):
181+
self.logger.info('Removing routes to Hologram cloud')
182+
if self.localIPAddress:
183+
self._route.delete('10.176.0.0/16', self.localIPAddress)
184+
self._route.delete('10.254.0.0/16', self.localIPAddress)
185+
if self.scope == NetworkScope.SYSTEM:
186+
self.logger.info('Removing system-wide default route to cellular interface')
187+
self._route.delete_default(self.localIPAddress)
188+
176189
def _load_modem_drivers(self):
177190
dl = DriverLoader.DriverLoader()
178191
for (modemName, modemHandler) in self._modemHandlers.items():

Hologram/Network/Modem/Modem.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
from UtilClasses import ModemResult
1414
from UtilClasses import SMS
1515
from Hologram.Event import Event
16-
from Exceptions.HologramError import SerialError, HologramError, NetworkError
16+
from Exceptions.HologramError import SerialError, HologramError, NetworkError, PPPError
17+
1718

1819
from collections import deque
1920
import binascii
@@ -100,8 +101,16 @@ def connect(self, timeout):
100101
def disconnect(self):
101102

102103
if self._mode is not None:
103-
return self._mode.disconnect()
104-
return None
104+
res = self._mode.disconnect()
105+
self._mode = None
106+
return res
107+
else:
108+
try:
109+
PPP.shut_down_existing_ppp_session(self.logger)
110+
return True
111+
except PPPError as e:
112+
self.logger.info('Got PPPError trying to disconnect open sessions')
113+
return None
105114

106115
def _initialize_device_name(self, device_name):
107116
if device_name is None:
@@ -883,11 +892,17 @@ def modem_mode(self, mode):
883892

884893
@property
885894
def localIPAddress(self):
886-
return self._mode.localIPAddress
895+
if self._mode:
896+
return self._mode.localIPAddress
897+
else:
898+
return None
887899

888900
@property
889901
def remoteIPAddress(self):
890-
return self._mode.remoteIPAddress
902+
if self._mode:
903+
return self._mode.remoteIPAddress
904+
else:
905+
return None
891906

892907

893908
@property

Hologram/Network/Modem/ModemMode/PPP.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,35 +58,37 @@ def connect(self, timeout=DEFAULT_PPP_TIMEOUT):
5858

5959
def disconnect(self):
6060
self._ppp.disconnect()
61-
self.__shut_down_existing_ppp_session()
61+
PPP.shut_down_existing_ppp_session(self.logger)
6262
return True
6363

6464
# EFFECTS: Makes sure that there are no existing PPP instances on the same
6565
# device interface.
6666
def __enforce_no_existing_ppp_session(self):
6767

68-
pid_list = self.__check_for_existing_ppp_sessions()
68+
pid_list = PPP.check_for_existing_ppp_sessions(self.logger)
6969

7070
if len(pid_list) > 0:
7171
raise PPPError('Existing PPP session(s) are established by pid(s) %s. Please close/kill these processes first'
7272
% pid_list)
7373

74-
def __shut_down_existing_ppp_session(self):
75-
pid_list = self.__check_for_existing_ppp_sessions()
74+
@staticmethod
75+
def shut_down_existing_ppp_session(logger):
76+
pid_list = PPP.check_for_existing_ppp_sessions(logger)
7677

7778
# Process this only if it is a valid PID integer.
7879
for pid in pid_list:
79-
self.logger.info('Killing pid %s that currently have an active PPP session',
80+
logger.info('Killing pid %s that currently have an active PPP session',
8081
pid)
8182
process = psutil.Process(pid)
8283
process.terminate()
8384
# Wait at least 10 seconds for the process to terminate
8485
process.wait(10)
8586

86-
def __check_for_existing_ppp_sessions(self):
87+
@staticmethod
88+
def check_for_existing_ppp_sessions(logger):
8789

8890
existing_ppp_pids = []
89-
self.logger.info('Checking for existing PPP sessions')
91+
logger.info('Checking for existing PPP sessions')
9092

9193
for proc in psutil.process_iter():
9294
try:
@@ -95,7 +97,7 @@ def __check_for_existing_ppp_sessions(self):
9597
raise PPPError('Failed to check for existing PPP sessions')
9698

9799
if 'pppd' in pinfo['name']:
98-
self.logger.info('Found existing PPP session on pid: %s', pinfo['pid'])
100+
logger.info('Found existing PPP session on pid: %s', pinfo['pid'])
99101
existing_ppp_pids.append(pinfo['pid'])
100102

101103
return existing_ppp_pids

Hologram/Network/Modem/ModemMode/pppd.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ def disconnect(self):
118118
if self.proc and self.proc.poll() is None:
119119
self.proc.send_signal(signal.SIGTERM)
120120
time.sleep(1)
121+
# Reset the values when we disconnect
122+
self._laddr = None
123+
self._raddr = None
124+
self.proc = None
121125

122126

123127
# EFFECTS: Returns true if a cellular connection is established.

Hologram/Network/Route.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
class Route:
2222
def __init__(self):
23-
self.ipr = IPRoute()
2423
self.logger = logging.getLogger(__name__)
2524
self.logger.addHandler(NullHandler())
2625

@@ -56,13 +55,33 @@ def add_default(self, gateway):
5655
self.logger.debug('Could not set default route due to NetlinkError: %s', str(e))
5756

5857
def add(self, destination, gateway):
59-
self.ipr.route('add',
58+
self.logger.debug('Adding Route %s : %s', destination, gateway)
59+
with IPRoute() as ipr:
60+
ipr.route('add',
6061
dst=destination,
6162
gateway=gateway)
6263

64+
def delete_default(self, gateway):
65+
try:
66+
self.delete(DEFAULT_DESTINATION, gateway)
67+
except NetlinkError as e:
68+
self.logger.debug('Could not set default route due to NetlinkError: %s', str(e))
69+
70+
def delete(self, destination, gateway):
71+
self.logger.debug('Removing Route %s : %s', destination, gateway)
72+
try:
73+
with IPRoute() as ipr:
74+
ipr.route('del',
75+
dst=destination,
76+
gateway=gateway)
77+
except NetlinkError as e:
78+
self.logger.debug('Could not delete route due to NetlinkError: %s', str(e))
79+
80+
6381
def __interface_index(self, interface):
6482
index = None
65-
indexes = self.ipr.link_lookup(ifname=interface)
83+
with IPRoute() as ipr:
84+
indexes = ipr.link_lookup(ifname=interface)
6685
if len(indexes) == 1:
6786
index = indexes[0]
6887
return index
@@ -71,7 +90,8 @@ def __get_interface_state(self, interface):
7190
if self.is_interface_available(interface):
7291
link_state = None
7392
ipr_index = self.__interface_index(interface)
74-
links = self.ipr.get_links()
93+
with IPRoute() as ipr:
94+
links = ipr.get_links()
7595

7696
for link in links:
7797
if link['index'] == ipr_index:

0 commit comments

Comments
 (0)