get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/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 (trace || mt != nil) && changed {
   499  					c.traceInOp("MAPPING", []byte(fmt.Sprintf("%s -> %s", c.pa.mapped, c.pa.subject)))
   500  					// c.pa.subject is the subject the original is now mapped to.
   501  					mt.addSubjectMappingEvent(c.pa.subject)
   502  				}
   503  			}
   504  			if trace {
   505  				c.traceMsg(c.msgBuf)
   506  			}
   507  
   508  			c.processInboundMsg(c.msgBuf)
   509  
   510  			mt.sendEvent()
   511  			c.argBuf, c.msgBuf, c.header = nil, nil, nil
   512  			c.drop, c.as, c.state = 0, i+1, OP_START
   513  			// Drop all pub args
   514  			c.pa.arg, c.pa.pacache, c.pa.origin, c.pa.account, c.pa.subject, c.pa.mapped = nil, nil, nil, nil, nil, nil
   515  			c.pa.reply, c.pa.hdr, c.pa.size, c.pa.szb, c.pa.hdb, c.pa.queues = nil, -1, 0, nil, nil, nil
   516  			c.pa.trace = nil
   517  			lmsg = false
   518  		case OP_A:
   519  			switch b {
   520  			case '+':
   521  				c.state = OP_ASUB
   522  			case '-', 'u':
   523  				c.state = OP_AUSUB
   524  			default:
   525  				goto parseErr
   526  			}
   527  		case OP_ASUB:
   528  			switch b {
   529  			case ' ', '\t':
   530  				c.state = OP_ASUB_SPC
   531  			default:
   532  				goto parseErr
   533  			}
   534  		case OP_ASUB_SPC:
   535  			switch b {
   536  			case ' ', '\t':
   537  				continue
   538  			default:
   539  				c.state = ASUB_ARG
   540  				c.as = i
   541  			}
   542  		case ASUB_ARG:
   543  			switch b {
   544  			case '\r':
   545  				c.drop = 1
   546  			case '\n':
   547  				var arg []byte
   548  				if c.argBuf != nil {
   549  					arg = c.argBuf
   550  					c.argBuf = nil
   551  				} else {
   552  					arg = buf[c.as : i-c.drop]
   553  				}
   554  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
   555  					return err
   556  				}
   557  				if trace {
   558  					c.traceInOp("A+", arg)
   559  				}
   560  				if err := c.processAccountSub(arg); err != nil {
   561  					return err
   562  				}
   563  				c.drop, c.as, c.state = 0, i+1, OP_START
   564  			default:
   565  				if c.argBuf != nil {
   566  					c.argBuf = append(c.argBuf, b)
   567  				}
   568  			}
   569  		case OP_AUSUB:
   570  			switch b {
   571  			case ' ', '\t':
   572  				c.state = OP_AUSUB_SPC
   573  			default:
   574  				goto parseErr
   575  			}
   576  		case OP_AUSUB_SPC:
   577  			switch b {
   578  			case ' ', '\t':
   579  				continue
   580  			default:
   581  				c.state = AUSUB_ARG
   582  				c.as = i
   583  			}
   584  		case AUSUB_ARG:
   585  			switch b {
   586  			case '\r':
   587  				c.drop = 1
   588  			case '\n':
   589  				var arg []byte
   590  				if c.argBuf != nil {
   591  					arg = c.argBuf
   592  					c.argBuf = nil
   593  				} else {
   594  					arg = buf[c.as : i-c.drop]
   595  				}
   596  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
   597  					return err
   598  				}
   599  				if trace {
   600  					c.traceInOp("A-", arg)
   601  				}
   602  				c.processAccountUnsub(arg)
   603  				c.drop, c.as, c.state = 0, i+1, OP_START
   604  			default:
   605  				if c.argBuf != nil {
   606  					c.argBuf = append(c.argBuf, b)
   607  				}
   608  			}
   609  		case OP_S:
   610  			switch b {
   611  			case 'U', 'u':
   612  				c.state = OP_SU
   613  			default:
   614  				goto parseErr
   615  			}
   616  		case OP_SU:
   617  			switch b {
   618  			case 'B', 'b':
   619  				c.state = OP_SUB
   620  			default:
   621  				goto parseErr
   622  			}
   623  		case OP_SUB:
   624  			switch b {
   625  			case ' ', '\t':
   626  				c.state = OP_SUB_SPC
   627  			default:
   628  				goto parseErr
   629  			}
   630  		case OP_SUB_SPC:
   631  			switch b {
   632  			case ' ', '\t':
   633  				continue
   634  			default:
   635  				c.state = SUB_ARG
   636  				c.as = i
   637  			}
   638  		case SUB_ARG:
   639  			switch b {
   640  			case '\r':
   641  				c.drop = 1
   642  			case '\n':
   643  				var arg []byte
   644  				if c.argBuf != nil {
   645  					arg = c.argBuf
   646  					c.argBuf = nil
   647  				} else {
   648  					arg = buf[c.as : i-c.drop]
   649  				}
   650  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
   651  					return err
   652  				}
   653  				var err error
   654  
   655  				switch c.kind {
   656  				case CLIENT:
   657  					if trace {
   658  						c.traceInOp("SUB", arg)
   659  					}
   660  					err = c.parseSub(arg, false)
   661  				case ROUTER:
   662  					switch c.op {
   663  					case 'R', 'r':
   664  						if trace {
   665  							c.traceInOp("RS+", arg)
   666  						}
   667  						err = c.processRemoteSub(arg, false)
   668  					case 'L', 'l':
   669  						if trace {
   670  							c.traceInOp("LS+", arg)
   671  						}
   672  						err = c.processRemoteSub(arg, true)
   673  					}
   674  				case GATEWAY:
   675  					if trace {
   676  						c.traceInOp("RS+", arg)
   677  					}
   678  					err = c.processGatewayRSub(arg)
   679  				case LEAF:
   680  					if trace {
   681  						c.traceInOp("LS+", arg)
   682  					}
   683  					err = c.processLeafSub(arg)
   684  				}
   685  				if err != nil {
   686  					return err
   687  				}
   688  				c.drop, c.as, c.state = 0, i+1, OP_START
   689  			default:
   690  				if c.argBuf != nil {
   691  					c.argBuf = append(c.argBuf, b)
   692  				}
   693  			}
   694  		case OP_L:
   695  			switch b {
   696  			case 'S', 's':
   697  				c.state = OP_LS
   698  			case 'M', 'm':
   699  				c.state = OP_M
   700  			default:
   701  				goto parseErr
   702  			}
   703  		case OP_LS:
   704  			switch b {
   705  			case '+':
   706  				c.state = OP_SUB
   707  			case '-':
   708  				c.state = OP_UNSUB
   709  			default:
   710  				goto parseErr
   711  			}
   712  		case OP_R:
   713  			switch b {
   714  			case 'S', 's':
   715  				c.state = OP_RS
   716  			case 'M', 'm':
   717  				c.state = OP_M
   718  			default:
   719  				goto parseErr
   720  			}
   721  		case OP_RS:
   722  			switch b {
   723  			case '+':
   724  				c.state = OP_SUB
   725  			case '-':
   726  				c.state = OP_UNSUB
   727  			default:
   728  				goto parseErr
   729  			}
   730  		case OP_U:
   731  			switch b {
   732  			case 'N', 'n':
   733  				c.state = OP_UN
   734  			default:
   735  				goto parseErr
   736  			}
   737  		case OP_UN:
   738  			switch b {
   739  			case 'S', 's':
   740  				c.state = OP_UNS
   741  			default:
   742  				goto parseErr
   743  			}
   744  		case OP_UNS:
   745  			switch b {
   746  			case 'U', 'u':
   747  				c.state = OP_UNSU
   748  			default:
   749  				goto parseErr
   750  			}
   751  		case OP_UNSU:
   752  			switch b {
   753  			case 'B', 'b':
   754  				c.state = OP_UNSUB
   755  			default:
   756  				goto parseErr
   757  			}
   758  		case OP_UNSUB:
   759  			switch b {
   760  			case ' ', '\t':
   761  				c.state = OP_UNSUB_SPC
   762  			default:
   763  				goto parseErr
   764  			}
   765  		case OP_UNSUB_SPC:
   766  			switch b {
   767  			case ' ', '\t':
   768  				continue
   769  			default:
   770  				c.state = UNSUB_ARG
   771  				c.as = i
   772  			}
   773  		case UNSUB_ARG:
   774  			switch b {
   775  			case '\r':
   776  				c.drop = 1
   777  			case '\n':
   778  				var arg []byte
   779  				if c.argBuf != nil {
   780  					arg = c.argBuf
   781  					c.argBuf = nil
   782  				} else {
   783  					arg = buf[c.as : i-c.drop]
   784  				}
   785  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
   786  					return err
   787  				}
   788  				var err error
   789  
   790  				switch c.kind {
   791  				case CLIENT:
   792  					if trace {
   793  						c.traceInOp("UNSUB", arg)
   794  					}
   795  					err = c.processUnsub(arg)
   796  				case ROUTER:
   797  					if trace && c.srv != nil {
   798  						switch c.op {
   799  						case 'R', 'r':
   800  							c.traceInOp("RS-", arg)
   801  						case 'L', 'l':
   802  							c.traceInOp("LS-", arg)
   803  						}
   804  					}
   805  					err = c.processRemoteUnsub(arg)
   806  				case GATEWAY:
   807  					if trace {
   808  						c.traceInOp("RS-", arg)
   809  					}
   810  					err = c.processGatewayRUnsub(arg)
   811  				case LEAF:
   812  					if trace {
   813  						c.traceInOp("LS-", arg)
   814  					}
   815  					err = c.processLeafUnsub(arg)
   816  				}
   817  				if err != nil {
   818  					return err
   819  				}
   820  				c.drop, c.as, c.state = 0, i+1, OP_START
   821  			default:
   822  				if c.argBuf != nil {
   823  					c.argBuf = append(c.argBuf, b)
   824  				}
   825  			}
   826  		case OP_PI:
   827  			switch b {
   828  			case 'N', 'n':
   829  				c.state = OP_PIN
   830  			default:
   831  				goto parseErr
   832  			}
   833  		case OP_PIN:
   834  			switch b {
   835  			case 'G', 'g':
   836  				c.state = OP_PING
   837  			default:
   838  				goto parseErr
   839  			}
   840  		case OP_PING:
   841  			switch b {
   842  			case '\n':
   843  				if trace {
   844  					c.traceInOp("PING", nil)
   845  				}
   846  				c.processPing()
   847  				c.drop, c.state = 0, OP_START
   848  			}
   849  		case OP_PO:
   850  			switch b {
   851  			case 'N', 'n':
   852  				c.state = OP_PON
   853  			default:
   854  				goto parseErr
   855  			}
   856  		case OP_PON:
   857  			switch b {
   858  			case 'G', 'g':
   859  				c.state = OP_PONG
   860  			default:
   861  				goto parseErr
   862  			}
   863  		case OP_PONG:
   864  			switch b {
   865  			case '\n':
   866  				if trace {
   867  					c.traceInOp("PONG", nil)
   868  				}
   869  				c.processPong()
   870  				c.drop, c.state = 0, OP_START
   871  			}
   872  		case OP_C:
   873  			switch b {
   874  			case 'O', 'o':
   875  				c.state = OP_CO
   876  			default:
   877  				goto parseErr
   878  			}
   879  		case OP_CO:
   880  			switch b {
   881  			case 'N', 'n':
   882  				c.state = OP_CON
   883  			default:
   884  				goto parseErr
   885  			}
   886  		case OP_CON:
   887  			switch b {
   888  			case 'N', 'n':
   889  				c.state = OP_CONN
   890  			default:
   891  				goto parseErr
   892  			}
   893  		case OP_CONN:
   894  			switch b {
   895  			case 'E', 'e':
   896  				c.state = OP_CONNE
   897  			default:
   898  				goto parseErr
   899  			}
   900  		case OP_CONNE:
   901  			switch b {
   902  			case 'C', 'c':
   903  				c.state = OP_CONNEC
   904  			default:
   905  				goto parseErr
   906  			}
   907  		case OP_CONNEC:
   908  			switch b {
   909  			case 'T', 't':
   910  				c.state = OP_CONNECT
   911  			default:
   912  				goto parseErr
   913  			}
   914  		case OP_CONNECT:
   915  			switch b {
   916  			case ' ', '\t':
   917  				continue
   918  			default:
   919  				c.state = CONNECT_ARG
   920  				c.as = i
   921  			}
   922  		case CONNECT_ARG:
   923  			switch b {
   924  			case '\r':
   925  				c.drop = 1
   926  			case '\n':
   927  				var arg []byte
   928  				if c.argBuf != nil {
   929  					arg = c.argBuf
   930  					c.argBuf = nil
   931  				} else {
   932  					arg = buf[c.as : i-c.drop]
   933  				}
   934  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
   935  					return err
   936  				}
   937  				if trace {
   938  					c.traceInOp("CONNECT", removePassFromTrace(arg))
   939  				}
   940  				if err := c.processConnect(arg); err != nil {
   941  					return err
   942  				}
   943  				c.drop, c.state = 0, OP_START
   944  				// Reset notion on authSet
   945  				c.mu.Lock()
   946  				authSet = c.awaitingAuth()
   947  				c.mu.Unlock()
   948  			default:
   949  				if c.argBuf != nil {
   950  					c.argBuf = append(c.argBuf, b)
   951  				}
   952  			}
   953  		case OP_M:
   954  			switch b {
   955  			case 'S', 's':
   956  				c.state = OP_MS
   957  			default:
   958  				goto parseErr
   959  			}
   960  		case OP_MS:
   961  			switch b {
   962  			case 'G', 'g':
   963  				c.state = OP_MSG
   964  			default:
   965  				goto parseErr
   966  			}
   967  		case OP_MSG:
   968  			switch b {
   969  			case ' ', '\t':
   970  				c.state = OP_MSG_SPC
   971  			default:
   972  				goto parseErr
   973  			}
   974  		case OP_MSG_SPC:
   975  			switch b {
   976  			case ' ', '\t':
   977  				continue
   978  			default:
   979  				c.pa.hdr = -1
   980  				c.state = MSG_ARG
   981  				c.as = i
   982  			}
   983  		case MSG_ARG:
   984  			switch b {
   985  			case '\r':
   986  				c.drop = 1
   987  			case '\n':
   988  				var arg []byte
   989  				if c.argBuf != nil {
   990  					arg = c.argBuf
   991  					c.argBuf = nil
   992  				} else {
   993  					arg = buf[c.as : i-c.drop]
   994  				}
   995  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
   996  					return err
   997  				}
   998  				var err error
   999  				if c.kind == ROUTER || c.kind == GATEWAY {
  1000  					switch c.op {
  1001  					case 'R', 'r':
  1002  						if trace {
  1003  							c.traceInOp("RMSG", arg)
  1004  						}
  1005  						err = c.processRoutedMsgArgs(arg)
  1006  					case 'L', 'l':
  1007  						if trace {
  1008  							c.traceInOp("LMSG", arg)
  1009  						}
  1010  						lmsg = true
  1011  						err = c.processRoutedOriginClusterMsgArgs(arg)
  1012  					}
  1013  				} else if c.kind == LEAF {
  1014  					if trace {
  1015  						c.traceInOp("LMSG", arg)
  1016  					}
  1017  					err = c.processLeafMsgArgs(arg)
  1018  				}
  1019  				if err != nil {
  1020  					return err
  1021  				}
  1022  				c.drop, c.as, c.state = 0, i+1, MSG_PAYLOAD
  1023  
  1024  				// jump ahead with the index. If this overruns
  1025  				// what is left we fall out and process split
  1026  				// buffer.
  1027  				i = c.as + c.pa.size - LEN_CR_LF
  1028  			default:
  1029  				if c.argBuf != nil {
  1030  					c.argBuf = append(c.argBuf, b)
  1031  				}
  1032  			}
  1033  		case OP_I:
  1034  			switch b {
  1035  			case 'N', 'n':
  1036  				c.state = OP_IN
  1037  			default:
  1038  				goto parseErr
  1039  			}
  1040  		case OP_IN:
  1041  			switch b {
  1042  			case 'F', 'f':
  1043  				c.state = OP_INF
  1044  			default:
  1045  				goto parseErr
  1046  			}
  1047  		case OP_INF:
  1048  			switch b {
  1049  			case 'O', 'o':
  1050  				c.state = OP_INFO
  1051  			default:
  1052  				goto parseErr
  1053  			}
  1054  		case OP_INFO:
  1055  			switch b {
  1056  			case ' ', '\t':
  1057  				continue
  1058  			default:
  1059  				c.state = INFO_ARG
  1060  				c.as = i
  1061  			}
  1062  		case INFO_ARG:
  1063  			switch b {
  1064  			case '\r':
  1065  				c.drop = 1
  1066  			case '\n':
  1067  				var arg []byte
  1068  				if c.argBuf != nil {
  1069  					arg = c.argBuf
  1070  					c.argBuf = nil
  1071  				} else {
  1072  					arg = buf[c.as : i-c.drop]
  1073  				}
  1074  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
  1075  					return err
  1076  				}
  1077  				if err := c.processInfo(arg); err != nil {
  1078  					return err
  1079  				}
  1080  				c.drop, c.as, c.state = 0, i+1, OP_START
  1081  			default:
  1082  				if c.argBuf != nil {
  1083  					c.argBuf = append(c.argBuf, b)
  1084  				}
  1085  			}
  1086  		case OP_PLUS:
  1087  			switch b {
  1088  			case 'O', 'o':
  1089  				c.state = OP_PLUS_O
  1090  			default:
  1091  				goto parseErr
  1092  			}
  1093  		case OP_PLUS_O:
  1094  			switch b {
  1095  			case 'K', 'k':
  1096  				c.state = OP_PLUS_OK
  1097  			default:
  1098  				goto parseErr
  1099  			}
  1100  		case OP_PLUS_OK:
  1101  			switch b {
  1102  			case '\n':
  1103  				c.drop, c.state = 0, OP_START
  1104  			}
  1105  		case OP_MINUS:
  1106  			switch b {
  1107  			case 'E', 'e':
  1108  				c.state = OP_MINUS_E
  1109  			default:
  1110  				goto parseErr
  1111  			}
  1112  		case OP_MINUS_E:
  1113  			switch b {
  1114  			case 'R', 'r':
  1115  				c.state = OP_MINUS_ER
  1116  			default:
  1117  				goto parseErr
  1118  			}
  1119  		case OP_MINUS_ER:
  1120  			switch b {
  1121  			case 'R', 'r':
  1122  				c.state = OP_MINUS_ERR
  1123  			default:
  1124  				goto parseErr
  1125  			}
  1126  		case OP_MINUS_ERR:
  1127  			switch b {
  1128  			case ' ', '\t':
  1129  				c.state = OP_MINUS_ERR_SPC
  1130  			default:
  1131  				goto parseErr
  1132  			}
  1133  		case OP_MINUS_ERR_SPC:
  1134  			switch b {
  1135  			case ' ', '\t':
  1136  				continue
  1137  			default:
  1138  				c.state = MINUS_ERR_ARG
  1139  				c.as = i
  1140  			}
  1141  		case MINUS_ERR_ARG:
  1142  			switch b {
  1143  			case '\r':
  1144  				c.drop = 1
  1145  			case '\n':
  1146  				var arg []byte
  1147  				if c.argBuf != nil {
  1148  					arg = c.argBuf
  1149  					c.argBuf = nil
  1150  				} else {
  1151  					arg = buf[c.as : i-c.drop]
  1152  				}
  1153  				if err := c.overMaxControlLineLimit(arg, mcl); err != nil {
  1154  					return err
  1155  				}
  1156  				c.processErr(string(arg))
  1157  				c.drop, c.as, c.state = 0, i+1, OP_START
  1158  			default:
  1159  				if c.argBuf != nil {
  1160  					c.argBuf = append(c.argBuf, b)
  1161  				}
  1162  			}
  1163  		default:
  1164  			goto parseErr
  1165  		}
  1166  	}
  1167  
  1168  	// Check for split buffer scenarios for any ARG state.
  1169  	if c.state == SUB_ARG || c.state == UNSUB_ARG ||
  1170  		c.state == PUB_ARG || c.state == HPUB_ARG ||
  1171  		c.state == ASUB_ARG || c.state == AUSUB_ARG ||
  1172  		c.state == MSG_ARG || c.state == HMSG_ARG ||
  1173  		c.state == MINUS_ERR_ARG || c.state == CONNECT_ARG || c.state == INFO_ARG {
  1174  
  1175  		// Setup a holder buffer to deal with split buffer scenario.
  1176  		if c.argBuf == nil {
  1177  			c.argBuf = c.scratch[:0]
  1178  			c.argBuf = append(c.argBuf, buf[c.as:i-c.drop]...)
  1179  		}
  1180  		// Check for violations of control line length here. Note that this is not
  1181  		// exact at all but the performance hit is too great to be precise, and
  1182  		// catching here should prevent memory exhaustion attacks.
  1183  		if err := c.overMaxControlLineLimit(c.argBuf, mcl); err != nil {
  1184  			return err
  1185  		}
  1186  	}
  1187  
  1188  	// Check for split msg
  1189  	if (c.state == MSG_PAYLOAD || c.state == MSG_END_R || c.state == MSG_END_N) && c.msgBuf == nil {
  1190  		// We need to clone the pubArg if it is still referencing the
  1191  		// read buffer and we are not able to process the msg.
  1192  
  1193  		if c.argBuf == nil {
  1194  			// Works also for MSG_ARG, when message comes from ROUTE or GATEWAY.
  1195  			if err := c.clonePubArg(lmsg); err != nil {
  1196  				goto parseErr
  1197  			}
  1198  		}
  1199  
  1200  		// If we will overflow the scratch buffer, just create a
  1201  		// new buffer to hold the split message.
  1202  		if c.pa.size > cap(c.scratch)-len(c.argBuf) {
  1203  			lrem := len(buf[c.as:])
  1204  			// Consider it a protocol error when the remaining payload
  1205  			// is larger than the reported size for PUB. It can happen
  1206  			// when processing incomplete messages from rogue clients.
  1207  			if lrem > c.pa.size+LEN_CR_LF {
  1208  				goto parseErr
  1209  			}
  1210  			c.msgBuf = make([]byte, lrem, c.pa.size+LEN_CR_LF)
  1211  			copy(c.msgBuf, buf[c.as:])
  1212  		} else {
  1213  			c.msgBuf = c.scratch[len(c.argBuf):len(c.argBuf)]
  1214  			c.msgBuf = append(c.msgBuf, (buf[c.as:])...)
  1215  		}
  1216  	}
  1217  
  1218  	return nil
  1219  
  1220  authErr:
  1221  	c.authViolation()
  1222  	return ErrAuthentication
  1223  
  1224  parseErr:
  1225  	c.sendErr("Unknown Protocol Operation")
  1226  	snip := protoSnippet(i, PROTO_SNIPPET_SIZE, buf)
  1227  	err := fmt.Errorf("%s parser ERROR, state=%d, i=%d: proto='%s...'", c.kindString(), c.state, i, snip)
  1228  	return err
  1229  }
  1230  
  1231  func protoSnippet(start, max int, buf []byte) string {
  1232  	stop := start + max
  1233  	bufSize := len(buf)
  1234  	if start >= bufSize {
  1235  		return `""`
  1236  	}
  1237  	if stop > bufSize {
  1238  		stop = bufSize - 1
  1239  	}
  1240  	return fmt.Sprintf("%q", buf[start:stop])
  1241  }
  1242  
  1243  // Check if the length of buffer `arg` is over the max control line limit `mcl`.
  1244  // If so, an error is sent to the client and the connection is closed.
  1245  // The error ErrMaxControlLine is returned.
  1246  func (c *client) overMaxControlLineLimit(arg []byte, mcl int32) error {
  1247  	if c.kind != CLIENT {
  1248  		return nil
  1249  	}
  1250  	if len(arg) > int(mcl) {
  1251  		err := NewErrorCtx(ErrMaxControlLine, "State %d, max_control_line %d, Buffer len %d (snip: %s...)",
  1252  			c.state, int(mcl), len(c.argBuf), protoSnippet(0, MAX_CONTROL_LINE_SNIPPET_SIZE, arg))
  1253  		c.sendErr(err.Error())
  1254  		c.closeConnection(MaxControlLineExceeded)
  1255  		return err
  1256  	}
  1257  	return nil
  1258  }
  1259  
  1260  // clonePubArg is used when the split buffer scenario has the pubArg in the existing read buffer, but
  1261  // we need to hold onto it into the next read.
  1262  func (c *client) clonePubArg(lmsg bool) error {
  1263  	// Just copy and re-process original arg buffer.
  1264  	c.argBuf = c.scratch[:0]
  1265  	c.argBuf = append(c.argBuf, c.pa.arg...)
  1266  
  1267  	switch c.kind {
  1268  	case ROUTER, GATEWAY:
  1269  		if lmsg {
  1270  			return c.processRoutedOriginClusterMsgArgs(c.argBuf)
  1271  		}
  1272  		if c.pa.hdr < 0 {
  1273  			return c.processRoutedMsgArgs(c.argBuf)
  1274  		} else {
  1275  			return c.processRoutedHeaderMsgArgs(c.argBuf)
  1276  		}
  1277  	case LEAF:
  1278  		if c.pa.hdr < 0 {
  1279  			return c.processLeafMsgArgs(c.argBuf)
  1280  		} else {
  1281  			return c.processLeafHeaderMsgArgs(c.argBuf)
  1282  		}
  1283  	default:
  1284  		if c.pa.hdr < 0 {
  1285  			return c.processPub(c.argBuf)
  1286  		} else {
  1287  			return c.processHeaderPub(c.argBuf, nil)
  1288  		}
  1289  	}
  1290  }
  1291  
  1292  func (ps *parseState) getHeader() http.Header {
  1293  	if ps.header == nil {
  1294  		if hdr := ps.pa.hdr; hdr > 0 {
  1295  			reader := bufio.NewReader(bytes.NewReader(ps.msgBuf[0:hdr]))
  1296  			tp := textproto.NewReader(reader)
  1297  			tp.ReadLine() // skip over first line, contains version
  1298  			if mimeHeader, err := tp.ReadMIMEHeader(); err == nil {
  1299  				ps.header = http.Header(mimeHeader)
  1300  			}
  1301  		}
  1302  	}
  1303  	return ps.header
  1304  }