jk2addict has asked for the wisdom of the Perl Monks concerning the following question:

This is almost too embarrasing to ask help about, but no matter how many times I go over perlfaq5, it's not sinking in. I'm fiddling with the examples in the Stein Network Programming with Perl book, and managed to set up a workin tcp server. Just for giggles, I wanted to break out the authentication routine to it could be overridden by other modules.

Just for a little background, the tcp conversation consist of an authorization request, an auth. response, then it loops to service request after request. Each request and response is fixed in length.

Here's the inner loop of the server module (gutted for shortness):

sub start { while (1) { next unless $session = $self->__socket->accept; my $quit = 0; my $auth; read($session, $auth, 50); ... #do auth stuffs ... while (! $quit) { my $request; read($session, $request, 150); if ($request =~ /^Q\s*$/i) { $quit = 1; } else { print $session 'foo response'; }; }; close($session); next; }; ... }

Everything works as expected. Now I would like to pass the $session (IO::Socket::INET glob) to an anthentication sub. I've tried every encantation of passing globs, globrefs, and localizing, but regardless, my $session in the authenticate sub is empty.

sub authenticate { my ($self, $session) = @_; # $session is undef. return 1; } sub start { while (1) { next unless $session = $self->__socket->accept; my $quit = 0; if (!authenticate($session)) { $session->shutdown; next; } ... while (! $quit) { my $request; read($session, $request, 150); if ($request =~ /^Q\s+/i) { $quit = 1; } else { print $session 'foo response'; }; }; close($session); next; }; ... }

Obviously, I don't truely understand what $session really is, nr how to properly pass it. Feel free to institute broad usage of a moderate sized clue-stick upon the poster.

Thanks,
-=Chris

Replies are listed 'Best First'.
Re: Passing IO::Socket::INET
by dws (Chancellor) on Jan 27, 2003 at 19:11 UTC
    You're confusing subroutine invocation with method invocation. When you do
    if (!authenticate($session)) { ...
    you're passing a single parameter.
    sub authenticate { my ($self, $session) = @_; ...
    then puts this this single parameter into $self, which isn't what you expect.

    To invoke authenticate() as a method, you would need to write

    if (! $self->authenticate($session)) { ...
    But this wouldn't work, since start() doesn't set up $self.

      Bing. That was the problem. I know better, yet the stupidity persisted. (Step away from the keyboard, there's nothing more to break here.)

Re: Passing IO::Socket::INET
by l2kashe (Deacon) on Jan 27, 2003 at 19:19 UTC
    When I played like this it was writing a SMTP and POP module (just cause it was a good exercise)..

    # # initialization # $self->{'sock'} = IO::Socket::INET->new( args => 'go_here', ) || die "Cant create socket\nReason: $!\n"; # #retrieval for use # $sock = $obj->_get_sock(); sub _get_sock { return($_[0]->{'sock'}); }
    I honestly shouldn't be playing like that, cause I'm not quite sure how it works, only simply that it does. So I am assuming you could do something similar by storing it in a hash or even in an array and passing the hash/array around and then pulling the reference to the socket back out of the data structure.

    Hopefully someone more wizardly will explain what is going on. I believe that the IO::Socket returns a object, which is really just a blessed reference to a data structure. So you should be able to say.
    $sock = IO::Socket::INET->new( args => 'go_here', ) || die "blah\n$!\n"; $sock_ref = \$sock; some_func($sock_ref); sub some_func { $ref = shift; $sock = ${$ref}; $line = <$sock>; }
    Edit: I should clarify a little I guess, I do know how the code works, and what I am passing around, and even what is going on in _get_sock, Im just not overly familiar with OOP. I use it, but I don't understand all of the inner workings of perl OOP, and there are better ways to play with sockets. It was simply a shotgun approach, which proved I could prototype what I wanted and get a working model. I probably should have read your code, as opposed to simply assuming you wanted to know how to pass a socket around.

    /* And the Creator, against his better judgement, wrote man.c */
Re: Passing IO::Socket::INET
by pfaut (Priest) on Jan 27, 2003 at 19:19 UTC

    Your authenticate sub is expecting two args. Since the first is called $self, I will assume you want object oriented syntax. The problem I see with this is that the calling routing, start(), does not seem to have object oriented syntax. Although it uses a variable called $self, I don't see where you load it from but it appears to be defined outside of that routine.

    If you post the rest of the code, we might be able to come up with a more complete solution to your problem but from what you've shown here my recommendation would be to remove the $self in authenticate since you are only passing one argument in.

    --- print map { my ($m)=1<<hex($_)&11?' ':''; $m.=substr('AHJPacehklnorstu',hex($_),1) } split //,'2fde0abe76c36c914586c';