Click or drag to resize
BroccoliSharp BroRecord Class
Represents a Bro record implemented as an IList<BroField>.
Inheritance Hierarchy
SystemObject
  BroccoliSharpBroRecord

Namespace: BroccoliSharp
Assembly: BroccoliSharp (in BroccoliSharp.dll) Version: 1.0.5434.15853
Syntax
public class BroRecord : IList<BroField>, 
	ICollection<BroField>, IEnumerable<BroField>, IEnumerable, 
	IDisposable

The BroRecord type exposes the following members.

Constructors
Methods
  NameDescription
Public methodAdd(BroField)
Adds field to this BroRecord.
Public methodAdd(BroValue, String)
Adds new value to this BroRecord with specified fieldName.
Public methodAdd(String, BroType, String)
Adds a new column, with no initial value, to this BroRecord with the specified fieldName and type.
Public methodAdd(Object, BroType, String, String)
Adds new value of type to this BroRecord with specified fieldName.
Public methodClear
Removes all fields from this BroRecord.
Public methodClone
Gets a clone of this BroRecord.
Public methodContains(String)
Determines whether this BroRecord contains the specified fieldName.
Public methodContains(BroField)
Determines whether this BroRecord contains the specified field.
Public methodCopyTo
Copies the fields of this BroRecord to an Array, starting at a particular Array index.
Public methodDispose
Releases all the resources used by this BroRecord object.
Protected methodDispose(Boolean)
Releases the unmanaged resources used by this BroRecord object and optionally releases the managed resources.
Public methodEquals
Determines whether the specified Object is equal to the current Object.
(Inherited from Object.)
Protected methodFinalize
Releases the unmanaged resources before this BroRecord object is reclaimed by GC.
(Overrides ObjectFinalize.)
Public methodGetEnumerator
Returns an enumerator that iterates through the field collection.
Public methodGetHashCode
Serves as a hash function for a particular type.
(Inherited from Object.)
Public methodGetType
Gets the Type of the current instance.
(Inherited from Object.)
Public methodIndexOf(String)
Determines the index of the specified fieldName in this BroRecord.
Public methodIndexOf(BroField)
Determines the index of the specified field in this BroRecord.
Public methodInsert(Int32, BroField)
Inserts field in this BroRecord at the specified index.
Public methodInsert(Int32, BroValue, String)
Inserts value in this BroRecord at the specified index with specified fieldName.
Public methodInsert(Int32, Object, BroType, String, String)
Inserts value of type in this BroRecord at the specified index with specified fieldName.
Protected methodMemberwiseClone
Creates a shallow copy of the current Object.
(Inherited from Object.)
Public methodRemove(String)
Removes the first occurrence of the specified fieldName from this BroRecord.
Public methodRemove(BroField)
Removes the first occurrence of the specified field from this BroRecord.
Public methodRemoveAt
Removes the BroField item at the specified index.
Public methodToString
Returns a string that represents this BroRecord.
(Overrides ObjectToString.)
Top
Properties
  NameDescription
Public propertyCount
Gets the number of fields contained in this BroRecord.
Public propertyIsReadOnly
Gets a value indicating whether this BroRecord is read-only.
Public propertyItemInt32
Gets or sets the BroField at the specified index.
Public propertyItemString
Gets or sets the BroValue for the specified field name.
Top
Remarks

Handling Records

BroccoliSharp supports record structures, i.e., types that pack a set of values together, placing each value into its own field. In BroccoliSharp, the way you handle records is somewhat similar to events: after creating an empty record (of type BroRecord), you can iteratively add fields and values to it. The main difference is that you must specify a field name with the value; each value in a record can be identified both by position (a numerical index starting from zero), and by field name. You can retrieve values in a record by field index or field name. You can also reassign values. There is no explicit, IDL-style definition of record types. You define the type of a record implicitly by the sequence of field names and the sequence of the types of the values you put into the record.

Note that all fields in a record must be assigned before it can be shipped.

The functionality of a BroRecord is virtually identical to that of a .NET ListT with a type implementation of a BroField. The BroField class is simply a BroValue that also contains a field name for the record.

Keep in mind that a BroRecord field value may also contain another nested BroRecord.

Examples

The BroRecord has two indexer properties. One will access BroField values by index and the other by field name:

C#
BroRecord record = new BroRecord();
BroVector list = new BroVector();

for (int i = 0; i < 10; i++)
  list.Add(i, BroType.Int);

record.Add(list.Count, BroType.Int, "listCount");
record.Add(list, "list");
record.Add("bro.myorg.com", BroType.IpAddr, "ipAddress");
record.Add("MyEvent Text String", "textString");
record.Add(2, BroType.Enum, "enumCol", "transport_proto");
record.Add(false, "booleanCol");

// Get first item by index
BroValue firstItem = record[0];

// Get column named "enumCol"
BroValue enumCol = record["enumCol"];

This example shows a record based "ping" working with the broping-record.bro script:

C#
using System;
using System.Threading;
using BroccoliSharp;

namespace BroPingRecord
{
    class Program
    {
        static int Main(string[] args)
        {
            if (args.Length != 1)
            {
                Console.WriteLine("Usage:");
                Console.WriteLine("    BroPingRecord host:port");
                return 1;
            }

            try
            {
                string hostName = args[0];

                Console.WriteLine("Attempting to establish Bro connection to \"{0}\"...", hostName);

                // Create the connection object
                using (BroConnection connection = new BroConnection(hostName))
                {
                    // Register to receive the pong event
                    connection.RegisterForEvent("pong", e =>
                    {
                        BroRecord pongData = e.Parameters[0];
                        DateTime src_time = pongData["src_time"];
                        DateTime dst_time = pongData["dst_time"];

                        Console.WriteLine("pong event from {0}: seq={1}, time={2}/{3} s",
                            hostName,
                            pongData["seq"],
                            (dst_time - src_time).TotalSeconds,
                            (BroTime.Now - src_time).TotalSeconds);
                    });

                    connection.Connect();

                    Console.WriteLine("Bro connection established. Starting ping cycle, press any key to cancel...");

                    using (BroRecord pingData = new BroRecord())
                    {
                        int seq = 0;

                        // Define columns without any initial value
                        pingData.Add("seq", BroType.Count);
                        pingData.Add("src_time", BroType.Time);

                        while (!Console.KeyAvailable)
                        {
                            // Update ping record parameters
                            pingData["seq"] = new BroValue(seq++, BroType.Count);
                            pingData["src_time"] = BroTime.Now;

                            // Send ping
                            connection.SendEvent("ping", pingData);

                            // Process any received responses
                            connection.ProcessInput();

                            // Wait one second between pings
                            Thread.Sleep(1000);
                        }
                    }
                }

                return 0;
            }
            catch (Exception ex)
            {
                Console.Write("Exception: {0}{1}", ex.Message, Environment.NewLine);
                return 1;
            }
        }
    }
}

Thread Safety
Implementation of BroRecord is not synchronized, as a result, enumerating through the record will intrinsically not be a thread-safe procedure. In cases where enumeration contends with write accesses, record should be locked during the entire enumeration. To allow the record to be accessed by multiple threads for reading and writing, synchronization will be required.
See Also