source: code/trunk/user.go@ 131

Last change on this file since 131 was 131, checked in by contact, 5 years ago

Move upstreamConn.history to network

File size: 3.6 KB
Line 
1package soju
2
3import (
4 "sync"
5 "time"
6
7 "gopkg.in/irc.v3"
8)
9
10type upstreamIncomingMessage struct {
11 msg *irc.Message
12 uc *upstreamConn
13}
14
15type downstreamIncomingMessage struct {
16 msg *irc.Message
17 dc *downstreamConn
18}
19
20type network struct {
21 Network
22 user *user
23
24 lock sync.Mutex
25 conn *upstreamConn
26 history map[string]uint64
27}
28
29func newNetwork(user *user, record *Network) *network {
30 return &network{
31 Network: *record,
32 user: user,
33 history: make(map[string]uint64),
34 }
35}
36
37func (net *network) run() {
38 var lastTry time.Time
39 for {
40 if dur := time.Now().Sub(lastTry); dur < retryConnectMinDelay {
41 delay := retryConnectMinDelay - dur
42 net.user.srv.Logger.Printf("waiting %v before trying to reconnect to %q", delay.Truncate(time.Second), net.Addr)
43 time.Sleep(delay)
44 }
45 lastTry = time.Now()
46
47 uc, err := connectToUpstream(net)
48 if err != nil {
49 net.user.srv.Logger.Printf("failed to connect to upstream server %q: %v", net.Addr, err)
50 continue
51 }
52
53 uc.register()
54
55 net.lock.Lock()
56 net.conn = uc
57 net.lock.Unlock()
58
59 if err := uc.readMessages(net.user.upstreamIncoming); err != nil {
60 uc.logger.Printf("failed to handle messages: %v", err)
61 }
62 uc.Close()
63
64 net.lock.Lock()
65 net.conn = nil
66 net.lock.Unlock()
67 }
68}
69
70type user struct {
71 User
72 srv *Server
73
74 upstreamIncoming chan upstreamIncomingMessage
75 downstreamIncoming chan downstreamIncomingMessage
76
77 lock sync.Mutex
78 networks []*network
79 downstreamConns []*downstreamConn
80}
81
82func newUser(srv *Server, record *User) *user {
83 return &user{
84 User: *record,
85 srv: srv,
86 upstreamIncoming: make(chan upstreamIncomingMessage, 64),
87 downstreamIncoming: make(chan downstreamIncomingMessage, 64),
88 }
89}
90
91func (u *user) forEachNetwork(f func(*network)) {
92 u.lock.Lock()
93 for _, network := range u.networks {
94 f(network)
95 }
96 u.lock.Unlock()
97}
98
99func (u *user) forEachUpstream(f func(uc *upstreamConn)) {
100 u.lock.Lock()
101 for _, network := range u.networks {
102 network.lock.Lock()
103 uc := network.conn
104 network.lock.Unlock()
105
106 if uc == nil || !uc.registered || uc.closed {
107 continue
108 }
109 f(uc)
110 }
111 u.lock.Unlock()
112}
113
114func (u *user) forEachDownstream(f func(dc *downstreamConn)) {
115 u.lock.Lock()
116 for _, dc := range u.downstreamConns {
117 f(dc)
118 }
119 u.lock.Unlock()
120}
121
122func (u *user) getNetwork(name string) *network {
123 for _, network := range u.networks {
124 if network.Addr == name {
125 return network
126 }
127 }
128 return nil
129}
130
131func (u *user) run() {
132 networks, err := u.srv.db.ListNetworks(u.Username)
133 if err != nil {
134 u.srv.Logger.Printf("failed to list networks for user %q: %v", u.Username, err)
135 return
136 }
137
138 u.lock.Lock()
139 for _, record := range networks {
140 network := newNetwork(u, &record)
141 u.networks = append(u.networks, network)
142
143 go network.run()
144 }
145 u.lock.Unlock()
146
147 for {
148 select {
149 case upstreamMsg := <-u.upstreamIncoming:
150 msg, uc := upstreamMsg.msg, upstreamMsg.uc
151 if err := uc.handleMessage(msg); err != nil {
152 uc.logger.Printf("failed to handle message %q: %v", msg, err)
153 }
154 case downstreamMsg := <-u.downstreamIncoming:
155 msg, dc := downstreamMsg.msg, downstreamMsg.dc
156 err := dc.handleMessage(msg)
157 if ircErr, ok := err.(ircError); ok {
158 ircErr.Message.Prefix = dc.srv.prefix()
159 dc.SendMessage(ircErr.Message)
160 } else if err != nil {
161 dc.logger.Printf("failed to handle message %q: %v", msg, err)
162 dc.Close()
163 }
164 }
165 }
166}
167
168func (u *user) createNetwork(net *Network) (*network, error) {
169 network := newNetwork(u, net)
170 err := u.srv.db.StoreNetwork(u.Username, &network.Network)
171 if err != nil {
172 return nil, err
173 }
174 u.lock.Lock()
175 u.networks = append(u.networks, network)
176 u.lock.Unlock()
177 go network.run()
178 return network, nil
179}
Note: See TracBrowser for help on using the repository browser.