Thanks, Rocco.  I appreciate the help.

I've been playing with your solution and it seems to work ok for the
login portion of the interaction, but not the hand off to BOS (whatever
that is -- I assume it's just the chat server).

Here's what happens:

Net::OSCAR interacts with the login server, then closes the connection. 
At this point its debug code shows this:

login: Got authorization response.
login: Login OK - connecting to BOS
login: Closing.
BOS: Connecting to 205.188.8.47:5190.

At that point, the code you suggested dies with:

Can't call method "process_one" on an undefined value at
POE/Component/OSCAR.pm

... which is from the process_one line in wr_ok.  

So I added some debug code to wr_ok, like so:

my $fileno = fileno($socket);
print "in write ok: " . join(', ', $fileno, $socket->opened,
$socket->error, $socket->clearerr, join(',', $socket->stat)) . "\n";

which at this stage yields

in write ok: , , -1, -1,

i.e., the socket appears to be invalid/non-existent.  

Adding a simple

return unless $fileno;

avoids the error, but just causes the app to hang, as both wr_ok and
rd_ok are repeatedly called with an invalid socket.

During all this, ex_ok is never called, though it should be upon the
disconnect, right?

Also, if I set an event to look at all the Oscar connections a few
seconds into all this, there's still only one, and it's fileno is the
same as that of the original socket.  Can something happen so that a
socket and its fileno become dissociated?

I can post the code if you're interested, but completely understand if
you've got bigger fish to fry.

Thanks,
Dan

On Thu, 2003-08-21 at 21:10, Rocco Caputo wrote:
> On Thu, Aug 21, 2003 at 04:12:34PM -0400, Dan McCormick wrote:
> > Howdy,
> > 
> > If no one's released a PoCo::Net::OSCAR (i.e. the public face of AOL's
> > IM), I've got one to offer.
> > 
> > However, I was hoping for a bit of feedback first, because I'm not sure
> > I've gone about it in the best way.  The Net::OSCAR module is very nice
> > in that it can use other event loops.  The only hitch is that it thinks
> > in terms of filenos and it looks like POE thinks in terms of sockets and
> > handles.  I'm not too well-versed in this area, but after a bit of trial
> > and error, I came up with this:
> > 
> > # sign on, and set up POE to monitor all the connections
> > $_[HEAP]->{oscar}->signon( %args );
> 
> [...]
> 
> > This works fine, but it seems a bit heavy on the selects.  Is there a
> > better way?
> 
> It looks like Net::OSCAR has a findconn() function that will find a
> connection based on a socket's file descriptor.  Generating file
> descriptors from socket handles is a lot easier than going the other
> way: just call fileno() on them.
> 
> This code (untested!) simulates Net::OSCAR::process_connections() on one
> connection at a time.
> 
> The only shame is that Net::OSCAR::findconn() does a grep on all the
> connections to find the matching one.  A hash of (fileno => connection)
> pairs would be nice there.
> 
>   foreach my $conn (@{ $heap->{oscar}->{connections} }) {
>     $kernel->select($connection->{socket}, 'rd_ok', 'wr_ok', 'ex_ok');
>   }
> 
>   sub rd_ok {
>     my ($heap, $socket) = @_[HEAP, ARG0];
>     my $conn = $heap->{oscar}->findconn(fileno($socket));
>     $conn->process_one(1, 0);
>   }
> 
>   sub wr_ok {
>     my ($heap, $socket) = @_[HEAP, ARG0];
>     my $conn = $heap->{oscar}->findconn(fileno($socket));
>     $conn->process_one(0, 1);
>   }
> 
>   sub ex_ok {
>     my ($heap, $socket) = @_[HEAP, ARG0];
>     my $conn = $heap->{oscar}->findconn(fileno($socket));
>     $kernel->select($socket);  # stop the socket from POE
>     $connection->{sockerr} = 1;
>     $connection->disconnect();
>   }
> 
> Good luck.

Reply via email to