summaryrefslogtreecommitdiff
path: root/pkg/server/server.go
diff options
context:
space:
mode:
authorMikhail Osipov <mike.osipov@gmail.com>2020-01-20 04:20:48 +0300
committerMikhail Osipov <mike.osipov@gmail.com>2020-01-20 04:20:48 +0300
commit6fc33abdea2e0a09adf5cf1811fe1ee2fd36f0c9 (patch)
tree23fcefa80b13ed62f733e9855deb66948c473e80 /pkg/server/server.go
initial
Diffstat (limited to 'pkg/server/server.go')
-rw-r--r--pkg/server/server.go121
1 files changed, 121 insertions, 0 deletions
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
+ }
+}