func (c *Conn) startReceive() {
	recvCounter.Add(1)
	defer func() {
		c.Close()
		c.disconnHandler(c)
		recvCounter.Add(-1)
	}()

	for {
		var m message
		err := c.receive(&m)
		if err != nil {
			// if we closed the connection
			if !c.connected.Load().(bool) {
				log.Printf("conn: closed %v: %v", c.ID, c.RemoteAddr())
				break
			}

			// if peer closed the connection
			if err == io.EOF {
				log.Printf("conn: peer disconnected %v: %v", c.ID, c.RemoteAddr())
				break
			}

			log.Printf("conn: error while receiving message: %v", err)
			break
		}

		// if the message is a request
		if m.Method != "" {
			reqCounter.Add(1)
			c.wg.Add(1)
			go func() {
				defer reqCounter.Add(-1)
				defer recoverAndLog(c, &c.wg)
				ctx := newReqCtx(c, m.ID, m.Method, m.Params, c.middleware)
				if err := ctx.Next(); err != nil {
					log.Printf("ctx: request middleware returned error: %v", err)
					c.Close()
				}
				if ctx.Res != nil || ctx.Err != nil {
					if err := ctx.Conn.sendResponse(ctx.ID, ctx.Res, ctx.Err); err != nil {
						log.Printf("ctx: error sending response: %v", err)
						c.Close()
					}
				}
			}()

			continue
		}

		// if the message is not a JSON-RPC message
		if m.ID == "" || (m.Result == nil && m.Error == nil) {
			log.Printf("conn: received an unknown message %v: %v, %v", c.ID, c.RemoteAddr(), m)
			break
		}

		// if the message is a response
		if resHandler, ok := c.resRoutes.GetOk(m.ID); ok {
			resCounter.Add(1)
			c.wg.Add(1)
			go func() {
				defer resCounter.Add(-1)
				defer recoverAndLog(c, &c.wg)
				err := resHandler.(func(ctx *ResCtx) error)(newResCtx(c, m.ID, m.Result, m.Error))
				c.resRoutes.Delete(m.ID)
				if err != nil {
					log.Printf("conn: error while handling response: %v", err)
					c.Close()
				}
			}()
		} else {
			log.Printf("conn: error while handling response: got response to a request with unknown ID: %v", m.ID)
			break
		}
	}
}
func (c *Conn) startReceive() {
	recvCounter.Add(1)
	defer func() {
		c.Close()
		c.disconnHandler(c)
		recvCounter.Add(-1)
	}()

	for {
		var m message
		err := c.receive(&m)
		if err != nil {
			// if we closed the connection
			if !c.connected.Load().(bool) {
				log.Printf("conn: closed %v: %v", c.ID, c.RemoteAddr())
				break
			}

			// if peer closed the connection
			if err == io.EOF {
				log.Printf("conn: peer disconnected %v: %v", c.ID, c.RemoteAddr())
				break
			}

			log.Printf("conn: error while receiving message: %v", err)
			break
		}

		// if the message is a request
		if m.Method != "" {
			reqCounter.Add(1)
			c.wg.Add(1)
			go func() {
				defer reqCounter.Add(-1)
				defer recoverAndLog(c, &c.wg)
				ctx := newReqCtx(c, m.ID, m.Method, m.Params, c.middleware)
				if err := ctx.Next(); err != nil {
					log.Printf("ctx: request middleware returned error: %v", err)
					c.Close()
				}
				if ctx.Res != nil || ctx.Err != nil {
					if err := ctx.Conn.sendResponse(ctx.ID, ctx.Res, ctx.Err); err != nil {
						log.Printf("ctx: error sending response: %v", err)
						c.Close()
					}
				}
			}()

			continue
		}

		// if the message is not a JSON-RPC message
		if m.ID == "" || (m.Result == nil && m.Error == nil) {
			log.Printf("conn: received an unknown message %v: %v, %v", c.ID, c.RemoteAddr(), m)
			break
		}

		// if the message is a response
		if resHandler, ok := c.resRoutes.GetOk(m.ID); ok {
			resCounter.Add(1)
			c.wg.Add(1)
			go func() {
				defer resCounter.Add(-1)
				defer recoverAndLog(c, &c.wg)
				err := resHandler.(func(ctx *ResCtx) error)(newResCtx(c, m.ID, m.Result, m.Error))
				c.resRoutes.Delete(m.ID)
				if err != nil {
					log.Printf("conn: error while handling response: %v", err)
					c.Close()
				}
			}()
		} else {
			log.Printf("conn: error while handling response: got response to a request with unknown ID: %v", m.ID)
			break
		}
	}
}
// startReceive starts receiving messages. This method blocks and does not return until the connection is closed.