blob: ac95da25ff46dba8e2453c5b0bed070d30d8c76a [file] [log] [blame]
package impl
import (
"crypto/md5"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"veyron2/ipc"
"veyron2/security"
"veyron2/services/mgmt/repository"
)
const (
VersionFile = "VERSION"
Version = "1.0"
)
// dispatcher holds the state of the binary repository dispatcher.
type dispatcher struct {
auth security.Authorizer
state *state
}
// newDispatcher is the dispatcher factory.
func NewDispatcher(root string, depth int, authorizer security.Authorizer) (*dispatcher, error) {
if min, max := 0, md5.Size-1; min > depth || depth > max {
return nil, fmt.Errorf("Unexpected depth, expected a value between %v and %v, got %v", min, max, depth)
}
if _, err := os.Stat(root); err != nil {
return nil, fmt.Errorf("Stat(%v) failed: %v", root, err)
}
path := filepath.Join(root, VersionFile)
output, err := ioutil.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("ReadFile(%v) failed: %v", path, err)
}
if expected, got := Version, strings.TrimSpace(string(output)); expected != got {
return nil, fmt.Errorf("Unexpected version: expected %v, got %v", expected, got)
}
return &dispatcher{
auth: authorizer,
state: &state{
depth: depth,
root: root,
},
}, nil
}
// DISPATCHER INTERFACE IMPLEMENTATION
func (d *dispatcher) Lookup(suffix string) (ipc.Invoker, security.Authorizer, error) {
invoker := ipc.ReflectInvoker(repository.NewServerBinary(newInvoker(d.state, suffix)))
return invoker, d.auth, nil
}