Commit aea1e178 authored by ale's avatar ale
Browse files

implement the local RPC API

parent 21892b5e
package tlswatch
import (
"net"
"net/rpc"
"flag"
"log"
)
var (
socketPath = flag.String("socket", "/var/lib/tlswatch/sock", "Control socket")
)
// All we need, really, is access to the database.
type PolicyWatcherRpc struct {
db Database
}
type ListConflictsReq struct {}
type ListConflictsResp struct {
Conflicts []Conflict
}
func (pwr *PolicyWatcherRpc) ListConflicts(req ListConflictsReq, resp *ListConflictsResp) error {
session := pwr.db.Session()
defer session.Close()
iter, err := session.Scan(conflictsTable, "", "Z")
if err != nil {
return err
}
defer iter.Close()
conflicts := make([]Conflict, 0)
for iter.Next() {
var c Conflict
iter.Value(&c)
conflicts = append(conflicts, c)
}
resp.Conflicts = conflicts
return nil
}
type ResolveConflictReq struct {
Domain string
}
type ResolveConflictResp struct {}
func (pwr *PolicyWatcherRpc) ResolveConflict(req ResolveConflictReq, resp *ResolveConflictResp) error {
session := pwr.db.Session()
defer session.Close()
session.Del(conflictsTable, req.Domain)
return nil
}
// Run the local RPC server.
func RunRpcServer(pw *PolicyWatcherRpc) {
rpc.RegisterName("PolicyWatcher", pw)
l, err := net.Listen("unix", *socketPath)
if err != nil {
log.Fatal(err)
}
go rpc.Accept(l)
}
// Client for the RPC interface.
type PolicyWatcherClient struct {
DbOpen func() Database
}
type fallbackFunc func(fakeServer *PolicyWatcherRpc) error
// Invoke a remote method if the server is available, otherwise create
// a local 'fake' server, and invoke the desired method directly. This
// is useful for database access, where we want to support an 'online'
// mode (with the daemon running) and an 'offline' one. If this is not
// an option, caller should set fallback to 'nil'.
func (pwc *PolicyWatcherClient) do(method string, req, resp interface{}, fallback fallbackFunc) error {
if client, err := rpc.Dial("unix", *socketPath); err == nil {
defer client.Close()
return client.Call(method, req, resp)
} else if fallback != nil {
log.Printf("Warning: could not connect to running tlswatch daemon (%s), accessing database directly!", err)
db := pwc.DbOpen()
defer db.Close()
return fallback(&PolicyWatcherRpc{db})
} else {
return err
}
// Unreached.
return nil
}
func (pwc *PolicyWatcherClient) ListConflicts() ([]Conflict, error) {
var resp ListConflictsResp
err := pwc.do("PolicyWatcher.ListConflicts", ListConflictsReq{}, &resp, func(fakeServer *PolicyWatcherRpc) error {
return fakeServer.ListConflicts(ListConflictsReq{}, &resp)
})
if err != nil {
return nil, err
}
return resp.Conflicts, nil
}
func (pwc *PolicyWatcherClient) ResolveConflict(domain string) error {
req := ResolveConflictReq{domain}
var resp ResolveConflictResp
err := pwc.do("PolicyWatcher.ResolveConflict", req, &resp, func(fakeServer *PolicyWatcherRpc) error {
return fakeServer.ResolveConflict(req, &resp)
})
return err
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment