Skip to content

Commit 4b26a86

Browse files
committed
Added probe count option to rnprobe
1 parent 43a6e28 commit 4b26a86

File tree

1 file changed

+95
-80
lines changed

1 file changed

+95
-80
lines changed

RNS/Utilities/rnprobe.py

+95-80
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
DEFAULT_PROBE_SIZE = 16
3434
DEFAULT_TIMEOUT = 12
3535

36-
def program_setup(configdir, destination_hexhash, size=None, full_name = None, verbosity = 0, timeout=None):
36+
def program_setup(configdir, destination_hexhash, size=None, full_name = None, verbosity = 0, timeout=None, probes=1):
3737
if size == None: size = DEFAULT_PROBE_SIZE
3838
if full_name == None:
3939
print("The full destination name including application name aspects must be specified for the destination")
@@ -96,90 +96,103 @@ def program_setup(configdir, destination_hexhash, size=None, full_name = None, v
9696
*aspects
9797
)
9898

99-
try:
100-
probe = RNS.Packet(request_destination, os.urandom(size))
101-
probe.pack()
102-
except OSError:
103-
print("Error: Probe packet size of "+str(len(probe.raw))+" bytes exceed MTU of "+str(RNS.Reticulum.MTU)+" bytes")
104-
exit(3)
105-
106-
receipt = probe.send()
107-
108-
if more_output:
109-
nhd = reticulum.get_next_hop(destination_hash)
110-
via_str = " via "+RNS.prettyhexrep(nhd) if nhd != None else ""
111-
if_str = " on "+str(reticulum.get_next_hop_if_name(destination_hash)) if reticulum.get_next_hop_if_name(destination_hash) != "None" else ""
112-
more = via_str+if_str
113-
else:
114-
more = ""
115-
116-
print("\rSent "+str(size)+" byte probe to "+RNS.prettyhexrep(destination_hash)+more+" ", end=" ")
99+
sent = 0
100+
replies = 0
101+
while probes:
117102

118-
_timeout = time.time() + (timeout or DEFAULT_TIMEOUT+reticulum.get_first_hop_timeout(destination_hash))
119-
i = 0
120-
while receipt.status == RNS.PacketReceipt.SENT and not time.time() > _timeout:
121-
time.sleep(0.1)
122-
print(("\b\b"+syms[i]+" "), end="")
123-
sys.stdout.flush()
124-
i = (i+1)%len(syms)
125-
126-
if time.time() > _timeout:
127-
print("\r \rProbe timed out")
128-
exit(2)
129-
130-
print("\b\b ")
131-
sys.stdout.flush()
132-
133-
if receipt.status == RNS.PacketReceipt.DELIVERED:
134-
hops = RNS.Transport.hops_to(destination_hash)
135-
if hops != 1:
136-
ms = "s"
103+
try:
104+
probe = RNS.Packet(request_destination, os.urandom(size))
105+
probe.pack()
106+
except OSError:
107+
print("Error: Probe packet size of "+str(len(probe.raw))+" bytes exceed MTU of "+str(RNS.Reticulum.MTU)+" bytes")
108+
exit(3)
109+
110+
receipt = probe.send()
111+
sent += 1
112+
113+
if more_output:
114+
nhd = reticulum.get_next_hop(destination_hash)
115+
via_str = " via "+RNS.prettyhexrep(nhd) if nhd != None else ""
116+
if_str = " on "+str(reticulum.get_next_hop_if_name(destination_hash)) if reticulum.get_next_hop_if_name(destination_hash) != "None" else ""
117+
more = via_str+if_str
137118
else:
138-
ms = ""
119+
more = ""
139120

140-
rtt = receipt.get_rtt()
141-
if (rtt >= 1):
142-
rtt = round(rtt, 3)
143-
rttstring = str(rtt)+" seconds"
144-
else:
145-
rtt = round(rtt*1000, 3)
146-
rttstring = str(rtt)+" milliseconds"
147-
148-
reception_stats = ""
149-
if reticulum.is_connected_to_shared_instance:
150-
reception_rssi = reticulum.get_packet_rssi(receipt.proof_packet.packet_hash)
151-
reception_snr = reticulum.get_packet_snr(receipt.proof_packet.packet_hash)
152-
reception_q = reticulum.get_packet_q(receipt.proof_packet.packet_hash)
153-
154-
if reception_rssi != None:
155-
reception_stats += " [RSSI "+str(reception_rssi)+" dBm]"
156-
157-
if reception_snr != None:
158-
reception_stats += " [SNR "+str(reception_snr)+" dB]"
159-
160-
if reception_q != None:
161-
reception_stats += " [Link Quality "+str(reception_q)+"%]"
121+
print("\rSent probe "+str(sent)+" ("+str(size)+" bytes) to "+RNS.prettyhexrep(destination_hash)+more+" ", end=" ")
162122

163-
else:
164-
if receipt.proof_packet != None:
165-
if receipt.proof_packet.rssi != None:
166-
reception_stats += " [RSSI "+str(receipt.proof_packet.rssi)+" dBm]"
167-
168-
if receipt.proof_packet.snr != None:
169-
reception_stats += " [SNR "+str(receipt.proof_packet.snr)+" dB]"
170-
171-
print(
172-
"Valid reply received from "+
173-
RNS.prettyhexrep(receipt.destination.hash)+
174-
"\nRound-trip time is "+rttstring+
175-
" over "+str(hops)+" hop"+ms+
176-
reception_stats
177-
)
123+
_timeout = time.time() + (timeout or DEFAULT_TIMEOUT+reticulum.get_first_hop_timeout(destination_hash))
124+
i = 0
125+
while receipt.status == RNS.PacketReceipt.SENT and not time.time() > _timeout:
126+
time.sleep(0.1)
127+
print(("\b\b"+syms[i]+" "), end="")
128+
sys.stdout.flush()
129+
i = (i+1)%len(syms)
178130

179-
else:
180-
print("\r \rProbe timed out")
131+
if time.time() > _timeout:
132+
print("\r \rProbe timed out")
133+
134+
else:
135+
print("\b\b ")
136+
sys.stdout.flush()
137+
138+
if receipt.status == RNS.PacketReceipt.DELIVERED:
139+
replies += 1
140+
hops = RNS.Transport.hops_to(destination_hash)
141+
if hops != 1:
142+
ms = "s"
143+
else:
144+
ms = ""
145+
146+
rtt = receipt.get_rtt()
147+
if (rtt >= 1):
148+
rtt = round(rtt, 3)
149+
rttstring = str(rtt)+" seconds"
150+
else:
151+
rtt = round(rtt*1000, 3)
152+
rttstring = str(rtt)+" milliseconds"
153+
154+
reception_stats = ""
155+
if reticulum.is_connected_to_shared_instance:
156+
reception_rssi = reticulum.get_packet_rssi(receipt.proof_packet.packet_hash)
157+
reception_snr = reticulum.get_packet_snr(receipt.proof_packet.packet_hash)
158+
reception_q = reticulum.get_packet_q(receipt.proof_packet.packet_hash)
159+
160+
if reception_rssi != None:
161+
reception_stats += " [RSSI "+str(reception_rssi)+" dBm]"
162+
163+
if reception_snr != None:
164+
reception_stats += " [SNR "+str(reception_snr)+" dB]"
165+
166+
if reception_q != None:
167+
reception_stats += " [Link Quality "+str(reception_q)+"%]"
168+
169+
else:
170+
if receipt.proof_packet != None:
171+
if receipt.proof_packet.rssi != None:
172+
reception_stats += " [RSSI "+str(receipt.proof_packet.rssi)+" dBm]"
173+
174+
if receipt.proof_packet.snr != None:
175+
reception_stats += " [SNR "+str(receipt.proof_packet.snr)+" dB]"
176+
177+
print(
178+
"Valid reply received from "+
179+
RNS.prettyhexrep(receipt.destination.hash)+
180+
"\nRound-trip time is "+rttstring+
181+
" over "+str(hops)+" hop"+ms+
182+
reception_stats
183+
)
184+
185+
else:
186+
print("\r \rProbe timed out")
187+
188+
probes -= 1
189+
190+
loss = round((1-(replies/sent))*100, 2)
191+
print(f"Sent {sent}, received {replies}, packet loss {loss}%")
192+
if loss > 0:
181193
exit(2)
182-
194+
else:
195+
exit(0)
183196

184197

185198
def main():
@@ -188,6 +201,7 @@ def main():
188201

189202
parser.add_argument("--config", action="store", default=None, help="path to alternative Reticulum config directory", type=str)
190203
parser.add_argument("-s", "--size", action="store", default=None, help="size of probe packet payload in bytes", type=int)
204+
parser.add_argument("-n", "--probes", action="store", default=1, help="number of probes to send", type=int)
191205
parser.add_argument("-t", "--timeout", metavar="seconds", action="store", default=None, help="timeout before giving up", type=float)
192206
parser.add_argument("--version", action="version", version="rnprobe {version}".format(version=__version__))
193207
parser.add_argument("full_name", nargs="?", default=None, help="full destination name in dotted notation", type=str)
@@ -212,7 +226,8 @@ def main():
212226
destination_hexhash = args.destination_hash,
213227
size = args.size,
214228
full_name = args.full_name,
215-
verbosity = args.verbose
229+
verbosity = args.verbose,
230+
probes = args.probes,
216231
)
217232

218233
except KeyboardInterrupt:

0 commit comments

Comments
 (0)