Custom Application Integration
How to integrate Secure LSL into your own applications.
Overview
The key principle of Secure LSL is transparency. Your existing code works unchanged; just link against the secure liblsl library and configure keys.
Integration Steps
Step 1: Link Against Secure liblsl
Step 2: Generate Keys
On every device that runs your application:
Step 3: Run Your Application
No code changes needed. Your application now uses encrypted streams.
Adding Security Awareness
While your code works without changes, you can add security awareness for better user experience.
Display Security Status
#include <lsl_cpp.h>
#include <iostream>
void display_security_status(const lsl::stream_info& info) {
std::cout << "Stream: " << info.name() << "\n";
if (info.security_enabled()) {
std::cout << " Status: ENCRYPTED 🔒\n";
std::cout << " Fingerprint: " << info.security_fingerprint() << "\n";
} else {
std::cout << " Status: NOT ENCRYPTED ⚠️\n";
}
}
Require Security
For applications handling sensitive data, you may want to require encryption:
void connect_secure_only(const std::string& stream_type) {
// Check local security first
if (!lsl::local_security_enabled()) {
throw std::runtime_error("Security not configured. Run lsl-keygen first.");
}
// Resolve streams
auto streams = lsl::resolve_stream("type", stream_type, 1, 5.0);
if (streams.empty()) {
throw std::runtime_error("No streams found");
}
// Verify encryption
if (!streams[0].security_enabled()) {
throw std::runtime_error("Stream is not encrypted. "
"Enable security on the stream source.");
}
// Safe to connect
lsl::stream_inlet inlet(streams[0]);
// ...
}
import pylsl
def connect_secure_only(stream_type):
# Check local security first
if not pylsl.local_security_enabled():
raise RuntimeError("Security not configured. Run lsl-keygen first.")
# Resolve streams
streams = pylsl.resolve_stream('type', stream_type, timeout=5.0)
if not streams:
raise RuntimeError("No streams found")
# Verify encryption
if not streams[0].security_enabled():
raise RuntimeError("Stream is not encrypted. "
"Enable security on the stream source.")
# Safe to connect
inlet = pylsl.StreamInlet(streams[0])
return inlet
Security-Aware UI Patterns
Stream Selector with Security Indicators
import pylsl
from tkinter import *
class SecureStreamSelector:
def __init__(self, root):
self.root = root
self.listbox = Listbox(root, width=50)
self.listbox.pack()
self.refresh_streams()
def refresh_streams(self):
self.listbox.delete(0, END)
streams = pylsl.resolve_streams(timeout=2.0)
for stream in streams:
# Add security indicator
if stream.security_enabled():
prefix = "🔒 "
else:
prefix = "⚠️ "
name = f"{prefix}{stream.name()} ({stream.type()}, {stream.channel_count()}ch)"
self.listbox.insert(END, name)
Connection Status Display
class SecurityStatusWidget {
public:
void update(const lsl::stream_info& info) {
if (info.security_enabled()) {
set_icon("lock_icon.png");
set_status("Encrypted");
set_fingerprint(info.security_fingerprint());
set_color(GREEN);
} else {
set_icon("warning_icon.png");
set_status("NOT Encrypted");
set_fingerprint("");
set_color(YELLOW);
}
}
private:
void set_icon(const std::string& path);
void set_status(const std::string& text);
void set_fingerprint(const std::string& fp);
void set_color(Color c);
};
Error Handling
Handle security-related connection failures gracefully:
try {
lsl::stream_inlet inlet(info);
std::vector<float> sample(info.channel_count());
inlet.pull_sample(sample, 5.0);
} catch (const lsl::lost_error& e) {
std::string msg = e.what();
if (msg.find("security") != std::string::npos) {
std::cerr << "Security error: " << msg << "\n";
std::cerr << "Check that all devices have matching security configuration.\n";
} else {
std::cerr << "Connection lost: " << msg << "\n";
}
}
Configuration Management
Application-Specific Configuration
For applications that need custom configuration paths:
// Set config before creating any LSL objects
setenv("LSLAPICFG", "/path/to/app/config/lsl_api.cfg", 1);
// Now create outlets/inlets
lsl::stream_outlet outlet(info);
Bundled Configuration
For standalone applications, bundle the configuration:
#include <filesystem>
void ensure_security_config() {
namespace fs = std::filesystem;
// Check if user has config
fs::path user_config = fs::path(getenv("HOME")) / ".lsl_api" / "lsl_api.cfg";
if (!fs::exists(user_config)) {
std::cout << "Security not configured.\n";
std::cout << "Run: lsl-keygen\n";
// Or offer to run it automatically
}
}
Testing Secure Streams
Unit Test Pattern
#include <gtest/gtest.h>
#include <lsl_cpp.h>
TEST(Security, OutletInletEncrypted) {
// Create secure outlet
lsl::stream_info out_info("TestSecure", "Test", 1, 100, lsl::cf_float32, "test123");
ASSERT_TRUE(out_info.security_enabled());
lsl::stream_outlet outlet(out_info);
// Resolve and verify security
auto results = lsl::resolve_stream("name", "TestSecure", 1, 5.0);
ASSERT_FALSE(results.empty());
ASSERT_TRUE(results[0].security_enabled());
// Create inlet and verify data transfer
lsl::stream_inlet inlet(results[0]);
std::vector<float> out_sample = {42.0f};
outlet.push_sample(out_sample);
std::vector<float> in_sample(1);
inlet.pull_sample(in_sample, 5.0);
ASSERT_FLOAT_EQ(out_sample[0], in_sample[0]);
}
Integration Test with Security Verification
import pytest
import pylsl
def test_secure_stream_round_trip():
"""Verify data survives encryption/decryption."""
# Create outlet
info = pylsl.StreamInfo('SecureTest', 'Test', 8, 256, 'float32', 'pytest123')
assert info.security_enabled(), "Security should be enabled"
outlet = pylsl.StreamOutlet(info)
# Resolve and verify
streams = pylsl.resolve_stream('name', 'SecureTest', timeout=5.0)
assert len(streams) > 0
assert streams[0].security_enabled()
# Create inlet
inlet = pylsl.StreamInlet(streams[0])
# Test data transfer
test_data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]
outlet.push_sample(test_data)
received, _ = inlet.pull_sample(timeout=5.0)
assert received == pytest.approx(test_data)
Deployment Checklist
Before deploying your secure application:
- Application is linked against secure liblsl
- All deployment machines have
lsl-keygenavailable - Documentation explains security setup
- Error messages guide users through security issues
- Optional: Application shows security status in UI
- Optional: Application can require encryption for sensitive data
Next Steps
- C++ API Reference - Full API documentation
- Python API Reference - Python bindings
- How Encryption Works - Technical details