diff options
-rw-r--r-- | cmd_nick.go | 1 | ||||
-rw-r--r-- | meselog/meselog.go | 7 | ||||
-rw-r--r-- | users.go | 95 |
3 files changed, 100 insertions, 3 deletions
diff --git a/cmd_nick.go b/cmd_nick.go index 0ca7173..deff08b 100644 --- a/cmd_nick.go +++ b/cmd_nick.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "git.sr.ht/~runxiyu/meseircd/meselog" ) diff --git a/meselog/meselog.go b/meselog/meselog.go index d9c84f5..402d674 100644 --- a/meselog/meselog.go +++ b/meselog/meselog.go @@ -5,11 +5,11 @@ import ( ) func log(str string, keyvals []any) { - fmt.Print(str+" ") + fmt.Print(str + " ") for i, j := range keyvals { - if i & 1 == 0 { + if i&1 == 0 { fmt.Printf("%v=", j) - } else if i == len(keyvals) - 1 { + } else if i == len(keyvals)-1 { fmt.Printf("%#v", j) } else { fmt.Printf("%#v ", j) @@ -21,6 +21,7 @@ func log(str string, keyvals []any) { func Error(str string, keyvals ...any) { log("ERROR "+str, keyvals) } + func Debug(str string, keyvals ...any) { log("DEBUG "+str, keyvals) } diff --git a/users.go b/users.go new file mode 100644 index 0000000..d94a0fe --- /dev/null +++ b/users.go @@ -0,0 +1,95 @@ +package main + +import ( + "net" + "sync" + + "git.sr.ht/~runxiyu/meseircd/meselog" +) + +type User struct { + Clients []*Client + UID uint64 + Nick string + Ident string + Gecos string + Host string + Caps map[string]struct{} + Extra map[string]any + Server *Server + State ClientState +} + +func (user *User) SendToLocalClients(msg SMsg) (numSent uint) { + for _, c := range user.Clients { + if c.Server != self { + continue + } + err := c.Send(msg) + if err == nil { + numSent++ + } + } + return +} + +func (user *User) ClientSource() string { + // TODO: Edge cases where these aren't available + return user.Nick + "!" + user.Ident + "@" + user.Host +} + +func (user *User) ServerSource() uint64 { + return user.UID +} + +// func (user *User) Delete() { +// if client.conn != nil { +// (*client.conn).Close() +// } +// if !cidToClient.CompareAndDelete(client.CID, client) { +// meselog.Error("cid inconsistent", "cid", client.CID, "client", client) +// } +// if client.State >= ClientStateRegistered || client.Nick != "*" { +// if !nickToClient.CompareAndDelete(client.Nick, client) { +// meselog.Error("nick inconsistent", "nick", client.Nick, "client", client) +// } +// } +// } + +func NewLocalUser(conn *net.Conn) (*User, error) { + var uidPart uint32 + { + uidPartCountLock.Lock() + defer uidPartCountLock.Unlock() + if uidPartCount == ^uint32(0) { // UINT32_MAX + return nil, ErrFullClients + } + uidPartCount++ + uidPart = uidPartCount + } + client := &Client{ + conn: conn, + Server: self, + State: ClientStatePreRegistration, + Nick: "*", + Caps: make(map[string]struct{}), + Extra: make(map[string]any), + CID: uint64(self.SID)<<32 | uint64(uidPart), + } + return client, nil +} + +const ( + ClientStatePreRegistration ClientState = iota + ClientStateCapabilities + ClientStateCapabilitiesFinished + ClientStateRegistered + ClientStateRemote +) + +var ( + cidToClient = sync.Map{} + nickToClient = sync.Map{} + uidPartCount uint32 + uidPartCountLock sync.Mutex +) |