Added configurable timeouts and overridable version string
This commit is contained in:
parent
a1d207d5fa
commit
c0e6d50e0c
49
irc.go
49
irc.go
@ -23,7 +23,21 @@ func (irc *Connection) readLoop() {
|
|||||||
br := bufio.NewReaderSize(irc.socket, 512)
|
br := bufio.NewReaderSize(irc.socket, 512)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
// Set a read deadline based on the combined timeout and ping frequency
|
||||||
|
// We should ALWAYS have received a response from the server within the timeout
|
||||||
|
// after our own pings
|
||||||
|
if irc.socket != nil {
|
||||||
|
irc.socket.SetReadDeadline(time.Now().Add(irc.Timeout + irc.PingFreq))
|
||||||
|
}
|
||||||
|
|
||||||
msg, err := br.ReadString('\n')
|
msg, err := br.ReadString('\n')
|
||||||
|
|
||||||
|
// We got past our blocking read, so bin timeout
|
||||||
|
if irc.socket != nil {
|
||||||
|
var zero time.Time
|
||||||
|
irc.socket.SetReadDeadline(zero)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
irc.Error <- err
|
irc.Error <- err
|
||||||
break
|
break
|
||||||
@ -77,7 +91,16 @@ func (irc *Connection) writeLoop() {
|
|||||||
if irc.Debug {
|
if irc.Debug {
|
||||||
irc.log.Printf("--> %s\n", b)
|
irc.log.Printf("--> %s\n", b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set a write deadline based on the time out
|
||||||
|
irc.socket.SetWriteDeadline(time.Now().Add(irc.Timeout))
|
||||||
|
|
||||||
_, err := irc.socket.Write([]byte(b))
|
_, err := irc.socket.Write([]byte(b))
|
||||||
|
|
||||||
|
// Past blocking write, bin timeout
|
||||||
|
var zero time.Time
|
||||||
|
irc.socket.SetWriteDeadline(zero)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
irc.Error <- err
|
irc.Error <- err
|
||||||
break
|
break
|
||||||
@ -86,19 +109,19 @@ func (irc *Connection) writeLoop() {
|
|||||||
irc.writerExit <- true
|
irc.writerExit <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
//Pings the server if we have not recived any messages for 5 minutes
|
//Pings the server if we have not received any messages for 5 minutes
|
||||||
func (irc *Connection) pingLoop() {
|
func (irc *Connection) pingLoop() {
|
||||||
ticker := time.NewTicker(1 * time.Minute) //Tick every minute.
|
ticker := time.NewTicker(1 * time.Minute) // Tick every minute for monitoring
|
||||||
ticker2 := time.NewTicker(15 * time.Minute) //Tick every 15 minutes.
|
ticker2 := time.NewTicker(irc.PingFreq) // Tick at the ping frequency.
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
//Ping if we haven't received anything from the server within 4 minutes
|
//Ping if we haven't received anything from the server within the keep alive period
|
||||||
if time.Since(irc.lastMessage) >= (4 * time.Minute) {
|
if time.Since(irc.lastMessage) >= irc.KeepAlive {
|
||||||
irc.SendRawf("PING %d", time.Now().UnixNano())
|
irc.SendRawf("PING %d", time.Now().UnixNano())
|
||||||
}
|
}
|
||||||
case <-ticker2.C:
|
case <-ticker2.C:
|
||||||
//Ping every 15 minutes.
|
//Ping at the ping frequency
|
||||||
irc.SendRawf("PING %d", time.Now().UnixNano())
|
irc.SendRawf("PING %d", time.Now().UnixNano())
|
||||||
//Try to recapture nickname if it's not as configured.
|
//Try to recapture nickname if it's not as configured.
|
||||||
if irc.nick != irc.nickcurrent {
|
if irc.nick != irc.nickcurrent {
|
||||||
@ -192,6 +215,10 @@ func (irc *Connection) Disconnect() {
|
|||||||
<-irc.pingerExit
|
<-irc.pingerExit
|
||||||
irc.socket.Close()
|
irc.socket.Close()
|
||||||
irc.socket = nil
|
irc.socket = nil
|
||||||
|
if irc.netsock != nil {
|
||||||
|
irc.netsock.Close()
|
||||||
|
irc.netsock = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (irc *Connection) Reconnect() error {
|
func (irc *Connection) Reconnect() error {
|
||||||
@ -204,9 +231,11 @@ func (irc *Connection) Connect(server string) error {
|
|||||||
|
|
||||||
var err error
|
var err error
|
||||||
if irc.UseTLS {
|
if irc.UseTLS {
|
||||||
irc.socket, err = tls.Dial("tcp", irc.server, irc.TLSConfig)
|
if irc.netsock, err = net.DialTimeout("tcp", irc.server, irc.Timeout); err == nil {
|
||||||
|
irc.socket = tls.Client(irc.netsock, irc.TLSConfig)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
irc.socket, err = net.Dial("tcp", irc.server)
|
irc.socket, err = net.DialTimeout("tcp", irc.server, irc.Timeout)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -238,6 +267,10 @@ func IRC(nick, user string) *Connection {
|
|||||||
writerExit: make(chan bool),
|
writerExit: make(chan bool),
|
||||||
pingerExit: make(chan bool),
|
pingerExit: make(chan bool),
|
||||||
endping: make(chan bool),
|
endping: make(chan bool),
|
||||||
|
Version: VERSION,
|
||||||
|
KeepAlive: 4 * time.Minute,
|
||||||
|
Timeout: 1 * time.Minute,
|
||||||
|
PingFreq: 15 * time.Minute,
|
||||||
}
|
}
|
||||||
irc.setupCallbacks()
|
irc.setupCallbacks()
|
||||||
return irc
|
return irc
|
||||||
|
@ -84,7 +84,7 @@ func (irc *Connection) setupCallbacks() {
|
|||||||
|
|
||||||
//Version handler
|
//Version handler
|
||||||
irc.AddCallback("CTCP_VERSION", func(e *Event) {
|
irc.AddCallback("CTCP_VERSION", func(e *Event) {
|
||||||
irc.SendRawf("NOTICE %s :\x01VERSION %s\x01", e.Nick, VERSION)
|
irc.SendRawf("NOTICE %s :\x01VERSION %s\x01", e.Nick, irc.Version)
|
||||||
})
|
})
|
||||||
|
|
||||||
irc.AddCallback("CTCP_USERINFO", func(e *Event) {
|
irc.AddCallback("CTCP_USERINFO", func(e *Event) {
|
||||||
|
@ -17,8 +17,13 @@ type Connection struct {
|
|||||||
Password string
|
Password string
|
||||||
UseTLS bool
|
UseTLS bool
|
||||||
TLSConfig *tls.Config
|
TLSConfig *tls.Config
|
||||||
|
Version string
|
||||||
|
Timeout time.Duration
|
||||||
|
PingFreq time.Duration
|
||||||
|
KeepAlive time.Duration
|
||||||
|
|
||||||
socket net.Conn
|
socket net.Conn
|
||||||
|
netsock net.Conn
|
||||||
pread, pwrite chan string
|
pread, pwrite chan string
|
||||||
readerExit, writerExit, pingerExit chan bool
|
readerExit, writerExit, pingerExit chan bool
|
||||||
endping chan bool
|
endping chan bool
|
||||||
|
Loading…
Reference in New Issue
Block a user