summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/client/main.go10
-rw-r--r--cmd/daemon/main.go13
-rw-r--r--core/data.go11
-rw-r--r--docs/rfc.md7
-rw-r--r--server/server.go71
5 files changed, 77 insertions, 35 deletions
diff --git a/cmd/client/main.go b/cmd/client/main.go
index 2612267..8c2258a 100644
--- a/cmd/client/main.go
+++ b/cmd/client/main.go
@@ -18,7 +18,7 @@ var (
)
func main() {
- prompt.Commands["*"] = broadcast
+ prompt.Commands["send"] = sendMessage
flag.StringVar(&serverAddr, "a", "localhost:9999", "Server address:port")
flag.StringVar(&user, "u", "user", "username")
@@ -74,16 +74,14 @@ func handleMessage(conn net.Conn, msg core.Message) {
log.Println("received message", msg.Source, "->", msg.Target, msg.Content)
}
-func broadcast(args []string) {
+func sendMessage(args []string) {
msg := core.Message{
Source: user,
- Target: "*",
+ Target: args[0],
Timestamp: time.Now(),
- Content: strings.Join(args[0:], " "),
+ Content: strings.Join(args[1:], " "),
}
- log.Println(msg.Content)
-
if err := core.Send(conn, msg); err != nil {
panic(err)
}
diff --git a/cmd/daemon/main.go b/cmd/daemon/main.go
index 32b3954..d0e4d1c 100644
--- a/cmd/daemon/main.go
+++ b/cmd/daemon/main.go
@@ -14,8 +14,9 @@ import (
)
var (
- cmds = map[string]func(args []string){}
-
+ cmds = map[string]func(args []string){
+ "broadcast": sendBroadcast,
+ }
serv *server.Server
)
@@ -24,9 +25,10 @@ func main() {
fmt.Println("Commands:", slices.Sorted(maps.Keys(cmds)))
addr := flag.String("a", "localhost:9999", "listening address:port")
+ name := flag.String("n", "localhost", "server name")
flag.Parse()
- serv = server.NewServer(*addr)
+ serv = server.NewServer(*addr, *name)
go func() {
if err := serv.Start(); err != nil {
@@ -56,3 +58,8 @@ func readCmds() {
log.Println(err)
}
}
+
+func sendBroadcast(args []string) {
+ msg := strings.Join(args[0:], " ")
+ serv.SendBroadcast(msg)
+}
diff --git a/core/data.go b/core/data.go
index b25b853..9783c47 100644
--- a/core/data.go
+++ b/core/data.go
@@ -5,6 +5,7 @@ import (
"encoding/binary"
"fmt"
"io"
+ "strings"
"time"
)
@@ -29,6 +30,7 @@ type ErrorType uint8
const (
ErrorUnknown ErrorType = 0x00
ErrorAuthFailed = 0x01
+ ErrorNotFound = 0x02
)
type Frame struct {
@@ -176,3 +178,12 @@ func decodeString(buf io.Reader, ptr *string) error {
*ptr = string(strBytes)
return nil
}
+
+func ReadAddr(addr string) (string, string, error) {
+ channel, host, ok := strings.Cut(addr, "@")
+ if !ok {
+ return "", "", fmt.Errorf("invalid address")
+ }
+
+ return channel, host, nil
+}
diff --git a/docs/rfc.md b/docs/rfc.md
index 6f902b0..eb8f5c1 100644
--- a/docs/rfc.md
+++ b/docs/rfc.md
@@ -175,9 +175,10 @@ Payload is always empty for this type.
#### Error types
-| Type | Description |
-|------|--------------------------------------------|
-| 0x01 | Auth failed. Invalid username or password. |
+| Type | Description |
+|------|-----------------------------------------------------------|
+| 0x01 | Auth failed. Invalid username or password. |
+| 0x02 | Not found. User or channel cannot access user or channel. |
### Handshake
diff --git a/server/server.go b/server/server.go
index 51e71b1..bbfb676 100644
--- a/server/server.go
+++ b/server/server.go
@@ -6,12 +6,14 @@ import (
"log"
"net"
"sync"
+ "time"
"git.sr.ht/~rctt/solec/core"
)
type Server struct {
listenAddr string
+ name string
users map[string]User
mu sync.Mutex
}
@@ -21,9 +23,20 @@ type User struct {
Conns map[net.Conn]struct{}
}
-func NewServer(listenAddr string) *Server {
+func (u *User) Send(payload core.Wrapper) error {
+ for c := range u.Conns {
+ if err := core.Send(c, payload); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func NewServer(listenAddr string, name string) *Server {
return &Server{
listenAddr: listenAddr,
+ name: name,
users: make(map[string]User),
}
}
@@ -46,6 +59,27 @@ func (s *Server) Start() error {
}
}
+func (s *Server) SendBroadcast(msg string) {
+ payload := core.Message{
+ Source: "op@example.org",
+ Target: "*@example.org",
+ Timestamp: time.Now(),
+ Content: msg,
+ }
+ data, err := core.Encode(payload)
+ if err != nil {
+ panic(err)
+ }
+
+ for _, u := range s.users {
+ for c := range u.Conns {
+ if _, err := c.Write(data); err != nil {
+ log.Println("cannot send", err)
+ }
+ }
+ }
+}
+
func (s *Server) handleConn(conn net.Conn) {
if err := s.performHandshake(conn); err != nil {
log.Println("handshake error", err)
@@ -157,32 +191,23 @@ func (s *Server) handlePayload(conn net.Conn, user User, payload any) error {
func (s *Server) handleMessage(conn net.Conn, user User, msg core.Message) error {
log.Println("message:", user.Name, "->", msg.Target, msg.Content)
- if msg.Target == "*" {
- return s.broadcastMessage(conn, user, msg)
+ channel, host, err := core.ReadAddr(msg.Target)
+ if err != nil {
+ return err
}
- return nil
-}
-
-func (s *Server) broadcastMessage(conn net.Conn, user User, msg core.Message) error {
- for _, u := range s.users {
- if u.Name == user.Name {
- continue
- }
-
- for c := range u.Conns {
- if err := core.Send(c, msg); err != nil {
- log.Println("cannot send", err)
- }
- }
+ if host == s.name {
+ return s.handleLocalMessage(channel, msg)
}
- // Forward message for other connections from the same user
- for c := range s.users[user.Name].Conns {
- if err := core.Send(c, msg); err != nil {
- log.Println("cannot send", err)
- }
+ return fmt.Errorf("not supported")
+}
+
+func (s *Server) handleLocalMessage(channel string, msg core.Message) error {
+ user, ok := s.users[channel]
+ if !ok {
+ return errors.New("target not found")
}
- return nil
+ return user.Send(msg)
}