Net-Nmsg/lib/Net/Nmsg/Output.pm
# Use of the Net-Silk library and related source code is subject to the
# terms of the following licenses:
#
# GNU Public License (GPL) Rights pursuant to Version 2, June 1991
# Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013
#
# NO WARRANTY
#
# ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER
# PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY
# PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN
# "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
# KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT
# LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE,
# MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE
# OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT,
# SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY
# TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF
# WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES.
# LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF
# CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON
# CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE
# DELIVERABLES UNDER THIS LICENSE.
#
# Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie
# Mellon University, its trustees, officers, employees, and agents from
# all claims or demands made against them (and any related losses,
# expenses, or attorney's fees) arising out of, or relating to Licensee's
# and/or its sub licensees' negligent use or willful misuse of or
# negligent conduct or willful misconduct regarding the Software,
# facilities, or other rights or assistance granted by Carnegie Mellon
# University under this License, including, but not limited to, any
# claims of product liability, personal injury, death, damage to
# property, or violation of any laws or regulations.
#
# Carnegie Mellon University Software Engineering Institute authored
# documents are sponsored by the U.S. Department of Defense under
# Contract FA8721-05-C-0003. Carnegie Mellon University retains
# copyrights in all material produced under this contract. The U.S.
# Government retains a non-exclusive, royalty-free license to publish or
# reproduce these documents, or allow others to do so, for U.S.
# Government purposes only pursuant to the copyright license under the
# contract clause at 252.227.7013.
package Net::Nmsg::Output;
use strict;
use warnings;
use Carp;
use base qw( Net::Nmsg::Layer );
use Net::Nmsg::Util qw( :io :buffer :vendor );
use Net::Nmsg::Msg;
use Net::Nmsg::Handle;
use constant HANDLE_IO => 'Net::Nmsg::Handle';
use constant OUTPUT_XS => 'Net::Nmsg::XS::output';
use constant RATE_XS => 'Net::Nmsg::XS::rate';
my %Defaults = (
# common
filter_vendor => undef,
filter_msgtype => undef,
# nmsg
source => undef,
operator => undef,
group => undef,
# nmsg/stream
buffered => 1,
zlibout => 0,
rate => NMSG_DEFAULT_SO_RATE,
freq => NMSG_DEFAULT_SO_FREQ,
bufsz => undef, # depends on stream/socket
# socket
broadcast => 0,
sndbuf => NMSG_DEFAULT_SO_SNDBUF,
# pres
endline => $/,
);
sub _defaults { \%Defaults }
sub get_filter_msgtype { shift->_get_xs_opt(filter_msgtype => @_) }
sub get_operator { shift->_get_xs_opt(operator => @_) }
sub get_source { shift->_get_xs_opt(source => @_) }
sub get_group { shift->_get_xs_opt(group => @_) }
sub get_buffered { shift->_get_xs_opt(buffered => @_) }
sub get_zlibout { shift->_get_xs_opt(zlibout => @_) }
sub get_endline { shift->_get_xs_opt(endline => @_) }
sub set_filter_msgtype { shift->_set_xs_opt(filter_msgtype => @_) }
sub set_operator { shift->_set_xs_opt(operator => @_) }
sub set_source { shift->_set_xs_opt(source => @_) }
sub set_group { shift->_set_xs_opt(group => @_) }
sub set_buffered { shift->_set_xs_opt(buffered => @_) }
sub set_zlibout { shift->_set_xs_opt(zlibout => @_) }
sub set_endline { shift->_set_xs_opt(endline => @_) }
sub get_rate {
my $self = shift;
my $r = $self->_get_xs_opt(rate => @_);
my($rate, $freq) = ($r->[0], $r->[1]);
wantarray ? ($rate, $freq) : [$rate, $freq];
}
sub set_rate {
my $self = shift;
my($rate, $freq);
if (@_ == 1 && ref $_[0]) {
($rate, $freq) = @{$_[0]};
}
else {
($rate, $freq) = @_;
}
$self->_set_xs_opt(rate => [$rate, $freq, RATE_XS->init($rate, $freq)])
}
###
sub is_file { (shift->_xs || return)->is_file }
sub is_json { (shift->_xs || return)->is_json }
sub is_sock { (shift->_xs || return)->is_sock }
sub is_pres { (shift->_xs || return)->is_pres }
sub is_cb { (shift->_xs || return)->is_cb }
###
sub _map_opts {
my $self = shift;
my %opt = @_;
my $rate = delete $opt{rate};
my $freq = delete $opt{freq};
$opt{rate} = [$rate, $freq];
my $vendor = delete $opt{filter_vendor};
my $msgtype = delete $opt{filter_msgtype};
if (defined $vendor || defined $msgtype) {
$self->error("vendor and msgtype required")
unless defined $vendor && defined $msgtype;
$opt{filter_msgtype} = [$vendor, $msgtype];
}
%opt;
}
sub _init_output {
my $self = shift;
my($spec, $io, $xs, %opt) = @_;
*$self->{_spec} = $spec;
*$self->{_io} = $io;
*$self->{_xs} = $xs;
$self->_dup_io_w;
$self->_init_opts(%opt);
$self;
}
sub open {
my $self = shift;
my $spec = shift;
if (@_ % 2 && $_[0] =~ /^\d+$/) {
$spec = join('/', $spec, shift);
}
($self, $spec, my($fatal, %opt)) = $self->_open_init($spec, @_);
if (Net::Nmsg::Util::is_callback($spec)) {
return $self->open_cb($spec, %opt)
|| ($fatal ? croak $self->error : return);
}
elsif (Net::Nmsg::Util::looks_like_socket($spec)) {
return $self->open_sock($spec, %opt)
|| ($fatal ? croak $self->error : return);
}
else {
return $self->open_file($spec, %opt)
|| ($fatal ? croak $self->error : return);
}
}
sub open_file {
my($self, $spec, $fatal, %opt) = shift->_open_init(@_);
$opt{bufsz} = NMSG_WBUFSZ_MAX unless defined $opt{bufsz};
my $io;
eval { $io = $self->HANDLE_IO->open_output_file($spec, %opt) };
$@ && $self->error($@) && ($fatal ? croak $self->error : return);
my $xs;
eval { $xs = $self->OUTPUT_XS->open_file($io, $opt{bufsz}) };
$@ && $self->error($@) && ($fatal ? croak $self->error : return);
$self->_init_output($spec, $io, $xs, %opt);
}
sub open_json {
my($self, $spec, $fatal, %opt) = shift->_open_init(@_);
my $io;
eval { $io = $self->HANDLE_IO->open_output_file($spec, %opt) };
$@ && $self->error($@) && ($fatal ? croak $self->error : return);
my $xs;
eval { $xs = $self->OUTPUT_XS->open_json($io) };
$@ && $self->error($@) && ($fatal ? croak $self->error : return);
$self->_init_output($spec, $io, $xs, %opt);
}
sub open_sock {
my $self = shift;
my $spec = @_ % 2 ? shift : join('/', splice(@_, 0, 2));
($self, $spec, my($fatal, %opt)) = $self->_open_init($spec, @_);
$opt{bufsz} = NMSG_WBUFSZ_ETHER unless defined $opt{bufsz};
my $io;
eval { $io = $self->HANDLE_IO->open_output_sock($spec, %opt) };
$@ && $self->error($@) && ($fatal ? croak $self->error : return);
my $xs;
eval { $xs = $self->OUTPUT_XS->open_sock($io, $opt{bufsz}) };
$@ && $self->error($@) && ($fatal ? croak $self->error : return);
$self->_init_output($spec, $io, $xs, %opt);
}
sub open_pres {
my($self, $spec, $fatal, %opt) = shift->_open_init(@_);
my $io;
eval { $io = $self->HANDLE_IO->open_output_file($spec, %opt) };
$@ && $self->error($@) && ($fatal ? croak $self->error : return);
my $xs;
eval { $xs = $self->OUTPUT_XS->open_pres($io) };
$@ && $self->error($@) && ($fatal ? croak $self->error : return);
$self->_init_output($spec, $io, $xs, %opt);
}
sub open_cb {
my($self, $cb, $fatal, %opt) = shift->_open_init(@_);
my $io;
eval { $io = $self->HANDLE_IO->open_output_cb($cb, %opt) };
$@ && $self->error($@) && ($fatal ? croak $self->error : return);
my $xs;
eval { $xs = $self->OUTPUT_XS->open_callback($cb) };
$@ && $self->error($@) && ($fatal ? croak $self->error : return);
$self->_init_output($cb, $io, $xs, %opt);
}
### perl IO
sub write {
push(@_, $_) if @_ == 1 && defined $_;
eval {
(shift->_xs || croak "attempted write on closed output")->write(@_);
};
croak $@ if $@;
}
###
1;
__END__
=head1 NAME
Net::Nmsg::Output - Perl interface for nmsg outputs
=head1 SYNOPSIS
use Net::Nmsg::Input;
use Net::Nmsg::Output;
my $in = Net::Nmsg::Input->open('input.nmsg');
my $out = Net::Nmsg::Output->open('output.nmsg');
my $c = 0;
while (my $msg = <$in>) {
print "got message $c $msg\n";
$out->write($msg);
++$c;
}
# alternatively:
my $cb = sub {
print "got message $c ", shift, "\n"
$out->write($msg);
++$c;
};
$in->loop($cb);
=head1 DESCRIPTION
Net::Nmsg::Output provides the perl interface for the
Net::Nmsg::XS::output extension.
=head1 CONSTRUCTORS
=over
=item open($spec, %options)
Creates and opens new output object. The output can be specified as a
file name or handle, callback reference, or socket.
Options, where applicable, also apply to the more specific
open calls detailed further below. Available options:
=over
=item filter_vendor
=item filter_msgtype
Restricts the output to messages of the given vendor and msgtype. Both
are required if filtering is desired.
=item source
=item operator
=item group
Set the source, operator, and group fields on outputs (nmsg only)
=item buffered_io
Control whether or not the output socket is buffered (default: 1).
=item zlibout
Enable or disable zlib compression of output (nmsg only)
=item rate
=item freq
Limit the payload output rate
=item bufsz
Set the buffer size for the output (the default value is based on
whether the output is a file or socket)
=item broadcast
Set broadcast mode (socket only)
=item sndbuf
Set send buffer size (socket only)
=item endline
Set the line ending character for presentation outputs.
=back
=item open_file($spec, %options)
Opens an output in nmsg format, as specified by file name or file handle.
=item open_json($spec, %options)
Opens an output in JSON format, as specified by file name or file handle.
=item open_sock($spec, %options)
Opens an output socket as specified by "host/port" or socket handle.
The host and port can also be provided as separate arguments.
=item open_pres($spec, %options)
Opens an output in presentation format, as specified by file name
or file handle. The 'filter_vendor' and 'filter_msgtype' options
are required.
=item open_cb($callback)
Opens a callback output using the provided code reference. The callback
will be invoked with a Net::Nmsg::Msg reference each time a message is
'written' to the output.
=back
=head2 ACCESSORS
=over
=item set_msgtype($vendor, $msgtype)
=item get_msgtype
=item set_source($source)
=item get_source()
=item set_operator($operator)
=item get_operator()
=item set_group($group)
=item get_group()
=item set_rate($rate, $freq)
=item get_rate()
=item set_buffered_io($bool)
=item get_buffered_io()
=item set_zlibout($bool)
=item get_zlibout()
=item set_endline($eol)
=item get_endline()
=item get_bufsz()
=back
=head2 METHODS
=over
=item write($msg)
Write the given Net::Nmsg::Msg object to this output.
=back
=head1 SEE ALSO
L<Net::Nmsg>, L<Net::Nmsg::IO>, L<Net::Nmsg::Input>, L<Net::Nmsg::Msg>, L<nmsgtool(1)>
=head1 AUTHOR
Matthew Sisk, E<lt>sisk@cert.orgE<gt>
=head1 COPYRIGHT & LICENSE
Copyright (C) 2010-2015 by Carnegie Mellon University
Use of the Net-Silk library and related source code is subject to the
terms of the following licenses:
GNU Public License (GPL) Rights pursuant to Version 2, June 1991
Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013
NO WARRANTY
See GPL.txt and LICENSE.txt for more details.
=cut