Quellcode durchsuchen

exempt a configurable number of MARKREAD commands from fakelag

tags/v2.11.0-rc1
Shivaram Lingamneni vor 1 Jahr
Ursprung
Commit
7ad31497c2
6 geänderte Dateien mit 58 neuen und 11 gelöschten Zeilen
  1. 8
    0
      default.yaml
  2. 12
    4
      irc/client.go
  3. 12
    0
      irc/config.go
  4. 12
    1
      irc/fakelag.go
  5. 6
    6
      irc/fakelag_test.go
  6. 8
    0
      traditional.yaml

+ 8
- 0
default.yaml Datei anzeigen

849
     # sending any commands:
849
     # sending any commands:
850
     cooldown: 2s
850
     cooldown: 2s
851
 
851
 
852
+    # exempt a certain number of command invocations per session from fakelag;
853
+    # this is to speed up "resynchronization" of client state during reattach
854
+    command-budgets:
855
+        "CHATHISTORY": 16
856
+        "MARKREAD":    16
857
+        "MONITOR":     1
858
+        "WHO":         4
859
+
852
 # the roleplay commands are semi-standardized extensions to IRC that allow
860
 # the roleplay commands are semi-standardized extensions to IRC that allow
853
 # sending and receiving messages from pseudo-nicknames. this can be used either
861
 # sending and receiving messages from pseudo-nicknames. this can be used either
854
 # for actual roleplaying, or for bridging IRC with other protocols.
862
 # for actual roleplaying, or for bridging IRC with other protocols.

+ 12
- 4
irc/client.go Datei anzeigen

668
 			}
668
 			}
669
 		}
669
 		}
670
 
670
 
671
+		msg, err := ircmsg.ParseLineStrict(line, true, MaxLineLen)
672
+		// XXX defer processing of command error parsing until after fakelag
673
+
671
 		if client.registered {
674
 		if client.registered {
672
-			touches := session.deferredFakelagCount + 1
675
+			// apply deferred fakelag
676
+			for i := 0; i < session.deferredFakelagCount; i++ {
677
+				session.fakelag.Touch("")
678
+			}
673
 			session.deferredFakelagCount = 0
679
 			session.deferredFakelagCount = 0
674
-			for i := 0; i < touches; i++ {
675
-				session.fakelag.Touch()
680
+			// touch for the current command
681
+			var command string
682
+			if err == nil {
683
+				command = msg.Command
676
 			}
684
 			}
685
+			session.fakelag.Touch(command)
677
 		} else {
686
 		} else {
678
 			// DoS hardening, #505
687
 			// DoS hardening, #505
679
 			session.registrationMessages++
688
 			session.registrationMessages++
683
 			}
692
 			}
684
 		}
693
 		}
685
 
694
 
686
-		msg, err := ircmsg.ParseLineStrict(line, true, MaxLineLen)
687
 		if err == ircmsg.ErrorLineIsEmpty {
695
 		if err == ircmsg.ErrorLineIsEmpty {
688
 			continue
696
 			continue
689
 		} else if err == ircmsg.ErrorTagsTooLong {
697
 		} else if err == ircmsg.ErrorTagsTooLong {

+ 12
- 0
irc/config.go Datei anzeigen

524
 	BurstLimit        uint `yaml:"burst-limit"`
524
 	BurstLimit        uint `yaml:"burst-limit"`
525
 	MessagesPerWindow uint `yaml:"messages-per-window"`
525
 	MessagesPerWindow uint `yaml:"messages-per-window"`
526
 	Cooldown          time.Duration
526
 	Cooldown          time.Duration
527
+	CommandBudgets    map[string]int `yaml:"command-budgets"`
527
 }
528
 }
528
 
529
 
529
 type TorListenersConfig struct {
530
 type TorListenersConfig struct {
1428
 	}
1429
 	}
1429
 	config.Server.capValues[caps.Languages] = config.languageManager.CapValue()
1430
 	config.Server.capValues[caps.Languages] = config.languageManager.CapValue()
1430
 
1431
 
1432
+	if len(config.Fakelag.CommandBudgets) != 0 {
1433
+		// normalize command names to uppercase:
1434
+		commandBudgets := make(map[string]int, len(config.Fakelag.CommandBudgets))
1435
+		for command, budget := range config.Fakelag.CommandBudgets {
1436
+			commandBudgets[strings.ToUpper(command)] = budget
1437
+		}
1438
+		config.Fakelag.CommandBudgets = commandBudgets
1439
+	} else {
1440
+		config.Fakelag.CommandBudgets = nil
1441
+	}
1442
+
1431
 	if config.Server.Relaymsg.Enabled {
1443
 	if config.Server.Relaymsg.Enabled {
1432
 		for _, char := range protocolBreakingNameCharacters {
1444
 		for _, char := range protocolBreakingNameCharacters {
1433
 			if strings.ContainsRune(config.Server.Relaymsg.Separators, char) {
1445
 			if strings.ContainsRune(config.Server.Relaymsg.Separators, char) {

+ 12
- 1
irc/fakelag.go Datei anzeigen

5
 
5
 
6
 import (
6
 import (
7
 	"time"
7
 	"time"
8
+
9
+	"github.com/ergochat/ergo/irc/utils"
8
 )
10
 )
9
 
11
 
10
 // fakelag is a system for artificially delaying commands when a user issues
12
 // fakelag is a system for artificially delaying commands when a user issues
36
 
38
 
37
 func (fl *Fakelag) Initialize(config FakelagConfig) {
39
 func (fl *Fakelag) Initialize(config FakelagConfig) {
38
 	fl.config = config
40
 	fl.config = config
41
+	// XXX don't share mutable member CommandBudgets:
42
+	if config.CommandBudgets != nil {
43
+		fl.config.CommandBudgets = utils.CopyMap(config.CommandBudgets)
44
+	}
39
 	fl.nowFunc = time.Now
45
 	fl.nowFunc = time.Now
40
 	fl.sleepFunc = time.Sleep
46
 	fl.sleepFunc = time.Sleep
41
 	fl.state = FakelagBursting
47
 	fl.state = FakelagBursting
58
 }
64
 }
59
 
65
 
60
 // register a new command, sleep if necessary to delay it
66
 // register a new command, sleep if necessary to delay it
61
-func (fl *Fakelag) Touch() {
67
+func (fl *Fakelag) Touch(command string) {
62
 	if !fl.config.Enabled {
68
 	if !fl.config.Enabled {
63
 		return
69
 		return
64
 	}
70
 	}
65
 
71
 
72
+	if budget, ok := fl.config.CommandBudgets[command]; ok && budget > 0 {
73
+		fl.config.CommandBudgets[command] = budget - 1
74
+		return
75
+	}
76
+
66
 	now := fl.nowFunc()
77
 	now := fl.nowFunc()
67
 	// XXX if lastTouch.IsZero(), treat it as "very far in the past", which is fine
78
 	// XXX if lastTouch.IsZero(), treat it as "very far in the past", which is fine
68
 	elapsed := now.Sub(fl.lastTouch)
79
 	elapsed := now.Sub(fl.lastTouch)

+ 6
- 6
irc/fakelag_test.go Datei anzeigen

60
 	window, _ := time.ParseDuration("1s")
60
 	window, _ := time.ParseDuration("1s")
61
 	fl, mt := newFakelagForTesting(window, 3, 2, window)
61
 	fl, mt := newFakelagForTesting(window, 3, 2, window)
62
 
62
 
63
-	fl.Touch()
63
+	fl.Touch("")
64
 	slept, _ := mt.lastSleep()
64
 	slept, _ := mt.lastSleep()
65
 	if slept {
65
 	if slept {
66
 		t.Fatalf("should not have slept")
66
 		t.Fatalf("should not have slept")
69
 	interval, _ := time.ParseDuration("100ms")
69
 	interval, _ := time.ParseDuration("100ms")
70
 	for i := 0; i < 2; i++ {
70
 	for i := 0; i < 2; i++ {
71
 		mt.pause(interval)
71
 		mt.pause(interval)
72
-		fl.Touch()
72
+		fl.Touch("")
73
 		slept, _ := mt.lastSleep()
73
 		slept, _ := mt.lastSleep()
74
 		if slept {
74
 		if slept {
75
 			t.Fatalf("should not have slept")
75
 			t.Fatalf("should not have slept")
77
 	}
77
 	}
78
 
78
 
79
 	mt.pause(interval)
79
 	mt.pause(interval)
80
-	fl.Touch()
80
+	fl.Touch("")
81
 	if fl.state != FakelagThrottled {
81
 	if fl.state != FakelagThrottled {
82
 		t.Fatalf("should be throttled")
82
 		t.Fatalf("should be throttled")
83
 	}
83
 	}
91
 	}
91
 	}
92
 
92
 
93
 	// send another message without a pause; we should have to sleep for 500 msec
93
 	// send another message without a pause; we should have to sleep for 500 msec
94
-	fl.Touch()
94
+	fl.Touch("")
95
 	if fl.state != FakelagThrottled {
95
 	if fl.state != FakelagThrottled {
96
 		t.Fatalf("should be throttled")
96
 		t.Fatalf("should be throttled")
97
 	}
97
 	}
102
 	}
102
 	}
103
 
103
 
104
 	mt.pause(interval * 6)
104
 	mt.pause(interval * 6)
105
-	fl.Touch()
105
+	fl.Touch("")
106
 	if fl.state != FakelagThrottled {
106
 	if fl.state != FakelagThrottled {
107
 		t.Fatalf("should still be throttled")
107
 		t.Fatalf("should still be throttled")
108
 	}
108
 	}
112
 	}
112
 	}
113
 
113
 
114
 	mt.pause(window * 2)
114
 	mt.pause(window * 2)
115
-	fl.Touch()
115
+	fl.Touch("")
116
 	if fl.state != FakelagBursting {
116
 	if fl.state != FakelagBursting {
117
 		t.Fatalf("should be bursting again")
117
 		t.Fatalf("should be bursting again")
118
 	}
118
 	}

+ 8
- 0
traditional.yaml Datei anzeigen

821
     # sending any commands:
821
     # sending any commands:
822
     cooldown: 2s
822
     cooldown: 2s
823
 
823
 
824
+    # exempt a certain number of command invocations per session from fakelag;
825
+    # this is to speed up "resynchronization" of client state during reattach
826
+    command-budgets:
827
+        "CHATHISTORY": 16
828
+        "MARKREAD":    16
829
+        "MONITOR":     1
830
+        "WHO":         4
831
+
824
 # the roleplay commands are semi-standardized extensions to IRC that allow
832
 # the roleplay commands are semi-standardized extensions to IRC that allow
825
 # sending and receiving messages from pseudo-nicknames. this can be used either
833
 # sending and receiving messages from pseudo-nicknames. this can be used either
826
 # for actual roleplaying, or for bridging IRC with other protocols.
834
 # for actual roleplaying, or for bridging IRC with other protocols.

Laden…
Abbrechen
Speichern