package anidb
import (
- "encoding/gob"
- "github.com/Kovensky/go-anidb/udp"
- "log"
+ "github.com/EliasFleckenstein03/go-anidb/udp"
"sync"
"time"
)
-func init() {
- gob.RegisterName("*github.com/Kovensky/go-anidb.banCache", &banCache{})
-}
-
const banDuration = 30*time.Minute + 1*time.Second
-type banCache struct{ time.Time }
-
-func (c *banCache) Touch() {
- c.Time = time.Now()
-}
-func (c *banCache) IsStale() bool {
- return time.Now().Sub(c.Time) > banDuration
-}
-
// Returns whether the last UDP API access returned a 555 BANNED message.
func Banned() bool {
- var banTime banCache
- cache.Get(&banTime, "banned")
+ stat, err := Cache.Stat("banned")
+ if err != nil {
+ return false
+ }
- stale := banTime.IsStale()
- if stale {
- cache.Delete("banned")
+ switch ts := stat.ModTime(); {
+ case ts.IsZero():
+ return false
+ case time.Now().Sub(ts) > banDuration:
+ return false
+ default:
+ return true
}
- return !stale
}
func setBanned() {
- cache.Set(&banCache{}, "banned")
+ Cache.Touch("banned")
}
type paramSet struct {
type udpWrap struct {
*udpapi.AniDBUDP
+ adb *AniDB
+
sendLock sync.Mutex
sendQueueCh chan paramSet
credLock sync.Mutex
credentials *credentials
connected bool
+
+ user *User
}
-func newUDPWrap() *udpWrap {
+func newUDPWrap(adb *AniDB) *udpWrap {
u := &udpWrap{
AniDBUDP: udpapi.NewAniDBUDP(),
+ adb: adb,
sendQueueCh: make(chan paramSet, 10),
}
go u.sendQueue()
var bannedReply udpapi.APIReply = &bannedAPIReply{}
-func logRequest(set paramSet) {
+func (udp *udpWrap) logRequest(set paramSet) {
switch set.cmd {
case "AUTH":
- log.Printf("UDP>>> AUTH user=%s\n", set.params["user"])
+ udp.adb.Logger.Printf("UDP>>> AUTH user=%s\n", set.params["user"])
default:
- log.Printf("UDP>>> %s %s\n", set.cmd, udpapi.ParamMap(set.params).String())
+ udp.adb.Logger.Printf("UDP>>> %s %s\n", set.cmd, udpapi.ParamMap(set.params).String())
}
}
-func logReply(reply udpapi.APIReply) {
- log.Printf("UDP<<< %d %s\n", reply.Code(), reply.Text())
+func (udp *udpWrap) logReply(reply udpapi.APIReply) {
+ udp.adb.Logger.Printf("UDP<<< %d %s\n", reply.Code(), reply.Text())
}
func (udp *udpWrap) sendQueue() {
- initialWait := 6 * time.Second
+ initialWait := 5 * time.Second
wait := initialWait
for set := range udp.sendQueueCh {
Retry:
continue
}
- logRequest(set)
+ udp.logRequest(set)
reply := <-udp.AniDBUDP.SendRecv(set.cmd, udpapi.ParamMap(set.params))
if reply.Error() == udpapi.TimeoutError {
// retry
- wait = (wait * 15) / 10
+ wait = wait * 2
if wait > time.Minute {
wait = time.Minute
}
- log.Printf("UDP--- Timeout; waiting %s before retry", wait)
+ udp.adb.Logger.Printf("UDP--- Timeout; waiting %s before retry", wait)
+
+ delete(set.params, "s")
+ delete(set.params, "tag")
time.Sleep(wait)
goto Retry
}
- logReply(reply)
+ udp.logReply(reply)
wait = initialWait
case 403, 501, 506: // not logged in, or session expired
if r := udp.ReAuth(); r.Error() == nil {
// retry
+
+ delete(set.params, "s")
+ delete(set.params, "tag")
+
goto Retry
}
case 503, 504: // client library rejected
panic(reply.Error())
- case 555: // IP (and user, possibly client) temporarily banned
+ // 555: IP (and user, possibly client) temporarily banned
+ // 601: Server down (treat the same as a ban)
+ case 555, 601:
setBanned()
}
set.ch <- reply
}
}
-type errorReply struct {
- udpapi.APIReply
- err error
-}
-
-func (r *errorReply) Code() int {
- return 999
-}
-func (r *errorReply) Text() string {
- return r.err.Error()
-}
-func (r *errorReply) Error() error {
- return r.err
-}
-
func (udp *udpWrap) SendRecv(cmd string, params paramMap) <-chan udpapi.APIReply {
ch := make(chan udpapi.APIReply, 1)
}
}
+ if params == nil {
+ params = paramMap{}
+ }
+
udp.sendQueueCh <- paramSet{
cmd: cmd,
params: params,