Codebase list kcptun / 9f23ffd
Merge upstream tag: v20210103 Roger Shimizu 3 years ago
2 changed file(s) with 43 addition(s) and 34 deletion(s). Raw diff Collapse all Expand all
151151 --mode value profiles: fast3, fast2, fast, normal, manual (default: "fast")
152152 --conn value set num of UDP connections to server (default: 1)
153153 --autoexpire value set auto expiration time(in seconds) for a single UDP connection, 0 to disable (default: 0)
154 --scavengettl value set how long an expired connection can live(in sec), -1 to disable (default: 600)
154 --scavengettl value set how long an expired connection can live (in seconds) (default: 600)
155155 --mtu value set maximum transmission unit for UDP packets (default: 1350)
156156 --sndwnd value set send window size(num of packets) (default: 128)
157157 --rcvwnd value set receive window size(num of packets) (default: 512)
7272 }
7373 }
7474
75 type timedSession struct {
76 session *smux.Session
77 expiryDate time.Time
78 }
79
7580 func main() {
7681 rand.Seed(int64(time.Now().Nanosecond()))
7782 if VERSION == "SELFBUILD" {
123128 cli.IntFlag{
124129 Name: "scavengettl",
125130 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)",
127132 },
128133 cli.IntFlag{
129134 Name: "mtu",
420425 }
421426 }
422427
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
423436 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)
437438 rr := uint16(0)
438439 for {
439440 p1, err := listener.AcceptTCP()
443444 idx := rr % numconn
444445
445446 // 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)) {
448449 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 }
450454 }
451455
452456 go handleClient(muxes[idx].session, p1, config.Quiet)
456460 myApp.Run(os.Args)
457461 }
458462
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
465470 ticker := time.NewTicker(time.Second)
466471 defer ticker.Stop()
467 var sessionList []scavengeSession
472 var sessionList []timedSession
468473 for {
469474 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)})
473479 case <-ticker.C:
474 var newList []scavengeSession
480 if len(sessionList) == 0 {
481 continue
482 }
483
484 var newList []timedSession
475485 for k := range sessionList {
476486 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) {
479490 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())
483492 } else {
484493 newList = append(newList, sessionList[k])
485494 }