110 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			110 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package rep
 | 
						|
 | 
						|
import (
 | 
						|
	"encoding/json"
 | 
						|
	"net"
 | 
						|
	"net/http"
 | 
						|
	"strings"
 | 
						|
	"sync"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"git.crumpington.com/public/jldb/lib/errs"
 | 
						|
	"git.crumpington.com/public/jldb/lib/httpconn"
 | 
						|
	"git.crumpington.com/public/jldb/lib/wal"
 | 
						|
)
 | 
						|
 | 
						|
type client struct {
 | 
						|
	client *http.Client
 | 
						|
 | 
						|
	// The following are constant.
 | 
						|
	endpoint string
 | 
						|
	pskBytes [64]byte
 | 
						|
	timeout  time.Duration
 | 
						|
 | 
						|
	lock sync.Mutex
 | 
						|
	conn net.Conn
 | 
						|
}
 | 
						|
 | 
						|
func newClient(endpoint, psk string, timeout time.Duration) *client {
 | 
						|
	httpClient := &http.Client{
 | 
						|
		Timeout: timeout,
 | 
						|
	}
 | 
						|
 | 
						|
	if !strings.HasSuffix(endpoint, "/") {
 | 
						|
		endpoint += "/"
 | 
						|
	}
 | 
						|
 | 
						|
	return &client{
 | 
						|
		client:   httpClient,
 | 
						|
		endpoint: endpoint,
 | 
						|
		pskBytes: pskToBytes(psk),
 | 
						|
		timeout:  timeout,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (c *client) GetInfo() (info Info, err error) {
 | 
						|
	req, err := http.NewRequest(http.MethodGet, c.endpoint+pathGetInfo, nil)
 | 
						|
	if err != nil {
 | 
						|
		return info, errs.Unexpected.WithErr(err)
 | 
						|
	}
 | 
						|
	req.SetBasicAuth("", string(c.pskBytes[:]))
 | 
						|
 | 
						|
	resp, err := c.client.Do(req)
 | 
						|
	if err != nil {
 | 
						|
		return info, errs.IO.WithErr(err)
 | 
						|
	}
 | 
						|
	defer resp.Body.Close()
 | 
						|
 | 
						|
	if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
 | 
						|
		return info, errs.IO.WithErr(err)
 | 
						|
	}
 | 
						|
	return info, nil
 | 
						|
}
 | 
						|
 | 
						|
func (c *client) RecvState(recv func(net.Conn) error) error {
 | 
						|
	err := c.dialConnect(c.endpoint + pathSendState)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	defer c.conn.Close()
 | 
						|
 | 
						|
	return recv(c.conn)
 | 
						|
}
 | 
						|
 | 
						|
func (c *client) StreamWAL(w *wal.WAL) error {
 | 
						|
	err := c.dialConnect(c.endpoint + pathStreamWAL)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	defer c.conn.Close()
 | 
						|
 | 
						|
	return w.Recv(c.conn, c.timeout)
 | 
						|
}
 | 
						|
 | 
						|
func (c *client) Close() {
 | 
						|
	c.lock.Lock()
 | 
						|
	defer c.lock.Unlock()
 | 
						|
	if c.conn != nil {
 | 
						|
		c.conn.Close()
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// ----------------------------------------------------------------------------
 | 
						|
 | 
						|
func (c *client) dialConnect(endpoint string) error {
 | 
						|
	conn, err := httpconn.Dial(endpoint)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	conn.SetWriteDeadline(time.Now().Add(c.timeout))
 | 
						|
	if _, err := conn.Write(c.pskBytes[:]); err != nil {
 | 
						|
		return errs.IO.WithErr(err)
 | 
						|
	}
 | 
						|
 | 
						|
	c.lock.Lock()
 | 
						|
	defer c.lock.Unlock()
 | 
						|
	c.conn = conn
 | 
						|
	return nil
 | 
						|
}
 |