Exemplo n.º 1
0
void
__bro_io_msg_queue_dump(BroConn *bc, const char *message)
{
  BroMsg *msg;
  
  printf("%s: connection %p, length %i\n", message, bc, bc->msg_queue_len);
  
  for (msg = bc->msg_queue.tqh_first; msg; msg = msg->msg_queue.tqe_next)
    printf(" -- %s(%i)\n", msg_type_2_str(msg->msg_header.hdr_type), msg->msg_num);
}
Exemplo n.º 2
0
static int      
io_msg_fill_tx(BroConn *bc, BroMsg *msg)
{
  int result = TRUE;

  D_ENTER;

  if (!bc || !msg)
    {
      D(("Input error.\n"));
      D_RETURN_(FALSE);
    }

  /* Check if anything is still left in the input buffer. In that case,
   * we don't fill anything in but return right away, so the message
   * gets queued.
   */
  if (__bro_buf_get_used_size(bc->tx_buf) > 0)
    {
      D(("Buffer not empty; not filling!\n"));
      D_RETURN_(FALSE);
    }
  
  D((">>> Attempting write of %s\n", msg_type_2_str(msg->msg_header.hdr_type)));

  /* We will collect the message chunk in the connection's tx buffer.
   * We append stuff to it as we go along and at the end write it out.
   * When being sent, he buffer has the amount of octets to send at
   * the beginning, so the reader knows how much is coming.
   */
  __bro_buf_reset(bc->tx_buf);

  msg->msg_header_size = sizeof(BroMsgHeader);
  
  if (! __bro_buf_write_int(bc->tx_buf, msg->msg_header_size))
    {
      __bro_buf_reset(bc->tx_buf);
      D_RETURN_(FALSE);
    }
  
  /* Hook in the Bro message header */
  if (! io_fill_msg_header(bc->tx_buf, &msg->msg_header))
    {
      __bro_buf_reset(bc->tx_buf);
      D_RETURN_(FALSE);
    }
  
  if (msg->msg_cont_type != BRO_MSG_CONT_NONE)
    {
      uint32 msg_size_pos, msg_size_end;

      /* This starts another chunk of data (in Bro protocol speak),
       * but here we cannot yet know how big the chunk will be.
       * We save the offset in the buffer and return to it later,
       * overwriting the value with the then correct one.
       */
      msg_size_pos = __bro_buf_get_used_size(bc->tx_buf);
      if (! __bro_buf_write_int(bc->tx_buf, msg->msg_size))
	{
	  __bro_buf_reset(bc->tx_buf);
	  D_RETURN_(FALSE);
	}
      
      /* Gather the payload of the message we are about
       * to send into the buffer BUF.
       */
      switch (msg->msg_cont_type)
	{
	case BRO_MSG_CONT_RAW:
	  D(("Filling raw data into buffer\n"));
	  if (! io_fill_raw(bc->tx_buf, msg->msg_cont_raw))
	    {
	      __bro_buf_reset(bc->tx_buf);
	      D_RETURN_(FALSE);
	    }
	  break;
	  
	case BRO_MSG_CONT_EVENT:
	  /* Check if the peer actually requested the event, and if not,
	   * drop it silently (i.e., still return success).
	   */
	  if (! __bro_ht_get(bc->ev_mask, msg->msg_cont_ev->name.str_val))
	    {
	      D(("Event '%s' not requested by peer -- dropping.\n",
		 msg->msg_cont_ev->name.str_val));
	      __bro_buf_reset(bc->tx_buf);

	      /* This is not an error but a silent drop, so we
	       * return success.
	       */
	      D_RETURN_(TRUE);
	    }
	  
	  D(("Filling event into buffer\n"));
	  
	  if (! __bro_event_serialize(msg->msg_cont_ev, bc))
	    {
	      D(("Error during serialization.\n"));
	      __bro_buf_reset(bc->tx_buf);
	      D_RETURN_(FALSE);	
	    }
	  break;
	  
	case BRO_MSG_CONT_REQUEST:
	  D(("Filling request into buffer\n"));
	  if (! io_fill_request(bc->tx_buf, msg->msg_cont_req))
	    {
	      __bro_buf_reset(bc->tx_buf);
	      D_RETURN_(FALSE);	
	    }
	  break;

#ifdef BRO_PCAP_SUPPORT	  
	case BRO_MSG_CONT_PACKET:
	  if (! __bro_packet_serialize(msg->msg_cont_packet, bc))
	    {
	      __bro_buf_reset(bc->tx_buf);	      
	      D_RETURN_(FALSE);
	    }
	  break;
#endif
	default:
	  D(("ERROR -- invalid message content code %i\n", msg->msg_cont_type));
	  break;
	}
      
      /* Now calculate length of entire transmission --
       * we know where we wrote the uint32 containing the
       * size of the chunk, and we know where we are now,
       * so the length is their difference, minus the uint32
       * itself.
       */
      msg_size_end = __bro_buf_get_used_size(bc->tx_buf);
      msg->msg_size = msg_size_end - msg_size_pos - sizeof(uint32);
      D(("Serialized message sized %i bytes.\n", msg->msg_size));
      
      if (! __bro_buf_ptr_seek(bc->tx_buf, msg_size_pos, SEEK_SET))
	{
	  D(("Cannot seek to position %u -- we're screwed.\n", msg_size_pos));
	  __bro_buf_reset(bc->tx_buf);
	  D_RETURN_(FALSE);
	}
      
      if (! __bro_buf_write_int(bc->tx_buf, msg->msg_size))
	{
	  __bro_buf_reset(bc->tx_buf);
	  D_RETURN_(FALSE);
	}
    }
  
  D_RETURN_(result);
}
Exemplo n.º 3
0
static int
io_msg_queue(BroConn *bc, BroMsg *msg)
{
  D_ENTER;

  if (!bc || !msg)
    D_RETURN_(FALSE);

  /* If anything is left over in the buffer, write it out now.
   * We don't care if it succeeds or not.
   */
  io_msg_empty_tx(bc);

  /* If the queue is empty, try to send right away.
   * If not, enqueue the event, and try to flush.
   */
  D(("Enqueing msg of type %s\n", msg_type_2_str(msg->msg_header.hdr_type)));

  if (! bc->msg_queue.tqh_first)
    {
      D(("No queue yet.\n"));
      if (io_msg_fill_tx(bc, msg))
	{
	  D(("Message serialized.\n"));

	  if (io_msg_empty_tx(bc))
	    {
	      D(("Message sent.\n"));
	    }

	  __bro_io_msg_free(msg);
	  bc->state->io_msg = BRO_IOMSG_WRITE;
	  D_RETURN_(TRUE);
	}
    }
  
  if (bc->state->tx_dead && ! (bc->conn_flags & BRO_CFLAG_ALWAYS_QUEUE))
    {
      D(("Connection %p disconnected, and no queuing requested: dropping message.\n", bc));
      __bro_io_msg_free(msg);
      D_RETURN_(FALSE);
    }

  TAILQ_INSERT_TAIL(&bc->msg_queue, msg, msg_queue);
  bc->msg_queue_len++;
  D(("Queue length now %i\n", bc->msg_queue_len));
  
  __bro_io_msg_queue_flush(bc);

  /* Check that the queue does not grow too big: */
  while (bc->msg_queue_len > BRO_MSG_QUEUELEN_MAX)
    {
      BroMsg *msg = bc->msg_queue.tqh_first;

      TAILQ_REMOVE(&bc->msg_queue, msg, msg_queue);
      __bro_io_msg_free(msg);
      bc->msg_queue_len--;
      
      D(("Dropped one message due to excess queue length, now %i\n", bc->msg_queue_len));
    }
  
  D_RETURN_(TRUE);
}
Exemplo n.º 4
0
char const *rpc_info_2_str(struct proto_info const *info_)
{
    struct rpc_proto_info const *info = DOWNCAST(info_, info, rpc_proto_info);
    return tempstr_printf("type: %s, %s", msg_type_2_str(info->msg_type),
                          info->msg_type == RPC_CALL ? call_msg_2_str(&info->u.call_msg) : reply_msg_2_str(&info->u.reply_msg) );
}