Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

main catchup #1

Merged
merged 64 commits into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
09437c7
initial workflow
dolled-possum Jan 3, 2025
691af73
testing workflow
dolled-possum Jan 3, 2025
9642355
second workflow test
dolled-possum Jan 3, 2025
cc36293
final workflow test
dolled-possum Jan 3, 2025
e952ece
dotenv
dolled-possum Jan 3, 2025
0113105
new implementation for debugging
dolled-possum Jan 3, 2025
a16e45b
meaningless change
litsel-pitdyr Jan 3, 2025
2dfbe37
removed meaningless change
litsel-pitdyr Jan 3, 2025
15fa97d
more debug info
dolled-possum Jan 3, 2025
cd72a0d
avoid error on client close
dolled-possum Jan 3, 2025
6b72d00
updated error code
dolled-possum Jan 3, 2025
4cdb479
100ms delay before trying to send subscription data
litsel-pitdyr Jan 3, 2025
941e947
1 extra zero
litsel-pitdyr Jan 3, 2025
73bb818
delay handshake until remote ready
dolled-possum Jan 3, 2025
f8c3c1e
updating socket close codes
dolled-possum Jan 3, 2025
4e05f14
do not pass 1006 to remoteSocket
dolled-possum Jan 3, 2025
b4f6b8a
add express
dolled-possum Jan 3, 2025
aa4bf28
server/app/routes framework
litsel-pitdyr Jan 3, 2025
c3c094a
default GET
dolled-possum Jan 3, 2025
72d8695
added return to default route
litsel-pitdyr Jan 3, 2025
5e8015d
no host specificity
dolled-possum Jan 3, 2025
4aec91f
Merge branch 'dev' of https://github.com/kinode-dao/rpc-prox into dev
dolled-possum Jan 3, 2025
9aa69a5
copied proxy logic to app.js
litsel-pitdyr Jan 3, 2025
a04d4ab
double-start fix
litsel-pitdyr Jan 3, 2025
df6579f
renamed default route
litsel-pitdyr Jan 3, 2025
e8dc1f1
disabling routes (diagnostic)
litsel-pitdyr Jan 3, 2025
74743df
server def with express no routes
dolled-possum Jan 3, 2025
9fdf308
sigh
dolled-possum Jan 3, 2025
06dbaeb
using Router again
dolled-possum Jan 3, 2025
be1573a
local binding only
dolled-possum Jan 3, 2025
b590b8a
Restoring 1006->1011 handling
dolled-possum Jan 3, 2025
d8ede30
ensure responses are text
dolled-possum Jan 4, 2025
070a368
more coercion to string
dolled-possum Jan 4, 2025
c02672a
cleanup unused test
dolled-possum Jan 4, 2025
2e63bc9
clean up node_modules
dolled-possum Jan 5, 2025
54ec988
confirming workflow
dolled-possum Jan 5, 2025
b7ce0b8
add hostmane to logging
dolled-possum Jan 5, 2025
26114ec
wrong property?
dolled-possum Jan 5, 2025
2bca60a
trust proxy
dolled-possum Jan 5, 2025
ec9b4c0
diagnostics
dolled-possum Jan 5, 2025
5f07a7d
diagonalostics
dolled-possum Jan 5, 2025
2695eaf
testing with node-cache
litsel-pitdyr Jan 6, 2025
854c600
Revert "testing with node-cache"
litsel-pitdyr Jan 6, 2025
f09bc99
retrying node-cache
litsel-pitdyr Jan 6, 2025
55aedd5
moved node-cache init to server.js
litsel-pitdyr Jan 6, 2025
a3cae62
forgot to commit routes.js
litsel-pitdyr Jan 6, 2025
a55a5dd
controller format for proxy management routes
litsel-pitdyr Jan 6, 2025
a8bd832
testing userConnections cached variable
litsel-pitdyr Jan 7, 2025
c55fbba
forgot to reset cache
litsel-pitdyr Jan 7, 2025
6c1d581
different return for getUserConnectionsStatus
litsel-pitdyr Jan 7, 2025
2a055cb
attempting fix for getUserConnectionsStatus return
litsel-pitdyr Jan 8, 2025
9a61c0e
toggleRestrictedProxy -> setRestrictedProxy
litsel-pitdyr Jan 8, 2025
80a8fe7
added express.json()
litsel-pitdyr Jan 8, 2025
d20cc8d
diagnostics
litsel-pitdyr Jan 8, 2025
2815144
another attempted fix
litsel-pitdyr Jan 8, 2025
86192fd
separate route to clear userConnections cache while returning
litsel-pitdyr Jan 8, 2025
1ab960b
added localonly middleware
litsel-pitdyr Jan 8, 2025
611bad6
added /monitor to setRestrictedProxy route
litsel-pitdyr Jan 8, 2025
dbdfad8
route change
dolled-possum Jan 8, 2025
3302b23
middleware secret usage
dolled-possum Jan 8, 2025
1a106a8
testing new proxy subdomain format splitting
litsel-pitdyr Jan 10, 2025
158cff5
check for existance of userConnections cache in getUserConnectionStatus
litsel-pitdyr Jan 10, 2025
3609fee
small fix
litsel-pitdyr Jan 10, 2025
b4bfba5
just a small logging fix
litsel-pitdyr Jan 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
25 changes: 25 additions & 0 deletions .github/workflows/prox_dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: RPC proxy CI

on:
push:
branches: [ dev ]

jobs:
deploy:
runs-on: ubuntu-latest
timeout-minutes: 60

steps:
- name: build and deploy proxy
uses: appleboy/ssh-action@master
with:
host: ${{ vars.SSH_PROX_HOST }}
username: ${{ vars.SSH_USER }}
key: ${{ secrets.SSH_PROX_ED25519KEY }}
port: ${{ vars.SSH_PORT }}
command_timeout: 60m
script: |
cd ~/rpc-prox
git pull origin dev
yarn
~/restart_prox.sh
198 changes: 107 additions & 91 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,92 +1,108 @@
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const url = require('url');
/**
* Delayed WebSocket Proxy:
* The handshake with the client won't complete until we confirm
* the remote server is actually connected.
*/

const app = express();
const server = http.createServer(app);

// Target WebSocket server
const targetWsUrl = 'wss://optimism-mainnet.infura.io/ws/v3/SOME_KEY';

// Create a WebSocket server
const wss = new WebSocket.Server({ server });

// Handle WebSocket connections
wss.on('connection', (clientSocket, req) => {
console.log('New client connected');

const clientDomain = req.headers.host;
console.log(`New client connected from domain: ${clientDomain}`);

// Connect to the target WebSocket server
const targetSocket = new WebSocket(targetWsUrl);

clientSocket.on('message', (message) => {
try {
let decodedMessage = message.toString();
const parsedMessage = JSON.parse(decodedMessage);

// Check the method type
if (parsedMessage.method === 'eth_subscribe') {
console.log('Forwarding eth_subscribe request');
// Forward eth_subscribe request to target
if (targetSocket.readyState === WebSocket.OPEN) {
targetSocket.send(decodedMessage);
}
} else if (parsedMessage.method === 'eth_call') {
console.log('Forwarding eth_call request');
// Forward eth_call request to target
if (targetSocket.readyState === WebSocket.OPEN) {
targetSocket.send(decodedMessage);
}
} else {
console.log('Forwarding unknown request:', parsedMessage.method);
if (targetSocket.readyState === WebSocket.OPEN) {
targetSocket.send(decodedMessage);
}
}
} catch (err) {
console.error('Error parsing or forwarding message:', err);
}
});

targetSocket.on('message', (message) => {
try {
let decodedMessage = message.toString();
const parsedMessage = JSON.parse(decodedMessage);

// For subscriptions (e.g., eth_subscribe), forward messages to the client
if (parsedMessage.params && parsedMessage.params.subscription) {
console.log('Forwarding subscription update');
}

// Send response back to the client
if (clientSocket.readyState === WebSocket.OPEN) {
clientSocket.send(decodedMessage);
}
} catch (err) {
console.error('Error parsing or forwarding target message:', err);
}
});
// Handle client disconnection
clientSocket.on('close', () => {
targetSocket.close();
console.log('Client disconnected');
});

// Handle target server disconnection
targetSocket.on('close', () => {
clientSocket.close();
console.log('Target server disconnected');
});

// Handle errors
clientSocket.on('error', (err) => console.error('Client socket error:', err));
targetSocket.on('error', (err) => console.error('Target socket error:', err));
});

// Start the HTTP server
server.listen(8080, () => {
console.log('WebSocket proxy server running on port 8080');
});
require('dotenv').config();
const http = require('http');
const WebSocket = require('ws');

// For timestamped logs
function tsLog(...args) {
console.log(`[${new Date().toISOString()}]`, ...args);
}
function tsError(...args) {
console.error(`[${new Date().toISOString()}]`, ...args);
}

// Read the remote WebSocket URL from environment variables
const REMOTE_URL = process.env.REMOTE_URL || 'wss://echo.websocket.org';

// Create an HTTP server manually
const server = http.createServer((req, res) => {
// Just respond with something if an HTTP request comes in
res.writeHead(200);
res.end('This is a WS proxy server.\n');
});

// Create a WebSocket server in "noServer" mode
const wss = new WebSocket.Server({ noServer: true });

// Our own connection counter for logging
let connectionCounter = 0;

/**
* "upgrade" event fires whenever a client attempts to upgrade
* from HTTP to WebSocket.
*/
server.on('upgrade', (req, socket, head) => {
// Step 1: Attempt a connection to the REMOTE_URL
const remoteSocket = new WebSocket(REMOTE_URL);

remoteSocket.on('open', () => {
tsLog(`[remote] Connected to ${REMOTE_URL}`);

// Step 2: Once remote is open, upgrade the incoming client connection
wss.handleUpgrade(req, socket, head, (clientSocket) => {
// Step 3: Emit the usual 'connection' event
wss.emit('connection', clientSocket, req, remoteSocket);
});
});

remoteSocket.on('error', (err) => {
tsError('[remote] Failed to connect:', err);
// If remote fails, return an HTTP 503 to the client, then destroy
socket.write('HTTP/1.1 503 Service Unavailable\r\n\r\n');
socket.destroy();
});
});

// Handle new client connections on the wss
wss.on('connection', (clientSocket, req, remoteSocket) => {
const clientId = ++connectionCounter;
tsLog(`[client #${clientId}] Handshake complete (remote is open)`);

// Forward messages client -> remote
clientSocket.on('message', (data) => {
tsLog(`[client #${clientId} -> remote] ${data}`);
if (remoteSocket.readyState === WebSocket.OPEN) {
remoteSocket.send(data);
} else {
tsLog(`[client #${clientId}] Remote not open for sending.`);
}
});

// Forward messages remote -> client
remoteSocket.on('message', (data) => {
tsLog(`[remote -> client #${clientId}] ${data}`);
clientSocket.send(data);
});

// Close events
clientSocket.on('close', (code, reason) => {
tsLog(`[client #${clientId}] Closed (code=${code}, reason=${reason})`);
if(code !== 1006) remoteSocket.close(code, reason);
});
remoteSocket.on('close', (code, reason) => {
tsLog(`[remote -> client #${clientId}] Closed (code=${code}, reason=${reason})`);
clientSocket.close(code, reason);
});

// Error events
clientSocket.on('error', (err) => {
tsError(`[client #${clientId}] Error:`, err);
remoteSocket.close(1011, 'Client error');
});
remoteSocket.on('error', (err) => {
tsError(`[remote -> client #${clientId}] Error:`, err);
clientSocket.close(1011, 'Remote error');
});
});

// Finally, start the HTTP server
const PORT = 8080;
server.listen(PORT, () => {
tsLog(`WebSocket proxy listening on ws://localhost:${PORT}`);
});

1 change: 0 additions & 1 deletion node_modules/.bin/mime

This file was deleted.

1 change: 0 additions & 1 deletion node_modules/.bin/nodemon

This file was deleted.

1 change: 0 additions & 1 deletion node_modules/.bin/nodetouch

This file was deleted.

1 change: 0 additions & 1 deletion node_modules/.bin/semver

This file was deleted.

Loading
Loading