A
A. Farber
Hello,
I have an object, which reads a header
from a non-blocking socket and if the header
indicates, that there is more data to read
(a chat string) then it will read that too.
To handle those 2 reading states
(reading a header; reading a chat string)
I try to use 3 variables: $buf, $toread, $offset
and then call sysread($buf, $toread, $offset).
My problem is, that I need to set
$buf to _point_ to $self->{REQ_HEADER}
in the 1st state and to $self->{CHAT}
in the 2nd state. But I don't know how.
In C-code (which I'm trying to port to Perl)
this has been very easy. But in Perl I don't
know how and rereading "perlref" doesn't help.
Any hints please?
Alex
PS: My complete, but buggy code is below:
sub read {
my $self = shift;
my $fh = $self->{FH};
my ($buf, $toread, $offset, $nbytes);
# start or continue reading the request header
if ($self->{NREAD} < REQ_HEADER_LEN) {
$buf = $self->{REQ_HEADER};
$offset = $self->{NREAD};
$toread = REQ_HEADER_LEN - $offset;
# start or continue reading the chat string
} else {
$buf = $self->{CHAT};
$offset = $self->{NREAD} - REQ_HEADER_LEN;
$toread = $self->{LEN} - $offset;
}
# XXX the buf is WRONG here:
$nbytes = $fh->sysread($buf, $toread, $offset);
unless (defined $nbytes) {
# interrupted by signal or would block - retry later
return if $!{EINTR} || $!{EAGAIN} || $!{EWOULDBLOCK};
# connection interrupted - remove the Apache child
$self->remove($fh);
return;
}
if (0 == $nbytes) {
# connection closed - remove the Apache child
$self->remove($fh);
return;
}
$self->{NREAD} += $nbytes;
print STDERR "nbytes = $nbytes\n";
# not done yet - continue reading
return if $nbytes < $toread;
if (REQ_HEADER_LEN == $self->{NREAD}) {
($self->{SID}, $self->{EVENT}, $self->{MOD}, $self-
printf STDERR "sid=%s, event=%x, mod=%x, len=%x\n",
$self->{SID}, $self->{EVENT}, $self->{MOD}, $self-
# not done yet - continue reading (the chat string)
return if $self->{LEN} > 0;
}
print STDERR "done reading";
#$Poll->mask($fh => POLLOUT);
}
I have an object, which reads a header
from a non-blocking socket and if the header
indicates, that there is more data to read
(a chat string) then it will read that too.
To handle those 2 reading states
(reading a header; reading a chat string)
I try to use 3 variables: $buf, $toread, $offset
and then call sysread($buf, $toread, $offset).
My problem is, that I need to set
$buf to _point_ to $self->{REQ_HEADER}
in the 1st state and to $self->{CHAT}
in the 2nd state. But I don't know how.
In C-code (which I'm trying to port to Perl)
this has been very easy. But in Perl I don't
know how and rereading "perlref" doesn't help.
Any hints please?
Alex
PS: My complete, but buggy code is below:
sub read {
my $self = shift;
my $fh = $self->{FH};
my ($buf, $toread, $offset, $nbytes);
# start or continue reading the request header
if ($self->{NREAD} < REQ_HEADER_LEN) {
$buf = $self->{REQ_HEADER};
$offset = $self->{NREAD};
$toread = REQ_HEADER_LEN - $offset;
# start or continue reading the chat string
} else {
$buf = $self->{CHAT};
$offset = $self->{NREAD} - REQ_HEADER_LEN;
$toread = $self->{LEN} - $offset;
}
# XXX the buf is WRONG here:
$nbytes = $fh->sysread($buf, $toread, $offset);
unless (defined $nbytes) {
# interrupted by signal or would block - retry later
return if $!{EINTR} || $!{EAGAIN} || $!{EWOULDBLOCK};
# connection interrupted - remove the Apache child
$self->remove($fh);
return;
}
if (0 == $nbytes) {
# connection closed - remove the Apache child
$self->remove($fh);
return;
}
$self->{NREAD} += $nbytes;
print STDERR "nbytes = $nbytes\n";
# not done yet - continue reading
return if $nbytes < $toread;
if (REQ_HEADER_LEN == $self->{NREAD}) {
($self->{SID}, $self->{EVENT}, $self->{MOD}, $self-
unpack 'A32xN3', $self->{REQ_HEADER};{LEN}) =
printf STDERR "sid=%s, event=%x, mod=%x, len=%x\n",
$self->{SID}, $self->{EVENT}, $self->{MOD}, $self-
{LEN};
# not done yet - continue reading (the chat string)
return if $self->{LEN} > 0;
}
print STDERR "done reading";
#$Poll->mask($fh => POLLOUT);
}