Skip to content

Instantly share code, notes, and snippets.

@nf
Last active May 17, 2017 21:47
Show Gist options
  • Save nf/d9aed75ca58f1105c57c1f7275652227 to your computer and use it in GitHub Desktop.
Save nf/d9aed75ca58f1105c57c1f7275652227 to your computer and use it in GitHub Desktop.
skeleton upspin server
package main
import (
"fmt"
"net/http"
"upspin.io/access"
"upspin.io/cloud/https"
"upspin.io/config"
"upspin.io/errors"
"upspin.io/flags"
"upspin.io/log"
"upspin.io/pack"
"upspin.io/path"
"upspin.io/rpc/dirserver"
"upspin.io/rpc/storeserver"
"upspin.io/serverutil"
"upspin.io/upspin"
_ "upspin.io/key/transports"
_ "upspin.io/pack/eeintegrity"
)
func main() {
flags.Parse(flags.Server)
cfg, err := config.FromFile(flags.Config)
if err != nil {
log.Fatal(err)
}
addr := upspin.NetAddr(flags.NetAddr)
ep := upspin.Endpoint{
Transport: upspin.Remote,
NetAddr: addr,
}
s, err := newServer(cfg, ep)
if err != nil {
log.Fatal(err)
}
http.Handle("/api/Store/", storeserver.New(cfg, s.StoreServer(), addr))
http.Handle("/api/Dir/", dirserver.New(cfg, s.DirServer(), addr))
https.ListenAndServeFromFlags(nil)
}
const accessRef = upspin.Reference(access.AccessFile)
var accessRefdata = upspin.Refdata{Reference: accessRef}
var errNotImplemented = errors.Str("not implemented")
type server struct {
cfg upspin.Config
ep upspin.Endpoint
accessEntry *upspin.DirEntry
accessBytes []byte
}
func newServer(cfg upspin.Config, ep upspin.Endpoint) (*server, error) {
s := &server{
cfg: cfg,
ep: ep,
}
rootAccess := []byte(fmt.Sprintf("Read: %s\nList,Create: all\n", cfg.UserName()))
var err error
s.accessEntry, s.accessBytes, err = s.pack(access.AccessFile, rootAccess)
if err != nil {
return nil, err
}
return s, nil
}
const packing = upspin.EEIntegrityPack
func (s *server) pack(filePath string, data []byte) (*upspin.DirEntry, []byte, error) {
name := upspin.PathName(s.cfg.UserName()) + "/" + upspin.PathName(filePath)
de := &upspin.DirEntry{
Writer: s.cfg.UserName(),
Name: name,
SignedName: name,
Packing: packing,
Time: upspin.Now(),
Sequence: 1,
}
bp, err := pack.Lookup(packing).Pack(s.cfg, de)
if err != nil {
return nil, nil, err
}
cipher, err := bp.Pack(data)
if err != nil {
return nil, nil, err
}
bp.SetLocation(upspin.Location{
Endpoint: s.ep,
Reference: upspin.Reference(filePath),
})
return de, cipher, bp.Close()
}
func (s *server) DirServer() upspin.DirServer { return dirServer{s} }
func (s *server) StoreServer() upspin.StoreServer { return storeServer{s} }
func (s *server) Endpoint() upspin.Endpoint { return s.ep }
func (s *server) Ping() bool { return true }
func (s *server) Close() {}
type dirServer struct {
*server
}
func (s dirServer) Dial(upspin.Config, upspin.Endpoint) (upspin.Service, error) {
return s, nil
}
func (s dirServer) Lookup(name upspin.PathName) (*upspin.DirEntry, error) {
p, err := path.Parse(name)
if err != nil {
return nil, err
}
if p.User() != s.cfg.UserName() {
return nil, errors.E(name, errors.NotExist)
}
fp := p.FilePath()
switch fp {
case "": // Root directory.
return &upspin.DirEntry{
Name: p.Path(),
SignedName: p.Path(),
Attr: upspin.AttrDirectory,
Time: upspin.Now(),
}, nil
case access.AccessFile:
return s.accessEntry, nil
}
return nil, errors.E(name, errors.Private)
}
func (s dirServer) Glob(pattern string) ([]*upspin.DirEntry, error) {
return serverutil.Glob(pattern, s.Lookup, s.listDir)
}
func (s dirServer) listDir(name upspin.PathName) ([]*upspin.DirEntry, error) {
p, err := path.Parse(name)
if err != nil {
return nil, err
}
if p.User() != s.cfg.UserName() || p.FilePath() != "" {
return nil, errors.E(name, errors.NotExist)
}
return []*upspin.DirEntry{
s.accessEntry,
}, nil
}
func (s dirServer) WhichAccess(name upspin.PathName) (*upspin.DirEntry, error) {
return s.accessEntry, nil
}
func (s dirServer) Put(entry *upspin.DirEntry) (*upspin.DirEntry, error) {
return nil, errNotImplemented
}
func (s dirServer) Delete(name upspin.PathName) (*upspin.DirEntry, error) {
return nil, errNotImplemented
}
func (s dirServer) Watch(name upspin.PathName, order int64, done <-chan struct{}) (<-chan upspin.Event, error) {
return nil, upspin.ErrNotSupported
}
type storeServer struct {
*server
}
func (s storeServer) Dial(upspin.Config, upspin.Endpoint) (upspin.Service, error) {
return s, nil
}
func (s storeServer) Get(ref upspin.Reference) ([]byte, *upspin.Refdata, []upspin.Location, error) {
if ref == accessRef {
return s.accessBytes, &accessRefdata, nil, nil
}
return nil, nil, nil, errors.E(errors.NotExist)
}
func (s storeServer) Put(data []byte) (*upspin.Refdata, error) {
return nil, errNotImplemented
}
func (s storeServer) Delete(ref upspin.Reference) error {
return errNotImplemented
}
users:
- name: user
- name: imageserver
dirserver: $imageserver
storeserver: $imageserver
servers:
- name: keyserver
- name: storeserver
- name: dirserver
- name: imageserver
importpath: upspin.io/exp/cmd/imageserver
domain: example.com
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment