Skip to content

Commit e7ecbe8

Browse files
committed
refact
0 parents  commit e7ecbe8

17 files changed

Lines changed: 546 additions & 0 deletions

.gitignore

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# If you prefer the allow list template instead of the deny list, see community template:
2+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3+
#
4+
# Binaries for programs and plugins
5+
*.exe
6+
*.exe~
7+
*.dll
8+
*.so
9+
*.dylib
10+
11+
# Test binary, built with `go test -c`
12+
*.test
13+
14+
# Output of the go coverage tool, specifically when used with LiteIDE
15+
*.out
16+
17+
# Dependency directories (remove the comment below to include it)
18+
# vendor/
19+
20+
# Go workspace file
21+
go.work
22+
23+
/lcode

LICENSE

Whitespace-only changes.

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# 简介
2+
3+
起因是某位朋友抱怨 vim 太难用了, 想在服务器上使用本地的 vscode 进行编辑,
4+
但 vscode remote ssh 太吃内存了, 简单编辑用 webdav 文件协议编辑也许可行?
5+
6+
也许会加上命令行支持?
7+
8+
# 进度
9+
10+
- [x] webdav
11+
- [ ] edit with local vscode
12+
13+
# 设计概述
14+
15+
```sh
16+
# open vscode for opening lcode plugin, lcode plugin will start server
17+
code
18+
ssh -R 4349:127.0.0.1:4349 root@your_host
19+
# defualt connect server addr is 127.0.0.1:4349
20+
lcode -c 127.0.0.1:4349
21+
# log vscode link, you can click the link to open vscode
22+
# if vscode lcode plugin is active will auto open
23+
-> vscode://lcode-plugin/uuid-key
24+
```

go.mod

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module github.com/shynome/lcode
2+
3+
go 1.18
4+
5+
require (
6+
github.com/shynome/httprelay-go v0.0.2
7+
golang.org/x/net v0.0.0-20210614182718-04defd469f4e
8+
)

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
github.com/shynome/httprelay-go v0.0.2 h1:Z+Zvh7w9OIeBluZTg7Ef52EImmu2XbkhdS7tvnxQ2Dk=
2+
github.com/shynome/httprelay-go v0.0.2/go.mod h1:CjDFSTBc/hqGTOfWZ6RmRKbIBzuD/qigX6AMYXZiLr0=
3+
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
4+
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=

init.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"os"
6+
"path/filepath"
7+
8+
"github.com/shynome/httprelay-go"
9+
"github.com/shynome/lcode/table"
10+
)
11+
12+
var LCODE_CONNECT string = "http://127.0.0.1:4349"
13+
14+
var db *table.Table
15+
16+
func init() {
17+
c := os.Getenv("LCODE_CONNECT")
18+
if c != "" {
19+
LCODE_CONNECT = c
20+
}
21+
22+
lcodeTmpdir := filepath.Join(os.TempDir(), "lcode-nuts")
23+
db = table.New(lcodeTmpdir)
24+
err := db.Open()
25+
if err != nil {
26+
panic(err)
27+
}
28+
}
29+
30+
func initProxy(proxy *httprelay.Proxy) {
31+
id, err := makeUniqueID()
32+
if err != nil {
33+
log.Fatal(err)
34+
}
35+
proxy.Auth.ID = id
36+
proxy.Auth.Secret = id
37+
if proxy.Parallel < 4 {
38+
proxy.Parallel = 4
39+
}
40+
proxy.Println = func(i ...interface{}) {}
41+
}

lcode.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"os"
7+
"os/signal"
8+
"path/filepath"
9+
10+
"github.com/shynome/httprelay-go"
11+
)
12+
13+
func main() {
14+
defer db.Dispose()
15+
16+
proxy := httprelay.NewProxy(LCODE_CONNECT)
17+
initProxy(proxy)
18+
initWebdav(http.DefaultServeMux)
19+
20+
pwd, _ := os.Getwd()
21+
var codedir = "."
22+
if len(os.Args) >= 2 {
23+
codedir = os.Args[1]
24+
}
25+
codedir = filepath.Join(pwd, codedir)
26+
27+
db.Allow(codedir)
28+
defer db.Deny(codedir)
29+
30+
vscodeLink := genVscodeLink(proxy.Auth.ID, codedir)
31+
32+
fmt.Println(vscodeLink)
33+
// go reqOpen(vscodeLink)
34+
go proxy.Serve(nil)
35+
36+
c := make(chan os.Signal, 1)
37+
signal.Notify(c, os.Interrupt)
38+
<-c
39+
}

lcode_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package main
2+
3+
import "testing"
4+
5+
func TestRunMain(t *testing.T) {
6+
main()
7+
}

table/lib_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package table_test
2+
3+
import (
4+
"os"
5+
"testing"
6+
"time"
7+
8+
"github.com/shynome/lcode/table"
9+
)
10+
11+
func TestTable(t *testing.T) {
12+
pwd, _ := os.Getwd()
13+
table := table.New(pwd)
14+
table.EmptyRulesFile()
15+
err := table.Open()
16+
if err != nil {
17+
t.Error(err)
18+
return
19+
}
20+
table.Allow("/a/b")
21+
time.Sleep(time.Second)
22+
if table.IsDeny("/a/b") {
23+
t.Error("should be allowed")
24+
}
25+
table.Deny("/a/b")
26+
time.Sleep(time.Second)
27+
if !table.IsDeny("/a/b") {
28+
t.Error("should be deny")
29+
}
30+
return
31+
}

table/table.go

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
package table
2+
3+
import (
4+
"bufio"
5+
"io"
6+
"io/fs"
7+
"os"
8+
"path/filepath"
9+
"strings"
10+
"sync"
11+
"time"
12+
)
13+
14+
type AllowedDirs map[string]bool
15+
16+
type Table struct {
17+
lock *sync.RWMutex
18+
allowedDirs AllowedDirs
19+
rulesFile string
20+
stopWatch chan bool
21+
}
22+
23+
func New(dir string) *Table {
24+
table := &Table{
25+
lock: &sync.RWMutex{},
26+
allowedDirs: AllowedDirs{},
27+
stopWatch: make(chan bool),
28+
rulesFile: filepath.Join(dir, "/allowed-dirs.table"),
29+
}
30+
return table
31+
}
32+
33+
func (t *Table) Open() (err error) {
34+
err = t.LoadTable()
35+
go t.Watch()
36+
return
37+
}
38+
39+
func (t *Table) Allow(dir string) {
40+
t.writeToFile("+", dir)
41+
42+
t.lock.Lock()
43+
defer t.lock.Unlock()
44+
t.allowedDirs[dir] = true
45+
}
46+
47+
func (t *Table) Deny(dir string) {
48+
t.writeToFile("-", dir)
49+
50+
t.lock.Lock()
51+
defer t.lock.Unlock()
52+
delete(t.allowedDirs, dir)
53+
}
54+
55+
func (t *Table) writeToFile(flag, dir string) {
56+
f, err := os.OpenFile(t.rulesFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
57+
if err != nil {
58+
return
59+
}
60+
defer f.Close()
61+
rule := flag + dir + "\n"
62+
if _, err := f.WriteString(rule); err != nil {
63+
panic(err)
64+
}
65+
}
66+
func (t *Table) EmptyRulesFile() error {
67+
return os.Remove(t.rulesFile)
68+
}
69+
70+
func (t *Table) IsDeny(dir string) (deny bool) {
71+
t.lock.RLock()
72+
defer t.lock.RUnlock()
73+
74+
deny = true
75+
for d := range t.allowedDirs {
76+
if strings.HasPrefix(dir, d) {
77+
return false
78+
}
79+
}
80+
return true
81+
}
82+
83+
func (t *Table) GetAllowedDirs() map[string]bool {
84+
t.lock.RLock()
85+
defer t.lock.RUnlock()
86+
87+
return t.allowedDirs
88+
}
89+
90+
func (t *Table) Dispose() (err error) {
91+
t.stopWatch <- true
92+
93+
t.LoadTable()
94+
95+
var count int = 0
96+
for range t.allowedDirs {
97+
count++
98+
}
99+
if count == 0 {
100+
if err = t.EmptyRulesFile(); err != nil {
101+
return
102+
}
103+
}
104+
return
105+
}
106+
107+
func (t *Table) Watch() {
108+
ticker := time.NewTicker(time.Millisecond * 500)
109+
lastMtime := t.getRulesFileStat().ModTime()
110+
for {
111+
select {
112+
case <-t.stopWatch:
113+
ticker.Stop()
114+
return
115+
case <-ticker.C:
116+
stat := t.getRulesFileStat()
117+
mtime := stat.ModTime()
118+
if lastMtime.Equal(mtime) {
119+
continue
120+
}
121+
lastMtime = mtime
122+
if err := t.LoadTable(); err != nil {
123+
panic(err)
124+
}
125+
}
126+
}
127+
}
128+
func (t *Table) getRulesFileStat() fs.FileInfo {
129+
stat, err := os.Stat(t.rulesFile)
130+
if err != nil {
131+
panic(err)
132+
}
133+
return stat
134+
}
135+
136+
func (t *Table) LoadTable() (err error) {
137+
t.lock.Lock()
138+
defer t.lock.Unlock()
139+
140+
f, err := os.OpenFile(t.rulesFile, os.O_CREATE|os.O_RDONLY, 0644)
141+
if err != nil {
142+
return
143+
}
144+
defer f.Close()
145+
m := LoadTable(f)
146+
147+
t.allowedDirs = m
148+
return
149+
}
150+
151+
func LoadTable(r io.Reader) AllowedDirs {
152+
m := AllowedDirs{}
153+
154+
scanner := bufio.NewScanner(r)
155+
for scanner.Scan() {
156+
line := scanner.Text()
157+
if strings.HasPrefix(line, "+") {
158+
dir := strings.TrimPrefix(line, "+")
159+
m[dir] = true
160+
}
161+
if strings.HasPrefix(line, "-") {
162+
dir := strings.TrimPrefix(line, "-")
163+
_, ok := m[dir]
164+
if ok {
165+
delete(m, dir)
166+
}
167+
}
168+
}
169+
return m
170+
}

0 commit comments

Comments
 (0)