<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: NITISH Sharma</title>
    <description>The latest articles on DEV Community by NITISH Sharma (@nitish_sharma).</description>
    <link>https://dev.to/nitish_sharma</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3836037%2F1d58dfbd-51a6-45dc-95f6-b737ba25a729.jpg</url>
      <title>DEV Community: NITISH Sharma</title>
      <link>https://dev.to/nitish_sharma</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nitish_sharma"/>
    <language>en</language>
    <item>
      <title>I Built a Modern Blog Website Using Vibe Coding</title>
      <dc:creator>NITISH Sharma</dc:creator>
      <pubDate>Fri, 24 Jul 2026 07:01:32 +0000</pubDate>
      <link>https://dev.to/nitish_sharma/-i-built-a-modern-blog-website-using-vibe-coding-100m</link>
      <guid>https://dev.to/nitish_sharma/-i-built-a-modern-blog-website-using-vibe-coding-100m</guid>
      <description>&lt;p&gt;"Vibe coding" has been impossible to avoid the last few months — describe what you want in plain English, watch an AI generate the app, ship it. I'd used AI tools as a coding partner before, mostly for systems-level work in C++, where I'm reviewing generated code line by line anyway. What I hadn't done was hand something a full frontend from scratch and see how much of that same "describe it, review it, steer it" workflow actually held up outside my comfort zone.&lt;/p&gt;

&lt;p&gt;So I picked a real project instead of a toy one: my personal blog. Small enough to fully understand end to end, substantial enough that routing, layout, and content structure would actually surface real friction if the tool couldn't handle them.&lt;/p&gt;

&lt;p&gt;This is what that process actually looked like — including the parts that didn't just work on the first try.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Vibe Coding Means to Me
&lt;/h2&gt;

&lt;p&gt;I want to be upfront about the frame I went in with, because "vibe coding" gets talked about two very different ways.&lt;/p&gt;

&lt;p&gt;One version treats it like a replacement for knowing how to build software — describe the vibe, get the app, never look at the code. That's not what this was.&lt;/p&gt;

&lt;p&gt;The version I actually used treats AI as a fast, very literal collaborator: it can generate a huge amount of working structure from a description, but it doesn't know what "good" looks like for &lt;em&gt;my&lt;/em&gt; project, and it doesn't catch its own mistakes. That part's still on me. So in practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I described intent, not implementation details — what the blog should do, not which components to use&lt;/li&gt;
&lt;li&gt;I reviewed what came back before trusting it, the same way I'd review a pull request&lt;/li&gt;
&lt;li&gt;I made the actual architectural calls — what pages exist, how content is structured, what stays out of scope&lt;/li&gt;
&lt;li&gt;I stepped in to fix or rewrite anything that was subtly wrong rather than just "looked" right in the preview&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The skill that mattered wasn't typing less code. It was asking clearer questions and knowing when to stop trusting the preview and go read the actual output.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Idea Behind My Blog
&lt;/h2&gt;

&lt;p&gt;I already write longer technical pieces on dev.to, but I wanted one place that was fully mine — for project write-ups (the kind of deep-dive I did on building a packet sniffer with libpcap) tied directly to how I want to be positioned professionally. The site's tagline sums up the intent pretty directly: &lt;strong&gt;Systems Programmer &amp;amp; Security Engineer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The brief for the blog itself was deliberately narrow: fast, readable, no CMS overhead, nothing that gets in the way of the writing. A blog is exactly the kind of project where the &lt;em&gt;content&lt;/em&gt; should be the interesting part, not the platform underneath it — which also made it a fair test case for vibe coding, since I wasn't trying to build something architecturally novel.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Technologies Used
&lt;/h2&gt;

&lt;p&gt;I built it using &lt;strong&gt;Google AI Studio's Build mode&lt;/strong&gt;, which generates a full React application from a natural-language description. A few specifics about how it actually works, since "vibe coding" tools vary a lot underneath the same marketing term:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A two-pane interface: a chat panel for describing what you want, and a live code editor + preview pane showing the actual generated project&lt;/li&gt;
&lt;li&gt;An annotation mode that lets you click directly on an element in the preview and describe a visual change, instead of describing "the button in the top right" in words&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Code&lt;/strong&gt; tab that shows the real generated source — not a black box, an actual editable React project&lt;/li&gt;
&lt;li&gt;One-click deploy, which is exactly how the site ended up live at a &lt;code&gt;.ai.studio&lt;/code&gt; subdomain in the first place&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No custom backend — a blog doesn't need one, and keeping that scope small mattered for how well the AI-generated result would actually hold up.&lt;/p&gt;

&lt;p&gt;A rough shape of the kind of prompt that kicks off a build like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Build a minimal, modern personal blog in React.
Home page: list of posts with title, date, short excerpt.
Post page: full article content, clean typography, no sidebar clutter.
No backend — content should be easy to add as static entries.
Dark, minimal aesthetic. Fast load, no unnecessary animation.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  My Development Workflow Using AI
&lt;/h2&gt;

&lt;p&gt;The rhythm ended up being closer to iterative pair programming than "one prompt, done":&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start broad&lt;/strong&gt; — one prompt describing the overall structure and pages, to get a working skeleton fast&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Iterate conversationally&lt;/strong&gt; — follow-up prompts to adjust layout, spacing, and typography, using the annotation tool for anything visual instead of describing it in words&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actually read the Code tab&lt;/strong&gt; — periodically stopping to look at what got generated rather than just trusting that the live preview looked right&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix by hand where needed&lt;/strong&gt; — anything that was subtly off got corrected directly rather than re-prompted into a worse state&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;[Add here: one specific real example of a refinement loop you went through — e.g. a particular layout tweak, a piece of content structure you had to re-prompt several times to get right.]&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges I Faced (and How I Solved Them)
&lt;/h2&gt;

&lt;p&gt;The biggest one wasn't a bug — it was scope. Tools like this are genuinely good at producing a working prototype fast, but the well-documented gap across this entire category (not just this one) is production-readiness: things like persistence, proper error handling, and security hardening aren't there by default. A generated blog looks finished in the preview long before it's actually finished.&lt;/p&gt;

&lt;p&gt;Concretely, that meant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Treating the first generated version as a &lt;em&gt;draft&lt;/em&gt; to review, not a shippable result&lt;/li&gt;
&lt;li&gt;Going through the actual source in the Code tab rather than assuming the preview told the whole story&lt;/li&gt;
&lt;li&gt;Being the one to decide what "done" meant — the tool has no opinion on that, and won't tell you when it's cut a corner&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;[Add here: the specific challenge or bug you actually hit while building this — what broke, how you noticed, how you fixed it.]&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What AI Did Well
&lt;/h2&gt;

&lt;p&gt;To be fair to the tool, a few things about this workflow were genuinely impressive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scaffolding speed&lt;/strong&gt; — skipping the "blank React project, routing, build config" setup tax entirely and starting from a working skeleton&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visual iteration&lt;/strong&gt; — the annotation/click-to-edit flow made small design tweaks fast without hand-writing CSS for every adjustment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context retention&lt;/strong&gt; — it kept track of the whole project across a long back-and-forth conversation rather than losing the thread between prompts, which is where a lot of earlier AI coding tools used to fall apart&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a solo side project, that speed genuinely changed how much I was willing to attempt in a weekend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where AI Struggled — and Why Developer Judgment Still Mattered
&lt;/h2&gt;

&lt;p&gt;The flip side of that speed: the tool has no sense of what "finished" means for &lt;em&gt;my&lt;/em&gt; specific project. It'll happily generate something that looks complete in a live preview while quietly skipping things a shipped product actually needs — error states, edge cases, the boring-but-necessary parts.&lt;/p&gt;

&lt;p&gt;That's not a knock on the tool so much as a description of what it's actually for: fast, high-quality &lt;em&gt;scaffolding&lt;/em&gt;, not a substitute for someone who knows what a finished product should look like. Every decision about scope, priorities, and what "good" meant for this specific blog was still mine to make — the prompt doesn't make architectural decisions, it just executes on the ones you've already made, whether or not you've made them well.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vibe coding compresses the blank-page problem, not the judgment problem.&lt;/strong&gt; Getting from zero to something working got dramatically faster. Knowing what "something good" actually looks like didn't get any easier — that part's still entirely on the developer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reading the generated code isn't optional if you're shipping it.&lt;/strong&gt; The preview can look finished while the code underneath is not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clear, specific prompts beat vague ones&lt;/strong&gt;, exactly like clear, specific tickets beat vague ones on any team — "vibe" is doing a lot of work in "vibe coding," but specificity still wins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The fastest path to a good result is still knowing roughly what good looks like before you start prompting&lt;/strong&gt; — the tool amplifies direction, it doesn't supply it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts: Would I Use Vibe Coding Again?
&lt;/h2&gt;

&lt;p&gt;Yes — specifically for this category of project. Personal tools, prototypes, low-stakes frontends where I want to get from idea to something real fast, and where I'm going to review and finish the result myself rather than ship the first output verbatim. I wouldn't treat it as a blanket replacement for writing code by hand, especially anywhere production-readiness, security, or genuinely novel architecture actually matters — that's exactly where the gap between "impressive demo" and "finished product" shows up.&lt;/p&gt;

&lt;p&gt;What it did change is how much I was willing to attempt for something like a personal blog, where the writing was always supposed to be the point, not the frontend plumbing underneath it.&lt;/p&gt;

&lt;p&gt;If you've tried vibe coding yourself — whether it was AI Studio, or something else entirely — I'd genuinely like to hear how it went for you. What worked, where you had to step in and take over, and whether it changed how you think about your own workflow. Drop it in the comments; I'm curious how consistent this experience actually is across different tools and project types.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>coding</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building a Packet Sniffer in C++ with libpcap (And the Segfault That Taught Me a Lesson)</title>
      <dc:creator>NITISH Sharma</dc:creator>
      <pubDate>Wed, 22 Jul 2026 14:24:07 +0000</pubDate>
      <link>https://dev.to/nitish_sharma/building-a-packet-sniffer-in-c-with-libpcap-and-the-segfault-that-taught-me-a-lesson-1ig2</link>
      <guid>https://dev.to/nitish_sharma/building-a-packet-sniffer-in-c-with-libpcap-and-the-segfault-that-taught-me-a-lesson-1ig2</guid>
      <description>&lt;p&gt;I'm a CS student working toward a portfolio in AI/ML, DevOps, and cybersecurity, and one of the bigger projects on that list is &lt;strong&gt;NetSentinel&lt;/strong&gt; — an ML-based intrusion detection system. You can't detect anomalies in network traffic if you can't first &lt;em&gt;read&lt;/em&gt; network traffic, so before touching any machine learning, I went back to basics: write a packet sniffer in C++ using &lt;code&gt;libpcap&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This post is the story of that sniffer — what it does, the bugs it taught me the hard way, and the refactor that mattered more than any single feature I added.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why libpcap, and what even is a &lt;code&gt;pcap_t&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;libpcap&lt;/code&gt; is the C library behind tools like &lt;code&gt;tcpdump&lt;/code&gt; and Wireshark's capture engine. It gives you raw access to packets flowing across a network interface, before any of your OS's normal socket machinery gets involved.&lt;/p&gt;

&lt;p&gt;The first thing that trips people up is &lt;code&gt;pcap_t&lt;/code&gt; — the handle you get back when you open a capture session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;pcap_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;descr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pcap_open_live&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAXBYTES2CAPTURE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errbuf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;pcap_t&lt;/code&gt; is what's called an &lt;strong&gt;opaque struct&lt;/strong&gt; — you get a pointer to it, but you never see or touch its internal fields. Every single thing you do with it goes through a function call: &lt;code&gt;pcap_loop()&lt;/code&gt; to start capturing, &lt;code&gt;pcap_setfilter()&lt;/code&gt; to configure it, &lt;code&gt;pcap_close()&lt;/code&gt; to tear it down. You never write &lt;code&gt;descr-&amp;gt;something&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If that pattern feels familiar, it should — it's the exact same shape as a &lt;code&gt;FILE*&lt;/code&gt; from &lt;code&gt;&amp;lt;cstdio&amp;gt;&lt;/code&gt;, or a &lt;code&gt;sqlite3*&lt;/code&gt; from SQLite's C API. Open, operate through functions, close. Once that clicked for me, a bunch of other C libraries suddenly felt less mysterious.&lt;/p&gt;

&lt;h2&gt;
  
  
  Letting the user pick a device
&lt;/h2&gt;

&lt;p&gt;The very first version of this sniffer just auto-picked whatever device &lt;code&gt;pcap_lookupdev()&lt;/code&gt; handed back (deprecated now, but fine for a first pass). The obvious next step was letting the user choose — laptop Wi-Fi, loopback, whatever.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pcap_findalldevs()&lt;/code&gt; gives you a linked list of every available interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;pcap_if_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;alldevs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;pcap_findalldevs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;alldevs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errbuf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pcap_if_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;alldevs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Interesting detail: unlike &lt;code&gt;pcap_t&lt;/code&gt;, a &lt;code&gt;pcap_if_t&lt;/code&gt; is &lt;strong&gt;not&lt;/strong&gt; opaque. &lt;code&gt;d-&amp;gt;name&lt;/code&gt;, &lt;code&gt;d-&amp;gt;next&lt;/code&gt;, &lt;code&gt;d-&amp;gt;description&lt;/code&gt; are plain, directly-accessible fields — no accessor functions needed. The two types sit at opposite ends of "how much the library hides from you," and it's a nice example of a library only hiding what actually needs hiding.&lt;/p&gt;

&lt;p&gt;I wrote a small helper to walk the list by index so a user could type a number instead of a device name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;pcap_if_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;selectNodeByIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pcap_if_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;targetIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetIndex&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;pcap_if_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;currentIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentIndex&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;targetIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;currentIndex&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looked done. It was not done.&lt;/p&gt;

&lt;h2&gt;
  
  
  The segfault: a classic use-after-free
&lt;/h2&gt;

&lt;p&gt;Here's what my &lt;code&gt;main()&lt;/code&gt; looked like right after wiring device selection in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Opening device: "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;selectedDev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;pcap_freealldevs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alldevs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;descr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pcap_open_live&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;selectedDev&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAXBYTES2CAPTURE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errbuf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it, print the device list, type a number... segfault. Instantly.&lt;/p&gt;

&lt;p&gt;The bug: &lt;code&gt;selectedDev&lt;/code&gt; isn't a separate copy of anything — it's a pointer &lt;em&gt;into&lt;/em&gt; the same linked list &lt;code&gt;alldevs&lt;/code&gt; owns. &lt;code&gt;pcap_freealldevs(alldevs)&lt;/code&gt; walks the whole list and frees every node in it, including the exact node &lt;code&gt;selectedDev&lt;/code&gt; points to. The very next line dereferences &lt;code&gt;selectedDev-&amp;gt;name&lt;/code&gt; — memory that had just been freed.&lt;/p&gt;

&lt;p&gt;Two variables, two different names, pointing at overlapping memory. Freeing one silently invalidates the other, and nothing about the code &lt;em&gt;looks&lt;/em&gt; wrong — that's what makes use-after-free bugs so nasty compared to, say, a syntax error.&lt;/p&gt;

&lt;p&gt;The fix was just reordering — finish reading from the list before freeing it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Opening device: "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;selectedDev&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;descr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pcap_open_live&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;selectedDev&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAXBYTES2CAPTURE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errbuf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;descr&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cerr&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"pcap_open_live failed: "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;errbuf&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;pcap_freealldevs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alldevs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;pcap_loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;descr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;processPackets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;reinterpret_cast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;u_char&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;pcap_freealldevs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alldevs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// only free once nothing still points into it&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lesson that stuck with me: before calling &lt;code&gt;free&lt;/code&gt;/&lt;code&gt;delete&lt;/code&gt;/&lt;code&gt;pcap_freealldevs&lt;/code&gt; on anything, the real question isn't "am I done with &lt;em&gt;this&lt;/em&gt; variable" — it's "does &lt;em&gt;anything else&lt;/em&gt; still point into this memory."&lt;/p&gt;

&lt;h2&gt;
  
  
  The quiet failure: when nothing crashes, but nothing happens either
&lt;/h2&gt;

&lt;p&gt;Bug #2 was sneakier because there was no crash at all. I'd pick loopback, see "Opening device: lo" print... and then the program would just exit. No error, no packets, nothing.&lt;/p&gt;

&lt;p&gt;Turns out &lt;code&gt;pcap_open_live()&lt;/code&gt; can succeed at opening the handle even without the right privileges — the actual failure happens later, on the first internal read inside &lt;code&gt;pcap_loop()&lt;/code&gt;, and I wasn't checking its return value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pcap_loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;descr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;processPackets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;reinterpret_cast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;u_char&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;PCAP_ERROR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cerr&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"pcap_loop failed: "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;pcap_geterr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;descr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once I added that check, the actual problem showed up immediately: permissions. Capturing raw packets needs &lt;code&gt;CAP_NET_RAW&lt;/code&gt;/&lt;code&gt;CAP_NET_ADMIN&lt;/code&gt;, which a normal user doesn't have by default:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;setcap cap_net_raw,cap_net_admin&lt;span class="o"&gt;=&lt;/span&gt;eip ./simplesniffer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The real takeaway here: &lt;strong&gt;check return values from anything that can fail silently.&lt;/strong&gt; A function returning early with an error code and a function succeeding can look identical if you never look at what it returned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Actually parsing packets: peeling layers one at a time
&lt;/h2&gt;

&lt;p&gt;With capture working, the fun part: turning raw bytes into something meaningful. A captured frame is layers stacked back to back in memory — Ethernet header, then IP header, then TCP/UDP/ICMP, then payload. You don't copy anything to get at each layer; you just reinterpret the same buffer at increasing offsets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;ether_header&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;reinterpret_cast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;ether_header&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;etherType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ntohs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eth&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ether_type&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;etherType&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;ETHERTYPE_IP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;parseIPv4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;ether_header&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="n"&gt;caplen&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;ether_header&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two details bit me here that are worth knowing up front:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Byte order.&lt;/strong&gt; Multi-byte fields like &lt;code&gt;ether_type&lt;/code&gt; and port numbers arrive in network byte order (big-endian), and my CPU is little-endian. Skipping &lt;code&gt;ntohs()&lt;/code&gt;/&lt;code&gt;ntohl()&lt;/code&gt; means comparing the right bytes in the wrong order — the classic "why is this never matching" bug.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Variable header length.&lt;/strong&gt; &lt;code&gt;struct ip&lt;/code&gt;'s &lt;code&gt;ip_hl&lt;/code&gt; field is a &lt;em&gt;word&lt;/em&gt; count, not a byte count, because IP headers can carry optional fields. Forgetting to multiply by 4 means computing the wrong offset for everything after it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full pipeline ended up as: &lt;code&gt;parseEthernet&lt;/code&gt; → check EtherType → &lt;code&gt;parseIPv4&lt;/code&gt; → check protocol number → &lt;code&gt;parseTCP&lt;/code&gt;/&lt;code&gt;parseUDP&lt;/code&gt;/&lt;code&gt;parseICMP&lt;/code&gt;. Each function only ever needs to know about its own header — no function reaches backward or forward across layers it doesn't own.&lt;/p&gt;

&lt;h2&gt;
  
  
  The refactor that mattered more than any feature
&lt;/h2&gt;

&lt;p&gt;Here's the part I actually want other people building similar tools to take away.&lt;/p&gt;

&lt;p&gt;My first working parser looked like this — each function found something, and immediately &lt;code&gt;printf&lt;/code&gt;'d it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;parseIPv4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;u_char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;caplen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...parse the header...&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[ip] %s -&amp;gt; %s | protocol %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;srcIp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dstIp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ip_p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It worked. It was also a dead end. If I ever wanted to save packets to a file, group them into flows, or hand features to an ML model — all &lt;em&gt;actual requirements&lt;/em&gt; for NetSentinel — I'd have had to re-parse the same raw bytes all over again, because the only "output" of parsing was text on a terminal.&lt;/p&gt;

&lt;p&gt;The fix: stop printing inside the parser. Parse into a plain data struct instead, and let something else decide what to do with it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;PacketInfo&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;uint8_t&lt;/span&gt;  &lt;span class="n"&gt;srcMac&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kt"&gt;uint8_t&lt;/span&gt;  &lt;span class="n"&gt;dstMac&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;etherType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;bool&lt;/span&gt;        &lt;span class="n"&gt;hasIPv4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;srcIp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;dstIp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;uint8_t&lt;/span&gt;     &lt;span class="n"&gt;protocol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;uint8_t&lt;/span&gt;     &lt;span class="n"&gt;ttl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;bool&lt;/span&gt;     &lt;span class="n"&gt;hasTransport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;srcPort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;dstPort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every &lt;code&gt;parse*&lt;/code&gt; function now takes a &lt;code&gt;PacketInfo&amp;amp;&lt;/code&gt; and fills it in instead of printing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;parseIPv4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;u_char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;caplen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PacketInfo&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...same parsing logic as before...&lt;/span&gt;
    &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hasIPv4&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;srcIp&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;srcIp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dstIp&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dstIp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;protocol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;iph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ip_p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ttl&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;iph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ip_ttl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Printing becomes one function, called once, after parsing is completely done:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;PacketInfo&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;parseEthernet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;caplen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;printPacketInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// the ONLY function that touches stdout now&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The satisfying confirmation that this actually worked: my parser's &lt;code&gt;.cpp&lt;/code&gt; file no longer needed to &lt;code&gt;#include &amp;lt;cstdio&amp;gt;&lt;/code&gt; at all. Zero output dependency, anywhere in the parsing code. Anything that wants packet data now — a flow tracker, a CSV writer, a feature extractor for a model — just becomes another reader of &lt;code&gt;PacketInfo&lt;/code&gt;. None of them will ever need to touch a raw byte buffer.&lt;/p&gt;

&lt;p&gt;One small design detail worth calling out: notice the &lt;code&gt;bool hasIPv4&lt;/code&gt; flag sitting next to the IP fields. Not every frame is IPv4 — some are ARP, some IPv6 — and without that flag, an unparsed packet's &lt;code&gt;srcIp&lt;/code&gt;/&lt;code&gt;ttl&lt;/code&gt; would just sit at their zero-initialized defaults with no way to tell "genuinely empty" apart from "never reached this layer." Every optional layer in the struct follows that same has-flag pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;The plan from here is to build outward from &lt;code&gt;PacketInfo&lt;/code&gt; rather than back into raw bytes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Group packets into &lt;strong&gt;flows&lt;/strong&gt; (keyed by source/destination IP + port + protocol) and track stats per flow — packet counts, byte counts, duration&lt;/li&gt;
&lt;li&gt;Export flow records so a Python pipeline can train a baseline anomaly-detection model on them&lt;/li&gt;
&lt;li&gt;Eventually feed live traffic through that trained model for real-time flagging — the actual "intrusion detection" part of NetSentinel&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of that would be possible in a sane way if every consumer still had to re-parse raw Ethernet frames from scratch. That's the whole reason this refactor came before any of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it yourself
&lt;/h2&gt;

&lt;p&gt;If you want to see this working without needing real suspicious traffic: capture on loopback and generate traffic yourself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; ./simplesniffer     &lt;span class="c"&gt;# pick the loopback interface&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a second terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ping &lt;span class="nt"&gt;-c&lt;/span&gt; 3 127.0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see the layered output for each ICMP echo request/reply. Swap &lt;code&gt;ping&lt;/code&gt; for &lt;code&gt;nc -l 127.0.0.1 9999&lt;/code&gt; and &lt;code&gt;echo "hello" | nc 127.0.0.1 9999&lt;/code&gt; in two more terminals if you want to see the TCP path instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons that generalize past this one project
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Opaque handles&lt;/strong&gt; (&lt;code&gt;pcap_t&lt;/code&gt;, &lt;code&gt;FILE*&lt;/code&gt;, &lt;code&gt;sqlite3*&lt;/code&gt;) all follow the same shape: operate through functions only, never touch fields directly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use-after-free doesn't always look wrong.&lt;/strong&gt; Two differently-named pointers can point into the same memory — freeing one silently breaks the other.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check return values from anything that can fail without crashing.&lt;/strong&gt; A silent early return and a full success can look identical from the outside.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decouple "compute the answer" from "do something with the answer."&lt;/strong&gt; The moment your parsing/logic function starts calling &lt;code&gt;printf&lt;/code&gt; (or writing to a file, or hitting a network socket) directly, you've locked yourself into re-doing that computation for every new consumer that shows up later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Still very much a work in progress — next post will probably be about turning &lt;code&gt;PacketInfo&lt;/code&gt; into flow-level statistics.&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>networking</category>
      <category>cybersecurity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Finally wrapped up my Terminal Chat (TUI) project.</title>
      <dc:creator>NITISH Sharma</dc:creator>
      <pubDate>Sun, 22 Mar 2026 18:18:20 +0000</pubDate>
      <link>https://dev.to/nitish_sharma/finally-wrapped-up-my-terminal-chat-tui-project-118d</link>
      <guid>https://dev.to/nitish_sharma/finally-wrapped-up-my-terminal-chat-tui-project-118d</guid>
      <description>&lt;p&gt;Built a real-time multi-user chat system in C++ using TCP sockets and ncurses. Multiple rooms, mentions, online users — all inside the terminal. No buttons, no mouse, just pure keyboard and questionable life choices.&lt;br&gt;
I’ll be honest — I did use ChatGPT along the way. But not as a shortcut. More like a debugging partner that doesn’t get tired of my mistakes. The actual building, breaking, fixing, and understanding… that part was on me.&lt;br&gt;
Also, I’ve realized something:&lt;br&gt;
I genuinely enjoy building TUIs.&lt;br&gt;
There’s something weirdly satisfying about making complex systems work inside a terminal. It’s not flashy, it’s not “modern UI”, and most people won’t care… but for those who live in the terminal — this is home.&lt;br&gt;
This project is basically for people who:&lt;br&gt;
open terminal first, browser later&lt;br&gt;
think keyboard &amp;gt; mouse&lt;br&gt;
and don’t mind staring at text all day&lt;br&gt;
&lt;a href="https://github.com/monkonthehill/Major_projects/tree/main/termchat" rel="noopener noreferrer"&gt;Click for github repo&lt;/a&gt;&lt;br&gt;
Next step: make it more scalable and less “it works on my machine”.&lt;/p&gt;

</description>
      <category>cli</category>
      <category>cpp</category>
      <category>networking</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I Built a Tool That Turns TODO Comments Into Actual Documentation</title>
      <dc:creator>NITISH Sharma</dc:creator>
      <pubDate>Fri, 20 Mar 2026 19:50:27 +0000</pubDate>
      <link>https://dev.to/nitish_sharma/i-built-a-tool-that-turns-todo-comments-into-actual-documentation-34d2</link>
      <guid>https://dev.to/nitish_sharma/i-built-a-tool-that-turns-todo-comments-into-actual-documentation-34d2</guid>
      <description>&lt;p&gt;Most developers already “document” their code — just not in a structured way.&lt;/p&gt;

&lt;p&gt;We write things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// TODO: optimize this&lt;/span&gt;
&lt;span class="c1"&gt;// BUG: fix crash here&lt;/span&gt;
&lt;span class="c1"&gt;// NOTE: handle edge case&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Over time, these comments pile up across files, and eventually… they become invisible.&lt;/p&gt;

&lt;p&gt;I ran into this problem while working on multiple small projects. I knew I had pending work scattered across the codebase, but there was no simple way to track it without introducing another tool or workflow.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;DocTrack&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 The Idea
&lt;/h2&gt;

&lt;p&gt;Instead of forcing developers to adopt a new system, I wanted to &lt;strong&gt;reuse what already exists inside the code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;DocTrack scans a project and extracts structured information from inline comments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What needs to be done (TODO, BUG, etc.)&lt;/li&gt;
&lt;li&gt;Where it exists (file + line)&lt;/li&gt;
&lt;li&gt;What context it belongs to (code block)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Turn implicit developer notes into explicit, usable documentation.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ⚙️ How It Works
&lt;/h2&gt;

&lt;p&gt;At a high level, the tool:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Recursively scans a directory using C++17 filesystem APIs&lt;/li&gt;
&lt;li&gt;Reads files line-by-line&lt;/li&gt;
&lt;li&gt;Uses regex to detect tagged comments:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;TODO&lt;/li&gt;
&lt;li&gt;BUG&lt;/li&gt;
&lt;li&gt;NOTE&lt;/li&gt;
&lt;li&gt;FIXME&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CODENOTE&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extracts:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;file name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;line number&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;message&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Captures surrounding code context using a &lt;strong&gt;brace-tracking approach&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Generates output inside a &lt;code&gt;docs/&lt;/code&gt; folder:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;doc.md&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;report.html&lt;/code&gt; (via Pandoc)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 The Interesting Part: Context Extraction
&lt;/h2&gt;

&lt;p&gt;Extracting a single line is easy. Extracting meaningful context is not.&lt;/p&gt;

&lt;p&gt;I initially tried using regex to capture entire functions, but that quickly breaks due to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;nested &lt;code&gt;{}&lt;/code&gt; blocks&lt;/li&gt;
&lt;li&gt;different coding styles&lt;/li&gt;
&lt;li&gt;multi-line structures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead, I implemented a &lt;strong&gt;brace counting strategy&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;When a relevant tag (like BUG or FIXME) is detected:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start capturing lines immediately&lt;/li&gt;
&lt;li&gt;Increment counter on &lt;code&gt;{&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Decrement on &lt;code&gt;}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stop when braces balance&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This provides a reasonable approximation of the surrounding code block without needing a full AST parser.&lt;/p&gt;

&lt;p&gt;It’s not perfect, but it works reliably for most real-world cases.&lt;/p&gt;




&lt;h2&gt;
  
  
  📄 Example Output
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# FILE: calculator.cpp

### Line 12 [BUG] → fix division logic

int divide(int a, int b) {
    // BUG: division by zero
    return a / b;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚖️ Trade-offs
&lt;/h2&gt;

&lt;p&gt;This approach intentionally avoids:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AST parsing (too complex for a first version)&lt;/li&gt;
&lt;li&gt;language-specific parsing logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead, it favors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;speed&lt;/li&gt;
&lt;li&gt;simplicity&lt;/li&gt;
&lt;li&gt;language-agnostic behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The downside:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;context detection is heuristic-based&lt;/li&gt;
&lt;li&gt;edge cases can break block extraction&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Why This Approach
&lt;/h2&gt;

&lt;p&gt;There are already tools for task tracking, but most require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;manual input&lt;/li&gt;
&lt;li&gt;separate interfaces&lt;/li&gt;
&lt;li&gt;extra discipline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DocTrack works differently:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no new workflow&lt;/li&gt;
&lt;li&gt;no extra effort&lt;/li&gt;
&lt;li&gt;just leverage what developers already write&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔗 Project
&lt;/h2&gt;

&lt;p&gt;If you're curious or want to try it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/monkonthehill/doctrack" rel="noopener noreferrer"&gt;https://github.com/monkonthehill/doctrack&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 Open Questions
&lt;/h2&gt;

&lt;p&gt;I’m still exploring a few directions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Should this move toward AST-based parsing for accuracy?&lt;/li&gt;
&lt;li&gt;Would a VS Code extension be more useful than CLI?&lt;/li&gt;
&lt;li&gt;How to handle large codebases efficiently?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Would love to hear thoughts from others building developer tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Final Thought
&lt;/h2&gt;

&lt;p&gt;Developers already leave a trail of intent inside their code.&lt;/p&gt;

&lt;p&gt;The real opportunity is not adding more tools —&lt;br&gt;
but extracting value from what’s already there.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>showdev</category>
      <category>sideprojects</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
