There is no reason to export this functions and this types.

This commit is contained in:
claudemiro
2015-01-31 15:12:54 -03:00
parent d74426127c
commit 201cba86a9
14 changed files with 193 additions and 195 deletions
+22 -22
View File
@@ -14,7 +14,7 @@ import (
) )
// An App // An App
type App struct { type app struct {
sync.Mutex sync.Mutex
Name string Name string
@@ -27,22 +27,22 @@ type App struct {
WebHooks bool WebHooks bool
URLWebHook string URLWebHook string
Channels map[string]*Channel `json:"-"` Channels map[string]*channel `json:"-"`
Connections map[string]*Connection `json:"-"` Connections map[string]*connection `json:"-"`
Stats *expvar.Map `json:"-"` Stats *expvar.Map `json:"-"`
} }
// Alloc memory for Connections and Channels // Alloc memory for Connections and Channels
func (a *App) Init() { func (a *app) Init() {
a.Connections = make(map[string]*Connection) a.Connections = make(map[string]*connection)
a.Channels = make(map[string]*Channel) a.Channels = make(map[string]*channel)
a.Stats = expvar.NewMap(fmt.Sprintf("%s (%s)", a.Name, a.AppID)) a.Stats = expvar.NewMap(fmt.Sprintf("%s (%s)", a.Name, a.AppID))
} }
// Only Presence channels // Only Presence channels
func (a *App) PresenceChannels() []*Channel { func (a *app) PresenceChannels() []*channel {
var channels []*Channel var channels []*channel
for _, c := range a.Channels { for _, c := range a.Channels {
if c.IsPresence() { if c.IsPresence() {
@@ -54,8 +54,8 @@ func (a *App) PresenceChannels() []*Channel {
} }
// Only Private channels // Only Private channels
func (a *App) PrivateChannels() []*Channel { func (a *app) PrivateChannels() []*channel {
var channels []*Channel var channels []*channel
for _, c := range a.Channels { for _, c := range a.Channels {
if c.IsPrivate() { if c.IsPrivate() {
@@ -67,8 +67,8 @@ func (a *App) PrivateChannels() []*Channel {
} }
// Only Public channels // Only Public channels
func (a *App) PublicChannels() []*Channel { func (a *app) PublicChannels() []*channel {
var channels []*Channel var channels []*channel
for _, c := range a.Channels { for _, c := range a.Channels {
if c.IsPublic() { if c.IsPublic() {
@@ -80,7 +80,7 @@ func (a *App) PublicChannels() []*Channel {
} }
// Disconnect Socket // Disconnect Socket
func (a *App) Disconnect(socketID string) { func (a *app) Disconnect(socketID string) {
log.Infof("Disconnecting socket %+v", socketID) log.Infof("Disconnecting socket %+v", socketID)
conn, err := a.FindConnection(socketID) conn, err := a.FindConnection(socketID)
@@ -113,7 +113,7 @@ func (a *App) Disconnect(socketID string) {
} }
// Connect a new Subscriber // Connect a new Subscriber
func (a *App) Connect(conn *Connection) { func (a *app) Connect(conn *connection) {
log.Infof("Adding a new Connection %s to app %s", conn.SocketID, a.Name) log.Infof("Adding a new Connection %s to app %s", conn.SocketID, a.Name)
a.Lock() a.Lock()
defer a.Unlock() defer a.Unlock()
@@ -124,7 +124,7 @@ func (a *App) Connect(conn *Connection) {
} }
// Find a Connection on this app // Find a Connection on this app
func (a *App) FindConnection(socketID string) (*Connection, error) { func (a *app) FindConnection(socketID string) (*connection, error) {
conn, exists := a.Connections[socketID] conn, exists := a.Connections[socketID]
if exists { if exists {
@@ -135,7 +135,7 @@ func (a *App) FindConnection(socketID string) (*Connection, error) {
} }
// DeleteChannel removes the channel from app // DeleteChannel removes the channel from app
func (a *App) RemoveChannel(c *Channel) { func (a *app) RemoveChannel(c *channel) {
log.Infof("Remove the channel %s from app %s", c.ChannelID, a.Name) log.Infof("Remove the channel %s from app %s", c.ChannelID, a.Name)
a.Lock() a.Lock()
defer a.Unlock() defer a.Unlock()
@@ -158,7 +158,7 @@ func (a *App) RemoveChannel(c *Channel) {
} }
// Add a new Channel to this APP // Add a new Channel to this APP
func (a *App) AddChannel(c *Channel) { func (a *app) AddChannel(c *channel) {
log.Infof("Adding a new channel %s to app %s", c.ChannelID, a.Name) log.Infof("Adding a new channel %s to app %s", c.ChannelID, a.Name)
a.Lock() a.Lock()
@@ -183,7 +183,7 @@ func (a *App) AddChannel(c *Channel) {
// Returns a Channel from this app // Returns a Channel from this app
// If not found then the channel is created and added to this app // If not found then the channel is created and added to this app
func (a *App) FindOrCreateChannelByChannelID(n string) *Channel { func (a *app) FindOrCreateChannelByChannelID(n string) *channel {
c, err := a.FindChannelByChannelID(n) c, err := a.FindChannelByChannelID(n)
if err != nil { if err != nil {
@@ -195,7 +195,7 @@ func (a *App) FindOrCreateChannelByChannelID(n string) *Channel {
} }
// Find the channel by channel ID // Find the channel by channel ID
func (a *App) FindChannelByChannelID(n string) (*Channel, error) { func (a *app) FindChannelByChannelID(n string) (*channel, error) {
c, exists := a.Channels[n] c, exists := a.Channels[n]
if exists { if exists {
@@ -205,16 +205,16 @@ func (a *App) FindChannelByChannelID(n string) (*Channel, error) {
return nil, errors.New("Channel does not exists") return nil, errors.New("Channel does not exists")
} }
func (a *App) Publish(c *Channel, event RawEvent, ignore string) error { func (a *app) Publish(c *channel, event rawEvent, ignore string) error {
a.Stats.Add("TotalUniqueMessages", 1) a.Stats.Add("TotalUniqueMessages", 1)
return c.Publish(a, event, ignore) return c.Publish(a, event, ignore)
} }
func (a *App) Unsubscribe(c *Channel, conn *Connection) error { func (a *app) Unsubscribe(c *channel, conn *connection) error {
return c.Unsubscribe(a, conn) return c.Unsubscribe(a, conn)
} }
func (a *App) Subscribe(c *Channel, conn *Connection, data string) error { func (a *app) Subscribe(c *channel, conn *connection, data string) error {
return c.Subscribe(a, conn, data) return c.Subscribe(a, conn, data)
} }
+2 -2
View File
@@ -11,9 +11,9 @@ import (
var id = 0 var id = 0
func newApp() *App { func newApp() *app {
a := App{Name: "Test", AppID: strconv.Itoa(id), Key: "123", Secret: "123", OnlySSL: false, ApplicationDisabled: false, UserEvents: true} a := app{Name: "Test", AppID: strconv.Itoa(id), Key: "123", Secret: "123", OnlySSL: false, ApplicationDisabled: false, UserEvents: true}
a.Init() a.Init()
id++ id++
+18 -18
View File
@@ -15,46 +15,46 @@ import (
) )
// A Channel // A Channel
type Channel struct { type channel struct {
sync.Mutex sync.Mutex
CreatedAt time.Time CreatedAt time.Time
ChannelID string ChannelID string
Subscriptions map[string]*Subscription Subscriptions map[string]*subscription
} }
// Return true if the channel has at least one subscriber // Return true if the channel has at least one subscriber
func (c *Channel) IsOccupied() bool { func (c *channel) IsOccupied() bool {
return c.TotalSubscriptions() > 0 return c.TotalSubscriptions() > 0
} }
// Check if the type of the channel is presence or is private // Check if the type of the channel is presence or is private
func (c *Channel) IsPresenceOrPrivate() bool { func (c *channel) IsPresenceOrPrivate() bool {
return c.IsPresence() || c.IsPrivate() return c.IsPresence() || c.IsPrivate()
} }
// Check if the type of the channel is public // Check if the type of the channel is public
func (c *Channel) IsPublic() bool { func (c *channel) IsPublic() bool {
return !c.IsPresenceOrPrivate() return !c.IsPresenceOrPrivate()
} }
// Check if the type of the channel is presence // Check if the type of the channel is presence
func (c *Channel) IsPresence() bool { func (c *channel) IsPresence() bool {
return strings.HasPrefix(c.ChannelID, "presence-") return strings.HasPrefix(c.ChannelID, "presence-")
} }
// Check if the type of the channel is private // Check if the type of the channel is private
func (c *Channel) IsPrivate() bool { func (c *channel) IsPrivate() bool {
return strings.HasPrefix(c.ChannelID, "private-") return strings.HasPrefix(c.ChannelID, "private-")
} }
// Get the total of subscribers // Get the total of subscribers
func (c *Channel) TotalSubscriptions() int { func (c *channel) TotalSubscriptions() int {
return len(c.Subscriptions) return len(c.Subscriptions)
} }
// Get the total of users. // Get the total of users.
func (c *Channel) TotalUsers() int { func (c *channel) TotalUsers() int {
total := make(map[string]int) total := make(map[string]int)
for _, s := range c.Subscriptions { for _, s := range c.Subscriptions {
@@ -65,7 +65,7 @@ func (c *Channel) TotalUsers() int {
} }
// Add a new subscriber to the channel // Add a new subscriber to the channel
func (c *Channel) Subscribe(a *App, conn *Connection, channelData string) error { func (c *channel) Subscribe(a *app, conn *connection, channelData string) error {
log.Infof("Subscribing %s to channel %s", conn.SocketID, c.ChannelID) log.Infof("Subscribing %s to channel %s", conn.SocketID, c.ChannelID)
c.Lock() c.Lock()
@@ -105,7 +105,7 @@ func (c *Channel) Subscribe(a *App, conn *Connection, channelData string) error
a.TriggerMemberAddedHook(c, subscription) a.TriggerMemberAddedHook(c, subscription)
// pusher_internal:subscription_succeeded // pusher_internal:subscription_succeeded
data := make(map[string]SubscriptionSucceeedEventPresenceData) data := make(map[string]subscriptionSucceeedEventPresenceData)
data["presence"] = newSubscriptionSucceedEventPresenceData(c) data["presence"] = newSubscriptionSucceedEventPresenceData(c)
js, err = json.Marshal(data) js, err = json.Marshal(data)
@@ -129,14 +129,14 @@ func (c *Channel) Subscribe(a *App, conn *Connection, channelData string) error
} }
// IsSubscribed check if the user is subscribed // IsSubscribed check if the user is subscribed
func (c *Channel) IsSubscribed(conn *Connection) bool { func (c *channel) IsSubscribed(conn *connection) bool {
_, exists := c.Subscriptions[conn.SocketID] _, exists := c.Subscriptions[conn.SocketID]
return exists return exists
} }
// Remove the subscriber from the channel // Remove the subscriber from the channel
// It destroy the channel if the channels does not have any subscribers. // It destroy the channel if the channels does not have any subscribers.
func (c *Channel) Unsubscribe(a *App, conn *Connection) error { func (c *channel) Unsubscribe(a *app, conn *connection) error {
log.Infof("Unsubscribing %s from channel %s", conn.SocketID, c.ChannelID) log.Infof("Unsubscribing %s from channel %s", conn.SocketID, c.ChannelID)
c.Lock() c.Lock()
@@ -169,14 +169,14 @@ func (c *Channel) Unsubscribe(a *App, conn *Connection) error {
} }
// Create a new Channel // Create a new Channel
func newChannel(channelID string) *Channel { func newChannel(channelID string) *channel {
log.Infof("Creating a new channel: %s", channelID) log.Infof("Creating a new channel: %s", channelID)
return &Channel{ChannelID: channelID, CreatedAt: time.Now(), Subscriptions: make(map[string]*Subscription)} return &channel{ChannelID: channelID, CreatedAt: time.Now(), Subscriptions: make(map[string]*subscription)}
} }
// Publish a MemberAddedEvent to all subscriptions // Publish a MemberAddedEvent to all subscriptions
func (c *Channel) PublishMemberAddedEvent(a *App, data string, subscription *Subscription) { func (c *channel) PublishMemberAddedEvent(a *app, data string, subscription *subscription) {
for _, subs := range c.Subscriptions { for _, subs := range c.Subscriptions {
if subs != subscription { if subs != subscription {
subs.Connection.Publish(newMemberAddedEvent(c.ChannelID, data)) subs.Connection.Publish(newMemberAddedEvent(c.ChannelID, data))
@@ -185,7 +185,7 @@ func (c *Channel) PublishMemberAddedEvent(a *App, data string, subscription *Sub
} }
// Publish a MemberRemovedEvent to all subscriptions // Publish a MemberRemovedEvent to all subscriptions
func (c *Channel) PublishMemberRemovedEvent(a *App, subscription *Subscription) { func (c *channel) PublishMemberRemovedEvent(a *app, subscription *subscription) {
for _, subs := range c.Subscriptions { for _, subs := range c.Subscriptions {
if subs != subscription { if subs != subscription {
subs.Connection.Publish(newMemberRemovedEvent(c.ChannelID, subscription)) subs.Connection.Publish(newMemberRemovedEvent(c.ChannelID, subscription))
@@ -194,7 +194,7 @@ func (c *Channel) PublishMemberRemovedEvent(a *App, subscription *Subscription)
} }
// Publish messages to all Subscribers // Publish messages to all Subscribers
func (c *Channel) Publish(a *App, event RawEvent, ignore string) error { func (c *channel) Publish(a *app, event rawEvent, ignore string) error {
b, err := event.Data.MarshalJSON() b, err := event.Data.MarshalJSON()
if err != nil { if err != nil {
+14 -14
View File
@@ -10,44 +10,44 @@ import (
) )
// The config file // The config file
type ConfigFile struct { type configFile struct {
Host string // The host, eg: :8080 will start on 0.0.0.0:8080 Host string // The host, eg: :8080 will start on 0.0.0.0:8080
Expvar bool Expvar bool
User string User string
Password string Password string
Apps []*App Apps []*app
} }
// Error for App not found // Error for App not found
var AppNotFoundError = errors.New("App not found") var AppNotFoundError = errors.New("App not found")
// Initialize Apps // Initialize Apps
func (c *ConfigFile) Init() { func (c *configFile) Init() {
for _, app := range c.Apps { for _, app := range c.Apps {
app.Init() app.Init()
} }
} }
func (c *ConfigFile) WasProvidedUserAndPassword() bool { func (c *configFile) WasProvidedUserAndPassword() bool {
return len(strings.TrimSpace(c.User)) > 0 && len(strings.TrimSpace(c.Password)) > 0 return len(strings.TrimSpace(c.User)) > 0 && len(strings.TrimSpace(c.Password)) > 0
} }
// Returns an App with by appID // Returns an App with by appID
func (c *ConfigFile) GetAppByAppID(appID string) (*App, error) { func (c *configFile) GetAppByAppID(appID string) (*app, error) {
for _, app := range c.Apps { for _, a := range c.Apps {
if app.AppID == appID { if a.AppID == appID {
return app, nil return a, nil
} }
} }
return &App{}, AppNotFoundError return &app{}, AppNotFoundError
} }
// Returns an App with by key // Returns an App with by key
func (c *ConfigFile) GetAppByKey(key string) (*App, error) { func (c *configFile) GetAppByKey(key string) (*app, error) {
for _, app := range c.Apps { for _, a := range c.Apps {
if app.Key == key { if a.Key == key {
return app, nil return a, nil
} }
} }
return &App{}, AppNotFoundError return &app{}, AppNotFoundError
} }
+4 -4
View File
@@ -10,20 +10,20 @@ import (
) )
// An User Connection // An User Connection
type Connection struct { type connection struct {
SocketID string SocketID string
Socket *websocket.Conn Socket *websocket.Conn
} }
// Create a new Subscriber // Create a new Subscriber
func newConnection(socketID string, s *websocket.Conn) *Connection { func newConnection(socketID string, s *websocket.Conn) *connection {
log.Infof("Creating a new Subscriber %+v", socketID) log.Infof("Creating a new Subscriber %+v", socketID)
return &Connection{SocketID: socketID, Socket: s} return &connection{SocketID: socketID, Socket: s}
} }
// Publish the message to websocket atached to this client // Publish the message to websocket atached to this client
func (conn *Connection) Publish(m interface{}) { func (conn *connection) Publish(m interface{}) {
go func() { go func() {
if err := conn.Socket.WriteJSON(m); err != nil { if err := conn.Socket.WriteJSON(m); err != nil {
log.Errorf("Error publishing message to connection %+v, %s", conn, err) log.Errorf("Error publishing message to connection %+v, %s", conn, err)
+44 -44
View File
@@ -5,114 +5,114 @@
package ipe package ipe
// Base interface // Base interface
type WebsocketError interface { type websocketError interface {
GetCode() int GetCode() int
GetMsg() string GetMsg() string
} }
// Base struct // Base struct
type BaseWebsocketError struct { type baseWebsocketError struct {
Code int Code int
Msg string Msg string
} }
func (e BaseWebsocketError) GetCode() int { func (e baseWebsocketError) GetCode() int {
return e.Code return e.Code
} }
func (e BaseWebsocketError) GetMsg() string { func (e baseWebsocketError) GetMsg() string {
return e.Msg return e.Msg
} }
// Unsupprted protocol version // Unsupprted protocol version
type UnsupportedProtocolVersionError struct { type unsupportedProtocolVersionError struct {
BaseWebsocketError baseWebsocketError
} }
func newUnsupportedProtocolVersionError() UnsupportedProtocolVersionError { func newUnsupportedProtocolVersionError() unsupportedProtocolVersionError {
return UnsupportedProtocolVersionError{ return unsupportedProtocolVersionError{
BaseWebsocketError{Code: UNSUPPORTED_PROTOCOL_VERSION, Msg: "Unsupported protocol version"}, baseWebsocketError{Code: UNSUPPORTED_PROTOCOL_VERSION, Msg: "Unsupported protocol version"},
} }
} }
// The application does not exists // The application does not exists
// See the configuration file // See the configuration file
type ApplicationDoesNotExistsError struct { type applicationDoesNotExistsError struct {
BaseWebsocketError baseWebsocketError
} }
func newApplicationDoesNotExistsError() ApplicationDoesNotExistsError { func newApplicationDoesNotExistsError() applicationDoesNotExistsError {
return ApplicationDoesNotExistsError{ return applicationDoesNotExistsError{
BaseWebsocketError{Code: APPLICATION_DOES_NOT_EXISTS, Msg: "Could not found an app with the given key"}, baseWebsocketError{Code: APPLICATION_DOES_NOT_EXISTS, Msg: "Could not found an app with the given key"},
} }
} }
// The user did not send the protocol version // The user did not send the protocol version
type NoProtocolVersionSuppliedError struct { type noProtocolVersionSuppliedError struct {
BaseWebsocketError baseWebsocketError
} }
func newNoProtocolVersionSuppliedError() NoProtocolVersionSuppliedError { func newNoProtocolVersionSuppliedError() noProtocolVersionSuppliedError {
return NoProtocolVersionSuppliedError{ return noProtocolVersionSuppliedError{
BaseWebsocketError{Code: NO_PROTOCOL_VERSION_SUPPLIED, Msg: "No protocol version supplied"}, baseWebsocketError{Code: NO_PROTOCOL_VERSION_SUPPLIED, Msg: "No protocol version supplied"},
} }
} }
// When the application is disabled. // When the application is disabled.
// See the configuration file // See the configuration file
type ApplicationDisabledError struct { type applicationDisabledError struct {
BaseWebsocketError baseWebsocketError
} }
func newApplicationDisabledError() NoProtocolVersionSuppliedError { func newApplicationDisabledError() noProtocolVersionSuppliedError {
return NoProtocolVersionSuppliedError{ return noProtocolVersionSuppliedError{
BaseWebsocketError{Code: APPLICATION_DISABLED, Msg: "Application disabled"}, baseWebsocketError{Code: APPLICATION_DISABLED, Msg: "Application disabled"},
} }
} }
// When the application only accepts SSL connections // When the application only accepts SSL connections
type ApplicationOnlyAccepsSSLError struct { type applicationOnlyAccepsSSLError struct {
BaseWebsocketError baseWebsocketError
} }
func newApplicationOnlyAccepsSSLError() ApplicationOnlyAccepsSSLError { func newApplicationOnlyAccepsSSLError() applicationOnlyAccepsSSLError {
return ApplicationOnlyAccepsSSLError{ return applicationOnlyAccepsSSLError{
BaseWebsocketError{Code: APPLICATION_ONLY_ACCEPTS_SSL, Msg: "Application only accepts SSL connections, reconnect using wss://"}, baseWebsocketError{Code: APPLICATION_ONLY_ACCEPTS_SSL, Msg: "Application only accepts SSL connections, reconnect using wss://"},
} }
} }
// When the user send an invalid version // When the user send an invalid version
type InvalidVersionStringFormatError struct { type invalidVersionStringFormatError struct {
BaseWebsocketError baseWebsocketError
} }
func newInvalidVersionStringFormatError() InvalidVersionStringFormatError { func newInvalidVersionStringFormatError() invalidVersionStringFormatError {
return InvalidVersionStringFormatError{ return invalidVersionStringFormatError{
BaseWebsocketError{Code: INVALID_VERSION_STRING_FORMAT, Msg: "Invalid version string format"}, baseWebsocketError{Code: INVALID_VERSION_STRING_FORMAT, Msg: "Invalid version string format"},
} }
} }
// Used when the error was internal // Used when the error was internal
// * Decoding json // * Decoding json
// * Writing to output // * Writing to output
type GenericReconnectImmediatelyError struct { type genericReconnectImmediatelyError struct {
BaseWebsocketError baseWebsocketError
} }
func newGenericReconnectImmediatelyError() GenericReconnectImmediatelyError { func newGenericReconnectImmediatelyError() genericReconnectImmediatelyError {
return GenericReconnectImmediatelyError{ return genericReconnectImmediatelyError{
BaseWebsocketError{Code: GENERIC_RECONNECT_IMMEDIATELY, Msg: "Generic reconnect immediately"}, baseWebsocketError{Code: GENERIC_RECONNECT_IMMEDIATELY, Msg: "Generic reconnect immediately"},
} }
} }
// When pusher wants to send an Generic error, it only send the message, the code become nil // When pusher wants to send an Generic error, it only send the message, the code become nil
// Currently I do not know how to send nil, so I send GENERIC_ERROR // Currently I do not know how to send nil, so I send GENERIC_ERROR
type GenericError struct { type genericError struct {
BaseWebsocketError baseWebsocketError
} }
func newGenericError(msg string) GenericError { func newGenericError(msg string) genericError {
return GenericError{ return genericError{
BaseWebsocketError{Code: GENERIC_ERROR, Msg: msg}, baseWebsocketError{Code: GENERIC_ERROR, Msg: msg},
} }
} }
+42 -42
View File
@@ -18,24 +18,24 @@ import (
// "channelData": "extra data" // "channelData": "extra data"
// } // }
// } // }
type SubscribeEventData struct { type subscribeEventData struct {
Channel string `json:"channel"` Channel string `json:"channel"`
Auth string `json:"auth,omitempty"` Auth string `json:"auth,omitempty"`
ChannelData string `json:"channel_data,omitempty"` ChannelData string `json:"channel_data,omitempty"`
} }
type SubscribeEvent struct { type subscribeEvent struct {
Event string `json:"event"` Event string `json:"event"`
Data SubscribeEventData `json:"data"` Data subscribeEventData `json:"data"`
} }
// Create a new subscribe event with the specified channel and data // Create a new subscribe event with the specified channel and data
func newSubscribeEvent(channel, auth, channelData string) SubscribeEvent { func newSubscribeEvent(channel, auth, channelData string) subscribeEvent {
data := SubscribeEventData{Channel: channel, Auth: auth, ChannelData: channelData} data := subscribeEventData{Channel: channel, Auth: auth, ChannelData: channelData}
return SubscribeEvent{Event: "pusher:subscribe", Data: data} return subscribeEvent{Event: "pusher:subscribe", Data: data}
} }
type UnsubscribeEventData struct { type unsubscribeEventData struct {
Channel string `json:"channel"` Channel string `json:"channel"`
} }
@@ -45,30 +45,30 @@ type UnsubscribeEventData struct {
// "channel": "The channel" // "channel": "The channel"
// } // }
// } // }
type UnsubscribeEvent struct { type unsubscribeEvent struct {
Event string `json:"event"` Event string `json:"event"`
Data UnsubscribeEventData `json:"data"` Data unsubscribeEventData `json:"data"`
} }
// Create a new unsubscribe event for the specified channel // Create a new unsubscribe event for the specified channel
func newUnsubscribeEvent(channel string) UnsubscribeEvent { func newUnsubscribeEvent(channel string) unsubscribeEvent {
data := UnsubscribeEventData{Channel: channel} data := unsubscribeEventData{Channel: channel}
return UnsubscribeEvent{Event: "pusher:unsubscribe", Data: data} return unsubscribeEvent{Event: "pusher:unsubscribe", Data: data}
} }
// { // {
// "event": "pusher_internal:subscription_succeeded", // "event": "pusher_internal:subscription_succeeded",
// "channel": "the channel" // "channel": "the channel"
// } // }
type SubscriptionSucceededEvent struct { type subscriptionSucceededEvent struct {
Event string `json:"event"` Event string `json:"event"`
Channel string `json:"channel"` Channel string `json:"channel"`
Data string `json:"data"` Data string `json:"data"`
} }
// Create a new subscription succeed event for the specified channel // Create a new subscription succeed event for the specified channel
func newSubscriptionSucceededEvent(channel, data string) SubscriptionSucceededEvent { func newSubscriptionSucceededEvent(channel, data string) subscriptionSucceededEvent {
return SubscriptionSucceededEvent{Event: "pusher_internal:subscription_succeeded", Channel: channel, Data: data} return subscriptionSucceededEvent{Event: "pusher_internal:subscription_succeeded", Channel: channel, Data: data}
} }
// Data Subscription Succeed // Data Subscription Succeed
@@ -89,14 +89,14 @@ func newSubscriptionSucceededEvent(channel, data string) SubscriptionSucceededEv
// \"count\": 2 // \"count\": 2
// } // }
// }" // }"
type SubscriptionSucceeedEventPresenceData struct { type subscriptionSucceeedEventPresenceData struct {
Ids []string `json:"ids"` Ids []string `json:"ids"`
Hash map[string]interface{} `json:"hash"` Hash map[string]interface{} `json:"hash"`
Count int `json:"count"` Count int `json:"count"`
} }
func newSubscriptionSucceedEventPresenceData(c *Channel) SubscriptionSucceeedEventPresenceData { func newSubscriptionSucceedEventPresenceData(c *channel) subscriptionSucceeedEventPresenceData {
event := SubscriptionSucceeedEventPresenceData{} event := subscriptionSucceeedEventPresenceData{}
var ids []string var ids []string
hash := make(map[string]interface{}, c.TotalSubscriptions()) hash := make(map[string]interface{}, c.TotalSubscriptions())
@@ -121,28 +121,28 @@ func newSubscriptionSucceedEventPresenceData(c *Channel) SubscriptionSucceeedEve
// "event": "pusher:pong", // "event": "pusher:pong",
// "data": {} // "data": {}
// } // }
type PongEvent struct { type pongEvent struct {
Event string `json:"event"` Event string `json:"event"`
Data string `json:"data"` Data string `json:"data"`
} }
// Create a new pong event // Create a new pong event
func newPongEvent() PongEvent { func newPongEvent() pongEvent {
return PongEvent{Event: "pusher:pong", Data: "{}"} return pongEvent{Event: "pusher:pong", Data: "{}"}
} }
// { // {
// "event": "pusher:ping", // "event": "pusher:ping",
// "data": {} // "data": {}
// } // }
type PingEvent struct { type pingEvent struct {
Event string `json:"event"` Event string `json:"event"`
Data string `json:"data"` Data string `json:"data"`
} }
// Create a new ping event // Create a new ping event
func newPingEvent() PingEvent { func newPingEvent() pingEvent {
return PingEvent{Event: "pusher:ping", Data: "{}"} return pingEvent{Event: "pusher:ping", Data: "{}"}
} }
// { // {
@@ -152,7 +152,7 @@ func newPingEvent() PingEvent {
// "code": 4000 // "code": 4000
// } // }
// } // }
type ErrorEvent struct { type errorEvent struct {
Event string `json:"event"` Event string `json:"event"`
Data interface{} `json:"data"` Data interface{} `json:"data"`
} }
@@ -161,7 +161,7 @@ type ErrorEvent struct {
// Pusher protocol is very strange in some parts // Pusher protocol is very strange in some parts
// It send null in some errors. // It send null in some errors.
// So I created this GENERIC_ERROR thing, just to verify if the json must have null on the error code // So I created this GENERIC_ERROR thing, just to verify if the json must have null on the error code
func newErrorEvent(code int, message string) ErrorEvent { func newErrorEvent(code int, message string) errorEvent {
var data interface{} var data interface{}
if code == GENERIC_ERROR { if code == GENERIC_ERROR {
@@ -182,7 +182,7 @@ func newErrorEvent(code int, message string) ErrorEvent {
} }
} }
return ErrorEvent{Event: "pusher:error", Data: data} return errorEvent{Event: "pusher:error", Data: data}
} }
// { // {
@@ -192,19 +192,19 @@ func newErrorEvent(code int, message string) ErrorEvent {
// "activity_timeout" : 120 // "activity_timeout" : 120
// } // }
// } // }
type ConnectionEstablishedEventData struct { type connectionEstablishedEventData struct {
SocketId string `json:"socket_id"` SocketId string `json:"socket_id"`
ActivityTimeout int `json:"activity_timeout"` ActivityTimeout int `json:"activity_timeout"`
} }
type ConnectionEstablishedEvent struct { type connectionEstablishedEvent struct {
Event string `json:"event"` Event string `json:"event"`
Data string `json:"data"` Data string `json:"data"`
} }
// Create a new connection established event using the specified socketId // Create a new connection established event using the specified socketId
func newConnectionEstablishedEvent(socketId string) ConnectionEstablishedEvent { func newConnectionEstablishedEvent(socketId string) connectionEstablishedEvent {
data := ConnectionEstablishedEventData{SocketId: socketId, ActivityTimeout: 120} data := connectionEstablishedEventData{SocketId: socketId, ActivityTimeout: 120}
b, err := json.Marshal(data) b, err := json.Marshal(data)
@@ -212,7 +212,7 @@ func newConnectionEstablishedEvent(socketId string) ConnectionEstablishedEvent {
panic("events: Could not Marshal json ConnectionEstablishedEvent") panic("events: Could not Marshal json ConnectionEstablishedEvent")
} }
return ConnectionEstablishedEvent{Event: "pusher:connection_established", Data: string(b)} return connectionEstablishedEvent{Event: "pusher:connection_established", Data: string(b)}
} }
// { // {
@@ -220,14 +220,14 @@ func newConnectionEstablishedEvent(socketId string) ConnectionEstablishedEvent {
// "channel": "presence-example-channel", // "channel": "presence-example-channel",
// "data": String // "data": String
// } // }
type MemberAddedEvent struct { type memberAddedEvent struct {
Event string `json:"event"` Event string `json:"event"`
Channel string `json:"channel"` Channel string `json:"channel"`
Data string `json:"data"` Data string `json:"data"`
} }
func newMemberAddedEvent(channel, data string) MemberAddedEvent { func newMemberAddedEvent(channel, data string) memberAddedEvent {
return MemberAddedEvent{Event: "pusher_internal:member_added", Channel: channel, Data: data} return memberAddedEvent{Event: "pusher_internal:member_added", Channel: channel, Data: data}
} }
// { // {
@@ -235,13 +235,13 @@ func newMemberAddedEvent(channel, data string) MemberAddedEvent {
// "channel": "presence-example-channel", // "channel": "presence-example-channel",
// "data": String // "data": String
// } // }
type MemberRemovedEvent struct { type memberRemovedEvent struct {
Event string `json:"event"` Event string `json:"event"`
Channel string `json:"channel"` Channel string `json:"channel"`
Data string `json:"data"` Data string `json:"data"`
} }
func newMemberRemovedEvent(channel string, s *Subscription) MemberRemovedEvent { func newMemberRemovedEvent(channel string, s *subscription) memberRemovedEvent {
data, err := json.Marshal(struct { data, err := json.Marshal(struct {
UserID string `json:"user_id"` UserID string `json:"user_id"`
}{ }{
@@ -252,7 +252,7 @@ func newMemberRemovedEvent(channel string, s *Subscription) MemberRemovedEvent {
log.Error(err) log.Error(err)
} }
return MemberRemovedEvent{Event: "pusher_internal:member_removed", Channel: channel, Data: string(data)} return memberRemovedEvent{Event: "pusher_internal:member_removed", Channel: channel, Data: string(data)}
} }
// { // {
@@ -260,19 +260,19 @@ func newMemberRemovedEvent(channel string, s *Subscription) MemberRemovedEvent {
// "channel": "The channel", // "channel": "The channel",
// "data": {} // "data": {}
// } // }
type RawEvent struct { type rawEvent struct {
Event string `json:"event"` Event string `json:"event"`
Channel string `json:"channel"` Channel string `json:"channel"`
Data json.RawMessage `json:"data"` Data json.RawMessage `json:"data"`
} }
type ResponseEvent struct { type responseEvent struct {
Event string `json:"event"` Event string `json:"event"`
Channel string `json:"channel"` Channel string `json:"channel"`
Data interface{} `json:"data"` Data interface{} `json:"data"`
} }
// The response event that is broadcasted to the client sockets // The response event that is broadcasted to the client sockets
func newResponseEvent(name, channel string, data interface{}) ResponseEvent { func newResponseEvent(name, channel string, data interface{}) responseEvent {
return ResponseEvent{Event: name, Channel: channel, Data: data} return responseEvent{Event: name, Channel: channel, Data: data}
} }
+2 -2
View File
@@ -11,7 +11,7 @@ import (
) )
// Conf holds the global configuration state // Conf holds the global configuration state
var Conf ConfigFile var Conf configFile
// Start Parse the configuration file and starts the ipe server // Start Parse the configuration file and starts the ipe server
func Start(configfile string) error { func Start(configfile string) error {
@@ -26,7 +26,7 @@ func Start(configfile string) error {
} }
Conf.Init() Conf.Init()
router := NewRouter() router := newRouter()
if err := http.ListenAndServe(Conf.Host, router); err != nil { if err := http.ListenAndServe(Conf.Host, router); err != nil {
return err return err
+1 -1
View File
@@ -68,7 +68,7 @@ func postEvents(w http.ResponseWriter, r *http.Request) {
for _, c := range input.Channels { for _, c := range input.Channels {
channel := app.FindOrCreateChannelByChannelID(c) channel := app.FindOrCreateChannelByChannelID(c)
app.Publish(channel, RawEvent{Event: input.Name, Channel: c, Data: input.Data}, input.SocketID) app.Publish(channel, rawEvent{Event: input.Name, Channel: c, Data: input.Data}, input.SocketID)
} }
w.Header().Set("Content-Type", "application/json;charset=UTF-8") w.Header().Set("Content-Type", "application/json;charset=UTF-8")
+1 -1
View File
@@ -14,7 +14,7 @@ import (
// NewRouter is a function that returns a new configured Router // NewRouter is a function that returns a new configured Router
// It add the necessary middlewares // It add the necessary middlewares
func NewRouter() *mux.Router { func newRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true) router := mux.NewRouter().StrictSlash(true)
if Conf.Expvar { if Conf.Expvar {
+7 -9
View File
@@ -9,7 +9,7 @@ import (
) )
// A route // A route
type Route struct { type route struct {
Name string Name string
Method string Method string
Pattern string Pattern string
@@ -17,38 +17,36 @@ type Route struct {
RequiresRestAuth bool RequiresRestAuth bool
} }
type Routes []Route var routes = []route{
route{
var routes = Routes{
Route{
"PostEvents", "PostEvents",
"POST", "POST",
"/apps/{app_id}/events", "/apps/{app_id}/events",
postEvents, postEvents,
true, true,
}, },
Route{ route{
"GetChannels", "GetChannels",
"GET", "GET",
"/apps/{app_id}/channels", "/apps/{app_id}/channels",
getChannels, getChannels,
true, true,
}, },
Route{ route{
"GetChannel", "GetChannel",
"GET", "GET",
"/apps/{app_id}/channels/{channel_name}", "/apps/{app_id}/channels/{channel_name}",
getChannel, getChannel,
true, true,
}, },
Route{ route{
"GetChannelUsers", "GetChannelUsers",
"GET", "GET",
"/apps/{app_id}/channels/{channel_name}/users", "/apps/{app_id}/channels/{channel_name}/users",
getChannelUsers, getChannelUsers,
true, true,
}, },
Route{ route{
"Websocket", "Websocket",
"GET", "GET",
"/app/{key}", "/app/{key}",
+4 -4
View File
@@ -5,13 +5,13 @@
package ipe package ipe
// A Channel Subscription // A Channel Subscription
type Subscription struct { type subscription struct {
Connection *Connection Connection *connection
Id string Id string
Data string Data string
} }
// Create a new Subscription // Create a new Subscription
func newSubscription(conn *Connection, data string) *Subscription { func newSubscription(conn *connection, data string) *subscription {
return &Subscription{Connection: conn, Data: data} return &subscription{Connection: conn, Data: data}
} }
+25 -25
View File
@@ -33,12 +33,12 @@ import (
// //
// X-Pusher-Key: A Pusher app may have multiple tokens. The oldest active token will be used, identified by this key. // X-Pusher-Key: A Pusher app may have multiple tokens. The oldest active token will be used, identified by this key.
// X-Pusher-Signature: A HMAC SHA256 hex digest formed by signing the POST payload (body) with the tokens secret. // X-Pusher-Signature: A HMAC SHA256 hex digest formed by signing the POST payload (body) with the tokens secret.
type WebHook struct { type webHook struct {
TimeMs int64 `json:"time_ms"` TimeMs int64 `json:"time_ms"`
Events []HookEvent `json:"events"` Events []hookEvent `json:"events"`
} }
type HookEvent struct { type hookEvent struct {
Name string `json:"name"` Name string `json:"name"`
Channel string `json:"channel"` Channel string `json:"channel"`
Event string `json:"event,omitempty"` Event string `json:"event,omitempty"`
@@ -47,36 +47,36 @@ type HookEvent struct {
UserId string `json:"user_id,omitempty"` UserId string `json:"user_id,omitempty"`
} }
func newChannelOcuppiedHook(channel *Channel) HookEvent { func newChannelOcuppiedHook(channel *channel) hookEvent {
return HookEvent{Name: "channel_occupied", Channel: channel.ChannelID} return hookEvent{Name: "channel_occupied", Channel: channel.ChannelID}
} }
func newChannelVacatedHook(channel *Channel) HookEvent { func newChannelVacatedHook(channel *channel) hookEvent {
return HookEvent{Name: "channel_vacated", Channel: channel.ChannelID} return hookEvent{Name: "channel_vacated", Channel: channel.ChannelID}
} }
func newMemberAddedHook(channel *Channel, s *Subscription) HookEvent { func newMemberAddedHook(channel *channel, s *subscription) hookEvent {
return HookEvent{Name: "member_added", Channel: channel.ChannelID, UserId: s.Id} return hookEvent{Name: "member_added", Channel: channel.ChannelID, UserId: s.Id}
} }
func newMemberRemovedHook(channel *Channel, s *Subscription) HookEvent { func newMemberRemovedHook(channel *channel, s *subscription) hookEvent {
return HookEvent{Name: "member_removed", Channel: channel.ChannelID, UserId: s.Id} return hookEvent{Name: "member_removed", Channel: channel.ChannelID, UserId: s.Id}
} }
func newClientHook(channel *Channel, s *Subscription, event string, data interface{}) HookEvent { func newClientHook(channel *channel, s *subscription, event string, data interface{}) hookEvent {
return HookEvent{Name: "client_event", Channel: channel.ChannelID, Event: event, Data: data, SocketID: s.Connection.SocketID} return hookEvent{Name: "client_event", Channel: channel.ChannelID, Event: event, Data: data, SocketID: s.Connection.SocketID}
} }
// channel_occupied // channel_occupied
// { "name": "channel_occupied", "channel": "test_channel" } // { "name": "channel_occupied", "channel": "test_channel" }
func (a *App) TriggerChannelOccupiedHook(c *Channel) { func (a *app) TriggerChannelOccupiedHook(c *channel) {
event := newChannelOcuppiedHook(c) event := newChannelOcuppiedHook(c)
triggerHook(event.Name, a, c, event) triggerHook(event.Name, a, c, event)
} }
// channel_vacated // channel_vacated
// { "name": "channel_vacated", "channel": "test_channel" } // { "name": "channel_vacated", "channel": "test_channel" }
func (a *App) TriggerChannelVacatedHook(c *Channel) { func (a *app) TriggerChannelVacatedHook(c *channel) {
event := newChannelVacatedHook(c) event := newChannelVacatedHook(c)
triggerHook(event.Name, a, c, event) triggerHook(event.Name, a, c, event)
} }
@@ -89,7 +89,7 @@ func (a *App) TriggerChannelVacatedHook(c *Channel) {
// "socket_id": "socket_id of the sending socket", // "socket_id": "socket_id of the sending socket",
// "user_id": "user_id associated with the sending socket" # Only for presence channels // "user_id": "user_id associated with the sending socket" # Only for presence channels
// } // }
func (a *App) TriggerClientEventHook(c *Channel, s *Subscription, client_event string, data interface{}) { func (a *app) TriggerClientEventHook(c *channel, s *subscription, client_event string, data interface{}) {
event := newClientHook(c, s, client_event, data) event := newClientHook(c, s, client_event, data)
if c.IsPresence() { if c.IsPresence() {
@@ -104,7 +104,7 @@ func (a *App) TriggerClientEventHook(c *Channel, s *Subscription, client_event s
// "channel": "presence-your_channel_name", // "channel": "presence-your_channel_name",
// "user_id": "a_user_id" // "user_id": "a_user_id"
// } // }
func (a *App) TriggerMemberAddedHook(c *Channel, s *Subscription) { func (a *app) TriggerMemberAddedHook(c *channel, s *subscription) {
event := newMemberAddedHook(c, s) event := newMemberAddedHook(c, s)
triggerHook(event.Name, a, c, event) triggerHook(event.Name, a, c, event)
} }
@@ -114,21 +114,21 @@ func (a *App) TriggerMemberAddedHook(c *Channel, s *Subscription) {
// "channel": "presence-your_channel_name", // "channel": "presence-your_channel_name",
// "user_id": "a_user_id" // "user_id": "a_user_id"
// } // }
func (a *App) TriggerMemberRemovedHook(c *Channel, s *Subscription) { func (a *app) TriggerMemberRemovedHook(c *channel, s *subscription) {
event := newMemberRemovedHook(c, s) event := newMemberRemovedHook(c, s)
triggerHook(event.Name, a, c, event) triggerHook(event.Name, a, c, event)
} }
func triggerHook(name string, app *App, c *Channel, event HookEvent) { func triggerHook(name string, a *app, c *channel, event hookEvent) {
if !app.WebHooks { if !a.WebHooks {
log.Infof("Webhooks are not enabled for app: %s", app.Name) log.Infof("Webhooks are not enabled for app: %s", a.Name)
return return
} }
go func() { go func() {
log.Infof("Triggering %s event", name) log.Infof("Triggering %s event", name)
hook := WebHook{TimeMs: time.Now().Unix()} hook := webHook{TimeMs: time.Now().Unix()}
hook.Events = append(hook.Events, event) hook.Events = append(hook.Events, event)
@@ -144,15 +144,15 @@ func triggerHook(name string, app *App, c *Channel, event HookEvent) {
var req *http.Request var req *http.Request
req, err = http.NewRequest("POST", app.URLWebHook, bytes.NewReader(js)) req, err = http.NewRequest("POST", a.URLWebHook, bytes.NewReader(js))
if err != nil { if err != nil {
log.Errorf("Error creating request: %+v", err) log.Errorf("Error creating request: %+v", err)
return return
} }
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Pusher-Key", app.Key) req.Header.Set("X-Pusher-Key", a.Key)
req.Header.Set("X-Pusher-Signature", utils.HashMAC(js, []byte(app.Secret))) req.Header.Set("X-Pusher-Signature", utils.HashMAC(js, []byte(a.Secret)))
log.V(1).Infof("%+v", req.Header) log.V(1).Infof("%+v", req.Header)
log.V(1).Infof("%+v", string(js)) log.V(1).Infof("%+v", string(js))
+7 -7
View File
@@ -26,7 +26,7 @@ var upgrader = websocket.Upgrader{
} }
// Handle open Subscriber. // Handle open Subscriber.
func onOpen(conn *websocket.Conn, w http.ResponseWriter, r *http.Request, sessionID string, app *App) WebsocketError { func onOpen(conn *websocket.Conn, w http.ResponseWriter, r *http.Request, sessionID string, app *app) websocketError {
params := r.URL.Query() params := r.URL.Query()
p := params.Get("protocol") p := params.Get("protocol")
@@ -62,7 +62,7 @@ func onOpen(conn *websocket.Conn, w http.ResponseWriter, r *http.Request, sessio
} }
// Handle the close event // Handle the close event
func onClose(sessionID string, app *App) { func onClose(sessionID string, app *app) {
app.Disconnect(sessionID) app.Disconnect(sessionID)
} }
@@ -70,7 +70,7 @@ func onClose(sessionID string, app *App) {
// //
// If there is an unrecoverable error then break the loop, // If there is an unrecoverable error then break the loop,
// otherwise just keep going. // otherwise just keep going.
func onMessage(conn *websocket.Conn, w http.ResponseWriter, r *http.Request, sessionID string, app *App) { func onMessage(conn *websocket.Conn, w http.ResponseWriter, r *http.Request, sessionID string, app *app) {
var event struct { var event struct {
Event string `json:"event"` Event string `json:"event"`
} }
@@ -102,7 +102,7 @@ func onMessage(conn *websocket.Conn, w http.ResponseWriter, r *http.Request, ses
emitWSError(newGenericReconnectImmediatelyError(), conn) emitWSError(newGenericReconnectImmediatelyError(), conn)
} }
case "pusher:subscribe": case "pusher:subscribe":
subscribeEvent := SubscribeEvent{} subscribeEvent := subscribeEvent{}
if err := json.Unmarshal(message, &subscribeEvent); err != nil { if err := json.Unmarshal(message, &subscribeEvent); err != nil {
emitWSError(newGenericReconnectImmediatelyError(), conn) emitWSError(newGenericReconnectImmediatelyError(), conn)
@@ -142,7 +142,7 @@ func onMessage(conn *websocket.Conn, w http.ResponseWriter, r *http.Request, ses
emitWSError(newGenericReconnectImmediatelyError(), conn) emitWSError(newGenericReconnectImmediatelyError(), conn)
} }
case "pusher:unsubscribe": case "pusher:unsubscribe":
unsubscribeEvent := UnsubscribeEvent{} unsubscribeEvent := unsubscribeEvent{}
if err := json.Unmarshal(message, &unsubscribeEvent); err != nil { if err := json.Unmarshal(message, &unsubscribeEvent); err != nil {
emitWSError(newGenericReconnectImmediatelyError(), conn) emitWSError(newGenericReconnectImmediatelyError(), conn)
@@ -171,7 +171,7 @@ func onMessage(conn *websocket.Conn, w http.ResponseWriter, r *http.Request, ses
emitWSError(newGenericError("To send client events, you must enable this feature in the Settings."), conn) emitWSError(newGenericError("To send client events, you must enable this feature in the Settings."), conn)
} }
clientEvent := RawEvent{} clientEvent := rawEvent{}
if err := json.Unmarshal(message, &clientEvent); err != nil { if err := json.Unmarshal(message, &clientEvent); err != nil {
log.Error(err) log.Error(err)
@@ -237,7 +237,7 @@ func wsHandler(w http.ResponseWriter, r *http.Request) {
} }
// Emit an Websocket ErrorEvent // Emit an Websocket ErrorEvent
func emitWSError(err WebsocketError, conn *websocket.Conn) { func emitWSError(err websocketError, conn *websocket.Conn) {
event := newErrorEvent(err.GetCode(), err.GetMsg()) event := newErrorEvent(err.GetCode(), err.GetMsg())