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/server/server.go | |
initial
Diffstat (limited to 'pkg/server/server.go')
| -rw-r--r-- | pkg/server/server.go | 121 |
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 + } +} |
