...

Package group

import "github.com/Diarkis/diarkis/group"
Overview
Index

Overview ▾

Package group ▷

Group - Distributed Group Communication Module

Suited for building large number multi-directional communication groups. Able to connect users with different network protocols with no limit to the number of users to connect with.

Configurations

Group configurations are explained below.

{
	"remoteJoinTries": 4,
	"relayLimit": 2,
	"sendInterval": 300,
	"staticGroups": [
		{ "groupID": "52 character long unique group ID", "interval": 200 }
	]
}

▶︎ Configuration Value

remoteJoinTries - Default is 4

Controls the number of tries to join a group using remote server processes when the original group data is lost on the server process.

relayLimit - Default is 2

Configures the number of servers to propagate broadcast messages simultaneously. The higher the value is faster the propagation of the message, but higher server work load.

sendInterval - Default is 300

Configures the outbound packet buffer interval in milliseconds. This configuration is effective to the replicated groups and it may differ from the original master group. If set to 0, group will not buffer packets.

staticGroups - A list of static groups to create on process start.
Group ID can be custom defined. Interval controls message buffering on the server.

Defines the static group IDs to be created at the start of the server. Static groups are groups the always exists and never deleted. The format of the value is an array of maps as shown below:

[NOTE] Static group ID length must be exactly 52 character-long.

[
  {
    "groupID": "52 character-long unique ID",
    "interval": 200 // outbound packet buffer interval in milliseconds
  }
]

Static groups are statically created on server process start and will never be discarded until the server process stops. Useful for creating a group that expects all clients to join for global notifications etc.

Index ▾

func AfterBroadcastGroupCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func AfterCreateGroupCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func AfterJoinGroupCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func AfterLeaveGroupCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func Announce(groupID string, ver uint8, cmd uint16, message []byte, reliable bool)
func BeforeBroadcastGroupCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func BeforeCreateGroupCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func BeforeJoinGroupCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func BeforeLeaveGroupCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func Broadcast(groupID string, senderUser *user.User, ver uint8, cmd uint16, message []byte, reliable bool)
func ExposeCommands()
func GetGroupIDList(userData *user.User) []string
func GetLatestGroupID(userData *user.User) string
func GetMemberMeshNodes(groupID string) []string
func IsJoinError(err error) bool
func IsLeaveError(err error) bool
func IsNewGroupError(err error) bool
func Join(groupID string, userData *user.User, ver uint8, cmd uint16, message []byte, callback func(error))
func Leave(groupID string, userData *user.User, ver uint8, cmd uint16, message []byte, callback func(error))
func NewGroup(userData *user.User, allowEmpty bool, join bool, ttl int64, interval int64) (string, error)
func SetOnDiscardCustomMessage(custom func(groupID string, userID string, userSID string) (message []byte))
func SetOnRejoinCustomMessage(custom func(groupID string, userID string, userSID string) (message []byte))
func SetOnTickByID(groupID string, cb func(groupID string), interval int64) error
func Setup(confpath string)
func SetupAsTCPServer()
func SetupAsUDPServer()
func SetupAsWebSocketServer()
type Group
    func GetGroupByID(groupID string) *Group
type Member
type SendData
type SyncGroupData

func AfterBroadcastGroupCmd

func AfterBroadcastGroupCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))

AfterBroadcastGroupCmd registers a callback function to be executed after broadcast group command:

Must be called before ExposeCommands

Parameters

ver     - Command ver sent from the client.
cmd     - Command ID sent from the client.
payload - Command payload sent from the client.
userData - User data representing the client that sent the command.
next    - The function to signal the command to move on to the next operation of the same ver and command ID.
          This function must be called at the end of all operations in the callback.
          If you pass an error, it will not proceed to the next operations of the same command ver and ID.

func AfterCreateGroupCmd

func AfterCreateGroupCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))

AfterCreateGroupCmd registers a callback function to be executed after create group command:

Must be called before ExposeCommands

Parameters

ver     - Command ver sent from the client.
cmd     - Command ID sent from the client.
payload - Command payload sent from the client.
userData - User data representing the client that sent the command.
next    - The function to signal the command to move on to the next operation of the same ver and command ID.
          This function must be called at the end of all operations in the callback.
          If you pass an error, it will not proceed to the next operations of the same command ver and ID.

func AfterJoinGroupCmd

func AfterJoinGroupCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))

AfterJoinGroupCmd registers a callback function to be executed after join group command:

Must be called before ExposeCommands

Parameters

ver     - Command ver sent from the client.
cmd     - Command ID sent from the client.
payload - Command payload sent from the client.
userData - User data representing the client that sent the command.
next    - The function to signal the command to move on to the next operation of the same ver and command ID.
          This function must be called at the end of all operations in the callback.
          If you pass an error, it will not proceed to the next operations of the same command ver and ID.

func AfterLeaveGroupCmd

func AfterLeaveGroupCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))

AfterLeaveGroupCmd registers a callback function to be executed after leave group command:

Must be called before ExposeCommands

Parameters

ver     - Command ver sent from the client.
cmd     - Command ID sent from the client.
payload - Command payload sent from the client.
userData - User data representing the client that sent the command.
next    - The function to signal the command to move on to the next operation of the same ver and command ID.
          This function must be called at the end of all operations in the callback.
          If you pass an error, it will not proceed to the next operations of the same command ver and ID.

func Announce

func Announce(groupID string, ver uint8, cmd uint16, message []byte, reliable bool)

Announce sends a broadcast message to the other members in the group without having the "sender": MUST not be called by client directly for security reason

[NOTE] Uses mutex lock internally.
[NOTE] This function is asynchronous.

Parameters

groupID    - Target group ID.
senderUSer - User that sends the broadcast.
ver        - Command version used for the broadcast message.
cmd        - Command ID used for the broadcast message.
message    - Message byte array to be sent as the broadcast.
reliable   - If true, UDP will become RUDP.

func BeforeBroadcastGroupCmd

func BeforeBroadcastGroupCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))

BeforeBroadcastGroupCmd registers a callback function to be executed before broadcast group command:

Must be called before ExposeCommands

Parameters

ver     - Command ver sent from the client.
cmd     - Command ID sent from the client.
payload - Command payload sent from the client.
userData - User data representing the client that sent the command.
next    - The function to signal the command to move on to the next operation of the same ver and command ID.
          This function must be called at the end of all operations in the callback.
          If you pass an error, it will not proceed to the next operations of the same command ver and ID.

func BeforeCreateGroupCmd

func BeforeCreateGroupCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))

BeforeCreateGroupCmd registers a callback function to be executed before create group command:

Must be called before ExposeCommands

Parameters

ver     - Command ver sent from the client.
cmd     - Command ID sent from the client.
payload - Command payload sent from the client.
userData - User data representing the client that sent the command.
next    - The function to signal the command to move on to the next operation of the same ver and command ID.
          This function must be called at the end of all operations in the callback.
          If you pass an error, it will not proceed to the next operations of the same command ver and ID.

func BeforeJoinGroupCmd

func BeforeJoinGroupCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))

BeforeJoinGroupCmd registers a callback function to be executed before join group command:

Must be called before ExposeCommands

Parameters

ver     - Command ver sent from the client.
cmd     - Command ID sent from the client.
payload - Command payload sent from the client.
userData - User data representing the client that sent the command.
next    - The function to signal the command to move on to the next operation of the same ver and command ID.
          This function must be called at the end of all operations in the callback.
          If you pass an error, it will not proceed to the next operations of the same command ver and ID.

func BeforeLeaveGroupCmd

func BeforeLeaveGroupCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))

BeforeLeaveGroupCmd registers a callback function to be executed before leave group command:

Must be called before ExposeCommands

Parameters

ver     - Command ver sent from the client.
cmd     - Command ID sent from the client.
payload - Command payload sent from the client.
userData - User data representing the client that sent the command.
next    - The function to signal the command to move on to the next operation of the same ver and command ID.
          This function must be called at the end of all operations in the callback.
          If you pass an error, it will not proceed to the next operations of the same command ver and ID.

func Broadcast

func Broadcast(groupID string, senderUser *user.User, ver uint8, cmd uint16, message []byte, reliable bool)

Broadcast Sends a broadcast message to the other members in the group

[NOTE] Uses mutex lock internally.
[NOTE] This function is asynchronous.
[NOTE] This function may fail silently.

Parameters

groupID    - Target group ID.
senderUSer - User that sends the broadcast.
ver        - Command version used for the broadcast message.
cmd        - Command ID used for the broadcast message.
message    - Message byte array to be sent as the broadcast.
reliable   - If true, UDP will become RUDP.

func ExposeCommands

func ExposeCommands()

ExposeCommands exposes commands to the client to work with the Group package

The following commands will be exposed to the client:

func GetGroupIDList

func GetGroupIDList(userData *user.User) []string

GetGroupIDList returns an array of group IDs

[NOTE] Uses mutex lock internally.

Parameters

userData *user.User - Target user to retrieve the list of group IDs from.

func GetLatestGroupID

func GetLatestGroupID(userData *user.User) string

GetLatestGroupID returns the newest group ID the user joined or created

[NOTE] Uses mutex lock internally.

Parameters

userData *user.User - Target user to retrieve the last group ID joined.

func GetMemberMeshNodes

func GetMemberMeshNodes(groupID string) []string

GetMemberMeshNodes returns an array of member mesh nodes that are participating the group

[NOTE] Uses mutex lock internally.

Parameters

groupID string - Target group ID to retrieve the list of server internal addresses that group is stored.

func IsJoinError

func IsJoinError(err error) bool

IsJoinError returns true if the given error is or contains a GroupJoinError.

func IsLeaveError

func IsLeaveError(err error) bool

IsLeaveError returns true if the given error is or contains a GroupLeaveError.

func IsNewGroupError

func IsNewGroupError(err error) bool

IsNewGroupError returns true if the given error is or contains a GroupNewError.

func Join

func Join(groupID string, userData *user.User, ver uint8, cmd uint16, message []byte, callback func(error))

Join Joins a group and notify the other members of the group on joining the group If message is nil or empty, broadcast will NOT be sent

[NOTE] Uses mutex lock internally.
[NOTE] This function is asynchronous.

Error Cases

+------------------------------+-------------------------------------------+
| Error                        | Reason                                    |
+------------------------------+-------------------------------------------+
| User is already in the group | The user is already a member of the group |
| Failed to add a member       | The group trying to join does not exist   |
| Reliable Response timed out  | Internal network failed and timed out     |
+------------------------------+-------------------------------------------+

Parameters

groupID  - Target group ID to join.
userData - User to join the group.
ver      - Command version used for the message sent when join is successful.
cmd      - Command ID used for the message sent when join is successful.
message  - Message byte array to be sent when join is successful.
           If message is either nil or empty, the message will not be sent.

callback func(error) - Callback invoked when join operation is completed.

func Leave

func Leave(groupID string, userData *user.User, ver uint8, cmd uint16, message []byte, callback func(error))

Leave Leaves from a group and notify the other members on leaving If message is nil or empty, broadcast will NOT be sent

[NOTE] Uses mutex lock internally.
[NOTE] This function is asynchronous.

Error Cases

+--------------------------+-----------------------------------------+
| Error                    | Reason                                  |
+--------------------------+-----------------------------------------+
| User is not in the group | The user is not a member of the group   |
| Group not found          | The group to leave from does not exists |
+--------------------------+-----------------------------------------+

Parameters

groupID  - Target group ID to leave from.
userData - User to leave the group.
ver      - Command version used for the message sent when leave is successful.
cmd      - Command ID used for the message sent when leave is successful.
message  - Message byte array to be sent when leave is successful.
           If message is either nil or empty, the message will not be sent.

callback func(error) - Callback invoked when join operation is completed.

func NewGroup

func NewGroup(userData *user.User, allowEmpty bool, join bool, ttl int64, interval int64) (string, error)

NewGroup Creates a new group and returns the group ID as a string to the callback function.

[NOTE] Uses mutex lock internally.

Error Cases

┌────────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Error                      │ Reason                                                                                                 │
├────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Invalid TTL                │ TTL must be greater than 10 seconds                                                                    │
├────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Node is offline            │ A new group cannot be created on a server node that is in offline state (marked and ready to shutdown) │
├────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Allow empty and join false │ Allow empty false must be followed by join true, otherwise the new group will be deleted immediately.  │
└────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────┘

Parameters

allowEmpty - If true, the group will not be deleted until TTL expires even if all members leave
join       - If true, the creator user will join the group automatically
ttl        - TTL of the group in seconds. The value must be greater than 10
interval   - Broadcast interval in milliseconds. Interval below 100ms will be forced to 0. If it's 0, no packet merge

func SetOnDiscardCustomMessage

func SetOnDiscardCustomMessage(custom func(groupID string, userID string, userSID string) (message []byte))

SetOnDiscardCustomMessage sets a custom function to create a custom message to be sent to members on user discard

[CRITICALLY IMPORTANT] Using pointer variables that are defined outside of the callback closure
                       in the callback closure will cause those pointers to be not garbage collected leading to memory leak.

[CRITICALLY IMPORTANT] If the callback is blocked, it will lead to a goroutine leak and the join operation will be blocked.

custom func(groupID string, userID string, userSID string) []byte - Custom function to create custom message byte array.

func SetOnRejoinCustomMessage

func SetOnRejoinCustomMessage(custom func(groupID string, userID string, userSID string) (message []byte))

SetOnRejoinCustomMessage assigns a callback on rejoin to create a custom message

[CRITICALLY IMPORTANT] Using pointer variables that are defined outside of the callback closure
                       in the callback closure will cause those pointers to be not garbage collected leading to memory leak.

[CRITICALLY IMPORTANT] If the callback is blocked, it will lead to a goroutine leak and the leave operation will be blocked.

custom func(groupID string, userID string, userSID string) []byte - Custom function to create custom message byte array.

func SetOnTickByID

func SetOnTickByID(groupID string, cb func(groupID string), interval int64) error

SetOnTickByID assigns a callback to a given group ID to be executed at every given interval in seconds.

[CRITICALLY IMPORTANT] Using pointer variables that are defined outside of the callback closure
                       in the callback closure will cause those pointers to be not garbage collected leading to memory leak.

[CRITICALLY IMPORTANT] If the callback is blocked, it will lead to a goroutine leak and the tick will be blocked entirely.

[IMPORTANT] The interval evaluation is executed every 2 seconds.

func Setup

func Setup(confpath string)

Setup optionally loads configurations

configpath string - Absolute path for the configuration file to read.

func SetupAsTCPServer

func SetupAsTCPServer()

SetupAsTCPServer Sets up group package as TCP server

func SetupAsUDPServer

func SetupAsUDPServer()

SetupAsUDPServer Sets up group package as UDP/RUDP server

func SetupAsWebSocketServer

func SetupAsWebSocketServer()

SetupAsWebSocketServer Sets up group package as WebSocket server

type Group

Group group data structure

type Group struct {
    ID         string
    AllowEmpty bool
    // remote member mesh node list
    RemoteMemberNodes map[string]bool
    // user ID as key
    MemberMeshEndPoints map[string]string
    // user ID as key and user SID as value
    MemberSIDs map[string]string
    // If true, the group is static and never discarded
    IsStatic bool

    TTL int64

    sync.RWMutex
    // contains filtered or unexported fields
}

func GetGroupByID

func GetGroupByID(groupID string) *Group

GetGroupByID returns a group instance by its ID.

[IMPORTANT] If the group does not exist or the given ID.

type Member

Member member of a group data structure

type Member struct {
    UID          string
    SID          string
    MeshEndPoint string
}

type SendData

SendData represents internally used data

type SendData struct {
    GroupID  string `json:"groupID"`
    Ver      uint8  `json:"ver"`
    Cmd      uint16 `json:"cmd"`
    Message  []byte `json:"message"`
    Reliable bool   `json:"reliable"`
}

type SyncGroupData

SyncGroupData represents internally used data

type SyncGroupData struct {
    GroupID      string `json:"groupID"`
    MeshEndpoint string `json:"meshEndPoint"`
    Method       string `json:"method"`
}