mailwal

Coding Challenge #142 - Software KVM

John Crickett from Coding Challenges

I invite you to upgrade to a paid subscription. Paid subscribers have told me they appreciate me creating the programming projects and would like to see more of them in the future.


Coding Challenge #142 - Software KVM

This challenge is to build your own version of Barrier.

Hi, this is John with this week’s Coding Challenge.

🙏 Thank you for being a subscriber, I’m honoured to have you as a reader. 🎉

If there is a Coding Challenge you’d like to see, please let me know by replying to this email📧

Coding Challenge #142 - Software KVM

This challenge is to build your own software KVM switch, a simplified version of Barrier, the open source tool that lets you control several computers with a single keyboard and mouse.

If you’ve ever had two or three computers side by side on your desk, you’ll know the pain of swapping keyboards and mice between them, swapping you between different keyboards and mice, or reaching for a physical KVM switch.

Barrier solves this in software: move your cursor off the edge of one screen and it reappears on the next computer, carrying your keyboard and clipboard with it. No extra cables, no hardware box, just a small program running on each machine.

In this challenge you’ll build both halves of that system from scratch, speaking Barrier’s own open wire protocol, so that a real, unmodified Barrier client or server can interoperate with yours, and two instances of your own build can run the whole show on their own.

Fancy Winning A MacBook Neo or some Merch? Then Join Kesta’s Hacktober Event.

This October I’m pleased to be part of the Kestra Hacktober event. It’s a great way to contribute to open source this October and win some great prizes!

There are two ways to enter:

  1. Fix an issue in their open-source codebase.

They’ve identified and scoped a number of issues across their core and plugin repositories. They’re tagged good-first-issue, so you can find one that interests you.

  1. Build a blueprint, a ready-to-use flow template that other developers can pick up and run.

Whichever way you take part, there are prizes to be won!

🥇 1st place: 13” MacBook Neo

🥈 2nd place: Apple iPad

🥉 3rd place: $150 Amazon gift card

You need to register here to win prizes.

And you can find the full details on Kestra’s Hacktober page.

OK, on with the coding challenge!

The Challenge - Building Your Own Software KVM

You’re going to build a software KVM. It’s a client-server systems.

The server captures keyboard and mouse activity on your main machine, works out which connected screen should be in control as the cursor crosses screen edges, and forwards input, clipboard and status updates to the right client over the network.

The client connects to a server, and acts on everything it’s sent, moving the cursor, typing keystrokes, updating the clipboard, on the machine it’s running on. Because you’re implementing Barrier’s real protocol rather than inventing your own, you’ll be able to test your work against the genuine Barrier client and server at every stage, right up until the point where you don’t need them any more.

This is challenge combines binary network protocol work with low level, platform specific input handling, so pick a language with solid support for both TCP sockets and OS level mouse and keyboard capture.

Step Zero

In this introductory step you’re going to set your environment up ready to begin developing and testing your solution.

Choose your target platform and programming language, bearing in mind you’ll need a library for network programming, one for capturing global mouse and keyboard events on your own machine (not just events inside your own windows), and one for injecting simulated mouse and keyboard input, since you’ll eventually be building the client side too. Most mainstream languages have options for all three.

Download and install the real Barrier client on a second machine, you’ll use this throughout the challenge as the thing your server controls. Also consider installing a packet capture tool such as Wireshark or tcpdump, and spend some time capturing traffic between two genuine Barrier instances so you have a reference for what correctly formed messages look like.

Finally, read through Barrier’s own protocol header in its source code (src/lib/barrier/protocol_types.h in the debauchee/barrier repository) to familiarise yourself with the message codes you’ll be implementing.

Step 1

In this step your goal is to accept connections from Barrier clients and complete the initial handshake.

Your server should listen for TCP connections on port 24800, the default Barrier port. When a client connects, it should send a Hello message carrying the protocol’s major and minor version, and wait for the client to reply with a HelloBack message containing the client’s own version and the name it was configured with.

Testing: Point the Barrier client at your server’s address and port. Watch your server log the client’s reported name and protocol version once the handshake completes. If you installed Wireshark, capture the exchange in Wireshark and compare it against the reference capture you took in Step Zero.

Step 2

In this step your goal is to reject clients speaking an incompatible version of the protocol.

If the version a client reports in its HelloBack is one your server doesn’t support, your server should respond with an EICV (incompatible version) message and close the connection rather than proceeding.

Testing: Write a small script that opens a raw TCP connection to your server and sends a HelloBack with a deliberately wrong version number. Confirm your server sends EICV and disconnects. Then reconnect with the real Barrier client and confirm the normal handshake still succeeds.

Step 3

In this step your goal is to load a screen configuration describing the layout of connected screens.

Your server should read a configuration that names each client screen and defines its directional neighbours, left, right, top and bottom, relative to the other configured screens. This is the layout Barrier itself asks you to draw when you arrange screens in its own configuration tool.

Testing: Write a configuration with at least two screens, for example office-mac to the left of office-pc, and confirm your server parses it into a lookup you can query, such as “what is to the right of office-mac?”. Try a configuration that references a screen that doesn’t exist and confirm your server reports a clear error instead of crashing.

Step 4

In this step your goal is to exchange screen information with a connected client.

After the handshake, your server should receive a DINF message from the client reporting its screen size and current cursor position, and acknowledge it with a CIAK message.

Testing: Connect the real Barrier client and confirm your server logs the screen resolution it reports in its DINF message. Compare the CIAK your server sends against the one sent by a genuine Barrier server in your Wireshark reference capture if you did it.

Step 5

In this step your goal is to track which screen currently has control and where the cursor is on it.

Your server captures mouse movement on your own machine (the one with the physical keyboard and mouse attached), so it needs to keep its own model of which screen is “active” and the cursor’s current coordinates on that screen, updating it as the mouse moves.

Testing: Move your mouse around your screen and log the coordinates your server is tracking. Confirm the logged position matches where your cursor actually is, and that it stays within your screen’s bounds.

Step 6

In this step your goal is to detect when the cursor should hand off to another screen.

When the cursor reaches the edge of the active screen, your server should check the screen configuration from Step 3 for a neighbour in that direction. If one is configured, that’s a handoff; if there’s no neighbour configured on that edge, the cursor should simply stop at the edge as normal.

Testing: With a configuration that has a neighbour to the right but none above, move your cursor to the right edge and confirm your server detects a handoff. Move it to the top edge and confirm it doesn’t.

Step 7

In this step your goal is to actually switch control to the neighbouring screen.

When your server detects a handoff, it should send a CINN command to the client gaining control, including the coordinates where the cursor enters and a sequence number, and send a COUT command to the client that just lost control.

Testing: With the real Barrier client connected and configured as a neighbour, move your cursor to the matching screen edge and watch the cursor appear on the client machine. Move it back the other way and confirm control returns to your own screen.

Step 8

In this step your goal is to forward keyboard activity to the client currently in control.

Your server should forward key press and release events using DKDN and DKUP messages, carrying the key code and modifier mask, and forward repeated keystrokes from a held key using DKRP.

Testing: With the Barrier client in control, open a text editor on the client machine and type on your physical keyboard. Confirm the correct characters appear, including held keys like a repeated letter when you hold a key down, and that modifier combinations like Shift+A produce a capital letter.

Step 9

In this step your goal is to forward mouse button and wheel activity.

Your server should forward mouse button press and release events using DMDN and DMUP messages carrying the button id, and forward scroll wheel movement using DMWM.

Testing: With the Barrier client in control, click and scroll with your physical mouse. Confirm clicks register correctly on the client machine (for example, clicking a button in an open application) and that scrolling moves the content on the client’s screen.

Step 10

In this step your goal is to switch to relative mouse movement once control has entered a client screen.

Rather than repeatedly resending absolute coordinates, your server should send relative movement deltas using DMRM once the cursor has entered a client’s screen.

Testing: Capture the traffic between your server and the Barrier client while moving the mouse continuously across the client’s screen. Confirm the messages are DMRM, not repeated DMMV, and that cursor movement on the client stays smooth with no jumps or drift.

Step 11

In this step your goal is to keep connections alive and close them cleanly.

Your server should send a CALV keep-alive message to each connected client every 3 seconds, and disconnect any client that fails to respond within 9 seconds. It should also support a CNOP no-op message for simple connectivity checks, and send a CBYE message when deliberately closing a connection.

Testing: Leave a client connected and idle, and confirm in Wireshark that CALV messages go out roughly every 3 seconds. Simulate an unresponsive client (for example, by blocking its replies with a firewall rule) and confirm your server disconnects it after about 9 seconds. Stop your server normally and confirm the client receives a CBYE before the connection closes.

Step 12

In this step your goal is to synchronise the clipboard between screens.

When the clipboard changes on the screen currently in control, your server should send a CCLP ownership notification followed by a DCLP message carrying the clipboard contents to the other connected clients, and it should accept the same messages coming the other way when the clipboard changes on a client.

Testing: Copy some text on your own machine while a client is connected, then paste on the client machine and confirm the same text appears. Then copy something on the client machine and confirm it comes back to your own clipboard.

Step 13

In this step your goal is to notify clients when your screensaver starts or stops.

Your server should send a CSEC message to connected clients when the primary screen’s screensaver activates, and another when it deactivates.

Testing: Trigger your machine’s screensaver and confirm connected clients receive a CSEC message indicating the started state, followed by one indicating the stopped state when you dismiss it.

Step 14

In this step your goal is to support more than two screens at once.

Your screen configuration and switching logic from earlier steps should work for any number of connected screens arranged in a configurable grid, not just a single pair.

Testing: Configure three screens in an L shape, for example one to the right of your primary, and one below that one, connect three client instances, and confirm the cursor moves correctly between all of them as you’d expect from the layout, including that moving diagonally across two edges in sequence puts you on the right screen each time.

Step 15

In this step your goal is to confirm full interoperability with a real Barrier client.

Run an extended session using only the genuine, unmodified Barrier client as your test client; type, click, scroll, switch screens back and forth, and sync the clipboard, all without the client needing any changes or special configuration to work with your server.

Testing: Use your server as a daily driver for a short working session, controlling the Barrier client machine for ordinary tasks like browsing or editing a document. If everything behaves as it would with a genuine Barrier server, nice work!

Step 16

In this step your goal is to implement the client side of the protocol, so your own build can act as the screen being controlled, not just the one doing the controlling.

Your client should connect to a server, complete the handshake and the DINF/CIAK exchange, and then act on everything the server sends it: moving the cursor and injecting keystrokes on CINN/COUT and the DKDN/DKUP/DKRP/DMDN/DMUP/DMWM/DMRM messages, updating the local clipboard on CCLP/DCLP, responding to CALV and CNOP, and disconnecting cleanly on CBYE.

Testing: First connect your client to a Barrier server and confirm it behaves just like a genuine Barrier client, moving the cursor and typing correctly on your machine as the Barrier server hands it control.

Then run two instances of your own build, one as server and one as client, on two machines (or two user sessions on one machine), with no real Barrier software involved at all, and repeat the full set of tests from the earlier steps, screen switching, typing, clicking, scrolling, and clipboard sync, end to end between your own software only.

Going Further

Once you have the core software KVM working, here are some ideas to take it further:

  • Add TLS encryption to the connection, matching the SSL support in newer versions of the real protocol.

  • Support file drag and drop between screens using the DFTR message.

  • Add hotkey-triggered screen switching as an alternative to edge detection.

  • Handle screens with different resolutions or DPI scaling correctly when translating cursor coordinates.

  • Build a small configuration UI for drawing the screen layout, rather than hand editing a config file.

  • Add automatic reconnection when a client drops and comes back.

  • Package your server and client as a background service or system tray application.

Share Your Solutions!

If you think your solution is an example other developers can learn from please share it, put it on GitHub, GitLab or elsewhere. Then let me know via Bluesky or LinkedIn or just post about it there and tag me. Alternately please add a link to it in the Coding Challenges Shared Solutions Github repo

Request for Feedback

I’m writing these challenges to help you develop your skills as a software engineer based on how I’ve approached my own personal learning and development. What works for me, might not be the best way for you - so if you have suggestions for how I can make these challenges more useful to you and others, please get in touch and let me know. All feedback is greatly appreciated.

You can reach me on Bluesky, LinkedIn or through SubStack

Thanks and happy coding!

John

© 2026 John Crickett
548 Market Street PMB 72296, San Francisco, CA 94104