Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
86ff574
Bump 0.1.2 version that is using max 25.1
msaelices Feb 16, 2025
1bfb734
Minor change in the README
msaelices Feb 16, 2025
035c005
Better title in README
msaelices Feb 16, 2025
c9d215b
Complete the Contributing document
msaelices Feb 16, 2025
e044bac
Still stick to the 25.1 version
msaelices Feb 20, 2025
e350b45
Pin the exact max version
msaelices Feb 21, 2025
9d40f15
Fix conda channel
msaelices Feb 21, 2025
0ff237b
io_uring is only supported in linux
msaelices Feb 21, 2025
41e72a0
Fix magic.lock to support only Linux
msaelices Feb 22, 2025
e53636a
WIP work to support concurrency via io_uring
msaelices Mar 1, 2025
977c5ae
Decrease some values to make compiler now to slow
msaelices Mar 1, 2025
e24fbb2
Allow to change the server port in the argument
msaelices Mar 1, 2025
3c477d5
Allow customizing the port in the client
msaelices Mar 1, 2025
7db157a
Update dependencies
msaelices Mar 1, 2025
e6378db
Do not open a connection in each event
msaelices Mar 1, 2025
47bdddd
Update dependencies to nightly
msaelices Mar 1, 2025
4e6fe97
Adapt the code to work with nightly
msaelices Mar 1, 2025
7e47eb4
Decrease max message len due to compiler issues with InlineArray and …
msaelices Mar 2, 2025
81d1c82
Handle the case of DNS failure by using the IP directly
msaelices Mar 2, 2025
1b25e48
Ensure the run_client.sh and run_server.sh are executed in the same d…
msaelices Mar 2, 2025
d0fa469
Pass the given arguments to the client.mojo and server.mojo scripts
msaelices Mar 2, 2025
69f1009
Prevent copying the server protocol on READ so we will keep its state
msaelices Mar 2, 2025
9d3d371
Log the conninfo in each completion entry
msaelices Mar 2, 2025
b4314a9
Fix the writing of response back to the client. Broken because of copies
msaelices Mar 2, 2025
a266371
Removal of more ServerProtocol copies to fix edge cases and avoid une…
msaelices Mar 2, 2025
6d70849
Simplify Socket.connect() logic
msaelices Mar 2, 2025
648a186
Increase the max message length from 1K to 2K as the compiler time is
msaelices Mar 2, 2025
55e0c63
Some useful comment about the why ServerProtocol has a __moveinit__
msaelices Mar 2, 2025
6e68ff3
Update README.md with the new concurrency support mentioned
msaelices Mar 2, 2025
6dd5504
New Client.recv_text() useful function to increase API ergonomics
msaelices Mar 3, 2025
e553173
Simplify echo example
msaelices Mar 3, 2025
3c02a00
New Client.recv_text() useful function to increase API ergonomics
msaelices Mar 3, 2025
5db80a8
Simplify echo example
msaelices Mar 3, 2025
8a6e8e2
Add a note about the concurrent support implemented in the io_uring b…
msaelices Mar 3, 2025
0cc5c4a
WIP implementation of a pure sha1 algorithm in Mojo
msaelices Mar 3, 2025
fc9dc4d
Better formatting. Replace Tuple typing with ()
msaelices Mar 3, 2025
e510ebb
Test for the sha1 and the handshake modules
msaelices Mar 3, 2025
54ff094
Remove remaining "from python import Python" import sentences
msaelices Mar 3, 2025
e0beef2
Remove TODO item from README.md
msaelices Mar 3, 2025
8a4b155
Remove meaningless comment
msaelices Mar 3, 2025
18ed085
Merge pull request #6 from msaelices/sha1-in-mojo
msaelices Mar 3, 2025
1dfd067
Merge branch 'main' into io_uring
msaelices Mar 3, 2025
6e4f35a
Fix issue with last char received from server
msaelices Mar 3, 2025
807e0fd
Stack allocate the chunk in sha1 to spped up the hashing
msaelices Mar 3, 2025
6d869fe
Preallocate some chunk of data in the sha1 algorithm to speed it up
msaelices Mar 4, 2025
c165494
Merge branch 'main' into io_uring
msaelices Mar 4, 2025
b5f4976
Update dependencies
msaelices Mar 23, 2025
c4e5ce8
Adapt the code to the new 25.3.0 version (unreleased)
msaelices Mar 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
# Contributing Guide

## Install and upgrade Magic
## Activate the magic shell

For development, you can activate the magic shell by running:

```bash
magic update && magic install
magic shell
```

## How to build this package

Once you have the magic shell activated, you can build the package by running:

```bash
mojo package src/websockets -o websockets.mojopkg
``
./scripts/build.sh
```

## How to run tests

To run the tests, you can run:

```bash
./scripts/run-tests.sh
```
24 changes: 9 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# mojo-websockets
# Mojo Websockets

![logo](./assets/logo.jpeg)

`mojo-websockets` is a lightweight library for handling WebSocket connections in Mojo.
`mojo-websockets` is a lightweight library for handling WebSocket connections in Mojo.

It aims to provide an similar interface as the [python-websockets](https://github.com/python-websockets/websockets) package for creating WebSocket servers and clients, with additional features for enhanced usability.

Expand All @@ -13,6 +13,7 @@ This software is in a early stage of development. Please DO NOT use yet for prod
## Features

- **WebSocket Server and Client**: Supports creating both WebSocket servers and clients.
- **Asynchronous non-blocking communication**: Support concurrent connections via [io_uring](https://unixism.net/loti/).
- **Compatibility**: API designed to be intuitive for developers familiar with the Python websockets library.
- **Sans/IO Layer**: Implements a WebSocket Sans/IO layer pure Mojo and performs no I/O of its own.

Expand All @@ -34,16 +35,13 @@ For a complete listing, see the [features](docs/features.md) document.
```mojo
from websockets.aliases import Bytes
from websockets.sync.server import serve, WSConnection
from websockets.utils.bytes import bytes_to_str


fn on_message(conn: WSConnection, data: Bytes) raises -> None:
str_received = bytes_to_str(data)
str_received = String(StringSlice.from_utf8(data))
print("<<< ", str_received)
conn.send_text(str_received)
print(">>> ", str_received)


fn main() raises:
with serve(on_message, "127.0.0.1", 8000) as server:
server.serve_forever()
Expand All @@ -53,15 +51,13 @@ fn main() raises:

```mojo
from websockets.sync.client import connect
from websockets.utils.bytes import bytes_to_str


fn send_and_receive(msg: String) raises:
with connect("ws://127.0.0.1:8000") as client:
client.send_text(msg)
print(">>> ", msg)
response = client.recv()
print("<<< ", bytes_to_str(response))
response = client.recv_text()
print("<<< ", response)

fn main() raises:
send_and_receive("Hello world!")
Expand All @@ -70,9 +66,7 @@ fn main() raises:

## TODO

- [ ] Asynchronous non-blocking communication (waiting for the Mojo async/await support)
- [ ] Implement automatic reconnection for clients
- [ ] Get rid of Python dependencies and logic (e.g. no more `from python import ...`)
- [ ] Make sure it passes all the tests in [Autobahn|Testsuite](https://github.com/crossbario/autobahn-testsuite/)
- [ ] Implement subprotocols and extensions
- [ ] Optimize performance for high-concurrency scenarios
Expand All @@ -86,9 +80,9 @@ Contributions are welcome! If you'd like to contribute, please follow the contri

## Acknowledgments

We have taken a lot of code from the amazing [lightbug_http](https://github.com/saviorand/lightbug_http) project.

Also, we took inspiration and some code from the [python-websockets](https://github.com/websockets) project, specially for implementing the [WebSocket Sans/IO layer](https://websockets.readthedocs.io/en/stable/howto/sansio.html) and their tests.
* We have taken a lot of code from the amazing [lightbug_http](https://github.com/saviorand/lightbug_http) project.
* We took inspiration and some code from the [python-websockets](https://github.com/websockets) project, specially for implementing the [WebSocket Sans/IO layer](https://websockets.readthedocs.io/en/stable/howto/sansio.html) and their tests.
* We are using the [io_uring](https://github.com/dmitry-salin/io_uring/) library for the I/O operations concurrency.

## License

Expand Down
12 changes: 8 additions & 4 deletions examples/echo/client.mojo
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
"""Client example using the threading API."""

import sys

from websockets.sync.client import connect
from websockets.utils.bytes import bytes_to_str, str_to_bytes


fn send_and_receive_loop() raises:
with connect("ws://127.0.0.1:8001") as client:
args = sys.argv()
port = Int(args[1]) if len(args) > 1 else 8001
with connect("ws://127.0.0.1:{}".format(port)) as client:
while True:
msg = input("Enter a message: ")
client.send_text(msg)
print(">>> ", msg)
response = client.recv()
print("<<< ", bytes_to_str(response))
response = client.recv_text()
print("<<< ", response)


fn main() raises:
Expand Down
4 changes: 3 additions & 1 deletion examples/echo/run_client.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/usr/bin/env bash

mojo -I ../../src/ client.mojo
cd "$(dirname "$0")"
# Run with debug logging enabled
mojo -I ../../src/ -D LOG_LEVEL=DEBUG client.mojo "$@"
4 changes: 3 additions & 1 deletion examples/echo/run_server.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/usr/bin/env bash

mojo -I ../../src/ server.mojo
cd "$(dirname "$0")"
# Run with debug logging enabled
mojo -I ../../src/ -D LOG_LEVEL=DEBUG server.mojo "$@"
16 changes: 10 additions & 6 deletions examples/echo/server.mojo
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
"""Server example using the threading API."""
"""WebSocket server example using io_uring for concurrency."""

import sys
from utils import StringSlice

from websockets.aliases import Bytes
from websockets.sync.server import serve, WSConnection
from websockets.utils.bytes import bytes_to_str


fn on_message(conn: WSConnection, data: Bytes) raises -> None:
str_received = bytes_to_str(data)
str_received = String(StringSlice.from_utf8(data))
print("<<< ", str_received)
conn.send_text(str_received)
print(">>> ", str_received)


fn main() raises:
with serve(on_message, "127.0.0.1", 8001) as server:
print("Starting WebSocket echo server with io_uring concurrency support")
print("Multiple clients can connect simultaneously")
args = sys.argv()
port = Int(args[1]) if len(args) > 1 else 8001
with serve(on_message, "127.0.0.1", port) as server:
server.serve_forever()


Loading