diff options
| author | Mikhail Osipov <mike.osipov@gmail.com> | 2020-01-20 04:20:48 +0300 |
|---|---|---|
| committer | Mikhail Osipov <mike.osipov@gmail.com> | 2020-01-20 04:20:48 +0300 |
| commit | 6fc33abdea2e0a09adf5cf1811fe1ee2fd36f0c9 (patch) | |
| tree | 23fcefa80b13ed62f733e9855deb66948c473e80 /pkg | |
initial
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/client/client.go | 57 | ||||
| -rw-r--r-- | pkg/config/config.go | 8 | ||||
| -rw-r--r-- | pkg/config/log.go | 7 | ||||
| -rw-r--r-- | pkg/server/echo.go | 15 | ||||
| -rw-r--r-- | pkg/server/exit.go | 13 | ||||
| -rw-r--r-- | pkg/server/server.go | 121 | ||||
| -rw-r--r-- | pkg/server/status.go | 15 |
7 files changed, 236 insertions, 0 deletions
diff --git a/pkg/client/client.go b/pkg/client/client.go new file mode 100644 index 0000000..d94b5a3 --- /dev/null +++ b/pkg/client/client.go @@ -0,0 +1,57 @@ +package client + +import ( + "tunnel/pkg/config" + "strings" + "errors" + "time" + "net" + "io" +) + +var errClosed = errors.New("server closed connection") + +type Client struct { + conn net.Conn +} + +func New() (*Client, error) { + conn, err := net.Dial(config.SockType, config.SockPath) + if err != nil { + return nil, err + } + + return &Client{conn: conn}, nil +} + +func (c *Client) Send(args []string) (string, error) { + c.conn.SetDeadline(time.Now().Add(time.Second)); + + defer func () { + var t time.Time + c.conn.SetDeadline(t) + }() + + msg := strings.Join(args, " ") + buf := make([]byte, config.BufSize) + + _, ew := c.conn.Write([]byte(msg)) + if ew != nil { + return "", ew + } + + nr, er := c.conn.Read(buf) + if er != nil { + if er == io.EOF { + return "", errClosed + } + + return "", er + } + + return string(buf[:nr]), nil +} + +func (c *Client) Close() { + c.conn.Close() +} diff --git a/pkg/config/config.go b/pkg/config/config.go new file mode 100644 index 0000000..c620e4a --- /dev/null +++ b/pkg/config/config.go @@ -0,0 +1,8 @@ +package config + +const SockType = "unixpacket" +const SockPath = "/tmp/tunnel.sock" + +const TimeFormat = "2006-01-02 15:04:05" + +const BufSize = 1024 diff --git a/pkg/config/log.go b/pkg/config/log.go new file mode 100644 index 0000000..9aa24b6 --- /dev/null +++ b/pkg/config/log.go @@ -0,0 +1,7 @@ +package config + +import "log" + +func init() { + log.SetFlags(log.Lshortfile) +} diff --git a/pkg/server/echo.go b/pkg/server/echo.go new file mode 100644 index 0000000..74c0450 --- /dev/null +++ b/pkg/server/echo.go @@ -0,0 +1,15 @@ +package server + +import ( + "strings" + "fmt" + "io" +) + +func init() { + setHandler("echo", echo) +} + +func echo(s *Server, args []string, out io.Writer) { + fmt.Fprint(out, strings.Join(args[1:], " ")) +} diff --git a/pkg/server/exit.go b/pkg/server/exit.go new file mode 100644 index 0000000..504c7d1 --- /dev/null +++ b/pkg/server/exit.go @@ -0,0 +1,13 @@ +package server + +import ( + "io" +) + +func init() { + setHandler("exit", exit) +} + +func exit(s *Server, args []string, out io.Writer) { + s.Stop() +} diff --git a/pkg/server/server.go b/pkg/server/server.go new file mode 100644 index 0000000..ed0106b --- /dev/null +++ b/pkg/server/server.go @@ -0,0 +1,121 @@ +package server + +import ( + "tunnel/pkg/config" + "strings" + "bytes" + "sync" + "time" + "fmt" + "log" + "net" + "io" +) + +type handler func (*Server, []string, io.Writer) + +var handlers = map[string]handler{} + +type Server struct { + listen net.Listener + since time.Time + + wg sync.WaitGroup + m sync.Mutex + + done bool +} + +func setHandler(cmd string, h handler) { + if _, ok := handlers[cmd]; ok { + panic(fmt.Sprintf("handler %s already registered", cmd)) + } + + handlers[cmd] = h +} + +func (s *Server) isDone() bool { + s.m.Lock() + defer s.m.Unlock() + return s.done +} + +func New() (*Server, error) { + listen, err := net.Listen(config.SockType, config.SockPath) + if err != nil { + return nil, err + } + + s := &Server{ + listen: listen, + since: time.Now(), + } + + return s, nil +} + +func (s *Server) Run() { + for { + conn, err := s.listen.Accept() + if err != nil { + if s.isDone() { + break + } + + log.Print(err) + continue + } + + log.Print("new client") + + s.wg.Add(1) + + go s.handle(conn) + } + + s.wg.Wait() +} + +func (s *Server) Stop() { + s.m.Lock() + s.done = true + s.m.Unlock() + + s.listen.Close() +} + +func (s *Server) handle(c net.Conn) { + defer c.Close() + defer s.wg.Done() + + buf := make([]byte, config.BufSize) + + nr, er := c.Read(buf) + if er != nil { + if er != io.EOF { + log.Print("handle: ", er) + } + return + } + + data := string(buf[:nr]) + args := strings.Split(data, " ") + out := bytes.NewBuffer(nil) + + if h, ok := handlers[args[0]]; ok { + log.Printf("handle: run: %s", data) + h(s, args, out) + } else { + fmt.Fprint(out, "unknown command") + } + + if out.Len() == 0 { + out.Write([]byte("\n")) + } + + _, ew := c.Write(out.Bytes()) + if ew != nil { + log.Print("handle: ", ew) + return + } +} diff --git a/pkg/server/status.go b/pkg/server/status.go new file mode 100644 index 0000000..6fb2a2a --- /dev/null +++ b/pkg/server/status.go @@ -0,0 +1,15 @@ +package server + +import ( + "tunnel/pkg/config" + "fmt" + "io" +) + +func init() { + setHandler("status", status) +} + +func status(s *Server, args []string, out io.Writer) { + fmt.Fprintf(out, "since %s", s.since.Format(config.TimeFormat)) +} |
