Checking Zoom latency externally

Here is a handy script that I often use to check the quality of the Zoom connection. It measures TCP latency instead of the usual ICMP stuff (which is often blocked). #!/usr/bin/env python3 """ TCP Ping Test (defaults to port 80, 10000 packets) Usage: ./tcpping.py host [port] [maxCount] - Ctrl-C Exits with Results """ """ pip3 install matplotlib numpy python3 ./tcp_ping_grapher.py 115.114.56.202 443 100 python3 ./tcp_ping_grapher.py teams.microsoft.com 443 100 """ import sys import socket import time import signal from timeit import default_timer as timer # https://matplotlib.org/examples/animation/animate_decay.html import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation host = None port = 80 # Default to 10000 connections max maxCount = 10000 ## Inputs # Required Host try: host = sys.argv[1] # host = "115.114.56.202" except IndexError: print("Usage: tcpping.py host [port] [maxCount]") sys.exit(1) # Optional Port try: port = int(sys.argv[2]) # port = 443 except ValueError: print("Error: Port Must be Integer:", sys.argv[2]) sys.exit(1) except IndexError: pass # Optional maxCount try: maxCount = int(sys.argv[3]) except ValueError: print("Error: Max Count Value Must be Integer", sys.argv[3]) sys.exit(1) except IndexError: pass # Pass/Fail counters passed = 0 failed = 0 def getResults(): """ Summarize Results """ lRate = 0 if failed != 0: lRate = failed / (count) * 100 lRate = "%.2f" % lRate print("\nTCP Ping Results: Connections (Total/Pass/Fail): [{:}/{:}/{:}] (Failed: {:}%)".format((count), passed, failed, str(lRate))) def signal_handler(signal, frame): """ Catch Ctrl-C and Exit """ getResults() sys.exit(0) # Register SIGINT Handler signal.signal(signal.SIGINT, signal_handler) def work(t=0): passed = 0 failed = 0 count = 0 maxCount = 3200 # Loop while less than max count or until Ctrl-C caught while count < maxCount: # Increment Counter count += 1 success = False # New Socket s = socket.socket( socket.AF_INET, socket.SOCK_STREAM) # 1sec Timeout s.settimeout(1) # Start a timer s_start = timer() # Try to Connect try: s.connect((host, int(port))) s.shutdown(socket.SHUT_RD) success = True # Connection Timed Out except socket.timeout: print("Connection timed out!") failed += 1 except OSError as e: print("OS Error:", e) failed += 1 # Stop Timer s_stop = timer() s_runtime = "%.2f" % (1000 * (s_stop - s_start)) if success: print("Connected to %s[%s]: tcp_seq=%s time=%s ms" % (host, port, (count-1), s_runtime)) passed += 1 # Sleep for 1sec if count < maxCount: # time.sleep(0.5) # time.sleep(1) time.sleep(2) t += 2 yield t, float(s_runtime) # Output Results if maxCount reached # getResults() def data_gen(t=0): cnt = 0 while cnt < 1000: cnt += 1 t += 0.1 yield t, np.sin(2*np.pi*t) * np.exp(-t/10.) def init(): ax.set_ylim(0, 128 * 3) ax.set_xlim(0, 300) del xdata[:] del ydata[:] line.set_data(xdata, ydata) return line, fig, ax = plt.subplots() line, = ax.plot([], [], lw=2) ax.grid() xdata, ydata = [], [] def run(data): # update the data t, y = data xdata.append(t) ydata.append(y) xmin, xmax = ax.get_xlim() if t >= xmax: ax.set_xlim(xmin, 2*xmax) ax.figure.canvas.draw() line.set_data(xdata, ydata) return line, ani = animation.FuncAnimation(fig, run, work, blit=False, interval=10, repeat=False, init_func=init) plt.show() Usage: ...

August 8, 2025 · 3 min · 516 words · Dhiru Kholia

Debugging / reversing Firebase gRPC traffic with mitmproxy

Recently, I was stuck in figuring out how the Firebase gRPC calls worked and how I could generate, modify, and replay them. Trapping and modifying the existing gRPC traffic was not working too well. Finally, I took a step back and spent some time on learning how to build and debug simple Firebase applications. This approach helped me tremendously and I was able to make further progress with my original task in almost no time. ...

April 16, 2025 · 3 min · 434 words · Dhiru Kholia

Reimagining the 'Tangara' music player - Part 2

Tangara is a pretty awesome project! It recently inspired us to build a similar FOSS DAP product but at a much lower cost of <= 40 USD. Our initial tech stack: RP2350-Zero, PCM5102A 32-bit 384kHz DAC, Burr-Brown OPA1662 (specified for 3.3v) as the unity gain buffer and headphone driver, no explicit DC-DC converters anywhere, microSD card, everything will be a module if possible We quickly got this prototype working on a breadboard and discovered some limitations: ...

April 11, 2025 · 5 min · 957 words · Dhiru Kholia

Reimagining the 'Tangara' music player

Tangara is a pretty awesome project - no doubts about it. I found this review of Tangara's design pretty interesting and educational. It has inspired us to build a similar FOSS DAP product but at a much lower cost of 40 USD (that being the launch price of Sansa Clip in year 2007). The idea is to deliver '90% of the value' of Tangara in a slightly smaller (but fatter) and more cost-effective package. ...

February 15, 2025 · 3 min · 568 words · Dhiru Kholia

Easy Taint Tracking - Finding Heartbleed in 2024

Aim Finding 'Heartbleed' class of bugs with taint analysis. Background reading: https://heartbleed.com/ Motivation While Coverity is now able to detect this bug, we wanted to evaluate the state of open-source security tooling in 2024. Have we been able to reduce the cost of finding such bugs after all these years? The Idea Can we find an execution path from the tainted data in the n2s function to sensitive functions? Since n2s typically operates on network received bytes, it can serve as a taint source. ...

November 1, 2024 · 3 min · 488 words · Dhiru Kholia

My solar powered website

This notebook (aka 'blog') is powered by free solar energy! I was (and am) inspired to start writing again by reading this excellent article by 'LOW←TECH MAGAZINE'. Imitation is the sincerest form of flattery… Tech stack: Navitas 100W Solar Panel, Exide solar charge controller (10A), Exide Solar Blitz 40AH battery, 200W 20A DC-DC CC CV Buck module (Robu), Cuzor Mini Pro RouterUPS (12V), LM2596S DC-DC 24V/12V to 5V 5A Step Down USB module, Raspberry Pi Zero 2W ...

January 1, 1999 · 1 min · 181 words · Dhiru Kholia