_asm
Гость
|
|
« Ответ #5 : 27-01-2004 10:19 » |
|
sub get_halflife_master_packets { # packet_handler my ($self,$filter) = @_; my $socket = $$self{socket}; my $cmd = sprintf($servers{$$self{gametype}}{master_query}{command}, $filter); my $header = $servers{$$self{gametype}}{master_query}{response}; my ($res,$unique,$batch) = (0,0,0); my $result = ''; my @ary = (); my $sel = new IO::Select($socket); $self->timedout(0);
if ($sel->can_write($$self{maxwait})) { # get first batch $socket->send($cmd); } else { $self->timedout(1); }
if (!$self->timedout) { $res = $self->get_halflife_packets(); if ($res =~ s/^$header//s) { # $header is assumed to have one () match in it for $1 $unique = unpack('l',$1); $result .= $res; } }
while ($unique != 0 and !$self->timedout) { # get all remaining batches $res = ''; if ($sel->can_write($$self{maxwait})) { my $cmd2 = sprintf($servers{$$self{gametype}}{master_query}{command2}, pack('i',$unique), $filter); $socket->send($cmd2); } else { $self->timedout(1); } $res = $self->get_halflife_packets() if (!$self->timedout); if ($res =~ s/^$header//s) { $unique = unpack('l',$1); $result .= $res; } }
return $result; }
sub get_halflife_packets() { my ($self) = @_; my $sock = $$self{socket}; my $sel = new IO::Select($sock); my @packets = (''); my ($head, $inhead, $size, $first, $last, $seq); my $buff = ''; my $morepackets = 1; $seq = ''; $first = 0; $last = 0; $self->timedout(0); while (!$self->timedout and $morepackets) { if ($sel->can_read($$self{maxwait})) { $sock->recv($buff, 1500); $size = length($buff); # must keep track of original size of buffer # print "=== ($size) " . $buff . "\n"; # debug $head = substr($buff,0,4); # get first 4 bytes (32bit int) last unless $head; my $packettype = int(unpack('l',$head) || 0); # if ($packettype == -1) { # single packet, no more will be sent from server $packets[0] = $buff; # leave the 5 byte header intact $morepackets = 0;
} elsif ($packettype == -2) { # -2 header signifies a multi-packet sequence is being sent $buff = substr($buff, 4); # remove "-2" header, its useless $seq = unpack('l',substr($buff,0,4)); # we're ignoring the sequence for the time being, so its not actually used $inhead = unpack('c',substr($buff,4,1)); # get 9th (4th since we've trimmed the headers already) byte (partial packet 0x02 or last packet 0x12?) $buff = substr($buff,5); # strip off the sequence# and 'inhead' byte
if ($inhead == 0x02) { # 0x02 is the 'first' packet in the sequence unshift(@packets, $buff); # add packet to front of array (unshifted incase we already received packets) $first++; $morepackets = !$last; # if we've received the 'last' packet already then we're done
} elsif ($inhead == 0x12) { # 0x12 is a 'partial' packet ## there isn't much we can do to make sure multiple 'partial' packets are received in the correct order ## so we'll just append each 'partial' we get onto the @packets array and hope for the best ## All we CAN tell is, if the 'partial' packet is less then 1400 then its the last packet, otherwise it goes ## 'in the middle' push(@packets, $buff); $morepackets = (($size == 1400) or !$first); # more, if this packet is 1400 or we haven't gotten the 'first' packet yet $last++ if $size < 1400; # is this the last packet? } else { ## invalid packet? }
} else { $morepackets = 0; # ignore anything else, since the header is unknown/invalid
} } else { $self->timedout(1); } }
|