Implement reconnection retry on disconnect.

This fixes a problem when trying to download multiple files from same server
main
Stefano 2021-11-26 17:35:43 +01:00
parent d2c8df3593
commit 0c6b340499
1 changed files with 38 additions and 32 deletions

54
xdcc.go
View File

@ -118,36 +118,25 @@ func (transfer *XdccTransfer) Start() error {
return transfer.conn.Connect() return transfer.conn.Connect()
} }
type XdccEvent interface{} type TransferEvent interface{}
type TransferAbortedEvent struct { type TransferAbortedEvent struct {
Error string Error string
} }
const maxConnAttempts = 5
type XdccTransfer struct { type XdccTransfer struct {
filePath string filePath string
url IRCFileURL url IRCFileURL
conn *irc.Conn conn *irc.Conn
connAttempts int
started bool started bool
events chan XdccEvent events chan TransferEvent
}
type TransferManager struct {
transfers map[IRCBot]*XdccTransfer
}
func (tm *TransferManager) addTransfer(fileUrl *IRCFileURL, filePath string) {
transfer, ok := tm.transfers[fileUrl.GetBot()]
if !ok {
transfer = NewXdccTransfer(*fileUrl, filePath)
tm.transfers[fileUrl.GetBot()] = transfer
// add transfer
}
} }
func NewXdccTransfer(url IRCFileURL, filePath string) *XdccTransfer { func NewXdccTransfer(url IRCFileURL, filePath string) *XdccTransfer {
rand.Seed(time.Now().UTC().UnixNano())
conn := irc.SimpleClient(IRCClientUserName + strconv.Itoa(int(rand.Uint32()))) conn := irc.SimpleClient(IRCClientUserName + strconv.Itoa(int(rand.Uint32())))
conn.Config().Server = url.Network conn.Config().Server = url.Network
conn.Config().NewNick = func(nick string) string { conn.Config().NewNick = func(nick string) string {
@ -159,7 +148,8 @@ func NewXdccTransfer(url IRCFileURL, filePath string) *XdccTransfer {
url: url, url: url,
filePath: filePath, filePath: filePath,
started: false, started: false,
events: make(chan XdccEvent, defaultEventChanSize), connAttempts: 0,
events: make(chan TransferEvent, defaultEventChanSize),
} }
t.setupHandlers(url.Channel, url.UserName, url.Slot) t.setupHandlers(url.Channel, url.UserName, url.Slot)
return t return t
@ -175,22 +165,28 @@ func (transfer *XdccTransfer) setupHandlers(channel string, userName string, slo
// e.g. join channel on connect. // e.g. join channel on connect.
conn.HandleFunc(irc.CONNECTED, conn.HandleFunc(irc.CONNECTED,
func(conn *irc.Conn, line *irc.Line) { func(conn *irc.Conn, line *irc.Line) {
fmt.Println("connected ", channel) transfer.connAttempts = 0
conn.Join(channel) conn.Join(channel)
}) })
conn.HandleFunc(irc.ERROR, func(conn *irc.Conn, line *irc.Line) {
})
// send xdcc send on successfull join // send xdcc send on successfull join
conn.HandleFunc(irc.JOIN, conn.HandleFunc(irc.JOIN,
func(conn *irc.Conn, line *irc.Line) { func(conn *irc.Conn, line *irc.Line) {
if line.Args[0] == channel && !transfer.started { if line.Args[0] == channel && !transfer.started {
fmt.Println("contacting ", transfer.url.UserName)
transfer.send(&XdccSendReq{Slot: slot}) transfer.send(&XdccSendReq{Slot: slot})
} }
}) })
conn.HandleFunc(irc.PRIVMSG, func(conn *irc.Conn, line *irc.Line) {
})
conn.HandleFunc(irc.CTCP, conn.HandleFunc(irc.CTCP,
func(conn *irc.Conn, line *irc.Line) { func(conn *irc.Conn, line *irc.Line) {
fmt.Println(line.Text())
res, err := parseCTCPRes(line.Text()) res, err := parseCTCPRes(line.Text())
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
@ -201,13 +197,23 @@ func (transfer *XdccTransfer) setupHandlers(channel string, userName string, slo
conn.HandleFunc(irc.DISCONNECTED, conn.HandleFunc(irc.DISCONNECTED,
func(conn *irc.Conn, line *irc.Line) { func(conn *irc.Conn, line *irc.Line) {
if !transfer.started { var err error = nil
if transfer.connAttempts < maxConnAttempts {
time.Sleep(time.Second)
err = conn.Connect()
}
if (err != nil || transfer.connAttempts >= maxConnAttempts) && !transfer.started {
transfer.notifyEvent(&TransferAbortedEvent{Error: "disconnected from server"}) transfer.notifyEvent(&TransferAbortedEvent{Error: "disconnected from server"})
} }
transfer.connAttempts++
}) })
} }
func (transfer *XdccTransfer) PollEvents() chan XdccEvent { func (transfer *XdccTransfer) PollEvents() chan TransferEvent {
return transfer.events return transfer.events
} }
@ -225,7 +231,7 @@ type TransferStartedEvent struct {
type TransferCompletedEvent struct{} type TransferCompletedEvent struct{}
func (transfer *XdccTransfer) notifyEvent(e XdccEvent) { func (transfer *XdccTransfer) notifyEvent(e TransferEvent) {
select { select {
case transfer.events <- e: case transfer.events <- e:
default: default: