func (k *Kite) SendWebRTCRequest(req *protocol.WebRTCSignalMessage) error {
	if err := k.SetupKontrolClient(); err != nil {
		return err
	}
	<-k.kontrol.readyConnected
	_, err := k.kontrol.TellWithTimeout(WebRTCHandlerName, k.Config.Timeout, req)
	return err
}
SendWebRTCRequest sends requests to kontrol for signalling purposes.
package kite
import (
	"errors"
	"fmt"
	"math/rand"
	"net/url"
	"os"
	"sync"
	"time"
	"github.com/koding/kite/dnode"
	"github.com/koding/kite/protocol"
)
const (
	kontrolRetryDuration = 10 * time.Second
	proxyRetryDuration   = 10 * time.Second
)
var ErrNoKitesAvailable = errors.New("no kites availabile")
type kontrolClient struct {
	*Client
	sync.Mutex  
	onceConnected   sync.Once
	onceRegistered  sync.Once
	readyConnected  chan struct{}
	readyRegistered chan struct{}
	lastRegisteredURL *url.URL
	registerChan chan *url.URL
}
type registerResult struct {
	URL *url.URL
}
func (k *Kite) SetupKontrolClient() error {
	if k.kontrol.Client != nil {
		return nil  
	}
	if k.Config.KontrolURL == "" {
		return errors.New("no kontrol URL given in config")
	}
	client := k.NewClient(k.Config.KontrolURL)
	client.Kite = protocol.Kite{Name: "kontrol"}  
	client.Auth = &Auth{
		Type: "kiteKey",
		Key:  k.KiteKey(),
	}
	k.kontrol.Lock()
	k.kontrol.Client = client
	k.kontrol.Unlock()
	k.kontrol.OnConnect(func() {
		k.Log.Info("Connected to Kontrol")
		k.Log.Debug("Connected to Kontrol with session %q", client.session.ID())
		k.kontrol.Lock()
		if k.kontrol.lastRegisteredURL != nil {
			select {
			case k.kontrol.registerChan <- k.kontrol.lastRegisteredURL:
			default:
			}
		}
		k.kontrol.Unlock()
		k.kontrol.onceConnected.Do(func() { close(k.kontrol.readyConnected) })
	})
	k.kontrol.OnDisconnect(func() {
		k.Log.Warning("Disconnected from Kontrol.")
	})
	if _, err := k.kontrol.DialForever(); err != nil {
		return err
	}
	return nil
}
func (k *Kite) GetKites(query *protocol.KontrolQuery) ([]*Client, error) {
	if err := k.SetupKontrolClient(); err != nil {
		return nil, err
	}
	clients, err := k.getKites(protocol.GetKitesArgs{Query: query})
	if err != nil {
		return nil, err
	}
	if len(clients) == 0 {
		return nil, ErrNoKitesAvailable
	}
	return clients, nil
}
func (k *Kite) getKites(args protocol.GetKitesArgs) ([]*Client, error) {
	<-k.kontrol.readyConnected
	response, err := k.kontrol.TellWithTimeout("getKites", k.Config.Timeout, args)
	if err != nil {
		return nil, err
	}
	var result = new(protocol.GetKitesResult)
	err = response.Unmarshal(&result)
	if err != nil {
		return nil, err
	}
	clients := make([]*Client, len(result.Kites))
	for i, currentKite := range result.Kites {
		auth := &Auth{
			Type: "token",
			Key:  currentKite.Token,
		}
		clients[i] = k.NewClient(currentKite.URL)
		clients[i].Kite = currentKite.Kite
		clients[i].Auth = auth
	}
	for _, c := range clients {
		token, err := NewTokenRenewer(c, k)
		if err != nil {
			k.Log.Error("Error in token. Token will not be renewed when it expires: %s", err)
			continue
		}
		token.RenewWhenExpires()
		c.closeRenewer = token.disconnect
	}
	return clients, nil
}
func (k *Kite) GetToken(kite *protocol.Kite) (string, error) {
	if err := k.SetupKontrolClient(); err != nil {
		return "", err
	}
	<-k.kontrol.readyConnected
	result, err := k.kontrol.TellWithTimeout("getToken", k.Config.Timeout, kite)
	if err != nil {
		return "", err
	}
	var tkn string
	err = result.Unmarshal(&tkn)
	if err != nil {
		return "", err
	}
	return tkn, nil
}