Release v0.1.0

This commit is contained in:
Manu Herrera
2019-10-01 12:22:30 -03:00
parent 41e6aad190
commit d301c63596
915 changed files with 378049 additions and 11 deletions

21
vendor/github.com/lightninglabs/gozmq/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016 Timothy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

29
vendor/github.com/lightninglabs/gozmq/README.md generated vendored Normal file
View File

@@ -0,0 +1,29 @@
# gozmq
GoZMQ is a pure Go ZMQ pubsub client implementation.
Only a very limited subset of ZMQ is implemented: NULL security, SUB socket.
## Usage
Please visit https://godoc.org/github.com/tstranex/gozmq for the full
documentation.
## Installation
To install, run:
```
go get github.com/tstranex/gozmq
```
## Example
See example/main.go for a full example.
```go
c, err := gozmq.Subscribe("127.0.0.1:1234", []string{""})
for {
msg, err := c.Receive()
// Process message
}
```

3
vendor/github.com/lightninglabs/gozmq/go.mod generated vendored Normal file
View File

@@ -0,0 +1,3 @@
module github.com/lightninglabs/gozmq
go 1.12

462
vendor/github.com/lightninglabs/gozmq/zmq.go generated vendored Normal file
View File

@@ -0,0 +1,462 @@
// Package gozmq provides a ZMQ pubsub client.
//
// It implements the protocol described here:
// http://rfc.zeromq.org/spec:23/ZMTP/
package gozmq
import (
"errors"
"fmt"
"io"
"net"
"os"
"regexp"
"strings"
"sync"
"time"
)
var (
// MaxBodySize is the maximum frame size we're willing to accept.
// The maximum size of a Bitcoin message is 32MiB.
MaxBodySize uint64 = 0x02000000
)
// reconnectError wraps any error with a timeout, which allows clients to keep
// attempting to read normally while the underlying socket attempts to
// reconnect.
type reconnectError struct {
error
}
// Timeout implements the timeout interface from net and other packages.
func (e *reconnectError) Timeout() bool {
return true
}
func connFromAddr(addr string) (net.Conn, error) {
re, err := regexp.Compile(`((tcp|unix|ipc)://)?([^:]*):?(\d*)`)
if err != nil {
return nil, err
}
submatch := re.FindStringSubmatch(addr)
if addrs, err := net.LookupIP(submatch[3]); (err == nil &&
len(addrs) > 0) || submatch[2] == "tcp" ||
net.ParseIP(submatch[3]) != nil || submatch[4] != "" {
// We have a TCP address.
return net.DialTimeout("tcp", strings.Replace(submatch[3], "*",
"", 1)+":"+submatch[4], time.Minute)
} else if _, err := os.Stat(submatch[3]); err == nil ||
submatch[2] == "unix" || submatch[2] == "ipc" {
// We have a UNIX socket.
return net.DialTimeout("unix", submatch[3], time.Minute)
}
return nil, fmt.Errorf("couldn't resolve address %s", addr)
}
// Conn is a connection to a ZMQ server.
type Conn struct {
conn net.Conn
topics []string
timeout time.Duration
closeConn sync.Once
quit chan struct{}
}
func (c *Conn) writeAll(buf []byte) error {
written := 0
for written < len(buf) {
n, err := c.conn.Write(buf[written:])
if err != nil {
return err
}
written += n
}
return nil
}
func (c *Conn) writeGreeting() error {
signature := []byte{0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0x7f}
version := []byte{3, 0}
mechanism := make([]byte, 20)
for i, chr := range "NULL" {
mechanism[i] = byte(chr)
}
server := []byte{0}
var greeting []byte
greeting = append(greeting, signature...)
greeting = append(greeting, version...)
greeting = append(greeting, mechanism...)
greeting = append(greeting, server...)
for len(greeting) < 64 {
greeting = append(greeting, 0)
}
return c.writeAll(greeting)
}
func (c *Conn) readGreeting() error {
greet := make([]byte, 64)
if _, err := io.ReadFull(c.conn, greet); err != nil {
return err
}
if greet[0] != 0xff || greet[9] != 0x7f {
return errors.New("invalid signature")
}
if greet[10] < 3 {
return errors.New("peer version is too old")
}
if string(greet[12:17]) != "NULL\x00" {
return errors.New("unsupported security mechanism")
}
if greet[32] != 0 {
return errors.New("as-server must be zero for NULL")
}
return nil
}
func (c *Conn) writeFrame(flag byte, buf []byte) error {
if flag&0xf8 != 0 {
return errors.New("invalid flag")
}
if flag&2 != 0 {
return errors.New("caller must not specify long frame flag")
}
var header []byte
if len(buf) > 255 {
flag = flag | 2
header = []byte{flag, 0, 0, 0, 0, 0, 0, 0, 0}
size := len(buf)
i := len(header) - 1
for size > 0 {
header[i] = byte(size & 0xff)
size = size >> 8
i--
}
} else {
header = []byte{flag, byte(len(buf))}
}
if err := c.writeAll(header); err != nil {
return err
}
return c.writeAll(buf)
}
func (c *Conn) writeCommand(name string, data []byte) error {
size := len(name)
if size > 255 {
return errors.New("command name is too long")
}
body := append([]byte{byte(size)}, []byte(name)...)
buf := append(body, data...)
var flag byte = 4
return c.writeFrame(flag, buf)
}
func (c *Conn) writeReady(socketType string) error {
if len(socketType) > 255 {
return errors.New("socket type too long")
}
const socketTypeName = "Socket-Type"
metadata := []byte{byte(len(socketTypeName))}
metadata = append(metadata, []byte(socketTypeName)...)
metadata = append(metadata, []byte{0, 0, 0, byte(len(socketType))}...)
metadata = append(metadata, []byte(socketType)...)
return c.writeCommand(commandReady, metadata)
}
func (c *Conn) writeMessage(parts [][]byte) error {
if len(parts) == 0 {
return errors.New("empty message")
}
for _, msg := range parts[:len(parts)-1] {
if err := c.writeFrame(1, msg); err != nil {
return err
}
}
return c.writeFrame(0, parts[len(parts)-1])
}
func (c *Conn) subscribe(prefix string) error {
msg := append([]byte{1}, []byte(prefix)...)
return c.writeMessage([][]byte{msg})
}
func (c *Conn) readCommand() (string, []byte, error) {
flag, buf, err := c.readFrame(true)
if err != nil {
return "", nil, err
}
if flag&4 != 4 {
return "", nil, errors.New("expected command frame")
}
if len(buf) < 1 {
return "", nil, errors.New("empty command buffer")
}
size := int(buf[0])
buf = buf[1:]
if size > len(buf) {
return "", nil, errors.New("invalid command name size")
}
name := string(buf[:size])
data := buf[size:]
return name, data, nil
}
const commandReady = "READY"
func (c *Conn) readReady() error {
name, metadata, err := c.readCommand()
if err != nil {
return err
}
if name != commandReady {
return errors.New("expected ready command")
}
m := make(map[string]string)
for len(metadata) > 0 {
size := int(metadata[0])
metadata = metadata[1:]
if size > len(metadata) {
return errors.New("invalid metadata")
}
name := metadata[:size]
metadata = metadata[size:]
if len(metadata) < 4 {
return errors.New("invalid metadata")
}
var valueSize uint32
for i := 0; i < 4; i++ {
valueSize = valueSize<<8 + uint32(metadata[i])
}
metadata = metadata[4:]
if int(valueSize) > len(metadata) {
return errors.New("invalid metadata")
}
value := metadata[:valueSize]
metadata = metadata[valueSize:]
m[string(name)] = string(value)
}
return nil
}
// Read a frame from the socket, setting deadline before each read to prevent
// timeouts during or between frames. The initialFrame should be used to denote
// whether this is the first frame we'll read for a _new_ message.
//
// NOTE: This is a blocking call if there is nothing to read from the
// connection.
func (c *Conn) readFrame(initialFrame bool) (byte, []byte, error) {
// We'll only set a read deadline if this is not the first frame of a
// message. We do this to ensure we receive complete messages in a
// timely manner.
if !initialFrame {
c.conn.SetReadDeadline(time.Now().Add(c.timeout))
}
var flagBuf [1]byte
if _, err := io.ReadFull(c.conn, flagBuf[:1]); err != nil {
return 0, nil, err
}
flag := flagBuf[0]
if flag&0xf8 != 0 {
return 0, nil, errors.New("invalid flag")
}
var size uint64
if flag&2 == 2 {
// Long form
var buf [8]byte
c.conn.SetReadDeadline(time.Now().Add(c.timeout))
if _, err := io.ReadFull(c.conn, buf[:8]); err != nil {
return 0, nil, err
}
for _, b := range buf {
size = (size << 8) | uint64(b)
}
} else {
// Short form
var buf [1]byte
c.conn.SetReadDeadline(time.Now().Add(c.timeout))
if _, err := io.ReadFull(c.conn, buf[:1]); err != nil {
return 0, nil, err
}
size = uint64(buf[0])
}
if size > MaxBodySize {
return 0, nil, errors.New("frame too large")
}
buf := make([]byte, size)
// Prevent timeout during large data read in case of slow connection.
c.conn.SetReadDeadline(time.Time{})
if _, err := io.ReadFull(c.conn, buf); err != nil {
return 0, nil, err
}
return flag, buf, nil
}
// readMessage reads a new message from the connection.
//
// NOTE: This is a blocking call if there is nothing to read from the
// connection.
func (c *Conn) readMessage() ([][]byte, error) {
// We'll only set read deadlines on the underlying connection when
// reading messages of multiple frames after the first frame has been
// read. This is done to ensure we receive all of the frames of a
// message within a reasonable time frame. When reading the first frame,
// we want to avoid setting them as we don't know when a new message
// will be available for us to read.
initialFrame := true
var parts [][]byte
for {
flag, buf, err := c.readFrame(initialFrame)
if err != nil {
return nil, err
}
if flag&4 != 0 {
return nil, errors.New("expected message frame")
}
parts = append(parts, buf)
if flag&1 == 0 {
break
}
if len(parts) > 16 {
return nil, errors.New("message has too many parts")
}
initialFrame = false
}
return parts, nil
}
// Subscribe connects to a publisher server and subscribes to the given topics.
func Subscribe(addr string, topics []string, timeout time.Duration) (*Conn, error) {
conn, err := connFromAddr(addr)
if err != nil {
return nil, err
}
conn.SetDeadline(time.Now().Add(10 * time.Second))
c := &Conn{
conn: conn,
topics: topics,
timeout: timeout,
quit: make(chan struct{}),
}
if err := c.writeGreeting(); err != nil {
conn.Close()
return nil, err
}
if err := c.readGreeting(); err != nil {
conn.Close()
return nil, err
}
if err := c.writeReady("SUB"); err != nil {
conn.Close()
return nil, err
}
if err := c.readReady(); err != nil {
conn.Close()
return nil, err
}
for _, topic := range topics {
if err := c.subscribe(topic); err != nil {
conn.Close()
return nil, err
}
}
conn.SetDeadline(time.Time{})
return c, nil
}
// Receive a message from the publisher. It blocks until a new message is
// received. If the connection times out and it was not explicitly terminated,
// then a timeout error is returned. Otherwise, if it was explicitly terminated,
// then io.EOF is returned.
func (c *Conn) Receive() ([][]byte, error) {
messages, err := c.readMessage()
// If the error is either nil or a non-EOF error, we return it as-is.
if err != io.EOF {
return messages, err
}
// We got an EOF, so our socket is disconnected. If the connection was
// explicitly terminated, we'll return the EOF error.
select {
case <-c.quit:
return nil, io.EOF
default:
}
// Otherwise, we'll attempt to reconnect. If successful, we'll replace
// the existing connection with the new one. Either way, return a
// timeout error.
errTimeout := &net.OpError{
Op: "read",
Net: c.conn.LocalAddr().Network(),
Source: c.conn.LocalAddr(),
Addr: c.conn.RemoteAddr(),
Err: &reconnectError{err},
}
newConn, err := Subscribe(
c.conn.RemoteAddr().String(), c.topics, c.timeout,
)
if err != nil {
// Prevent CPU overuse by refused reconnection attempts.
time.Sleep(c.timeout)
} else {
c.conn.Close()
c.conn = newConn.conn
}
return nil, errTimeout
}
// Close the underlying connection. Any further operations will fail.
func (c *Conn) Close() error {
var err error
c.closeConn.Do(func() {
close(c.quit)
err = c.conn.Close()
})
return err
}
// RemoteAddr returns the remote network address.
func (c *Conn) RemoteAddr() net.Addr {
return c.conn.RemoteAddr()
}