72 | 72 |
}
|
73 | 73 |
}
|
74 | 74 |
|
|
75 |
type timedSession struct {
|
|
76 |
session *smux.Session
|
|
77 |
expiryDate time.Time
|
|
78 |
}
|
|
79 |
|
75 | 80 |
func main() {
|
76 | 81 |
rand.Seed(int64(time.Now().Nanosecond()))
|
77 | 82 |
if VERSION == "SELFBUILD" {
|
|
123 | 128 |
cli.IntFlag{
|
124 | 129 |
Name: "scavengettl",
|
125 | 130 |
Value: 600,
|
126 | |
Usage: "set how long an expired connection can live(in sec), -1 to disable",
|
|
131 |
Usage: "set how long an expired connection can live (in seconds)",
|
127 | 132 |
},
|
128 | 133 |
cli.IntFlag{
|
129 | 134 |
Name: "mtu",
|
|
420 | 425 |
}
|
421 | 426 |
}
|
422 | 427 |
|
|
428 |
// start snmp logger
|
|
429 |
go generic.SnmpLogger(config.SnmpLog, config.SnmpPeriod)
|
|
430 |
|
|
431 |
// start scavenger
|
|
432 |
chScavenger := make(chan timedSession, 128)
|
|
433 |
go scavenger(chScavenger, &config)
|
|
434 |
|
|
435 |
// start listener
|
423 | 436 |
numconn := uint16(config.Conn)
|
424 | |
muxes := make([]struct {
|
425 | |
session *smux.Session
|
426 | |
ttl time.Time
|
427 | |
}, numconn)
|
428 | |
|
429 | |
for k := range muxes {
|
430 | |
muxes[k].session = waitConn()
|
431 | |
muxes[k].ttl = time.Now().Add(time.Duration(config.AutoExpire) * time.Second)
|
432 | |
}
|
433 | |
|
434 | |
chScavenger := make(chan *smux.Session, 128)
|
435 | |
go scavenger(chScavenger, config.ScavengeTTL)
|
436 | |
go generic.SnmpLogger(config.SnmpLog, config.SnmpPeriod)
|
|
437 |
muxes := make([]timedSession, numconn)
|
437 | 438 |
rr := uint16(0)
|
438 | 439 |
for {
|
439 | 440 |
p1, err := listener.AcceptTCP()
|
|
443 | 444 |
idx := rr % numconn
|
444 | 445 |
|
445 | 446 |
// do auto expiration && reconnection
|
446 | |
if muxes[idx].session.IsClosed() || (config.AutoExpire > 0 && time.Now().After(muxes[idx].ttl)) {
|
447 | |
chScavenger <- muxes[idx].session
|
|
447 |
if muxes[idx].session == nil || muxes[idx].session.IsClosed() ||
|
|
448 |
(config.AutoExpire > 0 && time.Now().After(muxes[idx].expiryDate)) {
|
448 | 449 |
muxes[idx].session = waitConn()
|
449 | |
muxes[idx].ttl = time.Now().Add(time.Duration(config.AutoExpire) * time.Second)
|
|
450 |
muxes[idx].expiryDate = time.Now().Add(time.Duration(config.AutoExpire) * time.Second)
|
|
451 |
if config.AutoExpire > 0 { // only when autoexpire set
|
|
452 |
chScavenger <- muxes[idx]
|
|
453 |
}
|
450 | 454 |
}
|
451 | 455 |
|
452 | 456 |
go handleClient(muxes[idx].session, p1, config.Quiet)
|
|
456 | 460 |
myApp.Run(os.Args)
|
457 | 461 |
}
|
458 | 462 |
|
459 | |
type scavengeSession struct {
|
460 | |
session *smux.Session
|
461 | |
ts time.Time
|
462 | |
}
|
463 | |
|
464 | |
func scavenger(ch chan *smux.Session, ttl int) {
|
|
463 |
func scavenger(ch chan timedSession, config *Config) {
|
|
464 |
// When AutoExpire is set to 0 (default), sessionList will keep empty.
|
|
465 |
// Then this routine won't need to do anything; thus just terminate it.
|
|
466 |
if config.AutoExpire <= 0 {
|
|
467 |
return
|
|
468 |
}
|
|
469 |
|
465 | 470 |
ticker := time.NewTicker(time.Second)
|
466 | 471 |
defer ticker.Stop()
|
467 | |
var sessionList []scavengeSession
|
|
472 |
var sessionList []timedSession
|
468 | 473 |
for {
|
469 | 474 |
select {
|
470 | |
case sess := <-ch:
|
471 | |
sessionList = append(sessionList, scavengeSession{sess, time.Now()})
|
472 | |
log.Println("session marked as expired", sess.RemoteAddr())
|
|
475 |
case item := <-ch:
|
|
476 |
sessionList = append(sessionList, timedSession{
|
|
477 |
item.session,
|
|
478 |
item.expiryDate.Add(time.Duration(config.ScavengeTTL) * time.Second)})
|
473 | 479 |
case <-ticker.C:
|
474 | |
var newList []scavengeSession
|
|
480 |
if len(sessionList) == 0 {
|
|
481 |
continue
|
|
482 |
}
|
|
483 |
|
|
484 |
var newList []timedSession
|
475 | 485 |
for k := range sessionList {
|
476 | 486 |
s := sessionList[k]
|
477 | |
if s.session.NumStreams() == 0 || s.session.IsClosed() {
|
478 | |
log.Println("session normally closed", s.session.RemoteAddr())
|
|
487 |
if s.session.IsClosed() {
|
|
488 |
log.Println("scavenger: session normally closed:", s.session.LocalAddr())
|
|
489 |
} else if time.Now().After(s.expiryDate) {
|
479 | 490 |
s.session.Close()
|
480 | |
} else if ttl >= 0 && time.Since(s.ts) >= time.Duration(ttl)*time.Second {
|
481 | |
log.Println("session reached scavenge ttl", s.session.RemoteAddr())
|
482 | |
s.session.Close()
|
|
491 |
log.Println("scavenger: session closed due to ttl:", s.session.LocalAddr())
|
483 | 492 |
} else {
|
484 | 493 |
newList = append(newList, sessionList[k])
|
485 | 494 |
}
|