shithub: mycel

ref: 5286f0a7643e5105f6b243081adc172b641c5caa
dir: /browser/fs/fs.go/

View raw version
package fs

import (
	"bufio"
	"encoding/json"
	"fmt"
	"github.com/knusbaum/go9p/fs"
	"github.com/knusbaum/go9p/proto"
	"github.com/psilva261/opossum"
	"github.com/psilva261/opossum/logger"
	"github.com/psilva261/opossum/nodes"
	"net"
	"os/user"
	"strings"
	"sync"
)

var (
	log *logger.Logger
	mu sync.RWMutex
	oFS *fs.FS
	un string
	gn string
	cssDir *fs.StaticDir
	jsDir *fs.StaticDir
	html string
	DOM Queryable
)

type Queryable interface {
	Query(q string) ([]*nodes.Node, error)
}

func SetLogger(l *logger.Logger) {
	log = l
}

func init() {
	var root *fs.StaticDir

	u, err := user.Current()
	if err != nil {
		log.Errorf("get user: %v", err)
		return
	}
	un = u.Username
	gn, err = opossum.Group(u)
	if err != nil {
		log.Errorf("get group: %v", err)
		return
	}
	oFS, root = fs.NewFS(un, gn, 0500)
	h := fs.NewDynamicFile(
		oFS.NewStat("html", un, gn, 0400),
		func() []byte {
			mu.RLock()
			defer mu.RUnlock()

			return []byte(html)
		},
	)
	root.AddChild(h)
	d, err := fs.CreateStaticDir(oFS, root, un, "css", 0500|proto.DMDIR, 0)
	if err != nil {
		log.Errorf("create static dir: %v", err)
		return
	}
	cssDir = d.(*fs.StaticDir)
	root.AddChild(cssDir)
	d, err = fs.CreateStaticDir(oFS, root, un, "js", 0500|proto.DMDIR, 0)
	if err != nil {
		log.Errorf("create static dir: %v", err)
		return
	}
	jsDir = d.(*fs.StaticDir)
	root.AddChild(jsDir)
	q := fs.NewListenFile(oFS.NewStat("query", un, gn, 0600))
	root.AddChild(q)
	lq := (*fs.ListenFileListener)(q)
	go Query(lq)
}

func Query(lq *fs.ListenFileListener) {
	for {
		conn, err := lq.Accept()
		if err != nil {
			log.Errorf("accept: %v", err)
			continue
		}
		go query(conn)
	}
}

func query(conn net.Conn) {
	r := bufio.NewReader(conn)
	enc := json.NewEncoder(conn)
	defer conn.Close()

	l, err := r.ReadString('\n')
	if err != nil {
		log.Errorf("read string: %v", err)
		return
	}
	l = strings.TrimSpace(l)

	if DOM == nil {
		return
	}
	nodes, err := DOM.Query(l)
	if err != nil {
		log.Errorf("query nodes: %v", err)
		return
	}
	if err := enc.Encode(nodes); err != nil {
		log.Errorf("encode: %v", err)
		return
	}
}

func Update(htm string, css []string, js []string) {
	mu.Lock()
	defer mu.Unlock()

	html = htm
	for name := range cssDir.Children() {
		cssDir.DeleteChild(name)
	}
	for i, s := range css {
		fn := fmt.Sprintf("%d.css", i)
		f := fs.NewStaticFile(
			oFS.NewStat(fn, un, gn, 0400),
			[]byte(s),
		)
		cssDir.AddChild(f)
	}
	for name := range jsDir.Children() {
		jsDir.DeleteChild(name)
	}
	for i, s := range js {
		fn := fmt.Sprintf("%d.js", i)
		f := fs.NewStaticFile(
			oFS.NewStat(fn, un, gn, 0400),
			[]byte(s),
		)
		jsDir.AddChild(f)
	}
}

func Srv9p() {
	if err := post(oFS.Server()); err != nil {
		log.Errorf("srv9p: %v", err)
	}
}