aboutsummaryrefslogtreecommitdiff
path: root/users.go
blob: d94a0fec1ddbcc718c0a55f02e5e741298b55d28 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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
)