<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Tawaliou]]></title><description><![CDATA[Software Developer | Love Low Level Eng. | Python, Javascript, C, Linux, I'm learning backend development and system programming.]]></description><link>https://tawaliou.com</link><generator>RSS for Node</generator><lastBuildDate>Fri, 10 Apr 2026 06:30:09 GMT</lastBuildDate><atom:link href="https://tawaliou.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[OS Design and Implementation: (Week 6 - 7) - 
Interrupts & Device Driver; Locks]]></title><description><![CDATA[xv6 Book; Chapter 6 - 7 - Interrupts & Device Driver; Locks: https://pdos.csail.mit.edu/6.1810/2025/xv6/book-riscv-rev5.pdf
Chapter 6 and 7 are about Interrupts, device driver and locks.
Interrupts an]]></description><link>https://tawaliou.com/os-design-and-implementation-week-6-7-interrupts-device-driver-locks</link><guid isPermaLink="true">https://tawaliou.com/os-design-and-implementation-week-6-7-interrupts-device-driver-locks</guid><category><![CDATA[systemprogramming]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Kernel]]></category><category><![CDATA[operating system]]></category><category><![CDATA[interrupts]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Thu, 02 Apr 2026 18:54:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f9bb8f3ff730d5cb8dedb03/ece9779f-02d2-4849-b3cf-acc6d38af908.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>xv6 Book; Chapter 6 - 7 - Interrupts &amp; Device Driver; Locks</strong>: <a href="https://pdos.csail.mit.edu/6.1810/2025/xv6/book-riscv-rev5.pdf">https://pdos.csail.mit.edu/6.1810/2025/xv6/book-riscv-rev5.pdf</a></p>
<p>Chapter 6 and 7 are about Interrupts, device driver and locks.</p>
<h2>Interrupts and Device Driver</h2>
<blockquote>
<p>A driver is the code in an operating system that manages a particular device (network card, mouse, screen...): it configures the device hardware, tells the device to perform operations, handles the resulting interrupts, and interacts with processes using the device</p>
</blockquote>
<p>An interrupt is a type of trap that allows a device to communicate with the operating system.</p>
<p>Here are some details about interrupts and device drivers:</p>
<ul>
<li><p>The CPU does not directly control I/O devices; instead, it communicates with a microcontroller installed on the devices via a control bus.</p>
</li>
<li><p>Memory-mapped I/O is a communication technique where each device is allocated a specific memory space in RAM, allowing the CPU to read or write data.</p>
</li>
<li><p>Polling, or programmed I/O, is another technique where the OS periodically checks if there is data to read from the device.</p>
</li>
<li><p>Interrupt-based I/O is akin to a trap, as discussed in OS Design and Implementation (Week 4) - Trap.</p>
</li>
</ul>
<h2>Locks</h2>
<p>Sure! Everyone is familiar with locks: they enable the OS to safeguard shared resources during use.In this chapter, we explore the internals of locks. Although I don't grasp everything, I gain new insights about them.</p>
<h2><strong>Labs</strong></h2>
<p>There are three labs where we were tasked with building a network driver and adding a custom lock mechanism to xv6. I completed the first one:</p>
<ul>
<li><p><strong>[Device Drivers] Network Interface Card (e1000) driver</strong>: Implement <code>e1000_transmit</code> and <code>e1000_recv</code> in <code>kernel/e1000.c</code> to manage packet flow by manipulating the hardware's transmit and receive descriptor rings via DMA and control registers. You must successfully pass the "txone" and "rxone" tests by correctly handling buffer allocation, hardware status checks, and synchronization. <strong>Completed</strong></p>
</li>
<li><p><strong>[Device Drivers] UDP Receive:</strong> Implement <code>ip_rx</code>, <code>sys_recv</code>, and <code>sys_bind</code> in <code>kernel/net.c</code> to enable UDP packet reception by filtering incoming IP traffic, queuing up to 16 packets per bound port, and delivering them to user processes. You must handle the transition between network and host byte orders using <code>ntohs</code>/<code>ntohl</code> and ensure the system correctly manages packet buffers to pass all <code>nettest</code> verification suites. I implemented <code>ip_rx</code>, <code>sys_bind</code>, i didn't complete the <code>sys_recv</code>.</p>
</li>
<li><p><strong>[Locks] Read-Write Lock:</strong> You must implement a read-write spinlock in xv6 that allows multiple concurrent readers but ensures exclusive access for a single writer. To prevent writer starvation, your lock must implement a priority scheme where any pending writer blocks new readers from acquiring the lock until the writer has finished.</p>
</li>
</ul>
<h2>Next week</h2>
<p>Next weeks is about <strong>Scheduling.</strong></p>
<p>By the way, here's my GitHub repo for the lab course: <a href="https://github.com/TawalMc/MIT-6.1810Fall2025-xv6"><strong>https://github.com/TawalMc/MIT-6.1810Fall2025-xv6</strong></a></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f9bb8f3ff730d5cb8dedb03/9afed4bc-5f91-48e9-8bce-8256fc9e284f.png" alt="" style="display:block;margin:0 auto" />]]></content:encoded></item><item><title><![CDATA[OS Design and Implementation: (Week 5) - Page fault]]></title><description><![CDATA[Lecture
xv6 Book; Chapter 5 - Page fault: https://pdos.csail.mit.edu/6.1810/2025/xv6/book-riscv-rev5.pdf
Chapter 5 discusses page faults. A page fault is an exception that occurs when a virtual addres]]></description><link>https://tawaliou.com/os-design-and-implementation-week-5-page-fault</link><guid isPermaLink="true">https://tawaliou.com/os-design-and-implementation-week-5-page-fault</guid><category><![CDATA[Kernel]]></category><category><![CDATA[Linux]]></category><category><![CDATA[systemprogramming]]></category><category><![CDATA[operating system]]></category><category><![CDATA[page-fault]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Fri, 20 Feb 2026 21:47:52 GMT</pubDate><content:encoded><![CDATA[<h2>Lecture</h2>
<p><strong>xv6 Book; Chapter 5 - Page fault</strong>: <a href="https://pdos.csail.mit.edu/6.1810/2025/xv6/book-riscv-rev5.pdf">https://pdos.csail.mit.edu/6.1810/2025/xv6/book-riscv-rev5.pdf</a></p>
<p>Chapter 5 discusses page faults. A page fault is an exception that occurs when a virtual address is used but either:</p>
<ul>
<li><p>lacks a mapping in the page table (physical memory is not yet allocated),</p>
</li>
<li><p>has an invalid mapping because PTE_V is not set,</p>
</li>
<li><p>or the requested operation (read, write, execute, user, etc.) is not permitted, meaning the appropriate flags (PTE_R, PTE_W, etc.) are not set.</p>
</li>
</ul>
<p>An interesting aspect of page faults is that, when combined with the page table (which maps virtual addresses to physical addresses), they allow the kernel to fully control memory usage, enabling the application of various techniques. For example:</p>
<ul>
<li><p>Copy-on-Write (<strong>CoW</strong>): When executing a fork system call, the kernel shares memory between the parent and child instead of copying the parent's memory to the child, as was done previously. The parent's memory is marked as read-only in the page table and shared with the child. If a write operation occurs, a page fault exception is triggered because the memory is read-only. This alerts the kernel to allocate new memory and copy the shared data before allowing the write operation. This approach ensures that a copy is made only if a write operation occurs, making the fork process faster.</p>
</li>
<li><p><strong>Demand paging</strong>: In this approach, the kernel stores only a portion of the user program's pages in RAM, while the rest remain on disk. The page table entries (PTE) for the pages on disk are marked as invalid. The kernel loads these pages into RAM only when the program requests them, triggering a page fault exception due to their invalid PTEs.</p>
</li>
</ul>
<p>It's as if the kernel intentionally allows this exception and knows how to handle it whenever it occurs.</p>
<h2><strong>Labs</strong></h2>
<p>There is just one lab: Implement copy-on-write (COW) fork() to delay allocating and copying physical memory pages until they are actually needed, if at all. I didn't finish it.</p>
<h2>Next week</h2>
<p>Next weeks is about <strong>Interrupts and Locks.</strong></p>
<p>By the way, here's my GitHub repo for the lab course: <a href="https://github.com/TawalMc/MIT-6.1810Fall2025-xv6"><strong>https://github.com/TawalMc/MIT-6.1810Fall2025-xv6</strong></a></p>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/5f9bb8f3ff730d5cb8dedb03/581dfde2-0fd5-4059-a1d7-e71f2e7c33de.png" alt="" style="display:block;margin:0 auto" />]]></content:encoded></item><item><title><![CDATA[OS Design and Implementation: (Week 4) - Trap]]></title><description><![CDATA[Lecture
xv6 Book; Chapter 4 - Traps and system calls: https://pdos.csail.mit.edu/6.1810/2025/xv6/book-riscv-rev5.pdf
The lecture in the 4th week was about Traps.A trap is an event that causes the CPU to switch from its current task to specific code i...]]></description><link>https://tawaliou.com/os-design-and-implementation-week-4-trap</link><guid isPermaLink="true">https://tawaliou.com/os-design-and-implementation-week-4-trap</guid><category><![CDATA[Kernel]]></category><category><![CDATA[Linux]]></category><category><![CDATA[systemprogramming]]></category><category><![CDATA[operating system]]></category><category><![CDATA[traps]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Tue, 13 Jan 2026 22:25:41 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-lecture">Lecture</h2>
<p><strong>xv6 Book; Chapter 4 - Traps and system calls</strong>: <a target="_blank" href="https://pdos.csail.mit.edu/6.1810/2025/xv6/book-riscv-rev5.pdf">https://pdos.csail.mit.edu/6.1810/2025/xv6/book-riscv-rev5.pdf</a></p>
<p>The lecture in the 4th week was about <strong>Traps.</strong><br />A trap is an event that causes the CPU to switch from its current task to specific code in the kernel space to handle the event. There are three types of traps:</p>
<ul>
<li><p><strong>syscall:</strong> user space code asking the kernel (through the <strong>ecall</strong> instruction) to perform an action</p>
</li>
<li><p><strong>interrupt:</strong> when a device requests attention, like an I/O operation with a disk</p>
</li>
<li><p><strong>exception:</strong> when something goes wrong in either the kernel or user space.</p>
</li>
</ul>
<p>Anyway, there are common operations that need to be done when a trap occurs:</p>
<ol>
<li><p>Save the current state of the CPU and what's being executed (registers, memory, etc.)</p>
</li>
<li><p>The CPU enters supervisor mode.</p>
</li>
<li><p>The kernel performs appropriate checks (permissions, security, etc.)</p>
</li>
<li><p>Jump to the kernel code (handler) that will handle the trap.</p>
</li>
<li><p>Restore the saved state.</p>
</li>
<li><p>Resume the execution of the running code.</p>
</li>
</ol>
<p>Saying it like this makes it sound easy, but it's more complicated. For example, in the case of Xv6, process state saving is written directly in RISC-V assembly language, and there can be more layers between when the trap occurs and when the process execution resumes.</p>
<p>In the case of a syscall, here is a path in the code:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768319669107/c5181c27-dbf1-47f9-9cbf-a0282a855920.png" alt class="image--center mx-auto" /></p>
<p>Where <strong>trampoline</strong> is a memory space within the process address space, mapped directly to the same memory space inside the kernel address space, containing the code to enter and exit the kernel.</p>
<p>You can find more details in the book: <a target="_blank" href="https://pdos.csail.mit.edu/6.1810/2025/xv6/book-riscv-rev5.pdf">https://pdos.csail.mit.edu/6.1810/2025/xv6/book-riscv-rev5.pdf</a></p>
<p>There was a lot of RISC-V assembly code to read at this point 😭</p>
<h2 id="heading-labs">Labs</h2>
<p>There are two labs to complete - <a target="_blank" href="https://pdos.csail.mit.edu/6.1810/2025/labs/traps.html">https://pdos.csail.mit.edu/6.1810/2025/labs/traps.html</a>:</p>
<ol>
<li><p><strong>Backtrace:</strong> A <strong>backtrace</strong>, also known as StackTrace, reconstructs the call history by going through a chain of stack frames. Each frame stores a return address and a pointer to the caller's frame. By starting with the <strong>frame pointer (s0)</strong> and following these links upward, you can identify and print the return address for every function in the current execution path.</p>
</li>
<li><p><strong>Alarm:</strong> You will implement a feature in xv6 that periodically interrupts a process after a set amount of CPU time, serving as a basic foundation for <strong>user-level interrupt and fault handlers</strong>. Your solution is complete once it successfully passes the <code>alarmtest</code> and <code>usertests -q</code> verification suites.</p>
</li>
</ol>
<p>Unlike in week 3, I completed these two labs this time. A big thank you to <a target="_blank" href="https://github.com/Miigon">https://github.com/Miigon</a> for having solutions for some labs of this course, but for the 2020 version "<a target="_blank" href="https://github.com/Miigon/my-xv6-labs-2020">https://github.com/Miigon/my-xv6-labs-2020</a>." It really helped me after spending about 2 weeks working on these labs. My challenge was reading the lectures, the book, and trying to understand the code and explanations on my own, so it wasn't always easy. Having a repository to check when I'm stuck or facing difficulties is really helpful.</p>
<h2 id="heading-next-week">Next week</h2>
<p>Next week is about <strong>Page faults.</strong></p>
<p>By the way, here's my GitHub repo for the lab course: <a target="_blank" href="https://github.com/TawalMc/MIT-6.1810Fall2025-xv6"><strong>https://github.com/TawalMc/MIT-6.1810Fall2025-xv6</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[OS Design and Implementation: (Week 3) - Page tables]]></title><description><![CDATA[Okay! Not only did I spend more than 3 weeks on it, but I also completed only 2 of the 3 labs about page tables. And yes, it was a tough chapter. Anything related to memory is tough, by the way.
In short, this chapter was about page tables and how th...]]></description><link>https://tawaliou.com/os-design-and-implementation-week-3-page-tables</link><guid isPermaLink="true">https://tawaliou.com/os-design-and-implementation-week-3-page-tables</guid><category><![CDATA[Kernel]]></category><category><![CDATA[Linux]]></category><category><![CDATA[systemprogramming]]></category><category><![CDATA[operating system]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Wed, 31 Dec 2025 05:52:17 GMT</pubDate><content:encoded><![CDATA[<p>Okay! Not only did I spend more than 3 weeks on it, but I also completed only 2 of the 3 labs about page tables. And yes, it was a tough chapter. Anything related to memory is tough, by the way.</p>
<p>In short, this chapter was about page tables and how the OS creates virtual memory for applications. In fact, the memory used by user applications or that we get when doing</p>
<pre><code class="lang-c"><span class="hljs-keyword">int</span> a = <span class="hljs-number">25</span>;
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"%p"</span>, &amp;a);
</code></pre>
<p>is virtual memory that the OS creates and maps to physical memory.<br />The OS doesn't allow user applications to interact directly with the RAM (this is too dangerous); instead,</p>
<ul>
<li><p>It allocates the same address space of <code>[0; 0x3fffffffff]</code> for each process or application, which contains blocks of memory that are 4096 bits in size.</p>
</li>
<li><p>Then, it maps or associates each address of this virtual memory to a real address in the RAM using what we call a <strong>Page Table Entry</strong>.</p>
</li>
</ul>
<p>There are many other aspects of Virtual Memory, such as access rights to addresses, page size, and the Translation Lookaside Buffer (which acts like an LRU cache for mapping virtual addresses to physical addresses)...</p>
<p>This technique allows the OS to control access to memory and check if a process has the right to read, execute, or write to a memory address, addressing a security concern.</p>
<p>Now, back to the course. It took me some time to understand what Virtual Memory is and how it works, and even more time to complete the labs, which were:</p>
<ol>
<li><p>Map a read-only page containing the PID into the process's virtual memory during creation. The user program then reads the PID directly from that memory address, avoiding the system call.</p>
</li>
<li><p>To help visualize RISC-V page tables, write a function that prints the contents of a page table.</p>
</li>
<li><p>Create megapages by setting valid and read bits in a level-1 PTE and pointing it to a 2MB-aligned physical address.</p>
<p> This reduces page table size and TLB misses, significantly boosting performance for memory-intensive programs. <strong><em>(Not completed)</em></strong>.</p>
</li>
</ol>
<p>And yes, there is an approach called Superpages. Instead of allocating small memory sizes like 4096 bits, the OS allocates larger superpages, such as 2MB. However, it's not straightforward. There are some challenges with its implementation. And guess what? There are two papers to read about it (I swear 😭 It's not just something I imagined about the course):</p>
<ul>
<li><p>Practical, transparent operating system support for superpages [<a target="_blank" href="https://www.usenix.org/conference/osdi-02/practical-transparent-operating-system-support-superpages">https://www.usenix.org/conference/osdi-02/practical-transparent-operating-system-support-superpages</a>] <strong><em>(In reading)</em></strong></p>
</li>
<li><p>A Comprehensive Analysis of Superpage Management Mechanisms and Policies [<a target="_blank" href="https://www.usenix.org/conference/atc20/presentation/zhu-weixi">https://www.usenix.org/conference/atc20/presentation/zhu-weixi</a>] <strong><em>(Not started)</em></strong>.</p>
</li>
</ul>
<p>So, what now? I'll leave it there and start <strong>Week 4</strong>: <strong>Trap and Syscall entry-exit</strong>. Maybe while reading and doing the labs, I can come back to the Superpages lab. I'm not required to understand everything right away 😂  </p>
<p>By the way, here's my GitHub repo for the lab course: <a target="_blank" href="https://github.com/TawalMc/MIT-6.1810Fall2025-xv6">https://github.com/TawalMc/MIT-6.1810Fall2025-xv6</a></p>
]]></content:encoded></item><item><title><![CDATA[Year In Review 2025: The only bad choice is the absence of choice]]></title><description><![CDATA[Here's a brief review of how my 2025 went.Once again, we're at the end of the year, and it's nice to read people's Year In Review..
I did it last year: Dev Retro 2024, so I’ll do it again.
Let's thank God for keeping us healthy and alive this year.
Y...]]></description><link>https://tawaliou.com/year-in-review-2025-the-only-bad-choice-is-the-absence-of-choice</link><guid isPermaLink="true">https://tawaliou.com/year-in-review-2025-the-only-bad-choice-is-the-absence-of-choice</guid><category><![CDATA[devretro2025]]></category><category><![CDATA[yearinreview]]></category><category><![CDATA[2025]]></category><category><![CDATA[recap]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Mon, 22 Dec 2025 08:07:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1766391884258/8325439b-c9f6-43c5-9186-e95b94368c53.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Here's a brief review of how my 2025 went.<br />Once again, we're at the end of the year, and it's nice to read people's <strong>Year In Review</strong>.<strong>.</strong></p>
<p>I did it last year: <a target="_blank" href="https://tawaldevuniverse.hashnode.dev/dev-retro-2024">Dev Retro 2024</a>, so I’ll do it again.</p>
<p><strong><mark>Let's thank God for keeping us healthy and alive this year.</mark></strong></p>
<h2 id="heading-year-of-decisions">Year of Decisions</h2>
<p>This year was mainly about making decisions. What should I study? What should I do next? What am I interested in? What can I do, and what do I want?<br />If you've read my <a target="_blank" href="https://tawaldevuniverse.hashnode.dev/dev-retro-2024">Year In Review 2024</a> (called Dev Retro 2024), you'll know that I set some goals based on what I knew at that time. Well, I changed some of them this year.</p>
<p>So, I'll talk about my daily job, what I did in my free time, and the decisions I made.</p>
<h3 id="heading-at-work">At work</h3>
<p>Compared to 2024, not much has changed. Just take a look at the section <a target="_blank" href="https://tawaldevuniverse.hashnode.dev/dev-retro-2024#heading-at-work"><strong>At work</strong></a> from my <a target="_blank" href="https://tawaldevuniverse.hashnode.dev/dev-retro-2024">Year in Review of 2024</a>.</p>
<p>I'm still a backend developer working on some services at <a target="_blank" href="https://uptimise.io/">Uptimise</a>, a startup I joined in 2022. We officially launched the product this year, and it's been great working with everyone. This year, I didn't do any major refactoring or big projects. We focused on making the two versions, Uptimise Benin and Uptimise Ivory Coast, more stable. There's still work to do, but we're making progress.</p>
<p>Now, let's talk about my personal projects and what I did in my free time..</p>
<h3 id="heading-networking-cisco-networking-basics">Networking: Cisco Networking Basics</h3>
<p>I'm not good in networking, and everyone knows it. So this year, I decided to change that and learn the basics of networking.<br />From June to July, I took the Cisco Networking Basics course. I worked on it during nights and weekends, and it went well. I really enjoyed it. I learned a lot and now feel less clueless when talking about networking at work, configuring my router, or handling network tasks on my computer..</p>
<p>I wrote a series about it here: <a target="_blank" href="https://tawaldevuniverse.hashnode.dev/series/networking-linux-system-programming">Networking Basics</a></p>
<h3 id="heading-operating-system-engineering">Operating System Engineering</h3>
<p>It's no secret that I'm interested in system engineering and have a background in embedded systems. Currently, I'm a web (backend) developer, but I really want to switch to this part of the industry. Will I do it? I don't know. The only thing I know is that I want it, and I'll try to make it happen. Failure is part of the game, just like success, right?</p>
<p>After taking the Computer Architecture and Organization course (From Nand to Tetris) in 2024, I decided to move to the next step: Operating System Design and Implementation. The goal is to understand OS concepts and contribute to the Linux Kernel.</p>
<p>So, in November, I started the MIT Course on OS Fall 2025 (<a target="_blank" href="https://pdos.csail.mit.edu/6.1810/2025/schedule.html">https://pdos.csail.mit.edu/6.1810/2025/schedule.html</a>). It's 15 weeks of lectures with labs, books, and papers to complete. I'm currently in week 3. Yes, the lessons and labs are not easy to complete, at least for me, but I'm doing my best 😅.</p>
<h3 id="heading-blogging">Blogging</h3>
<p>I restarted blogging in the middle of this year. My goal was to write regularly, aiming for 1 or 2 blog posts per month about my work. It didn't go exactly as planned, but it wasn't bad at all. This year, I wrote 9 articles on Networking and OS. These articles cover what I learned in those courses.</p>
<p>The good thing is that I wrote at my own pace: 1 or 2 articles per month, or more if I could. I wrote a little bit whenever I had time, like writing 10 lines at night or spending an hour on an article on Saturday. The idea is to make it a part of my daily routine..</p>
<h3 id="heading-social-media-post-linkedin-and-twitter">Social Media post: LinkedIn and Twitter</h3>
<p>Some of my friends, <a target="_blank" href="https://bj.linkedin.com/in/trinit%C3%A9-zinsou">Trinité</a> (my Lead), <a target="_blank" href="http://linkedin.com/in/frejus-zotongninou/">Fréjus</a> (our Product Designer), <a target="_blank" href="https://bj.linkedin.com/in/devalade">Alade</a>, and <a target="_blank" href="https://bj.linkedin.com/in/amidou-ta%C3%AFrou-ciss%C3%A9">Cissé</a>, advised me to start posting about my progress on LinkedIn. So, that's what I did. It helps me connect with people who share my interests. Mostly, I share summaries of the articles I wrote on these two networks.<br />My LinkedIn: <a target="_blank" href="http://www.linkedin.com/in/tawaliou-alao-26688614b">Tawaliou ALAO</a><br />My Twitter: <a target="_blank" href="http://www.linkedin.com/in/tawaliou-alao-26688614b">@TawalMc</a></p>
<h3 id="heading-rejection-for-master-application">Rejection for Master Application</h3>
<p>In the section titled <a target="_blank" href="https://tawaldevuniverse.hashnode.dev/dev-retro-2024#heading-rejection-for-master-application">Rejection for Master Application</a> in my Year In Review 2024, I explained that I was rejected for a Master's in Embedded Systems through Campus France and for Electrical and Computer Engineering (ECE) at CMU Rwanda. I decided to reapply for ECE this year. So, yes, I reapplied, and guess what? I got rejected again. Why? My application wasn't outstanding, so I guess that's the truth. Maybe I didn't do something right, or my background doesn't align well with the courses, or my path isn't impressive. Anyway, I don't care anymore 😂. I applied to a few other universities, like King Abdullah University of Science and Technology, and got rejected too 😂..</p>
<p>And some problems arise: Should I apply for Campus France (Licence 3) and do everything to leave the country 😂? Or should I stay and pursue a master's degree here? Should I even pursue a master's degree at all?<br />You know, when you wake up with these kinds of thoughts and questions in your mind, it's hard to stay focused. The combination of the <strong>unknown</strong>, <strong>fear of bad choices</strong>, and <strong>failures</strong> increases indecision.<br />So I did something I often do in situations like this: I asked for advice from elders. It's the same thing: don't fear failure, don't fear making bad choices, fear not making a choice at all..</p>
<p>So I made two decisions:</p>
<ul>
<li><p>Stay. No more applications, at least for a master's abroad.</p>
</li>
<li><p>Go all-in on system programming. Put all my effort into this field. That's why, in the sections above, I mentioned that I started the OS Engineering course by MIT..</p>
</li>
</ul>
<p><strong>Is this a good choice?</strong> <strong>Will it pay off?</strong> <strong>I don’t know.</strong><br />Right now, I mostly care about the process rather than the results.<br />There are also many reasons behind my decision to focus on System Programming. In a future article, I’ll discuss some of these reasons that motivate me to choose this path..</p>
<p>To give you a hint, here are two of them::</p>
<ul>
<li><p>I currently need time, I need to have full control over my free time and the freedom to study system programming.</p>
</li>
<li><p>Try hard and take risks to achieve it. This article by Aaron Francis: <a target="_blank" href="https://aaronfrancis.com/2024/what-if-you-tried-hard-dac139a5">What if you tried hard</a> explained it</p>
</li>
</ul>
<blockquote>
<p>I wonder what would happen if you gave it all you had and even risked embarrassing yourself if it didn't work out.</p>
<p>Aaron Francis (<a target="_blank" href="https://aaronfrancis.com/2024/what-if-you-tried-hard-dac139a5">https://aaronfrancis.com/2024/what-if-you-tried-hard-dac139a5</a>)</p>
</blockquote>
<h2 id="heading-what-for-the-next-2026-2027">What for the next (2026, 2027, …) ?</h2>
<p>To be honest, as usual, I don't have <strong>clear, well-defined plans</strong> that I begin at the start of the year. No, nothing like that. I just have some important goals. I usually start working in this direction from October (3 months before the new year). This helps me adjust based on how things unfold.</p>
<p>So for the next few years:</p>
<ul>
<li><p><strong>Be consistent in blogging</strong>, aiming for at least 1 or 2 articles per month</p>
</li>
<li><p><strong>Get involved in open source projects (System Programming)</strong></p>
</li>
<li><p><strong>Linux Kernel</strong></p>
</li>
<li><p><strong>Read at least 6 papers on Operating System available on:</strong></p>
<ul>
<li><strong>Operating System Design and Implementation (OSDI) by USENIX</strong></li>
</ul>
</li>
</ul>
<h2 id="heading-last-words">Last Words</h2>
<p>A few things to keep in mind:</p>
<ul>
<li><p>Things don’t always go as planned, so it's good to be flexible.</p>
</li>
<li><p>Try hard at whatever interests you. At least give it a shot.</p>
</li>
<li><p>Be patient, seriously.</p>
</li>
<li><p>Avoid comparisons, as they only create frustration and prevent you from focusing on yourself.</p>
</li>
<li><p>Make choices, even if they might seem silly. Make decisions based on what you know, want, care about, and fear. Don’t hold back when you need to decide.</p>
</li>
<li><p>Sometimes, or often, life isn't easy, and that's just how it is.</p>
</li>
<li><p>And have hope.</p>
</li>
</ul>
<p>There are many people I want to think about this year, from my parents, my closest friends, and my girlfriend to my colleagues and elders. But there will be a dedicated blog post for that in the future (I hope).</p>
<p>Share your Year in Review with me. It inspires me..</p>
]]></content:encoded></item><item><title><![CDATA[OS Design and Implementation: (Week 2) - Syscall]]></title><description><![CDATA[It took me almost three weeks (nights and week-end) to read Chapter 2 of the xv6 book: Operating System Organization, study the xv6 code (process and system calls), and finish the assignments on system calls.
This chapter covers the organization of t...]]></description><link>https://tawaliou.com/os-design-and-implementation-week-2-syscall</link><guid isPermaLink="true">https://tawaliou.com/os-design-and-implementation-week-2-syscall</guid><category><![CDATA[System Programming]]></category><category><![CDATA[Kernel]]></category><category><![CDATA[Linux]]></category><category><![CDATA[operating system]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Sun, 21 Dec 2025 11:13:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1766315546401/8e61eecc-0375-46b5-8287-ab91a5fba7ae.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It took me almost three weeks (nights and week-end) to read <a target="_blank" href="https://pdos.csail.mit.edu/6.1810/2025/xv6/book-riscv-rev5.pdf">Chapter 2 of the xv6 book: <em>Operating System Organization</em></a>, study the xv6 code (process and system calls), and finish the assignments on system calls.</p>
<p>This chapter covers the organization of the operating system:</p>
<ul>
<li><p>There is a separation between the kernel and user space: user space code does not directly call kernel space code.</p>
</li>
<li><p>Processes are isolated, with each process running as if it has its own dedicated CPU and virtual memory, which is its own memory space (it cannot access memory outside this space without requesting more).</p>
</li>
<li><p>The underlying architecture (CPU) provides a system call mechanism (RISC-V uses the ecall instruction) to switch from user code to kernel code.</p>
</li>
<li><p>The kernel performs checks when a system call is triggered to ensure the operation is allowed and the correct arguments are passed.</p>
</li>
<li><p>Every system call, like read for example, is assigned a number (the read system call number in xv6 is 5) that the kernel uses to identify which system call the user code triggered.</p>
</li>
<li><p>And more... I'll explain "System Call" in more detail in my next blog post.</p>
</li>
</ul>
<p>And the labs? I spent most of my time trying to understand the assignments and figuring out where to start. Here are the labs:</p>
<ul>
<li><p>Implement a system call called “interpose” that limits the use of system calls based on a bitmask passed as an argument to interpose.</p>
</li>
<li><p>Exploit a vulnerability in xv6 that lets a process read data from another process's virtual memory. This lab helps illustrate why kernel code must be well-written.</p>
</li>
</ul>
<p>Currently, I'm getting hands-on experience with GDB for more effective debugging of the C and kernel code.</p>
<p>Next week, I'll start Week 3: Page Tables.</p>
]]></content:encoded></item><item><title><![CDATA[System Programming: OS Design and Implementation]]></title><description><![CDATA[Start the MIT 6.1810 Fall2025 Course
So… here’s an update on my learning path.
2023 – 2024: Building a Modern Computer from First Principles (aka Nand2Tetris). I studied the fundamentals of computer architecture; from logic gates and the CPU to the o...]]></description><link>https://tawaliou.com/system-programming-os-design-and-implementation</link><guid isPermaLink="true">https://tawaliou.com/system-programming-os-design-and-implementation</guid><category><![CDATA[operating system]]></category><category><![CDATA[Linux]]></category><category><![CDATA[System Programming]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Mon, 03 Nov 2025 09:47:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1762162746900/5ad3ec0f-3781-4c19-a683-0ec520ea7d7a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-start-the-mit-61810-fall2025-course">Start the MIT 6.1810 Fall2025 Course</h2>
<p>So… here’s an update on my learning path.</p>
<p><strong>2023 – 2024:</strong> <em>Building a Modern Computer from First Principles</em> (aka <strong>Nand2Tetris</strong>). I studied the fundamentals of computer architecture; from logic gates and the CPU to the operating system and compiler.</p>
<p><strong>Mid 2025:</strong> <em>Introduction to Networking Basics.</em></p>
<p><strong>Late 2025 – :</strong></p>
<p>I want to learn more about OS internals, especially the Linux kernel and similar topics. So, some days ago, I started the <strong>MIT 6.1810</strong> course on <em>Design and Implementation of Operating Systems</em>.</p>
<p>The course is based on <strong>xv6</strong>, a simple Unix-like teaching operating system. The goal is to study OS concepts by extending xv6.</p>
<p><strong>What’s good about this course:</strong></p>
<ul>
<li><p>It’s well structured and has a clear schedule. (This year’s session started in September 2025 and is expected to end in December 2025.)</p>
</li>
<li><p>It combines theory with practical labs, so you don’t just read; you build as well.</p>
</li>
</ul>
<p>I’ll spend some nights and weekends working on it, enjoy the process, and share updates about my progress here.</p>
<p>I’m currently working on the Week 1 assignment (<em>Lab: Utilities</em>), where we’re implementing Unix-like utilities using the xv6 API.</p>
<p>By the way, MIT offers really well-structured courses on various topics in Computer Science.</p>
<p><strong>MIT 61.810</strong> Fall 2025 (Operating System Engineering) link:[<a target="_blank" href="https://pdos.csail.mit.edu/6.1810/2025/overview.html">https://pdos.csail.mit.edu/6.1810/2025/overview.html</a>]</p>
<h2 id="heading-update-07-november-2025">Update [07 November 2025]</h2>
<h3 id="heading-lectures">Lectures</h3>
<p>I just finished week 1 of the course. This week, I read <a target="_blank" href="https://pdos.csail.mit.edu/6.1810/2025/xv6/book-riscv-rev5.pdf">Chapter 1: Operating System Interface</a> of the book on <strong>xv6.</strong> This chapter introduces:</p>
<ul>
<li><p>The <strong>xv6</strong> system calls, such as <strong>open</strong>, which "opens" a file by returning a file descriptor, and <strong>fork</strong>, which creates a process.</p>
</li>
<li><p>How processes behave, including how to create a child process and execute a command.</p>
</li>
<li><p>Importantly, what a <strong>file descriptor</strong> is (an entry in a table for each process that lists files opened by the process), which allows a process to read or write.</p>
</li>
<li><p>A method for processes to communicate (Inter-Process Communication): <strong>Pipes</strong>, which use file descriptors.</p>
</li>
</ul>
<p>I also read the chapters on Pointers (Arrays, Characters, Structs) from <strong>The C Programming Language (Second Edition) by <em>Kernighan and Ritchie (K&amp;R)</em></strong> to refresh key concepts about manipulating pointers.</p>
<p>Then there are the assignments or labs.</p>
<h3 id="heading-lab-assignments-unix-utilities">Lab Assignments: Unix utilities</h3>
<p>The labs focused on writing Unix-like utilities. Here are a few, along with brief descriptions::</p>
<ul>
<li><p><strong>sixfive (not so easy):</strong> For each input file, <strong>sixfive</strong> must print all the numbers in the file that are multiples of 5 or 6. Number are a sequence of decimal digits separated by characters in the string " -\r\t\n./,"<em>.</em></p>
</li>
<li><p><strong>memdump (not so easy):</strong> Implement the function memdump(char <em>fmt, char</em> data). <strong>memdump()</strong>'s purpose is to print the contents of the memory pointed to by data in the format described by the fmt argument.</p>
</li>
<li><p><strong>find (not easy):</strong> Write a simple version of the UNIX find program for xv6: find all the files in a directory tree with a specific name.</p>
</li>
<li><p><strong>pingpong (easy and from Fall 2020):</strong> Write a program that uses UNIX system calls to <strong>ping-pong</strong> a byte between two processes over a pair of pipes, one for each direction</p>
</li>
</ul>
<p>These labs were not too difficult and had clear instructions, but I often felt stuck and unsure of what to do. However, after reading <strong>chapter 1</strong> of the <strong>xv6</strong> book multiple times and reviewing the source code of some existing utilities, I completed them. Here are a few things to remember (and I'm not ready to forget them)::</p>
<ol>
<li>When creating a <strong>child</strong> with the <strong>fork</strong> system call, don't forget to use <strong>wait</strong> in the <strong>parent</strong>. This ensures that the parent waits for the child to finish executing. This way, both the <strong>parent</strong> and <strong>child</strong> code will run properly.</li>
</ol>
<ul>
<li><pre><code class="lang-c">  <span class="hljs-keyword">if</span> (fork() == <span class="hljs-number">0</span>) <span class="hljs-comment">// Child</span>
  {
      write(<span class="hljs-number">1</span>, <span class="hljs-string">"hello "</span>, <span class="hljs-number">6</span>);
      <span class="hljs-built_in">exit</span>(<span class="hljs-number">0</span>);
  }
  <span class="hljs-keyword">else</span> <span class="hljs-comment">// Parent</span>
  {
      wait(<span class="hljs-number">0</span>); <span class="hljs-comment">// Don't forget to wait here so child can execute</span>
      write(<span class="hljs-number">1</span>, <span class="hljs-string">"world\n"</span>, <span class="hljs-number">6</span>);
  }
</code></pre>
<p>  Forgetting this, make me stuck on the pingpong <strong>task.</strong></p>
</li>
</ul>
<ol start="2">
<li><p>When we define an array of <strong>int</strong> and another of <strong>char</strong>, like <code>int tab_1[5]</code> and <code>char tab_2[5]</code>, we know that <strong>tab_1</strong> and <strong>tab_2</strong> are pointers to the first element ([0]) of the array. Also, <code>tab_1[1]</code> is equivalent to <code>*(tab_1 + 1)</code>, and the same applies to <code>tab_2[1]</code>, which is equivalent to <code>*(tab_2 + 1)</code>..</p>
<ul>
<li><p>But if we assume that the memory address of <strong>tab_1</strong> is <strong>4000</strong> and the address of <strong>tab_2</strong> is <strong>5000</strong>, what will be the address of <code>tab_1[1]</code> and <code>tab_2[2]</code>? The address of <code>tab_1[1]</code> will be <strong>4000 + 4 bytes = 4004</strong>, not <strong>4001</strong>, since <code>sizeof(int) = 4 bytes</code> on most modern 32-bit/64-bit computers..</p>
<p>  Why? Because <strong>tab_1</strong> is a series of contiguous memory addresses that store integers, each with a size of 4 bytes (<code>sizeof(int)</code>). To move from one address or index to the next in the array, you need to step by 4 bytes. So, you move 4 bytes at a time. <code>tab_1[0]</code> occupies the memory blocks from <strong>4000 to 4003</strong>, and <code>tab_1[1]</code> starts at <strong>4004</strong>.</p>
<p>  The same rule applies to <strong>tab_2</strong>, but here <code>sizeof(char)</code> <strong>\= 1</strong>, so the address of <code>tab_2[1]</code> will be <strong>5000 + 1 byte = 5001</strong>.</p>
<p>  The rule is simple: <strong>New Address = Start Address + (N * sizeof(Type))</strong></p>
</li>
<li><p>But here's another question: when we use <code>*(tab_1 + 1)</code> or <code>tab_1[1]</code>, how does the compiler know to add <strong>N * sizeof(Type)</strong> to the initial address? Well, this is done at compile time when the compiler generates the assembly code. It uses a table called the Symbol Table, which holds information about variables, functions, and other elements in our code. This allows it to check the data type and perform the appropriate calculations..</p>
</li>
</ul>
</li>
</ol>
<p>From <strong>Gemini</strong></p>
<blockquote>
<p>When the compiler reads your source code, it builds an internal data structure called the <strong>Symbol Table</strong>. This table tracks every identifier (variable, function, type, etc.) in your program and records all its key attributes, including its data type.</p>
<p><strong>For a pointer variable declared as</strong> <code>int *p</code><strong>; the Symbol Table records that</strong> <code>p</code> <strong>is a pointer to an</strong> <code>int</code><strong>.</strong></p>
</blockquote>
<p><strong>Done for now, see you next time!</strong></p>
<p>It's good to write the utility and get back into C to remember these concepts before diving into OS.</p>
<p>I'm starting Week 2 of the course.</p>
<p>By the way, here's my GitHub repo for the lab course: <a target="_blank" href="https://github.com/TawalMc/MIT-6.1810Fall2025-xv6">https://github.com/TawalMc/MIT-6.1810Fall2025-xv6</a></p>
]]></content:encoded></item><item><title><![CDATA[Networking Programming: getaddrinfo]]></title><description><![CDATA[I was reading about network programming and sockets with Beej’s Guide to Networking Programming, and we ended up writing a simplified version of the nslookup program in C. This program takes a domain name and finds the IPs associated with it by query...]]></description><link>https://tawaliou.com/networking-programming-getaddrinfo</link><guid isPermaLink="true">https://tawaliou.com/networking-programming-getaddrinfo</guid><category><![CDATA[networking]]></category><category><![CDATA[Linux]]></category><category><![CDATA[System Programming]]></category><category><![CDATA[socket]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Wed, 15 Oct 2025 09:44:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1760520923083/971b37b2-dd91-4f21-8b8f-eaaf651341f3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I was reading about network programming and sockets with <a target="_blank" href="https://beej.us/guide/bgnet/html/split/">Beej’s Guide to Networking Programming</a>, and we ended up writing a simplified version of the <code>nslookup</code> program in C. This program takes a domain name and finds the IPs associated with it by querying the DNS. <em>nslookup does more than that</em>, but for us, it's impressive to create something similar. After that, I tried to build the same thing in Python and laughed at the result: just 3 lines of code.</p>
<p>So, I'll show you the C code first, followed by the Python code.</p>
<p><code>showip.c</code></p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> _POSIX_C_SOURCE 200112L</span>

<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;string.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;sys/types.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;sys/socket.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;netdb.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;arpa/inet.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;netinet/in.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;sys/socket.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span> <span class="hljs-keyword">const</span> *argv[])</span>
</span>{
    <span class="hljs-keyword">int</span> status;
    <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">addrinfo</span> <span class="hljs-title">hints</span>, *<span class="hljs-title">res</span>, *<span class="hljs-title">p</span>;</span>
    <span class="hljs-keyword">char</span> ipstr[INET6_ADDRSTRLEN];

    <span class="hljs-keyword">if</span> (argc != <span class="hljs-number">2</span>)
    {
        <span class="hljs-built_in">fprintf</span>(<span class="hljs-built_in">stderr</span>, <span class="hljs-string">"usage: showip hostname\n"</span>);
        <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
    }

    <span class="hljs-built_in">memset</span>(&amp;hints, <span class="hljs-number">0</span>, <span class="hljs-keyword">sizeof</span> hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    <span class="hljs-keyword">if</span> ((status = getaddrinfo(argv[<span class="hljs-number">1</span>], <span class="hljs-string">"80"</span>, &amp;hints, &amp;res)) != <span class="hljs-number">0</span>)
    {
        <span class="hljs-built_in">fprintf</span>(<span class="hljs-built_in">stderr</span>, <span class="hljs-string">"gai error: %s\n"</span>, gai_strerror(status));
        <span class="hljs-keyword">return</span> <span class="hljs-number">2</span>;
    }

    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"IP addressess for %s: \n\n"</span>, argv[<span class="hljs-number">1</span>]);

    <span class="hljs-keyword">for</span> (p = res; p != <span class="hljs-literal">NULL</span>; p = p-&gt;ai_next)
    {
        <span class="hljs-keyword">void</span> *addr;
        <span class="hljs-keyword">char</span> *ipver;
        <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">sockaddr_in</span> *<span class="hljs-title">ipv4</span>;</span>
        <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">sockaddr_in6</span> *<span class="hljs-title">ipv6</span>;</span>

        <span class="hljs-keyword">if</span> (p-&gt;ai_family == AF_INET)
        {
            ipv4 = (struct sockaddr_in *)p-&gt;ai_addr;
            addr = &amp;(ipv4-&gt;sin_addr);
            ipver = <span class="hljs-string">"IPv4"</span>;
        }
        <span class="hljs-keyword">else</span>
        {
            ipv6 = (struct sockaddr_in6 *)p-&gt;ai_addr;
            addr = &amp;(ipv6-&gt;sin6_addr);
            ipver = <span class="hljs-string">"IPv6"</span>;
        }

        inet_ntop(p-&gt;ai_family, addr, ipstr, <span class="hljs-keyword">sizeof</span> ipstr);
        <span class="hljs-built_in">printf</span>(<span class="hljs-string">" %s: %s\n"</span>, ipver, ipstr);
    }

    freeaddrinfo(res);
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>And now the <code>showip.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> socket
<span class="hljs-keyword">import</span> sys
<span class="hljs-keyword">from</span> socket <span class="hljs-keyword">import</span> AddressFamily

FAMILY_TYPE = {<span class="hljs-string">"AF_INET"</span>: <span class="hljs-string">"IPv4"</span>, <span class="hljs-string">"AF_INET6"</span>: <span class="hljs-string">"IPv6"</span>}
PORT = <span class="hljs-string">'80'</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    host = sys.argv[<span class="hljs-number">1</span>]
    <span class="hljs-keyword">try</span>:
        host_info = socket.getaddrinfo(host,  <span class="hljs-comment"># hostname</span>
                                       PORT,  <span class="hljs-comment"># hostname port</span>
                                       socket.AF_UNSPEC,  <span class="hljs-comment"># IPv4/IPv6</span>
                                       socket.SOCK_STREAM <span class="hljs-comment"># TCP,</span>
                                       flags=socket.AI_CANONNAME
                                       )
        <span class="hljs-keyword">for</span> info <span class="hljs-keyword">in</span> host_info:
            family = AddressFamily(info[<span class="hljs-number">0</span>]).name
            text = <span class="hljs-string">f"<span class="hljs-subst">{FAMILY_TYPE[family]}</span>: <span class="hljs-subst">{info[<span class="hljs-number">4</span>][<span class="hljs-number">0</span>]}</span> --&gt; <span class="hljs-subst">{info[<span class="hljs-number">3</span>]}</span>"</span>
            print(text)
    <span class="hljs-keyword">except</span> socket.gaierror:
        print(<span class="hljs-string">f"Hostname <span class="hljs-subst">{host}</span> could not be resolved."</span>, file=sys.stderr)
        <span class="hljs-keyword">return</span>

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    <span class="hljs-keyword">if</span> len(sys.argv) != <span class="hljs-number">2</span>:
        <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"usage: showip hostname"</span>)
    main()
</code></pre>
<p>When we run the Python code, we get this:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># [(&lt;AddressFamily.AF_INET: 2&gt;, &lt;SocketKind.SOCK_STREAM: 1&gt;, 6, 'hashnode.com', ('66.33.60.194', 8081)), (&lt;AddressFamily.AF_INET: 2&gt;, &lt;SocketKind.SOCK_STREAM: 1&gt;, 6, '', ('76.76.21.22', 8081))]</span>
$ IPv4: 66.33.60.194 --&gt;  hashnode.com
  IPv4: 76.76.21.22 --&gt;
</code></pre>
<p>We can see that even though the Python code is shorter, it uses a similar API to the C code. This is because Python simply wraps the <code>socket</code> API provided in C, which helps reduce some of the developer's workload. The key part is using <code>getaddrinfo</code> (get address info), which is defined like this::</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">getaddrinfo</span><span class="hljs-params">(<span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *node,
                <span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *service,
                <span class="hljs-keyword">const</span> struct addrinfo *hints,
                struct addrinfo **res)</span></span>;
</code></pre>
<pre><code class="lang-python">socket.getaddrinfo(host, port, family=<span class="hljs-number">0</span>, type=<span class="hljs-number">0</span>, proto=<span class="hljs-number">0</span>, flags=<span class="hljs-number">0</span>)

<span class="hljs-comment"># and returned value</span>
<span class="hljs-comment"># list if of tuples (family, type, proto, canonname, sockaddr)</span>
</code></pre>
<p>You can already see the similarity.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>C</strong></td><td><strong>Python</strong></td><td><strong>Description</strong></td><td><strong>Example</strong></td></tr>
</thead>
<tbody>
<tr>
<td><code>node</code></td><td><code>host</code></td><td><mark>Hostname</mark> or IP address</td><td><code>hashnode.com</code></td></tr>
<tr>
<td><code>service</code></td><td><code>port</code></td><td>The <mark>service type</mark> (“http”,…) or <mark>Port number</mark></td><td><code>80</code></td></tr>
<tr>
<td><code>hints</code> (structure)</td><td><code>family</code>, <code>type</code>, <code>proto</code></td><td><mark>Address family</mark> (IPv4/v6, …); <mark>Socket type</mark> (stream, datagram, …); <mark>Protocol</mark> (TCP, UDP, …)</td><td>family: <code>AF_INET</code> (IPv4), <code>AF_INET6</code> (IPv6), <code>AF_UNSPEC</code>(unspecified) type: <code>SOCK_STREAM</code> proto: <code>0</code> (any), if set to 0 and type to SOCK_STREAM the system will pick TCP</td></tr>
<tr>
<td><code>res</code> (Linked List)</td><td>list of (<code>family</code>, <code>type</code>, <code>proto</code>, <code>canonname</code>, <code>sockaddr</code>)</td><td>family, type, proto are the same as decrbed above; <mark>Canonical name</mark>: the true host name by the DNS (will read about it) sockaddr is a tuple of IP and Port</td></tr>
</tbody>
</table>
</div><p>In the C code, the result is stored in a linked list, and the head's address is passed to <code>getaddrinfo</code>. This is why we iterate over <code>res</code> and <code>res-&gt;ai_next</code>. In Python, the library takes care of this iteration, so we just go through the list of tuples until the end.</p>
<p>Why a list of IPs? Because a hostname can have multiple IPs (both IPv4 and IPv6) associated with it.</p>
<p>Good, right? Yeah, but I wondered how Python's <code>getaddrinfo</code> is implemented behind the scenes, so I asked ChatGPT, and it gave me this: <a target="_blank" href="https://chatgpt.com/s/t_68eba17bdb4481919241ce01a7890c5b">https://chatgpt.com/s/t_68eba17bdb4481919241ce01a7890c5b</a></p>
<p>You can read it to get some ideas (I didn't understand everything).</p>
<p><strong>Done for now, see you next time!</strong></p>
<p>It's great to see the work Python has already done for developers and how things operate behind the scenes with C. I'm currently learning about network programming, so there might be a future article on sockets or similar topics.</p>
]]></content:encoded></item><item><title><![CDATA[Learning Networkings Basics - Extension of a LAN]]></title><description><![CDATA[Three months ago, I began exploring networking with the Cisco Networking Basics course, and it was fun. Then, just a month later, I encountered a simple networking task, and I was glad I took the course. Not because the task was complex, but because ...]]></description><link>https://tawaliou.com/learning-networkings-basics-extension-of-a-lan</link><guid isPermaLink="true">https://tawaliou.com/learning-networkings-basics-extension-of-a-lan</guid><category><![CDATA[networking]]></category><category><![CDATA[System Programming]]></category><category><![CDATA[Linux]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Tue, 16 Sep 2025 22:37:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1758059657502/c1c54acc-7502-4850-8bb4-07b38eb5480f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Three months ago, I began exploring networking with the Cisco Networking Basics course, and it was fun. Then, just a month later, I encountered a simple networking task, and I was glad I took the course. Not because the task was complex, but because I understood each step and knew why I was doing what I did. Let me provide some background.</p>
<p>I used to subscribe to a monthly unlimited internet package from a popular Mobile Network Operator in my country, which is also an ISP (Internet Service Provider). I won't mention the company's name, so I'll call it OPERATOR. In my opinion, it was expensive and slow. It cost 15,000 XOF, about $27 per month, and once you used 25GB, your internet speed dropped from 2MB to 1MB. After using the first 25GB, the rest of the month was a struggle: the speed was slow, and you could barely browse websites other than YouTube. Under these conditions, taking online courses was tough. So, after some recommendations from friends, I decided to switch to another Mobile Network Operator that offers fiber optic for faster internet.</p>
<blockquote>
<p><strong>TL;DR:</strong> I'm really satisfied right now. I hope it stays this way.</p>
</blockquote>
<p>Now, here's the problem: the location where the fiber optic and main router were installed doesn't let my phone connect to the Wi-Fi when I'm in my room. The solution is to extend the network. The good news is that we have a second router at home. So, I need to connect the second router to the first one and place it near my room.</p>
<p>I did it, and it was easy. I just followed a few steps and asked chat.gpt if I had any doubts. I used the second router as a switch, so now I have one local network.</p>
<p>Let's name the router that comes with the optic fiber (the one provided by the ISP) <code>MAIN_ROUTER</code>, and the second one <code>SECOND_ROUTER</code>. Here are the steps and reasons:</p>
<ul>
<li><p>Get the <code>MAIN_ROUTER</code>'s configuration info:</p>
<ul>
<li><p>Access the admin page: The admin ID, password, and IP are on the back of the router.</p>
</li>
<li><p>Write down information like:</p>
<ul>
<li><p>Gateway (router address): This will be used by a host as the Destination IP Address for transmission outside of the LAN.</p>
</li>
<li><p>DNS server: It's important to save the correct address; otherwise, even if you have an internet connection, you can't reach websites.</p>
</li>
<li><p>IP range, subnet mask.</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p>Connect the <code>SECOND_ROUTER</code> to the first one through the LAN port (usually orange or yellow).</p>
</li>
<li><p>Configure the <code>SECOND_ROUTER</code> by:</p>
<ul>
<li><p>Change its mode to <mark>Bridge</mark> or <mark>Access Point</mark>, or select an option other than acting as a Router if available.</p>
</li>
<li><p>Entering the same configuration info listed above on its admin page.</p>
</li>
<li><p>Disabling its DHCP Server to ensure that the <code>MAIN_ROUTER</code> is the only one assigning IP addresses to hosts.</p>
</li>
<li><p>Giving it a static address outside the IP range of the <code>MAIN_ROUTER</code> but in the same subnet. For example, if the IP range of <code>MAIN_ROUTER</code> is <code>192.168.1.100</code> - <code>192.168.1.254</code> (and the subnet is <code>192.168.1.1/24</code>), you can set the <code>SECOND_ROUTER</code> IP address to <code>192.168.1.2</code>.<code>68.1.2</code>.</p>
</li>
</ul>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758060181747/d38364cd-7b41-4407-bb03-e1acbe73abc1.jpeg" alt="LAN ports on Router" class="image--center mx-auto" /></p>
<p>It's not really that complicated, but I like it.</p>
]]></content:encoded></item><item><title><![CDATA[Learning Networkings Basics - Next]]></title><description><![CDATA[After almost two months, I finished the Networking Basics course provided by the CISCO Networking Academy.
I started the course not only because I lacked knowledge in networking but also because I believe networking is an important part of the IT fie...]]></description><link>https://tawaliou.com/learning-networkings-basics-next</link><guid isPermaLink="true">https://tawaliou.com/learning-networkings-basics-next</guid><category><![CDATA[networking]]></category><category><![CDATA[Linux]]></category><category><![CDATA[systemprogramming]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Fri, 25 Jul 2025 11:05:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1753440398443/39c1695a-2ba1-4929-8ac3-bf1fb2713802.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>After almost two months, I finished the <a target="_blank" href="https://www.netacad.com/courses/networking-basics?courseLang=en-US">Networking Basics</a> course provided by the CISCO Networking Academy.</p>
<p>I started the course not only because I lacked knowledge in networking but also because I believe networking is an important part of the IT field. Now that I have completed the course, I am more comfortable with terms like subnet, broadcast domain, DNS resolver, and others when reading articles or documentation for tools I use daily.</p>
<p>Here are some things I appreciated about the course:</p>
<ul>
<li><p>Well-written chapters with clear use cases and illustrations</p>
</li>
<li><p>Short videos with good explanations and visuals, each lasting a maximum of 8 minutes <em>(I prefer text over video when studying)</em></p>
</li>
<li><p>Practice chapters using CISCO Packet Tracer</p>
</li>
<li><p>Short and long exams after each chapter, featuring multiple-choice questions to assess learners' knowledge</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752308218828/8e03c077-4f31-4411-84ba-4a17760e64dc.png" alt class="image--center mx-auto" /></p>
<p>I really appreciate the course's structure and highly recommend it.</p>
<p>What's next? I'm continuing with network programming because there are still things I need and want to learn in this area. I started with Beej's networking guide.</p>
]]></content:encoded></item><item><title><![CDATA[Learning Networkings Basics - 4]]></title><description><![CDATA[In this new blog post, I'll explain what I learned about how data is transmitted within and outside a LAN on Layer 2 of the TCP/IP model. It's important to remember that on Layer 2, a host can send data to other hosts if it knows their IP addresses.
...]]></description><link>https://tawaliou.com/learning-networkings-basics-4</link><guid isPermaLink="true">https://tawaliou.com/learning-networkings-basics-4</guid><category><![CDATA[Linux]]></category><category><![CDATA[networking]]></category><category><![CDATA[systemprogramming]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Thu, 17 Jul 2025 17:25:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752773097079/59a39d0c-492a-40b2-93fa-c5125c2ddec7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this new blog post, I'll explain what I learned about how data is transmitted within and outside a LAN on Layer 2 of the TCP/IP model. It's important to remember that on Layer 2, a host can send data to other hosts if it knows their IP addresses.</p>
<p>To illustrate this, let's use this network schema as an example.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752706780789/4a7db267-d418-46fc-9207-9c105d39e7c5.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-transmission-inside-a-lan">Transmission inside a LAN</h2>
<p>Let’s say <strong>Host 1</strong> wants to send data or packets to <strong>Host 2</strong>. Both hosts are in the same LAN. There are two possible scenarios: either Host 1 already knows Host 2's MAC address, or Host 1 only knows Host 2's IP address but not the MAC address.</p>
<h3 id="heading-mac-addr-is-known">MAC Addr is known</h3>
<p>In this case, Host 1's ARP table already contains the IP and MAC addresses of Host 2, making the process straightforward.</p>
<p>In fact:</p>
<ol>
<li><p>Host 1 will put its IP and MAC addresses in the source address sections, then use Host 2's IP and MAC addresses as the destination and send the packet to switch S1.</p>
</li>
<li><p>At switch S1, after it de-encapsulates the frame, it will check its MAC Address Table to see if there is a port associated with the destination MAC. If yes, it will forward the frame to this port. If not, it will broadcast the message to all ports except the sending port. In this last case, the frame will be processed only by the host with the corresponding MAC address; others will discard it.</p>
</li>
</ol>
<p>You can get more information about this case in this article I wrote on <a target="_blank" href="https://tawaldevuniverse.hashnode.dev/learning-networking-basics-2">Ethernet and Switch</a>.</p>
<h3 id="heading-mac-addr-is-not-known">MAC Addr is not known</h3>
<p>Host 1's ARP table doesn’t contain the IP and MAC addresses of Host 2. Therefore, before sending the packets, Host 1 will try to discover the MAC address of Host 2 with an ARP request. ARP stands for <strong>Address Resolution Protocol.</strong> So, what happens is an intermediate step where:</p>
<ol>
<li><p>Host 1 will send a Broadcast MAC addr frame with the IP address of Host 2.</p>
</li>
<li><p>Switch S1 will forward it to all ports (except the sending one), and each of the hosts connected to the switch will compare the IP addr in the frame to their own IP.</p>
</li>
<li><p>The corresponding host (Host 2) will be the only one to reply and will send back its MAC addr.</p>
</li>
<li><p>Host 1 will then store the MAC addr in its ARP Table and will set the destination MAC addr of the frame with this new value.</p>
</li>
<li><p>Then the packets will be sent following the steps in the case of <strong>MAC Addr is known (above)</strong>.</p>
</li>
</ol>
<p><strong>Note: Routers</strong> do not forward broadcast domain packets, so <strong>Host A and B</strong> will not receive these packets.</p>
<p>Here is the Ethernet Frame that will be sent (this is a simplified version)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752561216182/fcc0c075-43ff-406d-8423-9a40bb506074.png" alt class="image--center mx-auto" /></p>
<p>Following text summarise what’s said in this paragraph.</p>
<blockquote>
<p>The method that a host uses to send messages to a destination on a remote network differs from the way a host sends messages on the same local network. When a host needs to send a message to another host located on the same network, it will forward the message directly. A host will use ARP to discover the MAC address of the destination host. The IPv4 packet contains the destination IPv4 address and encapsulates the packet into a frame containing the MAC address of the destination and forwards it out.</p>
</blockquote>
<p><em>from cisco</em></p>
<h2 id="heading-transmission-outside-a-lan">Transmission outside a LAN</h2>
<p>The transmission of a packet outside a LAN is done at Layer 2 of the <strong>TCP/IP</strong> model; the Internet Layer. So we need the IP of the destination host. At this layer, we necessarily need a <strong>Router</strong> to route the traffic (transmit the packet) outside the LAN. So what happens?</p>
<p>Let's suppose that <strong>Host 1</strong> wants to send a packet to <strong>Host B</strong>.</p>
<ul>
<li><p>The Destination MAC addr will be the Default Gateway MAC addr in the LAN: <strong>XXXX</strong>, then</p>
</li>
<li><p>The Router will:</p>
<ul>
<li><p>get the frame,</p>
</li>
<li><p>de-encapsulate it,</p>
</li>
<li><p>evaluate the best path by which to send the packet,</p>
</li>
<li><p>replace the DEST MAC Addr with the next Router MAC Addr,</p>
</li>
<li><p>replace the SRC MAC Addr with its MAC Addr in the new LAN: <strong>QQQQ</strong>,</p>
</li>
<li><p>send the packet.</p>
</li>
<li><p>The next router does the same thing, but if it’s the last router and the packet is already in the DEST LAN, it puts its MAC Addr in the LAN as SRC MAC addr.</p>
</li>
</ul>
</li>
</ul>
<p>As the last router and the destination host are in the same LAN, the steps in <strong>“Transmission inside a LAN”</strong> will be executed to either get and set the destination MAC addr of the packet or send the packet if the destination MAC addr is already known.</p>
<p>The following text summarizes what's said in this paragraph.</p>
<blockquote>
<p>When a host needs to send a message to a remote network, it must use the router. The host includes the IP address of the destination host within the packet just like before. However, when it encapsulates the packet into a frame, it uses the MAC address of the router as the destination for the frame. In this way, the router will receive and accept the frame based on the MAC address.</p>
</blockquote>
<p><em>from cisco</em></p>
<p>The picture below shows changes in the packet sent from a LAN to another.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752709245124/5455155a-8e44-4246-8b47-5365cc95e4ce.png" alt class="image--center mx-auto" /></p>
<p>Magic, right? I really like how networking is designed, and I wonder how the field developed like that.</p>
]]></content:encoded></item><item><title><![CDATA[Learning Networking Basics - 3]]></title><description><![CDATA[Continuing my study of networking basics, I learned about the Router, which is part of the Network Layer (Layer 3) of the OSI Model and the Internet Layer (Layer 2) of TCP/IP. I'll keep it brief and share some interesting things I learned about DHCP,...]]></description><link>https://tawaliou.com/learning-networking-basics-3</link><guid isPermaLink="true">https://tawaliou.com/learning-networking-basics-3</guid><category><![CDATA[networking]]></category><category><![CDATA[systemprogramming]]></category><category><![CDATA[Linux]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Thu, 03 Jul 2025 00:11:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752773066420/4516ff67-c8a4-4490-965b-f70bf54a1985.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Continuing my study of networking basics, I learned about the <strong>Router</strong>, which is part of the <strong>Network Layer (Layer 3)</strong> of the <strong>OSI Model</strong> and the <strong>Internet Layer (Layer 2)</strong> of <strong>TCP/IP.</strong> I'll keep it brief and share some interesting things I learned about DHCP, routing, ARP, and generally how packets move from a LAN to a remote LAN.</p>
<h2 id="heading-dhcp">DHCP</h2>
<p>DHCP stands for <strong>Dynamic Host Configuration Protocol</strong> and allows hosts to be dynamically assigned IP addresses (IPv4/IPv6). So, you’re not required to know the range of addresses available for hosts in the network, and even if the host restarts, it will automatically get an IP. To have DHCP configured on the host, you need a DHCP Server from which the host will get its IP <em>dynamically.</em> The following are the steps that occur when DHCP is configured (in four steps):</p>
<ol>
<li><p>Host (which is a <strong>DHCP Client</strong>) sends a <strong>broadcast</strong> (255.255.255.255) message <strong>«DHCP DISCOVER»</strong> to the <strong>DHCP server</strong> asking for an IP.</p>
</li>
<li><p>The DHCP server responds back with a <strong>unicast</strong> or <strong>broadcast</strong> message, a <strong>«DHCP OFFER»</strong> that contains an IP + Subnet mask (like 192.168.11.2 + 255.255.255.0) for the new host.</p>
</li>
<li><p>The host responds with a <strong>broadcast</strong> message, a <strong>«DHCP REQUEST»</strong> asking for confirmation to use the IP sent.</p>
</li>
<li><p>DHCP confirms with an <strong>ACKNOWLEDGMENT,</strong> a unicast/broadcast message <strong>«DHCP ACK»</strong> sent back that confirms to the host that it can use the IP sent above.</p>
</li>
</ol>
<p>Next, here's a diagram that shows the flow when a DHCP Client request an IP</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751180796587/25a23a21-3e71-49d7-ba2a-97bf5e0ca738.png" alt class="image--center mx-auto" /></p>
<p>Two additional interesting facts:</p>
<ul>
<li><p><em>Your</em> <strong><em>Router</em></strong> <em>(modem) can act like a DHCP Server and provide IPs dynamically to hosts that are connected to it.</em></p>
</li>
<li><p><em>Normally, you can manually configure your devices (phone, computer) to request IPs dynamically, but usually these devices are set by default to use DHCP to automatically request an IP.</em></p>
</li>
</ul>
<p>Now, if you want to implement the DHCP Protocol in C/Linux yourself, you can follow this post, <a target="_blank" href="https://www.linkedin.com/pulse/understanding-dhcp-socket-functions-david-zhu-sfgvc/?trackingId=c6sWj1mDQEmBFtRb3DmmKg%3D%3D"><strong>Understanding DHCP with Socket Functions</strong></a> by <a target="_blank" href="https://www.linkedin.com/in/david-zhu-3a68a855/">David Zhu</a> (LinkedIn), who publishes good and in-depth content on Networking.</p>
<p>So briefly, this is what happens when our phone/computer connects to Wi-Fi and automatically gets an IP address without us needing to do any configurations.</p>
<p>Now, let’s talk a little bit about routers.</p>
<h2 id="heading-router">Router</h2>
<p>Let’s list some properties of a Router:</p>
<ul>
<li><p>A router allows communication between different LANs or with a remote network. So a host in the LAN <strong>192.168.2.5/24</strong> can send a message to a host in the LAN <strong>192.168.3.4/24</strong>.</p>
</li>
<li><p>A router can act as a DHCP Server for hosts in a LAN and be a DHCP Client within an Internet Service Provider (<strong>ISP</strong>) to get an IP for internet communication.</p>
</li>
<li><p>The <strong>Default Gateway</strong> is the router’s IP in a LAN. So each LAN has its Default Gateway within the router.</p>
</li>
<li><p>Has an ARP (Address Resolution Protocol) Table: <strong>{MAC Addr, IPv4 Addr}</strong></p>
</li>
<li><p>Has a Routing table: <strong>{Port, Network IPv4 Addr, Type of connection}</strong> and best paths to reach a network</p>
</li>
</ul>
<p>Here is an example of a router with its address.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751399332286/52350fcb-b7ae-4c9d-9068-634122a2a386.jpeg" alt class="image--center mx-auto" /></p>
<p>That is it.</p>
<p>There is a lot to say about Router and DHCP, but I think now we can understand a little bit about them with this information. I am open to any suggestions regarding improvements to what is said in this article.</p>
<p>And in the next article, I’ll write about: <strong>How a host sends data to a host in the same LAN and in a remote LAN</strong> (yes, we’ll talk about Router again).</p>
]]></content:encoded></item><item><title><![CDATA[Learning Networking Basics - 2]]></title><description><![CDATA[Continuing my learning on networking basics, I learned about the Ethernet Switch, which is part of the physical layer of the OSI Model and the Network Access Layer of TCP/IP. I also discovered some interesting details about how the Ethernet switch fo...]]></description><link>https://tawaliou.com/learning-networking-basics-2</link><guid isPermaLink="true">https://tawaliou.com/learning-networking-basics-2</guid><category><![CDATA[networking]]></category><category><![CDATA[systemprogramming]]></category><category><![CDATA[Linux]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Mon, 16 Jun 2025 05:17:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752773033346/f9eac597-791f-470d-a341-8f95c08d64a8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Continuing my learning on networking basics, I learned about the <strong>Ethernet Switch</strong>, which is part of the physical layer of the <strong>OSI Model</strong> and the Network Access Layer of <strong>TCP/IP.</strong> I also discovered some interesting details about how the Ethernet switch forwards packets.</p>
<h2 id="heading-ethernet-switch">Ethernet switch</h2>
<h3 id="heading-ethernet-frame">Ethernet Frame</h3>
<p>The Ethernet switch, or simply switch, lets devices connect within a LAN. Its job is to forward or transmit packets (also known as <strong>Ethernet Frames</strong>) from a source device to a destination device using the MAC address of the <strong>Network Interface Card (NIC)</strong> in each device. A packet is just a sequence of bits (0s and 1s).</p>
<p>In the image below, you can see an example of a packet.</p>
<p><img src="https://huseyinpala.site/wp-content/uploads/2023/04/ethernet-frame-format.png" alt="Picture 1- Ethernet Frame Yapısı – Huseyin Pala" class="image--center mx-auto" /></p>
<p>So, we might ask, in a LAN, <strong>how does the switch know the device's MAC address to determine where to forward a packet</strong>? Let's look at this picture of a simple LAN.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749679778822/976f2017-7679-476f-b183-a4484ab6ac1c.jpeg" alt class="image--center mx-auto" /></p>
<p>My initial thought was that when a device connects to the LAN, it sends its NIC's MAC address to the switch, like a registration. This way, the switch would have the MAC addresses of all devices connected to the LAN, and when it receives a packet, it could use the destination MAC address in the packet to send it to the correct device.</p>
<p><strong>But that's not exactly how it works</strong>: In reality, the NIC in devices doesn't know if it's connected to a switch, so it doesn't need to send its MAC address. Also, the protocol must be designed to work independently of specific devices like the switch..</p>
<h3 id="heading-mac-address-table">MAC Address Table</h3>
<p>The switch has a MAC address table where it stores device MAC addresses along with the port each device is connected to.</p>
<p>When a packet is sent:</p>
<ol>
<li><p>The switch first checks if the <strong>Source Address</strong> is already in its MAC address table.</p>
</li>
<li><p>If it is, and the <strong>Destination Address</strong> is in the table, it forwards the packet to the port where the destination device is connected. If the <strong>Destination Address</strong> is not in the table, it broadcasts the packet to all ports except the source port.</p>
</li>
<li><p>If the Source Address is not in the table, the switch adds it with the corresponding port, then proceeds as in step 2, either broadcasting or directly forwarding the packet.</p>
</li>
<li><p>When a device connected to the switch receives the packet, it processes the packet if the Destination Address matches its MAC address; otherwise, it discards the packet.</p>
</li>
</ol>
<p>Here is a short illustration of this process: that.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749970586734/156aedd1-c872-4097-95fa-60a4681d5042.png" alt="Ethern frame foward politic by switch" class="image--center mx-auto" /></p>
<p>As we can see, it's a "simple" method to send packets and save MAC addresses simultaneously, using fewer resources. The table updates each time a new packet is sent.</p>
<p>Let me share another thing I learned about IPv4..</p>
<h2 id="heading-ipv4-network-host">IPv4 (Network + Host)</h2>
<p>In <strong>IPv4</strong>, there are <strong>Network</strong> and <strong>Host</strong> parts. The network part, also known as the <strong>Subnet</strong>, indicates which network the device is part of, while the host part identifies the specific device. Refer to the following image.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749972485360/890a606a-f9ee-4355-a7c9-ef55447304ea.png" alt="IPv4: Network + Host" class="image--center mx-auto" /></p>
<p>Here are a few things to understand:</p>
<ul>
<li><p>When we have an IPv4 address <strong>192.168.5.123/24</strong>, the <strong>24</strong> indicates that the first 24 bits (<strong>192.168.5.0</strong>) represent the network address.</p>
</li>
<li><p>The subnet mask, <strong>255.255.255.0</strong>, serves the same purpose as the <strong>24</strong>: it identifies the network. So, if we have these two pieces of information: <strong>192.168.5.123</strong> and <strong>255.255.255.0</strong>, it means that <strong>192.168.5.0</strong> is the network address.</p>
</li>
</ul>
<p>To conclude, there can be a broadcast address like <strong>192.168.5.255</strong>, which acts as a sub-group for devices with the same address. If a packet is sent to this address <strong>192.168.5.255</strong>, all devices with this broadcast address will receive the packet.</p>
<p>Now, on Linux, when we run <code>ifconfig -a</code> and see a display like the following, we understand what the second line means.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749994746836/b73dda91-efd9-4908-8289-7e7d38f13b06.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>There are many things I read, use, and see, but I don’t really understand their meanings. It's good to have a little bit of knowledge about them, like the whole world of networking.</p>
]]></content:encoded></item><item><title><![CDATA[Learning Networking Basics - 1]]></title><description><![CDATA[And I decided to learn networking fundamentals
Why ?
When I was working at YoupiLab as embedded software developer, my CEO told me multiple times that I need to learn networking basics that its a great part in IT. Now that I’m working as backend deve...]]></description><link>https://tawaliou.com/learning-networking-basics-1</link><guid isPermaLink="true">https://tawaliou.com/learning-networking-basics-1</guid><category><![CDATA[networking]]></category><category><![CDATA[Linux]]></category><category><![CDATA[ip address]]></category><category><![CDATA[router]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Tue, 03 Jun 2025 17:08:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752772995859/7b9256fe-3a68-44be-a966-1d3cfa752042.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>And I decided to learn networking fundamentals</p>
<h2 id="heading-why">Why ?</h2>
<p>When I was working at <a target="_blank" href="https://youpilab.com/">YoupiLab</a> as embedded software developer, my CEO told me multiple times that I need to learn networking basics that its a great part in IT. Now that I’m working as backend developer at <a target="_blank" href="https://uptimise.io/">Uptimise</a>, my Lead told me that if I want to advance in the field I need to be comfortable with Networking.</p>
<p>In fact, I don’t know too much about networking besides the fact that I can access my React application locally on <strong>localhost</strong> (<strong>127.0.0.1</strong>) and that generally, I need the <strong>IP address</strong> + <strong>Port</strong> to access an application, like <strong>127.0.0.1:3000</strong> for a React app 😅 (shame).</p>
<p>As I was interested in system programming, I thought, why not learn networking programming (system) at the same time? So I started this month with the <a target="_blank" href="https://www.netacad.com/courses/networking-basics?courseLang=en-US">Networking Basics</a> by Cisco Academy.</p>
<h2 id="heading-first-steps">First Steps</h2>
<p>The course seems good, with around 17 chapters, and the first 4 are about generalities (<em>I’m at chapter 5</em>). It provides good information to conceptualize what networking is, with the support of Cisco Packet Tracer to design networks.</p>
<p>These insights made me realize some things I did in the past but didn’t really understand because I searched “How to” on Google. It’s not bad, but now, I’m gradually understanding why some things are done in certain ways.</p>
<p>For example:</p>
<ul>
<li><p>On a router (even a wireless router), there is a built-in switch that allows devices to connect to the local network (LAN).</p>
</li>
<li><p>The ports usually colored in yellow or orange on a router are for LAN, and the usually blue port (one) is for the internet or Wide Area Network (WAN). That’s why when we want a device to be wired to the router, we connect it to the yellow ports through these (you know) cables with multiple colors.</p>
</li>
</ul>
<p>Basics right ? Yes, that’s why the course is named so.</p>
<p>There is an analogy that I get at this point that helps me remember all of these terms (IP address, LAN, WLAN, Gateway, Subnet Mask, Router, ISP, …):</p>
<blockquote>
<p>The IP addresses for the end devices can range from 192.168.0.2 - 192.168.0.254. <mark>Each device will get a unique IP address in the same network</mark>.</p>
<p>The <mark>subnet mask</mark> is used to <mark>differentiate the host</mark> and <mark>the network ID portion of the IP address</mark>. You can relate the <mark>IP address to your street address</mark>. The <mark>subnet mask defines the length of the street name</mark>. The network part of the address is your street, 192.168.0. <mark>The house number is the host port of the IP address</mark>. For the <mark>IP address 192.168.0.2</mark>, the <mark>house number is 2</mark> and the <mark>street is 192.168.0</mark>. If there is more than one house on the same street, for example, house number 3, will have an address 192.168.0.3. The maximum number of houses on this street is 253, ranging from 2 to 254.</p>
<p><mark>The default gateway is analogous to the street intersection</mark>. The traffic from the 192.168.0 street has to <mark>exit through the intersection to another street</mark>. Another street is another network. In this network, <mark>default gateway is the wireless router</mark> that directs the traffic from the local network to the cable modem, and the traffic is then sent to the ISP.</p>
<p>From Networking Basics by CISCO Academy.</p>
</blockquote>
<p>I understand that the <strong>default gateway</strong> that we read when doing Router config is the Router IP address, simple !</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The first 4 chapters may seem boring because the general info is already known, but from chapter 5, it starts to get really technical. As Linux networking is built on top of this knowledge, I hope at the end of the course to be able to understand more about Linux networking.</p>
]]></content:encoded></item><item><title><![CDATA[[Monthly Update] February 2025]]></title><description><![CDATA[Sys Prog, Coding Challenges, Go, Container, Linux Internal,
February 2025, I built a Linux utility in Go, learnt about how container are built (in Linux environment) and planning to learn about Linux Driver (Kernel Module). Here are some details.
Sys...]]></description><link>https://tawaliou.com/monthly-update-february-2025</link><guid isPermaLink="true">https://tawaliou.com/monthly-update-february-2025</guid><category><![CDATA[systemprogramming]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Linux]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Fri, 16 May 2025 11:57:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741079377997/7387d16f-1019-4427-9019-8a9ec2662e47.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Sys Prog, Coding Challenges, Go, Container, Linux Internal,</p>
<p>February 2025, I built a Linux utility in Go, learnt about how container are built (in Linux environment) and planning to learn about Linux Driver (Kernel Module). Here are some details.</p>
<h2 id="heading-sys-prog-coding-challenges-go">Sys Prog, Coding Challenges, Go</h2>
<p>I try <a target="_blank" href="https://codingchallenges.fyi/challenges/challenge-wc">Build your Own wc tool</a> by The Coding challenges in Go. The challenge is to rewrite in the langage of your choice from scratch the word counter utility found in Linux environment. And you have the freedom to expand the features. wc prints the number of lines, words, characters, bytes of file(s). You can read more details in the links I paste above.</p>
<p>In my case, I built it, and add some sugar features:</p>
<ul>
<li><p>handle multiple files: I use goroutines so the process of multiple files with the same size will took approximatively the amount of time of on file of the same size (good !)</p>
</li>
<li><p>nice output: in my case the output is like</p>
</li>
</ul>
<pre><code class="lang-typescript"> l: <span class="hljs-number">111</span>, w:<span class="hljs-number">100</span>, m: <span class="hljs-number">200</span>, c: <span class="hljs-number">200</span> text.txt
</code></pre>
<ul>
<li>I’ll add(I forget this feature) to get argument from standard input and not only from files.</li>
</ul>
<p>While doing this project, I learnt more about</p>
<ul>
<li><p><a target="_blank" href="https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/">unicodes, characters sets</a> and how Go handle them <a target="_blank" href="https://go.dev/blog/strings">here</a>: Go characters are known as Rune(😏)</p>
</li>
<li><p>newline vs number of lines</p>
</li>
</ul>
<h2 id="heading-container-under-the-hood">Container: under the hood</h2>
<p>I try to understand how containers like Docker are made and try to build a container from scratch. And even if I didn’t go to too far, I have learnt many things. And Yes: <strong>Linux</strong> is awesome, incredible as OS.</p>
<p>A container in Linux env, is based on: namespaces and cgroups. Namespaces help to have process in isolation and <strong>cgroups</strong> to put limit on ressources (memory, cpu, storage...) used by process</p>
<p>Here are the namespaces under linux:</p>
<ul>
<li><p><strong>Mount (mnt)</strong>: for mount points and provide a complete filesystems to the process which is now different of the host filesystems. <strong>That’s why you’ve a complete filesystems (root, dev, home with access) when you’re inside a container.</strong></p>
</li>
<li><p><strong>Process ID (pid)</strong>: a parent process with an ID can see other process but its children only see process from the same parent. <strong>That’s why when you’re inside a container you don’t get PID from applications/process outside the container.</strong></p>
</li>
<li><p><strong>Network</strong> <strong>(net):</strong> this namespace virtualize the network stack. <strong>You remember Docker Network ? Yeah this is the namespace that provide this capabilities</strong>: having your own network isolation inside on the host</p>
</li>
<li><p><strong>User</strong> <strong>ID</strong> (user): This namespace provide you everything related to user and their management: access/privilege, groups. <strong>You remember when creating a Docker image you can specify the user with USER command and create group ?</strong></p>
</li>
<li><p><strong>Inter-process Communication</strong> (System V IPC)</p>
</li>
<li><p><strong>UTS</strong> (Unix Time-Sharing, hostname): with this you have can hostname, DNS for specific process</p>
</li>
</ul>
<p>Here are some details about <a target="_blank" href="https://en.wikipedia.org/wiki/Linux_namespaces">Linux Namespaces</a> and <a target="_blank" href="https://en.wikipedia.org/wiki/Cgroups">Linux cgroups</a>.</p>
<p><a target="_blank" href="https://www.lizrice.com">Liz Rice</a> give many talks on how to build a simple and lightweight <a target="_blank" href="https://www.youtube.com/watch?v=8fi7uSYlOdc">container system from scratch in Go</a></p>
<p>I don’t know but, I think it’s the main reason why Docker is not avalable on Windows without WSL.</p>
<p>Right, hope you learn something from this articles, I’ll be back for sure.</p>
]]></content:encoded></item><item><title><![CDATA[[Monthly Update] January 2025]]></title><description><![CDATA[Sys Prog, Go, DSA-LeetCode, Django authentication and permission
Sys Prog
I was lazy to read more about process and how executable are running in Unix environment, let’s hope that until the end of the month I do it
Go
I decided to learn Go this year....]]></description><link>https://tawaliou.com/monthly-update-january-2025</link><guid isPermaLink="true">https://tawaliou.com/monthly-update-january-2025</guid><category><![CDATA[review]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[systemprogramming]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Tue, 04 Mar 2025 09:00:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741079164779/ab0c3c4f-94d3-43f5-a1b1-562f6ee846fd.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Sys Prog, Go, DSA-LeetCode, Django authentication and permission</p>
<h2 id="heading-sys-prog">Sys Prog</h2>
<p>I was lazy to read more about process and how executable are running in Unix environment, <strong><em>let’s hope that until the end of the month I do it</em></strong></p>
<h2 id="heading-go">Go</h2>
<p>I decided to learn Go this year. And I found a good website to learn it: <a target="_blank" href="https://quii.gitbook.io/learn-go-with-tests">Learn Go with tests</a>. It teaches it by using a Test Driven Development (TDD) approach and I like it. I could read the syntax, start quickly with some projects on CodingChallenges but I choose to learn with this technique and after I’ll do the codingchallenges projects. So now I did:</p>
<ul>
<li><p>Hello world, an introduction to TDD, Go module, how we could structure a Go projects and integers chapters.</p>
</li>
<li><p>The loop chapter. Go has just one loop statement: the <strong>for-loop</strong> that can be used in different way</p>
</li>
<li><p>Array and slices: array a static list with the size encoded in the type and slice a dynamic version of array</p>
</li>
</ul>
<h2 id="heading-dsa-leetcode">DSA-LeetCode</h2>
<ul>
<li>Some exercises on LeetCode based on patterns: Sliding Window</li>
</ul>
<h2 id="heading-django-auth-permissions">Django Auth + Permissions</h2>
<p>Here a start a toy project to deep dive into Django auth and permissions like:</p>
<ul>
<li><p>I’m using: Django+Django REST Framework+Django Allauth+Django Rest Auth</p>
</li>
<li><p>having two apps with two user’s models for the authentication: I finally use two models for each kind of user and they inherited from a main user with few attributes which is used in the authentication flow.</p>
</li>
<li><p>I’ll write some custom permissions and tests some stuffs</p>
</li>
<li><p>I’m also interested to try an IAM like Authelia(no keycloak is huge we’re using it in my work)</p>
</li>
</ul>
<h2 id="heading-system-design">System Design</h2>
<p>I started to read about sys design: lazy to work on syst design. I think I like read more about syst prog and kernel (lol)</p>
]]></content:encoded></item><item><title><![CDATA[Dev Retro 2024:]]></title><description><![CDATA[Sorry if here are many errors and typos in this articles, but I’m trying to improve my writing in english.
I’ll try in this article to talk a little bit about what happens to me inthis year (2024), my failures, my success, what I learn, what I don’t ...]]></description><link>https://tawaliou.com/dev-retro-2024</link><guid isPermaLink="true">https://tawaliou.com/dev-retro-2024</guid><category><![CDATA[Developer]]></category><category><![CDATA[systemprogramming]]></category><category><![CDATA[yearinreview]]></category><category><![CDATA[backend developments]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Mon, 30 Dec 2024 21:46:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735594178128/08c2aee1-9e9a-42ef-a289-e7524d43bda6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Sorry if here are many errors and typos in this articles, but I’m trying to improve my writing in english.</em></p>
<p>I’ll try in this article to talk a little bit about what happens to me inthis year (2024), my failures, my success, what I learn, what I don’t still understand. Why Dev Retro ? In 2023 I competed for <a target="_blank" href="https://tawaldevuniverse.hashnode.dev/dev-retro-2022-beginning-of-my-professional-career">Hashnode DevRetro 2022</a> and it was the name of the competition, and I like it, so</p>
<h2 id="heading-introduction">Introduction</h2>
<p>Ok, so first of all, I’m trying to restart with my blog. I started blogging in 2020-2021 but I was not regular so I’m planning to restart and write a monthly update about my work (mostly). I think this will help me to track my progress so I’ll write more for me and on my studies and works monthly.</p>
<p>2024 ? I was (and I’m still) still looking for answers to many questions ! It was a nice year, many struggles, a lot of works, a lot of reflexions. Mostly around my work as backend developper at <a target="_blank" href="https://www.uptimise.io/">Uptimsie</a> (even if I was doing fullstack tasks 😅) and my personal work: online courses.</p>
<h2 id="heading-at-work">At work</h2>
<p>So at work, it went well (I think). We’ve started to port and update Uptimise Benin codebase to Ivory-Coast. I suppose that it’s what we call “scale” right ? Anyway, we need to change some parts of our services to handle in the way Ivory-Coast manage human ressources. We are talking about: operations, default setup, flow and so on. So we need everything related to the technique to work well: API, services, CI/CD. The CI/CD part you know and I know that it’s not me (😅). Our Lead did it. Like always !</p>
<p>And guess what ? I was appointed to lead the development of Uptimise Ivory-Coast. I was not hyped, it’s good, but at the beginning I was not so interested: you’ll be sometimes the first that the CEO will call if there is problem. Can you imagine ? A lot of responsabilities ! And this is what our Lead did so far.</p>
<p>But we know that it’s a normal thing, learn to lead some colleagues, be the one that a bug in production is assigned to, to resolve it asap. It’s normal for a career evolution ! And guess what again, I finally liked it 😂. You know why: I could assign an issue to our interns or delegate some tasks that are important but could boring me to them 😂. I know it’s malicious but I love it.</p>
<p><strong>Fun Fact</strong>: Our Lead gave me access to some environments/servers and the first time I run our CI/CD after some updates, I broke things in production. I was like: “Damn, why this happen the first time I got the access, am I so bad !”</p>
<p>After May I think, I started to get tired, there was a lot of work to do for a small team like ours. And as I was responsible of some microservices when we building the Benin’s version, I’ve asked our Lead to do some refactoring in thes services for Ivory-Coast version. Don’t ask me why 😂. Sometimes I make a “git blame” and was shocked that I wrote some parts of the running code. I was like: “How could someone wrote this “shit” code" and the lead will look at you like (I’m sure he thinks something like): “are serious, you don’t know that your shit code is every where”. <strong>Let’s praise the <s>Clean Code</s> Shit Code.</strong></p>
<p>I finally did the refactoring for a part of one service, I love it. And it’s one of the reason (personally) I dont like freelancing or projects that you deliver to a client after few months and forget about it. I like to see the evolution of my own code, learn to improve it. If I cannot understand my own code after some months I suppose others could not too.</p>
<p>And now what I’ve learned from my work:</p>
<ul>
<li><p>Good comunication is the key: inside the teams, with those who are outside (CEO, product designer)</p>
</li>
<li><p>I don’t like to talk with the clients, be in discussion with them, maybe it’ll change but (you’ll learn from the next section) I prefer to stay in background do my job, get paid and it’s all. Everything related to “meeting”, “talk”, “long discussion” just annoyed me.</p>
</li>
<li><p>It’s good to have some elders that advise you on how to do some stuffs.</p>
</li>
<li><p>And <strong>there is so much to learn as a backend developer</strong> that sometimes I doubt that I could handle it.</p>
</li>
<li><p>Learn as I much you could, as much you and leave the rest in the hand of…God !</p>
</li>
<li><p>Progress at your own pace. You are only competing with yourself and your past versions.</p>
</li>
</ul>
<h2 id="heading-personal">Personal</h2>
<p>I love personal plans, personal works, why ? Because it’s the only time that you’ve for yourself to do dumb, cool, shit, things ! But if you don’t find a good balance with your work, you could loose everywhere.</p>
<h3 id="heading-backend-dev-is-great-but">Backend dev is great but…</h3>
<p>I’m interested by learning low level stuffs too. Not “Embedded System” particularly because what I love is not to design the electrical circuit or build a hardware. But I’m more interested with the code that run on these hardware. It’s technically called: “Embedded software” or “System Programming”. You know the topics like: process and memory management, file system, devices drivers. I finally understood it after studying the Nand To Tetris course.</p>
<p><strong>I was able to study from “October 2023” to “July 2024” (10 months) a course about these thing even if I’m not sure that one day I’ll need it.</strong></p>
<p>So now let’s talk in depth about my personal work in 2024</p>
<h3 id="heading-online-low-level-courses">Online Low Level Courses</h3>
<p>Online Low Level Courses (it’s a fake study) that I’ve imagined for my self to study system programming.</p>
<p>It contains:</p>
<h4 id="heading-from-nand-to-tetris-building-a-modern-computer-from-first-principles">From Nand To Tetris: Building a Modern Computer From First Principles</h4>
<p>From Nand to Tetris: Building a Modern Computer From First Principles is a populare online course available on <a target="_blank" href="https://www.coursera.org/learn/build-a-computer">Coursera</a> that I studied from <strong>October 2023</strong> to <strong>July 2024.</strong> It’s in two parts:</p>
<ul>
<li><p>Hardware: Logic gate, CPU, RAM, ALU and Registers implementations in HDL, Assembly Language,</p>
</li>
<li><p>Software: Jack programming language, Virtual Machine, Compiler, OS and their respective implementations</p>
</li>
</ul>
<p>I enjoy study this course during my weekends and the nights. I was able to complete it (without the OS part) even if I was tired from daily tasks at work.</p>
<p>After this course I’ve two ooptions: OS concepts and compiler. I choose OS because I think it could help me to understand more backend development and become one day may be “Infrastructure Engineer” or “Platform Engineer”.</p>
<p>If you want to know more about my experience while studying Nand2tetris, I wrote a more detailed thread about it on <a target="_blank" href="https://x.com/Tawal_Mc/status/1817517566572507174">Twitter</a></p>
<h4 id="heading-advanced-embedded-linux-development-specialization-by-cu-boulder">Advanced Embedded Linux Development Specialization by CU Boulder</h4>
<p>I’ve started to study the course <a target="_blank" href="https://www.coursera.org/learn/linux-system-programming-introduction-to-buildroot/home/welcome">Linux System Programming and Introduction to Buildroot</a> which is the first part of <a target="_blank" href="https://www.coursera.org/specializations/advanced-embedded-linux-development">Advanced Embedded Linux Development Specialization</a>. This course introduce me to the linux kernel source code and the linux system programming: fork, execv, thread, kernel cross-platform build, …<br />They provide short and well explained videos with assignment to complete. In addition they are two books as ressources to read: “The Linux System Programming” and “Mastering Embedded Linux Programming”.</p>
<h3 id="heading-rejection-for-master-application">Rejection for master application</h3>
<p>I applied for two masters and was rejected by both (I was shocked):</p>
<ul>
<li><p>embedded system in five universities in France.</p>
</li>
<li><p>electrical and computer engineering at CMU.</p>
</li>
</ul>
<p>I re-apply again for the last one and now I don’t know even if i’m accepted I’ll go to do it.</p>
<p>Why ? Now that I understand that I could learn system programming by myself and that it’s what I like in embedded system field and that backend dev is cool too, I was less attracted by the master.</p>
<h2 id="heading-next-years">Next Year(s)</h2>
<p>You kow backend development is paying my bills and until I was able to land a job in system programming I’ll try to improve my skills in backend development. There’s no doubt about it. I started to love it, what do you want, it’s what help me to buy my courses, so 😂. But for the next year it’s simple:</p>
<ul>
<li><p><strong>Backend development,</strong> I’ll continue to learn about : System Design, Django or a new backend framework, microservice, complex stuffs, data base</p>
</li>
<li><p><strong>Data Structure and Algorithm</strong>: I need to up my skill in this area</p>
</li>
<li><p><strong>System Programming</strong>: Learn Go and container from scratch, Linux driver developmment, maybe networking and why not to try to contribute to the Linux Kernel</p>
</li>
<li><p><strong>Coding Challenges Projects</strong>: Complete some projects on the website and work mainly around CLI projects, server/HTPP/Networking and containers projects</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>During this year 2024, I learn more about myself, to accept the life situations and change/adapt to what’ll happen. And some lessons for myself:</p>
<ul>
<li><p>Be yourself</p>
</li>
<li><p>Learn what you can</p>
</li>
<li><p>Do your best</p>
</li>
<li><p>Take rest</p>
</li>
<li><p>Learn/Study what make you happy</p>
</li>
<li><p>You’re not in a running agains other but you’re competing whith your version of yesterday</p>
</li>
<li><p>Time fly, you need to make some big decisions</p>
</li>
<li><p>Be humble</p>
</li>
</ul>
<p>And keep this in mind</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735594834846/3b852908-0353-4ba5-9d62-3c1002c2c258.jpeg" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Some tips when using T3 Stack: Unit Testing with tRPC procedures - environment setup]]></title><description><![CDATA[In this article, I introduced the side project that I'm building and the tools (stacks) I'm using. And in my last article, I talk about NextAuth and module augmentation. Here I'll share with you some tips I used when I was learning unit tests with tR...]]></description><link>https://tawaliou.com/some-tips-when-using-t3-stack-unit-testing-with-trpc-procedures-environment-setup</link><guid isPermaLink="true">https://tawaliou.com/some-tips-when-using-t3-stack-unit-testing-with-trpc-procedures-environment-setup</guid><category><![CDATA[React]]></category><category><![CDATA[trpc]]></category><category><![CDATA[prisma]]></category><category><![CDATA[Testing]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Sat, 20 May 2023 21:27:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1684606664630/6cff47ad-ce67-4893-bad1-289974d86e08.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this <a target="_blank" href="https://hashnode.com/post/cldr3hwu8000609mi52pz7jem">article</a>, I introduced the side project that I'm building and the tools (stacks) I'm using. And in my last <a target="_blank" href="https://tawaldevuniverse.hashnode.dev/some-tips-when-using-t3-stack-nextauth-and-models-types">article</a>, I talk about NextAuth and module augmentation. Here I'll share with you some tips I used when I was learning <strong>unit tests</strong> with tRPC procedures and Prisma. We'll setup our test environment here and in a future article we'll write little tests. At the end, you'll have some useful links that I used to do it.</p>
<h2 id="heading-unit-testing-with-trpc-prisma">Unit testing with tRPC + Prisma?</h2>
<p>Unit testing in software development is the process to check if a small (<em>unit)</em> part of the code executes like you want. You write code to test if some code behaves like you want without logging something. And I try to do it with tRPC + Prisma while using T3 Stack and it was funny. Here is the procedure I want to test</p>
<pre><code class="lang-typescript">getByProjectIdAndPos: protectedProcedure
    .input(
      z.object({
        projectId: z.string().nullish(),
        pos: z.number().nonnegative()
      })
    )
        .query(<span class="hljs-keyword">async</span> ({ ctx, input }) =&gt; {
            <span class="hljs-comment">// 1. should return undefined if projectId is not provided</span>
      <span class="hljs-keyword">if</span> (!input.projectId) <span class="hljs-keyword">return</span> <span class="hljs-literal">undefined</span>

      <span class="hljs-keyword">const</span> countExercises = <span class="hljs-keyword">await</span> ctx.prisma.exercise.count({
        where: { projectId: input.projectId }
      })

            <span class="hljs-comment">// 2. should throw an error if the provided pos is superior to number of exercises</span>
      <span class="hljs-keyword">if</span> (input.pos &gt;= countExercises) {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> TRPCError({
          code: <span class="hljs-string">'NOT_FOUND'</span>,
          message: <span class="hljs-string">`No exercise at position '<span class="hljs-subst">${input.pos + <span class="hljs-number">1</span>}</span>'`</span>
        })
      }

            <span class="hljs-comment">// 3. should return one exercise if position &lt; countExercises</span>
            <span class="hljs-comment">// 4. should return undefined if no exercise at this position</span>
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> ctx.prisma.exercise.findFirst({
        select: defaultExerciseSelect,
        where: {
          projectId: input.projectId
        },
        orderBy: {
          order: <span class="hljs-string">'asc'</span>
        },
        skip: input.pos,
        take: <span class="hljs-number">1</span>
      })
    })
</code></pre>
<p>Based on the position of the exercise provided, this procedure returns an exercise or throws an error. You can read the comments in the code to know what we want to test. But we have a few problems:</p>
<h2 id="heading-some-difficulties-to-test-this-procedure">Some difficulties to test this procedure</h2>
<ol>
<li><p>How to test a protected procedure?</p>
</li>
<li><p>How to test the body of this procedure where we're using Prisma client?</p>
</li>
</ol>
<p>One answer for all of them: Mocking</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/Tawal_Mc/status/1651986440467755031">https://twitter.com/Tawal_Mc/status/1651986440467755031</a></div>
<p> </p>
<p>So we need to <em>mock</em> the object that made this procedure to be protected and after we can mock Prisma client methods too.</p>
<h2 id="heading-what-makes-a-trpc-procedure-protected-in-t3-stack">What makes a tRPC procedure protected in T3 Stack?</h2>
<p>A protected procedure is a tRPC procedure whose access is done when the request is authenticated so the request needs a valid session. Check the session on NextAuth to know more about it. So we must mock a session if we want to test this procedure. And since we're using T3 Stack and Prisma as ORM, the prisma client also is set when creating the tRPC context. Look at the file <strong><em>src/server/api/trpc.ts</em></strong> file you will get this</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// I keep only useful code for the explanations</span>
<span class="hljs-keyword">import</span> <span class="hljs-keyword">type</span> {CreateNextContextOptions} <span class="hljs-keyword">from</span> <span class="hljs-string">"@trpc/server/adapters/next"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-keyword">type</span> {Session} <span class="hljs-keyword">from</span> <span class="hljs-string">"next-auth"</span>;

<span class="hljs-keyword">import</span> {getServerAuthSession} <span class="hljs-keyword">from</span> <span class="hljs-string">"../auth"</span>;
<span class="hljs-keyword">import</span> {prisma} <span class="hljs-keyword">from</span> <span class="hljs-string">"../db"</span>;

<span class="hljs-keyword">import</span> {initTRPC, TRPCError} <span class="hljs-keyword">from</span> <span class="hljs-string">"@trpc/server"</span>;

<span class="hljs-keyword">type</span> CreateContextOptions = {
  session: Session | <span class="hljs-literal">null</span>;
};

<span class="hljs-comment">/**
 * This helper generates the "internals" for a tRPC context. If you need to use
 * it, you can export it from here
 *
 * Examples of things you may need it for:
 * - testing, so we dont have to mock Next.js' req/res
 * - trpc's `createSSGHelpers` where we don't have req/res
 * @see https://create.t3.gg/en/usage/trpc#-servertrpccontextts
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> createInnerTRPCContext = <span class="hljs-function">(<span class="hljs-params">opts: CreateContextOptions</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> {
    session: opts.session,
    prisma,
  };
};

<span class="hljs-comment">/**
 * This is the actual context you'll use in your router. It will be used to
 * process every request that goes through your tRPC endpoint
 * @link https://trpc.io/docs/context
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> createTRPCContext = <span class="hljs-keyword">async</span> (opts: CreateNextContextOptions) =&gt; {
  <span class="hljs-keyword">const</span> { req, res } = opts;

  <span class="hljs-comment">// Get the session from the server using the unstable_getServerSession wrapper function</span>
  <span class="hljs-keyword">const</span> session = <span class="hljs-keyword">await</span> getServerAuthSession({ req, res });

  <span class="hljs-keyword">return</span> createInnerTRPCContext({
    session,
  });
};

<span class="hljs-comment">/**
 * 3. ROUTER &amp; PROCEDURE (THE IMPORTANT BIT)
 *
 * These are the pieces you use to build your tRPC API. You should import these
 * a lot in the /src/server/api/routers folder
 */</span>

<span class="hljs-comment">/**
 * This is how you create new routers and subrouters in your tRPC API
 * @see https://trpc.io/docs/router
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> createTRPCRouter = t.router;

<span class="hljs-comment">/**
 * Public (unauthed) procedure
 *
 * This is the base piece you use to build new queries and mutations on your
 * tRPC API. It does not guarantee that a user querying is authorized, but you
 * can still access user session data if they are logged in
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> publicProcedure = t.procedure;

<span class="hljs-comment">/**
 * Reusable middleware that enforces users are logged in before running the
 * procedure
 */</span>
<span class="hljs-keyword">const</span> enforceUserIsAuthed = t.middleware(<span class="hljs-function">(<span class="hljs-params">{ ctx, next }</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (!ctx.session || !ctx.session.user) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> TRPCError({ code: <span class="hljs-string">"UNAUTHORIZED"</span> });
  }
  <span class="hljs-keyword">return</span> next({
    ctx: {
      <span class="hljs-comment">// infers the `session` as non-nullable</span>
      session: { ...ctx.session, user: ctx.session.user },
    },
  });
});

<span class="hljs-comment">/**
 * Protected (authed) procedure
 *
 * If you want a query or mutation to ONLY be accessible to logged in users, use
 * this. It verifies the session is valid and guarantees ctx.session.user is not
 * null
 *
 * @see https://trpc.io/docs/procedures
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> protectedProcedure = t.procedure.use(enforceUserIsAuthed);
</code></pre>
<p>You can see that the <strong><em>createInnerTRPCContext</em></strong> takes a session as parameters and returns this session with an instance of the prisma client: it's what we'll use... Inside the <a target="_blank" href="https://create.t3.gg/en/usage/trpc#sample-integration-test">section tRPC</a> on T3 Stack documentation, you can find the solution</p>
<pre><code class="lang-typescript">test(<span class="hljs-string">"protected example router"</span>, <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> ctx = <span class="hljs-keyword">await</span> createInnerTRPCContext({
    session: {
      user: { id: <span class="hljs-string">"123"</span>, name: <span class="hljs-string">"John Doe"</span> },
      expires: <span class="hljs-string">"1"</span>,
    },
  });
  <span class="hljs-keyword">const</span> caller = appRouter.createCaller(ctx);

  <span class="hljs-comment">// ...</span>
});
</code></pre>
<p>or simply</p>
<pre><code class="lang-typescript">test(<span class="hljs-string">"protected example router"</span>, <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> session = {
      user: { id: <span class="hljs-string">"123"</span>, name: <span class="hljs-string">"John Doe"</span> },
      expires: <span class="hljs-string">"1"</span>,
    },

  <span class="hljs-comment">// The two lines below are the most important</span>
  <span class="hljs-keyword">const</span> ctx = <span class="hljs-keyword">await</span> createInnerTRPCContext({session});
  <span class="hljs-keyword">const</span> caller = appRouter.createCaller(ctx);
});
</code></pre>
<p>In our case we'll add the prisma client instance</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// I'll explain this line after: we create a mock version of the prisma client to avoid to have a direct access to the db</span>
<span class="hljs-keyword">import</span> prismaMock <span class="hljs-keyword">from</span> <span class="hljs-string">'@/server/__mocks__/db'</span>

test(<span class="hljs-string">"protected example router"</span>, <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> session = {
      user: { id: <span class="hljs-string">"123"</span>, name: <span class="hljs-string">"John Doe"</span> },
      expires: <span class="hljs-string">"1"</span>,
    },

  <span class="hljs-keyword">const</span> ctx = <span class="hljs-keyword">await</span> createInnerTRPCContext({session});
  <span class="hljs-keyword">const</span> caller = appRouter.createCaller({...ctx, prisma: prismaMock});

   <span class="hljs-comment">// And then</span>
   caller.exercise.getByProjectIdAndPos({ projectId: <span class="hljs-string">'1'</span>, pos: <span class="hljs-number">1</span> })    
});
</code></pre>
<p>we'll after explain the first line <strong><em>import prismaMock from '@/server/__mocks__/db</em></strong>.</p>
<h2 id="heading-setup-our-environment">Setup our environment</h2>
<h3 id="heading-add-vitest-and-mock-package">Add vitest and mock package</h3>
<p>I'm using vitest because it's blazing fast 🤣 and seems to be the new choice for tests in JS area.</p>
<pre><code class="lang-bash">yarn add vitest vitest-mock-extended -D
</code></pre>
<h3 id="heading-file-for-test">File for test</h3>
<p>Let's create the file inside <strong><em>src/server/api/routers/tests/exo</em></strong> where we'll put our tests related to exo.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { beforeEach, describe, expect, it, vi } <span class="hljs-keyword">from</span> <span class="hljs-string">'vitest'</span>

vi.mock(<span class="hljs-string">'../../../db'</span>) <span class="hljs-comment">// 1</span>

describe(<span class="hljs-string">'exo procedures testing'</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// 2  </span>
  beforeEach(<span class="hljs-function">() =&gt;</span> {
    vi.restoreAllMocks()
  })
)
</code></pre>
<ol>
<li><p>Vitest will mock the module found from the given path</p>
</li>
<li><p>Will reset all mocked functions/methods</p>
</li>
</ol>
<p><strong>NB</strong>: In the version of T3 Stack that I'm using (7.1.0, yes I need to upgrade), I add a default export of prisma inside <strong><em>src/server/db.ts</em></strong></p>
<h3 id="heading-mock-the-prisma-client">Mock the prisma client</h3>
<p>Inside <strong><em>/server/__mocks__/db</em></strong>, we have a deep-mocked (mock Prisma's method like <em>findFirst</em>, <em>create</em>, etc) version of the Prisma client which is reset before we run each test to avoid having direct access to the DB (we'll install vitest soon).</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> <span class="hljs-keyword">type</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@prisma/client"</span>
<span class="hljs-keyword">import</span> {beforeEach} <span class="hljs-keyword">from</span> <span class="hljs-string">"vitest"</span>
<span class="hljs-keyword">import</span> {mockDeep, mockReset} <span class="hljs-keyword">from</span> <span class="hljs-string">"vitest-mock-extended"</span>;

beforeEach(<span class="hljs-function">() =&gt;</span> {
    mockReset(db)
})

<span class="hljs-keyword">const</span> db = mockDeep&lt;PrismaClient&gt;()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> db
</code></pre>
<h3 id="heading-mock-the-session-object">Mock the session object</h3>
<p>Not something hard, we need just to create a <a target="_blank" href="https://tawaldevuniverse.hashnode.dev/some-tips-when-using-t3-stack-nextauth-and-models-types#heading-nextauth-and-module-augmentation">Session</a> object</p>
<p><strong><em>src/server/api/routers/tests/exo</em></strong></p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> <span class="hljs-keyword">type</span> { Session } <span class="hljs-keyword">from</span> <span class="hljs-string">'next-auth'</span>
<span class="hljs-comment">// code ...</span>

describe(<span class="hljs-string">"exo's procedures testing"</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> session: Session = {
    expires: <span class="hljs-string">'1'</span>,
    user: {
      id: <span class="hljs-string">'clgb17vnp000008jjere5g15i'</span>,
      username: <span class="hljs-string">''</span>
    }
  }
<span class="hljs-comment">// code ..</span>
}
</code></pre>
<p>So now we can imitate the protected behavior of our procedures after mocking:</p>
<ul>
<li><p>our session object</p>
</li>
<li><p>Prisma client</p>
</li>
</ul>
<h3 id="heading-configure-trpc-for-tests">Configure tRPC for tests</h3>
<p>What we're doing is like to create a little environment (by mocking some external libs) for our tests so we'll do the same with tRPC by creating a context that'll be used in our tests only. So let's add after the session object the following code to our test file</p>
<p><strong><em>src/server/api/routers/tests/exo</em></strong></p>
<pre><code class="lang-typescript">  <span class="hljs-comment">// 1</span>
  <span class="hljs-keyword">const</span> ctx = createInnerTRPCContext({ session })
  <span class="hljs-comment">// 2  </span>
  <span class="hljs-keyword">const</span> caller = appRouter.createCaller({ ...ctx, prisma: prismaMock }
</code></pre>
<ol>
<li><p>We pass to <em>createInnerTRPCContext</em> function provided by tRPC the session object we created (the mocked version of the session). So it's like we have an authenticated user represented by this session.</p>
</li>
<li><p><em>caller</em> will allow us to have access to the procedure we defined in our tRPC routers so it takes the mocked version of prisma and the context we created earlier</p>
</li>
</ol>
<p>With that we can do something like this</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">await</span> caller.targetTable.targetProcedure(<span class="hljs-comment">/* input here*/</span>)
</code></pre>
<h3 id="heading-final-setup">Final Setup</h3>
<p>If we put everything together we get this</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { beforeEach, describe, expect, it, vi } <span class="hljs-keyword">from</span> <span class="hljs-string">'vitest'</span>
<span class="hljs-keyword">import</span> <span class="hljs-keyword">type</span> { Session } <span class="hljs-keyword">from</span> <span class="hljs-string">'next-auth'</span>

<span class="hljs-comment">// 1- mock prisma module</span>
vi.mock(<span class="hljs-string">'../../../db'</span>) 

<span class="hljs-comment">// 2- our tests </span>
describe(<span class="hljs-string">'exo procedures testing'</span>, <span class="hljs-function">() =&gt;</span> {
<span class="hljs-comment">// 3- Reset everything  </span>
  beforeEach(<span class="hljs-function">() =&gt;</span> {
    vi.restoreAllMocks()
  })

  <span class="hljs-comment">// 4- session mocked  </span>
  <span class="hljs-keyword">const</span> session: Session = {
    expires: <span class="hljs-string">'1'</span>,
    user: {
      id: <span class="hljs-string">'clgb17vnp000008jjere5g15i'</span>,
      username: <span class="hljs-string">''</span>
    }
  }

  <span class="hljs-comment">// 5- init tRPC for test</span>
  <span class="hljs-keyword">const</span> ctx = createInnerTRPCContext({ session })
  <span class="hljs-keyword">const</span> caller = appRouter.createCaller({ ...ctx, prisma: prismaMock }   

  describe(<span class="hljs-string">"procedure 1 - tests"</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// put tests here  </span>
  })  
)
</code></pre>
<h2 id="heading-so">So</h2>
<p>In this article we set up our environment to write tests. In the next part of this series we'll write some tests to <strong><em>test</em></strong> 🤣 our setup. You can check these useful links:</p>
<ul>
<li><p><a target="_blank" href="https://www.prisma.io/blog/testing-series-1-8eRB5p0Y8o">The Ultimate Guide to Testing with Prisma</a></p>
</li>
<li><p><a target="_blank" href="https://create.t3.gg/en/usage/trpc#sample-integration-test">Sample integration test - tRPC and T3 Stack</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/trpc/trpc/blob/main/examples/next-prisma-starter/src/server/routers/post.test.ts">Example of tests with tRPC - tRPC Github</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Some tips when using T3 Stack: NextAuth and Models types]]></title><description><![CDATA[In my last article, I introduced the side project that I'm building and the tools (stacks) I'm using. And explain why I choose T3 Stack to build the project. Good, in this article I'll share some tips I discovered using T3 Stack when building the pro...]]></description><link>https://tawaliou.com/some-tips-when-using-t3-stack-nextauth-and-models-types</link><guid isPermaLink="true">https://tawaliou.com/some-tips-when-using-t3-stack-nextauth-and-models-types</guid><category><![CDATA[trpc]]></category><category><![CDATA[prisma]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[t3stack]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Sat, 04 Mar 2023 09:56:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677923475166/b1be1008-1c69-4eec-8e59-7d33be8c8f51.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my last <a target="_blank" href="https://hashnode.com/post/cldr3hwu8000609mi52pz7jem">article</a>, I introduced the side project that I'm building and the tools (stacks) I'm using. And explain why I choose <a target="_blank" href="https://create.t3.gg/">T3 Stack</a> to build the project. Good, in this article I'll share some tips I discovered using T3 Stack when building the project. Let's go!</p>
<h2 id="heading-reminder">Reminder</h2>
<ul>
<li><p>NextAuth needs/uses for authentication a model User with some pre-configured columns like name, image, email, etc.</p>
</li>
<li><p>With T3 Stack we use Prisma as ORM</p>
</li>
<li><p>We have added some columns to the User model like the username</p>
</li>
</ul>
<h2 id="heading-nextauth-and-module-augmentation">NextAuth and Module augmentation</h2>
<p><a target="_blank" href="https://next-auth.js.org/">NextAuth</a> is used for authentication in Next.js applications and is packed in T3 Stack. When using NextAuth, the hook <code>useSession</code> returns session data that can be checked to verify if someone is signed like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> index = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> { <span class="hljs-attr">data</span>: session } = useSession()
    <span class="hljs-keyword">if</span> (session) {
        <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>You're signed as {session.user.email}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>    
    }
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Not signed, we'll redirect you<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
}
</code></pre>
<p>But for security reasons, the session data returned (by default) contained just</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> DefaultSession {
    user?: {
        name?: <span class="hljs-built_in">string</span> | <span class="hljs-literal">null</span>;
        email?: <span class="hljs-built_in">string</span> | <span class="hljs-literal">null</span>;
        image?: <span class="hljs-built_in">string</span> | <span class="hljs-literal">null</span>;
    };
    expires: ISODateString;
}
</code></pre>
<p>So what can we do if we want to add a new property like the username which is a column of our User model that we define with Prisma?</p>
<p>T3 dedicated's <a target="_blank" href="https://create.t3.gg/en/usage/next-auth">section</a> to NextAuth and NextAuth <a target="_blank" href="https://next-auth.js.org/getting-started/typescript#module-augmentation">itself</a> already documented this part. To do it, we'll use module augmentation offered by TypeScript which allows a user to override classes, modules,... types that he/she doesn't access (maybe from a lib). To do it,</p>
<ol>
<li><p>We can override the Session interface in the <strong>next-auth module</strong> declaration inside the file <strong><em>types/next-auth.d.ts.</em></strong></p>
<pre><code class="lang-typescript"> <span class="hljs-keyword">import</span> { DefaultSession } <span class="hljs-keyword">from</span> <span class="hljs-string">"next-auth"</span>;

 <span class="hljs-keyword">declare</span> <span class="hljs-keyword">module</span> "next-auth" {
   <span class="hljs-keyword">interface</span> Session {
     user?: {
       id: <span class="hljs-built_in">string</span>;
       username: <span class="hljs-built_in">string</span> | <span class="hljs-literal">null</span>  
     } &amp; DefaultSession[<span class="hljs-string">"user"</span>];
   }
 }
</code></pre>
<p> We import <code>next-auth</code> module and override the Session interface by adding not only a <code>username</code> but also merging the type of user in DefaultSession so we still have the default properties of the user provided by NextAuth.</p>
</li>
<li><p>Then in the <strong><em>/pages/api/auth/[...nextauth].ts</em></strong> file we can override session callback by adding <code>username</code> like this</p>
<pre><code class="lang-typescript"> callbacks: {
     session({ session, user }) {
       <span class="hljs-keyword">if</span> (session.user) {
         session.user.id = user.id;
         session.user.username = user.username;
       }
       <span class="hljs-keyword">return</span> session;
     },
   },
</code></pre>
<p> But if you leave it like this, you'll get this warning from TS: <code>Property 'username' does not exist on type 'User | AdapterUser'</code>. Why?</p>
<p> Because, if you go to the TS definition of <code>User</code> (used by Nextauth) you'll see that it extends <code>DefaultUser</code> which has the following definition (the minimum)</p>
<pre><code class="lang-typescript"> <span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> DefaultUser {
     id: <span class="hljs-built_in">string</span>;
     name?: <span class="hljs-built_in">string</span> | <span class="hljs-literal">null</span>;
     email?: <span class="hljs-built_in">string</span> | <span class="hljs-literal">null</span>;
     image?: <span class="hljs-built_in">string</span> | <span class="hljs-literal">null</span>;
 }
</code></pre>
<p> So to fix this error, I think you guess the solution, yes: override the declaration of <code>User</code> as we did it with <code>Session</code> little above.</p>
</li>
<li><p>So back to the <strong><em>types/next-auth.d.ts,</em></strong> we can override <code>User</code> after the <code>Session</code> interface (inside next-auth declaration) like this</p>
<pre><code class="lang-typescript">   <span class="hljs-keyword">interface</span> User <span class="hljs-keyword">extends</span> DefaultUser{
     username: <span class="hljs-built_in">string</span> | <span class="hljs-literal">null</span>
   }
</code></pre>
<p> We've just override <code>User</code> interface by firstly extending <code>DefaultUser</code> (provided by NextAuth) and secondly adding a <code>username</code>.</p>
</li>
</ol>
<p>Let's move to another tip.</p>
<h2 id="heading-models-types-deductions-with-trpc">Models types deductions (with tRPC)</h2>
<p>With Prisma, we define our tables as models inside <strong><em>schema.prisma</em></strong> file but we don't have a direct access to their types in TypeScript because it generates types definitions in <strong><em>node_modules/.prisma/client/index.d.ts</em></strong> by default (read this <a target="_blank" href="https://www.prisma.io/docs/concepts/components/prisma-client/working-with-prismaclient/generating-prisma-client#why-is-prisma-client-generated-into-node_modulesprismaclient-by-default">link</a> if you want to change this output file location). But there are some ways to get these types:</p>
<ol>
<li><p>Use the return type of Prisma client methods like this</p>
<pre><code class="lang-typescript"> <span class="hljs-keyword">const</span> getById = <span class="hljs-keyword">async</span> () =&gt; <span class="hljs-keyword">await</span> prisma.post.findUnique({
 <span class="hljs-comment">//....</span>
 })

 <span class="hljs-keyword">type</span> Post = ReturnType&lt;<span class="hljs-keyword">typeof</span> getById&gt;
</code></pre>
</li>
<li><p>Or you can use the <code>GetPayload</code> version of the model type where we can specify all relations between this model and others</p>
<pre><code class="lang-typescript"> <span class="hljs-keyword">import</span> { PrismaClient, Prisma } <span class="hljs-keyword">from</span> <span class="hljs-string">"@prisma/client"</span>;
 <span class="hljs-keyword">type</span> User = Prisma.UserGetPayload&lt;{
     <span class="hljs-comment">// here you can specify all relations like: select, include, ...</span>
 }&gt;
</code></pre>
<p> You can read more <a target="_blank" href="https://www.prisma.io/docs/concepts/components/prisma-client/advanced-type-safety/prisma-validator">here</a> and on this <a target="_blank" href="https://www.prisma.io/docs/concepts/components/prisma-client/advanced-type-safety/prisma-validator">link</a>.</p>
</li>
</ol>
<p>I don't recommend you these solutions because we have <strong>tRPC</strong> (don't blame me).</p>
<p>In our case, we use Prisma client through tRPC. And you'll be happy to know that tRPC has a utility to infer routers' input/return types. Let's suppose that we have a router named <code>user</code> and we define inside this router a procedure <code>retrieve</code>. To get the return type in plain tRPC of this procedure we can do:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> <span class="hljs-keyword">type</span> { inferRouterInputs } <span class="hljs-keyword">from</span> <span class="hljs-string">"@trpc/server"</span>

<span class="hljs-keyword">type</span> User = inferRouterInputs&lt;AppRouter&gt;[<span class="hljs-string">'user'</span>][<span class="hljs-string">'retrieve'</span>]
</code></pre>
<p>Nice! But how will you be if I say that in T3 Stack there is a little helper to make this operation easier:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> {RouterOutputs} <span class="hljs-keyword">from</span> <span class="hljs-string">"@utils/api"</span>;
<span class="hljs-keyword">type</span> User = RouterOutputs[<span class="hljs-string">'project'</span>][<span class="hljs-string">'getById'</span>]
</code></pre>
<p>And yes, if you go to look inside the <strong><em>@utils/api</em></strong> you'll see that</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> RouterOutputs = inferRouterOutputs&lt;AppRouter&gt;;
</code></pre>
<p>Anyway, it's soft to use.</p>
<p><strong>Bonus:</strong></p>
<p>With this approach, TS can warm you that <code>User</code> type could be null, so to avoid it you can use the <code>NonNullable</code> utility:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> {RouterOutputs} <span class="hljs-keyword">from</span> <span class="hljs-string">"@utils/api"</span>;
<span class="hljs-keyword">type</span> User = NonNullable&lt;RouterOutputs[<span class="hljs-string">'project'</span>][<span class="hljs-string">'getById'</span>]&gt;
</code></pre>
<p>Right!</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I love the end-to-end typesafe that we get from tRPC and it's very cool to work with T3 Stack where they put together some great libs and frameworks to make full-stack development with JS much easier.</p>
<p>We are at the end of this article. I hope you enjoy it. If I get another tip while building my SaaS, I'll share them. Feedback or anything that could help me to improve this post is welcome.</p>
]]></content:encoded></item><item><title><![CDATA[Building a side project, a SaaS product based on T3 Stack]]></title><description><![CDATA[Before starting I want to thank Hashnode and point out that my article for Dev Retro 2022 was nominated among the winners, very happy.
The project
As the title said, I'm building a SaaS as a side project (maybe I can call it SaaSaSP 🤣). The idea is ...]]></description><link>https://tawaliou.com/building-a-side-project-a-saas-product-based-on-t3-stack</link><guid isPermaLink="true">https://tawaliou.com/building-a-side-project-a-saas-product-based-on-t3-stack</guid><category><![CDATA[SaaS]]></category><category><![CDATA[React]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[fullstack]]></category><dc:creator><![CDATA[Tawaliou ALAO]]></dc:creator><pubDate>Sun, 05 Feb 2023 08:01:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1675584490758/6045866e-b5f3-450c-9a46-a34861daf3d3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Before starting I want to thank Hashnode and point out that my article for</em> <a target="_blank" href="https://tawaldevuniverse.hashnode.dev/dev-retro-2022-beginning-of-my-professional-career"><em>Dev Retro 2022</em></a> <em>was nominated among</em> <a target="_blank" href="https://townhall.hashnode.com/dev-retro-2022-winners"><em>the winners</em></a><em>, very happy.</em></p>
<h2 id="heading-the-project">The project</h2>
<p>As the title said, I'm building a SaaS as a side project (maybe I can call it SaaSaSP 🤣). The idea is to allow people to build exercises with questions and responses on the platform and share this with other people who can practice. This platform will be used on one hand by students during revision periods and on another hand, by teachers who can share homework with their students.</p>
<p>I only work evenings and Saturdays on the project (because I have a full-time job). And currently, I can say that I am at 20% of the first version of the product.</p>
<h2 id="heading-the-design">The Design</h2>
<p>I don't have a design so I went to websites with which I like the design and I try to reproduce them for the pages I need. For example:</p>
<ul>
<li><p>Sign in: I'm stunned by the login page of Adobe so I tend to reproduce it</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1675030226869/3b1131cb-e879-4f63-b38d-3879aaf85093.jpeg" alt="Adobe login page" class="image--center mx-auto" /></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1675030348467/bda72fed-e10b-48f0-93c6-cf0ff1ca0b30.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Dashboard: I like vercel and sanity dashboards</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1675030487545/3bf61160-af2c-4276-b582-3cc80e217700.jpeg" alt="Sanity dashboard" class="image--center mx-auto" /></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1675030570222/c75bb0c9-7c5c-402a-9e04-801d59deb51e.jpeg" alt="Vercel dashboard" class="image--center mx-auto" /></p>
</li>
</ul>
<p>I don't finish to build the dashboard so I haven't concrete pictures.</p>
<h2 id="heading-the-stack-and-why-this">The Stack and why this?</h2>
<p>Yes, the big part. To make my choice here are the criteria I followed:</p>
<ol>
<li><p>I want to use tools with which I have some prior experiences to code the application quickly and which are popular and stable so that if I encounter a bug I can find resources to resolve it. In my case, I use only: (TS)React/Next.js. So the frontend lib/framework must be one of these two.</p>
</li>
<li><p>I don't want to deal too much with CSS and I hope the UI lib will have a lot of basic components with a good styling approach. Here I was thinking about 3 UI lib based on React (in order of consideration given):</p>
<ul>
<li><p><a target="_blank" href="https://react-spectrum.adobe.com/">React Spectrum</a> &amp; <a target="_blank" href="https://react-spectrum.adobe.com/react-aria/index.html">React Aria</a>: A collection of lib and tools from Adobe developers. They implement Adobe design systems which I find nice. It has many components including a date range picker, drags and drops, and useful resources. What I like about this lib are the efforts the maintainers put into accessibility and <a target="_blank" href="https://www.w3.org/TR/wai-aria-practices-1.2/">WAI-ARIA</a>. Also, they have many hooks like <a target="_blank" href="https://react-spectrum.adobe.com/react-aria/useDateRangePicker.html">useDateRangePicker</a> that you can use to build a custom component, here is a date range picker 😛.</p>
</li>
<li><p><a target="_blank" href="https://mantine.dev/">Mantine</a>: A relatively new lib with a bunch of pre-built advanced components like a search bar with a filter (more featured than what I built <a target="_blank" href="https://hashnode.com/post/clb7wly1g000a08l123l793wf">here</a>). Its strength lies in the ease with which you can customize its components with a better developer experience than with Material UI.</p>
</li>
<li><p><a target="_blank" href="https://nextui.org/">Next UI</a>: A new lib too, with a beautiful design around gradients and based on...React Aria ( 😎 Yes, the same as I mentioned above)</p>
</li>
<li><p><a target="_blank" href="https://chakra-ui.com/">Chakra UI</a>: One of my favourite UI components libs. Simple, easy to use with a very well-designed approach and built by a Nigerian (😎 a border country to Benin, my country). For my side projects, I use Chakra UI. It's very well documented and even if It doesn't have a lot of pre-built components like a date range picker, I was comfortable using it.</p>
<p>  <strong>So my choice?</strong>: Chakra, why?</p>
<p>  I found NextUI css API a little complicated (it supports styled-components), with React Spectrum the <a target="_blank" href="https://react-spectrum.adobe.com/react-spectrum/Button.html">button's</a> onClick prop becomes onPress (can you imagine ? I don't know the reason) and I don't like Mantine basic style (😄 someone who is not good in CSS criticizes a UI components libs). But Chakra, everything seems easy, simple and intuitive: <strong><em>_hover</em></strong> is a prop that you can provide with style when the mouse hover your component (really intuitive, isn't it ?)</p>
<p>  <strong>NB:</strong> I am not a fan of Material UI, customization is an obstacle course where you need to check the css class name of children in chrome inspector to overrides their styles</p>
</li>
</ul>
</li>
<li><p>I want a real full-stack React/Next framework that'll allow me to write JS code in both the server and front end. If it can include a config for database and authentication it'll be <strong>very good</strong>. And no, I don't have the time and energy to go with API first architecture so I cannot have the Node server separate from the frontend. So I have 3 choices:</p>
<ul>
<li><p><a target="_blank" href="https://redwoodjs.com/">Redwood.js</a>: It's a good candidate and I like the name and the full battery included: Routing, GraphQL, TypeScript, Prisma, and Authentication. It's good but I need to jump to GraphQL and they have their routing system (It'll take me some time to be ready, the time I don't have 😄). But I want to test it one day</p>
</li>
<li><p><a target="_blank" href="https://blitzjs.com/">Blitz.js</a>: Good too, built on top of...Next.js. It comes with authentication, is database agnostic and has a CLI tool: <em>blitz.</em> Two things I like about it: <a target="_blank" href="https://blitzjs.com/docs/route-manifest">Route manifest</a> which allows you to refer to a page by <em>name through an object</em> instead of hand-coded string (useful with dynamic route) and their use of <strong>Zod</strong> to validate input in form (it's the first time I hear about Zod). But they were talking about pivoting to a framework agnostic and they were relatively new, so I didn't pick them</p>
</li>
<li><p><a target="_blank" href="https://create.t3.gg/">T3 Stack</a>: On the home page you can read: <strong>The best way to start a full-stack, typesafe Next.js app.</strong> So I choose it 😄. Ok I'll explain. T3 Stack doesn't bring anything new but it puts together well know/established tools and libs to let you focus on your business logic. Firstly the core of this stack is also TypeScrpt/Next.js. Secondly, for authentication, they use <a target="_blank" href="https://next-auth.js.org/">NextAuth.js</a>, for the API they use tRPC which allows you to share your types between client and server code (input validations, return types) by writing typed procedures on the server side. tRPC has a plugin for the well-known <a target="_blank" href="https://react-query-v3.tanstack.com/">React Query</a> that T3 Stack includes for you. For the database, this stack uses the popular ORM <a target="_blank" href="https://www.prisma.io/">Prisma</a> so you can connect your application to all databases (PostgreSQL in my case) supported by Prisma. When configuring it asks to install tailwindcss for styling. Something great is that: you can install what you need only.</p>
<p>  You can understand that I chose T3 Stack. <strong>At the end of the project, I'll share my feelings after using this stack.</strong></p>
</li>
</ul>
</li>
</ol>
<p>There is another choice I need to do: the deployment platform. As I haven't finished or have a beta version yet, I haven't made my choice yet. But I'm thinking between: <a target="_blank" href="https://fly.io/">fly.io</a>, <a target="_blank" href="https://render.com/">render</a> and <a target="_blank" href="https://vercel.com/">vercel</a>.</p>
<p>We are athe end of this article, in my next article I'll share some tricks that I'm using with this stack.</p>
]]></content:encoded></item></channel></rss>