// client and transport handler for connections. func (s *Server) clientHandler(conn net.Conn) { defer conn.Close() c := &client{ conn: conn, enc: gob.NewEncoder(conn), dec: gob.NewDecoder(conn), } // get the first client struct as a handshake var handshake Message if err := c.dec.Decode(&handshake); err != nil { // client disconnected before it sent the full handshake if err != io.EOF { log.Errorln(err) } return } c.Client = handshake.Client log.Debug("new client: %v", handshake.Client) if c.Version != version.Revision { log.Warn("mismatched miniccc version: %v", c.Version) } // Set up minitunnel, dialing the server that should be running on the // client's side. Data is Trunk'd via Messages. local, remote := net.Pipe() defer local.Close() defer remote.Close() go func() { go Trunk(remote, c.UUID, c.sendMessage) tunnel, err := minitunnel.Dial(local) if err != nil { log.Error("dial: %v", err) return } s.clientLock.Lock() defer s.clientLock.Unlock() log.Debug("minitunnel created for %v", c.UUID) c.tunnel = tunnel }() c.Checkin = time.Now() if err := s.addClient(c); err != nil { log.Errorln(err) return } defer s.removeClient(c.UUID) var err error for err == nil { var m Message if err = c.dec.Decode(&m); err == nil { log.Debug("new message: %v", m.Type) switch m.Type { case MESSAGE_TUNNEL: _, err = remote.Write(m.Tunnel) case MESSAGE_FILE: m2 := s.readFile(m.Filename) m2.UUID = m.UUID err = c.sendMessage(m2) case MESSAGE_CLIENT: s.responses <- m.Client case MESSAGE_COMMAND: // this shouldn't be sent via the client... default: err = fmt.Errorf("unknown message type: %v", m.Type) } } } if err != io.EOF && !strings.Contains(err.Error(), "connection reset by peer") { log.Errorln(err) } }
// tunnel transport handler func (c *Client) handleTunnel(server bool, stop chan bool) { log.Debug("handleTunnel: %v", server) a, b := net.Pipe() c.tunnelData = make(chan []byte, 1024) go func() { if server { var err error c.tunnel, err = minitunnel.Dial(a) if err != nil { log.Errorln("Dial: %v", err) a.Close() b.Close() } } else { go func() { err := minitunnel.ListenAndServe(a) if err != nil { log.Fatalln("ListenAndServe: %v", err) } }() } }() go func() { for { var buf = make([]byte, BUFFER_SIZE) n, err := b.Read(buf) if err != nil { if err != io.ErrClosedPipe { log.Errorln(err) } a.Close() b.Close() return } // push it up in a message m := &Message{ Type: MESSAGE_TUNNEL, UUID: c.UUID, Tunnel: buf[:n], } c.out <- m } }() go func() { for { data := <-c.tunnelData if data == nil { return } _, err := b.Write(data) if err != nil { log.Errorln(err) a.Close() b.Close() return } } }() <-stop log.Debug("ron client tunnel close: %v", c.UUID) a.Close() b.Close() close(c.tunnelData) }