import (
"encoding/gob"
"github.com/Kovensky/go-anidb/udp"
+ "log"
+ "sync"
"time"
)
type udpWrap struct {
*udpapi.AniDBUDP
+ sendLock sync.Mutex
sendQueueCh chan paramSet
+ credLock sync.Mutex
credentials *credentials
connected bool
}
var bannedReply udpapi.APIReply = &bannedAPIReply{}
+func logRequest(set paramSet) {
+ switch set.cmd {
+ case "AUTH":
+ log.Printf("UDP>>> AUTH user=%s\n", set.params["user"])
+ default:
+ log.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) sendQueue() {
initialWait := 6 * time.Second
wait := initialWait
for set := range udp.sendQueueCh {
Retry:
+ if Banned() {
+ set.ch <- bannedReply
+ close(set.ch)
+ continue
+ }
+
+ logRequest(set)
reply := <-udp.AniDBUDP.SendRecv(set.cmd, udpapi.ParamMap(set.params))
if reply.Error() == udpapi.TimeoutError {
if wait > time.Minute {
wait = time.Minute
}
+ log.Printf("UDP--- Timeout; waiting %s before retry", wait)
+
time.Sleep(wait)
goto Retry
}
+ logReply(reply)
+
wait = initialWait
switch reply.Code() {
case 403, 501, 506: // not logged in, or session expired
- if err := udp.ReAuth(); err == nil {
+ if r := udp.ReAuth(); r.Error() == nil {
// retry
goto Retry
}
}
}
+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 udp.credentials == nil {
- ch <- &noauthAPIReply{}
- close(ch)
- return ch
- }
+
+ udp.sendLock.Lock()
+ defer udp.sendLock.Unlock()
if Banned() {
ch <- bannedReply
return ch
}
+ if !udp.connected {
+ if r := udp.ReAuth(); r.Error() != nil {
+ ch <- r
+ close(ch)
+ return ch
+ }
+ }
+
udp.sendQueueCh <- paramSet{
cmd: cmd,
params: params,