5 "github.com/Kovensky/go-anidb/udp"
12 gob.RegisterName("*github.com/Kovensky/go-anidb.banCache", &banCache{})
15 const banDuration = 30*time.Minute + 1*time.Second
17 type banCache struct{ time.Time }
19 func (c *banCache) Touch() {
22 func (c *banCache) IsStale() bool {
23 return time.Now().Sub(c.Time) > banDuration
26 // Returns whether the last UDP API access returned a 555 BANNED message.
29 cache.Get(&banTime, "banned")
31 stale := banTime.IsStale()
33 cache.Delete("banned")
39 cache.Set(&banCache{}, "banned")
42 type paramSet struct {
45 ch chan udpapi.APIReply
52 sendQueueCh chan paramSet
55 credentials *credentials
59 func newUDPWrap() *udpWrap {
61 AniDBUDP: udpapi.NewAniDBUDP(),
62 sendQueueCh: make(chan paramSet, 10),
68 type paramMap udpapi.ParamMap // shortcut
70 type noauthAPIReply struct {
74 func (r *noauthAPIReply) Code() int {
78 func (r *noauthAPIReply) Text() string {
82 func (r *noauthAPIReply) Error() error {
83 return &udpapi.APIError{Code: r.Code(), Desc: r.Text()}
86 type bannedAPIReply struct {
90 func (r *bannedAPIReply) Code() int {
93 func (r *bannedAPIReply) Text() string {
96 func (r *bannedAPIReply) Error() error {
97 return &udpapi.APIError{Code: r.Code(), Desc: r.Text()}
100 var bannedReply udpapi.APIReply = &bannedAPIReply{}
102 func logRequest(set paramSet) {
105 log.Printf("UDP>>> AUTH user=%s\n", set.params["user"])
107 log.Printf("UDP>>> %s %s\n", set.cmd, udpapi.ParamMap(set.params).String())
111 func logReply(reply udpapi.APIReply) {
112 log.Printf("UDP<<< %d %s\n", reply.Code(), reply.Text())
115 func (udp *udpWrap) sendQueue() {
116 initialWait := 6 * time.Second
118 for set := range udp.sendQueueCh {
121 set.ch <- bannedReply
127 reply := <-udp.AniDBUDP.SendRecv(set.cmd, udpapi.ParamMap(set.params))
129 if reply.Error() == udpapi.TimeoutError {
131 wait = (wait * 15) / 10
132 if wait > time.Minute {
135 log.Printf("UDP--- Timeout; waiting %s before retry", wait)
144 switch reply.Code() {
145 case 403, 501, 506: // not logged in, or session expired
146 if r := udp.ReAuth(); r.Error() == nil {
150 case 503, 504: // client library rejected
152 case 555: // IP (and user, possibly client) temporarily banned
160 type errorReply struct {
165 func (r *errorReply) Code() int {
168 func (r *errorReply) Text() string {
171 func (r *errorReply) Error() error {
175 func (udp *udpWrap) SendRecv(cmd string, params paramMap) <-chan udpapi.APIReply {
176 ch := make(chan udpapi.APIReply, 1)
179 defer udp.sendLock.Unlock()
188 if r := udp.ReAuth(); r.Error() != nil {
195 udp.sendQueueCh <- paramSet{