GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing github.com — kite/tokenrenewer.go at master · koding/kite Expand file tree/ Copy pathtokenrenewer.goMore file actions 165 lines (139 loc) · 4.44 KB / Copy pathtokenrenewer.goFile metadata and controls165 lines (139 loc) · 4.44 KB 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 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 ) // TokenRenewer renews the token of a Client just before it expires. type TokenRenewer struct { client *Client localKite *Kite validUntil time.Time signalRenewToken chan struct{} disconnect chan struct{} once sync.Once // for c.installHandlers 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) } // parse the token string and set 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 } // do noy return for ValidationErrorSignatureValid. This is because we // might asked for a kite who's public Key is different what we have. // We still should be able to send them requests. if (valErr.Errors & jwt.ValidationErrorSignatureInvalid) == 0 { return fmt.Errorf("Cannot parse token: %s", err) } } t.validUntil = time.Unix(claims.ExpiresAt, 0).UTC() return nil } // RenewWhenExpires renews the token before it expires. 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() // renews token before it expires (sends the first signal to the goroutine below) go time.AfterFunc(t.renewDuration(), t.sendRenewTokenSignal) // renew token on signal util remote kite disconnects. 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"): // If kite went down we're not going to renew the token, // as we need to dial either way. // // This case handles a situation, when kite missed // disconnect signal (observed to happen with XHR transport). 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) // Need to sleep here litle bit because a signal is sent // when an expired token is detected on incoming request. // This sleep prevents the signal from coming too fast. time.Sleep(1 * time.Second) go time.AfterFunc(retryInterval, t.sendRenewTokenSignal) } case <-t.disconnect: return } } } // The duration from now to the time token needs to be renewed. // Needs to be calculated after renewing the token. func (t *TokenRenewer) renewDuration() time.Duration { return t.validUntil.Add(-renewBefore).Sub(time.Now().UTC()) } func (t *TokenRenewer) startRenewLoop() { // In case when t.client missed a disconnect signal (e.g. due to timeout observed // by the remote end), previous renewLoop will be still running. t.sendDisconnectSignal() // if we don't wait to observe previous renewLoop goroutine handle the disconnect // signal, we'd have a race resulting in new renewLoop goroutine handling it. t.renewLoopWG.Wait() go t.renewLoop() } func (t *TokenRenewer) sendRenewTokenSignal() { // Needs to be non-blocking because tokenRenewer may be stopped. select { case t.signalRenewToken <- struct{}{}: default: } } func (t *TokenRenewer) sendDisconnectSignal() { // Needs to be non-blocking because tokenRenewer may be stopped. select { case t.disconnect <- struct{}{}: default: } } // renewToken gets a new token from a kontrolClient, parses it and sets it as the token. 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 } |
| You are visitor 01402520 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |