<?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>Forem: Douglas Makey Mendez Molero</title>
    <description>The latest articles on Forem by Douglas Makey Mendez Molero (@douglasmakey).</description>
    <link>https://forem.com/douglasmakey</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F24262%2F95aceb69-fcb6-4c91-a386-5147f3694cfe.jpeg</url>
      <title>Forem: Douglas Makey Mendez Molero</title>
      <link>https://forem.com/douglasmakey</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/douglasmakey"/>
    <language>en</language>
    <item>
      <title>MU Online in Rust: Hardening the Foundation, runtime, Timeouts, and Packet Size Limits</title>
      <dc:creator>Douglas Makey Mendez Molero</dc:creator>
      <pubDate>Thu, 12 Mar 2026 16:41:59 +0000</pubDate>
      <link>https://forem.com/douglasmakey/mu-online-in-rust-hardening-the-foundation-runtime-timeouts-and-packet-size-limits-1dlm</link>
      <guid>https://forem.com/douglasmakey/mu-online-in-rust-hardening-the-foundation-runtime-timeouts-and-packet-size-limits-1dlm</guid>
      <description>&lt;p&gt;We are not implementing login &lt;strong&gt;yet&lt;/strong&gt;, there is cleanup worth doing first. A few things were intentionally left behind in the previous article, and they are worth addressing before we go deeper.&lt;/p&gt;

&lt;p&gt;Before implementing login, handling encrypted packets, and authenticating real players, we must ensure the foundation can withstand basic abuse. This means enforcing timeouts, limiting packet sizes, and laying the groundwork for future enhancements. Clean up first, then harden.&lt;/p&gt;

&lt;p&gt;Currently, both servers duplicate the same TCP listener setup. Although the function is small and a bit of code duplication is tolerable, extracting this logic into a dedicated crate provides a single, clean place to apply these protections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing mu-runtime
&lt;/h2&gt;

&lt;p&gt;We are going to introduce a new crate called &lt;code&gt;mu-runtime&lt;/code&gt;. The idea is simple: one generic server loop, any handler you plug in. Taking advantage of Rust's generics, we can implement a &lt;code&gt;Server&lt;/code&gt; struct that accepts a generic handler for client connections:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;PacketStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Framed&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TcpStream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PacketCodec&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Server&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="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;run_tcp_listener&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;F&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="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;where&lt;/span&gt;
        &lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;Fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PacketStream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SocketAddr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Send&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;'static&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Send&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;'static&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;TcpListener&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.bind_addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="nf"&gt;.with_context&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to bind to {bind_addr}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bind_addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.bind_addr&lt;/span&gt;&lt;span class="p"&gt;)&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="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;shutdown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;pin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;ctrl_c&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;select!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;shutdown&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="n"&gt;accepted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="nf"&gt;.accept&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;peer_addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;accepted&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&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="p"&gt;};&lt;/span&gt;

                    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Framed&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PacketCodec&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;peer_addr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="k"&gt;.await&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="p"&gt;});&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&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;If you compare this to the previous implementation on both servers, it's nearly identical. The only real difference is that instead of calling a hardcoded &lt;code&gt;handle_client&lt;/code&gt; function, we now receive a generic handler. The magic is in the &lt;code&gt;where&lt;/code&gt; clause.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Method signature:&lt;/strong&gt; &lt;code&gt;run_tcp_listener&lt;/code&gt; accepts a handler closure &lt;code&gt;H&lt;/code&gt; that gets called for each inbound connection. The two generic parameters work together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;H: Fn(PacketStream, SocketAddr) -&amp;gt; F:&lt;/code&gt;&lt;/strong&gt; The handler receives a framed stream and the client's address, and returns a future. &lt;code&gt;Fn&lt;/code&gt; (not &lt;code&gt;FnOnce&lt;/code&gt;) means the same handler is reused for every connection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;F: Future&amp;lt;Output = Result&amp;lt;()&amp;gt;&amp;gt;:&lt;/code&gt;&lt;/strong&gt; The returned future resolves to &lt;code&gt;Result&amp;lt;()&amp;gt;&lt;/code&gt;, meaning each connection handler is async and can fail independently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Trait bounds explained:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Send + 'static&lt;/code&gt; on &lt;code&gt;H&lt;/code&gt;: the handler can be shared across threads and doesn't hold any temporary references that might become invalid. Required because we spawn a &lt;code&gt;tokio::spawn&lt;/code&gt; per connection.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Send + 'static&lt;/code&gt; on &lt;code&gt;F&lt;/code&gt;: the future returned by the handler can be sent to a Tokio task (again, &lt;code&gt;tokio::spawn&lt;/code&gt; requirement).&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The reason we use &lt;strong&gt;Fn&lt;/strong&gt; and not &lt;strong&gt;FnOnce&lt;/strong&gt; is that &lt;strong&gt;FnOnce&lt;/strong&gt; would &lt;em&gt;consume&lt;/em&gt; the handler on the first connection, leaving nothing for the second &lt;code&gt;accept()&lt;/code&gt;. The compiler would catch this, but the intent matters: we need a handler we can call repeatedly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now both &lt;code&gt;GameServer&lt;/code&gt; and &lt;code&gt;ConnectServer&lt;/code&gt; can use this &lt;code&gt;Server&lt;/code&gt; struct to start listening:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;tracing_subscriber&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GameServer"&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"0.0.0.0:55901"&lt;/span&gt;&lt;span class="nf"&gt;.parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="n"&gt;server&lt;/span&gt;
        &lt;span class="nf"&gt;.run_tcp_listener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;peer_addr&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;handle_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;peer_addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;.await&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simplifies both servers considerably and gives us a single, central place to evolve the TCP layer. The workspace crate structure now looks 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; ┌──────────────────────┐   ┌──────────────────────┐
 │    connect-server    │   │     game-server      │
 │  (handlers, config)  │   │  (handlers, config)  │
 └──────────┬───────────┘   └──────────┬───────────┘
            │                          │
            └─────────────┬────────────┘
                          │
            ┌─────────────▼────────────┐
            │        mu-runtime        │
            │  Server, PacketStream,   │
            │         timeouts         │
            └─────────────┬────────────┘
                          │
            ┌─────────────▼────────────┐
            │        mu-protocol       │
            │  Packet, PacketCodec,    │
            │  size limits, errors     │
            └──────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both servers depend on &lt;code&gt;mu-runtime&lt;/code&gt; for the TCP loop, and &lt;code&gt;mu-runtime&lt;/code&gt; depends on &lt;code&gt;mu-protocol&lt;/code&gt; for framing. The servers themselves only contain what is unique to them: their handlers and config. Now that we have a shared runtime, this is exactly the right place to enforce the protections we deliberately skipped in the first article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timeouts: The Idle Client Problem
&lt;/h2&gt;

&lt;p&gt;In the previous article, I mentioned some security measures that we intentionally skipped for simplicity. Let's start fixing that.&lt;/p&gt;

&lt;p&gt;We use plain &lt;code&gt;TCP&lt;/code&gt; as our transport. TCP provides reliability at the byte-stream level (retransmission, ordering, flow control), but it gives us no protection at the application level. Without additional safeguards, a single misbehaving or malicious client can tie up server resources indefinitely.&lt;/p&gt;

&lt;p&gt;The first line of defense is timeouts. We need two:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Read timeout:&lt;/strong&gt; limits how long we wait for a client to send data. Without this, a client that connects but never sends anything (intentionally or due to a network issue) holds a connection and a spawned task open forever.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read Timeout — Client sends partial data then goes silent
═══════════════════════════════════════════════════════════

  Client                          Server
    │                               │
    │──── [C1 04 00 01] ───────────►│  Valid packet header
    │                               │  Server expects remaining bytes...
    │                               │
    │          (silence)            │  ⏱ 1s...
    │                               │  ⏱ 2s...
    │                               │  ⏱ 3s...
    │                               │  ⏱ READ_TIMEOUT reached
    │                               │
    │       ◄──── [connection closed]
    │                               │
    Without timeout: server task blocks here forever,
    holding memory and a file descriptor hostage.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Write timeout:&lt;/strong&gt;  limits how long we wait for a client to drain data we're sending. A client that stops reading (or reads extremely slowly) causes backpressure that can stall our write side indefinitely.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Write Timeout — Client connects but never reads responses
═══════════════════════════════════════════════════════════

  Client                          Server
    │                               │
    │──── [packet request] ────────►│
    │                               │──── [packet response] ────► TCP buffer
    │                               │
    │    (client stops reading)     │  Server sends next packet...
    │                               │──── [data packet] ──────► TCP buffer
    │                               │                           TCP buffer full!
    │                               │
    │                               │  .send() blocks waiting
    │                               │  for client to drain buffer
    │                               │  ⏱ 1s...
    │                               │  ⏱ 2s...
    │                               │  ⏱ WRITE_TIMEOUT reached
    │                               │
    │       ◄──── [connection closed]
    │                               │
    Without timeout: server task stalls on .send(),
    backpressure from one client blocks its entire task.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without both of these, our server is vulnerable to resource exhaustion. Even a handful of bad clients could starve legitimate connections.&lt;/p&gt;

&lt;p&gt;To put it simply:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Read timeout:&lt;/strong&gt; for a client that won't talk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write timeout:&lt;/strong&gt; for a client that won't listen.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;These two timeouts protect against well-known attack patterns. The read timeout defends against &lt;strong&gt;Slowloris&lt;/strong&gt;, an attack where a client opens many connections and keeps them alive by sending data just slowly enough to prevent the server from closing them, eventually exhausting the connection pool. The write timeout defends against &lt;strong&gt;backpressure exhaustion&lt;/strong&gt;, where a client deliberately stops reading, causing TCP send buffers to fill up and server tasks to stall indefinitely waiting on a &lt;code&gt;.send()&lt;/code&gt; that can never complete.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Implementing Timeouts in PacketStream
&lt;/h3&gt;

&lt;p&gt;To add timeouts, we are going to evolve our &lt;code&gt;PacketStream&lt;/code&gt;. Instead of a plain type alias for &lt;code&gt;Framed&lt;/code&gt;, we are going to make it a proper wrapper with &lt;code&gt;recv&lt;/code&gt; and &lt;code&gt;send&lt;/code&gt; methods that layer &lt;code&gt;tokio::time::timeout&lt;/code&gt; on top:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;PacketStream&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Framed&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TcpStream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PacketCodec&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;read_timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;write_timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;PacketStream&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RawPacket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ConnectionError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.read_timeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.inner&lt;/span&gt;&lt;span class="nf"&gt;.next&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="nf"&gt;.map_err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ConnectionError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
            &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ConnectionError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ReadTimeout&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&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;RawPacket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;ConnectionError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.write_timeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.inner&lt;/span&gt;&lt;span class="nf"&gt;.send&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="k"&gt;.await&lt;/span&gt;
            &lt;span class="nf"&gt;.map_err&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;ConnectionError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;WriteTimeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
            &lt;span class="nf"&gt;.map_err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ConnectionError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;)&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;And in &lt;code&gt;run_tcp_listener&lt;/code&gt;, we replace the old stream with the new wrapper:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Old&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Framed&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PacketCodec&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// New&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;PacketStream&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.config.read_timeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.config.write_timeout&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;A small change with a real impact.&lt;/p&gt;

&lt;h3&gt;
  
  
  Seeing It in Action
&lt;/h3&gt;

&lt;p&gt;The best part about these protections is how trivially easy it is to trigger the attack and then watch the server shut it down. No special tools needed, just &lt;code&gt;nc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simulating a read-timeout attack (Slowloris):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open a terminal and connect to the &lt;code&gt;ConnectServer&lt;/code&gt; without sending anything:&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="nv"&gt;$ &lt;/span&gt;nc 127.0.0.1 44405
&lt;span class="c"&gt;# just sit here and do nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Before our fix, that connection would hold a &lt;code&gt;Tokio&lt;/code&gt; task and a file descriptor open indefinitely. With the read timeout in place, the server cuts it off after 30 seconds:&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="nv"&gt;RUST_LOG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info cargo run &lt;span class="nt"&gt;-p&lt;/span&gt; connect-server
2026-02-20T19:57:18.632733Z  INFO mu_runtime: ConnectServer listening &lt;span class="nv"&gt;bind_addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0:44405
2026-02-20T19:57:19.536570Z  INFO mu_runtime: client connected &lt;span class="nv"&gt;peer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1:55927
2026-02-20T19:57:19.536892Z DEBUG connect_server: sent hello packet &lt;span class="nv"&gt;peer_addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1:55927
2026-02-20T19:57:49.538663Z  WARN connect_server: Packet &lt;span class="nb"&gt;read &lt;/span&gt;error &lt;span class="nv"&gt;error&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;timed out
2026-02-20T19:57:49.538787Z  INFO connect_server: connect-server client disconnected &lt;span class="nv"&gt;peer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1:55927
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;nc&lt;/code&gt; session gets terminated on the client side too. The connection just drops. One idle connection, handled cleanly, no leaked resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simulating a write-timeout attack (backpressure exhaustion):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Honestly, the write timeout is impossible to demonstrate with the &lt;code&gt;ConnectServer&lt;/code&gt; as it currently stands, and it's worth understanding why. For a write to block, the client's TCP receive buffer must be completely full while the server is actively trying to send. The &lt;code&gt;ConnectServer's&lt;/code&gt; packets are tiny, the Hello is 4 bytes, a &lt;code&gt;ServerListResponse&lt;/code&gt; for two servers is ~15 bytes. The OS enforces a minimum receive buffer of around 4KB regardless of what you set on the socket. Those tiny packets will never come close to filling it, so &lt;code&gt;.send()&lt;/code&gt; always completes instantly and the write timeout never gets a chance to fire.&lt;/p&gt;

&lt;p&gt;The protection becomes real once the &lt;code&gt;GameServer&lt;/code&gt; starts streaming larger payloads such as: position updates, inventory data, map state. A client that connects, triggers a large response, and then stops reading will fill that buffer quickly. At that point, &lt;code&gt;.send()&lt;/code&gt; blocks, and without a write timeout the server task stalls indefinitely.&lt;/p&gt;

&lt;p&gt;So for now, trust the code more than the demo: the mechanism is correct, the &lt;code&gt;ConnectServer&lt;/code&gt; just doesn't produce enough data to make the failure mode visible yet. We'll see it in action when the &lt;code&gt;GameServer&lt;/code&gt; gets more interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Max Packet Size: Starving the Allocator
&lt;/h2&gt;

&lt;p&gt;Another vector worth closing is &lt;strong&gt;unbounded memory allocation&lt;/strong&gt;. A malicious client can send a crafted header claiming an excessively large packet size, forcing the server to allocate memory it will never use before any parsing occurs. Because this happens at the framing layer, that’s also the ideal point to block it.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ConnectServer&lt;/code&gt;, for example, only ever receives &lt;code&gt;C1&lt;/code&gt; packets meaning a maximum of &lt;strong&gt;255 bytes&lt;/strong&gt;. It has no business accepting a &lt;code&gt;C2/C4&lt;/code&gt; packet, which can be up to &lt;strong&gt;65,535 bytes&lt;/strong&gt;. If we blindly allocate memory for whatever length the client claims, a malicious client can send a crafted header claiming a massive packet size and force us to allocate memory we'll never actually use. That's a memory allocation DoS vector, and it happens before any parsing even occurs.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;GameServer&lt;/code&gt; legitimately receives &lt;code&gt;C2/C4&lt;/code&gt; packets, so it needs a higher ceiling. But we don't know yet if a real game packet comes close to the &lt;code&gt;65KB&lt;/code&gt; protocol maximum. We can set a tighter limit something like &lt;code&gt;12–24KB&lt;/code&gt; and adjust as real packets are implemented.&lt;/p&gt;

&lt;p&gt;The right place to enforce this is the codec, which is already responsible for framing the byte stream. The change is minimal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;PacketCodec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;max_packet_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;BytesMut&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&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;...&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;declared_len&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.max_packet_size&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ProtocolError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;PacketTooLarge&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.max_packet_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;declared_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&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="c1"&gt;// Each server enforces its own limit:&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ServerConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ConnectServer"&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;bind_addr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"0.0.0.0:44405"&lt;/span&gt;&lt;span class="nf"&gt;.parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;read_timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_secs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;write_timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_secs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;max_packet_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SMALL_PACKET_MAX_SIZE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// C1 only no need for larger packets&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We reject oversized packets at the codec level, before we touch the payload. No parsing, no allocation beyond the declared limit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Seeing It in Action
&lt;/h3&gt;

&lt;p&gt;This one is easy to trigger with just &lt;code&gt;nc&lt;/code&gt; and &lt;code&gt;printf&lt;/code&gt;. A &lt;code&gt;C2&lt;/code&gt; packet header is only 3 bytes: the type byte plus the 2-byte length field. That is all the codec needs to make its decision. We never have to send the actual payload.&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="c"&gt;# C2 packet claiming to be 1000 bytes:&lt;/span&gt;
&lt;span class="c"&gt;#   \xC2        — C2 type (large packet, 2-byte length)&lt;/span&gt;
&lt;span class="c"&gt;#   \x03\xE8    — length 1000 in big-endian&lt;/span&gt;
&lt;span class="c"&gt;#   \xF4\x06    — code/sub-code (doesn't matter, codec rejects before parsing)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'\xC2\x03\xE8\xF4\x06'&lt;/span&gt; | nc 127.0.0.1 44405
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;ConnectServer&lt;/code&gt; is configured with &lt;code&gt;SMALL_PACKET_MAX_SIZE = 255&lt;/code&gt;. As soon as the codec reads the 3-byte prefix and sees &lt;code&gt;declared_len = 1000 &amp;gt; 255&lt;/code&gt;, it returns &lt;code&gt;PacketTooLarge&lt;/code&gt;. No allocation, no parsing, connection closed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;2026-02-20T20:18:42.764238Z  INFO mu_runtime: ConnectServer listening &lt;span class="nv"&gt;bind_addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0:44405
2026-02-20T20:18:45.055888Z  INFO mu_runtime: client connected &lt;span class="nv"&gt;peer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1:56865
2026-02-20T20:18:45.056244Z DEBUG connect_server: sent hello packet &lt;span class="nv"&gt;peer_addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1:56865
2026-02-20T20:18:45.056295Z  WARN connect_server: Packet &lt;span class="nb"&gt;read &lt;/span&gt;error &lt;span class="nv"&gt;error&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;protocol error: packet too large: max 255 bytes, got 1000
2026-02-20T20:18:45.056312Z  INFO connect_server: connect-server client disconnected &lt;span class="nv"&gt;peer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1:56865
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The attack is dead before it even starts. The same packet sent to the &lt;code&gt;GameServer&lt;/code&gt; which has a higher limit would pass through, because it legitimately handles large packets. Each server enforces the right limit for its own protocol role.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where We Are Now
&lt;/h2&gt;

&lt;p&gt;With these changes, our server is meaningfully more robust. To summarize what we added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;mu-runtime:&lt;/code&gt;&lt;/strong&gt; A centralized, generic TCP listener that both servers share.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read timeout:&lt;/strong&gt; Disconnects clients that connect but never send data (Slowloris protection).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write timeout:&lt;/strong&gt; Disconnects clients that connect but never read responses (backpressure exhaustion protection).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Max packet size:&lt;/strong&gt; Rejects oversized packets at the codec level before any allocation happens (memory DoS protection).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are more mechanisms we could add such as: rate limiting, max concurrent connections, per-IP throttling, but we will revisit those when the need arises. For now, the foundation is solid enough to move forward.&lt;/p&gt;

&lt;p&gt;In the next article, I promise you that we will finally get to the login flow. That means dealing with XOR32-encrypted client packets and implementing our first real game logic.&lt;/p&gt;

&lt;p&gt;All the code can be found in the &lt;a href="https://github.com/douglasmakey/mu-rust" rel="noopener noreferrer"&gt;repository&lt;/a&gt;. Feel free to explore, experiment, and leave comments! &lt;strong&gt;Happy coding!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>network</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>From Nostalgia to Code - Building a MU Online Server in Rust</title>
      <dc:creator>Douglas Makey Mendez Molero</dc:creator>
      <pubDate>Fri, 06 Mar 2026 17:33:41 +0000</pubDate>
      <link>https://forem.com/douglasmakey/from-nostalgia-to-code-building-a-mu-online-server-in-rust-391h</link>
      <guid>https://forem.com/douglasmakey/from-nostalgia-to-code-building-a-mu-online-server-in-rust-391h</guid>
      <description>&lt;h1&gt;
  
  
  From Nostalgia to Code: Building a MU Online Server in Rust
&lt;/h1&gt;

&lt;p&gt;Somewhere between 2005 and 2009, my younger self spent almost all the time in front of a computer playing MU Online, one of the best MMORPGs in history if you ask me. Cybercafes with friends, deploying private servers from guides I barely understood, staying up way too late. Even many years later, every now and then the nostalgia kicks in and I end up playing again with friends to relive the good old times.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2F_next%2Fimage%3Furl%3D%252Fimages%252Fblog%252Fmu-castle.webp%26w%3D2048%26q%3D75" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2F_next%2Fimage%3Furl%3D%252Fimages%252Fblog%252Fmu-castle.webp%26w%3D2048%26q%3D75" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Last year, out of pure curiosity, I was looking on GitHub for MU Online projects and found a very interesting repository: &lt;a href="https://github.com/MUnique/OpenMU" rel="noopener noreferrer"&gt;OpenMU&lt;/a&gt;. These guys created a customizable server for MU Online using &lt;code&gt;C#&lt;/code&gt; from scratch. That is amazing, hats off to them. So I thought, why not use this repo as a reference to write a server in &lt;code&gt;Rust&lt;/code&gt;? My intention isn't to fully rewrite their project. I just want to learn how one of the best games of my childhood works under the hood and have some fun in the process.&lt;/p&gt;

&lt;p&gt;I started by cloning their project and analyzing the repo to understand how everything works, then trying to replicate minimal features. How much will I replicate? I don't know, we are going to discover that together I guess.&lt;/p&gt;

&lt;p&gt;After an initial inspection, the project has a &lt;code&gt;docs&lt;/code&gt; folder with very useful information that the team published describing the project, architecture, intentions, and other valuable details for what we are going to do.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The repo has multiple references to the version/protocol of the current implementation being the ENG (English version) of Season 6 Episode 3. Being honest, I don't remember too much about these versions and don't fully understand at this point how they changed. My last version that I played was 0.99 (the best version if you ask me, but biased haha). For now, we are going to focus on the latest one compatible with the Season 6 client.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One of the key docs is the architecture overview, which gives us a brief idea about how this implementation works. Again, we are not going to implement everything, but it's nice to have an idea about where to start.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2F_next%2Fimage%3Furl%3D%252Fimages%252Fblog%252Fmu-openmu-arch.webp%26w%3D2048%26q%3D75" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2F_next%2Fimage%3Furl%3D%252Fimages%252Fblog%252Fmu-openmu-arch.webp%26w%3D2048%26q%3D75" width="800" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The other key resource I found is the folder with the packet descriptions, which documents the messages exchanged between client and server. With this, we can get a solid idea of the protocol that MU Online implements. We are definitely going to need and spend time here to implement some minimal features.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In this context, a &lt;strong&gt;packet&lt;/strong&gt; is a structured sequence of bytes that represents a single message in the MU Online protocol. Each packet has a header that identifies what kind of message it is, how long it is, and whether it's encrypted, followed by an optional payload with the actual data. Think of it as an envelope: the header is the addressing and stamp, and the payload is the letter inside.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They already documented the list of which packets are being used in the communication between server and client and vice versa, so pretty nice to have.&lt;/p&gt;

&lt;p&gt;One of the key discoveries here is that the protocol utilizes the first byte as a &lt;strong&gt;Frame Identifier&lt;/strong&gt;. As described in the &lt;a href="https://github.com/douglasmakey/mu-rust/blob/main/docs/OpenMU/Packets/PacketTypes.md" rel="noopener noreferrer"&gt;PacketTypes.md&lt;/a&gt; documentation, this byte defines the &lt;strong&gt;binary contract&lt;/strong&gt; between the client and server, specifically governing the &lt;strong&gt;framing logic&lt;/strong&gt; (how to calculate packet length) and the &lt;strong&gt;cryptographic state&lt;/strong&gt; (whether XOR32 or Simple Modulus is applied).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Framing&lt;/strong&gt; is the process of determining where one message ends and the next one begins in a stream of bytes. Since TCP delivers data as a continuous byte stream with no built-in message boundaries, the protocol needs a way to delimit individual packets, that's what the frame identifier and the length fields do.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;First byte&lt;/th&gt;
&lt;th&gt;Length of the packet&lt;/th&gt;
&lt;th&gt;Encrypted Server -&amp;gt; Client&lt;/th&gt;
&lt;th&gt;Encrypted Client -&amp;gt; Server&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0xC1&lt;/td&gt;
&lt;td&gt;Specified by the second byte&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (XOR32)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0xC2&lt;/td&gt;
&lt;td&gt;Specified by the second and third byte&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (XOR32)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0xC3&lt;/td&gt;
&lt;td&gt;Specified by the second byte&lt;/td&gt;
&lt;td&gt;Yes (Simple modulus)&lt;/td&gt;
&lt;td&gt;Yes (Simple modulus + XOR32)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0xC4&lt;/td&gt;
&lt;td&gt;Specified by the second and third byte&lt;/td&gt;
&lt;td&gt;Yes (Simple modulus)&lt;/td&gt;
&lt;td&gt;Yes (Simple modulus + XOR32)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So basically, the first byte is the &lt;strong&gt;frame identifier&lt;/strong&gt; as we mentioned. It controls two things: how you read the &lt;strong&gt;length&lt;/strong&gt;, and whether the payload is &lt;strong&gt;encrypted&lt;/strong&gt;. The first byte tells the packet parser how to read the &lt;em&gt;rest&lt;/em&gt; of the data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C1 vs C2&lt;/strong&gt; is about size capacity. C1 stores the packet length in a single byte (byte index 1), so packets can be at most &lt;strong&gt;255 bytes&lt;/strong&gt;. C2 uses two bytes for length (indices 1-2), supporting up to &lt;strong&gt;65,535 bytes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C3 vs C4&lt;/strong&gt; mirror C1/C2 in their length encoding, but add &lt;strong&gt;Simple Modulus encryption&lt;/strong&gt; on top. I guess they're used for sensitive data, anything worth protecting from packet sniffing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encryption is Asymmetric by Direction
&lt;/h3&gt;

&lt;p&gt;This is a critical detail as we can see in the table:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server -&amp;gt; Client&lt;/strong&gt;: C1/C2 are plaintext. C3/C4 use Simple Modulus.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client -&amp;gt; Server&lt;/strong&gt;: &lt;em&gt;Everything&lt;/em&gt; gets XOR32 encrypted, and C3/C4 additionally get Simple Modulus + XOR32.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the client always encrypts outbound traffic (at minimum XOR32), while the server only encrypts when using C3/C4. This makes sense, sniffing what the server sends is less dangerous than injecting forged client packets.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is XOR32
&lt;/h2&gt;

&lt;p&gt;XOR is a bitwise operation: compare two bits, output 1 if they differ, 0 if they match.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1 XOR 1 = 0
1 XOR 0 = 1
0 XOR 1 = 1
0 XOR 0 = 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;XOR32 means we have a &lt;strong&gt;32-byte key&lt;/strong&gt; (a fixed sequence of 32 bytes, I originally thought it was 32 bits but after reading the implementation I figured out it's the key length). To encrypt, we XOR each byte of our data with the corresponding byte of the key, cycling back to the start of the key every 32 bytes.&lt;/p&gt;

&lt;p&gt;So it will be something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Data:    [A] [B] [C] [D] ...
Key:     [K0][K1][K2][K3] ...  (repeats every 32 bytes)
Result:  [A^K0] [B^K1] [C^K2] [D^K3] ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The beauty of XOR is that &lt;strong&gt;applying it twice reverses it&lt;/strong&gt;. Encrypt and decrypt are the same operation with the same key. That's why it's fast and simple. The weakness: if someone knows (or brute forces) the key, it's trivially broken. It's not real security, it's simple &lt;strong&gt;obfuscation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We won't implement &lt;code&gt;XOR32&lt;/code&gt; in this article since the client sends the only payload packet unencrypted for this scope, but we'll tackle it in the next one when we handle login. If you're curious, you can play with a basic &lt;code&gt;XOR32&lt;/code&gt; implementation in the &lt;a href="https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2024&amp;amp;gist=222821cb5f5bc9b147a88672736ecac9" rel="noopener noreferrer"&gt;Rust playground&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simple Modulus&lt;/strong&gt; (used by C3/C4 packets) is a custom block-based encryption algorithm that deserves its own article, so we'll skip it for now since our initial handshake scope doesn't require it. If you're curious, the OpenMU creator has two great posts about it: &lt;a href="https://munique.net/a-closer-look-at-the-mu-online-packet-encryption/" rel="noopener noreferrer"&gt;A closer look at the MU Online packet encryption&lt;/a&gt; and &lt;a href="https://munique.net/simplemodulus-revisited/" rel="noopener noreferrer"&gt;SimpleModulus revisited&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  C1 00 01 - The Initial Hello!
&lt;/h2&gt;

&lt;p&gt;Thanks to the great docs and the implementation that the &lt;a href="https://github.com/MUnique/OpenMU" rel="noopener noreferrer"&gt;OpenMU&lt;/a&gt; team provides, we can understand the initial flow of the communication between the &lt;code&gt;client&lt;/code&gt; and the &lt;code&gt;servers&lt;/code&gt;: the iconic login screen.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Hello by server&lt;/strong&gt; packet describes this initial interaction. The packet is sent by the server after the client connects, and the client will request the server list as soon as it receives the hello packet.&lt;/p&gt;

&lt;p&gt;Inspecting the packet:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Index&lt;/th&gt;
&lt;th&gt;Length&lt;/th&gt;
&lt;th&gt;Data Type&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Byte&lt;/td&gt;
&lt;td&gt;0xC1&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/douglasmakey/mu-rust/blob/main/docs/OpenMU/Packets/PacketTypes.md" rel="noopener noreferrer"&gt;Packet type&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Byte&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Packet header - length of the packet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Byte&lt;/td&gt;
&lt;td&gt;0x00&lt;/td&gt;
&lt;td&gt;Packet header - packet type identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Byte&lt;/td&gt;
&lt;td&gt;0x01&lt;/td&gt;
&lt;td&gt;Packet header - sub packet type identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Dissecting it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;0xC1&lt;/strong&gt; -&amp;gt; Small packet, no encryption server-&amp;gt;client, length in byte 1&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;0x04&lt;/strong&gt; -&amp;gt; Total packet length is 4 bytes (header only, no payload)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;0x00&lt;/strong&gt; -&amp;gt; Main packet type identifier&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;0x01&lt;/strong&gt; -&amp;gt; Sub-type&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After inspecting the packet definition headers and the implementation, we can infer that the first byte indicates whether the packet is small &lt;code&gt;(C1/C3)&lt;/code&gt; or large &lt;code&gt;(C2/C4)&lt;/code&gt;. Next comes the one or two byte length field, followed by a byte that serves as a packet or group identifier (for example, the connection or handshake family). And finally, some groups include a subtype byte, such as the hello packet, while others do not. So the &lt;strong&gt;Header Size&lt;/strong&gt; varies (3, 4, or 5 bytes) depending on the first byte and the type/sub-type.&lt;/p&gt;

&lt;p&gt;The two-level identification scheme (byte 2 or 3 = group/code, byte 3 or 4 = sub type/code) gives us a clean routing architecture. &lt;code&gt;0x00&lt;/code&gt; is the connection group, and within it &lt;code&gt;0x01&lt;/code&gt; means "hello." Think of it like &lt;code&gt;namespace::method&lt;/code&gt;, but as we mentioned, some packets just have a type and don't have a sub-type.&lt;/p&gt;

&lt;p&gt;As the docs say, after the hello packet is sent to the client, the client will send the &lt;code&gt;ServerListRequest (C1 F4 06)&lt;/code&gt; packet to the server. This packet is similar to the hello packet in definition, but the server will respond with the &lt;code&gt;ServerListResponse (C2 F4 06)&lt;/code&gt; packet, and this one is worth examining to understand the dynamic headers we discussed earlier.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Index&lt;/th&gt;
&lt;th&gt;Length&lt;/th&gt;
&lt;th&gt;Data Type&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Byte&lt;/td&gt;
&lt;td&gt;0xC2&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/douglasmakey/mu-rust/blob/main/docs/OpenMU/Packets/PacketTypes.md" rel="noopener noreferrer"&gt;Packet type&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Short&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Packet header - length of the packet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Byte&lt;/td&gt;
&lt;td&gt;0xF4&lt;/td&gt;
&lt;td&gt;Packet header - packet type identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Byte&lt;/td&gt;
&lt;td&gt;0x06&lt;/td&gt;
&lt;td&gt;Packet header - sub packet type identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;ShortBigEndian&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;ServerCount&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;ServerLoadInfo.Length * N&lt;/td&gt;
&lt;td&gt;Array of ServerLoadInfo&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Servers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;ServerLoadInfo Structure (Length: 4 Bytes):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Index&lt;/th&gt;
&lt;th&gt;Length&lt;/th&gt;
&lt;th&gt;Data Type&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;ShortLittleEndian&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;ServerId&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Byte&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;LoadPercentage&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In this packet we can see the dynamic header in action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining the Scope
&lt;/h2&gt;

&lt;p&gt;After reviewing the implementation, I decided the scope of this first effort: we are going to implement up to the also mythical login screen. That covers the client and server handshake, server list, and client server selection. I believe this will be enough for this first article.&lt;/p&gt;

&lt;p&gt;To achieve this, we need to review the implementation and gather all the components and required pieces that we have to put together. As we recently reviewed the packets, which are the foundation of the MU Online protocol, here is the list of packets involved for this scope:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hello (C1 00 01) - By Server&lt;/li&gt;
&lt;li&gt;ServerListRequest (C1 F4 06) - By Client&lt;/li&gt;
&lt;li&gt;ServerListResponse (C2 F4 06) - By Server&lt;/li&gt;
&lt;li&gt;ConnectionInfoRequest (C1 F4 03) - By Client&lt;/li&gt;
&lt;li&gt;ConnectionInfo (C1 F4 03) - By Server&lt;/li&gt;
&lt;li&gt;GameServerEntered (C1 F1 00) - By Server&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;[!NOTE]&lt;br&gt;
The bytes in parentheses after each packet name reflect the packet identification using the packet type, packet group, and packet sub-group. We are omitting the length field and the rest of the payload bytes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So the flow of this initial communication will be something like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhn8b1n2gei2smg7qvwpp.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhn8b1n2gei2smg7qvwpp.jpeg" alt=" " width="800" height="780"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;In the diagram above you can identify that we have 3 main components: the &lt;code&gt;Client&lt;/code&gt;, the &lt;code&gt;ConnectServer&lt;/code&gt;, and the &lt;code&gt;GameServer&lt;/code&gt;. MU Online's architecture separates the &lt;strong&gt;Discovery/Entry&lt;/strong&gt; phase from the &lt;strong&gt;Gameplay&lt;/strong&gt; phase. This separation provides some nice benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Load Balancing&lt;/strong&gt;: A single entry point (&lt;code&gt;ConnectServer&lt;/code&gt;) can distribute players across multiple &lt;code&gt;GameServer&lt;/code&gt; instances (e.g., Server 1, Server 2, Sub-Server 1).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: We can add more Game Servers horizontally without changing the client configuration. The client only needs to know the IP of the Connect Server, which as we can see in the diagram is the one responsible for providing Game Server information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolation&lt;/strong&gt;: If a Game Server crashes or restarts, the Connect Server remains online, allowing players to see the server status and reconnect to other available servers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ConnectServer - Discovery/Entry Phase
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;ConnectServer&lt;/strong&gt; is the &lt;em&gt;Gateway&lt;/em&gt; to our infrastructure. It listens on port &lt;code&gt;44405&lt;/code&gt; and is the first point of contact for any client.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core Responsibilities:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Handshake&lt;/strong&gt;: Handles the initial handshake with the client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server List Management&lt;/strong&gt;: Maintains a registry of available Game Servers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client Discovery&lt;/strong&gt;: Responds to client requests for the Server List.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redirection&lt;/strong&gt;: When a user selects a server, it provides the specific IP address and Port of that Game Server.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]&lt;br&gt;
Something to notice: after the client selects a game server and connects to it, the connection to the ConnectServer is typically closed shortly after.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  GameServer - Gameplay Phase
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;GameServer&lt;/strong&gt; is the &lt;em&gt;Engine&lt;/em&gt; of the world. It handles all logic once the player has selected a server, and it starts listening on port &lt;code&gt;55901&lt;/code&gt; by default.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core Responsibilities:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Authentication&lt;/strong&gt;: Validates User/Password (Login Packet handling).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;World State&lt;/strong&gt;: Manages maps, player positions, monsters, and items.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interaction Logic&lt;/strong&gt;: Handles movement, combat, trading, chat, and skills.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistence&lt;/strong&gt;: Reads/Writes character data to the Database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session Management&lt;/strong&gt;: Maintains the persistent TCP connection for the duration of play.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let's Start Building
&lt;/h2&gt;

&lt;p&gt;Well, with all of this context we have everything to start playing around and working on our server. We are going to build our simple server, but what about the client? For that, I found a couple of clients also on GitHub that mention they work with &lt;code&gt;OpenMU&lt;/code&gt;. The same team has their own client implementation, but I found one that I could compile from my Mac, so I am going to use that one. You can find the client &lt;a href="https://github.com/bernatvadell/muonline" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before we continue, something worth mentioning is that after the initial discovery and review of the flow that we are going to cover in this first effort, I found two important things related to the packets and flow involved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only one of the packets has a payload from client to server: the &lt;code&gt;ConnectionInfoRequest&lt;/code&gt; packet (which should be encrypted by XOR32 according to the docs, since all client-&amp;gt;server traffic uses XOR32 at minimum). But in this case, the client is sending the serverId unencrypted, so we don't need to implement XOR32 for this scope.&lt;/li&gt;
&lt;li&gt;For the last packet, &lt;code&gt;GameServerEntered&lt;/code&gt;, this is like the "hello packet" that the GameServer sends to the client as soon as it connects. If you inspect the definition, you'll find that this packet has a payload with some values like &lt;code&gt;PlayerId&lt;/code&gt;, &lt;code&gt;VersionString&lt;/code&gt;, and &lt;code&gt;Version&lt;/code&gt; in binary. After some research, I found these values are hardcoded in OpenMU, so we are going to use the same values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we start with our implementation. For that, we can create our new &lt;code&gt;Rust&lt;/code&gt; project. We are going to use a Rust &lt;code&gt;workspace&lt;/code&gt;. As this involves a fair amount of code, I won't show all of it here. Instead, I will highlight the most significant parts and explain from there. Some snippets are simplified for clarity, the full implementation is in the &lt;a href="https://github.com/douglasmakey/mu-rust" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Protocol Crate
&lt;/h3&gt;

&lt;p&gt;One of the central pieces of the architecture will be a crate that we are going to name &lt;code&gt;mu-protocol&lt;/code&gt;. Here we are going to define two central pieces for our client and server exchange: our &lt;code&gt;Packet&lt;/code&gt; definition and &lt;code&gt;Codec&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[derive(Debug,&lt;/span&gt; &lt;span class="nd"&gt;PartialEq,&lt;/span&gt; &lt;span class="nd"&gt;Eq,&lt;/span&gt; &lt;span class="nd"&gt;Clone,&lt;/span&gt; &lt;span class="nd"&gt;Copy)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;RawPacketType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;C1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;C2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;C3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;C4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;RawPacketType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;header_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;C1&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;C3&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;C2&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;C4&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&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;As we mentioned before, the protocol uses the first byte as a frame identifier. The protocol names it the PacketType (see &lt;a href="https://github.com/douglasmakey/mu-rust/blob/main/docs/OpenMU/Packets/PacketTypes.md" rel="noopener noreferrer"&gt;PacketTypes.md&lt;/a&gt;), and it defines the size of the packet and the encryption. So we create a simple enum to mirror this. &lt;code&gt;header_length&lt;/code&gt; applies the logic from the definition for determining the header length: remember C1 and C3 are small (defined by one byte) and C2 and C4 are the larger ones (defined by two bytes).&lt;/p&gt;

&lt;p&gt;Then, we have our &lt;code&gt;RawPacket&lt;/code&gt; definition. It's a pretty simple struct with some helper methods to make our journey easier. The idea is straightforward: it's a way to create a valid Packet based on the minimal protocol header definition, representing the packets exchanged between &lt;code&gt;client&lt;/code&gt; and &lt;code&gt;servers&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;RawPacket&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;packet_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RawPacketType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;RawPacket&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;try_new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ProtocolError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;declared_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;declared_length_from_prefix&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;bytes&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;actual_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;declared_len&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;actual_len&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ProtocolError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LengthMismatch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;declared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;declared_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;actual_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;packet_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bytes&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="nf"&gt;.try_into&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="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;packet_type&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;header_codes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;header_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.packet_type&lt;/span&gt;&lt;span class="nf"&gt;.header_length&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.bytes&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;header_len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.copied&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.bytes&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;header_len&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="nf"&gt;.copied&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;)&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;h3&gt;
  
  
  The Codec
&lt;/h3&gt;

&lt;p&gt;And the codec. But what is a codec in this context? A &lt;strong&gt;codec&lt;/strong&gt; (coder/decoder) is a component that knows how to transform raw bytes from a stream into structured messages (decoding) and back again (encoding). Since TCP gives us a continuous stream of bytes with no message boundaries, we need something to frame individual packets, that's what our codec does. We are using &lt;code&gt;tokio_util::codec&lt;/code&gt;, which provides the &lt;code&gt;Decoder&lt;/code&gt; and &lt;code&gt;Encoder&lt;/code&gt; traits that integrate directly with Tokio's async I/O. This way, we get a clean &lt;code&gt;Stream&lt;/code&gt; of &lt;code&gt;RawPacket&lt;/code&gt; items coming in and a &lt;code&gt;Sink&lt;/code&gt; for sending them out, without having to manually manage byte buffers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BytesMut&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;tokio_util&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;codec&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Decoder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Encoder&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;PacketCodec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Decoder&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;PacketCodec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RawPacket&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ProtocolError&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;BytesMut&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;declared_len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;declared_length_from_prefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;None&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="n"&gt;src&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;declared_len&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Tell tokio-util how many bytes we still need so it can size&lt;/span&gt;
            &lt;span class="c1"&gt;// the next read syscall appropriately.&lt;/span&gt;
            &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="nf"&gt;.reserve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;declared_len&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// split_to advances the buffer past this frame; freeze yields an&lt;/span&gt;
        &lt;span class="c1"&gt;// immutable Bytes (zero-copy, Arc-backed) for RawPacket to own.&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;packet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="nf"&gt;.split_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;declared_len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.freeze&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;RawPacket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;try_new&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="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Encoder&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RawPacket&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;PacketCodec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ProtocolError&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RawPacket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;BytesMut&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&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;dst&lt;/span&gt;&lt;span class="nf"&gt;.extend_from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="nf"&gt;.as_slice&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&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;h3&gt;
  
  
  The TCP Servers
&lt;/h3&gt;

&lt;p&gt;As we saw before, we are going to need a &lt;code&gt;ConnectServer&lt;/code&gt; and a &lt;code&gt;GameServer&lt;/code&gt;. These for now will be very simple &lt;code&gt;TCP&lt;/code&gt; listeners, and of course we are going to use the well-known &lt;code&gt;Tokio&lt;/code&gt; for everything related to &lt;code&gt;async I/O.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For this, we have a simple function on each server component that creates a &lt;code&gt;TCP&lt;/code&gt; listener and enters a loop for accepting connections:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;run_server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;TcpListener&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;bind&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;config&lt;/span&gt;&lt;span class="py"&gt;.bind_addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;.await&lt;/span&gt;
        &lt;span class="nf"&gt;.with_context&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to bind to {}"&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;config&lt;/span&gt;&lt;span class="py"&gt;.bind_addr&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="nd"&gt;info!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connect Server is listening"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Pin the future so we can poll it repeatedly across select! iterations.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;shutdown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;pin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;ctrl_c&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;select!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;shutdown&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;info!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"shutting down server"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;accepted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="nf"&gt;.accept&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;peer_addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;accepted&lt;/span&gt;&lt;span class="nf"&gt;.context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to accept client connection"&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="nd"&gt;info!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;peer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;peer_addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Client connected"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;client_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;clone&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;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;handle_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;peer_addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;client_config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nd"&gt;warn!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;peer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;peer_addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"client handling failed"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;Ok&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;Both &lt;code&gt;ConnectServer&lt;/code&gt; and &lt;code&gt;GameServer&lt;/code&gt; have an almost identical &lt;code&gt;run_server&lt;/code&gt; function that receives some sort of &lt;code&gt;Config&lt;/code&gt; relevant to each server. This function launches the TCP listener and keeps things simple for now.&lt;/p&gt;

&lt;p&gt;Where &lt;code&gt;ConnectServer&lt;/code&gt; and &lt;code&gt;GameServer&lt;/code&gt; differ is in the &lt;code&gt;handle_client&lt;/code&gt; function, which is responsible for handling each client connection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling the Client Connection
&lt;/h3&gt;

&lt;p&gt;If you remember, the &lt;code&gt;ConnectServer&lt;/code&gt; is the entry point and where almost all the communication exchange for this effort happens. So focusing on the &lt;code&gt;ConnectServer&lt;/code&gt;, let's look at its &lt;code&gt;handle_client&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;handle_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TcpStream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;peer_addr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SocketAddr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Arc&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ConnectConfig&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;framed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Framed&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PacketCodec&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;hello_packet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;RawPacket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;try_from_vec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;C1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0x04&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0x00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0x01&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="n"&gt;framed&lt;/span&gt;&lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hello_packet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;framed&lt;/span&gt;&lt;span class="nf"&gt;.next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;packet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;handle_packet&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;config&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;packet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;peer_addr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nn"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;PacketHandling&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Reply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;framed&lt;/span&gt;&lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nn"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;PacketHandling&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Ignore&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
            &lt;span class="nn"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;PacketHandling&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Disconnect&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;Ok&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;The key here is that as soon as the &lt;code&gt;Client&lt;/code&gt; connects to the &lt;code&gt;ConnectServer&lt;/code&gt;, we send the &lt;code&gt;Hello&lt;/code&gt; packet as we explained in the communication flow. That will cause the client to request the server list, and then we handle the subsequent requests. That part is resolved by &lt;code&gt;handlers::handle_packet&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we run the &lt;code&gt;ConnectServer&lt;/code&gt; and point a client at it, we can see the entire handshake flow playing out in the logs:&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="nv"&gt;RUST_LOG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;debug cargo run &lt;span class="nt"&gt;-p&lt;/span&gt; connect-server
2026-02-17T19:25:10.267046Z  INFO connect_server: starting connect server &lt;span class="nv"&gt;bind_addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0:44405 &lt;span class="nv"&gt;server_count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2
2026-02-17T19:25:10.267325Z  INFO connect_server: Connect Server is listening
2026-02-17T19:25:43.970652Z  INFO connect_server: Client connected &lt;span class="nv"&gt;peer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1:53368
2026-02-17T19:25:43.971023Z DEBUG connect_server: sent hello packet &lt;span class="nv"&gt;peer_addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1:53368
2026-02-17T19:25:43.993037Z DEBUG connect_server: received packet &lt;span class="nv"&gt;packet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;RawPacket&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;len&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4, &lt;span class="nv"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;C1, 04, F4, 06]&lt;span class="o"&gt;)&lt;/span&gt;
2026-02-17T19:25:43.993071Z  INFO connect_server::handlers: Server list requested &lt;span class="nv"&gt;peer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1:53368 &lt;span class="nv"&gt;server_count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2
2026-02-17T19:25:46.543965Z DEBUG connect_server: received packet &lt;span class="nv"&gt;packet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;RawPacket&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;len&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;6, &lt;span class="nv"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;C1, 06, F4, 03, 01, 00]&lt;span class="o"&gt;)&lt;/span&gt;
2026-02-17T19:25:46.544041Z  INFO connect_server::handlers: Connection info requested &lt;span class="nv"&gt;peer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1:53368 &lt;span class="nv"&gt;server_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
2026-02-17T19:25:46.544065Z DEBUG connect_server::packet: Building connection info &lt;span class="nv"&gt;ip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1 &lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;55901
2026-02-17T19:25:46.598691Z  INFO connect_server: connect-server client disconnected &lt;span class="nv"&gt;peer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1:53368
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see the exact flow we described earlier: the server sends the hello, the client requests the server list (&lt;code&gt;C1 04 F4 06&lt;/code&gt;), picks a server (&lt;code&gt;C1 06 F4 03 01 00&lt;/code&gt; with server_id=1), gets the connection info back, and disconnects. The raw bytes in the logs match our packet definitions perfectly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parsing Packets
&lt;/h3&gt;

&lt;p&gt;For parsing, we are going to use the powerful enum and pattern matching system of Rust to build a packet parser for the packets expected by the ConnectServer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;ConnectServerPacket&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ServerListRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ConnectionInfoRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;server_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;Unknown&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u8&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;sub_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;ConnectServerPacket&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parse&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;RawPacket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ProtocolError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sub_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="nf"&gt;.header_codes&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sub_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0xF4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0x06&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ServerListRequest&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0xF4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0x03&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="nf"&gt;.as_slice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;server_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_le_bytes&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]]);&lt;/span&gt;
                &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ConnectionInfoRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;server_id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Unknown&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sub_code&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="p"&gt;}&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;We determine the request type by inspecting the &lt;code&gt;code&lt;/code&gt; and &lt;code&gt;sub_code&lt;/code&gt;, the two-level identification system that we talked about before. Once we identify the request, we can easily build the response. With this, &lt;code&gt;handle_packet&lt;/code&gt; is pretty straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;handle_packet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;config&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;ConnectConfig&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;RawPacket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;peer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SocketAddr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;PacketHandling&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;ConnectServerPacket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;parse&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="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nn"&gt;PacketHandling&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Disconnect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;parsed&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;ConnectServerPacket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ServerListRequest&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_server_list_response&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;config&lt;/span&gt;&lt;span class="py"&gt;.servers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;Ok&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="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;PacketHandling&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Reply&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="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nn"&gt;PacketHandling&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Disconnect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nn"&gt;ConnectServerPacket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ConnectionInfoRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;server_id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="py"&gt;.servers&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.find&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="py"&gt;.id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;server_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_connection_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nf"&gt;Ok&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="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;PacketHandling&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Reply&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="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nn"&gt;PacketHandling&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Disconnect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="nb"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nn"&gt;PacketHandling&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Ignore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nn"&gt;ConnectServerPacket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Unknown&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sub_code&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;warn!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;sub_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown packet"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nn"&gt;PacketHandling&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Ignore&lt;/span&gt;
        &lt;span class="p"&gt;}&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;h3&gt;
  
  
  Building Responses
&lt;/h3&gt;

&lt;p&gt;And finally, after identifying the request we build the corresponding response, following each packet definition. Again, thanks to the OpenMU team for the great documentation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Wire layout constants for C2-F4-06 ServerListResponse.&lt;/span&gt;
&lt;span class="c1"&gt;// See: docs/OpenMU/Packets/C2-F4-06-ServerListResponse_by-server.md&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;HEADER_SIZE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// C2 framing(3) + code(1) + sub_code(1) + server_count(2)&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;ENTRY_SIZE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// server_id(2) + load_percentage(1) + padding(1)&lt;/span&gt;

&lt;span class="cd"&gt;/// Builds a C1-F4-03 ConnectionInfo response packet.&lt;/span&gt;
&lt;span class="cd"&gt;/// See: docs/OpenMU/Packets/C1-F4-03-ConnectionInfo_by-server.md&lt;/span&gt;
&lt;span class="cd"&gt;///&lt;/span&gt;
&lt;span class="cd"&gt;/// Wire layout (22 bytes total):&lt;/span&gt;
&lt;span class="cd"&gt;///   [0]    C1 header&lt;/span&gt;
&lt;span class="cd"&gt;///   [1]    length (22)&lt;/span&gt;
&lt;span class="cd"&gt;///   [2]    code   (0xF4)&lt;/span&gt;
&lt;span class="cd"&gt;///   [3]    sub    (0x03)&lt;/span&gt;
&lt;span class="cd"&gt;///   [4..20] IP address as a null-terminated ASCII string in a 16-byte field&lt;/span&gt;
&lt;span class="cd"&gt;///   [20..22] port as little-endian u16&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;build_connection_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Ipv4Addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RawPacket&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ip_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;BytesMut&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;with_capacity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.put_u8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;C1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.put_u8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.put_u8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0xF4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.put_u8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0x03&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// IPv4 max string is "255.255.255.255" (15 chars), which fits in the&lt;/span&gt;
    &lt;span class="c1"&gt;// 16-byte protocol field. Remaining bytes are null-padded.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ip_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ip_str&lt;/span&gt;&lt;span class="nf"&gt;.as_bytes&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.put_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip_bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ip_bytes&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.put_u8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0x00&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.put_u16_le&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nn"&gt;RawPacket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;try_new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.freeze&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cd"&gt;/// Builds a C2-F4-06 ServerListResponse packet.&lt;/span&gt;
&lt;span class="cd"&gt;/// See: docs/OpenMU/Packets/C2-F4-06-ServerListResponse_by-server.md&lt;/span&gt;
&lt;span class="cd"&gt;///&lt;/span&gt;
&lt;span class="cd"&gt;/// Wire layout:&lt;/span&gt;
&lt;span class="cd"&gt;///   [0]      C2 header&lt;/span&gt;
&lt;span class="cd"&gt;///   [1..3]   total length (big-endian u16) — uses C2 because the list can exceed 255 bytes&lt;/span&gt;
&lt;span class="cd"&gt;///   [3]      code   (0xF4)&lt;/span&gt;
&lt;span class="cd"&gt;///   [4]      sub    (0x06)&lt;/span&gt;
&lt;span class="cd"&gt;///   [5..7]   server count (big-endian u16)&lt;/span&gt;
&lt;span class="cd"&gt;///   [7..]    N × 4-byte ServerLoadInfo entries&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;build_server_list_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;servers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ConfiguredGameServer&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;anyhow&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RawPacket&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;payload_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HEADER_SIZE&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;servers&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ENTRY_SIZE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;packet_len&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u16&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payload_len&lt;/span&gt;
        &lt;span class="nf"&gt;.try_into&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.map_err&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;anyhow&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;anyhow!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"packet length overflow"&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="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;BytesMut&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;with_capacity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload_len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.put_u8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;C2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.put_u16&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet_len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.put_u8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0xF4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.put_u8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0x06&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;server_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u16&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;servers&lt;/span&gt;
        &lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.try_into&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.map_err&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;anyhow&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;anyhow!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"too many servers for u16 count field"&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="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.put_u16&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server_count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;servers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.put_u16_le&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="py"&gt;.id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.put_u8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="py"&gt;.load_percentage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.put_u8&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="c1"&gt;// padding byte defined by protocol&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nn"&gt;RawPacket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;try_new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="nf"&gt;.freeze&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;An important note here is that I am omitting a lot of improvements, features, and security measures that you may notice in our TCP listener on purpose. The idea is to revisit and implement them in future articles, so the code is kept pretty simple for now. As the series advances, the implementation will evolve.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Also, since this is a work in progress, a lot of the implementation will and must change as other features and flows are added and we play around with more complex game mechanisms.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;With this initial implementation, we achieve something great and very fun for me: the mythical login flow!&lt;/p&gt;

&lt;p&gt;Our ConnectServer responding with the server list, just like the old days:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2F_next%2Fimage%3Furl%3D%252Fimages%252Fblog%252Fmu-select-server.webp%26w%3D2048%26q%3D75" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2F_next%2Fimage%3Furl%3D%252Fimages%252Fblog%252Fmu-select-server.webp%26w%3D2048%26q%3D75" width="1110" height="878"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After selecting a server, the client connects to our GameServer and we get the login screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2F_next%2Fimage%3Furl%3D%252Fimages%252Fblog%252Fmu-login.webp%26w%3D2048%26q%3D75" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2F_next%2Fimage%3Furl%3D%252Fimages%252Fblog%252Fmu-login.webp%26w%3D2048%26q%3D75" width="1200" height="670"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seeing that login screen pop up from a server I wrote myself was honestly one of the most satisfying moments I've had in a while. What started as pure nostalgia turned into a deep dive into revisiting binary protocols, packet framing, and async networking in Rust.&lt;/p&gt;

&lt;p&gt;A few things that surprised me during this process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How well-documented the protocol actually is, thanks to the &lt;strong&gt;OpenMU team&lt;/strong&gt;. Without their work, this would have been a much harder journey.&lt;/li&gt;
&lt;li&gt;How clean the protocol design is for a game from &lt;code&gt;2001&lt;/code&gt;. The two-level packet identification, the separation between ConnectServer and GameServer, it's a simple and working architecture.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's a lot left to do: authentication, character selection, and eventually the actual game world. In the next article, we'll tackle the login flow and start dealing with encrypted client packets.&lt;/p&gt;

&lt;p&gt;All the code can be found in the &lt;a href="https://github.com/douglasmakey/mu-rust" rel="noopener noreferrer"&gt;repository&lt;/a&gt;. Feel free to explore, experiment, and leave comments! &lt;strong&gt;Happy coding!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>OSDev Bare Bones with Rust - Cross-Compilation and Freestanding</title>
      <dc:creator>Douglas Makey Mendez Molero</dc:creator>
      <pubDate>Tue, 10 Feb 2026 20:03:08 +0000</pubDate>
      <link>https://forem.com/douglasmakey/osdev-bare-bones-with-rust-cross-compilation-and-freestanding-598b</link>
      <guid>https://forem.com/douglasmakey/osdev-bare-bones-with-rust-cross-compilation-and-freestanding-598b</guid>
      <description>&lt;p&gt;For a while now, I've had &lt;code&gt;OSDev Bare Bones&lt;/code&gt; on my todo list—almost two or three years if I'm not wrong. I always wanted to give it a shot but never had the time, and in the last months I was dealing with some burnout. Fortunately, I'm managing to recover from that. Long story for another post, or maybe not.&lt;/p&gt;

&lt;p&gt;This post will be the first in a new series where I'll be working through the &lt;a href="https://wiki.osdev.org/Bare_Bones" rel="noopener noreferrer"&gt;OSDev Bare Bones&lt;/a&gt; tutorial, or at least try to get as far as I can. I'll be posting along the way to share knowledge as usual and also to reinforce my own learning.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;a href="https://wiki.osdev.org/Bare_Bones" rel="noopener noreferrer"&gt;OSDev Bare Bones&lt;/a&gt; tutorial is a well-known guide from the OSDev Wiki that walks you through creating a minimal operating system kernel. It covers the fundamentals: setting up a cross-compiler, writing a simple kernel in &lt;code&gt;C&lt;/code&gt;, and booting it with GRUB.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt; I think the OSDev tutorial is a very interesting exercise that can teach you a couple of things. My only thought is that it's a bit old. Also, I'm not a &lt;code&gt;C&lt;/code&gt; developer and I'm still fighting to learn more about &lt;code&gt;Rust&lt;/code&gt;, so I decided to have a look at the tutorial and try to follow it using &lt;code&gt;Rust&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;But of course, I want to read and follow the original tutorial first, trying to pair it with modern concepts and &lt;code&gt;Rust&lt;/code&gt; along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cross-Compilation
&lt;/h2&gt;

&lt;p&gt;The first step that the tutorial mentions is cross-compiling, and it talks about the setup of a &lt;code&gt;GCC cross-compiler&lt;/code&gt; for &lt;code&gt;i686-elf&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;i686-elf&lt;/code&gt; is a classic target designed for developing 32-bit (x86) operating systems. The &lt;code&gt;-elf&lt;/code&gt; target produces bare binaries with no OS assumptions for bare metal—exactly what we want for kernel development.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  What Is a Cross-Compiler?
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: A &lt;strong&gt;cross-compiler&lt;/strong&gt; produces code for a different platform than the one it runs on (e.g., compiling ARM code on an x86 machine).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A &lt;strong&gt;native compiler&lt;/strong&gt; runs on platform Y and produces binaries for platform Y. A &lt;strong&gt;cross-compiler&lt;/strong&gt; runs on platform X but produces binaries for platform Y.&lt;/p&gt;

&lt;p&gt;As I already mentioned, I'm not a &lt;code&gt;C&lt;/code&gt; developer—never used &lt;code&gt;C&lt;/code&gt; more than for ultra simple basic hello worlds or some lecture. So I didn't know how this process works in &lt;code&gt;C&lt;/code&gt;. I have more experience with Go and some experience with &lt;code&gt;Rust&lt;/code&gt;, where cross-compilation is a native feature offered out of the box.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Cross-Compilers Are Necessary
&lt;/h3&gt;

&lt;p&gt;The compiler must know the correct target platform (CPU, operating system). The compiler that comes with the host system does not know by default that it is compiling something else entirely. In our case, the host platform is our current operating system and the target platform is the operating system we are about to make. It is important to realize that these two platforms are not the same; the operating system we are developing is always going to be different from the operating system we currently use.&lt;/p&gt;

&lt;p&gt;As you read before, the guide mentions that we are going to use &lt;code&gt;i686-elf&lt;/code&gt;, designed to build &lt;code&gt;32-bit&lt;/code&gt; (i686) executable binaries that run on bare metal, without an underlying operating system. In my case, I have access to an ARM M1 Max as my main machine or a Lima VM running Ubuntu x86_64.&lt;/p&gt;

&lt;p&gt;The tutorial mentions &lt;code&gt;i686-elf&lt;/code&gt; which is 32-bit, because we will &lt;em&gt;not&lt;/em&gt; be able to correctly complete the tutorial with an x86_64-elf cross-compiler, as GRUB 1 "legacy" is only able to load 32-bit multiboot kernels.&lt;/p&gt;

&lt;p&gt;So, we will &lt;em&gt;not&lt;/em&gt; be able to correctly compile the operating system without a cross-compiler.&lt;/p&gt;

&lt;h2&gt;
  
  
  Freestanding and Hosted Environments
&lt;/h2&gt;

&lt;p&gt;As the guide mentions, to write an operating system kernel we need code that does not depend on any operating system features. This makes sense since the whole point of the guide is to create our own OS.&lt;/p&gt;

&lt;p&gt;Let's look at the two execution environments:&lt;/p&gt;

&lt;h3&gt;
  
  
  Hosted Environment
&lt;/h3&gt;

&lt;p&gt;This is when we are writing a program that runs on top of an existing &lt;strong&gt;Operating System&lt;/strong&gt; (Linux, macOS).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Contract:&lt;/strong&gt; The OS provides a &lt;strong&gt;managed environment&lt;/strong&gt;. It sets up the stack, clears memory, and handles hardware I/O.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Toolbox:&lt;/strong&gt; You have the &lt;strong&gt;Full Standard Library&lt;/strong&gt;. You can call &lt;code&gt;printf&lt;/code&gt; or &lt;code&gt;malloc&lt;/code&gt; because the OS provides the "plumbing" (drivers and memory managers) to make them work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety:&lt;/strong&gt; If your code crashes, the OS catches it and kills the process. The rest of the computer keeps running.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Target:&lt;/strong&gt; 99% of software (apps, web servers, CLI tools).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Freestanding Environment
&lt;/h3&gt;

&lt;p&gt;This is when we are writing code for &lt;strong&gt;Bare Metal&lt;/strong&gt; (a CPU with no OS).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Contract:&lt;/strong&gt; There is no help. You must manually define the &lt;strong&gt;Entry Point&lt;/strong&gt;  and tell the CPU how to use its own RAM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Toolbox:&lt;/strong&gt; You only have &lt;strong&gt;Core Language Primitives&lt;/strong&gt;. No &lt;code&gt;printf&lt;/code&gt;, no &lt;code&gt;malloc&lt;/code&gt;, no file system, no network. You only get basic types (integers, pointers) and math or core language features.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety:&lt;/strong&gt; If your code crashes, the CPU triggers a "Triple Fault" and the physical machine reboots. There is no "safety net."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Target:&lt;/strong&gt; The kernel itself, bootloaders, and embedded firmware.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Recap
&lt;/h3&gt;

&lt;p&gt;So basically, a &lt;strong&gt;cross-compiler&lt;/strong&gt; produces code for a different platform than the one it runs on, and a &lt;strong&gt;freestanding environment&lt;/strong&gt; is one where no OS or standard library exists just our code and the hardware. These two concepts go hand-in-hand: when writing an OS kernel or bare metal firmware, we have to cross-compile for our target architecture in freestanding mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Zig&lt;/strong&gt; to the Rescue?
&lt;/h2&gt;

&lt;p&gt;The guide has a link to &lt;a href="https://wiki.osdev.org/GCC_Cross-Compiler" rel="noopener noreferrer"&gt;GCC Cross-Compiler&lt;/a&gt; explaining how to set up the required compiler, which I found a bit complex and tedious. I remembered hearing a lot of good things about the &lt;code&gt;Zig&lt;/code&gt; compiler and its flexibility, so I thought I could just use &lt;code&gt;Zig&lt;/code&gt; as the compiler.&lt;/p&gt;

&lt;p&gt;The OSDev tutorial provides the following &lt;code&gt;C&lt;/code&gt; code for the &lt;code&gt;kernel.c&lt;/code&gt; file. Here's a brief walkthrough of what it does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;#if defined&lt;/code&gt; checks at the top are safeguards that prevent you from compiling with the wrong compiler—they ensure you're using a cross-compiler targeting i386.&lt;/li&gt;
&lt;li&gt;It defines a &lt;code&gt;vga_color&lt;/code&gt; enum and helper functions to create VGA text-mode entries (each character on screen is a 16-bit value: the character byte + a color byte).&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;terminal_*&lt;/code&gt; functions manage a simple text terminal by writing directly to VGA memory at &lt;code&gt;0xB8000&lt;/code&gt;—this is the physical address where the VGA text buffer lives in x86 systems.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kernel_main&lt;/code&gt; is our entry point: it initializes the terminal and prints "Hello, kernel World!".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's look at the full code and then jump to the cross-compilation part:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdbool.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stddef.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdint.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="cm"&gt;/* Check if the compiler thinks you are targeting the wrong operating system. */&lt;/span&gt;
&lt;span class="cp"&gt;#if defined(__linux__)
#error "You are not using a cross-compiler, you will most certainly run into trouble"
#endif
&lt;/span&gt;
&lt;span class="cm"&gt;/* This tutorial will only work for the 32-bit ix86 targets. */&lt;/span&gt;
&lt;span class="cp"&gt;#if !defined(__i386__)
#error "This tutorial needs to be compiled with a ix86-elf compiler"
#endif
&lt;/span&gt;
&lt;span class="cm"&gt;/* Hardware text mode color constants. */&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;vga_color&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;VGA_COLOR_BLACK&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="n"&gt;VGA_COLOR_BLUE&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;VGA_COLOR_GREEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;VGA_COLOR_CYAN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;VGA_COLOR_RED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;VGA_COLOR_MAGENTA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;VGA_COLOR_BROWN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;VGA_COLOR_LIGHT_GREY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;VGA_COLOR_DARK_GREY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;VGA_COLOR_LIGHT_BLUE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;VGA_COLOR_LIGHT_GREEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;VGA_COLOR_LIGHT_CYAN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;VGA_COLOR_LIGHT_RED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;VGA_COLOR_LIGHT_MAGENTA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;VGA_COLOR_LIGHT_BROWN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;VGA_COLOR_WHITE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="nf"&gt;vga_entry_color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;vga_color&lt;/span&gt; &lt;span class="n"&gt;fg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;vga_color&lt;/span&gt; &lt;span class="n"&gt;bg&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="n"&gt;fg&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;bg&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="nf"&gt;vga_entry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;uc&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;color&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="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint16_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;uc&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint16_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="nf"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;len&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;str&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="o"&gt;++&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;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cp"&gt;#define VGA_WIDTH   80
#define VGA_HEIGHT  25
#define VGA_MEMORY  0xB8000
&lt;/span&gt;
&lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;terminal_row&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;terminal_column&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;terminal_color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;uint16_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;terminal_buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint16_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;VGA_MEMORY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;terminal_initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;terminal_row&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="n"&gt;terminal_column&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="n"&gt;terminal_color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vga_entry_color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VGA_COLOR_LIGHT_GREY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VGA_COLOR_BLACK&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="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;y&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="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;VGA_HEIGHT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&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="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;x&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="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;VGA_WIDTH&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;VGA_WIDTH&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;terminal_buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vga_entry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;terminal_color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;terminal_setcolor&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;color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;terminal_color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;terminal_putentryat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&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;color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;VGA_WIDTH&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;terminal_buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vga_entry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;terminal_putchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;terminal_putentryat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;terminal_color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;terminal_column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;terminal_row&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="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;terminal_column&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;VGA_WIDTH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;terminal_column&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;terminal_row&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;VGA_HEIGHT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;terminal_row&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;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;terminal_write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&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="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;i&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="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;terminal_putchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;terminal_writestring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;terminal_write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;kernel_main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* Initialize terminal interface */&lt;/span&gt;
    &lt;span class="n"&gt;terminal_initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="cm"&gt;/* Newline support is left as an exercise. */&lt;/span&gt;
    &lt;span class="n"&gt;terminal_writestring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, kernel World!&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As was previously mentioned, if we try to compile this code with a regular &lt;code&gt;gcc&lt;/code&gt; on my Lima Ubuntu VM, you will see the safeguards in the code acting up:&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="nv"&gt;$ &lt;/span&gt;gcc &lt;span class="nt"&gt;-c&lt;/span&gt; kernel.c &lt;span class="nt"&gt;-o&lt;/span&gt; hosted_kernel.o
kernel.c:7:2: error: &lt;span class="c"&gt;#error "You are not using a cross-compiler, you will most certainly run into trouble"&lt;/span&gt;
    7 | &lt;span class="c"&gt;#error "You are not using a cross-compiler, you will most certainly run into trouble"&lt;/span&gt;
      |  ^~~~~
kernel.c:12:2: error: &lt;span class="c"&gt;#error "This tutorial needs to be compiled with a ix86-elf compiler"&lt;/span&gt;
   12 | &lt;span class="c"&gt;#error "This tutorial needs to be compiled with a ix86-elf compiler"&lt;/span&gt;
      |  ^~~~~
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if we use &lt;code&gt;Zig&lt;/code&gt; and its build magic, we get the output successfully and we can inspect the file:&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="nv"&gt;$ &lt;/span&gt;zig cc &lt;span class="nt"&gt;-target&lt;/span&gt; x86-freestanding-none &lt;span class="nt"&gt;-c&lt;/span&gt; kernel.c &lt;span class="nt"&gt;-o&lt;/span&gt; kernel.o
&lt;span class="nv"&gt;$ &lt;/span&gt;readelf &lt;span class="nt"&gt;-h&lt;/span&gt; kernel.o
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2&lt;span class="s1"&gt;'s complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          7164 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           40 (bytes)
  Number of section headers:         22
  Section header string table index: 20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that the class is &lt;code&gt;ELF32&lt;/code&gt; (32-bit) and the &lt;strong&gt;OS/ABI&lt;/strong&gt; is &lt;code&gt;UNIX - System V&lt;/code&gt;. If it said &lt;code&gt;Linux&lt;/code&gt;, it would &lt;strong&gt;not&lt;/strong&gt; be freestanding; it would have been built with Linux-specific assumptions.&lt;/p&gt;

&lt;p&gt;We could also inspect the symbol table, and we should not see &lt;code&gt;_start&lt;/code&gt;:&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="nv"&gt;$ &lt;/span&gt;nm kernel.o
         U __ubsan_handle_pointer_overflow
         U __ubsan_handle_shift_out_of_bounds
         U __ubsan_handle_type_mismatch_v1
000004f0 T kernel_main
00000000 T strlen
00000024 D terminal_buffer
00000008 B terminal_color
00000004 B terminal_column
000000a0 T terminal_initialize
00000390 T terminal_putchar
000002b0 T terminal_putentryat
00000000 B terminal_row
000002a0 T terminal_setcolor
00000410 T terminal_write
000004c0 T terminal_writestring
00000230 t vga_entry
000001e0 t vga_entry_color
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So great, we managed to cross-compile our &lt;code&gt;kernel.c&lt;/code&gt; for a different architecture in freestanding mode using &lt;code&gt;Zig&lt;/code&gt;. But as I mentioned at the beginning of the article, I want to do the same using &lt;code&gt;Rust&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Rust&lt;/strong&gt; in Action
&lt;/h2&gt;

&lt;p&gt;Beyond my personal goal of learning &lt;code&gt;Rust&lt;/code&gt;, it's actually an ideal candidate for OS development: it gives you the same low-level control as &lt;code&gt;C&lt;/code&gt; but with memory safety guarantees at compile time, no garbage collector, and first-class &lt;code&gt;no_std&lt;/code&gt; support designed exactly for bare-metal targets.&lt;/p&gt;

&lt;p&gt;Let's create a new project:&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="nv"&gt;$ &lt;/span&gt;cargo new osdev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A small disclaimer: &lt;code&gt;Rust&lt;/code&gt; by default offers &lt;code&gt;x86_64-unknown-none&lt;/code&gt;, which means 64-bit instead of the 32-bit target used in the tutorial. We could use nightly and a &lt;a href="https://doc.rust-lang.org/beta/nightly-rustc/rustc_target/spec/index.html" rel="noopener noreferrer"&gt;custom target spec&lt;/a&gt; to specify 32-bit, but for simplicity and because I want to try following along using 64-bit later! we are going to use &lt;code&gt;x86_64-unknown-none&lt;/code&gt;.&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="nv"&gt;$ &lt;/span&gt;rustup target add x86_64-unknown-none
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, both &lt;strong&gt;&lt;code&gt;Zig&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;Rust&lt;/code&gt;&lt;/strong&gt; leverage the &lt;strong&gt;Target Triple&lt;/strong&gt; convention for specifying targets:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Target Component&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;x86-freestanding-none (Zig)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;x86_64-unknown-none (Rust)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Definition&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Architecture&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;x86&lt;/code&gt; (32)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;x86_64&lt;/code&gt; (64)&lt;/td&gt;
&lt;td&gt;The CPU instruction set (32-bit vs. 64-bit).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Vendor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;freestanding&lt;/code&gt;*&lt;/td&gt;
&lt;td&gt;&lt;code&gt;unknown&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Historically the hardware maker. In OS dev, this is a "don't care" field.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;none&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;none&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Tells the compiler there is no OS (no Linux/macOS).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As you may know, when you create a fresh &lt;code&gt;Rust&lt;/code&gt; project it comes with its hello world version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world!"&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;If we try to compile using the target we previously installed (&lt;code&gt;x86_64-unknown-none&lt;/code&gt;), we get the following error:&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="nv"&gt;$ &lt;/span&gt;cargo build &lt;span class="nt"&gt;--target&lt;/span&gt; x86_64-unknown-none
   Compiling osdev v0.1.0 &lt;span class="o"&gt;(&lt;/span&gt;/Users/douglasmakey/workdir/personal/os-barebones/osdev&lt;span class="o"&gt;)&lt;/span&gt;
error[E0463]: can&lt;span class="s1"&gt;'t find crate for `std`
  |
  = note: the `x86_64-unknown-none` target may not support the standard library
  = note: `std` is required by `osdev` because it does not declare `#![no_std]`

error: cannot resolve a prelude import

error: cannot find macro `println` in this scope
 --&amp;gt; src/main.rs:2:5
  |
2 |     println!("Hello, world!");
  |     ^^^^^^^

error: `#[panic_handler]` function required, but not found

For more information about this error, try `rustc --explain E0463`.
error: could not compile `osdev` (bin "osdev") due to 4 previous errors
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This happens because our current build implicitly links the standard library. Since we specified a freestanding target (meaning no OS context, just core primitives), &lt;code&gt;Rust&lt;/code&gt; can't find &lt;code&gt;std&lt;/code&gt;. &lt;code&gt;Rust&lt;/code&gt; has support for this scenario using &lt;code&gt;#![no_std]&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#![no_std]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world!"&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;But if we try to compile this, we get another error:&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="nv"&gt;$ &lt;/span&gt;cargo build &lt;span class="nt"&gt;--target&lt;/span&gt; x86_64-unknown-none
   Compiling osdev v0.1.0 &lt;span class="o"&gt;(&lt;/span&gt;/Users/douglasmakey/workdir/personal/os-barebones/osdev&lt;span class="o"&gt;)&lt;/span&gt;
error: cannot find macro &lt;span class="sb"&gt;`&lt;/span&gt;println&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;this scope
 &lt;span class="nt"&gt;--&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; src/main.rs:3:5
  |
3 |     println!&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  |     ^^^^^^^

error: &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;#[panic_handler]` function required, but not found&lt;/span&gt;

error: could not compile &lt;span class="sb"&gt;`&lt;/span&gt;osdev&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;bin &lt;span class="s2"&gt;"osdev"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; due to 2 previous errors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is that &lt;code&gt;#![no_std]&lt;/code&gt; tells the &lt;code&gt;Rust&lt;/code&gt; compiler not to link against the standard library. Instead, it links against the &lt;code&gt;core&lt;/code&gt; library, which only provides core primitives. This means macros like &lt;code&gt;println!&lt;/code&gt; are gone. We are essentially disabling all OS dependent functionality. The other error is about the &lt;code&gt;panic_handler&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Panic Handler
&lt;/h3&gt;

&lt;p&gt;When a &lt;code&gt;Rust&lt;/code&gt; program encounters an unrecoverable error, it "panics." In a regular &lt;code&gt;std&lt;/code&gt; environment, this typically prints a backtrace and the OS catches it. In &lt;code&gt;no_std&lt;/code&gt;, you must define your own panic handler, as there's no OS to catch the panic. There is no "safety net."&lt;/p&gt;

&lt;p&gt;So to make this work, we need to address a few things: add the panic handler, drop &lt;code&gt;println!&lt;/code&gt;, and also tell the compiler that we don't have a normal &lt;code&gt;main&lt;/code&gt; entry point. In a freestanding environment there's no runtime that calls &lt;code&gt;main&lt;/code&gt; for us, so we use &lt;code&gt;#![no_main]&lt;/code&gt; to disable that expectation and define our own entry point &lt;code&gt;_start&lt;/code&gt; instead. The &lt;code&gt;#[unsafe(no_mangle)]&lt;/code&gt; attribute ensures the function name isn't changed by the compiler, so the linker can find it. The &lt;code&gt;-&amp;gt; !&lt;/code&gt; return type means the function never returns—which makes sense because there's no OS to return to, so we just loop forever.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#![no_std]&lt;/span&gt;
&lt;span class="nd"&gt;#![no_main]&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;PanicInfo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[unsafe(no_mangle)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;_start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[panic_handler]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;panic&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;PanicInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;loop&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;blockquote&gt;
&lt;p&gt;If you want to deep dive on &lt;code&gt;no_std&lt;/code&gt;, I found this article useful: &lt;a href="https://leapcell.io/blog/rust-without-the-standard-library-a-deep-dive-into-no-std-development" rel="noopener noreferrer"&gt;Rust Without the Standard Library: A Deep Dive into no_std Development&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And now if we compile again, this time it will succeed:&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="nv"&gt;$ &lt;/span&gt;readelf &lt;span class="nt"&gt;-h&lt;/span&gt; target/x86_64-unknown-none/debug/osdev
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2&lt;span class="s1"&gt;'s complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x1280
  Start of program headers:          64 (bytes into file)
  Start of section headers:          4216 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         8
  Size of section headers:           64 (bytes)
  Number of section headers:         21
  Section header string table index: 19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can notice, the header has similarities with our &lt;code&gt;kernel.c&lt;/code&gt; compiled with &lt;code&gt;Zig&lt;/code&gt;, of course with the difference of &lt;code&gt;ELF64&lt;/code&gt; (64-bit) and for the same reason the machine shows as AMD X86-64.&lt;/p&gt;

&lt;p&gt;We could also inspect the symbol table, this time, we’ll notice the presence of &lt;code&gt;_start&lt;/code&gt;. That’s because &lt;code&gt;cargo build&lt;/code&gt; automatically invokes the linker (LLD) when it detects a &lt;code&gt;pub fn _start&lt;/code&gt; in our code. By default, the linker looks for that symbol and exports it as the program’s entry point.&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="nv"&gt;$ &lt;/span&gt;nm target /x86_64-unknown-none/debug/osdev
0000000000002288 d _DYNAMIC
0000000000001280 T _start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I will leave this first article at this point. I hope you find it as interesting as I did. I will continue the series hopefully as soon as possible. I'll be working on the OS at the same time I write the articles, so a couple of things might change or I might make mistakes that I'll fix later on.&lt;/p&gt;

&lt;p&gt;In the next post, we'll cover implementing the bootloader and get our kernel running in QEMU—either by following the OSDev guide step by step or by using the &lt;code&gt;Rust&lt;/code&gt; bootloader crate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Lima Setup for Mac Users
&lt;/h2&gt;

&lt;p&gt;In case you want to play around with this on a Mac, I'm using &lt;a href="https://lima-vm.io/" rel="noopener noreferrer"&gt;Lima&lt;/a&gt; to run an x86_64 Ubuntu VM. Here's my current Lima configuration with &lt;code&gt;Zig&lt;/code&gt;, &lt;code&gt;Rust&lt;/code&gt;, and the build essentials pre-installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;vmType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;qemu"&lt;/span&gt;
&lt;span class="na"&gt;arch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x86_64"&lt;/span&gt;

&lt;span class="na"&gt;images&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://cloud-images.ubuntu.com/releases/24.04/release/ubuntu-24.04-server-cloudimg-amd64.img"&lt;/span&gt;
  &lt;span class="na"&gt;arch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x86_64"&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-amd64.img"&lt;/span&gt;
  &lt;span class="na"&gt;arch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x86_64"&lt;/span&gt;

&lt;span class="na"&gt;mounts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;path-to-your-repo"&lt;/span&gt;
  &lt;span class="na"&gt;writable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;provision&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;system&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;DEBIAN_FRONTEND=noninteractive apt-get update&lt;/span&gt;
    &lt;span class="s"&gt;DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential gdb qemu-system-x86 nasm xorriso mtools&lt;/span&gt;
    &lt;span class="s"&gt;snap install zig --beta --classic&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y&lt;/span&gt;
    &lt;span class="s"&gt;source "$HOME/.cargo/env"&lt;/span&gt;
    &lt;span class="s"&gt;rustup default stable&lt;/span&gt;
    &lt;span class="s"&gt;rustup component add rust-src llvm-tools-preview&lt;/span&gt;

&lt;span class="na"&gt;cpus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;
&lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4GiB"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can start the VM with:&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="nv"&gt;$ &lt;/span&gt;limactl start &lt;span class="nt"&gt;--name&lt;/span&gt; osdev osdev.yaml
&lt;span class="nv"&gt;$ &lt;/span&gt;limactl shell osdev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks for reading, and as always, feedback is welcome. &lt;strong&gt;Happy coding!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>zig</category>
      <category>c</category>
      <category>linux</category>
    </item>
    <item>
      <title>Playing with Rust: Building a Safer rm and Having Fun Along the Way</title>
      <dc:creator>Douglas Makey Mendez Molero</dc:creator>
      <pubDate>Sun, 20 Oct 2024 16:39:10 +0000</pubDate>
      <link>https://forem.com/douglasmakey/playing-with-rust-building-a-safer-rm-and-having-fun-along-the-way-55m6</link>
      <guid>https://forem.com/douglasmakey/playing-with-rust-building-a-safer-rm-and-having-fun-along-the-way-55m6</guid>
      <description>&lt;p&gt;Welcome to my &lt;strong&gt;YOLO&lt;/strong&gt; series, where I'll be showcasing simple tools and projects that I've built—sometimes for fun, sometimes to solve specific problems, and other times just out of pure curiosity. The goal here isn't just to present a tool; I'll also dive into something interesting related to the process, whether it's a technical insight or a lesson learned while crafting these little experiments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing rrm: The Command-Line Tool Nobody Asked For
&lt;/h2&gt;

&lt;p&gt;Nobody asked for it, and nobody want it—but here it is anyway. Meet &lt;a href="https://github.com/douglasmakey/rrm" rel="noopener noreferrer"&gt;rrm&lt;/a&gt;, a tool that solves a problem only I seem to have (but hey, it might be a Layer 8 issue—or, more likely, a skill issue!).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rrm&lt;/code&gt; adds a layer of safety to your command-line experience by moving files to a trash bin instead of permanently deleting them. With a customizable grace period, you get the chance to realize, &lt;strong&gt;"Oops, I actually needed that!"&lt;/strong&gt; before it’s too late.&lt;/p&gt;

&lt;p&gt;What’s more, &lt;code&gt;rrm&lt;/code&gt; doesn’t rely on external configuration files or tracking systems to manage deleted files. Instead, it leverages your filesystem’s &lt;strong&gt;extended attributes&lt;/strong&gt; to store essential metadata—like the original file path and deletion time—directly within the trashed item.&lt;/p&gt;

&lt;p&gt;You might be wondering, &lt;strong&gt;"Why am I building this tool when there are similar, possibly better tools out there?"&lt;/strong&gt; Well, the answer is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;I wanted to play with Rust.&lt;/strong&gt; Building small, purposeful tools is a great way to explore a language and sharpen skills.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;like developing my own CLI tools as a way to create a mental framework.&lt;/strong&gt; It helps me consistently approach how I structure command-line utilities for specific technologies. By building these tools, I refine my understanding of what dependencies to use, how to organize the code, and how to adapt each tool to the language’s ecosystem. It’s a way of building a mental playbook for creating CLI tools that suit my needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Because YOLO.&lt;/strong&gt; I enjoy making simple tools or proof-of-concepts around problems I want to solve or things I’m curious about. Sometimes, it’s about experimenting for the sake of learning.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1844834987184410735-190" src="https://platform.twitter.com/embed/Tweet.html?id=1844834987184410735"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1844834987184410735-190');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1844834987184410735&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fun note:&lt;/strong&gt; While working with &lt;code&gt;std::Path&lt;/code&gt;, I found an example in the Rust standard library that uses a folder named &lt;strong&gt;laputa&lt;/strong&gt;. I know it's a reference to Castle in the Sky, but for Spanish speakers, it’s also a curse word, which made it a funny moment for me!&lt;/p&gt;

&lt;h2&gt;
  
  
  Extended Attributes: Storing Metadata Without Changing the File
&lt;/h2&gt;

&lt;p&gt;When I started building &lt;code&gt;rrm&lt;/code&gt;, I needed a way to track the original path of deleted files and the time when they should be permanently removed. I didn’t want to use a &lt;code&gt;JSON&lt;/code&gt; file or implement a weird naming format that includes this information—especially if I wanted to store more data later. A database felt like overkill for such a small task.&lt;/p&gt;

&lt;p&gt;That’s when I discovered &lt;strong&gt;extended attributes&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Are Extended Attributes?
&lt;/h3&gt;

&lt;p&gt;Now, I don’t know about you, but I didn’t realize there was a built-in mechanism that lets you add custom metadata to files, which is supported by most Linux filesystems and Unix-like systems such as macOS. This feature is called &lt;a href="http://en.wikipedia.org/wiki/Extended_file_attributes" rel="noopener noreferrer"&gt;Extended File Attributes&lt;/a&gt;. Different systems have their own limitations—like how much data can be added or the specific namespaces used—but they &lt;strong&gt;do&lt;/strong&gt; allow you to store user-defined metadata.&lt;/p&gt;

&lt;p&gt;Extended attributes are essentially &lt;code&gt;name:value&lt;/code&gt; pairs that are permanently associated with files and directories. As I mentioned earlier, systems differ in how they handle this. For example, in Linux, the name starts with a namespace identifier. There are four such namespaces: &lt;code&gt;security&lt;/code&gt;, &lt;code&gt;system&lt;/code&gt;, &lt;code&gt;trusted&lt;/code&gt;, and &lt;code&gt;user&lt;/code&gt;. In Linux, the name starts with one of these, followed by a dot (".") and then a null-terminated string. On macOS, things are a bit different. macOS doesn't require namespaces at all, thanks to its &lt;strong&gt;Unified Metadata Approach&lt;/strong&gt;, which treats extended attributes as additional metadata directly tied to files without needing to be categorized.&lt;/p&gt;

&lt;p&gt;In this tiny CLI, I’m using the crate &lt;a href="https://crates.io/crates/xattr" rel="noopener noreferrer"&gt;xattr&lt;/a&gt;, which supports both Linux and macOS. Regarding the namespaces I mentioned earlier for Linux, we'll be focusing on the &lt;code&gt;user&lt;/code&gt; namespace since these attributes are meant to be used by the user. So, in the code, you’ll see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="cd"&gt;/// Namespace for extended attributes (xattrs) on macOS and other operating systems.&lt;/span&gt;
&lt;span class="cd"&gt;/// On macOS, this is an empty string, while on other operating systems, it is "user.".&lt;/span&gt;
&lt;span class="nd"&gt;#[cfg(target_os&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"macos"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;XATTR_NAMESPACE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nd"&gt;#[cfg(not(target_os&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"macos"&lt;/span&gt;&lt;span class="nd"&gt;))]&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;XATTR_NAMESPACE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"user."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;set_attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&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;Path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;attr_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;XATTR_NAMESPACE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attr&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;#[cfg(target_os = "macos")]&lt;/code&gt; attribute in Rust is used to conditionally compile code based on the target operating system. In this case, it ensures that the code block is only included when compiling for macOS. This is relevant because, as mentioned earlier, macOS doesn’t require a namespace for extended attributes, so the &lt;code&gt;XATTR_NAMESPACE&lt;/code&gt; is set to an empty string. For other operating systems, the namespace is set to &lt;code&gt;"user."&lt;/code&gt;. This conditional compilation allows the code to adapt seamlessly across different platforms, making the CLI cross-compatible with both Linux and macOS.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One thing I found pretty cool about extended attributes is that they don’t modify the file itself. The metadata lives in a separate disk space, referenced by the &lt;code&gt;inode&lt;/code&gt;. This means the file's actual contents remain unchanged. For example, if we create a simple file and use &lt;code&gt;shasum&lt;/code&gt; to get its checksum:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The inode (index node) is &lt;strong&gt;a data structure in a Unix-style file system that describes a file-system object such as a file or a directory&lt;/strong&gt;. &lt;a href="https://en.wikipedia.org/wiki/Inode#:~:text=The%20inode%20(index%20node)%20is,locations%20of%20the%20object's%20data." rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;a.txt
https://www.kungfudev.com/

&lt;span class="nv"&gt;$ &lt;/span&gt;shasum a.txt
e4c51607d5e7494143ffa5a20b73aedd4bc5ceb5  a.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After using &lt;code&gt;rrm&lt;/code&gt; to delete the file, we can list the deleted files and see that the file has been moved to the trash bin with its metadata intact:&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="nv"&gt;$ &lt;/span&gt;rrm &lt;span class="nb"&gt;rm &lt;/span&gt;a.txt

&lt;span class="nv"&gt;$ &lt;/span&gt;rrm list
╭──────────────────────────────────────────────────────┬──────────────────────────────────────┬──────┬─────────────────────╮
│ Original Path                                        ┆ ID                                   ┆ Kind ┆ Deletion Date       │
╞══════════════════════════════════════════════════════╪══════════════════════════════════════╪══════╪═════════════════════╡
│ /Users/douglasmakey/workdir/personal/kungfudev/a.txt ┆ 3f566788-75dc-4674-b069-0faeaa86aa55 ┆ File ┆ 2024-10-27 04:10:19 │
╰──────────────────────────────────────────────────────┴──────────────────────────────────────┴──────┴─────────────────────╯
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;As you can see, the file name is changed to a UUID. This is done to avoid name collisions when deleting files with the same name. By assigning a unique identifier to each file, &lt;code&gt;rrm&lt;/code&gt; ensures that every deleted file, even if they have identical names, can be tracked and recovered without any issues.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can navigate to the trash folder and inspect the file to confirm that its contents remain unchanged:&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="nv"&gt;$ &lt;/span&gt;shasum 3f566788-75dc-4674-b069-0faeaa86aa55
e4c51607d5e7494143ffa5a20b73aedd4bc5ceb5  3f566788-75dc-4674-b069-0faeaa86aa55
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, by using &lt;code&gt;xattr&lt;/code&gt; on macOS, we can verify that the file has its metadata, such as the deletion date and original path:&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="nv"&gt;$ &lt;/span&gt;xattr &lt;span class="nt"&gt;-l&lt;/span&gt; 3f566788-75dc-4674-b069-0faeaa86aa55
deletion_date: 2024-10-27T04:10:19.875614+00:00
original_path: /Users/douglasmakey/workdir/personal/kungfudev/a.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can imagine the range of potential use cases for simple validations or actions using this metadata. Since extended attributes work without modifying the file itself, they allow you to check file integrity or perform other operations without affecting the original content.&lt;/p&gt;

&lt;p&gt;This is just a small introduction to extended attributes and how they’re used in this project. It’s not meant to be an in-depth explanation, but if you’re interested in learning more, there are plenty of detailed resources out there. Here are a couple of links to the most useful and well-described resources on the topic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wiki.archlinux.org/title/Extended_attributes" rel="noopener noreferrer"&gt;https://wiki.archlinux.org/title/Extended_attributes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://man7.org/linux/man-pages/man7/xattr.7.html" rel="noopener noreferrer"&gt;https://man7.org/linux/man-pages/man7/xattr.7.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Extended_file_attributes" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Extended_file_attributes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Mocking in Rust: Exploring &lt;code&gt;mockall&lt;/code&gt; for Testing
&lt;/h2&gt;

&lt;p&gt;I’ve spent a few years working with &lt;code&gt;Go&lt;/code&gt;, and I’ve become fond of certain patterns—mocking being one of them. In Go, I typically implement things myself if it avoids unnecessary imports or gives me more flexibility. I’m so used to this approach that when I started writing tests in &lt;code&gt;Rust&lt;/code&gt;, I found myself preferring to manually mock certain things, like creating mock implementations of traits.&lt;/p&gt;

&lt;p&gt;For example, in this tiny CLI, I created a trait to decouple the trash manager from the way it interacts with the extended attributes. The trait, named &lt;code&gt;ExtendedAttributes&lt;/code&gt;, was initially intended for testing purposes, but also because I wasn’t sure whether I would use &lt;code&gt;xattr&lt;/code&gt; or another implementation. So, I defined the following trait:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;ExtendedAttributes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;set_attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&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;Path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&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;Path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;remove_attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&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;Path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;In Go, I would create something like the following, which provides a simple implementation of the previously mentioned interface. The code below is straightforward and generated without much consideration, just for the sake of example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// ExtendedAttributes allows for passing specific behavior via function fields&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ExtendedAttributes&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;SetAttrFunc&lt;/span&gt;    &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;
    &lt;span class="n"&gt;GetAttrFunc&lt;/span&gt;    &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;RemoveAttrFunc&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// SetAttr calls the injected behavior&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ExtendedAttributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SetAttr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&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;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetAttrFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// GetAttr calls the injected behavior&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ExtendedAttributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetAttr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&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="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetAttrFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// RemoveAttr calls the injected behavior&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ExtendedAttributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;RemoveAttr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&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;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemoveAttrFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&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;Then, I would use &lt;code&gt;my mock&lt;/code&gt; and inject the specific behavior needed for each test. Again, this is simple code just for the sake of the example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;TestSetAttrWithMock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;mock&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ExtendedAttributes&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;SetAttrFunc&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"/invalid/path"&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;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"invalid path"&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="no"&gt;nil&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetAttr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/invalid/path"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"expected error, got nil"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetAttr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/valid/path"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"expected no error, got %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&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;I've gotten used to this pattern in Go, and I plan to keep using it. But I’ve also been doing something similar in Rust. For this project, I decided to try the &lt;code&gt;mockall&lt;/code&gt; crate, and I found it really useful.&lt;/p&gt;

&lt;p&gt;First, I used the &lt;code&gt;mock!&lt;/code&gt; macro to manually mock my structure. I know &lt;code&gt;mockall&lt;/code&gt; has an &lt;code&gt;automock&lt;/code&gt; feature, but I prefer to define the mock struct directly in my tests where it will be used. &lt;em&gt;Let me know if this is something common or if the community has a different standard for this.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="nd"&gt;mock!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;XattrManager&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;ExtendedAttributes&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;XattrManager&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;set_attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;path&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;path&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;remove_attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;path&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&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;I found &lt;code&gt;mockall&lt;/code&gt; really useful, allowing me to inject specific behaviors into my tests without the verbosity of my old pattern.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="nd"&gt;#[test]&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;test_trash_items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&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;...&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;xattr_manager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;MockXattrManager&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;xattr_manager&lt;/span&gt;
            &lt;span class="nf"&gt;.expect_set_attr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nf"&gt;in_iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;original_path&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;original_path2&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()]),&lt;/span&gt;
                &lt;span class="nf"&gt;in_iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ORIGINAL_PATH_ATTR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DELETION_DATE_ATTR&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
                &lt;span class="nf"&gt;in_iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                    &lt;span class="n"&gt;original_path_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;original_path2_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;deletion_date&lt;/span&gt;&lt;span class="nf"&gt;.to_rfc3339&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="p"&gt;]),&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.times&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.returning&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nf"&gt;Ok&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="nd"&gt;#[test]&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;clean_trash_delete_old_file&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
        &lt;span class="n"&gt;xattr_manager&lt;/span&gt;
            &lt;span class="nf"&gt;.expect_get_attr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.times&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.returning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;DELETION_DATE_ATTR&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deletion_date_past&lt;/span&gt;&lt;span class="nf"&gt;.to_rfc3339&lt;/span&gt;&lt;span class="p"&gt;())),&lt;/span&gt;
                &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"some_path"&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;())),&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see, &lt;code&gt;mockall&lt;/code&gt; gives us the capability to define specific behaviors for our tests using its mock methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;MockXattrManager::new()&lt;/code&gt;&lt;/strong&gt;
This creates a new instance of the mock object &lt;code&gt;MockXattrManager&lt;/code&gt;, which is used to mock the behavior of &lt;code&gt;XattrManager&lt;/code&gt; for testing.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;xattr_manager.expect_set_attr()&lt;/code&gt;&lt;/strong&gt;
This sets up an expectation that the &lt;code&gt;set_attr&lt;/code&gt; method will be called during the test. You define the expected behavior of this method next.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;with(...)&lt;/code&gt;&lt;/strong&gt;
The &lt;code&gt;with&lt;/code&gt; method specifies the expected arguments when &lt;code&gt;set_attr&lt;/code&gt; is called. In this case, it’s expecting three arguments and uses &lt;code&gt;in_iter&lt;/code&gt; to indicate that each argument should match one of the values in the provided vector. This allows flexibility in the test, as it checks if the arguments are one of the values from the passed vector rather than a single exact match.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;times(4)&lt;/code&gt;&lt;/strong&gt;
This specifies that the &lt;code&gt;set_attr&lt;/code&gt; method is expected to be called exactly four times during the test.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;returning(|_, _, _| Ok(()))&lt;/code&gt;&lt;/strong&gt;
This tells the mock what to return when &lt;code&gt;set_attr&lt;/code&gt; is called. In this case, it returns &lt;code&gt;Ok(())&lt;/code&gt; regardless of the arguments (&lt;code&gt;|_, _, _|&lt;/code&gt; means the arguments are ignored). This simulates the successful execution of &lt;code&gt;set_attr&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of you might find this super basic or not that interesting, but as I mentioned, in this &lt;code&gt;YOLO series&lt;/code&gt;, I’m sharing things that I find interesting or just want to talk about. I wasn’t a big fan of using this kind of library in Go, partly due to Go’s constraints, but in Rust, I found &lt;code&gt;mockall&lt;/code&gt; really useful. It even reminded me of my old days with Python.&lt;/p&gt;

&lt;p&gt;Again, this section wasn’t meant to explain mocking in Rust or &lt;code&gt;mockall&lt;/code&gt;. I’m sure there are plenty of great resources that cover it in detail. I just wanted to mention it briefly.&lt;/p&gt;

&lt;h2&gt;
  
  
  To conclude
&lt;/h2&gt;

&lt;p&gt;In this post, I’ve shared some of the reasoning behind building &lt;code&gt;rrm&lt;/code&gt; and the tools I used along the way. From using extended attributes to simplify metadata handling to experimenting with the &lt;code&gt;mockall&lt;/code&gt; crate for testing in Rust, these were just things that piqued my interest.&lt;/p&gt;

&lt;p&gt;The goal of this YOLO series is to highlight the fun and learning that comes with building even simple tools. I hope you found something useful here, and I look forward to sharing more projects and insights in future posts. As always, feedback is welcome!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy coding!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>linux</category>
      <category>cli</category>
      <category>go</category>
    </item>
    <item>
      <title>Simple thoughts</title>
      <dc:creator>Douglas Makey Mendez Molero</dc:creator>
      <pubDate>Tue, 02 Jul 2024 19:09:09 +0000</pubDate>
      <link>https://forem.com/douglasmakey/simple-thoughts-4i4i</link>
      <guid>https://forem.com/douglasmakey/simple-thoughts-4i4i</guid>
      <description>&lt;p&gt;If you read an article that interests you and you enjoy it, or if you watch a video, consider leaving a message or a reaction. I don't consider myself a content creator, but I genuinely enjoy writing my articles and sharing them with others. For me, it's incredibly rewarding if just one person finds my articles helpful or at least interesting to read.&lt;/p&gt;

&lt;p&gt;When someone leaves a comment or reacts, it makes all the hours I spend preparing the content feel worthwhile. I know you don't have to do it—it's not mandatory—but next time, think about spending a few seconds to make the hours others spend creating content worth it. ❤️&lt;/p&gt;

&lt;p&gt;I'm not the only one who feels this way. I sometimes think my content might not be too interesting, but there's a lot of amazing content out there. So, next time, consider the effort and dedication people put into creating great content. Your engagement will make them happy!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Fooling Port Scanners: Simulating Open Ports with eBPF and Rust</title>
      <dc:creator>Douglas Makey Mendez Molero</dc:creator>
      <pubDate>Sat, 29 Jun 2024 21:47:09 +0000</pubDate>
      <link>https://forem.com/douglasmakey/fooling-port-scanners-simulating-open-ports-with-ebpf-and-rust-24e3</link>
      <guid>https://forem.com/douglasmakey/fooling-port-scanners-simulating-open-ports-with-ebpf-and-rust-24e3</guid>
      <description>&lt;p&gt;In our previous &lt;a href="https://www.kungfudev.com/blog/2024/06/14/network-sockets-syn-and-accept-queue"&gt;article&lt;/a&gt;, we explored the &lt;code&gt;SYN and accept queues&lt;/code&gt; and their crucial role in the TCP &lt;code&gt;three-way handshake&lt;/code&gt;. We learned that for a TCP connection to be fully established, the three-way handshake must be successfully completed. Let's recap this process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The client initiates the connection by sending a &lt;code&gt;SYN&lt;/code&gt; packet.&lt;/li&gt;
&lt;li&gt;The server responds with a &lt;code&gt;SYN-ACK&lt;/code&gt; packet.&lt;/li&gt;
&lt;li&gt;The client then sends an &lt;code&gt;ACK&lt;/code&gt; packet back to the server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, the client considers the connection established. However, it's important to note that from the server's perspective, the connection is only fully established when it receives and processes the final &lt;code&gt;ACK&lt;/code&gt; from the client.&lt;/p&gt;

&lt;p&gt;In this article, we will review the three-way handshake behavior and a related port scanning technique. We will also explore how to use &lt;code&gt;Rust&lt;/code&gt; and &lt;code&gt;eBPF&lt;/code&gt; to thwart curious individuals attempting to scan our machine using this technique.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the TCP Three-Way Handshake in Port Scanning
&lt;/h2&gt;

&lt;p&gt;As we delve deeper into TCP connection management, it's crucial to understand the server's behavior when it receives connection requests. Let's break this down:&lt;/p&gt;

&lt;p&gt;When a server has a socket listening on a specific port, it's ready to handle incoming connection requests. Upon receiving a &lt;code&gt;SYN&lt;/code&gt; packet, the server begins tracking potential connections by allocating resources, such as space in the &lt;code&gt;SYN queue&lt;/code&gt;. This behavior, while necessary for normal operation, can be exploited by malicious actors. For instance, the &lt;code&gt;SYN flood attack&lt;/code&gt; takes advantage of this resource allocation to overwhelm the server.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're interested in learning more about the &lt;code&gt;SYN flood attack&lt;/code&gt;, feel free to leave a comment. This attack exploits the TCP handshake process to overwhelm a server with incomplete connection requests. It works by sending a large number of &lt;code&gt;SYN&lt;/code&gt; packets to a server. The server allocates resources for each connection request, occupying significant kernel memory, while the cost for the client is just one &lt;code&gt;SYN&lt;/code&gt; packet per request, with no memory allocation on their end.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's important to note the phrase &lt;strong&gt;"When a server has a socket listening on a ..."&lt;/strong&gt; from our previous discussion. This condition is critical because it determines how the server responds to incoming &lt;code&gt;SYN&lt;/code&gt; packets. Let's clarify the two scenarios:&lt;/p&gt;

&lt;h3&gt;
  
  
  Server with a listening socket on the targeted port
&lt;/h3&gt;

&lt;p&gt;Flow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Receives &lt;code&gt;SYN&lt;/code&gt; packet&lt;/li&gt;
&lt;li&gt;Responds with &lt;code&gt;SYN-ACK&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Allocates resources to track the potential connection
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+--------+                      +-----------------------+
| Client |                      | Server with Listening |
|        |                      | Socket on Target Port |
+--------+                      +-----------------------+
     |                                    |
     |--- SYN --------------------------&amp;gt; |
     |                                    |
     |                                    |
     | &amp;lt;--- SYN-ACK --------------------- |
     |                                    |
     |                                    |
     |                                    |
     |                                    |
+--------+                      +-----------------------+
| Client |                      | Allocates Resources to|
|        |                      | Track Potential Conn. |
+--------+                      +-----------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Server without a listening socket on the targeted port
&lt;/h3&gt;

&lt;p&gt;Flow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Receives &lt;code&gt;SYN&lt;/code&gt; packet&lt;/li&gt;
&lt;li&gt;Responds with &lt;code&gt;RST-ACK&lt;/code&gt; (Reset-Acknowledge)&lt;/li&gt;
&lt;li&gt;No resources are allocated for connection tracking
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+--------+                      +-----------------------+
|        |                      | Server without        |
| Client |                      | Listening Socket on   |
|        |                      | Target Port           |
+--------+                      +-----------------------+
     |                                    |
     |--- SYN --------------------------&amp;gt; |
     |                                    |
     |                                    |
     | &amp;lt;--- RST-ACK --------------------- |
     |                                    |
     |                                    |
     |                                    |
     |                                    |
+--------+                      +------------------------+
| Client |                      | No Resources Allocated |
|        |                      | for Connection Tracking|
+--------+                      +------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;RST-ACK&lt;/code&gt; response in the second scenario is the server's way of saying, &lt;strong&gt;"There's no service listening on this port, so don't attempt to establish a connection."&lt;/strong&gt; This behavior is a fundamental aspect of TCP/IP networking and plays a crucial role in network security and resource management.&lt;/p&gt;

&lt;p&gt;As we can see, by sending a simple &lt;code&gt;SYN&lt;/code&gt; packet to a server on a specific port, we can determine if the port is open or not. This is the basis for one of the most popular techniques for port scanning: the Stealth SYN Scan.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stealth SYN Scan: A Popular Port Scanning Technique
&lt;/h2&gt;

&lt;p&gt;Indeed, the behavior we've discussed forms the basis for one of the most popular port scanning techniques: the Stealth SYN Scan, also known as a &lt;code&gt;half-open scan&lt;/code&gt;. This technique is called a half-open scan because it doesn’t actually open a full TCP connection. Instead, a SYN scan only sends the initial SYN packet and examines the response. If a &lt;code&gt;SYN/ACK&lt;/code&gt; packet is received, it indicates that the port is open and accepting connections. This is recorded, and an &lt;code&gt;RST&lt;/code&gt; packet is sent to tear down the connection.&lt;/p&gt;

&lt;p&gt;To recap:&lt;br&gt;
&lt;strong&gt;Stealth SYN Scan Process:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The scanner sends a &lt;code&gt;SYN&lt;/code&gt; packet to a target port.&lt;/li&gt;
&lt;li&gt;If the port is open (i.e., a service is listening):

&lt;ul&gt;
&lt;li&gt;The target responds with a &lt;code&gt;SYN-ACK&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The scanner immediately sends an &lt;code&gt;RST&lt;/code&gt; to terminate the connection.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If the port is closed:

&lt;ul&gt;
&lt;li&gt;The target responds with an &lt;code&gt;RST-ACK&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it's called "Stealth":&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The scan doesn't complete the full TCP handshake.&lt;/li&gt;
&lt;li&gt;It's less likely to be logged by basic firewall configurations.&lt;/li&gt;
&lt;li&gt;It can potentially bypass certain intrusion detection systems (IDS).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The SYN scan is popular for its speed, capable of scanning thousands of ports per second on a fast network. It's unobtrusive and stealthy, as it never completes TCP connections.&lt;/p&gt;
&lt;h3&gt;
  
  
  Nmap in Action: Demonstrating SYN Scans
&lt;/h3&gt;

&lt;p&gt;As you may know, &lt;code&gt;Nmap&lt;/code&gt; is a powerful network scanning and discovery tool widely used by security professionals and system administrators.&lt;/p&gt;

&lt;p&gt;Using Nmap, a &lt;code&gt;SYN scan&lt;/code&gt; can be performed with the command-line option &lt;code&gt;-sS&lt;/code&gt;. The program must be run as root since it requires raw-packet privileges. This is the default TCP scan when such privileges are available. Therefore, if you run Nmap as root, this technique will be used by default, and you don't need to specify the &lt;code&gt;-sS&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;So these commands are equivalent:&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-p-&lt;/span&gt; 192.168.2.107
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-p-&lt;/span&gt; 192.168.2.107
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we are simply instructing Nmap to perform a SYN scan on the target &lt;code&gt;192.168.2.107&lt;/code&gt; using &lt;code&gt;-p-&lt;/code&gt; to scan all ports from 1 through 65535. However, we can also specify individual ports or a range of ports.&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;nmap &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-p9000-9500&lt;/span&gt; 192.168.2.107
Starting Nmap 7.95 &lt;span class="o"&gt;(&lt;/span&gt; https://nmap.org &lt;span class="o"&gt;)&lt;/span&gt; at 2024-06-29 14:56 EDT
Nmap scan report &lt;span class="k"&gt;for &lt;/span&gt;dlm &lt;span class="o"&gt;(&lt;/span&gt;192.168.2.107&lt;span class="o"&gt;)&lt;/span&gt;
Host is up &lt;span class="o"&gt;(&lt;/span&gt;0.0085s latency&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Not shown: 499 closed tcp ports &lt;span class="o"&gt;(&lt;/span&gt;reset&lt;span class="o"&gt;)&lt;/span&gt;
PORT     STATE SERVICE
9090/tcp open  ...
9100/tcp open  ...
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the output above, we can see that the target machine has two open ports in the specific range from &lt;code&gt;9000 to 9500&lt;/code&gt;. The remaining 499 ports are closed. This is because, as we know, Nmap received &lt;code&gt;RST&lt;/code&gt; packets when it sent the initial &lt;code&gt;SYN&lt;/code&gt; to those ports.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crafting Our Defense: eBPF and Rust Implementation
&lt;/h2&gt;

&lt;p&gt;In previous articles, I explained how to start projects with Rust-Aya, including using their scaffolding generator. If you need a refresher, feel free to revisit &lt;a href="https://www.kungfudev.com/blog/2023/11/21/ddos-mitigation-with-rust-and-aya"&gt;Harnessing eBPF and XDP for DDoS Mitigation&lt;/a&gt; and &lt;a href="https://www.kungfudev.com/blog/2023/12/07/https-sniffer-with-rust-aya"&gt;Uprobes Siblings - Capturing HTTPS Traffic&lt;/a&gt;, or check the &lt;a href="https://aya-rs.dev/book/"&gt;Rust-Aya documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up the eBPF Program
&lt;/h3&gt;

&lt;p&gt;As we are going to use &lt;code&gt;XDP&lt;/code&gt; to accomplish this trick, the initial part of the code is very similar to the example explained in the article &lt;a href="https://www.kungfudev.com/blog/2023/11/21/ddos-mitigation-with-rust-and-aya"&gt;Harnessing eBPF and XDP for DDoS Mitigation&lt;/a&gt;. In this code, we first validate if the packet is an &lt;code&gt;IPv4 packet&lt;/code&gt; by examining the &lt;code&gt;ether_type&lt;/code&gt; in the Ethernet header. If it's not IPv4, the packet is passed through without further processing. Then, we look at the IPv4 header to check if it's a &lt;code&gt;TCP packet&lt;/code&gt;. Non-TCP packets are also allowed to pass. This way, our program focuses only on IPv4 TCP packets and then we store the TCP header in &lt;code&gt;tcp_hdr&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;try_syn_ack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;XdpContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ExecutionError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Use pointer arithmetic to obtain a raw pointer to the Ethernet header at the start of the XdpContext data.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;eth_hdr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;EthHdr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_mut_ptr_at&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;ctx&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="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Check the EtherType of the packet. If it's not an IPv4 packet, pass it along without further processing&lt;/span&gt;
    &lt;span class="c1"&gt;// We have to use unsafe here because we're dereferencing a raw pointer&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eth_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.ether_type&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;EtherType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Ipv4&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;xdp_action&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;XDP_PASS&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Using Ethernet header length, obtain a pointer to the IPv4 header which immediately follows the Ethernet header&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ip_hdr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;Ipv4Hdr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_mut_ptr_at&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;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;EthHdr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LEN&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="c1"&gt;// Check the protocol of the IPv4 packet. If it's not TCP, pass it along without further processing&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ip_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.proto&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;IpProto&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tcp&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;xdp_action&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;XDP_PASS&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Using the IPv4 header length, obtain a pointer to the TCP header which immediately follows the IPv4 header&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;TcpHdr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_mut_ptr_at&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;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;EthHdr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LEN&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nn"&gt;Ipv4Hdr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LEN&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="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Filtering Packets: Targeting Specific Ports
&lt;/h3&gt;

&lt;p&gt;Now that we've confirmed the received packet is a TCP packet, let's implement a simple filter in our eBPF program. This filter will instruct the program to interact only with packets whose destination port falls within the range of &lt;code&gt;9000 to 9500&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's important to note that this is a basic implementation. In a production environment, we'd want to implement a more robust and flexible solution. For instance, we could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use eBPF to listen for the &lt;code&gt;bind&lt;/code&gt; syscall in our server.&lt;/li&gt;
&lt;li&gt;Utilize eBPF maps to track all open ports on our server, avoiding interference with legitimate services.&lt;/li&gt;
&lt;li&gt;Alternatively, use eBPF maps to maintain a list of ports we want to simulate as open.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Again, we're using &lt;code&gt;unsafe&lt;/code&gt; throughout the code, as we're directly manipulating memory through raw pointers. This allows us to alter the packets or inspect them as needed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For now, let's keep it simple and focus on our port range filter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Check the destination port of the TCP packet. If it's not in the range 9000-9500, pass it along without further processing&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nn"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_be&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.dest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="o"&gt;..=&lt;/span&gt;&lt;span class="mi"&gt;9500&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;xdp_action&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;XDP_PASS&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;This code snippet does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We extract the destination port from the TCP header, converting it from network byte order (big-endian) to host byte order.&lt;/li&gt;
&lt;li&gt;We use a &lt;code&gt;match&lt;/code&gt; statement to check if the port falls within our target range.&lt;/li&gt;
&lt;li&gt;If the port is in the range 9000-9500, we continue processing.&lt;/li&gt;
&lt;li&gt;For any other port, we immediately return &lt;code&gt;XDP_PASS&lt;/code&gt;, allowing the packet to continue its normal journey through the network stack.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This filter allows us to focus our eBPF program's attention on a specific range of ports, which could be useful for various network management and security tasks. For example, we could use this to implement a &lt;code&gt;port knocking sequence&lt;/code&gt;, set up a honeypot, or monitor for potential port scan attempts within a specific range.&lt;/p&gt;

&lt;h3&gt;
  
  
  Identifying SYN Packets
&lt;/h3&gt;

&lt;p&gt;Now that we've confirmed the packet is destined for one of our target ports, our next step is to determine if it's a &lt;code&gt;SYN&lt;/code&gt; packet. Here's how we can check for a SYN packet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Check if it's a SYN packet&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;is_syn_packet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.syn&lt;/span&gt;&lt;span class="p"&gt;()&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;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.ack&lt;/span&gt;&lt;span class="p"&gt;()&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;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&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="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;is_syn_packet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;xdp_action&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;XDP_PASS&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;Let's break down this code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We define &lt;code&gt;is_syn_packet&lt;/code&gt; by checking two conditions: 

&lt;ul&gt;
&lt;li&gt;The SYN flag is set (&lt;code&gt;(*tcp_hdr).syn() != 0&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The ACK flag is not set (&lt;code&gt;(*tcp_hdr).ack() == 0&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A valid SYN packet in the initial TCP handshake should have the SYN flag set and the ACK flag unset.&lt;/li&gt;
&lt;li&gt;If the packet is not a SYN packet, we immediately return &lt;code&gt;XDP_PASS&lt;/code&gt;, allowing non-SYN packets to continue their normal path through the network stack.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Crafting the SYN-ACK Response
&lt;/h3&gt;

&lt;p&gt;Now that we've identified a &lt;code&gt;SYN&lt;/code&gt; packet targeting one of our ports of interest, we'll craft a &lt;code&gt;SYN-ACK&lt;/code&gt; response. To do this efficiently, we'll modify the incoming packet in-place, transforming it into our response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Swap Ethernet addresses&lt;/span&gt;
&lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eth_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.src_addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eth_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.dst_addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Swap IP addresses&lt;/span&gt;
&lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ip_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.src_addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ip_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.dst_addr&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;Here's what this code accomplishes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ethernet Address Swap:

&lt;ul&gt;
&lt;li&gt;We exchange the source and destination MAC addresses in the Ethernet header.&lt;/li&gt;
&lt;li&gt;This ensures our response packet will be routed back to the sender at the link layer.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;IP Address Swap:

&lt;ul&gt;
&lt;li&gt;Similarly, we swap the source and destination IP addresses in the IP header.&lt;/li&gt;
&lt;li&gt;This directs our response to the original sender at the network layer.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;core::mem::swap&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;This function efficiently exchanges the values of two mutable references without requiring a temporary variable.&lt;/li&gt;
&lt;li&gt;It's particularly useful here as it keeps our code concise and performant.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By modifying the existing packet, we're essentially "reflecting" it back to the sender, but with crucial changes that we'll make in the next steps to transform it into a valid &lt;code&gt;SYN-ACK&lt;/code&gt; response.&lt;/p&gt;

&lt;p&gt;After swapping the Ethernet and IP addresses, we now need to modify the TCP header to transform our packet into a valid &lt;code&gt;SYN-ACK&lt;/code&gt; response. This step is critical in simulating an open port and continuing the TCP handshake process. Here's how we accomplish this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Modify TCP header for SYN-ACK&lt;/span&gt;
&lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.dest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.set_ack&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="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.ack_seq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.seq&lt;/span&gt;&lt;span class="nf"&gt;.to_be&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="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.seq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1u32&lt;/span&gt;&lt;span class="nf"&gt;.to_be&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;Let's break down these modifications:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Port Swap:

&lt;ul&gt;
&lt;li&gt;We exchange the source and destination ports, ensuring our response goes back to the correct client port.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Setting the ACK Flag:

&lt;ul&gt;
&lt;li&gt;We set the ACK flag using &lt;code&gt;set_ack(1)&lt;/code&gt;. This, combined with the existing SYN flag, creates a &lt;code&gt;SYN-ACK&lt;/code&gt; packet.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Acknowledgment Number:

&lt;ul&gt;
&lt;li&gt;We set the acknowledgment number to the incoming sequence number plus one.&lt;/li&gt;
&lt;li&gt;This acknowledges the client's SYN and informs it of the next sequence number we expect.&lt;/li&gt;
&lt;li&gt;Note the use of &lt;code&gt;to_be()&lt;/code&gt; to handle endianness correctly.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Sequence Number:

&lt;ul&gt;
&lt;li&gt;We set our initial sequence number to 1 (converted to network byte order).&lt;/li&gt;
&lt;li&gt;In a real TCP stack, this would typically be a random number for security reasons.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;It's important to note that in our eBPF program, we're modifying packet headers without recalculating the checksums. In a production environment, this approach could lead to issues as the modified packets might be dropped by network stacks that verify checksums. For the sake of simplicity and focusing on the core concepts, we've omitted checksum recalculation in this demonstration.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Nmap&lt;/code&gt; typically uses raw sockets for its SYN scans. Raw sockets bypass much of the normal network stack processing, including checksum verification in many cases.&lt;/p&gt;

&lt;p&gt;Also, in a production environment, you might want to consider additional factors. This is just an oversimplified version that demonstrates the basic concept of tricking a simple SYN scan.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These modifications transform our incoming &lt;code&gt;SYN&lt;/code&gt; packet into a &lt;code&gt;SYN-ACK&lt;/code&gt; response, effectively simulating the behavior of an open port. This is a key step in our port scanning detection or simulation logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sending the Modified Packet
&lt;/h3&gt;

&lt;p&gt;After modifying our packet to create a valid &lt;code&gt;SYN-ACK&lt;/code&gt; response, the final step is to send this packet back to the client. We accomplish this using the &lt;code&gt;XDP_TX&lt;/code&gt; action. This action instructs the XDP framework to transmit the modified packet back out through the same network interface it arrived on.&lt;/p&gt;

&lt;p&gt;This action is particularly useful for applications like our port scan simulation, load balancers, firewalls, and other scenarios where rapid packet inspection and modification are crucial.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;xdp_action&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;XDP_TX&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using &lt;code&gt;XDP_TX&lt;/code&gt;, we're completing our port scanning response simulation in a highly efficient manner. This approach allows us to respond to SYN packets almost instantaneously, making our simulated open ports "virtually indistinguishable" from real ones in terms of response time.&lt;/p&gt;

&lt;p&gt;It's worth noting that this approach, while effective for &lt;code&gt;Syn Scan&lt;/code&gt; scenario, doesn't account for more sophisticated scanning techniques that might use non-standard flag combinations. In a production environment, you might want to implement more comprehensive checks to detect various types of port scans.&lt;/p&gt;

&lt;h3&gt;
  
  
  Putting It All Together: Running Our eBPF Program
&lt;/h3&gt;

&lt;p&gt;Full code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;try_syn_ack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;XdpContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ExecutionError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Use pointer arithmetic to obtain a raw pointer to the Ethernet header at the start of the XdpContext data.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;eth_hdr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;EthHdr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_mut_ptr_at&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;ctx&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="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Check the EtherType of the packet. If it's not an IPv4 packet, pass it along without further processing&lt;/span&gt;
    &lt;span class="c1"&gt;// We have to use unsafe here because we're dereferencing a raw pointer&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eth_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.ether_type&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;EtherType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Ipv4&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;xdp_action&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;XDP_PASS&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Using Ethernet header length, obtain a pointer to the IPv4 header which immediately follows the Ethernet header&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ip_hdr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;Ipv4Hdr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_mut_ptr_at&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;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;EthHdr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LEN&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="c1"&gt;// Check the protocol of the IPv4 packet. If it's not TCP, pass it along without further processing&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ip_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.proto&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;IpProto&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tcp&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;xdp_action&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;XDP_PASS&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Using the IPv4 header length, obtain a pointer to the TCP header which immediately follows the IPv4 header&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;TcpHdr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_mut_ptr_at&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;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;EthHdr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LEN&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nn"&gt;Ipv4Hdr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LEN&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="c1"&gt;// Check the destination port of the TCP packet. If it's not in the range 9000-9500, pass it along without further processing&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nn"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_be&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.dest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="o"&gt;..=&lt;/span&gt;&lt;span class="mi"&gt;9500&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;xdp_action&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;XDP_PASS&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Check if it's a SYN packet&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;is_syn_packet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.syn&lt;/span&gt;&lt;span class="p"&gt;()&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;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.ack&lt;/span&gt;&lt;span class="p"&gt;()&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;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&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="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;is_syn_packet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;xdp_action&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;XDP_PASS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Swap Ethernet addresses&lt;/span&gt;
    &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eth_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.src_addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eth_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.dst_addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Swap IP addresses&lt;/span&gt;
    &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ip_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.src_addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ip_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.dst_addr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Modify TCP header for SYN-ACK&lt;/span&gt;
    &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.dest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.set_ack&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="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.ack_seq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.seq&lt;/span&gt;&lt;span class="nf"&gt;.to_be&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="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tcp_hdr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.seq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1u32&lt;/span&gt;&lt;span class="nf"&gt;.to_be&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;xdp_action&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;XDP_TX&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;Now that we've implemented our eBPF program to simulate open ports within our chosen range, it's time to see it in action. This demonstration will showcase the power of eBPF in manipulating network behavior at a low level.&lt;/p&gt;

&lt;p&gt;First, let's run our eBPF program. Open a terminal and execute the following command:&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="nv"&gt;$ RUST_LOG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info cargo xtask run &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; wlp5s0
&lt;span class="o"&gt;[&lt;/span&gt;2024-06-29T19:57:33Z INFO  syn_ack] Waiting &lt;span class="k"&gt;for &lt;/span&gt;Ctrl-C...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With our eBPF program running, let's perform a port scan using &lt;code&gt;nmap&lt;/code&gt; to see the effects:&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-p9000-9500&lt;/span&gt; 192.168.2.107
Starting Nmap 7.95 &lt;span class="o"&gt;(&lt;/span&gt; https://nmap.org &lt;span class="o"&gt;)&lt;/span&gt; at 2024-06-29 15:57 EDT
Nmap scan report &lt;span class="k"&gt;for &lt;/span&gt;dlm &lt;span class="o"&gt;(&lt;/span&gt;192.168.2.107&lt;span class="o"&gt;)&lt;/span&gt;
Host is up &lt;span class="o"&gt;(&lt;/span&gt;0.0084s latency&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

PORT     STATE SERVICE
9000/tcp open  cslistener
9001/tcp open  tor-orport
9002/tcp open  dynamid
9003/tcp open  unknown
9004/tcp open  unknown
9005/tcp open  golem
9006/tcp open  unknown
9007/tcp open  ogs-client
9008/tcp open  ogs-server
...
9491/tcp open  unknown
9492/tcp open  unknown
9493/tcp open  unknown
9494/tcp open  unknown
9495/tcp open  unknown
9496/tcp open  unknown
9497/tcp open  unknown
9498/tcp open  unknown
9499/tcp open  unknown
9500/tcp open  ismserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see, Nmap reports all ports in the range &lt;code&gt;9000-9500&lt;/code&gt; as open. This is exactly what our eBPF program is designed to do: respond to &lt;code&gt;SYN&lt;/code&gt; packets on these ports with &lt;code&gt;SYN-ACK&lt;/code&gt;, simulating open ports.&lt;/p&gt;

&lt;p&gt;In a production environment, you would want to implement additional features such as logging, more sophisticated decision-making logic, and possibly integration with other security systems. This example serves as a foundation for understanding how eBPF can be used to manipulate network traffic at a fundamental level.&lt;/p&gt;

&lt;p&gt;For a deeper dive and hands-on experience, all the code discussed is available in my  &lt;a href="https://github.com/douglasmakey/syn-ack/tree/main"&gt;repository&lt;/a&gt;. Feel free to explore, experiment, and comments !&lt;/p&gt;

&lt;h2&gt;
  
  
  To conclude
&lt;/h2&gt;

&lt;p&gt;In this article, we've explored the intricacies of TCP handshakes and port scanning techniques, culminating in a practical demonstration of how eBPF and Rust can be used to manipulate network behavior at a fundamental level. By implementing a program that simulates open ports, we've showcased the power and flexibility of eBPF in network security applications. This approach not only provides a means to confuse potential attackers but also opens up possibilities for more advanced network management and security tools. &lt;/p&gt;

&lt;p&gt;Thank you for reading along. This blog is a part of my learning journey and your feedback is highly valued. There's more to explore and share regarding eBPF, so stay tuned for upcoming posts. Your insights and experiences are welcome as we learn and grow together in this domain. &lt;strong&gt;Happy coding!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ebpf</category>
      <category>rust</category>
      <category>linux</category>
      <category>networking</category>
    </item>
    <item>
      <title>Networking and Sockets: Syn and Accept queue</title>
      <dc:creator>Douglas Makey Mendez Molero</dc:creator>
      <pubDate>Fri, 21 Jun 2024 22:31:03 +0000</pubDate>
      <link>https://forem.com/douglasmakey/networking-and-sockets-syn-and-accept-queue-1lgn</link>
      <guid>https://forem.com/douglasmakey/networking-and-sockets-syn-and-accept-queue-1lgn</guid>
      <description>&lt;p&gt;In my previous &lt;a href="https://www.kungfudev.com/blog/2024/06/14/network-sockets-endianness" rel="noopener noreferrer"&gt;article&lt;/a&gt;, we discussed endianness, its importance, and how to work with it. Understanding endianness is crucial for dealing with data at the byte level, especially in network programming. We examined several examples that highlighted how endianness affects data interpretation.&lt;/p&gt;

&lt;p&gt;One key area we focused on was the relationship between endianness and &lt;code&gt;TCP stream sockets&lt;/code&gt;. We explained why the &lt;code&gt;bind&lt;/code&gt; syscall  expects certain information for the INET family to be in a specific endianness, known as network byte order. This ensures that data is correctly interpreted across different systems, which might use different native endianness.&lt;/p&gt;

&lt;p&gt;One of the next interesting topics after binding the socket is putting it into listening mode with the &lt;code&gt;listen&lt;/code&gt; syscall. In this article, we are going to dive a little deeper into this next phase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Listen: Handshake and SYN/Accept Queues
&lt;/h2&gt;

&lt;p&gt;Recall that TCP is connection-oriented protocol. This means the sender and receiver need to establish a connection based on agreed parameters through a &lt;code&gt;three-way handshake&lt;/code&gt;. The server must be listening for connection requests from clients before a connection can be established, and this is done using the &lt;code&gt;listen&lt;/code&gt; syscall.&lt;/p&gt;

&lt;p&gt;We won't delve into the details of the three-way handshake here, as many excellent articles cover this topic in depth. Additionally, there are related topics like&lt;code&gt;TFO (TCP Fast Open)&lt;/code&gt;and &lt;code&gt;syncookies&lt;/code&gt; that modify its behavior. Instead, we'll provide a brief overview. If you're interested, we can explore these topics in greater detail in future articles.&lt;/p&gt;

&lt;p&gt;The three-way handshake involves the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client sends a SYN (synchronize) packet to the server, indicating a desire to establish a connection.&lt;/li&gt;
&lt;li&gt;The server responds with a SYN-ACK (synchronize-acknowledge) packet, indicating a willingness to establish a connection.&lt;/li&gt;
&lt;li&gt;The client replies with an ACK (acknowledge) packet, confirming it has received the SYN-ACK message, and the connection is established.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2F_next%2Fimage%3Furl%3D%252Fimages%252Fblog%252Faccept-full.png%26w%3D1920%26q%3D75" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2F_next%2Fimage%3Furl%3D%252Fimages%252Fblog%252Faccept-full.png%26w%3D1920%26q%3D75" alt="handshake"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do you remember in the first article when we mentioned that the &lt;code&gt;listen&lt;/code&gt; operation involves the kernel creating two queues for the socket. The kernel uses these queues to store information related to the state of the connection. &lt;/p&gt;

&lt;p&gt;The kernel creates these two &lt;strong&gt;queues&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SYN Queue&lt;/strong&gt;: Its size is determined by a system-wide setting. Although referred to as a queue, it is actually a hash table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accept Queue&lt;/strong&gt;: Its size is specified by the application. We will discuss this further later. It functions as a FIFO (First In, First Out) queue for established connections.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As shown in the previous diagram, these queues play a crucial role in the process. When the server receives a &lt;code&gt;SYN&lt;/code&gt; request from the client, the kernel stores the connection in the &lt;code&gt;SYN queue&lt;/code&gt;. After the server receives an &lt;code&gt;ACK&lt;/code&gt; from the client, the kernel moves the connection from the &lt;code&gt;SYN queue&lt;/code&gt; to the &lt;code&gt;accept queue&lt;/code&gt;. Finally, when the server makes the &lt;code&gt;accept&lt;/code&gt; system call, the connection is taken out of the accept queue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accept Queue Size
&lt;/h3&gt;

&lt;p&gt;As mentioned, these queues have size limits, which act as thresholds for managing incoming connections. If the size limit of the &lt;code&gt;queues&lt;/code&gt; are exceeded, the kernel may discard or drop the incoming connection request or return an RST (Reset) packet to the client, indicating that the connection cannot be established. &lt;/p&gt;

&lt;p&gt;If you recall our previous examples where we created a socket server, you'll notice that we specified a backlog value and passed it to the &lt;code&gt;listen&lt;/code&gt; function. This backlog value determines the length of the queue for completely established sockets waiting to be accepted, known as the accept queue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Listen for incoming connections&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;backlog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Backlog&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&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="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to create backlog"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;listen&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;socket_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;backlog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to listen for connections"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we inspect the &lt;code&gt;Backlog::new&lt;/code&gt; function, we will uncover some interesting details. Here's the function definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MAXCONN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;libc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SOMAXCONN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="cd"&gt;/// Create a `Backlog`, an `EINVAL` will be returned if `val` is invalid.&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Into&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;cfg_if!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nd"&gt;#[cfg(any(target_os&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"linux"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;target_os&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"freebsd"&lt;/span&gt;&lt;span class="nd"&gt;))]&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;MIN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="o"&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="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;MIN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&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;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MIN&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MAXCONN&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.contains&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;val&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="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Errno&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;EINVAL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&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;We can notice a few things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On Linux and FreeBSD systems, the minimum acceptable value is &lt;code&gt;-1&lt;/code&gt;, while on other systems, it is &lt;code&gt;0&lt;/code&gt;. We will explore the behavior associated with these values later.&lt;/li&gt;
&lt;li&gt;The value should not exceed &lt;code&gt;MAXCONN&lt;/code&gt;, &lt;strong&gt;which is the default maximum number of established connections that can be queued&lt;/strong&gt;. Unlike in &lt;code&gt;C&lt;/code&gt;, where a value greater than &lt;code&gt;MAXCONN&lt;/code&gt; is silently capped to that limit, in Rust's &lt;code&gt;libc&lt;/code&gt; crate, exceeding &lt;code&gt;MAXCONN&lt;/code&gt; results in an error.&lt;/li&gt;
&lt;li&gt;Interestingly, in the &lt;code&gt;libc&lt;/code&gt; crate, &lt;code&gt;MAXCONN&lt;/code&gt; is hardcoded to &lt;code&gt;4096&lt;/code&gt;. Therefore, even if we modify &lt;code&gt;maxconn&lt;/code&gt;, this won't affect the listening socket, and we won't be able to use a greater value.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;SOMAXCONN&lt;/code&gt; Parameter
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;net.core.somaxconn&lt;/code&gt; kernel parameter sets the maximum number of established connections that can be queued for a socket. This parameter helps prevent a flood of connection requests from overwhelming the system. The default value for &lt;code&gt;net.core.somaxconn&lt;/code&gt; is defined by the &lt;code&gt;SOMAXCONN&lt;/code&gt; constant &lt;a href="https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/linux/socket.h#L297" rel="noopener noreferrer"&gt;here&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;You can view and modify this value using the &lt;code&gt;sysctl&lt;/code&gt; command:&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;sysctl net.core.somaxconn
net.core.somaxconn &lt;span class="o"&gt;=&lt;/span&gt; 4096

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;sysctl &lt;span class="nt"&gt;-w&lt;/span&gt; net.core.somaxconn&lt;span class="o"&gt;=&lt;/span&gt;8000
net.core.somaxconn &lt;span class="o"&gt;=&lt;/span&gt; 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Analyzing the Accept Queue with example
&lt;/h3&gt;

&lt;p&gt;If we run the example &lt;code&gt;listen-not-accept&lt;/code&gt;, which sets the backlog to &lt;code&gt;1&lt;/code&gt; without calling &lt;code&gt;accept&lt;/code&gt;, and then use &lt;code&gt;telnet&lt;/code&gt; to connect to it, we can use the &lt;code&gt;ss&lt;/code&gt; command to inspect the queue for that socket.&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="c"&gt;# server&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;cargo run &lt;span class="nt"&gt;--bin&lt;/span&gt; listen-not-accept
Socket file descriptor: 3

&lt;span class="c"&gt;# telnet&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;telnet 127.0.0.1 6797
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is &lt;span class="s1"&gt;'^]'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;ss&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;State                      Recv-Q                     Send-Q                                          Local Address:Port                                            Peer Address:Port                     Process                     
LISTEN                     1                          1                                                   127.0.0.1:6797                                                 0.0.0.0:&lt;span class="k"&gt;*&lt;/span&gt;                                         
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Recv-Q&lt;/strong&gt;: The size of the current accept queue. This indicates the number of completed connections waiting for the application to call &lt;code&gt;accept()&lt;/code&gt;. Since we have one connection from &lt;code&gt;telnet&lt;/code&gt; and the application is not calling &lt;code&gt;accept&lt;/code&gt;, we see a value of 1.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Send-Q&lt;/strong&gt;: The maximum length of the accept queue, which corresponds to the backlog size we set. In this case, it is 1.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testing Backlog Behavior on Linux
&lt;/h3&gt;

&lt;p&gt;We are going to execute the following code to dynamically test the backlog configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Testing backlog..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;backlog_size&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;server_socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nn"&gt;AddressFamily&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Inet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nn"&gt;SockType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nn"&gt;SockFlag&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="nn"&gt;SockProtocol&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tcp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to create server socket"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;server_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="nn"&gt;SockaddrIn&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1:8080"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server_socket&lt;/span&gt;&lt;span class="nf"&gt;.as_raw_fd&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;server_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nf"&gt;listen&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;server_socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Backlog&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;backlog_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;successful_connections&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;attempts&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;loop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;client_socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nn"&gt;AddressFamily&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Inet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nn"&gt;SockType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nn"&gt;SockFlag&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="nn"&gt;SockProtocol&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tcp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;attempts&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="k"&gt;match&lt;/span&gt; &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_socket&lt;/span&gt;&lt;span class="nf"&gt;.as_raw_fd&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;server_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;successful_connections&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_socket&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"Backlog {} successful connections: {} - attempts: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;backlog_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;successful_connections&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;attempts&lt;/span&gt;
        &lt;span class="p"&gt;);&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;The key functions of the code are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It iterates over a range of backlog values, creating a server socket and putting it in listen mode with each specific backlog value.&lt;/li&gt;
&lt;li&gt;It then enters a loop, attempting to connect client sockets to the server socket. If a connection is successful, it adds the client socket to the &lt;code&gt;successful_connections&lt;/code&gt; vector. If it fails, it breaks the loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows us to determine the exact number of successful connections for each backlog configuration.&lt;/p&gt;

&lt;p&gt;When we run the program, we will see output similar to the following. Note that this process may take a few minutes:&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="nv"&gt;$ &lt;/span&gt;cargo run &lt;span class="nt"&gt;--bin&lt;/span&gt; test-backlog
Backlog &lt;span class="nt"&gt;-1&lt;/span&gt; successful connections: 4097 - attempts: 4098
Backlog 0 successful connections: 1 - attempts: 2
Backlog 1 successful connections: 2 - attempts: 3
Backlog 2 successful connections: 3 - attempts: 4
Backlog 3 successful connections: 4 - attempts: 5
Backlog 4 successful connections: 5 - attempts: 6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the above output you can notice two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When listen receive the the min acceptable value &lt;code&gt;-1&lt;/code&gt; it will use the default value of &lt;code&gt;SOMAXCONN&lt;/code&gt;, we already know if we pass a value greather than &lt;code&gt;SOMAXCONN&lt;/code&gt; it will return an error.&lt;/li&gt;
&lt;li&gt;And the other "weird" that can notice is that always the connections are 1 more than the limit set by the backlog, for example, backlog is 3 but there are 4 connections, &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last result is due to the behavior of this &lt;a href="https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/net/sock.h#L1033" rel="noopener noreferrer"&gt;function&lt;/a&gt; in Linux. The &lt;code&gt;sk_ack_backlog&lt;/code&gt; represents the current number of acknowledged connections, while the &lt;code&gt;sk_max_ack_backlog&lt;/code&gt; represents our backlog value. For example, when the backlog is set to 3, the function checks if &lt;code&gt;sk_ack_backlog &amp;gt; sk_max_ack_backlog&lt;/code&gt;. When the third connection arrives, this check (&lt;code&gt;3 &amp;gt; 3&lt;/code&gt;) evaluates to false, meaning the queue is not considered full, and it allows one more connection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;sk_acceptq_is_full&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;sock&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sk&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="n"&gt;READ_ONCE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sk&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;sk_ack_backlog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;READ_ONCE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sk&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;sk_max_ack_backlog&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;h3&gt;
  
  
  Handling a Full Accept Queue
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2Fimages%2Fblog%2Faccept-full.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2Fimages%2Fblog%2Faccept-full.png" alt="acept queue"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we can see from our program's logs, the client will attempt to connect to the server one more time than the specified backlog value. For example, if the backlog is 4, it will attempt to connect 5 times. In the last attempt, the client and server go through the handshake process: the client sends the &lt;code&gt;SYN&lt;/code&gt;, the server responds with &lt;code&gt;SYN-ACK&lt;/code&gt;, and the client sends an &lt;code&gt;ACK&lt;/code&gt; back, thinking the connection is established.&lt;/p&gt;

&lt;p&gt;Unfortunately, if the server's &lt;code&gt;accept queue&lt;/code&gt; is full, it cannot move the connection from the &lt;code&gt;SYN queue&lt;/code&gt; to the &lt;code&gt;accept queue&lt;/code&gt;. The server's behavior when the accept queue overflows is primarily determined by the &lt;code&gt;net.ipv4.tcp_abort_on_overflow&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;Normally, this value is set to &lt;code&gt;0&lt;/code&gt;, meaning that when there is an overflow, the server will discard the client's &lt;code&gt;ACK&lt;/code&gt; packet from the third handshake, acting as if it never received it. The server will then retransmit the &lt;code&gt;SYN-ACK&lt;/code&gt; packet. The number of retransmissions the server will attempt is determined by the &lt;code&gt;net.ipv4.tcp_synack_retries&lt;/code&gt; option.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We can reduce or increase the &lt;code&gt;tcp_synack_retries&lt;/code&gt; value. By default, this value is set to 5 on Linux.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In our final attempt, when the retransmission limit is reached, the connection is removed from the &lt;code&gt;SYN queue&lt;/code&gt;, and the client receives an error. Again, this is an oversimplified overview of the process. The actual process is much more complex and involves additional steps and scenarios. However, for our purposes, we can keep things simpler.&lt;/p&gt;

&lt;p&gt;By running the command &lt;code&gt;netstat -s | grep "overflowed"&lt;/code&gt;, we can check for occurrences of socket listen queue overflows. For example, in my case, the output indicates that &lt;strong&gt;"433 times the listen queue of a socket overflowed,"&lt;/strong&gt; highlighting instances where the system's accept queue was unable to handle incoming connection requests. This can lead to potential connection issues.&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="nv"&gt;$ &lt;/span&gt;netstat &lt;span class="nt"&gt;-s&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"overflowed"&lt;/span&gt;
433 &lt;span class="nb"&gt;times &lt;/span&gt;the listen queue of a socket overflowed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing Backlog Behavior on Mac
&lt;/h3&gt;

&lt;p&gt;If we execute the same program on a Mac, we will observe some differences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As mentioned, for other systems, the minimum acceptable value is &lt;code&gt;0&lt;/code&gt;. Using this value gives us the default setting.&lt;/li&gt;
&lt;li&gt;The default value for &lt;code&gt;SOMAXCONN&lt;/code&gt; is &lt;code&gt;128&lt;/code&gt;, which can be retrieved using the command &lt;code&gt;sysctl kern.ipc.somaxconn&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Lastly, on a Mac, we don't encounter the issue of allowing &lt;code&gt;Backlog + 1&lt;/code&gt; connections. Instead, we accept the exact number of connections specified in the backlog.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cargo run &lt;span class="nt"&gt;--bin&lt;/span&gt; test-backlog
Backlog 0 successful connections: 128 - attempts: 129
Backlog 1 successful connections: 1 - attempts: 2
Backlog 2 successful connections: 2 - attempts: 3
Backlog 3 successful connections: 3 - attempts: 4
Backlog 4 successful connections: 4 - attempts: 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  SYN Queue Size Considerations
&lt;/h3&gt;

&lt;p&gt;As the &lt;code&gt;listen&lt;/code&gt; man page states, the maximum length of the queue for incomplete sockets &lt;code&gt;(SYN queue)&lt;/code&gt; can be set using the &lt;code&gt;tcp_max_syn_backlog&lt;/code&gt; parameter. However, when &lt;code&gt;syncookies&lt;/code&gt; are enabled, there is no logical maximum length, and this setting is ignored. Additionally, other factors influence the queue's size. As mentioned earlier: &lt;code&gt;its size is determined by a system-wide setting&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can find the code for this example and future ones in this &lt;a href="https://github.com/douglasmakey/socket_net" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  To Conclude
&lt;/h2&gt;

&lt;p&gt;In this article, we explored the role of TCP queues in connection management, focusing on the &lt;code&gt;SYN queue&lt;/code&gt; and the &lt;code&gt;accept queue&lt;/code&gt;. We tested various backlog configurations and examined how different settings impact connection handling. Additionally, we discussed system parameters like &lt;code&gt;tcp_max_syn_backlog&lt;/code&gt; and &lt;code&gt;net.ipv4.tcp_abort_on_overflow&lt;/code&gt;, and their effects on queue behavior.&lt;/p&gt;

&lt;p&gt;Understanding these concepts is crucial for optimizing server performance and managing high traffic scenarios. By running practical tests and using system commands, we gained insights into how to handle connection limits effectively.&lt;/p&gt;

&lt;p&gt;As we move forward, keeping these fundamentals in mind will help ensure robust and efficient network communication.&lt;/p&gt;

&lt;p&gt;Thank you for reading along. This blog is a part of my learning journey and your feedback is highly valued. There's more to explore and share regarding socket and network, so stay tuned for upcoming posts. Your insights and experiences are welcome as we learn and grow together in this domain. &lt;strong&gt;Happy coding!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>rust</category>
      <category>networking</category>
      <category>socket</category>
    </item>
    <item>
      <title>Introducing Shelldon: A New Rust CLI Tool with GPT Features</title>
      <dc:creator>Douglas Makey Mendez Molero</dc:creator>
      <pubDate>Mon, 17 Jun 2024 15:52:17 +0000</pubDate>
      <link>https://forem.com/douglasmakey/introducing-shelldon-a-new-rust-cli-tool-with-gpt-features-4hm4</link>
      <guid>https://forem.com/douglasmakey/introducing-shelldon-a-new-rust-cli-tool-with-gpt-features-4hm4</guid>
      <description>&lt;p&gt;I’m a big fan of tools like Warp and Raycast, especially for their AI capabilities. However, I’ve found their free tiers to be somewhat limiting. Since I already have an OpenAI account, I wanted a solution that would allow me to use my own token. That’s why I created Shelldon.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/douglasmakey/shelldon"&gt;Shelldon&lt;/a&gt; is a command-line tool written in Rust. It provides utilities for executing shell commands, managing prompts, and interacting with multiple LLMs.&lt;/p&gt;

&lt;p&gt;Yes, another CLI with GPT features. Shelldon is not intended to be a full GPT client from the terminal; there are a couple of CLIs much better for that and also a lot of applications and even the OpenAI ChatGPT apps. Shelldon is to solve some personal use cases and it is very useful for me; I hope it could be useful for you too. Also, I made it to have fun playing with Rust!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One of the features that other tools were missing for my use case is the ability to use custom prompts for specific tasks that I need. For that reason, I created Shelldon with the ability to manage prompts and use them whenever you want for specific tasks. You can read more about this &lt;a href="https://github.com/douglasmakey/shelldon?tab=readme-ov-file#handling-prompts"&gt;here&lt;/a&gt;. Also, I plan to extend it with plugins to integrate more complex workflows.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And if you are like me and spend more time in the terminal than in other apps, this might help you. I hope some of you find it useful too. I’m open to feedback and suggestions, and I’d love to hear how you might use Shelldon in your own setups.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Shelldon provides &lt;a href="https://github.com/douglasmakey/shelldon/releases"&gt;Github releases&lt;/a&gt; with prebuilt binaries for MacOS and Linux.&lt;/p&gt;

&lt;h3&gt;
  
  
  Homebrew
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew tap douglasmakey/tap
brew &lt;span class="nb"&gt;install &lt;/span&gt;shelldon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Building from Source
&lt;/h3&gt;

&lt;p&gt;If you prefer to build Shelldon from source, you can clone the repository and build it using cargo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/douglasmakey/shelldon.git
&lt;span class="nb"&gt;cd &lt;/span&gt;shelldon
cargo build &lt;span class="nt"&gt;--release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Shelldon supports different AI providers such as Ollama, OpenAI, Gemini, Anthropic, and Cohere. You can control which provider to use with the &lt;code&gt;--model&lt;/code&gt; flag. For example, &lt;code&gt;--model claude-3-haiku-20240307&lt;/code&gt; or &lt;code&gt;--model gemini-1.5-flash-latest&lt;/code&gt;. By default, Shelldon uses &lt;code&gt;gpt-4o&lt;/code&gt; as the model.&lt;/p&gt;

&lt;p&gt;To use Shelldon, you need to set your API keys for the mentioned providers. You can do this by setting an environment variable. Here’s how to set it in your terminal:&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;export &lt;/span&gt;&lt;span class="nv"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"api-key"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"api-key"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;COHERE_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"api-key"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GEMINI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"api-key"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Shelldon allows you to integrate GPT features into your shell commands easily. Here are some examples to get you started:&lt;/p&gt;

&lt;h3&gt;
  
  
  Running Shell Commands
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;shelldon &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"Show all the graphics ports for the Vagrant machine using Libvirt."&lt;/span&gt; &lt;span class="nt"&gt;--model&lt;/span&gt; gpt-4o
Command to execute: vagrant ssh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"virsh list --all | grep vagrant | awk '{print &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;1}' | xargs -I {} virsh domdisplay {}"&lt;/span&gt;
? &lt;span class="o"&gt;[&lt;/span&gt;R]un, &lt;span class="o"&gt;[&lt;/span&gt;M]odify, &lt;span class="o"&gt;[&lt;/span&gt;C]opy, &lt;span class="o"&gt;[&lt;/span&gt;A]bort › 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Analyzing Docker Logs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use Shelldon to analyze Docker logs and identify errors:&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="nv"&gt;$ &lt;/span&gt;docker logs nginx | shelldon ask &lt;span class="s2"&gt;"check logs, find errors"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Troubleshooting Kubernetes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Shelldon can help you understand why a Kubernetes pod is failing:&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="nv"&gt;$ &lt;/span&gt;k describe pod nginx | shelldon ask &lt;span class="s2"&gt;"why this pod is failing?"&lt;/span&gt;
The pod is failing because it was terminated due to an &lt;span class="s2"&gt;"Out of Memory"&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;OOM&lt;span class="o"&gt;)&lt;/span&gt; condition. The &lt;span class="sb"&gt;`&lt;/span&gt;OOMKilled&lt;span class="sb"&gt;`&lt;/span&gt; reason indicates that the container running &lt;span class="k"&gt;in &lt;/span&gt;the pod exceeded its memory limit, causing the system to &lt;span class="nb"&gt;kill &lt;/span&gt;the process to prevent it from affecting other processes on the node.

Here are some steps you can take to address this issue:
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Generate configuration files with the help of GPT:&lt;/strong&gt;&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="nv"&gt;$ &lt;/span&gt;shelldon ask &lt;span class="s2"&gt;"Create a basic nginx configuration file"&lt;/span&gt;
Configuration file content:
server &lt;span class="o"&gt;{&lt;/span&gt;
    listen 80&lt;span class="p"&gt;;&lt;/span&gt;
    server_name example.com&lt;span class="p"&gt;;&lt;/span&gt;

    location / &lt;span class="o"&gt;{&lt;/span&gt;
        proxy_pass http://localhost:3000&lt;span class="p"&gt;;&lt;/span&gt;
        proxy_set_header Host &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        proxy_set_header X-Real-IP &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        proxy_set_header X-Forwarded-For &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        proxy_set_header X-Forwarded-Proto &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Automate routine system tasks with ease:&lt;/strong&gt;&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="nv"&gt;$ &lt;/span&gt;shelldon &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"Find and delete all log files older than 30 days in /var/log"&lt;/span&gt;
Command to execute: find /var/log &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.log"&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f &lt;span class="nt"&gt;-mtime&lt;/span&gt; +30 &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;
? &lt;span class="o"&gt;[&lt;/span&gt;R]un, &lt;span class="o"&gt;[&lt;/span&gt;M]odify, &lt;span class="o"&gt;[&lt;/span&gt;C]opy, &lt;span class="o"&gt;[&lt;/span&gt;A]bort › 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Get help with writing meaningful Git commit messages:&lt;/strong&gt;&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="nv"&gt;$ &lt;/span&gt;git diff | shelldon ask &lt;span class="s2"&gt;"Generate a commit message"&lt;/span&gt; &lt;span class="nt"&gt;--copy&lt;/span&gt;
&lt;span class="s2"&gt;"Refactor logging system to improve error handling and performance. This change updates the logging library and adjusts the log levels for better clarity."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use the &lt;code&gt;--copy&lt;/code&gt; command to copy the output directly to your clipboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling Prompts
&lt;/h3&gt;

&lt;p&gt;Shelldon allows you to create, edit, list, and delete custom prompts to streamline your command-line workflows. Here’s how you can manage your prompts:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Command Overview&lt;/strong&gt;&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="nv"&gt;$ &lt;/span&gt;shelldon prompts &lt;span class="nt"&gt;-h&lt;/span&gt;
Usage: shelldon prompts &amp;lt;COMMAND&amp;gt;

Commands:
  create  Create a new prompt
  edit    Edit an existing prompt
  list    List all prompts
  delete  Delete an existing prompt
  &lt;span class="nb"&gt;help    &lt;/span&gt;Print this message or the &lt;span class="nb"&gt;help &lt;/span&gt;of the given subcommand&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;

Options:
  &lt;span class="nt"&gt;-h&lt;/span&gt;, &lt;span class="nt"&gt;--help&lt;/span&gt;  Print &lt;span class="nb"&gt;help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Listing Prompts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To view all the prompts you have created, use the list command:&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="nv"&gt;$ &lt;/span&gt;shelldon prompts list

╭────────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬───────────╮
│ Name       ┆ Content                                                                                                                                                                                                                                                 ┆ Variables │
╞════════════╪═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╪═══════════╡
│ script     ┆ Let’s think step by step and act as a &lt;span class="o"&gt;{&lt;/span&gt;script:bash&lt;span class="o"&gt;}&lt;/span&gt; code scripts expert. Provide only the &lt;span class="o"&gt;{&lt;/span&gt;script&lt;span class="o"&gt;}&lt;/span&gt; script code as output without any descriptions or explanations. Ensure the output is &lt;span class="k"&gt;in &lt;/span&gt;plain text format without Markdown formatting or symbols. If ┆ script    │
│            ┆ details are insufficient, provide the most logical solution. You are not allowed to ask &lt;span class="k"&gt;for &lt;/span&gt;more details. Just print the script directly.                                                                                                               ┆           │
├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ translator ┆ Let’s think step by step and act as a translator. Translate the following text from &lt;span class="o"&gt;{&lt;/span&gt;from:english&lt;span class="o"&gt;}&lt;/span&gt; to &lt;span class="o"&gt;{&lt;/span&gt;to:spanish&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; Make it sound natural to a native speaker of &lt;span class="o"&gt;{&lt;/span&gt;to&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;while &lt;/span&gt;keeping the original tone. Do only minimal edits without changing the tone. ┆ from, to  │
│            ┆ Avoid using fancy words. Reply with only the translated text and nothing &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; Do not provide explanations.                                                                                                                                             ┆           │
├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ note-taker ┆ I am software engineer and I’d like you to look at the following text I wrote and edit it to make it sound more natural to a native English speaker. Do only minimal/minor edits without changing the tone of the text, which should remain the same.   ┆           │
│            ┆ Dont use fancy words and I want you to only reply the correction, the improvements and nothing &lt;span class="k"&gt;else&lt;/span&gt;, &lt;span class="k"&gt;do &lt;/span&gt;not write explanations.                                                                                                                         ┆           │
╰────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴───────────╯
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use the &lt;code&gt;{}&lt;/code&gt; notation to add variables to the prompt, and you can override those values using the &lt;code&gt;--set key=value&lt;/code&gt; option. Additionally, in the prompt template, you can define default values like &lt;code&gt;{from:spanish}&lt;/code&gt;. This allows for flexible and dynamic prompts that can be customized based on user input.&lt;/p&gt;

&lt;p&gt;Then, you can run the ask command with a defined template:&lt;/p&gt;

&lt;p&gt;In my daily routine, I often need to generate bash and python scripts or cloud-init files. &lt;code&gt;shelldon&lt;/code&gt; helps me with this task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;shelldon ask &lt;span class="nt"&gt;--prompt&lt;/span&gt; script &lt;span class="s2"&gt;"Generate a cloud-init script to set up an Ubuntu server with the following steps:
1. Update Ubuntu.
2. Install Nginx.
3. Create a custom HTML file to be served by Nginx.
4. Ensure Nginx is enabled and started."&lt;/span&gt; &lt;span class="nt"&gt;--set&lt;/span&gt; &lt;span class="nv"&gt;script&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cloud-init &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; cloud-init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we can redirect the output directly to a file to create the script.&lt;/p&gt;

&lt;p&gt;Or some translations.&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;alias &lt;/span&gt;&lt;span class="nv"&gt;sat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"shelldon ask --prompt translator"&lt;/span&gt;
sat &lt;span class="s2"&gt;"Hey guys, I'm a few minutes late for the meeting, in less than 5 minutes I'll be there."&lt;/span&gt;
Hola chicos, voy unos minutos tarde para la reunión, en menos de 5 minutos estaré ahí.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also modify the values for the template:&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;alias &lt;/span&gt;&lt;span class="nv"&gt;sat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"shelldon ask --prompt translator"&lt;/span&gt;
sat &lt;span class="s2"&gt;"Chicos voy a llegar 5 minutos tarde a la reunion"&lt;/span&gt; &lt;span class="nt"&gt;--set&lt;/span&gt; &lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;english &lt;span class="nt"&gt;--set&lt;/span&gt; &lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;spanish
Guys, I&lt;span class="s1"&gt;'m going to be 5 minutes late to the meeting.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the ability to handle dynamic prompts with args and use them makes Shelldon a useful tool for me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/douglasmakey/shelldon"&gt;Shelldon&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>openai</category>
      <category>cli</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Networking and Sockets: Endianness</title>
      <dc:creator>Douglas Makey Mendez Molero</dc:creator>
      <pubDate>Fri, 14 Jun 2024 21:11:45 +0000</pubDate>
      <link>https://forem.com/douglasmakey/networking-and-sockets-endianness-4bn8</link>
      <guid>https://forem.com/douglasmakey/networking-and-sockets-endianness-4bn8</guid>
      <description>&lt;p&gt;In my previous article, we introduced some basic concepts about networking and sockets. We discussed different models and created a simple example of network communication using sockets, specifically starting with &lt;code&gt;Stream TCP&lt;/code&gt; sockets.&lt;/p&gt;

&lt;p&gt;We started with this socket type and family because it is one of the most common implementations and the one that the majority of developers work with most frequently. &lt;strong&gt;Stream TCP sockets are widely used due to their reliability and ability to establish a connection-oriented communication channel&lt;/strong&gt;. This makes them ideal for scenarios where data integrity and order are crucial, such as web browsing, email, and file transfers. By understanding the fundamentals of Stream TCP sockets, developers can build robust network applications and troubleshoot issues more effectively.&lt;/p&gt;

&lt;p&gt;In this article, we will continue working with this socket type and dive a bit deeper into socket programming. So far, we have seen how to create a listener socket as a server and how to use another socket to connect to it. Now, we will explore one key detail about this communication, the &lt;code&gt;endianness&lt;/code&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Endianness
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2F_next%2Fimage%3Furl%3D%252Fimages%252Fblog%252Fendianness_had.jpeg%26w%3D2048%26q%3D75" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2F_next%2Fimage%3Furl%3D%252Fimages%252Fblog%252Fendianness_had.jpeg%26w%3D2048%26q%3D75" alt="Image from Hackday"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Endianness refers to the order in which bytes are arranged in memory. In a &lt;code&gt;big-endian&lt;/code&gt; system, the most significant byte is stored at the smallest memory address, while in a &lt;code&gt;little-endian&lt;/code&gt; system, the least significant byte is stored first. Understanding endianness is &lt;strong&gt;"crucial"&lt;/strong&gt; in socket programming because data transmitted over a network may need to be converted between different endianness formats to ensure proper interpretation by different systems. This conversion ensures that the data remains consistent and accurate, regardless of the underlying architecture of the communicating devices.&lt;/p&gt;

&lt;p&gt;In this example, a 32-bit value 1,200,000 (hex &lt;code&gt;0x00124F80&lt;/code&gt;) shows endianness. In a big-endian system, bytes are stored as &lt;code&gt;0x00 0x12 0x4F 0x80&lt;/code&gt; from lowest to highest address. In a little-endian system, the order is reversed: &lt;code&gt;0x80 0x4F 0x12 0x00&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                        Endianness
              (Order of bytes in memory)

                    Big-Endian System
+-----------------+-----------------+-----------------+------------------+
| Most Significant|                 |                 | Least Significant|
| Byte            |                 |                 | Byte             |
| (MSB)           |                 |                 | (LSB)            |
+-----------------+-----------------+-----------------+------------------+
|      0x00       |      0x12       |      0x4F       |      0x80        |
+-----------------+-----------------+-----------------+------------------+
| Address: 0x00   | Address: 0x01   | Address: 0x02   | Address: 0x03    |
+-----------------+-----------------+-----------------+------------------+

                   Little-Endian System
+------------------+-----------------+-----------------+------------------+
| Least Significant|                 |                 | Most Significant |
| Byte             |                 |                 | Byte             |
| (LSB)            |                 |                 | (MSB)            |
+------------------+-----------------+-----------------+------------------+
|      0x80        |      0x4F       |      0x12       |      0x00        |
+------------------+-----------------+-----------------+------------------+
| Address: 0x00    | Address: 0x01   | Address: 0x02   | Address: 0x03    |
+------------------+-----------------+-----------------+------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Imagine you receive  &lt;code&gt;0x00124F80&lt;/code&gt;, and you don’t know if they are in big-endian or little-endian format. If you interpret these bytes using the wrong endianness, you’ll end up with a completely different value. In &lt;code&gt;big-endian&lt;/code&gt; format, the most significant byte comes first, so &lt;code&gt;0x00124F80&lt;/code&gt; remains the same &lt;code&gt;(decimal value: 1,200,000)&lt;/code&gt;. However, in &lt;code&gt;little-endian&lt;/code&gt; format, the bytes are reversed, and the value would be &lt;code&gt;0x804F1200&lt;/code&gt; &lt;code&gt;(decimal value: 2152665600)&lt;/code&gt;. This discrepancy can lead to significant errors in data processing, making it essential to handle endianness correctly.&lt;/p&gt;

&lt;p&gt;To illustrate the concept of endianness with a simpler decimal example, consider the 32-bit value 574. In a big-endian system, the most significant digits are stored first. For 574, the digits are 5, 7, and 4. In a big-endian system, this would be stored as 500 (5 x 100), 70 (7 x 10), and 4 (4 x 1), in that order. In contrast, a little-endian system would store these digits in reverse order: 4 (4 x 1), 70 (7 x 10), and 500 (5 x 100). This reversal can cause the value to be interpreted incorrectly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Network byte order
&lt;/h3&gt;

&lt;p&gt;So for that it’s crucial for machines to agree on endianness when communicating to ensure data is interpreted correctly. For example, in internet communication, standards like &lt;code&gt;RFC 1700&lt;/code&gt; and &lt;code&gt;RFC 9293&lt;/code&gt; define the use of big-endian format, also known as network byte order. This standardization ensures that all devices on the network interpret the data consistently, preventing errors and miscommunication.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;RFC 1700:&lt;br&gt;
The convention in the documentation of Internet Protocols is to express numbers in decimal and to picture data in "big-endian" order ...&lt;/p&gt;

&lt;p&gt;RFC 9293:&lt;br&gt;
Source Address: the IPv4 source address in network byte order&lt;br&gt;
Destination Address: the IPv4 destination address in network byte order&lt;/p&gt;

&lt;p&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc768" rel="noopener noreferrer"&gt;https://datatracker.ietf.org/doc/html/rfc768&lt;/a&gt;&lt;br&gt;
&lt;a href="https://datatracker.ietf.org/doc/html/rfc1700" rel="noopener noreferrer"&gt;https://datatracker.ietf.org/doc/html/rfc1700&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Machine agreements
&lt;/h3&gt;

&lt;p&gt;If your application defines a protocol that specifies byte order, both the sender and receiver must adhere to this protocol. If the protocol specifies that certain fields in the data should be in network byte order, then you must convert those fields accordingly. Many application data formats that rely on &lt;code&gt;plain text&lt;/code&gt; such as &lt;code&gt;JSON&lt;/code&gt; and &lt;code&gt;XML&lt;/code&gt; are either byte order independent (treating data as strings of bytes) or have their own specifications for encoding and decoding multi-byte values.&lt;/p&gt;

&lt;p&gt;Endianness only applies to &lt;code&gt;multi-byte&lt;/code&gt; values, meaning it affects how sequences of bytes representing larger data types (like integers and floating-point numbers) are ordered. Single-byte values are not affected by endianness. &lt;/p&gt;

&lt;p&gt;For example, in Rust, the crates &lt;code&gt;bincode&lt;/code&gt; and &lt;code&gt;postcard&lt;/code&gt; use &lt;code&gt;little-endian&lt;/code&gt; by default. This means that when you serialize data using these crates, multi-byte values will be ordered in little-endian format unless specified otherwise.&lt;/p&gt;

&lt;h3&gt;
  
  
  Socket address for binding
&lt;/h3&gt;

&lt;p&gt;If you have read or watched anything about socket programming, it is almost certain that you have encountered some &lt;code&gt;C&lt;/code&gt; examples. For instance, you might have seen something like the following code. This is because, as we learned earlier, IP addresses and ports need to be in big-endian format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sin_family&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AF_INET&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sin_addr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;s_addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;htonl&lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt;
&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sin_port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;htons&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sockfd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;sockaddr&lt;/span&gt; &lt;span class="o"&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;address&lt;/span&gt;&lt;span class="p"&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="n"&gt;address&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;These functions &lt;code&gt;htons&lt;/code&gt; and &lt;code&gt;htonl&lt;/code&gt; is part of a series of &lt;code&gt;C&lt;/code&gt; helper functions that help convert &lt;code&gt;multi-byte&lt;/code&gt; values to the host byte order. These functions ensure that data is correctly interpreted regardless of the underlying system’s endianness.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The htonl() function converts the unsigned integer hostlong from host byte order to network byte order.
The htons() function converts the unsigned short integer hostshort from host byte order to network byte order.
The ntohl() function converts the unsigned integer netlong from network byte order to host byte order.
The ntohs() function converts the unsigned short integer netshort from network byte order to host byte order.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modern programming languages and frameworks typically handle these formats for you and also offer specialized functions to manage them. For example, if we revisit our previous socket server example in Rust, we will see the following when creating the address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;server_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;SockaddrIn&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1:8080"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the previous line, we don’t have to deal with byte ordering due to the implementation. However, we can inspect the address to determine the default byte ordering on our machine, which is little-endian in my case. We can also convert it to big-endian, as required for the IP address and port.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create a socket address&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;sock_addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;SockaddrIn&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1:6797"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;sockaddr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sockaddr_in&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sock_addr&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"sockaddr: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sockaddr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"s_addr Default: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sockaddr&lt;/span&gt;&lt;span class="py"&gt;.sin_addr.s_addr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// big endian&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"s_addr be: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sockaddr&lt;/span&gt;&lt;span class="py"&gt;.sin_addr.s_addr&lt;/span&gt;&lt;span class="nf"&gt;.to_be&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="c1"&gt;// little endian&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"s_addr le: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sockaddr&lt;/span&gt;&lt;span class="py"&gt;.sin_addr.s_addr&lt;/span&gt;&lt;span class="nf"&gt;.to_le&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we run this code, we get the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cargo run --bin addr
sockaddr: sockaddr_in { sin_len: 16, sin_family: 2, sin_port: 36122, sin_addr: in_addr { s_addr: 16777343 }, sin_zero: [0, 0, 0, 0, 0, 0, 0, 0] }
s_addr Default: 16777343
s_addr be: 2130706433
s_addr le: 16777343
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we mentioned, although Rust and other modern programming languages handle byte ordering i some levels and offer convenient abstractions, it’s always valuable to understand these foundational concepts. &lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Example: Handling Endianness in Client-Server Communication
&lt;/h2&gt;

&lt;p&gt;Now that we know about byte ordering, we are going to create a simple example to illustrate what we have covered so far. For this, we will create a simple program that receives a file from a socket. The client will first send the size of the file, and then it will send the data of the file. Note that this will be a straightforward implementation, keeping the code simple to illustrate this concept.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server
&lt;/h3&gt;

&lt;p&gt;We are going to re-use the code from the last article about creating a socket server of type stream and INET family. We will create a simple function to set up this socket server and return the file descriptor. This will help us maintain a clean implementation and reuse it in all future examples. The function is named &lt;code&gt;create_tcp_server_socket&lt;/code&gt;, and it is quite simple, as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;create_tcp_server_socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OwnedFd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;nix&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;socket_fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nn"&gt;nix&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;AddressFamily&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Inet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Socket family&lt;/span&gt;
        &lt;span class="nn"&gt;nix&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;SockType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// Socket type&lt;/span&gt;
        &lt;span class="nn"&gt;nix&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;SockFlag&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&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="c1"&gt;// Create a socket address&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;sock_addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;SockaddrIn&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Bind the socket to the address&lt;/span&gt;
    &lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket_fd&lt;/span&gt;&lt;span class="nf"&gt;.as_raw_fd&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;sock_addr&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="c1"&gt;// Listen for incoming connections&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;backlog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Backlog&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&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="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;listen&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;socket_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;backlog&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="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket_fd&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;Now we can use that function to create a server socket and accept incoming connections.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;socket_fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_tcp_server_socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1:8000"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Accept incoming connections&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;conn_fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket_fd&lt;/span&gt;&lt;span class="nf"&gt;.as_raw_fd&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&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;Next, after accepting the connection, we expect to receive the size of the file that the client will transmit over the network. We expect to receive a 32-bit unsigned integer, so we prepare a 4-byte buffer to receive the size. We then read from the socket and put the data in the buffer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Receive the size of the file&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;size_buf&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;size_buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;MsgFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;file_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_ne_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size_buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"File size: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you notice, we are using &lt;code&gt;from_ne_bytes&lt;/code&gt; here. This function assumes that the bytes are arranged in the native endianness of our machine &lt;code&gt;(ne stands for native endianness)&lt;/code&gt;. Therefore, we expect that the value is using the same endianness as our machine.&lt;/p&gt;

&lt;p&gt;Finally, we will use that size to create an in-memory buffer to receive the file’s data over the connection and print the bytes read. As mentioned, this is a naive and basic implementation just to illustrate the case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Receive the file data&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;file_buf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&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="n"&gt;file_size&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;bytes_read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;file_buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;MsgFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"File data bytes read: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes_read&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;nix&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MsgFlags&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;socket_net&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;server&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;create_tcp_server_socket&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;os&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AsRawFd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;socket_fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_tcp_server_socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1:8000"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Accept incoming connections&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;conn_fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket_fd&lt;/span&gt;&lt;span class="nf"&gt;.as_raw_fd&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Receive the size of the file&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;size_buf&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;size_buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;MsgFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;file_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_ne_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size_buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"File size: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Receive the file data&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;file_buf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&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="n"&gt;file_size&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;bytes_read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;file_buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;MsgFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"File data bytes read: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes_read&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;h3&gt;
  
  
  Client
&lt;/h3&gt;

&lt;p&gt;For our client, the logic is again pretty simple and similar to what we had before, but with some subtle additions, like reading the file and sending its size before sending the actual data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="n"&gt;creation&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;
&lt;span class="c1"&gt;// Read the file into a buffer&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"./src/data/data.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to read file"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// send the size of the file to the server&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;socket_fd&lt;/span&gt;&lt;span class="nf"&gt;.as_raw_fd&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;size&lt;/span&gt;&lt;span class="nf"&gt;.to_ne_bytes&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;MsgFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// send the file to the server&lt;/span&gt;
&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket_fd&lt;/span&gt;&lt;span class="nf"&gt;.as_raw_fd&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;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;MsgFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&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 things to notice: as we mentioned earlier, we create a u32 for the file size and we are using the function &lt;code&gt;to_ne_bytes&lt;/code&gt; to send bytes arranged in the native endianness, which in my case is little-endian.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;data.txt&lt;/code&gt; file is a simple text file containing some lorem ipsum data. We can inspect its size using the stat command:&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;stat&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt;%s ./src/data/data.txt 
574
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are wondering why we have to deal with endianness for the size but not for the file content itself, remember what we learned earlier:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Many application data formats that relies on plain text, are either byte order independent (treating data as strings of bytes)  or ...&lt;/p&gt;
&lt;h3&gt;
  
  
  Running
&lt;/h3&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we can run our server and client to see the output and understand how it works. The size of the file is 574 bytes, and we send the entire file.&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="c"&gt;# Server&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;cargo run &lt;span class="nt"&gt;--bin&lt;/span&gt; tcp-file-server
Socket file descriptor: 3
Socket bound to address: 127.0.0.1:8000
File size: 574
File data bytes &lt;span class="nb"&gt;read&lt;/span&gt;: 574
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Client&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;cargo run &lt;span class="nt"&gt;--bin&lt;/span&gt; tcp-file-client
Socket file descriptor: 3
Sending file size: 574
Sending file data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far, so good, right? The behavior is as expected: we are sending a file with 574 bytes, and we are receiving that in the server. This works because both the client and server are using &lt;code&gt;ne (native endianness)&lt;/code&gt;, and since they are on the same machine, they are both using little-endian. But what if the client uses a different endianness? What if it sends the size using &lt;code&gt;big-endian&lt;/code&gt;, for example?&lt;/p&gt;

&lt;p&gt;We can simulate what will happen by modifying this line in the client to instruct it to send the data in big-endian instead of little-endian. For that, we use &lt;code&gt;to_be_bytes&lt;/code&gt; (be stands for big-endian):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;socket_fd&lt;/span&gt;&lt;span class="nf"&gt;.as_raw_fd&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;size&lt;/span&gt;&lt;span class="nf"&gt;.to_be_bytes&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;MsgFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we run our programs again, we will see why understanding endianness is important. From the client’s perspective, we are sending the same value, just in a different endianness. However, if you look at our server, you will notice the issue:&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="c"&gt;# Client&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;cargo run &lt;span class="nt"&gt;--bin&lt;/span&gt; tcp-file-client
Socket file descriptor: 3
Sending file size: 574
Sending file data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server still treats the size as if it is coming in the same endianness, which is little-endian. But it is not little-endian anymore; it is big-endian. This results in a totally different and incorrect value. In this simple case, it causes the server to allocate much more memory than needed for the buffer to receive the file. You can imagine that in more complex scenarios, this issue could have a much larger and more serious impact.&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="c"&gt;# Server&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;cargo run &lt;span class="nt"&gt;--bin&lt;/span&gt; tcp-file-server
Socket file descriptor: 3
Socket bound to address: 127.0.0.1:8000
File size: 1040318464
File data bytes &lt;span class="nb"&gt;read&lt;/span&gt;: 574
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if we were using our native OS bit size, like a 64-bit integer in my case, and used a u64 type for the size variable in both the client and server, the issue could be even worse. We can modify the following lines in the client and server and see the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// server&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;size_buf&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="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;file_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_ne_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size_buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// client&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After making these changes, let’s run the server and client again:&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="c"&gt;# Server&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;cargo run &lt;span class="nt"&gt;--bin&lt;/span&gt; tcp-file-server
Socket file descriptor: 3
Socket bound to address: 127.0.0.1:8000
File size: 4468133780304953344
memory allocation of 4468133780304953344 bytes failed
Aborted &lt;span class="o"&gt;(&lt;/span&gt;core dumped&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, the multi-byte representation of the integer is larger, and the value representation becomes colossal in the wrong byte order. Here, the server tries to allocate about 4.4 exabytes of memory, which is far more than what’s available on any current machine. This illustrates how critical it is to handle endianness correctly, as incorrect handling can lead to severe issues like memory allocation failures and program crashes.&lt;/p&gt;

&lt;p&gt;You can find the code for this example and future ones in this &lt;a href="https://github.com/douglasmakey/socket_net" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  To Conclude
&lt;/h2&gt;

&lt;p&gt;Understanding endianness is crucial for developing robust network applications. As demonstrated, even a simple task like sending a file over a network can lead to significant issues if endianness is not handled correctly. By adhering to standards and properly managing byte order, we ensure that data is accurately interpreted across different systems, preventing errors and enhancing the reliability of our applications. Modern programming languages like Rust provide helpful abstractions, but a solid grasp of these foundational concepts allows developers to troubleshoot and optimize their code more effectively. Always be mindful of endianness when working with multi-byte values in network communication to avoid potential pitfalls.&lt;/p&gt;

&lt;p&gt;Thank you for reading along. This blog is a part of my learning journey and your feedback is highly valued. There's more to explore and share regarding socket and network, so stay tuned for upcoming posts. Your insights and experiences are welcome as we learn and grow together in this domain. &lt;strong&gt;Happy coding!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>rust</category>
      <category>networking</category>
      <category>socket</category>
    </item>
    <item>
      <title>Getting Started with Networking and Sockets</title>
      <dc:creator>Douglas Makey Mendez Molero</dc:creator>
      <pubDate>Fri, 07 Jun 2024 20:02:59 +0000</pubDate>
      <link>https://forem.com/douglasmakey/getting-started-with-networking-and-sockets-403m</link>
      <guid>https://forem.com/douglasmakey/getting-started-with-networking-and-sockets-403m</guid>
      <description>&lt;p&gt;In the realm of software development and network engineering, understanding the fundamentals of sockets and networking is invaluable, regardless of your specific focus within the industry. This article aims to provide a comprehensive overview of these essential concepts, facilitating a clearer understanding of their importance and functionality for engineers. Let's delve into the basics and uncover the foundational principles that drive modern networking.&lt;/p&gt;

&lt;p&gt;To keep things simple, we will start with basic examples and gradually introduce more complexity. This approach allows us to build a strong foundation without getting overwhelmed. In future articles, we will explore more advanced topics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the OSI and TCP/IP Models: Foundations of Networking
&lt;/h2&gt;

&lt;h3&gt;
  
  
  OSI model
&lt;/h3&gt;

&lt;p&gt;We can't start discussing basic networking concepts without mentioning our old friend, the OSI model. For two computers to communicate effectively, they need to speak the same language, structured by the OSI model. This foundational framework has been a cornerstone in understanding and implementing network communications. By breaking down the complex process of data transmission into seven manageable layers, the OSI model provides a clear and organized approach to networking that has stood the test of time.&lt;/p&gt;

&lt;p&gt;The OSI model simplifies the complex process of data transmission by providing a universal language for networking. Each layer of the OSI model has specific responsibilities and capabilities, ensuring that technologies can interact seamlessly. Higher layers benefit from this abstraction, utilizing lower-layer functions without needing to understand their inner workings.&lt;/p&gt;

&lt;h3&gt;
  
  
  OSI model layers
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2Fimages%2Fblog%2F101osi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2Fimages%2Fblog%2F101osi.png" alt="Osi model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Physical Layer&lt;/strong&gt;: This is the lowest layer, dealing with the physical connection between devices. It is responsible for transmitting raw bit streams over a physical medium, such as cables or wireless signals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data-Link Layer&lt;/strong&gt;: This layer manages the transfer of data between two directly connected nodes. It handles error detection and correction, as well as flow control, ensuring reliable communication over the physical medium.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Layer&lt;/strong&gt;: This layer is responsible for routing data from the source to the destination across multiple networks. It uses logical addressing (such as IP addresses) to determine the best path for data transmission.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transport Layer&lt;/strong&gt;: This layer ensures reliable data transfer between systems. It provides error detection and recovery, flow control, and ensures complete data transfer through protocols like TCP (Transmission Control Protocol).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session Layer&lt;/strong&gt;: This layer manages sessions between applications. It establishes, maintains, and terminates connections, ensuring data is synchronized and properly sequenced.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Presentation Layer&lt;/strong&gt;: This layer translates data between the application layer and the network. It handles data encryption, compression, and translation, ensuring that data is presented in a readable format.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application Layer&lt;/strong&gt;: This is the topmost layer, which interacts directly with user applications. It provides network services to end-user applications, such as web browsers and email clients.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Have you ever heard the joke about Layer 8? If not, for those who enjoy a bit of networking humor, there's often mention of "Layer 8" — the user layer. It's a playful reminder that no matter how perfect the technical setup, the human element can introduce its own unique challenges!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When data is communicated through protocol layers, it's sent in small segments called packets. Each packet includes implementations from these protocol layers. Starting at the application layer, the data is encapsulated by the presentation layer, which is then encapsulated by the session layer, followed by the transport layer, and so on. This process is known as encapsulation.&lt;/p&gt;

&lt;p&gt;Each layer adds a header and a body to the packet. The header contains protocol-specific information necessary for that layer, while the body contains the encapsulated data, including headers from the previous layers. This encapsulation technique can be visualized like the layers of an onion.&lt;/p&gt;

&lt;p&gt;The illustration below demonstrates the encapsulation process as data moves from the application layer of one computer, across the Internet, to the application layer of the other computer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   Computer A Application                Computer B Application
       |                                      ▲
       ▼                                      |
   +---------------------+                +---------------------+
   | 7. Application      |                | 1. Physical         |
   +---------------------+                +---------------------+
       |                                      |
   +---------------------+                +---------------------+
   | 6. Presentation     |                | 2. Data-Link        |
   +---------------------+                +---------------------+
       |                                      |
   +---------------------+                +---------------------+
   | 5. Session          |                | 3. Network          |
   +---------------------+                +---------------------+
       |                                      |
   +---------------------+                +---------------------+
   | 4. Transport        |                | 4. Transport        |
   +---------------------+                +---------------------+
       |                                      |
   +---------------------+                +---------------------+
   | 3. Network          |                | 5. Session          |
   +---------------------+                +---------------------+
       |                                      |
   +---------------------+                +---------------------+
   | 2. Data-Link        |                | 6. Presentation     |
   +---------------------+                +---------------------+
       |                                      |
   +---------------------+                +---------------------+
   | 1. Physical         |                | 7. Application      |
   +---------------------+                +---------------------+
       |                                      |
       +--------------------------------------+
       |              Internet                |
       +--------------------------------------+

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TCP/IP as an Alternative to the OSI Model
&lt;/h3&gt;

&lt;p&gt;While the OSI model provides a detailed framework for understanding network communications, TCP/IP is the more practical and widely-used model in real-world networking. TCP/IP simplifies the structure into four layers and serves as the foundation for the Internet, emphasizing robust, scalable communication across diverse networks.&lt;/p&gt;

&lt;p&gt;Imagine you want to visit a website by entering a URL into your browser. Here’s how TCP/IP handles this request:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Application Layer&lt;/strong&gt;: Your web browser (application) generates an HTTP request for the webpage. In the TCP/IP model, the Application layer combines the functions of the Application, Presentation, and Session layers of the OSI model. This means it handles not only the user interface and communication protocols (Application layer in OSI), but also data translation, encryption, and compression (Presentation layer in OSI), as well as managing sessions and dialogues between the devices (Session layer in OSI). This consolidation simplifies the model and aligns it more closely with real-world protocols and applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transport Layer&lt;/strong&gt;: The HTTP request is handed to the TCP protocol, which breaks it into smaller packets, adds a header with port information, and ensures reliable transmission. This layer matches the Transport layer in the OSI model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internet Layer&lt;/strong&gt;: Each packet is then passed to the IP protocol, which adds another header containing the IP addresses of both the source (your computer) and the destination (the web server). This layer corresponds to the Network layer in the OSI model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Access Layer&lt;/strong&gt;: The packets are then sent over the physical network (like Ethernet or Wi-Fi), where they travel through various routers and switches to reach the web server. This layer combines the Data Link and Physical layers of the OSI model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both the OSI and TCP/IP models are open standards. They’re designed so that anyone can use them, or further build them out to meet specific requirements.&lt;/p&gt;

&lt;p&gt;Programs that use networking, such as web browsers and email clients, rely on the operating system to manage network communications. The operating system handles the intricate details of network encapsulation, making it easier for developers to write network programs. They simply need to use the network interface provided by the OS, without worrying about the underlying complexities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Sockets for communication
&lt;/h2&gt;

&lt;p&gt;To interface with the network or &lt;code&gt;enable inter-process communication&lt;/code&gt; (IPC), developers often use sockets. Sockets serve as standardized endpoints for sending and receiving data, whether across a network or between processes on the same machine. They provide a way for programs to communicate, abstracting the complexities of the underlying protocol layers. By using socket APIs provided by the operating system, developers can focus on building their application logic while the OS manages the detailed network and IPC operations. This makes tasks like creating a web server, a chat application, or facilitating communication between processes more straightforward and accessible. The most common types of sockets are stream sockets, which provide a reliable connection-oriented service, and datagram sockets, which offer a connectionless service.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For IPC communication offered by the Unix domain socket using the &lt;code&gt;AF_UNIX&lt;/code&gt; family, we already explore this in the article below. We may explore it again from another perspective in future parts of this article.&lt;br&gt;
&lt;a href="https://www.kungfudev.com/blog/2022/12/05/understanding-unix-domain-sockets-in-golang" rel="noopener noreferrer"&gt;https://www.kungfudev.com/blog/2022/12/05/understanding-unix-domain-sockets-in-golang&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;Stream sockets&lt;/code&gt; and &lt;code&gt;datagram sockets&lt;/code&gt; are the two most common types of sockets. Stream sockets, which use the TCP protocol, provide a reliable, connection-oriented service. This means that data is transmitted in a continuous stream, ensuring that it arrives in the correct order and without errors. Examples of stream sockets in action include web servers, where the integrity and order of the data (such as HTML pages) are crucial for proper rendering, and email clients, which require reliable data transmission to ensure messages are received intact. In contrast, datagram sockets use the UDP protocol and offer a connectionless service. This allows for faster data transmission but without the guarantees of order and reliability. An example of datagram sockets is in online gaming or live video streaming, where speed is more critical than perfect data accuracy, and occasional data loss is acceptable.&lt;/p&gt;

&lt;p&gt;I would bet that at least once you have seen the image below while learning about networking, sockets, or reading some network articles. This diagram illustrates the basic flow of socket communication between a server and a client, highlighting the key function calls and interactions involved in establishing a connection and exchanging data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2Fimages%2Fblog%2Fsocket-flow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kungfudev.com%2Fimages%2Fblog%2Fsocket-flow.png" alt="Socket flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sockets behave similarly to files because of the Unix philosophy of treating everything as a file. This design choice provides a consistent interface for performing input and output operations across different types of data streams, simplifying the programming model.&lt;/p&gt;

&lt;p&gt;Sockets and files both provide a stream of bytes that can be read from or written to. This stream abstraction fits well with many types of I/O operations, whether they involve local files, remote network communication, or inter-process communication.&lt;/p&gt;

&lt;p&gt;When a socket is created with the &lt;code&gt;socket()&lt;/code&gt; function, it requires parameters such as the domain (e.g., &lt;code&gt;AF_INET&lt;/code&gt; for IPv4), the type (e.g., &lt;code&gt;SOCK_STREAM&lt;/code&gt; for TCP), and the protocol (usually 0 to select the default protocol for the given type). The socket is then assigned a file descriptor, an integer that uniquely identifies the socket within the operating system.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A file descriptor is a unique integer assigned by the operating system to an open file or socket, serving as an abstract indicator for accessing various I/O resources, such as files, sockets, and pipes. In simple terms, when you open a file, the operating system creates an entry to represent that file and stores information about it. If there are N files open, there will be N corresponding entries in the operating system, each represented by an integer like 20, 21, etc. This integer is the file descriptor. It uniquely identifies an open file within a process, allowing the process to perform operations like reading, writing, and closing files using standardized functions. By managing resources this way, the operating system ensures efficient communication between processes and I/O resources.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.lenovo.com/ca/en/glossary/file-descriptor/" rel="noopener noreferrer"&gt;More info&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;bind()&lt;/code&gt; function associates the socket with a specific local &lt;code&gt;address&lt;/code&gt; and &lt;code&gt;port&lt;/code&gt;, which are provided as arguments. The &lt;code&gt;listen()&lt;/code&gt; function marks the socket as a passive socket that will be used to accept incoming connection requests, taking an argument that specifies the maximum number of pending connections. The &lt;code&gt;accept()&lt;/code&gt; function extracts the first connection request on the &lt;code&gt;queue of pending connections&lt;/code&gt;, creating a new socket &lt;code&gt;file descriptor&lt;/code&gt; for the connection.&lt;/p&gt;

&lt;p&gt;On the client side, the &lt;code&gt;connect()&lt;/code&gt; function is used to establish a connection to the server, requiring the server's address and port as arguments. Both the client and server can then use &lt;code&gt;send()&lt;/code&gt; and &lt;code&gt;recv()&lt;/code&gt;, or the analogous &lt;code&gt;write()&lt;/code&gt; and &lt;code&gt;read()&lt;/code&gt;, to transmit and receive data. The &lt;code&gt;close()&lt;/code&gt; function is used to close the socket, releasing the file descriptor.&lt;/p&gt;

&lt;p&gt;This design simplifies the API and makes it easier for developers to handle network communication using familiar file operations, streamlining the development process and making the code more intuitive and maintainable. By treating sockets as files, the operating system can efficiently manage various types of I/O operations using a unified interface, leveraging existing mechanisms for buffering, blocking, and error handling that are well-established for file systems.&lt;/p&gt;

&lt;p&gt;As we mentioned, there are a couple of socket &lt;a href="https://man7.org/linux/man-pages/man2/socket.2.html" rel="noopener noreferrer"&gt;types and families&lt;/a&gt;, but for now, for socket families we are going to focus on &lt;code&gt;AF_INET&lt;/code&gt; for IPv4, &lt;code&gt;AF_INET6&lt;/code&gt; for IPv6, and as we mentioned the &lt;code&gt;AF_UNIX&lt;/code&gt; for local communication within the same host. And regarding type, we will discuss the two primary types of sockets: stream sockets and datagram sockets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Socket in Actions
&lt;/h3&gt;

&lt;p&gt;To illustrate what we have learned so far, we will write a couple of programs in Rust. We will use the &lt;code&gt;nix&lt;/code&gt; crate, which provides friendly unix platform APIs (Linux, Darwin) for working with the socket API. While the Rust standard library offers standard socket functionality in the &lt;code&gt;std&lt;/code&gt;, the &lt;code&gt;nix&lt;/code&gt; crate provides more comprehensive and idiomatic access to lower-level unix system calls, making it easier to work with advanced socket features and perfect for explaining what we have seen until now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server
&lt;/h3&gt;

&lt;p&gt;So as we saw previously, to create a server the sequence of functions are: &lt;code&gt;socket()&lt;/code&gt;, &lt;code&gt;bind()&lt;/code&gt;, &lt;code&gt;listen()&lt;/code&gt;, and &lt;code&gt;accept()&lt;/code&gt;. The first step is to create the socket.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;socket_fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nn"&gt;nix&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;AddressFamily&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Inet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Socket family&lt;/span&gt;
    &lt;span class="nn"&gt;nix&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;SockType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// Socket type&lt;/span&gt;
    &lt;span class="nn"&gt;nix&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;SockFlag&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to create socket"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code snippet creates a new socket using the &lt;code&gt;nix&lt;/code&gt; crate in Rust. The &lt;code&gt;socket()&lt;/code&gt; function call includes several parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;nix::sys::socket::AddressFamily::Inet&lt;/code&gt;: Specifies the socket family, in this case, &lt;code&gt;AF_INET&lt;/code&gt;, which is used for IPv4 addresses.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nix::sys::socket::SockType::Stream&lt;/code&gt;: Specifies the socket type, &lt;code&gt;SOCK_STREAM&lt;/code&gt;, which indicates a stream socket using the TCP protocol.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nix::sys::socket::SockFlag::empty()&lt;/code&gt;: Indicates that no special flags are set for the socket.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;None&lt;/code&gt;: Indicates that the default protocol should be used.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After creating the socket, the next step is to bind the socket to a specific address and port. This associates the socket with a particular local endpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create a socket address&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;sock_addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nn"&gt;SockaddrIn&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1:6797"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to create socket address"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Bind the socket to the address&lt;/span&gt;
&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket_fd&lt;/span&gt;&lt;span class="nf"&gt;.as_raw_fd&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;sock_addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to bind socket"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code snippet binds the previously created socket to the local address &lt;code&gt;127.0.0.1&lt;/code&gt; (localhost) and port &lt;code&gt;6797&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SockaddrIn::from_str("127.0.0.1:6797")&lt;/code&gt;: Creates a new socket address (&lt;code&gt;SockaddrIn&lt;/code&gt;) from the string representation of the IPv4 address and port.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bind(socket_fd.as_raw_fd(), &amp;amp;sock_addr)&lt;/code&gt;: Binds the socket file descriptor to the specified address. This makes the socket listen for incoming connections on &lt;code&gt;127.0.0.1:6797&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Something to notice here is that we are using IP addresses and ports in a specific format because we are using &lt;code&gt;AddressFamily::Inet&lt;/code&gt;. Different protocol families have their own ways of defining endpoint addresses. This means the address format can vary depending on the address family, allowing sockets to handle different networking protocols and address formats properly. For this article, we are focusing on the INET family, but in future articles, we will explore other address families in more detail.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After binding the socket to a specific address and port, the next step is to listen for incoming connections. This prepares the socket to accept connection requests from clients.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Listen for incoming connections&lt;/span&gt;
&lt;span class="c1"&gt;// The backlog parameter specifies the maximum length of the queue of pending connections&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;backlog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Backlog&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&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="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to create backlog"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;listen&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;socket_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;backlog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to listen for connections"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code snippet sets up the socket to listen for incoming connections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;let backlog = Backlog::new(1).expect("Failed to create backlog");&lt;/code&gt;: This line creates a backlog object that specifies the maximum length of the queue of pending connections. In this case, the backlog is set to 1, meaning the socket can queue up to one pending connection.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;listen(&amp;amp;socket_fd, backlog).expect("Failed to listen for connections");&lt;/code&gt;: This line calls the &lt;code&gt;listen()&lt;/code&gt; function, which puts the socket into listening mode.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;We use a backlog of 1 because we are keeping the example simple and synchronous for now. In the future, we will introduce an asynchronous runtime to handle multiple connections more efficiently.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;listen&lt;/code&gt; operation involves the kernel creating two queues for this socket: the &lt;strong&gt;syn&lt;/strong&gt; queue and the &lt;strong&gt;accept&lt;/strong&gt; queue. To keep this article concise, we will explore these queues in detail in the next article.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At this point, the server socket is ready and waiting for incoming connection requests from clients. The &lt;code&gt;listen()&lt;/code&gt; function allows the server to queue incoming connections, which can be accepted and processed one by one.&lt;/p&gt;

&lt;p&gt;Once the server socket is set to listen for incoming connections, the next step is to accept these connections and handle the data communication with the client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Accept incoming connections&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;conn_fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket_fd&lt;/span&gt;&lt;span class="nf"&gt;.as_raw_fd&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to accept connection"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Read data&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;bytes_read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to read from connection"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;received_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;str&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_utf8&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;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;bytes_read&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to convert received data to string"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"Received {} bytes: {:?} repr: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;bytes_read&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;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;bytes_read&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;received_data&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code snippet demonstrates how to accept an incoming connection and read data from it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;let conn_fd = accept(socket_fd.as_raw_fd()).expect("Failed to accept connection");&lt;/code&gt;: This line calls the &lt;code&gt;accept()&lt;/code&gt; function to accept an incoming connection. It creates a new socket file descriptor for the connection, &lt;code&gt;conn_fd&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;let mut buf = [0u8; 1024];&lt;/code&gt;: This line initializes a buffer to store the incoming data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;let bytes_read = recv(conn_fd, &amp;amp;mut buf, MsgFlags::empty()).expect("Failed to read from connection");&lt;/code&gt;: This line reads data from the accepted connection into the buffer. The &lt;code&gt;recv()&lt;/code&gt; function is used for this purpose, with &lt;code&gt;MsgFlags::empty()&lt;/code&gt; indicating no special flags. The number of bytes read is stored in &lt;code&gt;bytes_read&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;let received_data = std::str::from_utf8(&amp;amp;buf[..bytes_read]).expect("Failed to convert received data to string");&lt;/code&gt;: This line converts the received byte data into a UTF-8 string. It slices the buffer up to the number of bytes read and converts it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, the server has accepted an incoming connection and read the data sent by the client. The server can then process this data, echo it back, or perform other actions based on the application logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;bytes_written&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn_fd&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;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;bytes_read&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nn"&gt;MsgFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to write to connection"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code snippet demonstrates how to send data back to the client:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;let bytes_written = send(conn_fd, &amp;amp;buf[..bytes_read], MsgFlags::empty()).expect("Failed to write to connection");&lt;/code&gt;: This line sends data from the buffer back to the client using the &lt;code&gt;send()&lt;/code&gt; function. The buffer is sliced to the number of bytes read from the client, ensuring only the received data is sent back. &lt;code&gt;MsgFlags::empty()&lt;/code&gt; indicates no special flags are used.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;For simplicity, we are using &lt;code&gt;MsgFlags::empty()&lt;/code&gt;, which indicates no special options are set, allowing the &lt;code&gt;send()&lt;/code&gt; and &lt;code&gt;recv()&lt;/code&gt; functions to operate in their default  mode. To read more about these &lt;a href="https://man7.org/linux/man-pages/man2/sendto.2.html" rel="noopener noreferrer"&gt;flags &lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With this step, the server echoes the received data back to the client, completing a simple round-trip communication. This demonstrates the basic flow of data from client to server and back to client, showcasing the core operations of socket communication.&lt;/p&gt;

&lt;p&gt;So putting it all together, we have the complete example for this simple TCP echo. We’ve explained each step, as discussed previously:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;socket_fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nn"&gt;nix&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;AddressFamily&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Inet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Socket family&lt;/span&gt;
        &lt;span class="nn"&gt;nix&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;SockType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// Socket type&lt;/span&gt;
        &lt;span class="nn"&gt;nix&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;SockFlag&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to create socket"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a socket address&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;sock_addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nn"&gt;SockaddrIn&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1:6797"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to create socket address"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Bind the socket to the address&lt;/span&gt;
    &lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket_fd&lt;/span&gt;&lt;span class="nf"&gt;.as_raw_fd&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;sock_addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to bind socket"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Listen for incoming connections&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;backlog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Backlog&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&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="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to create backlog"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;listen&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;socket_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;backlog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to listen for connections"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Accept incoming connections&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;conn_fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket_fd&lt;/span&gt;&lt;span class="nf"&gt;.as_raw_fd&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to accept connection"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// echo back the received data&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;bytes_read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;MsgFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed ... connection"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;received_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;str&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_utf8&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;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;bytes_read&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to ..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Echo back the received data&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;bytes_written&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn_fd&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;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;bytes_read&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nn"&gt;MsgFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to write to connection"&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;blockquote&gt;
&lt;p&gt;In Rust, we do not explicitly use the &lt;code&gt;close&lt;/code&gt; method to close sockets because Rust's ownership and borrowing system automatically handles resource management. When a socket goes out of scope, Rust's memory safety guarantees ensure that the socket is properly closed and resources are freed. This eliminates the need for explicit &lt;code&gt;close&lt;/code&gt; calls, reducing the risk of resource leaks and making the code cleaner and safer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most programming languages provide higher-level abstractions to simplify socket programming, making it more accessible and easier to use. These abstractions often wrap the underlying system calls, handling details, and resource management for you. For example, in Rust, the &lt;code&gt;std::net&lt;/code&gt; module offers a convenient API for TCP networking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;net&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;TcpListener&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;TcpListener&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1:7878"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="nf"&gt;.incoming&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connection established!"&lt;/span&gt;&lt;span class="p"&gt;);&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;In this example, &lt;code&gt;TcpListener::bind&lt;/code&gt; abstracts the complexity of creating and binding a socket, ensuring that the address is correctly formatted ""and byte-ordered."" The &lt;code&gt;incoming&lt;/code&gt; method returns an iterator over incoming connections, managing the accept loop. This abstraction makes the code more readable and easier to maintain, allowing us to focus on the application logic rather than the intricacies of socket communication.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running the server
&lt;/h3&gt;

&lt;p&gt;Now, if we run the server and use &lt;code&gt;telnet&lt;/code&gt; from another terminal, we will see this in action:&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="nv"&gt;$ &lt;/span&gt;cargo run part-one-server
Socket file descriptor: 3
Socket bound to address: 127.0.0.1:6797
Listening &lt;span class="k"&gt;for &lt;/span&gt;incoming connections...

received 22 bytes
bytes: &lt;span class="o"&gt;[&lt;/span&gt;72, 101, 108, 108, 111, 32, 102, 114, 111, 109, 32, 75, 117, 110, 103, 102, 117, 68, 101, 118, 13, 10]
hex repr: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0x48"&lt;/span&gt;, &lt;span class="s2"&gt;"0x65"&lt;/span&gt;, &lt;span class="s2"&gt;"0x6c"&lt;/span&gt;, &lt;span class="s2"&gt;"0x6c"&lt;/span&gt;, &lt;span class="s2"&gt;"0x6f"&lt;/span&gt;, &lt;span class="s2"&gt;"0x20"&lt;/span&gt;, &lt;span class="s2"&gt;"0x66"&lt;/span&gt;, &lt;span class="s2"&gt;"0x72"&lt;/span&gt;, &lt;span class="s2"&gt;"0x6f"&lt;/span&gt;, &lt;span class="s2"&gt;"0x6d"&lt;/span&gt;, &lt;span class="s2"&gt;"0x20"&lt;/span&gt;, &lt;span class="s2"&gt;"0x4b"&lt;/span&gt;, &lt;span class="s2"&gt;"0x75"&lt;/span&gt;, &lt;span class="s2"&gt;"0x6e"&lt;/span&gt;, &lt;span class="s2"&gt;"0x67"&lt;/span&gt;, &lt;span class="s2"&gt;"0x66"&lt;/span&gt;, &lt;span class="s2"&gt;"0x75"&lt;/span&gt;, &lt;span class="s2"&gt;"0x44"&lt;/span&gt;, &lt;span class="s2"&gt;"0x65"&lt;/span&gt;, &lt;span class="s2"&gt;"0x76"&lt;/span&gt;, &lt;span class="s2"&gt;"0x0d"&lt;/span&gt;, &lt;span class="s2"&gt;"0x0a"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
str repr: &lt;span class="s2"&gt;"Hello from KungfuDev&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

Sent 22 bytes back to client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This output indicates that the server is running, bound to the address &lt;code&gt;127.0.0.1:6797&lt;/code&gt;, and successfully received and echoed back data from a client.&lt;/p&gt;

&lt;p&gt;And in our &lt;code&gt;telnet(client)&lt;/code&gt; we can see the data is replied back.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;telnet localhost 6797
Trying 127.0.0.1...
Connected to localhost.
Escape character is &lt;span class="s1"&gt;'^]'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Hello from KungfuDev
Hello from KungfuDev
Connection closed by foreign host.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find the code in this repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  What about the client?
&lt;/h3&gt;

&lt;p&gt;As you saw in the diagram that illustrates the flow of socket communication, the client, instead of calling &lt;code&gt;listen&lt;/code&gt;, uses &lt;code&gt;connect&lt;/code&gt; to initiate a connection to a server socket.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket_fd&lt;/span&gt;&lt;span class="nf"&gt;.as_raw_fd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="nf"&gt;.as_bytes&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;MsgFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to send data to server"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The client uses the &lt;code&gt;connect&lt;/code&gt; function to establish a connection with the server. After successfully connecting, the client can send data to the server using the &lt;code&gt;send&lt;/code&gt; function and receive data from the server using the &lt;code&gt;recv&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;You can find the code for this example and future ones in this &lt;a href="https://github.com/douglasmakey/socket_net/tree/main" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  To conclude
&lt;/h2&gt;

&lt;p&gt;In this article, we explored the fundamentals of socket programming using Rust and the &lt;code&gt;nix&lt;/code&gt; crate. We began by understanding the OSI model and its practical application through the TCP/IP model, laying the groundwork for network communication. We then delved into the sequence of functions necessary to create a server: &lt;code&gt;socket()&lt;/code&gt;, &lt;code&gt;bind()&lt;/code&gt;, &lt;code&gt;listen()&lt;/code&gt;, and &lt;code&gt;accept()&lt;/code&gt;. By walking through a complete example, we demonstrated how to set up a simple server that listens for incoming connections, receives data, and echoes it back to the client.&lt;/p&gt;

&lt;p&gt;Running the provided Rust program and testing it with &lt;code&gt;telnet&lt;/code&gt; illustrated these concepts in action, showing how data is transmitted and received over a network. Although we kept the example synchronous and used a small backlog for simplicity, this foundation paves the way for more advanced topics such as asynchronous programming and handling multiple connections efficiently.&lt;/p&gt;

&lt;p&gt;Stay tuned for future articles where we will introduce asynchronous runtimes and explore additional and advanced socket programming techniques to enhance our networking skills.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>rust</category>
      <category>socket</category>
      <category>network</category>
    </item>
    <item>
      <title>Turning Problems into Solutions: Provide Alternatives, Not Excuses</title>
      <dc:creator>Douglas Makey Mendez Molero</dc:creator>
      <pubDate>Mon, 20 May 2024 21:41:07 +0000</pubDate>
      <link>https://forem.com/douglasmakey/turning-problems-into-solutions-provide-alternatives-not-excuses-4af0</link>
      <guid>https://forem.com/douglasmakey/turning-problems-into-solutions-provide-alternatives-not-excuses-4af0</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdmkvr8u6fwym02u2xam.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdmkvr8u6fwym02u2xam.jpeg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the journey of software engineering, there are moments when challenges seem insurmountable. These are the moments that test our problem-solving skills, resilience, and creativity. However, the way we approach these challenges can make all the difference. Instead of offering excuses, providing viable alternatives can transform a roadblock into a learning opportunity.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Importance of Mindset
&lt;/h3&gt;

&lt;p&gt;A crucial aspect of being a successful software engineer is adopting a proactive mindset. When faced with a problem, it's easy to resort to excuses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"The deadline is too tight."&lt;/li&gt;
&lt;li&gt;"The technology is too complex."&lt;/li&gt;
&lt;li&gt;"The requirements are unclear."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These statements, while potentially true, don't contribute to progress. Instead, they create a culture of stagnation. A proactive mindset shifts the focus from what can't be done to what can be explored.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;           ↑ Increase
       +--------------------+        
       |       +Solutions   |        
       |       +Solutions   |        
       |       +Solutions   |        
       |       +Solutions   |        +----------+
       |       +Solutions   |        | -Problems|
       |       +Solutions   |        | -Problems|
       |       +Solutions   |        | -Problems|
       |       +Solutions   |        | -Problems|
       +--------------------+        +----------+
                                      ↓ Decrease
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Analyzing the Situation
&lt;/h3&gt;

&lt;p&gt;When you encounter a problem, start by analyzing the situation thoroughly. Here are some steps to guide you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Understand the Problem&lt;/strong&gt;: Take the time to fully understand the problem. Break it down into smaller, manageable parts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identify Constraints&lt;/strong&gt;: Recognize the constraints you are working within, whether they are time, resources, or technical limitations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explore Alternatives&lt;/strong&gt;: Brainstorm possible solutions. Think outside the box and consider unconventional approaches.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Simple Example Scenarios
&lt;/h3&gt;

&lt;p&gt;Obviously, these examples are quite simple, but they help us get a clear idea of what the correct mindset should be.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tight Deadlines&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Situation&lt;/strong&gt;: The client requests a new feature, but the deadline is tight.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response with Excuses&lt;/strong&gt;: "We can't meet this deadline. It's impossible."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response with Options&lt;/strong&gt;: "Meeting this deadline is challenging, but we can prioritize the core functionality and add additional features in the next iteration. Alternatively, we can extend the deadline by a week to deliver the complete feature set."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Technical Limitations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Situation&lt;/strong&gt;: A particular technology doesn't support a requested feature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response with Excuses&lt;/strong&gt;: "This technology doesn't support that feature. We can't do it."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response with Options&lt;/strong&gt;: "While this technology doesn't support the feature directly, we can use a workaround or integrate another tool that provides the required functionality."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By providing these alternatives, you are not only demonstrating a solution-oriented mindset but also encouraging a culture of continuous learning and collaboration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Beyond Alternatives and Excuses
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Providing alternatives, not excuses&lt;/code&gt;, is more than just offering solutions. It's about how you handle issues or problems.&lt;/p&gt;

&lt;p&gt;At the beginning of my career, I was one of those people who, these days, I wouldn't be happy to work with. I was the &lt;code&gt;I told you so&lt;/code&gt; guy. I remember approaching the team and mentioning phrases that no one wanted to hear. My boss would say, &lt;code&gt;I don't want you to bring me a problem or say there is a problem when it's clear there is one. I want you to bring possible solutions.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In many cases, I knew we had a problem, and I had possible solutions or something to try, but my communication always started with the problem and not with the solutions. The same principle applies here. We should focus on presenting potential solutions first and foremost.&lt;/p&gt;

&lt;p&gt;My great friend &lt;a href="https://www.patrickdap.com/"&gt;Patrick D'appollonio&lt;/a&gt; , one of the best engineers I have known and from whom I have the fortune to learn, has always told me: &lt;code&gt;If you come with problems, at least bring a solution. This shows that you are interested in solving the problems and not just criticizing or pointing out something obvious!&lt;/code&gt; This advice has stayed with me throughout my career, reinforcing the importance of being proactive and solution-oriented.&lt;/p&gt;

&lt;h3&gt;
  
  
  I Don't Know
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k6YdUKGV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://www.kungfudev.com/images/blog/i-dont-know.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6YdUKGV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://www.kungfudev.com/images/blog/i-dont-know.gif" alt="I don't know" width="480" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main idea behind this concept is not to have an answer or proposal for every situation or question immediately. As we often hear, it's okay to say &lt;code&gt;I don't know,&lt;/code&gt; but this should be followed with &lt;code&gt;but I will figure it out.&lt;/code&gt; The key is to actively involve yourself in the process of finding a solution. Saying you'll figure it out means committing to understanding the problem, researching possible solutions, and engaging with your team to develop and propose viable options.&lt;/p&gt;

&lt;h3&gt;
  
  
  Relating to the Broken Windows Theory
&lt;/h3&gt;

&lt;p&gt;In my previous article on the &lt;a href="https://www.kungfudev.com/blog/2024/05/18/broken-windows"&gt;Broken Windows&lt;/a&gt; theory, we discussed the importance of maintaining quality and addressing small issues before they escalate. This concept ties closely to the mindset of providing alternatives and not excuses. Both approaches emphasize the importance of proactive problem-solving and a commitment to continuous improvement.&lt;/p&gt;

&lt;p&gt;When we focus on solutions rather than excuses, we prevent small issues from becoming major problems. Just as the &lt;strong&gt;Broken Windows&lt;/strong&gt; theory suggests that fixing minor issues can prevent larger ones, providing viable alternatives ensures that we address challenges head-on and maintain the integrity of our work. For example, giving excuses like &lt;code&gt;I will revisit this later&lt;/code&gt; without the commitment to actually do it can lead to accumulated technical debt. By providing solutions and following through, we maintain a higher standard of quality and reliability in our projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Communication is Key
&lt;/h3&gt;

&lt;p&gt;Effective communication is vital when presenting alternatives. Here’s how to ensure your suggestions are well-received:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Be Clear and Concise&lt;/strong&gt;: Clearly articulate the problem and your proposed solutions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provide Evidence&lt;/strong&gt;: Back up your suggestions with data or examples from past experiences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be Open to Feedback&lt;/strong&gt;: Encourage feedback and be prepared to iterate on your solutions based on input from others.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Building a Resilient Team
&lt;/h3&gt;

&lt;p&gt;As a senior engineer or team leader, it's important to foster an environment where team members feel empowered to suggest alternatives. Encourage open discussions, celebrate innovative ideas, and provide constructive feedback. This not only builds a resilient team but also instills a problem-solving mindset in junior engineers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In software engineering, challenges are inevitable. However, the way we respond to these challenges defines our growth and success. By providing alternatives instead of excuses, we pave the way for innovation, learning, and progress. Let’s commit to being solution-oriented, proactive, and collaborative in our approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remember, the next time you face a daunting task, think of alternatives. Your proactive approach could be the catalyst for a breakthrough solution.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>The Broken Window in Software Projects</title>
      <dc:creator>Douglas Makey Mendez Molero</dc:creator>
      <pubDate>Sat, 18 May 2024 22:42:50 +0000</pubDate>
      <link>https://forem.com/douglasmakey/the-broken-window-in-software-projects-kka</link>
      <guid>https://forem.com/douglasmakey/the-broken-window-in-software-projects-kka</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtimx171twzkirc3u7q7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtimx171twzkirc3u7q7.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In software development, the &lt;code&gt;Broken Window&lt;/code&gt; theory suggests that small issues, if left unfixed, can lead to bigger problems. Imagine a codebase where minor bugs or style inconsistencies are ignored. Over time, these small problems accumulate, making the code harder to maintain and increasing the likelihood of critical errors. However, this theory extends beyond just code issues. It also encompasses bad design choices, poor architectural decisions, and ineffective processes, all of which can degrade the overall quality and maintainability of a software project.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What is the Broken Window Theory? The Broken Window Theory originates from criminology and urban studies, suggesting that visible signs of disorder and neglect (like broken windows) lead to more disorder and crime. Applied to software engineering, it means that neglecting small issues in the codebase can lead to a general decline in code quality and discipline, inviting more significant problems.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Technical Debt
&lt;/h3&gt;

&lt;p&gt;When &lt;code&gt;broken windows&lt;/code&gt; are left unattended, they accumulate as &lt;code&gt;technical debt&lt;/code&gt;. This debt represents the future cost of rework and refactoring required to address these issues. Just like financial debt, technical debt accrues interest, making the codebase more difficult to work with over time. High technical debt can slow down development, introduce more bugs, and increase the cost of implementing new features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple Example Scenarios
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Hacky Solutions for Deadlines&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When a project deadline is close, you might implement a hacky solution just to get things working, promising to revisit and fix it later. This often doesn’t happen, and the quick fix becomes part of the codebase, increasing technical debt.&lt;/p&gt;

&lt;p&gt;How many times have you been in this situation or made that promise and never looked at that code again? You eventually accept it as part of the program, forgetting the commitment to review and improve it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inconsistent Coding Practices&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You notice that the code you're writing doesn't fit well with the existing code style or architecture, but you leave it as is, thinking you'll revisit it later. This inconsistency can lead to confusion and errors for future developers working on the code.&lt;/p&gt;

&lt;p&gt;You're not a team of one, and even if you are now, it won't always be that way. You must advocate for the practices and standards defined as a team. Everyone should be rowing in the same direction; after all, you're all in the same boat.&lt;/p&gt;

&lt;h3&gt;
  
  
  Beyond Code: Design and Decision-Making
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Design Flaws and Poor Decisions&lt;/strong&gt;: Broken windows are not limited to just code. They can also appear as bad design choices, poor architectural decisions, or ineffective processes. For example, an ill-thought-out system architecture that doesn't scale well or a design that doesn't consider user experience can be just as detrimental as poor code quality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Poor Implementation Practices&lt;/strong&gt;: Even if the design is solid, poor implementation can introduce broken windows. Rushed or sloppy coding, lack of adherence to best practices, or insufficient testing can all contribute to technical debt and a deteriorating codebase.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Cost of Broken Windows
&lt;/h4&gt;

&lt;p&gt;A few years ago, I joined a small team of engineers working on a project where the initial team had chosen a programming language that no one was proficient in. The decision to use this language was driven by its popularity at the time, not by the team's expertise. This poor decision led to many broken windows in the project. The team rushed through development, leaving many issues unresolved. While the project technically worked, taking it to the next level required a lot of effort. By systematically addressing these broken windows and pushing best practices, we managed to improve the project. However, the time and effort spent fixing these issues were significantly higher than if they had been addressed from the beginning.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaway
&lt;/h3&gt;

&lt;p&gt;Regularly address small issues to maintain code quality and prevent larger problems from developing. Keep your codebase clean and organized to minimize technical debt and ensure long-term project success. Create tickets for these issues and enforce you and your team to solve them. Give priority to these tickets to ensure that small problems do not accumulate and become more significant obstacles.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Maintaining a clean and organized codebase is crucial for long-term project success. The &lt;code&gt;Broken Window&lt;/code&gt; theory teaches us that small issues, if left unaddressed, can lead to significant problems, including increased technical debt. By understanding and addressing both code-level and design-level broken windows, you can prevent the accumulation of technical debt and ensure a more reliable, maintainable, and scalable software project. Prioritize these issues, create actionable tickets, and foster a culture of continuous improvement within your team. This proactive approach will lead to more efficient development and higher-quality software.&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>softwaredevelopment</category>
      <category>software</category>
    </item>
  </channel>
</rss>
