You've already forked woodpecker
							
							
				mirror of
				https://github.com/woodpecker-ci/woodpecker.git
				synced 2025-10-30 23:27:39 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			158 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			158 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package channel
 | |
| 
 | |
| import (
 | |
| 	"crypto/rand"
 | |
| 	"encoding/json"
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 	"time"
 | |
| 
 | |
| 	"code.google.com/p/go.net/websocket"
 | |
| 	"github.com/dchest/authcookie"
 | |
| )
 | |
| 
 | |
| // secret key used to generate tokens
 | |
| var secret = make([]byte, 32)
 | |
| 
 | |
| func init() {
 | |
| 	// generate the secret key by reading
 | |
| 	// from crypto/random
 | |
| 	if _, err := io.ReadFull(rand.Reader, secret); err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Create will generate a token and create a new
 | |
| // channel over which messages will be sent.
 | |
| func Create(name string) string {
 | |
| 	mu.Lock()
 | |
| 	defer mu.Unlock()
 | |
| 
 | |
| 	if _, ok := hubs[name]; !ok {
 | |
| 		hub := newHub(false, true)
 | |
| 		hubs[name] = hub
 | |
| 		go hub.run()
 | |
| 	}
 | |
| 	return authcookie.NewSinceNow(name, 24*time.Hour, secret)
 | |
| }
 | |
| 
 | |
| // CreateStream will generate a token and create a new
 | |
| // channel over which messages streams (ie build output)
 | |
| // are sent.
 | |
| func CreateStream(name string) string {
 | |
| 	mu.Lock()
 | |
| 	defer mu.Unlock()
 | |
| 
 | |
| 	if _, ok := hubs[name]; !ok {
 | |
| 		hub := newHub(true, false)
 | |
| 		hubs[name] = hub
 | |
| 		go hub.run()
 | |
| 	}
 | |
| 	return authcookie.NewSinceNow(name, 24*time.Hour, secret)
 | |
| }
 | |
| 
 | |
| // Token will generate a token, but will not create
 | |
| // a new channel.
 | |
| func Token(name string) string {
 | |
| 	return authcookie.NewSinceNow(name, 24*time.Hour, secret)
 | |
| }
 | |
| 
 | |
| // Send sends a message on the named channel.
 | |
| func Send(name string, message string) error {
 | |
| 	return SendBytes(name, []byte(message))
 | |
| }
 | |
| 
 | |
| // SendJSON sends a JSON-encoded value on
 | |
| // the named channel.
 | |
| func SendJSON(name string, value interface{}) error {
 | |
| 	m, err := json.Marshal(value)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	return SendBytes(name, m)
 | |
| }
 | |
| 
 | |
| // SendBytes send a message in byte format on
 | |
| // the named channel.
 | |
| func SendBytes(name string, value []byte) error {
 | |
| 	// get the hub for the specified channel name
 | |
| 	mu.RLock()
 | |
| 	hub, ok := hubs[name]
 | |
| 	mu.RUnlock()
 | |
| 
 | |
| 	if !ok {
 | |
| 		return fmt.Errorf("channel does not exist")
 | |
| 	}
 | |
| 
 | |
| 	go hub.Write(value)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func Read(ws *websocket.Conn) {
 | |
| 
 | |
| 	// get the name from the request
 | |
| 	hash := ws.Request().FormValue("token")
 | |
| 
 | |
| 	// get the hash of the token
 | |
| 	name := authcookie.Login(hash, secret)
 | |
| 
 | |
| 	// get the hub for the specified channel name
 | |
| 	mu.RLock()
 | |
| 	hub, ok := hubs[name]
 | |
| 	mu.RUnlock()
 | |
| 
 | |
| 	// if hub not found, exit
 | |
| 	if !ok {
 | |
| 		ws.Close()
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// internal representation of a connection
 | |
| 	// maximum queue of 100000 messages
 | |
| 	conn := &connection{
 | |
| 		send: make(chan string, 100000),
 | |
| 		ws:   ws,
 | |
| 	}
 | |
| 
 | |
| 	// register the connection with the hub
 | |
| 	hub.register <- conn
 | |
| 
 | |
| 	defer func() {
 | |
| 		go func() {
 | |
| 			hub.unregister <- conn
 | |
| 		}()
 | |
| 		closed := <-hub.closed
 | |
| 
 | |
| 		// this will remove the hub when the connection is
 | |
| 		// closed if the
 | |
| 		if hub.autoClose && closed {
 | |
| 			mu.Lock()
 | |
| 			delete(hubs, name)
 | |
| 			mu.Unlock()
 | |
| 		}
 | |
| 	}()
 | |
| 
 | |
| 	go conn.writer()
 | |
| 	conn.reader()
 | |
| }
 | |
| 
 | |
| func Close(name string) {
 | |
| 	// get the hub for the specified channel name
 | |
| 	mu.RLock()
 | |
| 	hub, ok := hubs[name]
 | |
| 	mu.RUnlock()
 | |
| 
 | |
| 	if !ok {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// close hub connections
 | |
| 	hub.Close()
 | |
| 
 | |
| 	// remove the hub
 | |
| 	mu.Lock()
 | |
| 	delete(hubs, name)
 | |
| 	mu.Unlock()
 | |
| }
 |