This file is indexed.

/usr/share/perl5/Perlbal/TCPListener.pm is in libperlbal-perl 1.80-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
######################################################################
# TCP listener on a given port
#
# Copyright 2004, Danga Interactive, Inc.
# Copyright 2005-2007, Six Apart, Ltd.


package Perlbal::TCPListener;
use strict;
use warnings;
no  warnings qw(deprecated);

use base "Perlbal::Socket";
use fields ('service',
            'hostport',
            'sslopts',
            'v6',  # bool: IPv6 libraries are available
            );
use Socket qw(IPPROTO_TCP SOL_SOCKET SO_SNDBUF);

BEGIN {
    eval { require Perlbal::SocketSSL };
    if (Perlbal::DEBUG > 0 && $@) { warn "SSL support failed on load: $@\n" }
}

# TCPListener
sub new {
    my Perlbal::TCPListener $self = shift;
    my ($hostport, $service, $opts) = @_;

    $self = fields::new($self) unless ref $self;
    $opts ||= {};

    # Were ipv4 or ipv6 explicitly mentioned by syntax?
    my $force_v4 = 0;
    my $force_v6 = 0;

    my @args;
    if ($hostport =~ /^\d+$/) {
        @args = ('LocalPort' => $hostport);
    } elsif ($hostport =~ /^\d+\.\d+\.\d+\.\d+:/) {
        $force_v4 = 1;
        @args = ('LocalAddr' => $hostport);
    }

    my $v6_errors = "";

    my $can_v6 = 0;
    if (!$force_v4) {
        eval "use Danga::Socket 1.61; 1; ";
        if ($@) {
            $v6_errors = "Danga::Socket 1.61 required for IPv6 support.";
        } elsif (!eval { require IO::Socket::INET6; 1 }) {
            $v6_errors = "IO::Socket::INET6 required for IPv6 support.";
        } else {
            $can_v6 = 1;
        }
    }

    my $socket_class = $can_v6 ? "IO::Socket::INET6" : "IO::Socket::INET";
    $self->{v6} = $can_v6;

    my $sock = $socket_class->new(
                                  @args,
                                  Proto => IPPROTO_TCP,
                                  Listen => 1024,
                                  ReuseAddr => 1,
                                  );

    return Perlbal::error("Error creating listening socket: " . ($@ || $!))
        unless $sock;

    if ($^O eq 'MSWin32') {
        # On Windows, we have to do this a bit differently.
        # IO::Socket should really do this for us, but whatever.
        my $do = 1;
        ioctl($sock, 0x8004667E, \$do) or return Perlbal::error("Unable to make listener on $hostport non-blocking: $!");
    }
    else {
        # IO::Socket::INET's Blocking => 0 just doesn't seem to work
        # on lots of perls.  who knows why.
        IO::Handle::blocking($sock, 0) or return Perlbal::error("Unable to make listener on $hostport non-blocking: $!");
    }

    $self->SUPER::new($sock);
    $self->{service} = $service;
    $self->{hostport} = $hostport;
    $self->{sslopts} = $opts->{ssl};
    $self->watch_read(1);
    return $self;
}

# TCPListener: accepts a new client connection
sub event_read {
    my Perlbal::TCPListener $self = shift;

    # accept as many connections as we can
    while (my ($psock, $peeraddr) = $self->{sock}->accept) {
        IO::Handle::blocking($psock, 0);

        if (my $sndbuf = $self->{service}->{client_sndbuf_size}) {
            my $rv = setsockopt($psock, SOL_SOCKET, SO_SNDBUF, pack("L", $sndbuf));
        }

        if (Perlbal::DEBUG >= 1) {
            my ($pport, $pipr) = $self->{v6} ?
                Socket6::unpack_sockaddr_in6($peeraddr) :
                Socket::sockaddr_in($peeraddr);
            my $pip = $self->{v6} ?
                "[" . Socket6::inet_ntop(Socket6::AF_INET6(), $pipr) . "]" :
                Socket::inet_ntoa($pipr);
            print "Got new conn: $psock ($pip:$pport) for " . $self->{service}->role . "\n";
        }

        # SSL promotion if necessary
        if ($self->{sslopts}) {
            # try to upgrade to SSL, this does no IO it just re-blesses
            # and prepares the SSL engine for handling us later
            Perlbal::SocketSSL2->start_SSL(
                                       $psock,
                                       SSL_server => 1,
                                       SSL_startHandshake => 0,
                                       %{ $self->{sslopts} },
                                       );
            print "  .. socket upgraded to SSL!\n" if Perlbal::DEBUG >= 1;

            # safety checking to ensure we got upgraded
            return $psock->close
                unless ref $psock eq 'Perlbal::SocketSSL2';

            # class into new package and run with it
            my $sslsock = new Perlbal::SocketSSL($psock, $self);
            $sslsock->try_accept;

            # all done from our point of view
            next;
        }

        # puts this socket into the right class
        $self->class_new_socket($psock);
    }
}

sub class_new_socket {
    my Perlbal::TCPListener $self = shift;
    my $psock = shift;

    my $service_role = $self->{service}->role;
    if ($service_role eq "reverse_proxy") {
        return Perlbal::ClientProxy->new($self->{service}, $psock);
    } elsif ($service_role eq "management") {
        return Perlbal::ClientManage->new($self->{service}, $psock);
    } elsif ($service_role eq "web_server") {
        return Perlbal::ClientHTTP->new($self->{service}, $psock);
    } elsif ($service_role eq "selector") {
        # will be cast to a more specific class later...
        return Perlbal::ClientHTTPBase->new($self->{service}, $psock, $self->{service});
    } elsif (my $creator = Perlbal::Service::get_role_creator($service_role)) {
        # was defined by a plugin, so we want to return one of these
        return $creator->($self->{service}, $psock);
    }
}

sub as_string {
    my Perlbal::TCPListener $self = shift;
    my $ret = $self->SUPER::as_string;
    my Perlbal::Service $svc = $self->{service};
    $ret .= ": listening on $self->{hostport} for service '$svc->{name}'";
    return $ret;
}

sub as_string_html {
    my Perlbal::TCPListener $self = shift;
    my $ret = $self->SUPER::as_string_html;
    my Perlbal::Service $svc = $self->{service};
    $ret .= ": listening on $self->{hostport} for service <b>$svc->{name}</b>";
    return $ret;
}

sub die_gracefully {
    # die off so we stop waiting for new connections
    my $self = shift;
    $self->close('graceful_death');
}

1;


# Local Variables:
# mode: perl
# c-basic-indent: 4
# indent-tabs-mode: nil
# End: