Exemple #1
0
func (s *reconnectingRaw) Accept() (conn.Conn, error) {
	for {

		s.RLock()
		c, err := s.RawSession.Accept()
		s.RUnlock()

		// if we get an error, reconnect instead of returning it
		if err != nil {
			//			s.Error("Error from Accept(): %v, reconnecting . . .", err)
			log.Printf("[ERROR] Error from Accept(): %v, reconnecting . . .\n", err)
			// reconnect can still return errors for permanent failures
			if err = s.reconnect(); err != nil {
				return nil, err
			}
		} else {
			return c, err
		}
	}
}
Exemple #2
0
func (s *ReconnectingSession) reconnect() error {
	var wait time.Duration = time.Second

	failTemp := func(err error) {
		//		s.raw.Info("Session failed: %v", err)
		log.Printf("[INFO] Session failed: %v\n", err)
		// session failed, wait before reconnecting
		//		s.raw.Info("Waiting %d seconds before reconnecting", int(wait.Seconds()))
		log.Printf("[INFO] Waiting %d seconds before reconnecting", int(wait.Seconds()))
		time.Sleep(wait)

		// exponentially increase wait time up to a limit
		wait = 2 * wait
		wait = time.Duration(math.Min(float64(wait), float64(maxWait)))
	}

	fail := func(err error) error {
		s.done <- err
		return err
	}

retry:
	// dial the tunnel server
	mux, err := s.dialer()
	if err != nil {
		failTemp(err)
		goto retry
	}

	// swap the muxado session in
	s.raw.Lock()
	s.raw.mux = mux
	s.raw.Unlock()

	resp, err := s.raw.Auth(s.raw.id, s.authExtra)
	if err != nil {
		failTemp(err)
		goto retry
	}

	// auth errors are considered permanent
	if resp.Error != "" {
		return fail(errors.New(resp.Error))
	}

	// re-establish binds
	s.RLock()
	for _, t := range s.tunnels {
		resp, err := s.raw.Listen(t.proto, t.bindOpts, t.bindExtra)
		if err != nil {
			s.RUnlock()
			failTemp(err)
			goto retry
		}

		if resp.Error != "" {
			s.RUnlock()
			return fail(errors.New(resp.Error))
		}
	}
	s.RUnlock()

	return nil
}