2026-01-30 17:33:19 -03:00
# libeasystorage
2026-01-30 12:00:38 -03:00
2026-02-02 15:50:33 -03:00
A simplified, higher-level C wrapper around [libstorage ](https://github.com/status-im/logos-storage-nim ). Includes
2026-02-02 15:09:44 -03:00
examples showing how to implement simple filesharing apps.
2026-01-30 12:00:38 -03:00
## Prerequisites
- CMake 3.14+
- C11 compiler
- libstorage (build or get binary from [logos-storage-nim ](https://github.com/status-im/logos-storage-nim ))
## Building
```bash
cmake -B build -DLOGOS_STORAGE_NIM_ROOT=/path/to/logos-storage-nim
cmake --build build
```
2026-02-02 15:50:33 -03:00
This produces three example executables:
- `storageconsole` — interactive CLI for managing a storage node
- `uploader` — uploads a local file and prints the CID and SPR
- `downloader` — downloads a file given a bootstrap SPR and CID
2026-01-30 12:00:38 -03:00
2026-01-30 12:48:51 -03:00
## API
```c
#include "easystorage.h"
2026-01-30 12:00:38 -03:00
2026-01-30 12:48:51 -03:00
// Create and start a node
node_config cfg = {
.api_port = 8080,
.disc_port = 9090,
.data_dir = "./data",
.log_level = "INFO",
2026-02-02 15:50:33 -03:00
.bootstrap_node = "< SPR > ",
.nat = "auto"
2026-01-30 12:48:51 -03:00
};
STORAGE_NODE node = e_storage_new(cfg);
e_storage_start(node);
2026-01-30 12:00:38 -03:00
2026-02-02 15:50:33 -03:00
// Get the node's Signed Peer Record
char *spr = e_storage_spr(node);
free(spr);
2026-01-30 12:48:51 -03:00
// Upload a file
char *cid = e_storage_upload(node, "/path/to/file.txt", progress_cb);
// Download a file
e_storage_download(node, cid, "/path/to/output.txt", progress_cb);
2026-01-30 18:14:42 -03:00
free(cid);
2026-01-30 12:00:38 -03:00
2026-01-30 12:48:51 -03:00
// Cleanup
e_storage_stop(node);
e_storage_destroy(node);
2026-01-30 12:00:38 -03:00
```
2026-01-30 12:48:51 -03:00
2026-02-02 15:50:33 -03:00
Configuration can also be loaded from an INI file:
```ini
[easystorage]
api-port=8080
disc-port=9090
data-dir=./data
log-level=INFO
bootstrap-node=spr:...
nat=none
```
2026-01-30 12:48:51 -03:00
2026-02-02 15:50:33 -03:00
```c
node_config cfg = {0};
e_storage_read_config("config.ini", &cfg);
// ... use cfg ...
e_storage_free_config(&cfg);
```
## Examples
### storageconsole
An interactive CLI included in `examples/storageconsole.c` :
2026-01-30 12:48:51 -03:00
```bash
./build/storageconsole
2026-01-30 12:00:38 -03:00
```
2026-01-30 12:48:51 -03:00
Commands: `help` , `start` , `stop` , `upload` , `download` , `quit` .
2026-02-02 15:50:33 -03:00
### uploader / downloader
2026-02-16 15:45:44 +11:00
Standalone programs that demonstrate file sharing between two nodes.
Optionally generate a file to upload. For example, using `dd` on nix-based systems:
```bash
# generate a 500MB file with random contents
dd if=/dev/urandom of=myfile.txt bs=1048576 count=500
```
2026-02-23 21:24:51 +11:00
In one terminal, start the uploader, passing in the path to a file to upload:
2026-02-02 15:50:33 -03:00
```bash
./build/uploader ./myfile.txt
# prints: Run: downloader <SPR> <CID> ./output-file
```
2026-02-16 15:45:44 +11:00
In another terminal, run the downloader with the printed values:
2026-02-02 15:50:33 -03:00
```bash
./build/downloader < SPR > < CID > ./output-file
```
2026-02-23 21:24:51 +11:00
#### Connecting to remote peers
To run the uploader/downloader example, but connect to peers remotely, the config will need to be updated before it will work.
##### UPnP / PMP
The easiest way to connect to remote peers is to enable UPnP or PMP in your router. Once this is enabled, update the config to:
```c
// uploader.c
node_config cfg = {
.api_port = 8080,
.disc_port = 9090,
.data_dir = "./uploader-data",
.log_level = "TRACE",
.bootstrap_node = "spr:CiUIAhIhApIj9p6zJDRbw2NoCo-tj98Y760YbppRiEpGIE1yGaMzEgIDARpJCicAJQgCEiECkiP2nrMkNFvDY2gKj62P3xjvrRhumlGISkYgTXIZozMQvcz8wQYaCwoJBAWhF3WRAnVEGgsKCQQFoRd1kQJ1RCpGMEQCIFZB84O_nzPNuViqEGRL1vJTjHBJ-i5ZDgFL5XZxm4HAAiB8rbLHkUdFfWdiOmlencYVn0noSMRHzn4lJYoShuVzlw",
.nat = "upnp" // or "pmp" or "any",
};
// downlaoder.c
node_config cfg = {
.api_port = 8081,
.disc_port = 9091,
.data_dir = "./downloader-data",
.log_level = "TRACE",
.bootstrap_node = "spr:CiUIAhIhApIj9p6zJDRbw2NoCo-tj98Y760YbppRiEpGIE1yGaMzEgIDARpJCicAJQgCEiECkiP2nrMkNFvDY2gKj62P3xjvrRhumlGISkYgTXIZozMQvcz8wQYaCwoJBAWhF3WRAnVEGgsKCQQFoRd1kQJ1RCpGMEQCIFZB84O_nzPNuViqEGRL1vJTjHBJ-i5ZDgFL5XZxm4HAAiB8rbLHkUdFfWdiOmlencYVn0noSMRHzn4lJYoShuVzlw",
.nat = "upnp" // or "pmp" or "any",
};
```
By specifying a common bootstrap node, the uploader and downloader will be able to share DHT entries. Specifically, the uploader will announce itself as a provider for the CID in the DHT to its closes neighbours (the bootstrap node), and the downloader will be able to traverse its closest peers when finding a provider for the CID.
#### Connecting to peers on the same network or machine
To connect to peers locally, the same config updates need to be made, except now, `nat` should be set to `none` :
```c
// uploader.c
node_config cfg = {
.api_port = 8080,
.disc_port = 9090,
.data_dir = "./uploader-data",
.log_level = "TRACE",
.bootstrap_node = "spr:CiUIAhIhApIj9p6zJDRbw2NoCo-tj98Y760YbppRiEpGIE1yGaMzEgIDARpJCicAJQgCEiECkiP2nrMkNFvDY2gKj62P3xjvrRhumlGISkYgTXIZozMQvcz8wQYaCwoJBAWhF3WRAnVEGgsKCQQFoRd1kQJ1RCpGMEQCIFZB84O_nzPNuViqEGRL1vJTjHBJ-i5ZDgFL5XZxm4HAAiB8rbLHkUdFfWdiOmlencYVn0noSMRHzn4lJYoShuVzlw",
.nat = "none"
};
// downlaoder.c
node_config cfg = {
.api_port = 8081,
.disc_port = 9091,
.data_dir = "./downloader-data",
.log_level = "TRACE",
.bootstrap_node = "spr:CiUIAhIhApIj9p6zJDRbw2NoCo-tj98Y760YbppRiEpGIE1yGaMzEgIDARpJCicAJQgCEiECkiP2nrMkNFvDY2gKj62P3xjvrRhumlGISkYgTXIZozMQvcz8wQYaCwoJBAWhF3WRAnVEGgsKCQQFoRd1kQJ1RCpGMEQCIFZB84O_nzPNuViqEGRL1vJTjHBJ-i5ZDgFL5XZxm4HAAiB8rbLHkUdFfWdiOmlencYVn0noSMRHzn4lJYoShuVzlw",
.nat = "none"
};
```
2026-01-30 12:00:38 -03:00
## Testing
```bash
cmake --build build
2026-02-02 15:50:33 -03:00
ctest --test-dir build
2026-01-30 12:00:38 -03:00
```
2026-02-02 15:50:33 -03:00
Tests use a mock libstorage implementation and do not require a running storage node.
2026-01-30 12:00:38 -03:00
## Project Structure
```
2026-02-02 15:50:33 -03:00
├── easystorage.h # Public API
├── easystorage.c # Implementation
├── CMakeLists.txt
2026-01-30 12:48:51 -03:00
├── examples/
2026-02-02 15:50:33 -03:00
│ ├── storageconsole.c # Interactive CLI
│ ├── uploader.c # File upload example
│ └── downloader.c # File download example
2026-01-30 12:00:38 -03:00
├── tests/
2026-02-02 15:50:33 -03:00
│ ├── test_runner.c # Unit tests
│ └── mock_libstorage.c # Mock libstorage for testing
└── vendor/
└── inih/ # Vendored INI file parser
2026-01-30 12:00:38 -03:00
```
## License
Dual-licensed under [Apache 2.0 ](LICENSE-APACHEv2 ) and [MIT ](LICENSE-MIT ).