]> git.lizzy.rs Git - go-anidb.git/blob - udp.go
anidb: Don't use a nil fileLock
[go-anidb.git] / udp.go
1 package anidb
2
3 import (
4         "encoding/gob"
5         "github.com/Kovensky/go-anidb/udp"
6         "time"
7 )
8
9 func init() {
10         gob.RegisterName("*github.com/Kovensky/go-anidb.banCache", &banCache{})
11 }
12
13 const banDuration = 30*time.Minute + 1*time.Second
14
15 type banCache struct{ time.Time }
16
17 func (c *banCache) Touch() {
18         c.Time = time.Now()
19 }
20 func (c *banCache) IsStale() bool {
21         return time.Now().Sub(c.Time) > banDuration
22 }
23
24 // Returns whether the last UDP API access returned a 555 BANNED message.
25 func Banned() bool {
26         var banTime banCache
27         cache.Get(&banTime, "banned")
28
29         stale := banTime.IsStale()
30         if stale {
31                 cache.Delete("banned")
32         }
33         return !stale
34 }
35
36 func setBanned() {
37         cache.Set(&banCache{}, "banned")
38 }
39
40 type paramSet struct {
41         cmd    string
42         params paramMap
43         ch     chan udpapi.APIReply
44 }
45
46 type udpWrap struct {
47         *udpapi.AniDBUDP
48
49         sendQueueCh chan paramSet
50
51         credentials *credentials
52         connected   bool
53 }
54
55 func newUDPWrap() *udpWrap {
56         u := &udpWrap{
57                 AniDBUDP:    udpapi.NewAniDBUDP(),
58                 sendQueueCh: make(chan paramSet, 10),
59         }
60         go u.sendQueue()
61         return u
62 }
63
64 type paramMap udpapi.ParamMap // shortcut
65
66 type noauthAPIReply struct {
67         udpapi.APIReply
68 }
69
70 func (r *noauthAPIReply) Code() int {
71         return 501
72 }
73
74 func (r *noauthAPIReply) Text() string {
75         return "LOGIN FIRST"
76 }
77
78 func (r *noauthAPIReply) Error() error {
79         return &udpapi.APIError{Code: r.Code(), Desc: r.Text()}
80 }
81
82 type bannedAPIReply struct {
83         udpapi.APIReply
84 }
85
86 func (r *bannedAPIReply) Code() int {
87         return 555
88 }
89 func (r *bannedAPIReply) Text() string {
90         return "BANNED"
91 }
92 func (r *bannedAPIReply) Error() error {
93         return &udpapi.APIError{Code: r.Code(), Desc: r.Text()}
94 }
95
96 var bannedReply udpapi.APIReply = &bannedAPIReply{}
97
98 func (udp *udpWrap) sendQueue() {
99         for set := range udp.sendQueueCh {
100                 reply := <-udp.AniDBUDP.SendRecv(set.cmd, udpapi.ParamMap(set.params))
101
102                 if reply.Error() == udpapi.TimeoutError {
103                         // retry
104                         go func(set paramSet) { udp.sendQueueCh <- set }(set)
105                         continue
106                 }
107
108                 switch reply.Code() {
109                 case 403, 501, 506: // not logged in, or session expired
110                         if err := udp.ReAuth(); err == nil {
111                                 // retry
112                                 go func(set paramSet) { udp.sendQueueCh <- set }(set)
113                                 continue
114                         }
115                 case 503, 504: // client library rejected
116                         panic(reply.Error())
117                 case 555: // IP (and user, possibly client) temporarily banned
118                         setBanned()
119                 }
120                 set.ch <- reply
121                 close(set.ch)
122         }
123 }
124
125 func (udp *udpWrap) SendRecv(cmd string, params paramMap) <-chan udpapi.APIReply {
126         ch := make(chan udpapi.APIReply, 1)
127         if udp.credentials == nil {
128                 ch <- &noauthAPIReply{}
129                 close(ch)
130                 return ch
131         }
132
133         if Banned() {
134                 ch <- bannedReply
135                 close(ch)
136                 return ch
137         }
138
139         udp.sendQueueCh <- paramSet{
140                 cmd:    cmd,
141                 params: params,
142                 ch:     ch,
143         }
144
145         return ch
146 }