func (t *TokenRenewer) renewToken() error {
	renew := &protocol.Kite{
		ID: t.client.Kite.ID,
	}
	token, err := t.localKite.GetToken(renew)
	if err != nil {
		return err
	}
	if err = t.parse(token); err != nil {
		return err
	}
	t.client.authMu.Lock()
	t.client.Auth.Key = token
	t.client.authMu.Unlock()
	t.client.callOnTokenRenewHandlers(token)
	return nil
}
renewToken gets a new token from a kontrolClient, parses it and sets it as the token.
package kite
import (
	"fmt"
	"strings"
	"sync"
	"time"
	jwt "github.com/dgrijalva/jwt-go"
	"github.com/koding/kite/kitekey"
	"github.com/koding/kite/protocol"
)
const (
	renewBefore   = 30 * time.Second
	retryInterval = 10 * time.Second
)
type TokenRenewer struct {
	client           *Client
	localKite        *Kite
	validUntil       time.Time
	signalRenewToken chan struct{}
	disconnect       chan struct{}
	once             sync.Once  
	renewLoopWG      sync.WaitGroup
}
func NewTokenRenewer(r *Client, k *Kite) (*TokenRenewer, error) {
	t := &TokenRenewer{
		client:           r,
		localKite:        k,
		signalRenewToken: make(chan struct{}),
		disconnect:       make(chan struct{}),
	}
	return t, t.parse(r.Auth.Key)
}
func (t *TokenRenewer) parse(tokenString string) error {
	claims := &kitekey.KiteClaims{}
	_, err := jwt.ParseWithClaims(tokenString, claims, t.localKite.RSAKey)
	if err != nil {
		valErr, ok := err.(*jwt.ValidationError)
		if !ok {
			return err
		}
		if (valErr.Errors & jwt.ValidationErrorSignatureInvalid) == 0 {
			return fmt.Errorf("Cannot parse token: %s", err)
		}
	}
	t.validUntil = time.Unix(claims.ExpiresAt, 0).UTC()
	return nil
}
func (t *TokenRenewer) RenewWhenExpires() {
	t.once.Do(t.installHandlers)
}
func (t *TokenRenewer) installHandlers() {
	t.client.OnConnect(t.startRenewLoop)
	t.client.OnTokenExpire(t.sendRenewTokenSignal)
	t.client.OnDisconnect(t.sendDisconnectSignal)
}
func (t *TokenRenewer) renewLoop() {
	t.renewLoopWG.Add(1)
	defer t.renewLoopWG.Done()
	go time.AfterFunc(t.renewDuration(), t.sendRenewTokenSignal)
	for {
		select {
		case <-t.signalRenewToken:
			switch err := t.renewToken(); {
			case err == nil:
				go time.AfterFunc(t.renewDuration(), t.sendRenewTokenSignal)
			case err == ErrNoKitesAvailable || strings.Contains(err.Error(), "no kites found"):
			default:
				t.localKite.Log.Error("token renewer: %s Cannot renew token for Kite: %s I will retry in %d seconds...",
					err, t.client.ID, retryInterval/time.Second)
				time.Sleep(1 * time.Second)
				go time.AfterFunc(retryInterval, t.sendRenewTokenSignal)
			}
		case <-t.disconnect:
			return
		}
	}
}
func (t *TokenRenewer) renewDuration() time.Duration {
	return t.validUntil.Add(-renewBefore).Sub(time.Now().UTC())
}
func (t *TokenRenewer) startRenewLoop() {
	t.sendDisconnectSignal()
	t.renewLoopWG.Wait()
	go t.renewLoop()
}
func (t *TokenRenewer) sendRenewTokenSignal() {
	select {
	case t.signalRenewToken <- struct{}{}:
	default:
	}
}
func (t *TokenRenewer) sendDisconnectSignal() {
	select {
	case t.disconnect <- struct{}{}:
	default:
	}
}