summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/client.go12
-rw-r--r--cmd/client/main.go9
-rw-r--r--core/data.go3
-rw-r--r--core/payload.go41
-rw-r--r--docs/rfc.md3
-rw-r--r--server/user.go23
6 files changed, 90 insertions, 1 deletions
diff --git a/client/client.go b/client/client.go
index 775fbb6..b07bc27 100644
--- a/client/client.go
+++ b/client/client.go
@@ -4,6 +4,7 @@ import (
"errors"
"io"
"net"
+ "time"
"go.rctt.net/solec/core"
)
@@ -83,6 +84,17 @@ func (c *Client) Leave(channel string) error {
return core.Send(c.conn, umod)
}
+func (c *Client) GetHistory(channel string, since time.Time, count, offset int) error {
+ hist := core.History{
+ Channel: channel,
+ Since: since,
+ Count: int64(count),
+ Offset: int64(offset),
+ }
+
+ return core.Send(c.conn, hist)
+}
+
func (c *Client) read() {
for {
payload, err := core.Read(c.conn)
diff --git a/cmd/client/main.go b/cmd/client/main.go
index b107d93..bc9f4ff 100644
--- a/cmd/client/main.go
+++ b/cmd/client/main.go
@@ -5,6 +5,7 @@ import (
"log"
"net"
"strings"
+ "time"
"go.rctt.net/solec/client"
"go.rctt.net/solec/core"
@@ -32,6 +33,7 @@ func main() {
prompt.Commands["send"] = sendMessage
prompt.Commands["join"] = join
prompt.Commands["leave"] = leave
+ prompt.Commands["history"] = history
flag.StringVar(&serverAddr, "a", "localhost:9999", "Server address:port")
flag.StringVar(&user, "u", "user", "username")
@@ -68,3 +70,10 @@ func leave(args []string) {
log.Println("cannot leave channel:", err)
}
}
+
+func history(args []string) {
+ err := c.GetHistory(args[0], time.Time{}, 99999999, 0)
+ if err != nil {
+ log.Println("cannot read channel history:", err)
+ }
+}
diff --git a/core/data.go b/core/data.go
index 2a98347..4d18604 100644
--- a/core/data.go
+++ b/core/data.go
@@ -24,6 +24,7 @@ const (
PayloadMessage = 0x05
PayloadServerAuth = 0x06
PayloadUsermode = 0x07
+ PayloadHistory = 0x08
PayloadTest = 0xFF
)
@@ -143,6 +144,8 @@ func Decode(buf io.Reader) (any, error) {
return DecodeMessage(buf)
case PayloadUsermode:
return DecodeUsermode(buf)
+ case PayloadHistory:
+ return DecodeHistory(buf)
case PayloadTest:
return DecodeTest(buf)
default:
diff --git a/core/payload.go b/core/payload.go
index 3c3afa1..b54a8cd 100644
--- a/core/payload.go
+++ b/core/payload.go
@@ -185,6 +185,47 @@ func DecodeUsermode(buf io.Reader) (Usermode, error) {
return u, nil
}
+type History struct {
+ Channel string
+ Since time.Time
+ Count int64
+ Offset int64
+}
+
+func (h History) Wrap() (PayloadType, []any) {
+ return PayloadHistory, []any{
+ h.Channel,
+ h.Since,
+ h.Count,
+ h.Offset,
+ }
+}
+
+func DecodeHistory(buf io.Reader) (History, error) {
+ var h History
+ err := decodeString(buf, &h.Channel)
+ if err != nil {
+ return h, err
+ }
+
+ err = decodeTime(buf, &h.Since)
+ if err != nil {
+ return h, err
+ }
+
+ err = decodeNumeric(buf, &h.Count)
+ if err != nil {
+ return h, err
+ }
+
+ err = decodeNumeric(buf, &h.Offset)
+ if err != nil {
+ return h, err
+ }
+
+ return h, nil
+}
+
type Test struct {
Num1 uint8
Time1 time.Time
diff --git a/docs/rfc.md b/docs/rfc.md
index b5fa585..e60527f 100644
--- a/docs/rfc.md
+++ b/docs/rfc.md
@@ -163,6 +163,7 @@ Payload type attributes describes following characteristics:
| 0x05 | Message | SC |
| 0x06 | ServerAuth | S |
| 0x07 | UserMode | C |
+| 0x08 | History. | C |
| 0xFF | Test | R |
### Success
@@ -243,7 +244,7 @@ example: joining, leaving or setting privilages.
| 0x00 | none |
| 0x01 | in_channel |
-### GetHistory
+### History
Read messages previously send to a specific channel. User has to member of the channel to perform this action. *since* field specifies start of time range for which history should be retrieved. *count* specifes how many messages should be returned in a single response. *GetHistory* is a locking sequence and it cannot be cancelled while in progress so *count* should be set relatively low. To get more messages use multiple requests with incremented *offset*.
diff --git a/server/user.go b/server/user.go
index 002ed89..6b0e946 100644
--- a/server/user.go
+++ b/server/user.go
@@ -118,6 +118,8 @@ func (s *Server) handleUserPayload(user *User, sender net.Conn, payload any) err
return s.handleMessage(sender, core.ConnTypeUser, v)
case core.Usermode:
return s.handleUsermode(user, sender, v)
+ case core.History:
+ return s.handleHistory(user, sender, v)
default:
return core.ErrUnexpectedPayloadType
}
@@ -151,3 +153,24 @@ func (s *Server) handleUsermode(user *User, conn net.Conn, mode core.Usermode) e
return nil
}
+
+func (s *Server) handleHistory(user *User, conn net.Conn, hist core.History) error {
+ // TODO: Add permissions check
+
+ messages, err := s.Storage.Read(hist.Channel, hist.Since, int(hist.Count), int(hist.Offset))
+ if err != nil {
+ return err
+ }
+
+ for _, m := range messages {
+ data, err := core.Encode(m)
+ if err != nil {
+ return err
+ }
+ if _, err := conn.Write(data); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}