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