github.com/nats-io/nats-server/v2@v2.11.0-preview.2/server/parser.go (about)

     1  // Copyright 2012-2024 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  }
    36  
    37  type pubArg struct {
    38  	arg     []byte
    39  	pacache []byte
    40  	origin  []byte
    41  	account []byte
    42  	subject []byte
    43  	deliver []byte
    44  	mapped  []byte
    45  	reply   []byte
    46  	szb     []byte
    47  	hdb     []byte
    48  	queues  [][]byte
    49  	size    int
    50  	hdr     int
    51  	psi     []*serviceImport
    52  	trace   *msgTrace
    53  }
    54  
    55  // Parser constants
    56  const (
    57  	OP_START parserState = iota
    58  	OP_PLUS
    59  	OP_PLUS_O
    60  	OP_PLUS_OK
    61  	OP_MINUS
    62  	OP_MINUS_E
    63  	OP_MINUS_ER
    64  	OP_MINUS_ERR
    65  	OP_MINUS_ERR_SPC
    66  	MINUS_ERR_ARG
    67  	OP_C
    68  	OP_CO
    69  	OP_CON
    70  	OP_CONN
    71  	OP_CONNE
    72  	OP_CONNEC
    73  	OP_CONNECT
    74  	CONNECT_ARG
    75  	OP_H
    76  	OP_HP
    77  	OP_HPU
    78  	OP_HPUB
    79  	OP_HPUB_SPC
    80  	HPUB_ARG
    81  	OP_HM
    82  	OP_HMS
    83  	OP_HMSG
    84  	OP_HMSG_SPC
    85  	HMSG_ARG
    86  	OP_P
    87  	OP_PU
    88  	OP_PUB
    89  	OP_PUB_SPC
    90  	PUB_ARG
    91  	OP_PI
    92  	OP_PIN
    93  	OP_PING
    94  	OP_PO
    95  	OP_PON
    96  	OP_PONG
    97  	MSG_PAYLOAD
    98  	MSG_END_R
    99  	MSG_END_N
   100  	OP_S
   101  	OP_SU
   102  	OP_SUB
   103  	OP_SUB_SPC
   104  	SUB_ARG
   105  	OP_A
   106  	OP_ASUB
   107  	OP_ASUB_SPC
   108  	ASUB_ARG
   109  	OP_AUSUB
   110  	OP_AUSUB_SPC
   111  	AUSUB_ARG
   112  	OP_L
   113  	OP_LS
   114  	OP_R
   115  	OP_RS
   116  	OP_U
   117  	OP_UN
   118  	OP_UNS
   119  	OP_UNSU
   120  	OP_UNSUB
   121  	OP_UNSUB_SPC
   122  	UNSUB_ARG
   123  	OP_M
   124  	OP_MS
   125  	OP_MSG
   126  	OP_MSG_SPC
   127  	MSG_ARG
   128  	OP_I
   129  	OP_IN
   130  	OP_INF
   131  	OP_INFO
   132  	INFO_ARG
   133  )
   134  
   135  func (c *client) parse(buf []byte) error {
   136  	// Branch out to mqtt clients. c.mqtt is immutable, but should it become
   137  	// an issue (say data race detection), we could branch outside in readLoop
   138  	if c.isMqtt() {
   139  		return c.mqttParse(buf)
   140  	}
   141  	var i int
   142  	var b byte
   143  	var lmsg bool
   144  
   145  	// Snapshots
   146  	c.mu.Lock()
   147  	// Snapshot and then reset when we receive a
   148  	// proper CONNECT if needed.
   149  	authSet := c.awaitingAuth()
   150  	// Snapshot max control line as well.
   151  	s, mcl, trace := c.srv, c.mcl, c.trace
   152  	c.mu.Unlock()
   153  
   154  	// Move to loop instead of range syntax to allow jumping of i
   155  	for i = 0; i < len(buf); i++ {
   156  		b = buf[i]
   157  
   158  		switch c.state {
   159  		case OP_START:
   160  			c.op = b
   161  			if b != 'C' && b != 'c' {
   162  				if authSet {
   163  					if s == nil {
   164  						goto authErr
   165  					}
   166  					var ok bool
   167  					// Check here for NoAuthUser. If this is set allow non CONNECT protos as our first.
   168  					// E.g. telnet proto demos.
   169  					if noAuthUser := s.getOpts().NoAuthUser; noAuthUser != _EMPTY_ {
   170  						s.mu.Lock()
   171  						user, exists := s.users[noAuthUser]
   172  						s.mu.Unlock()
   173  						if exists {
   174  							c.RegisterUser(user)
   175  							c.mu.Lock()
   176  							c.clearAuthTimer()
   177  							c.flags.set(connectReceived)
   178  							c.mu.Unlock()
   179  							authSet, ok = false, true
   180  						}
   181  					}
   182  					if !ok {
   183  						goto authErr
   184  					}
   185  				}
   186  				// If the connection is a gateway connection, make sure that
   187  				// if this is an inbound, it starts with a CONNECT.
   188  				if c.kind == GATEWAY && !c.gw.outbound && !c.gw.connected {
   189  					// Use auth violation since no CONNECT was sent.
   190  					// It could be a parseErr too.
   191  					goto authErr
   192  				}
   193  			}
   194  			switch b {
   195  			case 'P', 'p':
   196  				c.state = OP_P
   197  			case 'H', 'h':
   198  				c.state = OP_H
   199  			case 'S', 's':
   200  				c.state = OP_S
   201  			case 'U', 'u':
   202  				c.state = OP_U
   203  			case 'R', 'r':
   204  				if c.kind == CLIENT {
   205  					goto parseErr
   206  				} else {
   207  					c.state = OP_R
   208  				}
   209  			case 'L', 'l':
   210  				if c.kind != LEAF && c.kind != ROUTER {
   211  					goto parseErr
   212  				} else {
   213  					c.state = OP_L
   214  				}
   215  			case 'A', 'a':
   216  				if c.kind == CLIENT {
   217  					goto parseErr
   218  				} else {
   219  					c.state = OP_A
   220  				}
   221  			case 'C', 'c':
   222  				c.state = OP_C
   223  			case 'I', 'i':
   224  				c.state = OP_I
   225  			case '+':
   226  				c.state = OP_PLUS
   227  			case '-':
   228  				c.state = OP_MINUS
   229  			default:
   230  				goto parseErr
   231  			}
   232  		case OP_H:
   233  			switch b {
   234  			case 'P', 'p':
   235  				c.state = OP_HP
   236  			case 'M', 'm':
   237  				c.state = OP_HM
   238  			default:
   239  				goto parseErr
   240  			}
   241  		case OP_HP:
   242  			switch b {
   243  			case 'U', 'u':
   244  				c.state = OP_HPU
   245  			default:
   246  				goto parseErr
   247  			}
   248  		case OP_HPU:
   249  			switch b {
   250  			case 'B', 'b':
   251  				c.state = OP_HPUB
   252  			default:
   253  				goto parseErr
   254  			}
   255  		case OP_HPUB:
   256  			switch b {
   257  			case ' ', '\t':
   258  				c.state = OP_HPUB_SPC
   259  			default:
   260  				goto parseErr
   261  			}
   262  		case OP_HPUB_SPC:
   263  			switch b {
   264  			case ' ', '\t':
   265  				continue
   266  			default:
   267  				c.pa.hdr = 0
   268  				c.state = HPUB_ARG
   269  				c.as = i
   270  			}
   271  		case HPUB_ARG:
   272  			switch b {
   273  			case '\r':
   274  				c.drop = 1
   275  			case '\n':
   276  				var arg []byte
   277  				if c.argBuf != nil {
   278  					arg = c.argBuf
   279  					c.argBuf = nil
   280  				} else {
   281  					arg = buf[c.as : i-c.drop]
   282  				}
   283  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
   284  					return err
   285  				}
   286  				if trace {
   287  					c.traceInOp("HPUB", arg)
   288  				}
   289  				var remaining []byte
   290  				if i < len(buf) {
   291  					remaining = buf[i+1:]
   292  				}
   293  				if err := c.processHeaderPub(arg, remaining); err != nil {
   294  					return err
   295  				}
   296  
   297  				c.drop, c.as, c.state = 0, i+1, MSG_PAYLOAD
   298  				// If we don't have a saved buffer then jump ahead with
   299  				// the index. If this overruns what is left we fall out
   300  				// and process split buffer.
   301  				if c.msgBuf == nil {
   302  					i = c.as + c.pa.size - LEN_CR_LF
   303  				}
   304  			default:
   305  				if c.argBuf != nil {
   306  					c.argBuf = append(c.argBuf, b)
   307  				}
   308  			}
   309  		case OP_HM:
   310  			switch b {
   311  			case 'S', 's':
   312  				c.state = OP_HMS
   313  			default:
   314  				goto parseErr
   315  			}
   316  		case OP_HMS:
   317  			switch b {
   318  			case 'G', 'g':
   319  				c.state = OP_HMSG
   320  			default:
   321  				goto parseErr
   322  			}
   323  		case OP_HMSG:
   324  			switch b {
   325  			case ' ', '\t':
   326  				c.state = OP_HMSG_SPC
   327  			default:
   328  				goto parseErr
   329  			}
   330  		case OP_HMSG_SPC:
   331  			switch b {
   332  			case ' ', '\t':
   333  				continue
   334  			default:
   335  				c.pa.hdr = 0
   336  				c.state = HMSG_ARG
   337  				c.as = i
   338  			}
   339  		case HMSG_ARG:
   340  			switch b {
   341  			case '\r':
   342  				c.drop = 1
   343  			case '\n':
   344  				var arg []byte
   345  				if c.argBuf != nil {
   346  					arg = c.argBuf
   347  					c.argBuf = nil
   348  				} else {
   349  					arg = buf[c.as : i-c.drop]
   350  				}
   351  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
   352  					return err
   353  				}
   354  				var err error
   355  				if c.kind == ROUTER || c.kind == GATEWAY {
   356  					if trace {
   357  						c.traceInOp("HMSG", arg)
   358  					}
   359  					err = c.processRoutedHeaderMsgArgs(arg)
   360  				} else if c.kind == LEAF {
   361  					if trace {
   362  						c.traceInOp("HMSG", arg)
   363  					}
   364  					err = c.processLeafHeaderMsgArgs(arg)
   365  				}
   366  				if err != nil {
   367  					return err
   368  				}
   369  				c.drop, c.as, c.state = 0, i+1, MSG_PAYLOAD
   370  
   371  				// jump ahead with the index. If this overruns
   372  				// what is left we fall out and process split
   373  				// buffer.
   374  				i = c.as + c.pa.size - LEN_CR_LF
   375  			default:
   376  				if c.argBuf != nil {
   377  					c.argBuf = append(c.argBuf, b)
   378  				}
   379  			}
   380  		case OP_P:
   381  			switch b {
   382  			case 'U', 'u':
   383  				c.state = OP_PU
   384  			case 'I', 'i':
   385  				c.state = OP_PI
   386  			case 'O', 'o':
   387  				c.state = OP_PO
   388  			default:
   389  				goto parseErr
   390  			}
   391  		case OP_PU:
   392  			switch b {
   393  			case 'B', 'b':
   394  				c.state = OP_PUB
   395  			default:
   396  				goto parseErr
   397  			}
   398  		case OP_PUB:
   399  			switch b {
   400  			case ' ', '\t':
   401  				c.state = OP_PUB_SPC
   402  			default:
   403  				goto parseErr
   404  			}
   405  		case OP_PUB_SPC:
   406  			switch b {
   407  			case ' ', '\t':
   408  				continue
   409  			default:
   410  				c.pa.hdr = -1
   411  				c.state = PUB_ARG
   412  				c.as = i
   413  			}
   414  		case PUB_ARG:
   415  			switch b {
   416  			case '\r':
   417  				c.drop = 1
   418  			case '\n':
   419  				var arg []byte
   420  				if c.argBuf != nil {
   421  					arg = c.argBuf
   422  					c.argBuf = nil
   423  				} else {
   424  					arg = buf[c.as : i-c.drop]
   425  				}
   426  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
   427  					return err
   428  				}
   429  				if trace {
   430  					c.traceInOp("PUB", arg)
   431  				}
   432  				if err := c.processPub(arg); err != nil {
   433  					return err
   434  				}
   435  
   436  				c.drop, c.as, c.state = 0, i+1, MSG_PAYLOAD
   437  				// If we don't have a saved buffer then jump ahead with
   438  				// the index. If this overruns what is left we fall out
   439  				// and process split buffer.
   440  				if c.msgBuf == nil {
   441  					i = c.as + c.pa.size - LEN_CR_LF
   442  				}
   443  			default:
   444  				if c.argBuf != nil {
   445  					c.argBuf = append(c.argBuf, b)
   446  				}
   447  			}
   448  		case MSG_PAYLOAD:
   449  			if c.msgBuf != nil {
   450  				// copy as much as we can to the buffer and skip ahead.
   451  				toCopy := c.pa.size - len(c.msgBuf)
   452  				avail := len(buf) - i
   453  				if avail < toCopy {
   454  					toCopy = avail
   455  				}
   456  				if toCopy > 0 {
   457  					start := len(c.msgBuf)
   458  					// This is needed for copy to work.
   459  					c.msgBuf = c.msgBuf[:start+toCopy]
   460  					copy(c.msgBuf[start:], buf[i:i+toCopy])
   461  					// Update our index
   462  					i = (i + toCopy) - 1
   463  				} else {
   464  					// Fall back to append if needed.
   465  					c.msgBuf = append(c.msgBuf, b)
   466  				}
   467  				if len(c.msgBuf) >= c.pa.size {
   468  					c.state = MSG_END_R
   469  				}
   470  			} else if i-c.as+1 >= c.pa.size {
   471  				c.state = MSG_END_R
   472  			}
   473  		case MSG_END_R:
   474  			if b != '\r' {
   475  				goto parseErr
   476  			}
   477  			if c.msgBuf != nil {
   478  				c.msgBuf = append(c.msgBuf, b)
   479  			}
   480  			c.state = MSG_END_N
   481  		case MSG_END_N:
   482  			if b != '\n' {
   483  				goto parseErr
   484  			}
   485  			if c.msgBuf != nil {
   486  				c.msgBuf = append(c.msgBuf, b)
   487  			} else {
   488  				c.msgBuf = buf[c.as : i+1]
   489  			}
   490  
   491  			var mt *msgTrace
   492  			if c.pa.hdr > 0 {
   493  				mt = c.initMsgTrace()
   494  			}
   495  			// Check for mappings.
   496  			if (c.kind == CLIENT || c.kind == LEAF) && c.in.flags.isSet(hasMappings) {
   497  				changed := c.selectMappedSubject()
   498  				if changed {
   499  					if trace {
   500  						c.traceInOp("MAPPING", []byte(fmt.Sprintf("%s -> %s", c.pa.mapped, c.pa.subject)))
   501  					}
   502  					// c.pa.subject is the subject the original is now mapped to.
   503  					mt.addSubjectMappingEvent(c.pa.subject)
   504  				}
   505  			}
   506  			if trace {
   507  				c.traceMsg(c.msgBuf)
   508  			}
   509  
   510  			c.processInboundMsg(c.msgBuf)
   511  
   512  			mt.sendEvent()
   513  			c.argBuf, c.msgBuf, c.header = nil, nil, nil
   514  			c.drop, c.as, c.state = 0, i+1, OP_START
   515  			// Drop all pub args
   516  			c.pa.arg, c.pa.pacache, c.pa.origin, c.pa.account, c.pa.subject, c.pa.mapped = nil, nil, nil, nil, nil, nil
   517  			c.pa.reply, c.pa.hdr, c.pa.size, c.pa.szb, c.pa.hdb, c.pa.queues = nil, -1, 0, nil, nil, nil
   518  			c.pa.trace = nil
   519  			lmsg = false
   520  		case OP_A:
   521  			switch b {
   522  			case '+':
   523  				c.state = OP_ASUB
   524  			case '-', 'u':
   525  				c.state = OP_AUSUB
   526  			default:
   527  				goto parseErr
   528  			}
   529  		case OP_ASUB:
   530  			switch b {
   531  			case ' ', '\t':
   532  				c.state = OP_ASUB_SPC
   533  			default:
   534  				goto parseErr
   535  			}
   536  		case OP_ASUB_SPC:
   537  			switch b {
   538  			case ' ', '\t':
   539  				continue
   540  			default:
   541  				c.state = ASUB_ARG
   542  				c.as = i
   543  			}
   544  		case ASUB_ARG:
   545  			switch b {
   546  			case '\r':
   547  				c.drop = 1
   548  			case '\n':
   549  				var arg []byte
   550  				if c.argBuf != nil {
   551  					arg = c.argBuf
   552  					c.argBuf = nil
   553  				} else {
   554  					arg = buf[c.as : i-c.drop]
   555  				}
   556  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
   557  					return err
   558  				}
   559  				if trace {
   560  					c.traceInOp("A+", arg)
   561  				}
   562  				if err := c.processAccountSub(arg); err != nil {
   563  					return err
   564  				}
   565  				c.drop, c.as, c.state = 0, i+1, OP_START
   566  			default:
   567  				if c.argBuf != nil {
   568  					c.argBuf = append(c.argBuf, b)
   569  				}
   570  			}
   571  		case OP_AUSUB:
   572  			switch b {
   573  			case ' ', '\t':
   574  				c.state = OP_AUSUB_SPC
   575  			default:
   576  				goto parseErr
   577  			}
   578  		case OP_AUSUB_SPC:
   579  			switch b {
   580  			case ' ', '\t':
   581  				continue
   582  			default:
   583  				c.state = AUSUB_ARG
   584  				c.as = i
   585  			}
   586  		case AUSUB_ARG:
   587  			switch b {
   588  			case '\r':
   589  				c.drop = 1
   590  			case '\n':
   591  				var arg []byte
   592  				if c.argBuf != nil {
   593  					arg = c.argBuf
   594  					c.argBuf = nil
   595  				} else {
   596  					arg = buf[c.as : i-c.drop]
   597  				}
   598  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
   599  					return err
   600  				}
   601  				if trace {
   602  					c.traceInOp("A-", arg)
   603  				}
   604  				c.processAccountUnsub(arg)
   605  				c.drop, c.as, c.state = 0, i+1, OP_START
   606  			default:
   607  				if c.argBuf != nil {
   608  					c.argBuf = append(c.argBuf, b)
   609  				}
   610  			}
   611  		case OP_S:
   612  			switch b {
   613  			case 'U', 'u':
   614  				c.state = OP_SU
   615  			default:
   616  				goto parseErr
   617  			}
   618  		case OP_SU:
   619  			switch b {
   620  			case 'B', 'b':
   621  				c.state = OP_SUB
   622  			default:
   623  				goto parseErr
   624  			}
   625  		case OP_SUB:
   626  			switch b {
   627  			case ' ', '\t':
   628  				c.state = OP_SUB_SPC
   629  			default:
   630  				goto parseErr
   631  			}
   632  		case OP_SUB_SPC:
   633  			switch b {
   634  			case ' ', '\t':
   635  				continue
   636  			default:
   637  				c.state = SUB_ARG
   638  				c.as = i
   639  			}
   640  		case SUB_ARG:
   641  			switch b {
   642  			case '\r':
   643  				c.drop = 1
   644  			case '\n':
   645  				var arg []byte
   646  				if c.argBuf != nil {
   647  					arg = c.argBuf
   648  					c.argBuf = nil
   649  				} else {
   650  					arg = buf[c.as : i-c.drop]
   651  				}
   652  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
   653  					return err
   654  				}
   655  				var err error
   656  
   657  				switch c.kind {
   658  				case CLIENT:
   659  					if trace {
   660  						c.traceInOp("SUB", arg)
   661  					}
   662  					err = c.parseSub(arg, false)
   663  				case ROUTER:
   664  					switch c.op {
   665  					case 'R', 'r':
   666  						if trace {
   667  							c.traceInOp("RS+", arg)
   668  						}
   669  						err = c.processRemoteSub(arg, false)
   670  					case 'L', 'l':
   671  						if trace {
   672  							c.traceInOp("LS+", arg)
   673  						}
   674  						err = c.processRemoteSub(arg, true)
   675  					}
   676  				case GATEWAY:
   677  					if trace {
   678  						c.traceInOp("RS+", arg)
   679  					}
   680  					err = c.processGatewayRSub(arg)
   681  				case LEAF:
   682  					if trace {
   683  						c.traceInOp("LS+", arg)
   684  					}
   685  					err = c.processLeafSub(arg)
   686  				}
   687  				if err != nil {
   688  					return err
   689  				}
   690  				c.drop, c.as, c.state = 0, i+1, OP_START
   691  			default:
   692  				if c.argBuf != nil {
   693  					c.argBuf = append(c.argBuf, b)
   694  				}
   695  			}
   696  		case OP_L:
   697  			switch b {
   698  			case 'S', 's':
   699  				c.state = OP_LS
   700  			case 'M', 'm':
   701  				c.state = OP_M
   702  			default:
   703  				goto parseErr
   704  			}
   705  		case OP_LS:
   706  			switch b {
   707  			case '+':
   708  				c.state = OP_SUB
   709  			case '-':
   710  				c.state = OP_UNSUB
   711  			default:
   712  				goto parseErr
   713  			}
   714  		case OP_R:
   715  			switch b {
   716  			case 'S', 's':
   717  				c.state = OP_RS
   718  			case 'M', 'm':
   719  				c.state = OP_M
   720  			default:
   721  				goto parseErr
   722  			}
   723  		case OP_RS:
   724  			switch b {
   725  			case '+':
   726  				c.state = OP_SUB
   727  			case '-':
   728  				c.state = OP_UNSUB
   729  			default:
   730  				goto parseErr
   731  			}
   732  		case OP_U:
   733  			switch b {
   734  			case 'N', 'n':
   735  				c.state = OP_UN
   736  			default:
   737  				goto parseErr
   738  			}
   739  		case OP_UN:
   740  			switch b {
   741  			case 'S', 's':
   742  				c.state = OP_UNS
   743  			default:
   744  				goto parseErr
   745  			}
   746  		case OP_UNS:
   747  			switch b {
   748  			case 'U', 'u':
   749  				c.state = OP_UNSU
   750  			default:
   751  				goto parseErr
   752  			}
   753  		case OP_UNSU:
   754  			switch b {
   755  			case 'B', 'b':
   756  				c.state = OP_UNSUB
   757  			default:
   758  				goto parseErr
   759  			}
   760  		case OP_UNSUB:
   761  			switch b {
   762  			case ' ', '\t':
   763  				c.state = OP_UNSUB_SPC
   764  			default:
   765  				goto parseErr
   766  			}
   767  		case OP_UNSUB_SPC:
   768  			switch b {
   769  			case ' ', '\t':
   770  				continue
   771  			default:
   772  				c.state = UNSUB_ARG
   773  				c.as = i
   774  			}
   775  		case UNSUB_ARG:
   776  			switch b {
   777  			case '\r':
   778  				c.drop = 1
   779  			case '\n':
   780  				var arg []byte
   781  				if c.argBuf != nil {
   782  					arg = c.argBuf
   783  					c.argBuf = nil
   784  				} else {
   785  					arg = buf[c.as : i-c.drop]
   786  				}
   787  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
   788  					return err
   789  				}
   790  				var err error
   791  
   792  				switch c.kind {
   793  				case CLIENT:
   794  					if trace {
   795  						c.traceInOp("UNSUB", arg)
   796  					}
   797  					err = c.processUnsub(arg)
   798  				case ROUTER:
   799  					if trace && c.srv != nil {
   800  						switch c.op {
   801  						case 'R', 'r':
   802  							c.traceInOp("RS-", arg)
   803  						case 'L', 'l':
   804  							c.traceInOp("LS-", arg)
   805  						}
   806  					}
   807  					err = c.processRemoteUnsub(arg)
   808  				case GATEWAY:
   809  					if trace {
   810  						c.traceInOp("RS-", arg)
   811  					}
   812  					err = c.processGatewayRUnsub(arg)
   813  				case LEAF:
   814  					if trace {
   815  						c.traceInOp("LS-", arg)
   816  					}
   817  					err = c.processLeafUnsub(arg)
   818  				}
   819  				if err != nil {
   820  					return err
   821  				}
   822  				c.drop, c.as, c.state = 0, i+1, OP_START
   823  			default:
   824  				if c.argBuf != nil {
   825  					c.argBuf = append(c.argBuf, b)
   826  				}
   827  			}
   828  		case OP_PI:
   829  			switch b {
   830  			case 'N', 'n':
   831  				c.state = OP_PIN
   832  			default:
   833  				goto parseErr
   834  			}
   835  		case OP_PIN:
   836  			switch b {
   837  			case 'G', 'g':
   838  				c.state = OP_PING
   839  			default:
   840  				goto parseErr
   841  			}
   842  		case OP_PING:
   843  			switch b {
   844  			case '\n':
   845  				if trace {
   846  					c.traceInOp("PING", nil)
   847  				}
   848  				c.processPing()
   849  				c.drop, c.state = 0, OP_START
   850  			}
   851  		case OP_PO:
   852  			switch b {
   853  			case 'N', 'n':
   854  				c.state = OP_PON
   855  			default:
   856  				goto parseErr
   857  			}
   858  		case OP_PON:
   859  			switch b {
   860  			case 'G', 'g':
   861  				c.state = OP_PONG
   862  			default:
   863  				goto parseErr
   864  			}
   865  		case OP_PONG:
   866  			switch b {
   867  			case '\n':
   868  				if trace {
   869  					c.traceInOp("PONG", nil)
   870  				}
   871  				c.processPong()
   872  				c.drop, c.state = 0, OP_START
   873  			}
   874  		case OP_C:
   875  			switch b {
   876  			case 'O', 'o':
   877  				c.state = OP_CO
   878  			default:
   879  				goto parseErr
   880  			}
   881  		case OP_CO:
   882  			switch b {
   883  			case 'N', 'n':
   884  				c.state = OP_CON
   885  			default:
   886  				goto parseErr
   887  			}
   888  		case OP_CON:
   889  			switch b {
   890  			case 'N', 'n':
   891  				c.state = OP_CONN
   892  			default:
   893  				goto parseErr
   894  			}
   895  		case OP_CONN:
   896  			switch b {
   897  			case 'E', 'e':
   898  				c.state = OP_CONNE
   899  			default:
   900  				goto parseErr
   901  			}
   902  		case OP_CONNE:
   903  			switch b {
   904  			case 'C', 'c':
   905  				c.state = OP_CONNEC
   906  			default:
   907  				goto parseErr
   908  			}
   909  		case OP_CONNEC:
   910  			switch b {
   911  			case 'T', 't':
   912  				c.state = OP_CONNECT
   913  			default:
   914  				goto parseErr
   915  			}
   916  		case OP_CONNECT:
   917  			switch b {
   918  			case ' ', '\t':
   919  				continue
   920  			default:
   921  				c.state = CONNECT_ARG
   922  				c.as = i
   923  			}
   924  		case CONNECT_ARG:
   925  			switch b {
   926  			case '\r':
   927  				c.drop = 1
   928  			case '\n':
   929  				var arg []byte
   930  				if c.argBuf != nil {
   931  					arg = c.argBuf
   932  					c.argBuf = nil
   933  				} else {
   934  					arg = buf[c.as : i-c.drop]
   935  				}
   936  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
   937  					return err
   938  				}
   939  				if trace {
   940  					c.traceInOp("CONNECT", removePassFromTrace(arg))
   941  				}
   942  				if err := c.processConnect(arg); err != nil {
   943  					return err
   944  				}
   945  				c.drop, c.state = 0, OP_START
   946  				// Reset notion on authSet
   947  				c.mu.Lock()
   948  				authSet = c.awaitingAuth()
   949  				c.mu.Unlock()
   950  			default:
   951  				if c.argBuf != nil {
   952  					c.argBuf = append(c.argBuf, b)
   953  				}
   954  			}
   955  		case OP_M:
   956  			switch b {
   957  			case 'S', 's':
   958  				c.state = OP_MS
   959  			default:
   960  				goto parseErr
   961  			}
   962  		case OP_MS:
   963  			switch b {
   964  			case 'G', 'g':
   965  				c.state = OP_MSG
   966  			default:
   967  				goto parseErr
   968  			}
   969  		case OP_MSG:
   970  			switch b {
   971  			case ' ', '\t':
   972  				c.state = OP_MSG_SPC
   973  			default:
   974  				goto parseErr
   975  			}
   976  		case OP_MSG_SPC:
   977  			switch b {
   978  			case ' ', '\t':
   979  				continue
   980  			default:
   981  				c.pa.hdr = -1
   982  				c.state = MSG_ARG
   983  				c.as = i
   984  			}
   985  		case MSG_ARG:
   986  			switch b {
   987  			case '\r':
   988  				c.drop = 1
   989  			case '\n':
   990  				var arg []byte
   991  				if c.argBuf != nil {
   992  					arg = c.argBuf
   993  					c.argBuf = nil
   994  				} else {
   995  					arg = buf[c.as : i-c.drop]
   996  				}
   997  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
   998  					return err
   999  				}
  1000  				var err error
  1001  				if c.kind == ROUTER || c.kind == GATEWAY {
  1002  					switch c.op {
  1003  					case 'R', 'r':
  1004  						if trace {
  1005  							c.traceInOp("RMSG", arg)
  1006  						}
  1007  						err = c.processRoutedMsgArgs(arg)
  1008  					case 'L', 'l':
  1009  						if trace {
  1010  							c.traceInOp("LMSG", arg)
  1011  						}
  1012  						lmsg = true
  1013  						err = c.processRoutedOriginClusterMsgArgs(arg)
  1014  					}
  1015  				} else if c.kind == LEAF {
  1016  					if trace {
  1017  						c.traceInOp("LMSG", arg)
  1018  					}
  1019  					err = c.processLeafMsgArgs(arg)
  1020  				}
  1021  				if err != nil {
  1022  					return err
  1023  				}
  1024  				c.drop, c.as, c.state = 0, i+1, MSG_PAYLOAD
  1025  
  1026  				// jump ahead with the index. If this overruns
  1027  				// what is left we fall out and process split
  1028  				// buffer.
  1029  				i = c.as + c.pa.size - LEN_CR_LF
  1030  			default:
  1031  				if c.argBuf != nil {
  1032  					c.argBuf = append(c.argBuf, b)
  1033  				}
  1034  			}
  1035  		case OP_I:
  1036  			switch b {
  1037  			case 'N', 'n':
  1038  				c.state = OP_IN
  1039  			default:
  1040  				goto parseErr
  1041  			}
  1042  		case OP_IN:
  1043  			switch b {
  1044  			case 'F', 'f':
  1045  				c.state = OP_INF
  1046  			default:
  1047  				goto parseErr
  1048  			}
  1049  		case OP_INF:
  1050  			switch b {
  1051  			case 'O', 'o':
  1052  				c.state = OP_INFO
  1053  			default:
  1054  				goto parseErr
  1055  			}
  1056  		case OP_INFO:
  1057  			switch b {
  1058  			case ' ', '\t':
  1059  				continue
  1060  			default:
  1061  				c.state = INFO_ARG
  1062  				c.as = i
  1063  			}
  1064  		case INFO_ARG:
  1065  			switch b {
  1066  			case '\r':
  1067  				c.drop = 1
  1068  			case '\n':
  1069  				var arg []byte
  1070  				if c.argBuf != nil {
  1071  					arg = c.argBuf
  1072  					c.argBuf = nil
  1073  				} else {
  1074  					arg = buf[c.as : i-c.drop]
  1075  				}
  1076  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
  1077  					return err
  1078  				}
  1079  				if err := c.processInfo(arg); err != nil {
  1080  					return err
  1081  				}
  1082  				c.drop, c.as, c.state = 0, i+1, OP_START
  1083  			default:
  1084  				if c.argBuf != nil {
  1085  					c.argBuf = append(c.argBuf, b)
  1086  				}
  1087  			}
  1088  		case OP_PLUS:
  1089  			switch b {
  1090  			case 'O', 'o':
  1091  				c.state = OP_PLUS_O
  1092  			default:
  1093  				goto parseErr
  1094  			}
  1095  		case OP_PLUS_O:
  1096  			switch b {
  1097  			case 'K', 'k':
  1098  				c.state = OP_PLUS_OK
  1099  			default:
  1100  				goto parseErr
  1101  			}
  1102  		case OP_PLUS_OK:
  1103  			switch b {
  1104  			case '\n':
  1105  				c.drop, c.state = 0, OP_START
  1106  			}
  1107  		case OP_MINUS:
  1108  			switch b {
  1109  			case 'E', 'e':
  1110  				c.state = OP_MINUS_E
  1111  			default:
  1112  				goto parseErr
  1113  			}
  1114  		case OP_MINUS_E:
  1115  			switch b {
  1116  			case 'R', 'r':
  1117  				c.state = OP_MINUS_ER
  1118  			default:
  1119  				goto parseErr
  1120  			}
  1121  		case OP_MINUS_ER:
  1122  			switch b {
  1123  			case 'R', 'r':
  1124  				c.state = OP_MINUS_ERR
  1125  			default:
  1126  				goto parseErr
  1127  			}
  1128  		case OP_MINUS_ERR:
  1129  			switch b {
  1130  			case ' ', '\t':
  1131  				c.state = OP_MINUS_ERR_SPC
  1132  			default:
  1133  				goto parseErr
  1134  			}
  1135  		case OP_MINUS_ERR_SPC:
  1136  			switch b {
  1137  			case ' ', '\t':
  1138  				continue
  1139  			default:
  1140  				c.state = MINUS_ERR_ARG
  1141  				c.as = i
  1142  			}
  1143  		case MINUS_ERR_ARG:
  1144  			switch b {
  1145  			case '\r':
  1146  				c.drop = 1
  1147  			case '\n':
  1148  				var arg []byte
  1149  				if c.argBuf != nil {
  1150  					arg = c.argBuf
  1151  					c.argBuf = nil
  1152  				} else {
  1153  					arg = buf[c.as : i-c.drop]
  1154  				}
  1155  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
  1156  					return err
  1157  				}
  1158  				c.processErr(string(arg))
  1159  				c.drop, c.as, c.state = 0, i+1, OP_START
  1160  			default:
  1161  				if c.argBuf != nil {
  1162  					c.argBuf = append(c.argBuf, b)
  1163  				}
  1164  			}
  1165  		default:
  1166  			goto parseErr
  1167  		}
  1168  	}
  1169  
  1170  	// Check for split buffer scenarios for any ARG state.
  1171  	if c.state == SUB_ARG || c.state == UNSUB_ARG ||
  1172  		c.state == PUB_ARG || c.state == HPUB_ARG ||
  1173  		c.state == ASUB_ARG || c.state == AUSUB_ARG ||
  1174  		c.state == MSG_ARG || c.state == HMSG_ARG ||
  1175  		c.state == MINUS_ERR_ARG || c.state == CONNECT_ARG || c.state == INFO_ARG {
  1176  
  1177  		// Setup a holder buffer to deal with split buffer scenario.
  1178  		if c.argBuf == nil {
  1179  			c.argBuf = c.scratch[:0]
  1180  			c.argBuf = append(c.argBuf, buf[c.as:i-c.drop]...)
  1181  		}
  1182  		// Check for violations of control line length here. Note that this is not
  1183  		// exact at all but the performance hit is too great to be precise, and
  1184  		// catching here should prevent memory exhaustion attacks.
  1185  		if err := c.overMaxControlLineLimit(c.argBuf, mcl); err != nil {
  1186  			return err
  1187  		}
  1188  	}
  1189  
  1190  	// Check for split msg
  1191  	if (c.state == MSG_PAYLOAD || c.state == MSG_END_R || c.state == MSG_END_N) && c.msgBuf == nil {
  1192  		// We need to clone the pubArg if it is still referencing the
  1193  		// read buffer and we are not able to process the msg.
  1194  
  1195  		if c.argBuf == nil {
  1196  			// Works also for MSG_ARG, when message comes from ROUTE or GATEWAY.
  1197  			if err := c.clonePubArg(lmsg); err != nil {
  1198  				goto parseErr
  1199  			}
  1200  		}
  1201  
  1202  		// If we will overflow the scratch buffer, just create a
  1203  		// new buffer to hold the split message.
  1204  		if c.pa.size > cap(c.scratch)-len(c.argBuf) {
  1205  			lrem := len(buf[c.as:])
  1206  			// Consider it a protocol error when the remaining payload
  1207  			// is larger than the reported size for PUB. It can happen
  1208  			// when processing incomplete messages from rogue clients.
  1209  			if lrem > c.pa.size+LEN_CR_LF {
  1210  				goto parseErr
  1211  			}
  1212  			c.msgBuf = make([]byte, lrem, c.pa.size+LEN_CR_LF)
  1213  			copy(c.msgBuf, buf[c.as:])
  1214  		} else {
  1215  			c.msgBuf = c.scratch[len(c.argBuf):len(c.argBuf)]
  1216  			c.msgBuf = append(c.msgBuf, (buf[c.as:])...)
  1217  		}
  1218  	}
  1219  
  1220  	return nil
  1221  
  1222  authErr:
  1223  	c.authViolation()
  1224  	return ErrAuthentication
  1225  
  1226  parseErr:
  1227  	c.sendErr("Unknown Protocol Operation")
  1228  	snip := protoSnippet(i, PROTO_SNIPPET_SIZE, buf)
  1229  	err := fmt.Errorf("%s parser ERROR, state=%d, i=%d: proto='%s...'", c.kindString(), c.state, i, snip)
  1230  	return err
  1231  }
  1232  
  1233  func protoSnippet(start, max int, buf []byte) string {
  1234  	stop := start + max
  1235  	bufSize := len(buf)
  1236  	if start >= bufSize {
  1237  		return `""`
  1238  	}
  1239  	if stop > bufSize {
  1240  		stop = bufSize - 1
  1241  	}
  1242  	return fmt.Sprintf("%q", buf[start:stop])
  1243  }
  1244  
  1245  // Check if the length of buffer `arg` is over the max control line limit `mcl`.
  1246  // If so, an error is sent to the client and the connection is closed.
  1247  // The error ErrMaxControlLine is returned.
  1248  func (c *client) overMaxControlLineLimit(arg []byte, mcl int32) error {
  1249  	if c.kind != CLIENT {
  1250  		return nil
  1251  	}
  1252  	if len(arg) > int(mcl) {
  1253  		err := NewErrorCtx(ErrMaxControlLine, "State %d, max_control_line %d, Buffer len %d (snip: %s...)",
  1254  			c.state, int(mcl), len(c.argBuf), protoSnippet(0, MAX_CONTROL_LINE_SNIPPET_SIZE, arg))
  1255  		c.sendErr(err.Error())
  1256  		c.closeConnection(MaxControlLineExceeded)
  1257  		return err
  1258  	}
  1259  	return nil
  1260  }
  1261  
  1262  // clonePubArg is used when the split buffer scenario has the pubArg in the existing read buffer, but
  1263  // we need to hold onto it into the next read.
  1264  func (c *client) clonePubArg(lmsg bool) error {
  1265  	// Just copy and re-process original arg buffer.
  1266  	c.argBuf = c.scratch[:0]
  1267  	c.argBuf = append(c.argBuf, c.pa.arg...)
  1268  
  1269  	switch c.kind {
  1270  	case ROUTER, GATEWAY:
  1271  		if lmsg {
  1272  			return c.processRoutedOriginClusterMsgArgs(c.argBuf)
  1273  		}
  1274  		if c.pa.hdr < 0 {
  1275  			return c.processRoutedMsgArgs(c.argBuf)
  1276  		} else {
  1277  			return c.processRoutedHeaderMsgArgs(c.argBuf)
  1278  		}
  1279  	case LEAF:
  1280  		if c.pa.hdr < 0 {
  1281  			return c.processLeafMsgArgs(c.argBuf)
  1282  		} else {
  1283  			return c.processLeafHeaderMsgArgs(c.argBuf)
  1284  		}
  1285  	default:
  1286  		if c.pa.hdr < 0 {
  1287  			return c.processPub(c.argBuf)
  1288  		} else {
  1289  			return c.processHeaderPub(c.argBuf, nil)
  1290  		}
  1291  	}
  1292  }
  1293  
  1294  func (ps *parseState) getHeader() http.Header {
  1295  	if ps.header == nil {
  1296  		if hdr := ps.pa.hdr; hdr > 0 {
  1297  			reader := bufio.NewReader(bytes.NewReader(ps.msgBuf[0:hdr]))
  1298  			tp := textproto.NewReader(reader)
  1299  			tp.ReadLine() // skip over first line, contains version
  1300  			if mimeHeader, err := tp.ReadMIMEHeader(); err == nil {
  1301  				ps.header = http.Header(mimeHeader)
  1302  			}
  1303  		}
  1304  	}
  1305  	return ps.header
  1306  }