• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nats-io / nats-server / 24949216239

24 Apr 2026 08:34AM UTC coverage: 80.645% (-2.4%) from 83.05%
24949216239

push

github

web-flow
(2.14) [ADDED] `RemoteLeafOpts.IgnoreDiscoveredServers` option (#8067)

For a given leafnode remote, if this is set to true, this remote will
ignore any server leafnode URLs returned by the hub, allowing the user
to fully manage the servers this remote can connect to.

Resolves #8002

Signed-off-by: Ivan Kozlovic <ivan@synadia.com>

74685 of 92610 relevant lines covered (80.64%)

632737.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.75
/server/parser.go
1
// Copyright 2012-2025 The NATS Authors
2
// Licensed under the Apache License, Version 2.0 (the "License");
3
// you may not use this file except in compliance with the License.
4
// You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software
9
// distributed under the License is distributed on an "AS IS" BASIS,
10
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
// See the License for the specific language governing permissions and
12
// limitations under the License.
13

14
package server
15

16
import (
17
        "bufio"
18
        "bytes"
19
        "fmt"
20
        "net/http"
21
        "net/textproto"
22
)
23

24
type parserState int
25
type parseState struct {
26
        state   parserState
27
        op      byte
28
        as      int
29
        drop    int
30
        pa      pubArg
31
        argBuf  []byte
32
        msgBuf  []byte
33
        header  http.Header // access via getHeader
34
        scratch [MAX_CONTROL_LINE_SIZE]byte
35
        argsa   [MAX_HMSG_ARGS + 1][]byte // pre-allocated args array to avoid per-call heap escape
36
}
37

38
type pubArg struct {
39
        arg       []byte
40
        pacache   []byte
41
        origin    []byte
42
        account   []byte
43
        subject   []byte
44
        deliver   []byte
45
        mapped    []byte
46
        reply     []byte
47
        szb       []byte
48
        hdb       []byte
49
        queues    [][]byte
50
        size      int
51
        hdr       int
52
        psi       []*serviceImport
53
        trace     *msgTrace
54
        delivered bool // Only used for service imports
55
}
56

57
// Parser constants
58
const (
59
        OP_START parserState = iota
60
        OP_PLUS
61
        OP_PLUS_O
62
        OP_PLUS_OK
63
        OP_MINUS
64
        OP_MINUS_E
65
        OP_MINUS_ER
66
        OP_MINUS_ERR
67
        OP_MINUS_ERR_SPC
68
        MINUS_ERR_ARG
69
        OP_C
70
        OP_CO
71
        OP_CON
72
        OP_CONN
73
        OP_CONNE
74
        OP_CONNEC
75
        OP_CONNECT
76
        CONNECT_ARG
77
        OP_H
78
        OP_HP
79
        OP_HPU
80
        OP_HPUB
81
        OP_HPUB_SPC
82
        HPUB_ARG
83
        OP_HM
84
        OP_HMS
85
        OP_HMSG
86
        OP_HMSG_SPC
87
        HMSG_ARG
88
        OP_P
89
        OP_PU
90
        OP_PUB
91
        OP_PUB_SPC
92
        PUB_ARG
93
        OP_PI
94
        OP_PIN
95
        OP_PING
96
        OP_PO
97
        OP_PON
98
        OP_PONG
99
        MSG_PAYLOAD
100
        MSG_END_R
101
        MSG_END_N
102
        OP_S
103
        OP_SU
104
        OP_SUB
105
        OP_SUB_SPC
106
        SUB_ARG
107
        OP_A
108
        OP_ASUB
109
        OP_ASUB_SPC
110
        ASUB_ARG
111
        OP_AUSUB
112
        OP_AUSUB_SPC
113
        AUSUB_ARG
114
        OP_L
115
        OP_LS
116
        OP_R
117
        OP_RS
118
        OP_U
119
        OP_UN
120
        OP_UNS
121
        OP_UNSU
122
        OP_UNSUB
123
        OP_UNSUB_SPC
124
        UNSUB_ARG
125
        OP_M
126
        OP_MS
127
        OP_MSG
128
        OP_MSG_SPC
129
        MSG_ARG
130
        OP_I
131
        OP_IN
132
        OP_INF
133
        OP_INFO
134
        INFO_ARG
135
)
136

137
func (c *client) parse(buf []byte) error {
16,367,510✔
138
        // Branch out to mqtt clients. c.mqtt is immutable, but should it become
16,367,510✔
139
        // an issue (say data race detection), we could branch outside in readLoop
16,367,510✔
140
        if c.isMqtt() {
16,368,736✔
141
                return c.mqttParse(buf)
1,226✔
142
        }
1,226✔
143
        var i int
16,366,284✔
144
        var b byte
16,366,284✔
145
        var lmsg bool
16,366,284✔
146

16,366,284✔
147
        // Snapshots
16,366,284✔
148
        c.mu.Lock()
16,366,284✔
149
        // Snapshot and then reset when we receive a
16,366,284✔
150
        // proper CONNECT if needed.
16,366,284✔
151
        authSet := c.awaitingAuth()
16,366,284✔
152
        // Snapshot max control line as well.
16,366,284✔
153
        s, mcl, trace := c.srv, c.mcl, c.trace
16,366,284✔
154
        c.mu.Unlock()
16,366,284✔
155

16,366,284✔
156
        // Move to loop instead of range syntax to allow jumping of i
16,366,284✔
157
        for i = 0; i < len(buf); i++ {
1,196,769,677✔
158
                b = buf[i]
1,180,403,393✔
159

1,180,403,393✔
160
                switch c.state {
1,180,403,393✔
161
                case OP_START:
28,792,875✔
162
                        c.op = b
28,792,875✔
163
                        if b != 'C' && b != 'c' {
57,542,464✔
164
                                if authSet {
28,750,192✔
165
                                        if s == nil {
603✔
166
                                                goto authErr
×
167
                                        }
168
                                        var ok bool
603✔
169
                                        switch c.kind {
603✔
170
                                        case CLIENT:
3✔
171
                                                // Check here for NoAuthUser. If this is set allow non CONNECT protos as our first.
3✔
172
                                                // E.g. telnet proto demos.
3✔
173
                                                opts := s.getOpts()
3✔
174
                                                noAuthUser := opts.NoAuthUser
3✔
175
                                                if c.ws != nil {
3✔
176
                                                        if noAuthUserWS := opts.Websocket.NoAuthUser; noAuthUserWS != _EMPTY_ {
×
177
                                                                noAuthUser = noAuthUserWS
×
178
                                                        }
×
179
                                                }
180
                                                if noAuthUser != _EMPTY_ {
5✔
181
                                                        s.mu.Lock()
2✔
182
                                                        user, exists := s.users[noAuthUser]
2✔
183
                                                        s.mu.Unlock()
2✔
184
                                                        if exists {
4✔
185
                                                                c.RegisterUser(user)
2✔
186
                                                                c.mu.Lock()
2✔
187
                                                                c.clearAuthTimer()
2✔
188
                                                                c.flags.set(connectReceived)
2✔
189
                                                                c.mu.Unlock()
2✔
190
                                                                authSet, ok = false, true
2✔
191
                                                        }
2✔
192
                                                }
193
                                        case LEAF:
583✔
194
                                                // Compressed inbound leaf-node negotiation may require INFO
583✔
195
                                                // before CONNECT. Without compression, leaf connections must
583✔
196
                                                // still start with CONNECT.
583✔
197
                                                ok = (b == 'I' || b == 'i') && needsCompression(s.getOpts().LeafNode.Compression.Mode)
583✔
198
                                        }
199
                                        if !ok {
631✔
200
                                                goto authErr
28✔
201
                                        }
202
                                }
203
                        }
204
                        switch b {
28,792,847✔
205
                        case 'P', 'p':
10,233,826✔
206
                                c.state = OP_P
10,233,826✔
207
                        case 'H', 'h':
1,992,256✔
208
                                c.state = OP_H
1,992,256✔
209
                        case 'S', 's':
136,218✔
210
                                c.state = OP_S
136,218✔
211
                        case 'U', 'u':
15,570✔
212
                                c.state = OP_U
15,570✔
213
                        case 'R', 'r':
16,120,112✔
214
                                if c.kind == CLIENT {
16,120,112✔
215
                                        goto parseErr
×
216
                                } else {
16,120,112✔
217
                                        c.state = OP_R
16,120,112✔
218
                                }
16,120,112✔
219
                        case 'L', 'l':
166,388✔
220
                                if c.kind != LEAF && c.kind != ROUTER {
166,388✔
221
                                        goto parseErr
×
222
                                } else {
166,388✔
223
                                        c.state = OP_L
166,388✔
224
                                }
166,388✔
225
                        case 'A', 'a':
31✔
226
                                if c.kind == CLIENT {
31✔
227
                                        goto parseErr
×
228
                                } else {
31✔
229
                                        c.state = OP_A
31✔
230
                                }
31✔
231
                        case 'C', 'c':
43,286✔
232
                                c.state = OP_C
43,286✔
233
                        case 'I', 'i':
85,065✔
234
                                c.state = OP_I
85,065✔
235
                        case '+':
×
236
                                c.state = OP_PLUS
×
237
                        case '-':
94✔
238
                                c.state = OP_MINUS
94✔
239
                        default:
1✔
240
                                goto parseErr
1✔
241
                        }
242
                case OP_H:
1,992,256✔
243
                        switch b {
1,992,256✔
244
                        case 'P', 'p':
962,580✔
245
                                c.state = OP_HP
962,580✔
246
                        case 'M', 'm':
1,029,676✔
247
                                c.state = OP_HM
1,029,676✔
248
                        default:
×
249
                                goto parseErr
×
250
                        }
251
                case OP_HP:
962,580✔
252
                        switch b {
962,580✔
253
                        case 'U', 'u':
962,580✔
254
                                c.state = OP_HPU
962,580✔
255
                        default:
×
256
                                goto parseErr
×
257
                        }
258
                case OP_HPU:
962,580✔
259
                        switch b {
962,580✔
260
                        case 'B', 'b':
962,580✔
261
                                c.state = OP_HPUB
962,580✔
262
                        default:
×
263
                                goto parseErr
×
264
                        }
265
                case OP_HPUB:
962,580✔
266
                        switch b {
962,580✔
267
                        case ' ', '\t':
962,580✔
268
                                c.state = OP_HPUB_SPC
962,580✔
269
                        default:
×
270
                                goto parseErr
×
271
                        }
272
                case OP_HPUB_SPC:
962,580✔
273
                        switch b {
962,580✔
274
                        case ' ', '\t':
×
275
                                continue
×
276
                        default:
962,580✔
277
                                c.pa.hdr = 0
962,580✔
278
                                c.state = HPUB_ARG
962,580✔
279
                                c.as = i
962,580✔
280
                        }
281
                case HPUB_ARG:
34,962,672✔
282
                        switch b {
34,962,672✔
283
                        case '\r':
962,579✔
284
                                c.drop = 1
962,579✔
285
                        case '\n':
962,579✔
286
                                var arg []byte
962,579✔
287
                                if c.argBuf != nil {
962,666✔
288
                                        arg = c.argBuf
87✔
289
                                        c.argBuf = nil
87✔
290
                                } else {
962,579✔
291
                                        arg = buf[c.as : i-c.drop]
962,492✔
292
                                }
962,492✔
293
                                if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
962,579✔
294
                                        return err
×
295
                                }
×
296
                                if trace {
1,033,516✔
297
                                        c.traceInOp("HPUB", arg)
70,937✔
298
                                }
70,937✔
299
                                var remaining []byte
962,579✔
300
                                if i < len(buf) {
1,925,158✔
301
                                        remaining = buf[i+1:]
962,579✔
302
                                }
962,579✔
303
                                if err := c.processHeaderPub(arg, remaining); err != nil {
962,581✔
304
                                        return err
2✔
305
                                }
2✔
306

307
                                c.drop, c.as, c.state = 0, i+1, MSG_PAYLOAD
962,577✔
308
                                // If we don't have a saved buffer then jump ahead with
962,577✔
309
                                // the index. If this overruns what is left we fall out
962,577✔
310
                                // and process split buffer.
962,577✔
311
                                if c.msgBuf == nil {
1,925,154✔
312
                                        i = c.as + c.pa.size - LEN_CR_LF
962,577✔
313
                                }
962,577✔
314
                        default:
33,037,514✔
315
                                if c.argBuf != nil {
33,038,492✔
316
                                        c.argBuf = append(c.argBuf, b)
978✔
317
                                }
978✔
318
                        }
319
                case OP_HM:
1,029,676✔
320
                        switch b {
1,029,676✔
321
                        case 'S', 's':
1,029,676✔
322
                                c.state = OP_HMS
1,029,676✔
323
                        default:
×
324
                                goto parseErr
×
325
                        }
326
                case OP_HMS:
1,029,676✔
327
                        switch b {
1,029,676✔
328
                        case 'G', 'g':
1,029,676✔
329
                                c.state = OP_HMSG
1,029,676✔
330
                        default:
×
331
                                goto parseErr
×
332
                        }
333
                case OP_HMSG:
1,029,676✔
334
                        switch b {
1,029,676✔
335
                        case ' ', '\t':
1,029,676✔
336
                                c.state = OP_HMSG_SPC
1,029,676✔
337
                        default:
×
338
                                goto parseErr
×
339
                        }
340
                case OP_HMSG_SPC:
1,029,676✔
341
                        switch b {
1,029,676✔
342
                        case ' ', '\t':
×
343
                                continue
×
344
                        default:
1,029,676✔
345
                                c.pa.hdr = 0
1,029,676✔
346
                                c.state = HMSG_ARG
1,029,676✔
347
                                c.as = i
1,029,676✔
348
                        }
349
                case HMSG_ARG:
85,095,683✔
350
                        switch b {
85,095,683✔
351
                        case '\r':
1,029,676✔
352
                                c.drop = 1
1,029,676✔
353
                        case '\n':
1,029,676✔
354
                                var arg []byte
1,029,676✔
355
                                if c.argBuf != nil {
1,039,920✔
356
                                        arg = c.argBuf
10,244✔
357
                                        c.argBuf = nil
10,244✔
358
                                } else {
1,029,676✔
359
                                        arg = buf[c.as : i-c.drop]
1,019,432✔
360
                                }
1,019,432✔
361
                                if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
1,029,676✔
362
                                        return err
×
363
                                }
×
364
                                var err error
1,029,676✔
365
                                if c.kind == ROUTER || c.kind == GATEWAY {
2,058,951✔
366
                                        if trace {
1,031,418✔
367
                                                c.traceInOp("HMSG", arg)
2,143✔
368
                                        }
2,143✔
369
                                        err = c.processRoutedHeaderMsgArgs(arg)
1,029,275✔
370
                                } else if c.kind == LEAF {
802✔
371
                                        if trace {
557✔
372
                                                c.traceInOp("HMSG", arg)
156✔
373
                                        }
156✔
374
                                        err = c.processLeafHeaderMsgArgs(arg)
401✔
375
                                }
376
                                if err != nil {
1,029,676✔
377
                                        return err
×
378
                                }
×
379
                                c.drop, c.as, c.state = 0, i+1, MSG_PAYLOAD
1,029,676✔
380

1,029,676✔
381
                                // jump ahead with the index. If this overruns
1,029,676✔
382
                                // what is left we fall out and process split
1,029,676✔
383
                                // buffer.
1,029,676✔
384
                                i = c.as + c.pa.size - LEN_CR_LF
1,029,676✔
385
                        default:
83,036,331✔
386
                                if c.argBuf != nil {
83,477,256✔
387
                                        c.argBuf = append(c.argBuf, b)
440,925✔
388
                                }
440,925✔
389
                        }
390
                case OP_P:
10,233,825✔
391
                        switch b {
10,233,825✔
392
                        case 'U', 'u':
10,166,897✔
393
                                c.state = OP_PU
10,166,897✔
394
                        case 'I', 'i':
39,348✔
395
                                c.state = OP_PI
39,348✔
396
                        case 'O', 'o':
27,580✔
397
                                c.state = OP_PO
27,580✔
398
                        default:
×
399
                                goto parseErr
×
400
                        }
401
                case OP_PU:
10,166,897✔
402
                        switch b {
10,166,897✔
403
                        case 'B', 'b':
10,166,897✔
404
                                c.state = OP_PUB
10,166,897✔
405
                        default:
×
406
                                goto parseErr
×
407
                        }
408
                case OP_PUB:
10,166,897✔
409
                        switch b {
10,166,897✔
410
                        case ' ', '\t':
10,166,896✔
411
                                c.state = OP_PUB_SPC
10,166,896✔
412
                        default:
1✔
413
                                goto parseErr
1✔
414
                        }
415
                case OP_PUB_SPC:
10,166,895✔
416
                        switch b {
10,166,895✔
417
                        case ' ', '\t':
×
418
                                continue
×
419
                        default:
10,166,895✔
420
                                c.pa.hdr = -1
10,166,895✔
421
                                c.state = PUB_ARG
10,166,895✔
422
                                c.as = i
10,166,895✔
423
                        }
424
                case PUB_ARG:
183,885,578✔
425
                        switch b {
183,885,578✔
426
                        case '\r':
10,166,887✔
427
                                c.drop = 1
10,166,887✔
428
                        case '\n':
10,166,886✔
429
                                var arg []byte
10,166,886✔
430
                                if c.argBuf != nil {
10,191,954✔
431
                                        arg = c.argBuf
25,068✔
432
                                        c.argBuf = nil
25,068✔
433
                                } else {
10,166,886✔
434
                                        arg = buf[c.as : i-c.drop]
10,141,818✔
435
                                }
10,141,818✔
436
                                if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
10,166,886✔
437
                                        return err
×
438
                                }
×
439
                                if trace {
10,482,426✔
440
                                        c.traceInOp("PUB", arg)
315,540✔
441
                                }
315,540✔
442
                                if err := c.processPub(arg); err != nil {
10,166,892✔
443
                                        return err
6✔
444
                                }
6✔
445

446
                                c.drop, c.as, c.state = 0, i+1, MSG_PAYLOAD
10,166,880✔
447
                                // If we don't have a saved buffer then jump ahead with
10,166,880✔
448
                                // the index. If this overruns what is left we fall out
10,166,880✔
449
                                // and process split buffer.
10,166,880✔
450
                                if c.msgBuf == nil {
20,333,760✔
451
                                        i = c.as + c.pa.size - LEN_CR_LF
10,166,880✔
452
                                }
10,166,880✔
453
                        default:
163,551,805✔
454
                                if c.argBuf != nil {
164,018,039✔
455
                                        c.argBuf = append(c.argBuf, b)
466,234✔
456
                                }
466,234✔
457
                        }
458
                case MSG_PAYLOAD:
27,965,712✔
459
                        if c.msgBuf != nil {
30,464,548✔
460
                                // copy as much as we can to the buffer and skip ahead.
2,498,836✔
461
                                toCopy := c.pa.size - len(c.msgBuf)
2,498,836✔
462
                                avail := len(buf) - i
2,498,836✔
463
                                if avail < toCopy {
3,271,120✔
464
                                        toCopy = avail
772,284✔
465
                                }
772,284✔
466
                                if toCopy > 0 {
4,997,672✔
467
                                        start := len(c.msgBuf)
2,498,836✔
468
                                        // This is needed for copy to work.
2,498,836✔
469
                                        c.msgBuf = c.msgBuf[:start+toCopy]
2,498,836✔
470
                                        copy(c.msgBuf[start:], buf[i:i+toCopy])
2,498,836✔
471
                                        // Update our index
2,498,836✔
472
                                        i = (i + toCopy) - 1
2,498,836✔
473
                                } else {
2,498,836✔
474
                                        // Fall back to append if needed.
×
475
                                        c.msgBuf = append(c.msgBuf, b)
×
476
                                }
×
477
                                if len(c.msgBuf) >= c.pa.size {
4,225,388✔
478
                                        c.state = MSG_END_R
1,726,552✔
479
                                }
1,726,552✔
480
                        } else if i-c.as+1 >= c.pa.size {
50,933,752✔
481
                                c.state = MSG_END_R
25,466,876✔
482
                        }
25,466,876✔
483
                case MSG_END_R:
27,193,428✔
484
                        if b != '\r' {
27,193,429✔
485
                                goto parseErr
1✔
486
                        }
487
                        if c.msgBuf != nil {
28,934,837✔
488
                                c.msgBuf = append(c.msgBuf, b)
1,741,410✔
489
                        }
1,741,410✔
490
                        c.state = MSG_END_N
27,193,427✔
491
                case MSG_END_N:
27,193,426✔
492
                        if b != '\n' {
27,193,426✔
493
                                goto parseErr
×
494
                        }
495
                        if c.msgBuf != nil {
28,937,176✔
496
                                c.msgBuf = append(c.msgBuf, b)
1,743,750✔
497
                        } else {
27,193,426✔
498
                                c.msgBuf = buf[c.as : i+1]
25,449,676✔
499
                        }
25,449,676✔
500

501
                        var mt *msgTrace
27,193,426✔
502
                        if c.pa.hdr > 0 {
29,186,128✔
503
                                mt = c.initMsgTrace()
1,992,702✔
504
                        }
1,992,702✔
505
                        // Check for mappings.
506
                        if (c.kind == CLIENT || c.kind == LEAF) && c.in.flags.isSet(hasMappings) {
27,226,093✔
507
                                changed := c.selectMappedSubject()
32,667✔
508
                                if changed {
45,232✔
509
                                        if trace {
12,645✔
510
                                                c.traceInOp("MAPPING", []byte(fmt.Sprintf("%s -> %s", c.pa.mapped, c.pa.subject)))
80✔
511
                                        }
80✔
512
                                        // c.pa.subject is the subject the original is now mapped to.
513
                                        mt.addSubjectMappingEvent(c.pa.subject)
12,565✔
514
                                }
515
                        }
516
                        if trace {
27,589,005✔
517
                                c.traceMsg(c.msgBuf)
395,579✔
518
                        }
395,579✔
519

520
                        c.processInboundMsg(c.msgBuf)
27,193,426✔
521

27,193,426✔
522
                        mt.sendEvent()
27,193,426✔
523
                        c.argBuf, c.msgBuf, c.header = nil, nil, nil
27,193,426✔
524
                        c.drop, c.as, c.state = 0, i+1, OP_START
27,193,426✔
525
                        // Drop all pub args
27,193,426✔
526
                        c.pa.arg, c.pa.pacache, c.pa.origin, c.pa.account, c.pa.subject, c.pa.mapped = nil, nil, nil, nil, nil, nil
27,193,426✔
527
                        c.pa.reply, c.pa.hdr, c.pa.size, c.pa.szb, c.pa.hdb, c.pa.queues = nil, -1, 0, nil, nil, nil
27,193,426✔
528
                        c.pa.trace = nil
27,193,426✔
529
                        c.pa.delivered = false
27,193,426✔
530
                        lmsg = false
27,193,426✔
531
                case OP_A:
31✔
532
                        switch b {
31✔
533
                        case '+':
3✔
534
                                c.state = OP_ASUB
3✔
535
                        case '-', 'u':
28✔
536
                                c.state = OP_AUSUB
28✔
537
                        default:
×
538
                                goto parseErr
×
539
                        }
540
                case OP_ASUB:
3✔
541
                        switch b {
3✔
542
                        case ' ', '\t':
3✔
543
                                c.state = OP_ASUB_SPC
3✔
544
                        default:
×
545
                                goto parseErr
×
546
                        }
547
                case OP_ASUB_SPC:
3✔
548
                        switch b {
3✔
549
                        case ' ', '\t':
×
550
                                continue
×
551
                        default:
3✔
552
                                c.state = ASUB_ARG
3✔
553
                                c.as = i
3✔
554
                        }
555
                case ASUB_ARG:
11✔
556
                        switch b {
11✔
557
                        case '\r':
3✔
558
                                c.drop = 1
3✔
559
                        case '\n':
3✔
560
                                var arg []byte
3✔
561
                                if c.argBuf != nil {
3✔
562
                                        arg = c.argBuf
×
563
                                        c.argBuf = nil
×
564
                                } else {
3✔
565
                                        arg = buf[c.as : i-c.drop]
3✔
566
                                }
3✔
567
                                if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
3✔
568
                                        return err
×
569
                                }
×
570
                                if trace {
3✔
571
                                        c.traceInOp("A+", arg)
×
572
                                }
×
573
                                if err := c.processAccountSub(arg); err != nil {
3✔
574
                                        return err
×
575
                                }
×
576
                                c.drop, c.as, c.state = 0, i+1, OP_START
3✔
577
                        default:
5✔
578
                                if c.argBuf != nil {
5✔
579
                                        c.argBuf = append(c.argBuf, b)
×
580
                                }
×
581
                        }
582
                case OP_AUSUB:
28✔
583
                        switch b {
28✔
584
                        case ' ', '\t':
28✔
585
                                c.state = OP_AUSUB_SPC
28✔
586
                        default:
×
587
                                goto parseErr
×
588
                        }
589
                case OP_AUSUB_SPC:
28✔
590
                        switch b {
28✔
591
                        case ' ', '\t':
×
592
                                continue
×
593
                        default:
28✔
594
                                c.state = AUSUB_ARG
28✔
595
                                c.as = i
28✔
596
                        }
597
                case AUSUB_ARG:
142✔
598
                        switch b {
142✔
599
                        case '\r':
28✔
600
                                c.drop = 1
28✔
601
                        case '\n':
28✔
602
                                var arg []byte
28✔
603
                                if c.argBuf != nil {
28✔
604
                                        arg = c.argBuf
×
605
                                        c.argBuf = nil
×
606
                                } else {
28✔
607
                                        arg = buf[c.as : i-c.drop]
28✔
608
                                }
28✔
609
                                if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
28✔
610
                                        return err
×
611
                                }
×
612
                                if trace {
45✔
613
                                        c.traceInOp("A-", arg)
17✔
614
                                }
17✔
615
                                c.processAccountUnsub(arg)
28✔
616
                                c.drop, c.as, c.state = 0, i+1, OP_START
28✔
617
                        default:
86✔
618
                                if c.argBuf != nil {
86✔
619
                                        c.argBuf = append(c.argBuf, b)
×
620
                                }
×
621
                        }
622
                case OP_S:
136,218✔
623
                        switch b {
136,218✔
624
                        case 'U', 'u':
136,218✔
625
                                c.state = OP_SU
136,218✔
626
                        default:
×
627
                                goto parseErr
×
628
                        }
629
                case OP_SU:
136,218✔
630
                        switch b {
136,218✔
631
                        case 'B', 'b':
136,218✔
632
                                c.state = OP_SUB
136,218✔
633
                        default:
×
634
                                goto parseErr
×
635
                        }
636
                case OP_SUB:
1,165,245✔
637
                        switch b {
1,165,245✔
638
                        case ' ', '\t':
1,165,244✔
639
                                c.state = OP_SUB_SPC
1,165,244✔
640
                        default:
1✔
641
                                goto parseErr
1✔
642
                        }
643
                case OP_SUB_SPC:
1,165,243✔
644
                        switch b {
1,165,243✔
645
                        case ' ', '\t':
×
646
                                continue
×
647
                        default:
1,165,243✔
648
                                c.state = SUB_ARG
1,165,243✔
649
                                c.as = i
1,165,243✔
650
                        }
651
                case SUB_ARG:
43,622,241✔
652
                        switch b {
43,622,241✔
653
                        case '\r':
1,165,233✔
654
                                c.drop = 1
1,165,233✔
655
                        case '\n':
1,165,233✔
656
                                var arg []byte
1,165,233✔
657
                                if c.argBuf != nil {
1,193,830✔
658
                                        arg = c.argBuf
28,597✔
659
                                        c.argBuf = nil
28,597✔
660
                                } else {
1,165,233✔
661
                                        arg = buf[c.as : i-c.drop]
1,136,636✔
662
                                }
1,136,636✔
663
                                if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
1,165,233✔
664
                                        return err
×
665
                                }
×
666
                                var err error
1,165,233✔
667

1,165,233✔
668
                                switch c.kind {
1,165,233✔
669
                                case CLIENT:
136,217✔
670
                                        if trace {
149,289✔
671
                                                c.traceInOp("SUB", arg)
13,072✔
672
                                        }
13,072✔
673
                                        err = c.parseSub(arg, false)
136,217✔
674
                                case ROUTER:
834,955✔
675
                                        switch c.op {
834,955✔
676
                                        case 'R', 'r':
823,001✔
677
                                                if trace {
825,963✔
678
                                                        c.traceInOp("RS+", arg)
2,962✔
679
                                                }
2,962✔
680
                                                err = c.processRemoteSub(arg, false)
823,001✔
681
                                        case 'L', 'l':
11,954✔
682
                                                if trace {
12,148✔
683
                                                        c.traceInOp("LS+", arg)
194✔
684
                                                }
194✔
685
                                                err = c.processRemoteSub(arg, true)
11,954✔
686
                                        }
687
                                case GATEWAY:
161,209✔
688
                                        if trace {
161,404✔
689
                                                c.traceInOp("RS+", arg)
195✔
690
                                        }
195✔
691
                                        err = c.processGatewayRSub(arg)
161,209✔
692
                                case LEAF:
32,852✔
693
                                        if trace {
32,973✔
694
                                                c.traceInOp("LS+", arg)
121✔
695
                                        }
121✔
696
                                        err = c.processLeafSub(arg)
32,852✔
697
                                }
698
                                if err != nil {
1,165,233✔
699
                                        return err
×
700
                                }
×
701
                                c.drop, c.as, c.state = 0, i+1, OP_START
1,165,233✔
702
                        default:
41,291,775✔
703
                                if c.argBuf != nil {
42,009,682✔
704
                                        c.argBuf = append(c.argBuf, b)
717,907✔
705
                                }
717,907✔
706
                        }
707
                case OP_L:
166,388✔
708
                        switch b {
166,388✔
709
                        case 'S', 's':
58,729✔
710
                                c.state = OP_LS
58,729✔
711
                        case 'M', 'm':
107,659✔
712
                                c.state = OP_M
107,659✔
713
                        default:
×
714
                                goto parseErr
×
715
                        }
716
                case OP_LS:
58,729✔
717
                        switch b {
58,729✔
718
                        case '+':
44,806✔
719
                                c.state = OP_SUB
44,806✔
720
                        case '-':
13,923✔
721
                                c.state = OP_UNSUB
13,923✔
722
                        default:
×
723
                                goto parseErr
×
724
                        }
725
                case OP_R:
16,120,112✔
726
                        switch b {
16,120,112✔
727
                        case 'S', 's':
1,193,450✔
728
                                c.state = OP_RS
1,193,450✔
729
                        case 'M', 'm':
14,926,662✔
730
                                c.state = OP_M
14,926,662✔
731
                        default:
×
732
                                goto parseErr
×
733
                        }
734
                case OP_RS:
1,193,450✔
735
                        switch b {
1,193,450✔
736
                        case '+':
984,222✔
737
                                c.state = OP_SUB
984,222✔
738
                        case '-':
209,228✔
739
                                c.state = OP_UNSUB
209,228✔
740
                        default:
×
741
                                goto parseErr
×
742
                        }
743
                case OP_U:
15,570✔
744
                        switch b {
15,570✔
745
                        case 'N', 'n':
15,570✔
746
                                c.state = OP_UN
15,570✔
747
                        default:
×
748
                                goto parseErr
×
749
                        }
750
                case OP_UN:
15,570✔
751
                        switch b {
15,570✔
752
                        case 'S', 's':
15,570✔
753
                                c.state = OP_UNS
15,570✔
754
                        default:
×
755
                                goto parseErr
×
756
                        }
757
                case OP_UNS:
15,570✔
758
                        switch b {
15,570✔
759
                        case 'U', 'u':
15,570✔
760
                                c.state = OP_UNSU
15,570✔
761
                        default:
×
762
                                goto parseErr
×
763
                        }
764
                case OP_UNSU:
15,570✔
765
                        switch b {
15,570✔
766
                        case 'B', 'b':
15,570✔
767
                                c.state = OP_UNSUB
15,570✔
768
                        default:
×
769
                                goto parseErr
×
770
                        }
771
                case OP_UNSUB:
238,720✔
772
                        switch b {
238,720✔
773
                        case ' ', '\t':
238,720✔
774
                                c.state = OP_UNSUB_SPC
238,720✔
775
                        default:
×
776
                                goto parseErr
×
777
                        }
778
                case OP_UNSUB_SPC:
238,720✔
779
                        switch b {
238,720✔
780
                        case ' ', '\t':
×
781
                                continue
×
782
                        default:
238,720✔
783
                                c.state = UNSUB_ARG
238,720✔
784
                                c.as = i
238,720✔
785
                        }
786
                case UNSUB_ARG:
7,056,261✔
787
                        switch b {
7,056,261✔
788
                        case '\r':
238,715✔
789
                                c.drop = 1
238,715✔
790
                        case '\n':
238,715✔
791
                                var arg []byte
238,715✔
792
                                if c.argBuf != nil {
245,756✔
793
                                        arg = c.argBuf
7,041✔
794
                                        c.argBuf = nil
7,041✔
795
                                } else {
238,715✔
796
                                        arg = buf[c.as : i-c.drop]
231,674✔
797
                                }
231,674✔
798
                                if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
238,715✔
799
                                        return err
×
800
                                }
×
801
                                var err error
238,715✔
802

238,715✔
803
                                switch c.kind {
238,715✔
804
                                case CLIENT:
15,569✔
805
                                        if trace {
28,404✔
806
                                                c.traceInOp("UNSUB", arg)
12,835✔
807
                                        }
12,835✔
808
                                        err = c.processUnsub(arg)
15,569✔
809
                                case ROUTER:
174,702✔
810
                                        if trace && c.srv != nil {
175,103✔
811
                                                switch c.op {
401✔
812
                                                case 'R', 'r':
207✔
813
                                                        c.traceInOp("RS-", arg)
207✔
814
                                                case 'L', 'l':
194✔
815
                                                        c.traceInOp("LS-", arg)
194✔
816
                                                }
817
                                        }
818
                                        leafUnsub := c.op == 'L' || c.op == 'l'
174,702✔
819
                                        err = c.processRemoteUnsub(arg, leafUnsub)
174,702✔
820
                                case GATEWAY:
45,214✔
821
                                        if trace {
46,406✔
822
                                                c.traceInOp("RS-", arg)
1,192✔
823
                                        }
1,192✔
824
                                        err = c.processGatewayRUnsub(arg)
45,214✔
825
                                case LEAF:
3,230✔
826
                                        if trace {
3,242✔
827
                                                c.traceInOp("LS-", arg)
12✔
828
                                        }
12✔
829
                                        err = c.processLeafUnsub(arg)
3,230✔
830
                                }
831
                                if err != nil {
238,715✔
832
                                        return err
×
833
                                }
×
834
                                c.drop, c.as, c.state = 0, i+1, OP_START
238,715✔
835
                        default:
6,578,831✔
836
                                if c.argBuf != nil {
6,743,776✔
837
                                        c.argBuf = append(c.argBuf, b)
164,945✔
838
                                }
164,945✔
839
                        }
840
                case OP_PI:
39,348✔
841
                        switch b {
39,348✔
842
                        case 'N', 'n':
39,348✔
843
                                c.state = OP_PIN
39,348✔
844
                        default:
×
845
                                goto parseErr
×
846
                        }
847
                case OP_PIN:
39,348✔
848
                        switch b {
39,348✔
849
                        case 'G', 'g':
39,348✔
850
                                c.state = OP_PING
39,348✔
851
                        default:
×
852
                                goto parseErr
×
853
                        }
854
                case OP_PING:
78,696✔
855
                        switch b {
78,696✔
856
                        case '\n':
39,348✔
857
                                if trace {
39,971✔
858
                                        c.traceInOp("PING", nil)
623✔
859
                                }
623✔
860
                                c.processPing()
39,348✔
861
                                c.drop, c.state = 0, OP_START
39,348✔
862
                        }
863
                case OP_PO:
27,580✔
864
                        switch b {
27,580✔
865
                        case 'N', 'n':
27,580✔
866
                                c.state = OP_PON
27,580✔
867
                        default:
×
868
                                goto parseErr
×
869
                        }
870
                case OP_PON:
27,580✔
871
                        switch b {
27,580✔
872
                        case 'G', 'g':
27,580✔
873
                                c.state = OP_PONG
27,580✔
874
                        default:
×
875
                                goto parseErr
×
876
                        }
877
                case OP_PONG:
55,160✔
878
                        switch b {
55,160✔
879
                        case '\n':
27,580✔
880
                                if trace {
27,643✔
881
                                        c.traceInOp("PONG", nil)
63✔
882
                                }
63✔
883
                                c.processPong()
27,580✔
884
                                c.drop, c.state = 0, OP_START
27,580✔
885
                        }
886
                case OP_C:
43,286✔
887
                        switch b {
43,286✔
888
                        case 'O', 'o':
43,286✔
889
                                c.state = OP_CO
43,286✔
890
                        default:
×
891
                                goto parseErr
×
892
                        }
893
                case OP_CO:
43,286✔
894
                        switch b {
43,286✔
895
                        case 'N', 'n':
43,286✔
896
                                c.state = OP_CON
43,286✔
897
                        default:
×
898
                                goto parseErr
×
899
                        }
900
                case OP_CON:
43,286✔
901
                        switch b {
43,286✔
902
                        case 'N', 'n':
43,286✔
903
                                c.state = OP_CONN
43,286✔
904
                        default:
×
905
                                goto parseErr
×
906
                        }
907
                case OP_CONN:
43,286✔
908
                        switch b {
43,286✔
909
                        case 'E', 'e':
43,286✔
910
                                c.state = OP_CONNE
43,286✔
911
                        default:
×
912
                                goto parseErr
×
913
                        }
914
                case OP_CONNE:
43,286✔
915
                        switch b {
43,286✔
916
                        case 'C', 'c':
43,286✔
917
                                c.state = OP_CONNEC
43,286✔
918
                        default:
×
919
                                goto parseErr
×
920
                        }
921
                case OP_CONNEC:
43,286✔
922
                        switch b {
43,286✔
923
                        case 'T', 't':
43,286✔
924
                                c.state = OP_CONNECT
43,286✔
925
                        default:
×
926
                                goto parseErr
×
927
                        }
928
                case OP_CONNECT:
86,572✔
929
                        switch b {
86,572✔
930
                        case ' ', '\t':
43,286✔
931
                                continue
43,286✔
932
                        default:
43,286✔
933
                                c.state = CONNECT_ARG
43,286✔
934
                                c.as = i
43,286✔
935
                        }
936
                case CONNECT_ARG:
9,164,807✔
937
                        switch b {
9,164,807✔
938
                        case '\r':
43,286✔
939
                                c.drop = 1
43,286✔
940
                        case '\n':
43,286✔
941
                                var arg []byte
43,286✔
942
                                if c.argBuf != nil {
45,692✔
943
                                        arg = c.argBuf
2,406✔
944
                                        c.argBuf = nil
2,406✔
945
                                } else {
43,286✔
946
                                        arg = buf[c.as : i-c.drop]
40,880✔
947
                                }
40,880✔
948
                                if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
43,286✔
949
                                        return err
×
950
                                }
×
951
                                if trace {
43,949✔
952
                                        c.traceInOp("CONNECT", removeSecretsFromTrace(arg))
663✔
953
                                }
663✔
954
                                if err := c.processConnect(arg); err != nil {
43,520✔
955
                                        return err
234✔
956
                                }
234✔
957
                                c.drop, c.state = 0, OP_START
43,052✔
958
                                // Reset notion on authSet
43,052✔
959
                                c.mu.Lock()
43,052✔
960
                                authSet = c.awaitingAuth()
43,052✔
961
                                c.mu.Unlock()
43,052✔
962
                        default:
9,078,235✔
963
                                if c.argBuf != nil {
9,829,619✔
964
                                        c.argBuf = append(c.argBuf, b)
751,384✔
965
                                }
751,384✔
966
                        }
967
                case OP_M:
15,034,321✔
968
                        switch b {
15,034,321✔
969
                        case 'S', 's':
15,034,321✔
970
                                c.state = OP_MS
15,034,321✔
971
                        default:
×
972
                                goto parseErr
×
973
                        }
974
                case OP_MS:
15,034,321✔
975
                        switch b {
15,034,321✔
976
                        case 'G', 'g':
15,034,321✔
977
                                c.state = OP_MSG
15,034,321✔
978
                        default:
×
979
                                goto parseErr
×
980
                        }
981
                case OP_MSG:
15,034,321✔
982
                        switch b {
15,034,321✔
983
                        case ' ', '\t':
15,034,321✔
984
                                c.state = OP_MSG_SPC
15,034,321✔
985
                        default:
×
986
                                goto parseErr
×
987
                        }
988
                case OP_MSG_SPC:
15,034,321✔
989
                        switch b {
15,034,321✔
990
                        case ' ', '\t':
×
991
                                continue
×
992
                        default:
15,034,321✔
993
                                c.pa.hdr = -1
15,034,321✔
994
                                c.state = MSG_ARG
15,034,321✔
995
                                c.as = i
15,034,321✔
996
                        }
997
                case MSG_ARG:
540,612,311✔
998
                        switch b {
540,612,311✔
999
                        case '\r':
15,034,319✔
1000
                                c.drop = 1
15,034,319✔
1001
                        case '\n':
15,034,319✔
1002
                                var arg []byte
15,034,319✔
1003
                                if c.argBuf != nil {
15,471,061✔
1004
                                        arg = c.argBuf
436,742✔
1005
                                        c.argBuf = nil
436,742✔
1006
                                } else {
15,034,319✔
1007
                                        arg = buf[c.as : i-c.drop]
14,597,577✔
1008
                                }
14,597,577✔
1009
                                if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
15,034,319✔
1010
                                        return err
×
1011
                                }
×
1012
                                var err error
15,034,319✔
1013
                                if c.kind == ROUTER || c.kind == GATEWAY {
29,969,299✔
1014
                                        switch c.op {
14,934,980✔
1015
                                        case 'R', 'r':
14,926,660✔
1016
                                                if trace {
14,933,183✔
1017
                                                        c.traceInOp("RMSG", arg)
6,523✔
1018
                                                }
6,523✔
1019
                                                err = c.processRoutedMsgArgs(arg)
14,926,660✔
1020
                                        case 'L', 'l':
8,320✔
1021
                                                if trace {
8,584✔
1022
                                                        c.traceInOp("LMSG", arg)
264✔
1023
                                                }
264✔
1024
                                                lmsg = true
8,320✔
1025
                                                err = c.processRoutedOriginClusterMsgArgs(arg)
8,320✔
1026
                                        }
1027
                                } else if c.kind == LEAF {
198,678✔
1028
                                        if trace {
99,359✔
1029
                                                c.traceInOp("LMSG", arg)
20✔
1030
                                        }
20✔
1031
                                        err = c.processLeafMsgArgs(arg)
99,339✔
1032
                                }
1033
                                if err != nil {
15,034,320✔
1034
                                        return err
1✔
1035
                                }
1✔
1036
                                c.drop, c.as, c.state = 0, i+1, MSG_PAYLOAD
15,034,318✔
1037

15,034,318✔
1038
                                // jump ahead with the index. If this overruns
15,034,318✔
1039
                                // what is left we fall out and process split
15,034,318✔
1040
                                // buffer.
15,034,318✔
1041
                                i = c.as + c.pa.size - LEN_CR_LF
15,034,318✔
1042
                        default:
510,543,673✔
1043
                                if c.argBuf != nil {
515,176,998✔
1044
                                        c.argBuf = append(c.argBuf, b)
4,633,325✔
1045
                                }
4,633,325✔
1046
                        }
1047
                case OP_I:
85,065✔
1048
                        switch b {
85,065✔
1049
                        case 'N', 'n':
85,065✔
1050
                                c.state = OP_IN
85,065✔
1051
                        default:
×
1052
                                goto parseErr
×
1053
                        }
1054
                case OP_IN:
85,065✔
1055
                        switch b {
85,065✔
1056
                        case 'F', 'f':
85,065✔
1057
                                c.state = OP_INF
85,065✔
1058
                        default:
×
1059
                                goto parseErr
×
1060
                        }
1061
                case OP_INF:
85,065✔
1062
                        switch b {
85,065✔
1063
                        case 'O', 'o':
85,065✔
1064
                                c.state = OP_INFO
85,065✔
1065
                        default:
×
1066
                                goto parseErr
×
1067
                        }
1068
                case OP_INFO:
170,130✔
1069
                        switch b {
170,130✔
1070
                        case ' ', '\t':
85,065✔
1071
                                continue
85,065✔
1072
                        default:
85,065✔
1073
                                c.state = INFO_ARG
85,065✔
1074
                                c.as = i
85,065✔
1075
                        }
1076
                case INFO_ARG:
32,300,735✔
1077
                        switch b {
32,300,735✔
1078
                        case '\r':
85,063✔
1079
                                c.drop = 1
85,063✔
1080
                        case '\n':
85,063✔
1081
                                var arg []byte
85,063✔
1082
                                if c.argBuf != nil {
93,748✔
1083
                                        arg = c.argBuf
8,685✔
1084
                                        c.argBuf = nil
8,685✔
1085
                                } else {
85,063✔
1086
                                        arg = buf[c.as : i-c.drop]
76,378✔
1087
                                }
76,378✔
1088
                                if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
85,063✔
1089
                                        return err
×
1090
                                }
×
1091
                                if err := c.processInfo(arg); err != nil {
85,063✔
1092
                                        return err
×
1093
                                }
×
1094
                                c.drop, c.as, c.state = 0, i+1, OP_START
85,063✔
1095
                        default:
32,130,609✔
1096
                                if c.argBuf != nil {
33,096,386✔
1097
                                        c.argBuf = append(c.argBuf, b)
965,777✔
1098
                                }
965,777✔
1099
                        }
1100
                case OP_PLUS:
×
1101
                        switch b {
×
1102
                        case 'O', 'o':
×
1103
                                c.state = OP_PLUS_O
×
1104
                        default:
×
1105
                                goto parseErr
×
1106
                        }
1107
                case OP_PLUS_O:
×
1108
                        switch b {
×
1109
                        case 'K', 'k':
×
1110
                                c.state = OP_PLUS_OK
×
1111
                        default:
×
1112
                                goto parseErr
×
1113
                        }
1114
                case OP_PLUS_OK:
×
1115
                        switch b {
×
1116
                        case '\n':
×
1117
                                c.drop, c.state = 0, OP_START
×
1118
                        }
1119
                case OP_MINUS:
94✔
1120
                        switch b {
94✔
1121
                        case 'E', 'e':
94✔
1122
                                c.state = OP_MINUS_E
94✔
1123
                        default:
×
1124
                                goto parseErr
×
1125
                        }
1126
                case OP_MINUS_E:
94✔
1127
                        switch b {
94✔
1128
                        case 'R', 'r':
94✔
1129
                                c.state = OP_MINUS_ER
94✔
1130
                        default:
×
1131
                                goto parseErr
×
1132
                        }
1133
                case OP_MINUS_ER:
94✔
1134
                        switch b {
94✔
1135
                        case 'R', 'r':
94✔
1136
                                c.state = OP_MINUS_ERR
94✔
1137
                        default:
×
1138
                                goto parseErr
×
1139
                        }
1140
                case OP_MINUS_ERR:
94✔
1141
                        switch b {
94✔
1142
                        case ' ', '\t':
94✔
1143
                                c.state = OP_MINUS_ERR_SPC
94✔
1144
                        default:
×
1145
                                goto parseErr
×
1146
                        }
1147
                case OP_MINUS_ERR_SPC:
94✔
1148
                        switch b {
94✔
1149
                        case ' ', '\t':
×
1150
                                continue
×
1151
                        default:
94✔
1152
                                c.state = MINUS_ERR_ARG
94✔
1153
                                c.as = i
94✔
1154
                        }
1155
                case MINUS_ERR_ARG:
3,222✔
1156
                        switch b {
3,222✔
1157
                        case '\r':
94✔
1158
                                c.drop = 1
94✔
1159
                        case '\n':
94✔
1160
                                var arg []byte
94✔
1161
                                if c.argBuf != nil {
96✔
1162
                                        arg = c.argBuf
2✔
1163
                                        c.argBuf = nil
2✔
1164
                                } else {
94✔
1165
                                        arg = buf[c.as : i-c.drop]
92✔
1166
                                }
92✔
1167
                                if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
94✔
1168
                                        return err
×
1169
                                }
×
1170
                                c.processErr(string(arg))
94✔
1171
                                c.drop, c.as, c.state = 0, i+1, OP_START
94✔
1172
                        default:
3,034✔
1173
                                if c.argBuf != nil {
3,046✔
1174
                                        c.argBuf = append(c.argBuf, b)
12✔
1175
                                }
12✔
1176
                        }
1177
                default:
×
1178
                        goto parseErr
×
1179
                }
1180
        }
1181

1182
        // Check for split buffer scenarios for any ARG state.
1183
        if c.state == SUB_ARG || c.state == UNSUB_ARG ||
16,366,009✔
1184
                c.state == PUB_ARG || c.state == HPUB_ARG ||
16,366,009✔
1185
                c.state == ASUB_ARG || c.state == AUSUB_ARG ||
16,366,009✔
1186
                c.state == MSG_ARG || c.state == HMSG_ARG ||
16,366,009✔
1187
                c.state == MINUS_ERR_ARG || c.state == CONNECT_ARG || c.state == INFO_ARG {
16,885,216✔
1188

519,207✔
1189
                // Setup a holder buffer to deal with split buffer scenario.
519,207✔
1190
                if c.argBuf == nil {
1,038,108✔
1191
                        c.argBuf = c.scratch[:0]
518,901✔
1192
                        c.argBuf = append(c.argBuf, buf[c.as:i-c.drop]...)
518,901✔
1193
                }
518,901✔
1194
                // Check for violations of control line length here. Note that this is not
1195
                // exact at all but the performance hit is too great to be precise, and
1196
                // catching here should prevent memory exhaustion attacks.
1197
                if err := c.overMaxControlLineLimit(c.argBuf, mcl); err != nil {
519,208✔
1198
                        return err
1✔
1199
                }
1✔
1200
        }
1201

1202
        // Check for split msg
1203
        if (c.state == MSG_PAYLOAD || c.state == MSG_END_R || c.state == MSG_END_N) && c.msgBuf == nil {
18,109,782✔
1204
                // We need to clone the pubArg if it is still referencing the
1,743,774✔
1205
                // read buffer and we are not able to process the msg.
1,743,774✔
1206

1,743,774✔
1207
                if c.argBuf == nil {
3,487,548✔
1208
                        // Works also for MSG_ARG, when message comes from ROUTE or GATEWAY.
1,743,774✔
1209
                        if err := c.clonePubArg(lmsg); err != nil {
1,743,774✔
1210
                                goto parseErr
×
1211
                        }
1212
                }
1213

1214
                // If we will overflow the scratch buffer, just create a
1215
                // new buffer to hold the split message.
1216
                if c.pa.size > cap(c.scratch)-len(c.argBuf) {
1,778,489✔
1217
                        lrem := len(buf[c.as:])
34,715✔
1218
                        // Consider it a protocol error when the remaining payload
34,715✔
1219
                        // is larger than the reported size for PUB. It can happen
34,715✔
1220
                        // when processing incomplete messages from rogue clients.
34,715✔
1221
                        if lrem > c.pa.size+LEN_CR_LF {
34,715✔
1222
                                goto parseErr
×
1223
                        }
1224
                        c.msgBuf = make([]byte, lrem, c.pa.size+LEN_CR_LF)
34,715✔
1225
                        copy(c.msgBuf, buf[c.as:])
34,715✔
1226
                } else {
1,709,059✔
1227
                        c.msgBuf = c.scratch[len(c.argBuf):len(c.argBuf)]
1,709,059✔
1228
                        c.msgBuf = append(c.msgBuf, (buf[c.as:])...)
1,709,059✔
1229
                }
1,709,059✔
1230
        }
1231

1232
        return nil
16,366,008✔
1233

16,366,008✔
1234
authErr:
16,366,008✔
1235
        c.authViolation()
28✔
1236
        return ErrAuthentication
28✔
1237

28✔
1238
parseErr:
28✔
1239
        c.sendErr("Unknown Protocol Operation")
4✔
1240
        snip := protoSnippet(i, PROTO_SNIPPET_SIZE, buf)
4✔
1241
        err := fmt.Errorf("%s parser ERROR, state=%d, i=%d: proto='%s...'", c.kindString(), c.state, i, snip)
4✔
1242
        return err
4✔
1243
}
1244

1245
func protoSnippet(start, max int, buf []byte) string {
5✔
1246
        stop := start + max
5✔
1247
        bufSize := len(buf)
5✔
1248
        if start >= bufSize {
5✔
1249
                return `""`
×
1250
        }
×
1251
        if stop > bufSize {
8✔
1252
                stop = bufSize - 1
3✔
1253
        }
3✔
1254
        return fmt.Sprintf("%q", buf[start:stop])
5✔
1255
}
1256

1257
// Check if the length of buffer `arg` is over the max control line limit `mcl`.
1258
// If so, an error is sent to the client and the connection is closed.
1259
// The error ErrMaxControlLine is returned.
1260
func (c *client) overMaxControlLineLimit(arg []byte, mcl int32) error {
29,245,089✔
1261
        if c.kind != CLIENT {
47,169,965✔
1262
                return nil
17,924,876✔
1263
        }
17,924,876✔
1264
        if len(arg) > int(mcl) {
11,320,214✔
1265
                err := NewErrorCtx(ErrMaxControlLine, "State %d, max_control_line %d, Buffer len %d (snip: %s...)",
1✔
1266
                        c.state, int(mcl), len(c.argBuf), protoSnippet(0, MAX_CONTROL_LINE_SNIPPET_SIZE, arg))
1✔
1267
                c.sendErr(err.Error())
1✔
1268
                c.closeConnection(MaxControlLineExceeded)
1✔
1269
                return err
1✔
1270
        }
1✔
1271
        return nil
11,320,212✔
1272
}
1273

1274
// clonePubArg is used when the split buffer scenario has the pubArg in the existing read buffer, but
1275
// we need to hold onto it into the next read.
1276
func (c *client) clonePubArg(lmsg bool) error {
1,743,774✔
1277
        // Just copy and re-process original arg buffer.
1,743,774✔
1278
        c.argBuf = c.scratch[:0]
1,743,774✔
1279
        c.argBuf = append(c.argBuf, c.pa.arg...)
1,743,774✔
1280

1,743,774✔
1281
        switch c.kind {
1,743,774✔
1282
        case ROUTER, GATEWAY:
1,699,194✔
1283
                if lmsg {
1,699,791✔
1284
                        return c.processRoutedOriginClusterMsgArgs(c.argBuf)
597✔
1285
                }
597✔
1286
                if c.pa.hdr < 0 {
3,166,603✔
1287
                        return c.processRoutedMsgArgs(c.argBuf)
1,468,006✔
1288
                } else {
1,698,597✔
1289
                        return c.processRoutedHeaderMsgArgs(c.argBuf)
230,591✔
1290
                }
230,591✔
1291
        case LEAF:
1,492✔
1292
                if c.pa.hdr < 0 {
2,862✔
1293
                        return c.processLeafMsgArgs(c.argBuf)
1,370✔
1294
                } else {
1,492✔
1295
                        return c.processLeafHeaderMsgArgs(c.argBuf)
122✔
1296
                }
122✔
1297
        default:
43,088✔
1298
                if c.pa.hdr < 0 {
81,450✔
1299
                        return c.processPub(c.argBuf)
38,362✔
1300
                } else {
43,088✔
1301
                        return c.processHeaderPub(c.argBuf, nil)
4,726✔
1302
                }
4,726✔
1303
        }
1304
}
1305

1306
func (ps *parseState) getHeader() http.Header {
809✔
1307
        if ps.header == nil {
1,618✔
1308
                if hdr := ps.pa.hdr; hdr > 0 {
882✔
1309
                        reader := bufio.NewReader(bytes.NewReader(ps.msgBuf[0:hdr]))
73✔
1310
                        tp := textproto.NewReader(reader)
73✔
1311
                        tp.ReadLine() // skip over first line, contains version
73✔
1312
                        if mimeHeader, err := tp.ReadMIMEHeader(); err == nil {
146✔
1313
                                ps.header = http.Header(mimeHeader)
73✔
1314
                        }
73✔
1315
                }
1316
        }
1317
        return ps.header
809✔
1318
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc