~ev/bogbookv3

53d51feff9b495c1a230ad0d22a7376472a2c76d — Ev Bogue 10 days ago 41643c3
initial stab at replicator, it is only asking but nothing comes back yet
5 files changed, 145 insertions(+), 5 deletions(-)

A denobog.js
A pub.js
A replicate.js
M sbog.js
M server.js
A denobog.js => denobog.js +17 -0
@@ 0,0 1,17 @@
import nacl from './lib/nacl-fast-es.js'
import { keys } from './keys.js'
import { decode, encode } from './lib/base64.js'

export async function open (msg) {
  const author = msg.substring(44, 88)
  const sig = msg.substring(132)
  const hash = sha256(decode(sig))
   
  if (encode(hash) === msg.substring(0, 44)) {
    const opened = nacl.sign.open(decode(sig), decode(author))
    const message = JSON.parse(new TextDecoder().decode(opened))
    message.raw = msg
    return message
  }
}


A pub.js => pub.js +26 -0
@@ 0,0 1,26 @@
import { keys } from './keys.js'

const sockets = new Set()

export async function servePub (e) {


  const { socket, response } = Deno.upgradeWebSocket(e.request)
  const ws = socket
  sockets.add(ws)

  ws.onopen = () => {
  }

  ws.onmessage = (e) => {
    console.log(JSON.parse(e.data))
  }

  ws.onclose = function () {
    sockets.delete(socket)
  }

  ws.onerror = (e) => console.error(e)

  e.respondWith(response)
}

A replicate.js => replicate.js +91 -0
@@ 0,0 1,91 @@
import { keys } from './browserkeys.js'
import { logs } from './browserlog.js'

const peers = new Map()

export function blast (msg) {
  for (const peer of peers.values()) {
    console.log(msg)
    peer.send(msg)
  }
}

function replicate (ws) {
  // first check for my feed
  logs.query(keys.pubkey()).then(log => {
    if (!log) {
      ws.send(JSON.stringify({req: keys.pubkey(), seq: -1}))
    } else {
      ws.send(JSON.stringify({req: keys.pubkey(), seq: log.length}))
    }
  })

  // next check for the route feed

  const feeds = logs.getFeeds()

  var src = window.location.hash.substring(1)
  if (src && !feeds[src]) {
    console.log(src)
    logs.query(src).then(query => {
      if (!query.length) {
        ws.send(JSON.stringify({req: src, seq: -1}))  
      }
    })
  } 

  // next check for updates to existing feeds on repeat
  var timer

  function start () {
    timer = setInterval(function () {
      //console.log('timer')
      const feeds = logs.getFeeds()
      //console.log(feeds)
      Object.keys(feeds).forEach(function (key, index) {
        ws.send(JSON.stringify({req: key, seq: feeds[key].length}))
      })
    }, 10000)
  }

  start()

  // if connection closes we clear the timer and try to reconnect
  ws.onclose = (e) => {
    clearInterval(timer)
    setTimeout(function () {
      console.log('connection to ' + ws.url + ' closed, reconnecting')
      connect(ws.url, keys)
    }, 1000)
  }
}

export function connect (server) {
  console.log('Connecting to ' + server)
  const ws = new WebSocket(server)
  ws.binaryType = 'arraybuffer'

  ws.onopen = () => {
    //ws.send(keys.pubkey())
    replicate(ws)
  }
  
  ws.onmessage = (msg) => {
    console.log(msg.data)
  }

  ws.onclose = (e) => {
    setTimeout(function () {
      connect(server)
    }, 1000)
  }

  let retryCount = 1

  ws.onerror = (err) => {
    setTimeout(function () {
      ws.close()
      retryCount++
    }, 10000 * retryCount)
  }
}

M sbog.js => sbog.js +1 -0
@@ 33,3 33,4 @@ export async function open (msg) {
    return message
  }
}


M server.js => server.js +10 -5
@@ 1,5 1,6 @@
import { keys } from './keys.js'
import { config } from './config.js'
import { servePub } from './pub.js'
import { serveDir } from "https://deno.land/std@0.129.0/http/file_server.ts"
import { green } from 'https://deno.land/std@0.129.0/fmt/colors.ts'



@@ 12,11 13,15 @@ console.log(conf)
async function serve (conn) {
  const httpConn = Deno.serveHttp(conn)
  for await (const e of httpConn) {
    e.respondWith(serveDir(e.request, {fsRoot: '', showDirListing: true, quiet: true})).catch((error) => {
      try {
        conn.close() // coverup for a bug in Deno's http module that errors on connection close
      } catch {}
    })
    if (e.request.url.endsWith('ws')) {
      servePub(e)
    } else {
      e.respondWith(serveDir(e.request, {fsRoot: '', showDirListing: true, quiet: true})).catch((error) => {
        try {
          conn.close() // coverup for a bug in Deno's http module that errors on connection close
        } catch {}
      })
    }
  }
}