예제 #1
0
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
}
예제 #2
0
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)
	}
}
예제 #3
0
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
}