Beispiel #1
0
// NewRedis - Creates a Redis using the provided configuration.
func NewRedis(config RedisConfig, logger log.Modular) Authenticator {
	return &Redis{
		logger: logger.NewModule(":redis_auth"),
		config: config,
		pool:   newPool(config),
	}
}
Beispiel #2
0
// New - Creates and returns a new curator, and launches its internal loop.
func New(
	config Config,
	log log.Modular,
	stats metrics.Aggregator,
	auth acl.Authenticator,
	store store.Type,
) (Type, error) {

	curator := impl{
		config:      config,
		store:       store,
		log:         log.NewModule(":curator"),
		stats:       stats,
		auth:        auth,
		openBinders: make(map[string]binder.Type),
		errorChan:   make(chan binder.Error, 10),
		closeChan:   make(chan struct{}),
		closedChan:  make(chan struct{}),
	}
	go curator.loop()

	return &curator, nil
}
Beispiel #3
0
/*
New - Creates a binder targeting an existing document determined via an ID. Must provide a
store.Type to acquire the document and apply future updates to.
*/
func New(
	id string,
	block store.Type,
	config Config,
	errorChan chan<- Error,
	log log.Modular,
	stats metrics.Aggregator,
) (Type, error) {
	binder := impl{
		id:               id,
		config:           config,
		otBuffer:         text.NewOTBuffer(config.OTBufferConfig),
		block:            block,
		log:              log.NewModule(":binder"),
		stats:            stats,
		clients:          make([]*binderClient, 0),
		subscribeChan:    make(chan subscribeRequest),
		transformChan:    make(chan transformSubmission),
		messageChan:      make(chan messageSubmission),
		usersRequestChan: make(chan usersRequest),
		exitChan:         make(chan *binderClient),
		kickChan:         make(chan kickRequest),
		errorChan:        errorChan,
		closedChan:       make(chan struct{}),
	}
	binder.log.Debugln("Bound to document, attempting flush")

	if _, err := binder.flush(); err != nil {
		stats.Incr("binder.new.error", 1)
		return nil, err
	}
	go binder.loop()

	stats.Incr("binder.new.success", 1)
	return &binder, nil
}
Beispiel #4
0
/*
WebsocketHandler - Returns a websocket handler that routes new websockets to a curator. Use this
with an HTTP server with the "golang.org/x/net/websocket" package.
*/
func WebsocketHandler(
	finder curator.Type,
	timeout time.Duration,
	logger log.Modular,
	stats metrics.Aggregator,
) func(ws *websocket.Conn) {
	return func(ws *websocket.Conn) {
		var err error
		var session binder.Portal

		defer func() {
			if err != nil {
				websocket.JSON.Send(ws, leapHTTPServerMessage{
					Type:  "error",
					Error: fmt.Sprintf("socket initialization failed: %v", err),
				})
			}
			if err = ws.Close(); err != nil {
				logger.Errorf("Failed to close socket: %v\n", err)
			}
			stats.Decr("http.open_websockets", 1)
		}()

		stats.Incr("http.websocket.opened", 1)
		stats.Incr("http.open_websockets", 1)

		for session == nil && err == nil {
			var clientMsg leapHTTPClientMessage
			websocket.JSON.Receive(ws, &clientMsg)

			switch clientMsg.Command {
			case "create":
				if clientMsg.Document == nil {
					err = ErrInvalidDocument
				} else {
					session, err = finder.CreateDocument(
						clientMsg.UserID, clientMsg.Token, *clientMsg.Document, timeout)
				}
			case "read":
				if len(clientMsg.DocID) <= 0 {
					err = ErrInvalidDocument
				} else {
					session, err = finder.ReadDocument(
						clientMsg.UserID, clientMsg.Token, clientMsg.DocID, timeout)
				}
			case "edit":
				if len(clientMsg.DocID) <= 0 {
					err = ErrInvalidDocument
				} else {
					session, err = finder.EditDocument(
						clientMsg.UserID, clientMsg.Token, clientMsg.DocID, timeout)
				}
			case "ping":
				// Ignore and continue waiting for init message.
			default:
				err = fmt.Errorf(
					"first command must be init or ping, client sent: %v", clientMsg.Command,
				)
			}
		}

		if session != nil && err == nil {
			version := session.BaseVersion()
			websocket.JSON.Send(ws, leapHTTPServerMessage{
				Type:     "document",
				Document: session.Document(),
				Version:  &version,
			})
			session.ReleaseDocument()

			// Begin serving websocket IO.
			serveWebsocketIO(ws, session, timeout, logger, stats)
		}
	}
}