package Node::Socket;

=head1 Node::Socket

Abstract super class for writing socket handlers

=cut

use strict;
use Carp;
use Fcntl;

=head2 new

@ISA = qw/Node::Socket/;
$socket = $package->SUPER::new($handle);

Constructor, to be used by sub-class constructors.  Sets the
file-handle non-blocking, and adds it to the Node's IO::Select

=cut

sub new {
    my ($package, $handle) = @_;

    # create the object hash
    my $self = bless {
	handle => $handle,
    }, $package;

    # make the handle non-blocking
    my $flags = fcntl($handle, F_GETFL, 0)
	|| croak "Can't get fcntl flags";
    fcntl($handle, F_SETFL, $flags | O_NONBLOCK)
	|| croak "Can't set fcntl flags";

    # add the handle to the node's IO::Select
    Node->add_socket($self);

    return $self;
}

=head2 handle

get the IO::Handle

=cut

sub handle {
    my ($self) = @_;
    return $self->{handle};
}

=head2 socket_read

called by Node: abstract: subclasses need to implement this method

=cut

sub socket_read {
    my $self = shift;
    croak "socket_read not implemented for '$self'";
}

=head2 socket_write

called by Node: abstract: subclasses may need to implement this method

=cut

sub socket_write {
    my $self = shift;
    croak "socket_write not implemented for '$self'";
}

=head2 socket_error

called by Node: default socket error handler - dies.
Probably should just close the socket?

=cut

sub socket_error {
    my $self = shift;
    croak "error on socket '$self'";
}

=head2 close

clsoe the socket - removes the handle from the Node's IO::Select
TODO: should this also close the file handle?

=cut

sub close {
    my ($self) = @_;
    Node->remove_socket($self);
}

1
