func (s *Session) handleAuth() error { // accept ann auth stream raw, err := s.mux.Accept() if err != nil { return s.Error("Failed to accept auth stream: %v", err) } defer raw.Close() stream := conn.Wrap(raw, "session", "auth") // read the Auth message if err = proto.ReadMsgInto(stream, &s.auth); err != nil { return s.Error("Failed to read auth message; %v", err) } failAuth := func(e error) error { _ = proto.WriteMsg(stream, &proto.AuthResp{Error: e.Error()}) return e } // generate a client identifier s.id = s.auth.ClientId if s.id == "" { // it's a new session, assign an ID if s.id, err = util.SecureRandId(16); err != nil { return failAuth(fmt.Errorf("Failed generate client identifier: %v", err)) } } // put ourselves in the registry s.registry.register(s) // set logging prefix s.Logger.AddTags(s.id) // agree on protocol version // if proto.Version not in s.auth.Version if sort.SearchStrings(s.auth.Version, proto.Version) == len(s.auth.Version) { return failAuth(fmt.Errorf("No acceptable protocol version. Requested: %v, capable: %v", s.auth.Version, proto.Version)) } // auth hook if err = s.hooks.OnAuth(s, s.auth); err != nil { return failAuth(err) } // Respond to authentication authResp := &proto.AuthResp{ Version: proto.Version, ClientId: s.id, } if err = proto.WriteMsg(stream, authResp); err != nil { return failAuth(fmt.Errorf("Failed to write authentication response: %v", err)) } return nil }
func (s *Session) receive() { handleProxy := func(proxy conn.Conn) { // read out the proxy message var startPxy proto.StartProxy if err := proto.ReadMsgInto(proxy, &startPxy); err != nil { proxy.Error("Server failed to write StartProxy: %v", err) proxy.Close() return } // wrap connection so that it has a proper RemoteAddr() proxy = &proxyConn{Conn: proxy, remoteAddr: &proxyAddr{startPxy.ClientAddr}} // find tunnel tunnel, ok := s.getTunnel(startPxy.Url) if !ok { proxy.Error("Couldn't find tunnel for proxy: %s", startPxy.Url) proxy.Close() return } // deliver proxy connection tunnel.accept <- proxy } for { // accept the next proxy connection proxy, err := s.raw.Accept() if err != nil { s.raw.Error("Client accept error: %v", err) s.RLock() for _, t := range s.tunnels { go t.Close() } s.RUnlock() return } go handleProxy(proxy) } }
func (s *RawSession) req(tag string, req interface{}, resp interface{}) (err error) { stream, err := s.mux.Open() if err != nil { return } defer stream.Close() // log what happens on the stream c := conn.Wrap(stream, tag, s.id) // send the unlisten request if err = proto.WriteMsg(c, req); err != nil { return } // read out the unlisten response if err = proto.ReadMsgInto(c, resp); err != nil { return } return }