Next: , Previous: Files, Up: Values



3.15 Functions

You declare a Bro function type using:

function( argument* ) : type
where argument is a (possibly empty) comma-separated list of arguments, and the final “: type” declares the return type of the function. It is optional; if missing, then the function does not return a value.

Each argument is declared using:

param-name : type

So, for example:

         function(a: addr, p: port): string

corresponds to a function that takes two parameters, a of type addr and p of type port, and returns a value of type string.

You could furthermore declare:

         global generate_id: function(a: addr, p: port): string;

to define generate_id as a variable of this type. Note that the declaration does not define the body of the function, and, indeed, generate_id could have different function bodies at different times, by assigning different function values to it.

When defining a function including its body, the syntax is slightly different:

     function func-name ( argument* ) [ : type ] { statement* }

That is, you introduce func-name, the name of the function, between the keywork function and the opening parenthesis of the argument list, and you list the statements of the function within braces at the end.

For the previous example, we could define its body using:

         function generate_id(a: addr, p: port): string
             {
             if ( a in local_servers )
                 # Ignore port, they're always the same.
                 return fmt("server %s", a);
     
             if ( p < 1024/tcp )
                 # Privileged port, flag it.
                 return fmt("%s/priv-%s", a, p);
     
             # Nothing special - default formatting.
             return fmt("%s/%s", a, p);
             }

We also could have omitted the first definition; a function definition like the one immediately above automatically defines generate_id as a function of type function(a: addr, p: port): string. Note though that if func-name was indeed already declared, then the argument list much match exactly that of the previous definition. This includes the names of the arguments; Unlike in C, you cannot change the argument names between their first (forward) definition and the full definition of the function.

You can also define functions without using any name. These are referred to as are a type of expression.

You can only do two things with functions: or assign them. As an example of the latter, suppose we have:

         local id_funcs: table[conn_id] of function(p: port, a: addr): string;

would declare a local variable indexed by a

same type as in the previous example. You could then execute:

         id_funcs[c$id] = generate_id

or call whatever function is associated with a given conn_id:

         print fmt("id is: %s", id_funcs[c$id](80/tcp, 1.2.3.4));