Commit of work so far
This commit is contained in:
commit
8a5717b73c
|
@ -0,0 +1,80 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"io"
|
||||
"math/big"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
OrganisationName = "Status IM"
|
||||
)
|
||||
|
||||
func getCertTemplate() *x509.Certificate {
|
||||
return &x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
Subject: pkix.Name{
|
||||
Organization: []string{OrganisationName},
|
||||
},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().Add(time.Hour),
|
||||
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
BasicConstraintsValid: true,
|
||||
}
|
||||
}
|
||||
|
||||
func generateCert(certWriter io.Writer, key *ecdsa.PrivateKey) error {
|
||||
certTemplate := getCertTemplate()
|
||||
certBytes, err := x509.CreateCertificate(rand.Reader, certTemplate, certTemplate, &key.PublicKey, key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return pem.Encode(certWriter, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes})
|
||||
}
|
||||
|
||||
func generateKey(keyWriter io.Writer, key *ecdsa.PrivateKey) error {
|
||||
b, err := x509.MarshalECPrivateKey(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return pem.Encode(keyWriter, &pem.Block{Type: "EC PRIVATE KEY", Bytes: b})
|
||||
}
|
||||
|
||||
func GenerateKeyAndCert(certWriter io.Writer, keyWriter io.Writer) error {
|
||||
privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = generateCert(certWriter, privKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = generateKey(keyWriter, privKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteKeyAndCert() error {
|
||||
err := os.Remove(TLSKeyName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.Remove(TLSCertName)
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGenerateKeyAndCert(t *testing.T) {
|
||||
crtWriter := bytes.NewBuffer([]byte{})
|
||||
keyWriter := bytes.NewBuffer([]byte{})
|
||||
|
||||
err := GenerateKeyAndCert(crtWriter, keyWriter)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
expected := []*struct {
|
||||
Name string
|
||||
Bytes []byte
|
||||
Len int
|
||||
BeginWith string
|
||||
EndWith string
|
||||
PemBlock *pem.Block
|
||||
}{
|
||||
{
|
||||
"certificate",
|
||||
crtWriter.Bytes(),
|
||||
509,
|
||||
"-----BEGIN CERTIFICATE-----",
|
||||
"-----END CERTIFICATE-----",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"private key",
|
||||
keyWriter.Bytes(),
|
||||
227,
|
||||
"-----BEGIN EC PRIVATE KEY-----",
|
||||
"-----END EC PRIVATE KEY-----",
|
||||
nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, e := range expected {
|
||||
if len(e.Bytes) != e.Len {
|
||||
t.Errorf("%s pem bytes should be %d in length, received %d",
|
||||
e.Name,
|
||||
e.Len,
|
||||
len(e.Bytes),
|
||||
)
|
||||
}
|
||||
|
||||
bwl := len(e.BeginWith)
|
||||
if string(e.Bytes[:bwl]) != e.BeginWith {
|
||||
t.Errorf("%s pem should begin with '%s', recieved '%s'",
|
||||
e.Name,
|
||||
e.BeginWith,
|
||||
string(e.Bytes[:bwl]),
|
||||
)
|
||||
}
|
||||
|
||||
ewl := len(e.EndWith)
|
||||
if string(e.Bytes[len(e.Bytes)-ewl-1:len(e.Bytes)-1]) != e.EndWith{
|
||||
t.Errorf("%s pem should end with '%s', recieved '%s'",
|
||||
e.Name,
|
||||
e.EndWith,
|
||||
e.Bytes[len(e.Bytes)-ewl-1:len(e.Bytes)-1],
|
||||
)
|
||||
}
|
||||
|
||||
pb, r := pem.Decode(e.Bytes)
|
||||
if len(r) != 0 {
|
||||
t.Errorf("%s pem decode should be empty, remaining bytes %v", e.Name, r)
|
||||
}
|
||||
e.PemBlock = pb
|
||||
}
|
||||
|
||||
_, err = x509.ParseCertificate(expected[0].PemBlock.Bytes)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = x509.ParseECPrivateKey(expected[1].PemBlock.Bytes)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteKeyAndCert(t *testing.T) {
|
||||
err := DeleteKeyAndCert()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
)
|
||||
|
||||
const (
|
||||
KeysDir = "./keys/"
|
||||
TLSCertName = KeysDir + "tls.crt"
|
||||
TLSKeyName = KeysDir + "tls.key"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
CertPemBytes []byte
|
||||
KeyPemBytes []byte
|
||||
TLSConfig tls.Config
|
||||
}
|
||||
|
||||
func (a *App) Init() error {
|
||||
return a.generateKeyAndCert()
|
||||
}
|
||||
|
||||
func (a *App) generateKeyAndCert() error {
|
||||
crtWriter := bytes.NewBuffer([]byte{})
|
||||
keyWriter := bytes.NewBuffer([]byte{})
|
||||
|
||||
err := GenerateKeyAndCert(crtWriter, keyWriter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.KeyPemBytes = keyWriter.Bytes()
|
||||
a.CertPemBytes = crtWriter.Bytes()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) MakeTLS() error {
|
||||
cert, err := tls.X509KeyPair(a.CertPemBytes, a.KeyPemBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.TLSConfig = tls.Config{Certificates: []tls.Certificate{cert}, Rand: rand.Reader}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
mrand "math/rand"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/schollz/peerdiscovery"
|
||||
)
|
||||
|
||||
func TestPeerDiscovery(t *testing.T) {
|
||||
//wg := new(sync.WaitGroup)
|
||||
|
||||
for x:=0;x<10;x++{
|
||||
t.Logf("attempting discovery %d", x+1)
|
||||
ds, err := peerdiscovery.Discover(peerdiscovery.Settings{Limit: 1})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
//t.Logf("Read peer list of %s", "peer 1")
|
||||
for _, d := range ds {
|
||||
fmt.Printf("discovered '%s'\n", d.Address)
|
||||
}
|
||||
}
|
||||
|
||||
/*wg.Add(1)
|
||||
go peerDiscovery(t, "peer 1", wg)
|
||||
|
||||
wg.Add(1)
|
||||
go peerDiscovery(t, "peer 2", wg)
|
||||
*/
|
||||
|
||||
//wg.Wait()
|
||||
}
|
||||
|
||||
func peerDiscovery(t *testing.T, name string, wg *sync.WaitGroup) {
|
||||
t.Logf("Begin discovery %s", name)
|
||||
ds, err := peerdiscovery.Discover(peerdiscovery.Settings{Limit: 1})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
t.Logf("Read peer list of %s", name)
|
||||
for _, d := range ds {
|
||||
fmt.Printf("discovered '%s'\n", d.Address)
|
||||
}
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
func TestAnother(t *testing.T) {
|
||||
fmt.Println("Scanning for 10 seconds to find LAN peers")
|
||||
pl := randStringBytesMaskImprSrc(10)
|
||||
fmt.Printf("Payload sending : '%s'\n", pl)
|
||||
|
||||
// discover peers
|
||||
discoveries, err := peerdiscovery.Discover(peerdiscovery.Settings{
|
||||
Limit: -1,
|
||||
Payload: []byte(pl),
|
||||
Delay: 500 * time.Millisecond,
|
||||
TimeLimit: 10 * time.Second,
|
||||
Notify: func(d peerdiscovery.Discovered) {
|
||||
log.Println(d)
|
||||
},
|
||||
})
|
||||
|
||||
// print out results
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
} else {
|
||||
if len(discoveries) > 0 {
|
||||
fmt.Printf("Found %d other computers\n", len(discoveries))
|
||||
for i, d := range discoveries {
|
||||
fmt.Printf("%d) '%s' with payload '%s'\n", i, d.Address, d.Payload)
|
||||
}
|
||||
} else {
|
||||
fmt.Println("Found no devices. You need to run this on another computer at the same time.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// src is seeds the random generator for generating random strings
|
||||
var src = mrand.NewSource(time.Now().UnixNano())
|
||||
|
||||
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
const (
|
||||
letterIdxBits = 6 // 6 bits to represent a letter index
|
||||
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
|
||||
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
|
||||
)
|
||||
|
||||
// RandStringBytesMaskImprSrc prints a random string
|
||||
func randStringBytesMaskImprSrc(n int) string {
|
||||
b := make([]byte, n)
|
||||
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
|
||||
for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
|
||||
if remain == 0 {
|
||||
cache, remain = src.Int63(), letterIdxMax
|
||||
}
|
||||
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
|
||||
b[i] = letterBytes[idx]
|
||||
i--
|
||||
}
|
||||
cache >>= letterIdxBits
|
||||
remain--
|
||||
}
|
||||
|
||||
return string(b)
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-zeromq/zmq4"
|
||||
)
|
||||
|
||||
func zmq4Req() {
|
||||
logger := log.New(log.Writer(), "rrclient: ", log.LstdFlags)
|
||||
|
||||
req := zmq4.NewReq(context.Background())
|
||||
defer req.Close()
|
||||
|
||||
err := req.Dial("tcp://localhost:5559")
|
||||
if err != nil {
|
||||
logger.Fatalf("could not dial: %v", err)
|
||||
}
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
err := req.Send(zmq4.NewMsgString("Hello"))
|
||||
if err != nil {
|
||||
logger.Fatalf("could not send greeting: %v", err)
|
||||
}
|
||||
|
||||
msg, err := req.Recv()
|
||||
if err != nil {
|
||||
logger.Fatalf("could not recv greeting: %v", err)
|
||||
}
|
||||
logger.Printf("received reply %d [%s]\n", i, msg.Frames[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestZMQ4Req(t *testing.T) {
|
||||
zmq4Req()
|
||||
}
|
||||
|
||||
func zmq4Rep() {
|
||||
logger := log.New(log.Writer(), "rrworker: ", log.LstdFlags)
|
||||
|
||||
// Socket to talk to clients
|
||||
rep := zmq4.NewRep(context.Background())
|
||||
defer rep.Close()
|
||||
|
||||
err := rep.Listen("tcp://*:5559")
|
||||
if err != nil {
|
||||
logger.Fatalf("could not dial: %v", err)
|
||||
}
|
||||
|
||||
for {
|
||||
// Wait for next request from client
|
||||
msg, err := rep.Recv()
|
||||
if err != nil {
|
||||
logger.Fatalf("could not recv request: %v", err)
|
||||
}
|
||||
|
||||
logger.Printf("received request: [%s]\n", msg.Frames[0])
|
||||
|
||||
// Do some 'work'
|
||||
time.Sleep(time.Second)
|
||||
|
||||
// Send reply back to client
|
||||
err = rep.Send(zmq4.NewMsgString("World"))
|
||||
if err != nil {
|
||||
logger.Fatalf("could not send reply: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestZMQ4Rep(t *testing.T) {
|
||||
zmq4Rep()
|
||||
}
|
||||
|
||||
func TestZMQ4ReqRep(t *testing.T){
|
||||
go zmq4Rep()
|
||||
go zmq4Req()
|
||||
|
||||
time.Sleep(15 * time.Second)
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/go-zeromq/zyre"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestZyre(t *testing.T) {
|
||||
z1, cncl1 := makeNode()
|
||||
defer cncl1()
|
||||
|
||||
z2, cncl2 := makeNode()
|
||||
defer cncl2()
|
||||
|
||||
z1.SetVerbose()
|
||||
z2.SetVerbose()
|
||||
|
||||
err := z1.Start()
|
||||
if err != nil {
|
||||
spew.Dump(err)
|
||||
}
|
||||
|
||||
defer z1.Stop()
|
||||
|
||||
err = z2.Start()
|
||||
if err != nil {
|
||||
spew.Dump(err)
|
||||
}
|
||||
|
||||
defer z2.Stop()
|
||||
|
||||
wg := new(sync.WaitGroup)
|
||||
//wg.Add(1)
|
||||
go watchEvents(t, wg, z1)
|
||||
//wg.Add(1)
|
||||
go watchEvents(t, wg, z2)
|
||||
|
||||
z1.Join("TALK")
|
||||
z2.Join("TALK")
|
||||
|
||||
time.Sleep(time.Second)
|
||||
z1.Shout("TALK", []byte("I am here"))
|
||||
time.Sleep(time.Second)
|
||||
z1.Shout("TALK", []byte("Hi world"))
|
||||
|
||||
//wg.Wait()
|
||||
time.Sleep(time.Second)
|
||||
|
||||
spew.Dump(z1.Peers(), z2.Peers())
|
||||
}
|
||||
|
||||
func makeNode() (*zyre.Zyre, context.CancelFunc) {
|
||||
ctx, cncl := context.WithCancel(context.Background())
|
||||
z := zyre.NewZyre(ctx)
|
||||
|
||||
return z, cncl
|
||||
}
|
||||
|
||||
func watchEvents(t *testing.T, wg *sync.WaitGroup, z *zyre.Zyre) {
|
||||
select {
|
||||
case e := <- z.Events():
|
||||
t.Log(spew.Sdump(e))
|
||||
if string(e.Msg) == "Hi world" {
|
||||
//wg.Done()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package main
|
||||
|
||||
import "github.com/status-im/tcp-pair-sync-prototype/app"
|
||||
|
||||
func main() {
|
||||
a := new(app.App)
|
||||
err := a.Init()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright 2020 The go-zeromq Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/go-zeromq/zyre"
|
||||
)
|
||||
|
||||
func chat(ctx context.Context, input <-chan string, name string) {
|
||||
node := zyre.NewZyre(ctx)
|
||||
defer node.Stop()
|
||||
|
||||
err := node.Start()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
node.Join("CHAT")
|
||||
|
||||
for {
|
||||
select {
|
||||
case e := <-node.Events():
|
||||
fmt.Printf("\r%s%s> ", string(e.Msg), name)
|
||||
case msg := <-input:
|
||||
node.Shout("CHAT", []byte(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
input := make(chan string)
|
||||
name := flag.String("name", "Zyre", "Your name in the chat session")
|
||||
flag.Parse()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
go chat(ctx, input, *name)
|
||||
fmt.Printf("%s> ", *name)
|
||||
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
input <- fmt.Sprintf("%s: %s\n", *name, scanner.Text())
|
||||
fmt.Printf("%s> ", *name)
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
log.Fatalln("reading standard input:", err)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue