R4SAS
3 years ago
20 changed files with 72 additions and 14423 deletions
@ -1 +1 @@
@@ -1 +1 @@
|
||||
Subproject commit 8b3a7486c74b27199a08dc500e2a19dfe16e53a0 |
||||
Subproject commit 3925540517d31d62d1ad89158e2a075c9d539463 |
@ -1,44 +0,0 @@
@@ -1,44 +0,0 @@
|
||||
<html> |
||||
<head> |
||||
<title> websocket events </title> |
||||
<script type="text/javascript" src="leftpad.js"> |
||||
</script> |
||||
<style> |
||||
pre#log { |
||||
z-index: 1; |
||||
color: white; |
||||
position: fixed; |
||||
right: 0px; |
||||
top: 0px; |
||||
height: 100%; |
||||
font-size: 10px; |
||||
box-shadow: 0px 0px 10px 10px #1a1a1a; |
||||
background: rgba(1,1,1,0.5); |
||||
border-radius: 5px; |
||||
} |
||||
|
||||
body, canvas#main { |
||||
background: #222; |
||||
} |
||||
|
||||
canvas#main { |
||||
position: fixed; |
||||
left: 0px; |
||||
top: 0px; |
||||
z-index: -1; |
||||
} |
||||
|
||||
</style> |
||||
</head> |
||||
<body> |
||||
<div id="login-wrapper"> |
||||
<input id="ws-url" value="ws://127.0.0.1:7666"></input> |
||||
<button id="connect-button" onclick="startui()">connect</button> |
||||
</div> |
||||
<pre id="log"></pre> |
||||
<canvas id="main"> |
||||
</canvas> |
||||
<script type="text/javascript" src="ui.js"> |
||||
</script> |
||||
</body> |
||||
</html> |
@ -1,45 +0,0 @@
@@ -1,45 +0,0 @@
|
||||
|
||||
var cache = [ |
||||
'', |
||||
' ', |
||||
' ', |
||||
' ', |
||||
' ', |
||||
' ', |
||||
' ', |
||||
' ', |
||||
' ', |
||||
' ' |
||||
]; |
||||
|
||||
function leftpad (str, len, ch) { |
||||
// convert `str` to `string`
|
||||
str = str + ''; |
||||
// `len` is the `pad`'s length now
|
||||
len = len - str.length; |
||||
// doesn't need to pad
|
||||
if (len <= 0) return str; |
||||
// `ch` defaults to `' '`
|
||||
if (!ch && ch !== 0) ch = ' '; |
||||
// convert `ch` to `string`
|
||||
ch = ch + ''; |
||||
// cache common use cases
|
||||
if (ch === ' ' && len < 10) return cache[len] + str; |
||||
// `pad` starts with an empty string
|
||||
var pad = ''; |
||||
// loop
|
||||
while (true) { |
||||
// add `ch` to `pad` if `len` is odd
|
||||
if (len & 1) pad += ch; |
||||
// divide `len` by 2, ditch the remainder
|
||||
len >>= 1; |
||||
// "double" the `ch` so this operation count grows logarithmically on `len`
|
||||
// each time `ch` is "doubled", the `len` would need to be "doubled" too
|
||||
// similar to finding a value in binary search tree, hence O(log(n))
|
||||
if (len) ch += ch; |
||||
// `len` is 0, exit the loop
|
||||
else break; |
||||
} |
||||
// pad `str`!
|
||||
return pad + str; |
||||
} |
@ -1,11 +0,0 @@
@@ -1,11 +0,0 @@
|
||||
# i2pd websocket ui # |
||||
|
||||
requires building i2pd with websocket support |
||||
|
||||
make WEBSOCKETS=1 |
||||
|
||||
or |
||||
|
||||
cd i2pd/build |
||||
cmake -DWITH_WEBSOCKETS=ON . |
||||
|
@ -1,405 +0,0 @@
@@ -1,405 +0,0 @@
|
||||
var l = document.getElementById("log"); |
||||
var c = document.getElementById("main"); |
||||
var nodes = { |
||||
length: 0, |
||||
}; |
||||
var in_traffic = 0; |
||||
var out_traffic = 0; |
||||
var tick = 0; |
||||
|
||||
function nodeConnected(ident) { |
||||
if (nodes[ident]) { |
||||
return; |
||||
} |
||||
nodes[ident] = { |
||||
send: 0, |
||||
recv: 0 |
||||
}; |
||||
nodes.length ++; |
||||
} |
||||
|
||||
function nodeDisconnected(ident) { |
||||
if (nodes[ident]) { |
||||
delete nodes[ident]; |
||||
nodes.length --; |
||||
} |
||||
} |
||||
|
||||
function nodeSend(ident, n) { |
||||
if(!nodes[ident]) { |
||||
nodeConnected(ident); |
||||
} |
||||
nodes[ident].send += parseInt(n); |
||||
} |
||||
|
||||
function nodeRecv(ident, n) { |
||||
if(!nodes[ident]) { |
||||
nodeConnected(ident); |
||||
} |
||||
nodes[ident].recv += parseInt(n); |
||||
} |
||||
|
||||
|
||||
var tpeers = {}; |
||||
|
||||
var tunnels = { |
||||
length : 0 |
||||
}; |
||||
|
||||
function ensureTunnel(tid) { |
||||
if(!tunnels[tid]) { |
||||
tunnels[tid] = { |
||||
latency : -1, |
||||
color: "#ddd", |
||||
}; |
||||
tunnels.length ++; |
||||
} |
||||
} |
||||
|
||||
function tunnelBuild(peers, tid, inbound) { |
||||
logit("Tunnel "+tid+" build started"); |
||||
ensureTunnel(tid); |
||||
tunnels[tid].peers = peers.split(":"); |
||||
tunnels[tid].inbound = inbound; |
||||
tunnels[tid].state = "building"; |
||||
} |
||||
|
||||
function tunnelLatency(tid, latency) { |
||||
// logit("tunnel "+tid+" latency "+latency+"ms");
|
||||
if (!tunnels[tid]) return; |
||||
tunnels[tid].latency = latency; |
||||
} |
||||
|
||||
function tunnelEstablished(tid) { |
||||
if(!tunnels[tid]) return; |
||||
logit("Tunnel " + tid + " is healthy"); |
||||
tunnels[tid].state = "healthy"; |
||||
tunnels[tid].color = "#1d1"; |
||||
} |
||||
|
||||
function tunnelBuildFailed(tid) { |
||||
if(!tunnels[tid]) return; |
||||
logit("Tunnel " + tid + " failed to build"); |
||||
delete tunnels[tid]; |
||||
tunnels.length --; |
||||
} |
||||
|
||||
function tunnelTestFailed(tid) { |
||||
if(!tunnels[tid]) return; |
||||
logit("Tunnel " + tid + " has failed tunnel test"); |
||||
tunnels[tid].state = "stuck"; |
||||
tunnels[tid].color = "orange"; |
||||
} |
||||
|
||||
function tunnelFailed(tid) { |
||||
if(!tunnels[tid]) return; |
||||
logit("Tunnel " + tid + " has failed"); |
||||
delete tunnels[tid]; |
||||
tunnels.length--; |
||||
} |
||||
|
||||
function tunnelExpiring(tid) { |
||||
if(!tunnels[tid]) return; |
||||
logit("Tunnel " + tid + " is expired"); |
||||
delete tunnels[tid]; |
||||
tunnels.length--; |
||||
} |
||||
|
||||
|
||||
function tunnelState(tid, state) { |
||||
if (state == "3") { |
||||
tunnelEstablished(tid); |
||||
} else if (state == "2" ) { |
||||
tunnelBuildFailed(tid); |
||||
} else if (state == "4" ) { |
||||
tunnelTestFailed(tid); |
||||
} else if (state == "5" ) { |
||||
tunnelFailed(tid); |
||||
} else if (state == "6" ) { |
||||
tunnelExpiring(tid); |
||||
} |
||||
} |
||||
|
||||
function tunnelCreated(tid) { |
||||
logit("Tunnel "+tid+" was created"); |
||||
} |
||||
|
||||
function logit(msg) { |
||||
console.log(msg); |
||||
var t = document.createTextNode(msg); |
||||
var e = document.createElement("div"); |
||||
e.appendChild(t); |
||||
l.appendChild(e); |
||||
while(l.children.length > 50) |
||||
l.removeChild(l.children[0]); |
||||
} |
||||
|
||||
function socketClosed() { |
||||
var b = document.getElementById("connect-button"); |
||||
b.onclick = startui |
||||
b.innerHTML = "connect"; |
||||
} |
||||
|
||||
function startui() { |
||||
var el = document.getElementById("ws-url"); |
||||
var url; |
||||
if(el) |
||||
url = el.value; |
||||
else |
||||
url = "ws://127.0.0.1:7666"; |
||||
|
||||
var ws = new WebSocket(url); |
||||
ws.onclose = function (ev) { |
||||
if (ev.code == 1000) |
||||
logit("connection closed"); |
||||
else |
||||
logit("failed to connect to "+url); |
||||
nodes = { length: 0 }; |
||||
tpeers = { length: 0 }; |
||||
socketClosed(); |
||||
} |
||||
ws.onopen = function(ev) { |
||||
logit("connected to "+url); |
||||
var b = document.getElementById("connect-button"); |
||||
b.onclick = function() { |
||||
ws.close(); |
||||
} |
||||
b.innerHTML = "disconnect"; |
||||
} |
||||
ws.onmessage = function(ev) { |
||||
var j = JSON.parse(ev.data); |
||||
if (j) { |
||||
console.log(j); |
||||
if(j.type == "transport.connected") { |
||||
nodeConnected(j.ident); |
||||
} else if (j.type == "transport.disconnected") { |
||||
nodeDisconnected(j.ident); |
||||
} else if (j.type == "transport.sendmsg") { |
||||
nodeSend(j.ident, j.number); |
||||
} else if (j.type == "transport.recvmsg") { |
||||
nodeRecv(j.ident, j.number); |
||||
} else if (j.type == "tunnel.build") { |
||||
tunnelBuild(j.value, j.tid, j.inbound); |
||||
} else if (j.type == "tunnel.latency") { |
||||
tunnelLatency(j.tid, j.value); |
||||
} else if (j.type == "tunnel.state") { |
||||
tunnelState(j.tid, j.value); |
||||
} else if (j.type == "tunnels.created") { |
||||
tunnelCreated(j.tid); |
||||
} else if (j.type == "tunnels.expired") { |
||||
tunnelExpiring(j.tid); |
||||
} else { |
||||
logit("message: "+j.type); |
||||
} |
||||
} |
||||
}; |
||||
} |
||||
|
||||
function getPeer(h, us) { |
||||
if (tpeers[h]) { |
||||
return tpeers[h]; |
||||
} |
||||
console.log("make peer "+h); |
||||
|
||||
var p = { |
||||
x: Math.random(), |
||||
y: Math.random(), |
||||
name: h, |
||||
}; |
||||
if (us) { |
||||
p.x = 0.5; |
||||
p.y = 0.5; |
||||
} else { |
||||
while (Math.abs(p.x - 0.5) <= 0.1 ) { |
||||
p.x = Math.random(); |
||||
} |
||||
while (Math.abs(p.y - 0.5) <= 0.1 ) { |
||||
p.y = Math.random(); |
||||
} |
||||
} |
||||
tpeers[h] = p; |
||||
return p; |
||||
} |
||||
|
||||
function drawPeer(p) { |
||||
draw.beginPath(); |
||||
draw.lineWidth = 1; |
||||
draw.fillStyle = "white"; |
||||
draw.strokeStyle = "white"; |
||||
draw.arc(p.x * c.width, p.y * c.height, 20, 0, 2* Math.PI); |
||||
draw.stroke(); |
||||
draw.fillText(p.name.substr(0,6), p.x * c.width, p.y * c.height); |
||||
} |
||||
|
||||
|
||||
function getTraffic(node) { |
||||
if (!node) return 1; |
||||
return 1.0 + ( (node.send + node.recv + 1.0) / 1.5) ; |
||||
} |
||||
var draw = c.getContext("2d"); |
||||
var ticks = 0; |
||||
// draw
|
||||
setInterval(function() { |
||||
draw.canvas.width = window.innerWidth - 100; |
||||
draw.canvas.height = window.innerHeight - 100; |
||||
draw.font = "10px monospace"; |
||||
|
||||
draw.clearRect(0, 0, c.width, c.height); |
||||
|
||||
// draw tunnels
|
||||
|
||||
var e = []; |
||||
|
||||
for (var tid in tunnels) { |
||||
if(tid == "length") continue; |
||||
var t = tunnels[tid]; |
||||
var us = getPeer(t.peers[0], true); |
||||
var traff = getTraffic(nodes[t.peers[1]]); |
||||
e.push([us, getPeer(t.peers[1]), t.color, traff]); |
||||
for (var idx = 1 ; idx + 1 < t.peers.length; idx ++ ) { |
||||
var cur = getPeer(t.peers[idx]); |
||||
var next = getPeer(t.peers[idx+1]); |
||||
if(cur && next) |
||||
e.push([cur, next, t.color, traff]); |
||||
else |
||||
console.log(cur, next); |
||||
} |
||||
} |
||||
|
||||
for ( var h in tpeers ) { |
||||
if( h == "length") continue; |
||||
drawPeer(getPeer(h)); |
||||
} |
||||
|
||||
var newPeers = {}; |
||||
var counter = 0; |
||||
for ( var ed in e ) { |
||||
var edge = e[ed]; |
||||
draw.beginPath(); |
||||
draw.strokeStyle = edge[2]; |
||||
draw.lineWidth = edge[3]; |
||||
draw.moveTo(edge[0].x * c.width, edge[0].y * c.height); |
||||
draw.lineTo(edge[1].x * c.width, edge[1].y * c.height); |
||||
if(!newPeers[edge[0].name]) { |
||||
newPeers[edge[0].name] = edge[0]; |
||||
counter ++; |
||||
} |
||||
if(!newPeers[edge[1].name]) { |
||||
newPeers[edge[1].name] = edge[1]; |
||||
counter ++; |
||||
} |
||||
draw.stroke(); |
||||
} |
||||
newPeers.length = counter; |
||||
tpeers = newPeers; |
||||
|
||||
|
||||
|
||||
// draw nodes
|
||||
|
||||
var n = nodes.length; |
||||
|
||||
var centerx = c.width / 2; |
||||
var centery = c.height / 2; |
||||
|
||||
var mult = Math.log(10 + nodes.length) + 0.5; |
||||
|
||||
var outer_r = ((10 + n) * mult); |
||||
if(outer_r > c.width || outer_r > c.height) { |
||||
var smaller = c.height; |
||||
if(c.width < smaller) smaller = c.width; |
||||
outer_r = smaller - 20; |
||||
} |
||||
|
||||
var inner_r = outer_r / 2; |
||||
draw.beginPath(); |
||||
draw.lineWidth = 1; |
||||
draw.strokeStyle = "white"; |
||||
draw.arc(centerx, centery, inner_r, 0, 2* Math.PI); |
||||
draw.stroke(); |
||||
|
||||
|
||||
var idents = []; |
||||
var rad = 0; |
||||
for( var ident in nodes ) { |
||||
if (ident == "length" ) { |
||||
continue; |
||||
} |
||||
idents.push( ident ); |
||||
} |
||||
|
||||
idents = idents.sort(); |
||||
for (var i = 0; i < idents.length; i++) { |
||||
var ident = idents[i]; |
||||
rad += ( Math.PI * 2 ) / nodes.length; |
||||
|
||||
in_traffic += nodes[ident].recv / 10.0 ; |
||||
out_traffic += nodes[ident].send / 10.0; |
||||
|
||||
var send = (nodes[ident].send ) * 5; |
||||
var recv = (nodes[ident].recv ) * 5; |
||||
|
||||
var traff = (getTraffic(nodes[ident]) - 1) * 5; |
||||
|
||||
var x0 = (Math.cos(rad) * inner_r) + centerx; |
||||
var y0 = (Math.sin(rad) * inner_r) + centery; |
||||
var x1 = (Math.cos(rad) * (inner_r + traff )) + centerx; |
||||
var y1 = (Math.sin(rad) * (inner_r + traff )) + centery; |
||||
|
||||
draw.fillStyle = "white"; |
||||
draw.beginPath(); |
||||
var txt = ident.substr(0, 6); |
||||
draw.fillText(txt, x1-5, y1-5); |
||||
/** |
||||
if(i * 10 < c.height) { |
||||
txt += "| "+leftpad(nodes[ident].recv+" msg/s in", 15)+ " | "+leftpad(nodes[ident].send+" msg/s out", 15)+" |"; |
||||
draw.fillText(txt, 100, 20 + (i*10)); |
||||
} */ |
||||
nodes[ident].recv = 0; |
||||
nodes[ident].send = 0; |
||||
draw.moveTo(x0, y0); |
||||
|
||||
draw.strokeStyle = "#dfa"; |
||||
|
||||
draw.moveTo(x0, y0); |
||||
draw.lineTo(x1, y1); |
||||
draw.lineWidth = 8; |
||||
draw.stroke(); |
||||
/* |
||||
if(( 40 + idx ) < c.height) { |
||||
var send = nodes[ident].send * 10; |
||||
var recv = nodes[ident].recv * 10; |
||||
var t = send + recv; |
||||
if (!t) continue; |
||||
draw.fillStyle = "black"; |
||||
draw.fillText(ident.substr(0, 6), 10, idx); |
||||
draw.beginPath(); |
||||
draw.rect(100, idx-20, send, 10); |
||||
if(send >= c.width) draw.fillStyle = "red"; |
||||
else draw.fillStyle = "green"; |
||||
draw.fill(); |
||||
draw.beginPath(); |
||||
draw.rect(100, idx-10, recv, 10); |
||||
if(recv >= c.width) draw.fillStyle = "red"; |
||||
else draw.fillStyle = "blue"; |
||||
draw.fill(); |
||||
|
||||
idx += 40; |
||||
} |
||||
*/ |
||||
|
||||
} |
||||
draw.fillStyle = "white"; |
||||
draw.fillText("Tracked Peers | " +leftpad(" "+ nodes.length, 10), 500, 25); |
||||
draw.fillText("Tracked Tunnels | " +leftpad(" "+ tunnels.length, 10), 500, 35); |
||||
draw.fillText("In Traffic | "+leftpad(" "+Math.ceil(in_traffic)+" msg/s", 10), 500, 45); |
||||
draw.fillText("Out Traffic | "+leftpad(" "+Math.ceil(out_traffic)+" msg/s", 10), 500, 55); |
||||
|
||||
if (tick % 10 == 0) { |
||||
in_traffic = 0; |
||||
out_traffic = 0; |
||||
} |
||||
tick ++; |
||||
}, 100); |
||||
|
||||
logit("loaded"); |
@ -1,17 +0,0 @@
@@ -1,17 +0,0 @@
|
||||
WEBSOCKS_SRC = websocks.js |
||||
BT_OUT = websocks-bt.js |
||||
BT_SRC = bittorrent.js |
||||
|
||||
IRC_OUT = websocks-irc.js |
||||
IRC_SRC = irc-client.js |
||||
|
||||
all: $(BT_OUT) $(IRC_OUT) |
||||
|
||||
$(IRC_OUT): |
||||
browserify $(WEBSOCKS_SRC) $(IRC_SRC) -o $(IRC_OUT) |
||||
|
||||
$(BT_OUT): |
||||
browserify $(WEBSOCKS_SRC) $(BT_SRC) -o $(BT_OUT) |
||||
|
||||
clean: |
||||
rm -f $(BT_OUT) $(IRC_OUT) |
@ -1,12 +0,0 @@
@@ -1,12 +0,0 @@
|
||||
<!doctype html> |
||||
<html> |
||||
<head> |
||||
<title> bittorrent over i2p with WebSOCKS </title> |
||||
<script src="websocks-bt.js" type="text/javascript"></script> |
||||
<link rel="stylesheet" href="style.css"></link> |
||||
</head> |
||||
<body> |
||||
<label for="ws-server">WebSOCKS server:</label><input id="ws-server" value="ws://127.0.0.1:7766/"></input> |
||||
<label for="torrent-file">Torrent File:</label><input type="file" id="torrent-file" /> |
||||
<button onclick="start_downloading()">start</button> |
||||
</html> |
@ -1,23 +0,0 @@
@@ -1,23 +0,0 @@
|
||||
var Protocol = require('bittorrent-protocol'); |
||||
var stream = require('stream'); |
||||
var WebSocks = require("./websocks.js").WebSocks; |
||||
|
||||
|
||||
function start_torrent(torrent_file_blob) |
||||
{ |
||||
var torrent = new WebsocksTorrent(); |
||||
var elem = document.getElementById("ws-server"); |
||||
torrent.start(elem.value); |
||||
torrent.addTorrent(torrent_file_blob); |
||||
} |
||||
|
||||
function start_downloading() |
||||
{ |
||||
var elem = document.getElementById("torrent-file"); |
||||
var files = elem.files; |
||||
for (var f of files) { |
||||
if(f.slice) { |
||||
start_torrent(f.slice()); |
||||
} |
||||
} |
||||
} |
@ -1,10 +0,0 @@
@@ -1,10 +0,0 @@
|
||||
<!doctype html> |
||||
<html> |
||||
<head> |
||||
<title> websocks demos </title> |
||||
</head> |
||||
<body> |
||||
<a href="irc-client.html">irc client demo</a> |
||||
<a href="bittorrent-client.html">bittorrent client demo</a> |
||||
</body> |
||||
</html> |
@ -1,14 +0,0 @@
@@ -1,14 +0,0 @@
|
||||
<!doctype html> |
||||
<html> |
||||
<head> |
||||
<title> irc client with WebSOCKS </title> |
||||
<link rel="stylesheet" href="style.css"></link> |
||||
</head> |
||||
<body> |
||||
<label for="ws-server">WebSOCKS server:</label><input id="ws-server" value="ws://127.0.0.1:7766/"></input> |
||||
<input id="irc-server" value="irc.dg.i2p"></input> |
||||
<button id="connect">connect</button> |
||||
<div id="irc-window"> |
||||
</div> |
||||
<script src="websocks-irc.js" type="text/javascript"></script> |
||||
</html> |
@ -1,292 +0,0 @@
@@ -1,292 +0,0 @@
|
||||
var WebSocks = require("./websocks.js").WebSocks; |
||||
|
||||
|
||||
function ws_try_connect() |
||||
{ |
||||
|
||||
var elem = document.getElementById("irc-window"); |
||||
elem.remove(); |
||||
elem = document.createElement("div"); |
||||
elem.id ="irc-window"; |
||||
document.body.appendChild(elem); |
||||
|
||||
var input = document.createElement("input"); |
||||
input.setAttribute("class", "text-input"); |
||||
elem.appendChild(input); |
||||
|
||||
|
||||
var irc = { |
||||
connected: 0, |
||||
line_in: "", |
||||
target: "", |
||||
nick: "ebin", |
||||
panes: {} |
||||
}; |
||||
|
||||
function irc_ui_show_pane(pane) |
||||
{ |
||||
irc_ui_ensure_pane(pane); |
||||
// hide all other panes
|
||||
for (var k in irc.panes) { |
||||
if(k == pane) { |
||||
irc.panes[k].elem.style = "display: inline-block"; |
||||
irc.target = k; |
||||
} else { |
||||
irc.panes[k].elem.style = "display: none"; |
||||
} |
||||
} |
||||
} |
||||
|
||||
function irc_ui_ensure_pane(pane) |
||||
{ |
||||
if(irc.panes[pane]) return; |
||||
var e = document.createElement("pre"); |
||||
e.setAttribute("class", "text-window"); |
||||
e.style = "display: none"; |
||||
e.setAttribute("panename", pane); |
||||
irc.panes[pane] = { |
||||
elem: e, |
||||
name: pane |
||||
}; |
||||
var root = document.getElementById("irc-window"); |
||||
root.appendChild(e); |
||||
} |
||||
|
||||
function irc_ui_println(line, pane) |
||||
{ |
||||
if(line == "") return; |
||||
var node = document.createTextNode(line); |
||||
var e = document.createElement("div"); |
||||
e.appendChild(node); |
||||
if(!pane) { |
||||
pane = " "; |
||||
} |
||||
irc_ui_ensure_pane(pane); |
||||
var p = irc.panes[pane]; |
||||
if(p) { |
||||
p.elem.appendChild(e); |
||||
if (pane == irc.target) { |
||||
window.scroll(0, p.elem.offsetTop + p.elem.offsetHeight); |
||||
} |
||||
} else { |
||||
console.log("No pane called "+pane); |
||||
} |
||||
|
||||
} |
||||
|
||||
function irc_on_privmsg(src, target, msg) |
||||
{ |
||||
var parts = src.split("!"); |
||||
src = parts[0].slice(1); |
||||
irc_ui_println("<"+src+ "> "+msg, target); |
||||
} |
||||
|
||||
function irc_on_greeted(conn) |
||||
{ |
||||
irc_ui_println("successfully joined irc"); |
||||
} |
||||
|
||||
function irc_on_join(src, target) |
||||
{ |
||||
irc_ui_println("--> "+src, target); |
||||
} |
||||
|
||||
function irc_on_part(src, target) |
||||
{ |
||||
irc_ui_println("<-- "+src, target); |
||||
} |
||||
|
||||
function irc_on_other(src, cmd, target, msg) |
||||
{ |
||||
irc_ui_println("<"+src+"> "+msg, src); |
||||
} |
||||
|
||||
function irc_process_in(conn) |
||||
{ |
||||
var line = irc.line_in.trim(); |
||||
console.log("--> "+line); |
||||
if(line.startsWith("PING ")) { |
||||
// handle ping
|
||||
irc_sendline(conn, "PONG "+line.slice(5)); |
||||
return; |
||||
} |
||||
var parts = line.split(" "); |
||||
if (parts.length > 2) { |
||||
var src = parts[0]; |
||||
var cmd = parts[1]; |
||||
var target = parts[2]; |
||||
var idx = line.indexOf(target); |
||||
var msg = line.slice(idx+target.length+2); |
||||
if (cmd == "PRIVMSG") { |
||||
irc_on_privmsg(src, target, msg); |
||||
return; |
||||
} |
||||
if (cmd == "JOIN" ) { |
||||
irc_on_join(src, target); |
||||
return; |
||||
} |
||||
if (cmd == "PART") { |
||||
irc_on_part(src, target); |
||||
return; |
||||
} |
||||
|
||||
if(cmd == "PONG") return; |
||||
if(cmd == "376") { |
||||
// we have been greeted fully
|
||||
irc_on_greeted(conn); |
||||
return; |
||||
} |
||||
if (cmd == "433") { |
||||
irc.nick = irc.nick + "_"; |
||||
irc_sendline(conn, "NICK "+irc.nick); |
||||
irc_sendline(conn, "USER "+irc.nick+" "+irc.nick+" "+irc.nick+" :"+irc.nick); |
||||
} |
||||
irc_on_other(src.slice(1), cmd, target, msg); |
||||
} |
||||
irc_ui_println(line); |
||||
} |
||||
|
||||
function irc_data(conn, data) |
||||
{ |
||||
data = irc.line_in + data; |
||||
var lines = data.split("\n"); |
||||
for(var idx = 0; idx < lines.length; idx++) { |
||||
irc.line_in = lines [idx] + "\n"; |
||||
irc_process_in(conn); |
||||
} |
||||
} |
||||
|
||||
function irc_sendline(conn, line) |
||||
{ |
||||
console.log("<-- "+ line); |
||||
conn.write(line + "\n"); |
||||
} |
||||
|
||||
function irc_privmsg(conn, target, msg) |
||||
{ |
||||
irc_ui_println("<"+irc.nick+"> "+msg, target); |
||||
irc_sendline(conn, "PRIVMSG "+target+" :"+msg); |
||||
} |
||||
|
||||
function irc_join_channel(conn, chnl) |
||||
{ |
||||
irc_sendline(conn, "JOIN "+chnl); |
||||
irc_ui_ensure_pane(chnl); |
||||
} |
||||
|
||||
function handle_input_command(conn, arg, params) |
||||
{ |
||||
arg = arg.toLowerCase(); |
||||
if (arg == "j" || arg == "join") { |
||||
for (var idx = 0 ; idx < params.length; idx ++) { |
||||
irc_join_channel(conn, params[idx]); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
if(arg == "lp" || arg == "listpanes") { |
||||
irc_ui_println("--- begin list of panes", irc.target); |
||||
for (var k in irc.panes) { |
||||
if(k == irc.target) { |
||||
irc_ui_println("(active) : "+k, irc.target); |
||||
} else { |
||||
irc_ui_println(" : "+k, irc.target); |
||||
} |
||||
} |
||||
irc_ui_println("--- end list of panes", irc.target); |
||||
return; |
||||
} |
||||
|
||||
|
||||
if(arg == "m" || arg == "msg") { |
||||
irc_privmsg(conn, params[0], params.slice(1).join(" ")); |
||||
return; |
||||
} |
||||
|
||||
if(arg == "n" || arg == "nick") { |
||||
irc_sendline(conn, "NICK "+params[0]); |
||||
irc.nick = params[0]; |
||||
return; |
||||
} |
||||
if(arg == "r" || arg == "raw") { |
||||
irc_sendline(conn, params.join(" ")); |
||||
return; |
||||
} |
||||
if(arg == "q" || arg == "quit") { |
||||
irc_sendline(conn, "QUIT"); |
||||
return; |
||||
} |
||||
if(arg == "w" || arg == "window") { |
||||
irc.target = params[0]; |
||||
irc_ui_show_pane(irc.target); |
||||
return; |
||||
} |
||||
} |
||||
|
||||
function handle_input_line(conn, line) |
||||
{ |
||||
if(line[0] == "/") { |
||||
var parts = line.split(" "); |
||||
handle_input_command(conn, parts[0].slice(1), parts.slice(1)); |
||||
} else { |
||||
irc_privmsg(conn, irc.target, line); |
||||
} |
||||
}; |
||||
|
||||
function irc_connected(conn, url) |
||||
{ |
||||
irc.connected = 1; |
||||
console.log("connected to irc"); |
||||
irc_ui_println("connecting to "+url+"..."); |
||||
// send user command
|
||||
irc_sendline(conn, "NICK "+irc.nick); |
||||
irc_sendline(conn, "USER "+irc.nick+" "+irc.nick+" "+irc.nick+" :"+irc.nick); |
||||
irc.pinger = setInterval(function(){ |
||||
if(irc.connected) { |
||||
irc_sendline(conn, "PING :i-hate-tcp-lol-"+new Date().getTime()); |
||||
} |
||||
}, 10000); |
||||
input.addEventListener("keypress", function(ev){ |
||||
// handle enter key
|
||||
switch(ev.key) { |
||||
case "Enter": |
||||
handle_input_line(conn, input.value); |
||||
ev.preventDefault(); |
||||
input.value = ""; |
||||
} |
||||
return; |
||||
}); |
||||
} |
||||
|
||||
var e = document.getElementById("ws-server"); |
||||
var wsurl = e.value; |
||||
e = document.getElementById("irc-server"); |
||||
var irc_url = e.value; |
||||
|
||||
var parts = irc_url.split(":"); |
||||
var host = parts[0]; |
||||
var port = 6667; |
||||
if(parts.length != 1) { |
||||
port = parts[1]; |
||||
} |
||||
|
||||
irc_ui_show_pane(" "); |
||||
|
||||
var sock = new WebSocks(wsurl); |
||||
|
||||
sock.connect(host, port, function(err, writer, reader) { |
||||
if(err) { |
||||
console.log(err); |
||||
} else { |
||||
irc_connected(writer); |
||||
reader.on("data", function(data) { |
||||
irc_data(writer, data); |
||||
}); |
||||
} |
||||
}); |
||||
}; |
||||
|
||||
document.getElementById("connect").onclick = function() { |
||||
console.log("try connect"); |
||||
ws_try_connect(); |
||||
}; |
@ -1,15 +0,0 @@
@@ -1,15 +0,0 @@
|
||||
# demos |
||||
|
||||
## dependencies |
||||
|
||||
* browserify |
||||
* GNU Make |
||||
* i2pd with websockets enabled |
||||
* websocks tunnel |
||||
|
||||
## usage: |
||||
|
||||
make |
||||
python3 -m http.server 3000 |
||||
|
||||
then go [here](http://127.0.0.1:3000/) |
@ -1,23 +0,0 @@
@@ -1,23 +0,0 @@
|
||||
|
||||
.text-window { |
||||
position: fixed; |
||||
height: 90%; |
||||
width: 100%; |
||||
white-space: pre-wrap; |
||||
overflow-wrap: break-word; |
||||
overflow-y: scroll; |
||||
} |
||||
|
||||
.text-input { |
||||
width: 100%; |
||||
position: fixed; |
||||
bottom: 0px; |
||||
left: 10px; |
||||
} |
||||
|
||||
#irc-window { |
||||
position: fixed; |
||||
width: 95%; |
||||
top: 20px; |
||||
left: 10px; |
||||
} |
@ -1,137 +0,0 @@
@@ -1,137 +0,0 @@
|
||||
var stream = require('stream'); |
||||
|
||||
|
||||
function WebSocks(wsurl) |
||||
{ |
||||
this._wsurl = wsurl; |
||||
this._ws = null; |
||||
this._ouraddr = null; |
||||
this._remoteAddr = null; |
||||
this._recvbuffer = stream.PassThrough(); |
||||
this._sendbuffer = stream.PassThrough(); |
||||
} |
||||
|
||||
WebSocks.prototype.createListener = function(callback) { |
||||
var self = this; |
||||
self._doAccept(function(err) { |
||||
if(err) callback(err, null); |
||||
else { |
||||
callback(null, self._sendbuffer, self._recvbuffer); |
||||
} |
||||
}, function(data) { |
||||
self._recvbuffer.write(data); |
||||
}); |
||||
}; |
||||
|
||||
WebSocks.prototype._doAccept = function(accept_cb, recv_cb) { |
||||
var self = this; |
||||
self._socket(function (err, data) { |
||||
if(!self._remoteAddr) |
||||
{ |
||||
if(!data) |
||||
{ |
||||
// send handshake
|
||||
self._ws.send("accept"); |
||||
} |
||||
else |
||||
{ |
||||
// this means handshake read
|
||||
var j = JSON.parse(data); |
||||
if(j.error) { |
||||
connect_cb(j.error); |
||||
} else if(j.success){ |
||||
self._remoteAddr = host; |
||||
connect_cb(null); |
||||
} |
||||
// repeat
|
||||
setTimeout(function() { |
||||
self._doAccept(connect_cb); |
||||
}, 10); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
recv_cb(err, data); |
||||
} |
||||
}); |
||||
}; |
||||
|
||||
WebSocks.prototype._closed = function() |
||||
{ |
||||
var self = this; |
||||
self._recvbuffer.close(); |
||||
self._sendbuffer.close(); |
||||
self._ws.close(); |
||||
}; |
||||
|
||||
WebSocks.prototype.connect = function(host, port, connect_cb) { |
||||
var self = this; |
||||
self._socket(function (err, data) { |
||||
if(!self._remoteAddr) |
||||
{ |
||||
if(!data) |
||||
{ |
||||
// send handshake
|
||||
self._ws.send("connect "+host+":"+port); |
||||
} |
||||
else |
||||
{ |
||||
// this means handshake read
|
||||
var j = JSON.parse(data); |
||||
if(j.error) { |
||||
connect_cb(j.error, null, null); |
||||
} else if(j.success){ |
||||
self._remoteAddr = host; |
||||
connect_cb(null, self._sendbuffer, self._recvbuffer); |
||||
} else { |
||||
connect_cb("failed to connect", null, null); |
||||
} |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
self._recvbuffer.write(data); |
||||
} |
||||
}); |
||||
}; |
||||
|
||||
WebSocks.prototype._socket = function(cb) { |
||||
var self = this; |
||||
self._ws = new WebSocket(self._wsurl); |
||||
self._ws.onclose = function(ev) { |
||||
self._closed(); |
||||
}; |
||||
|
||||
self._ws.onopen = function(ev) { |
||||
console.log("connected to websocks"); |
||||
self._ws.send("getaddr"); |
||||
}; |
||||
|
||||
self._ws.onmessage = function(ev) { |
||||
if(!self._ouraddr) |
||||
{ |
||||
var j = JSON.parse(ev.data); |
||||
if(j.error) { |
||||
console.log("connect error: "+j.error); |
||||
cb(j.error, null); |
||||
return; |
||||
} |
||||
if(j.success && j.destination) { |
||||
self._ouraddr = j.destination; |
||||
} else { |
||||
cb("failed to connect", null); |
||||
return; |
||||
} |
||||
self._sendbuffer.on("data", function(data) { |
||||
self._ws.send(data); |
||||
}); |
||||
cb(null, null); |
||||
} |
||||
else |
||||
cb(null, ev.data); |
||||
}; |
||||
}; |
||||
|
||||
module.exports = { |
||||
"WebSocks": WebSocks, |
||||
}; |
Loading…
Reference in new issue