mirror of
https://github.com/jech/galene.git
synced 2024-11-22 16:45:58 +01:00
Server-side support for protocol 2.
The "time" field of messages is now a string in RFC 3339 format, and there is a new "error" field in messages.
This commit is contained in:
parent
c58064d923
commit
a1c1345719
3 changed files with 19 additions and 43 deletions
|
@ -60,7 +60,7 @@ func (err ProtocolError) Error() string {
|
||||||
type ChatHistoryEntry struct {
|
type ChatHistoryEntry struct {
|
||||||
Id string
|
Id string
|
||||||
User string
|
User string
|
||||||
Time int64
|
Time time.Time
|
||||||
Kind string
|
Kind string
|
||||||
Value interface{}
|
Value interface{}
|
||||||
}
|
}
|
||||||
|
@ -760,18 +760,6 @@ func (g *Group) WallOps(message string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func FromJSTime(tm int64) time.Time {
|
|
||||||
if tm == 0 {
|
|
||||||
return time.Time{}
|
|
||||||
}
|
|
||||||
return time.Unix(int64(tm)/1000, (int64(tm)%1000)*1000000)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ToJSTime(tm time.Time) int64 {
|
|
||||||
return int64((tm.Sub(time.Unix(0, 0)) + time.Millisecond/2) /
|
|
||||||
time.Millisecond)
|
|
||||||
}
|
|
||||||
|
|
||||||
const maxChatHistory = 50
|
const maxChatHistory = 50
|
||||||
|
|
||||||
func (g *Group) ClearChatHistory() {
|
func (g *Group) ClearChatHistory() {
|
||||||
|
@ -780,7 +768,7 @@ func (g *Group) ClearChatHistory() {
|
||||||
g.history = nil
|
g.history = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Group) AddToChatHistory(id, user string, time int64, kind string, value interface{}) {
|
func (g *Group) AddToChatHistory(id, user string, time time.Time, kind string, value interface{}) {
|
||||||
g.mu.Lock()
|
g.mu.Lock()
|
||||||
defer g.mu.Unlock()
|
defer g.mu.Unlock()
|
||||||
|
|
||||||
|
@ -796,7 +784,7 @@ func (g *Group) AddToChatHistory(id, user string, time int64, kind string, value
|
||||||
func discardObsoleteHistory(h []ChatHistoryEntry, duration time.Duration) []ChatHistoryEntry {
|
func discardObsoleteHistory(h []ChatHistoryEntry, duration time.Duration) []ChatHistoryEntry {
|
||||||
i := 0
|
i := 0
|
||||||
for i < len(h) {
|
for i < len(h) {
|
||||||
if time.Since(FromJSTime(h[i].Time)) <= duration {
|
if time.Since(h[i].Time) <= duration {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
|
|
|
@ -47,28 +47,12 @@ func TestGroup(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestJSTime(t *testing.T) {
|
|
||||||
tm := time.Now()
|
|
||||||
js := ToJSTime(tm)
|
|
||||||
tm2 := FromJSTime(js)
|
|
||||||
js2 := ToJSTime(tm2)
|
|
||||||
|
|
||||||
if js != js2 {
|
|
||||||
t.Errorf("%v != %v", js, js2)
|
|
||||||
}
|
|
||||||
|
|
||||||
delta := tm.Sub(tm2)
|
|
||||||
if delta < -time.Millisecond/2 || delta > time.Millisecond/2 {
|
|
||||||
t.Errorf("Delta %v, %v, %v", delta, tm, tm2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestChatHistory(t *testing.T) {
|
func TestChatHistory(t *testing.T) {
|
||||||
g := Group{
|
g := Group{
|
||||||
description: &Description{},
|
description: &Description{},
|
||||||
}
|
}
|
||||||
for i := 0; i < 2*maxChatHistory; i++ {
|
for i := 0; i < 2*maxChatHistory; i++ {
|
||||||
g.AddToChatHistory("id", "user", ToJSTime(time.Now()), "",
|
g.AddToChatHistory("id", "user", time.Now(), "",
|
||||||
fmt.Sprintf("%v", i),
|
fmt.Sprintf("%v", i),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,7 @@ type clientMessage struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Version []string `json:"version"`
|
Version []string `json:"version"`
|
||||||
Kind string `json:"kind,omitempty"`
|
Kind string `json:"kind,omitempty"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
Id string `json:"id,omitempty"`
|
Id string `json:"id,omitempty"`
|
||||||
Replace string `json:"replace,omitempty"`
|
Replace string `json:"replace,omitempty"`
|
||||||
Source string `json:"source,omitempty"`
|
Source string `json:"source,omitempty"`
|
||||||
|
@ -126,7 +127,7 @@ type clientMessage struct {
|
||||||
Group string `json:"group,omitempty"`
|
Group string `json:"group,omitempty"`
|
||||||
Value interface{} `json:"value,omitempty"`
|
Value interface{} `json:"value,omitempty"`
|
||||||
NoEcho bool `json:"noecho,omitempty"`
|
NoEcho bool `json:"noecho,omitempty"`
|
||||||
Time int64 `json:"time,omitempty"`
|
Time string `json:"time,omitempty"`
|
||||||
SDP string `json:"sdp,omitempty"`
|
SDP string `json:"sdp,omitempty"`
|
||||||
Candidate *webrtc.ICECandidateInit `json:"candidate,omitempty"`
|
Candidate *webrtc.ICECandidateInit `json:"candidate,omitempty"`
|
||||||
Label string `json:"label,omitempty"`
|
Label string `json:"label,omitempty"`
|
||||||
|
@ -834,6 +835,8 @@ func readMessage(conn *websocket.Conn, m *clientMessage) error {
|
||||||
return conn.ReadJSON(&m)
|
return conn.ReadJSON(&m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const protocolVersion = "2"
|
||||||
|
|
||||||
func StartClient(conn *websocket.Conn) (err error) {
|
func StartClient(conn *websocket.Conn) (err error) {
|
||||||
var m clientMessage
|
var m clientMessage
|
||||||
|
|
||||||
|
@ -858,7 +861,7 @@ func StartClient(conn *websocket.Conn) (err error) {
|
||||||
versionError := true
|
versionError := true
|
||||||
if m.Version != nil {
|
if m.Version != nil {
|
||||||
for _, v := range m.Version {
|
for _, v := range m.Version {
|
||||||
if v == "1" {
|
if v == protocolVersion {
|
||||||
versionError = false
|
versionError = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -973,7 +976,7 @@ func clientLoop(c *webClient, ws *websocket.Conn, versionError bool) error {
|
||||||
|
|
||||||
err := c.write(clientMessage{
|
err := c.write(clientMessage{
|
||||||
Type: "handshake",
|
Type: "handshake",
|
||||||
Version: []string{"1"},
|
Version: []string{protocolVersion},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -1203,7 +1206,7 @@ func handleAction(c *webClient, a interface{}) error {
|
||||||
Type: "chathistory",
|
Type: "chathistory",
|
||||||
Source: m.Id,
|
Source: m.Id,
|
||||||
Username: m.User,
|
Username: m.User,
|
||||||
Time: m.Time,
|
Time: m.Time.Format(time.RFC3339),
|
||||||
Value: m.Value,
|
Value: m.Value,
|
||||||
Kind: m.Kind,
|
Kind: m.Kind,
|
||||||
})
|
})
|
||||||
|
@ -1418,7 +1421,7 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var s string
|
var e, s string
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
s = "group does not exist"
|
s = "group does not exist"
|
||||||
} else if err == group.ErrNotAuthorised {
|
} else if err == group.ErrNotAuthorised {
|
||||||
|
@ -1426,8 +1429,8 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
||||||
time.Sleep(200 * time.Millisecond)
|
time.Sleep(200 * time.Millisecond)
|
||||||
} else if err == group.ErrAnonymousNotAuthorised {
|
} else if err == group.ErrAnonymousNotAuthorised {
|
||||||
s = "please choose a username"
|
s = "please choose a username"
|
||||||
} else if e, ok := err.(group.UserError); ok {
|
} else if err, ok := err.(group.UserError); ok {
|
||||||
s = string(e)
|
s = err.Error()
|
||||||
} else {
|
} else {
|
||||||
s = "internal server error"
|
s = "internal server error"
|
||||||
log.Printf("Join group: %v", err)
|
log.Printf("Join group: %v", err)
|
||||||
|
@ -1435,6 +1438,7 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
||||||
return c.write(clientMessage{
|
return c.write(clientMessage{
|
||||||
Type: "joined",
|
Type: "joined",
|
||||||
Kind: "fail",
|
Kind: "fail",
|
||||||
|
Error: e,
|
||||||
Group: m.Group,
|
Group: m.Group,
|
||||||
Username: c.username,
|
Username: c.username,
|
||||||
Value: s,
|
Value: s,
|
||||||
|
@ -1559,12 +1563,12 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
||||||
return c.error(group.UserError("join a group first"))
|
return c.error(group.UserError("join a group first"))
|
||||||
}
|
}
|
||||||
|
|
||||||
tm := group.ToJSTime(time.Now())
|
now := time.Now()
|
||||||
|
|
||||||
if m.Type == "chat" {
|
if m.Type == "chat" {
|
||||||
if m.Dest == "" {
|
if m.Dest == "" {
|
||||||
g.AddToChatHistory(
|
g.AddToChatHistory(
|
||||||
m.Source, m.Username, tm, m.Kind, m.Value,
|
m.Source, m.Username, now, m.Kind, m.Value,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1574,7 +1578,7 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
||||||
Dest: m.Dest,
|
Dest: m.Dest,
|
||||||
Username: m.Username,
|
Username: m.Username,
|
||||||
Privileged: member("op", c.permissions),
|
Privileged: member("op", c.permissions),
|
||||||
Time: tm,
|
Time: now.Format(time.RFC3339),
|
||||||
Kind: m.Kind,
|
Kind: m.Kind,
|
||||||
NoEcho: m.NoEcho,
|
NoEcho: m.NoEcho,
|
||||||
Value: m.Value,
|
Value: m.Value,
|
||||||
|
@ -1677,7 +1681,7 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
||||||
Type: "chat",
|
Type: "chat",
|
||||||
Dest: c.id,
|
Dest: c.id,
|
||||||
Username: "Server",
|
Username: "Server",
|
||||||
Time: group.ToJSTime(time.Now()),
|
Time: time.Now().Format(time.RFC3339),
|
||||||
Value: s,
|
Value: s,
|
||||||
})
|
})
|
||||||
case "setdata":
|
case "setdata":
|
||||||
|
|
Loading…
Reference in a new issue