DevIo.pm: Mask websocket replies (Forum #109910)

git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@22100 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2020-06-03 12:24:04 +00:00
parent 31405959e7
commit 85b9f3c13e

View File

@ -125,6 +125,33 @@ DevIo_TimeoutRead($$;$$)
return $answer; return $answer;
} }
sub
DevIo_MaskWS($$)
{
my ($opcode,$msg) = @_;
$opcode = pack("C",$opcode|0x80);
my $len = length($msg);
my $lb;
if($len < 126) {
$lb = chr(0x80+$len);
} else {
if ($len < 65536) {
$lb = chr(0x8E) . pack('n', $len);
} else {
$lb = chr(0x8F) . chr(0x00) . chr(0x00) .
chr(0x00) . chr(0x00) . pack('N', $len);
}
}
my $mask = pack("L",rand(2**32));
my @m = unpack("C*", $mask);
my $idx = 0;
$msg = pack("C*", map { $_ ^ $m[$idx++ % 4] } unpack("C*", $msg));
return $opcode.$lb.$mask.$msg;
}
sub sub
DevIo_DecodeWS($$) DevIo_DecodeWS($$)
{ {
@ -141,19 +168,6 @@ DevIo_DecodeWS($$)
my $len = (ord(substr($data,1,1)) & 0x7F); my $len = (ord(substr($data,1,1)) & 0x7F);
my $i = 2; my $i = 2;
# $op: 0=>Continuation, 1=>Text, 2=>Binary, 8=>Close, 9=>Ping, 10=>Pong
Log3 $hash, 5, "Websocket msg: OP:$op LEN:$len MASK:$mask FIN:$fin";
if($op == 8) { # Close, Normal, empty mask. #104718
syswrite($hash->{TCPDev}, pack("CCn",0x88,0x2,1000));
DevIo_CloseDev($hash);
return undef;
} elsif($op == 9) { # Ping
syswrite($hash->{TCPDev}, chr(0x8A).chr(0)); # Pong
$hash->{".WSBUF"} = substr($data, 2);
return DevIo_DecodeWS($hash, "");
}
if( $len == 126 ) { if( $len == 126 ) {
return "" if(length($data) < 4); return "" if(length($data) < 4);
$len = unpack('n', substr($data, $i, 2)); $len = unpack('n', substr($data, $i, 2));
@ -178,6 +192,20 @@ DevIo_DecodeWS($$)
my $idx = 0; my $idx = 0;
$data = pack("C*", map { $_ ^ $m[$idx++ % 4] } unpack("C*", $data)); $data = pack("C*", map { $_ ^ $m[$idx++ % 4] } unpack("C*", $data));
} }
# $op: 0=>Continuation, 1=>Text, 2=>Binary, 8=>Close, 9=>Ping, 10=>Pong
Log3 $hash, 5, "Websocket msg: OP:$op LEN:$len MASK:$mask FIN:$fin";
if($op == 8) { # Close, Normal, empty mask. #104718
syswrite($hash->{TCPDev}, DevIo_MaskWS(0x8,$data));
DevIo_CloseDev($hash);
return undef;
} elsif($op == 9) { # Ping
syswrite($hash->{TCPDev}, DevIo_MaskWS(0xA, $data)); # Pong
$hash->{".WSBUF"} = substr($data, 2);
return DevIo_DecodeWS($hash, "");
}
return $data; return $data;
} }
@ -198,19 +226,7 @@ DevIo_SimpleWrite($$$;$)
$hash->{USBDev}->write($msg); $hash->{USBDev}->write($msg);
} elsif($hash->{TCPDev}) { } elsif($hash->{TCPDev}) {
if($hash->{WEBSOCKET}) { $msg = DevIo_MaskWS($hash->{binary} ? 0x2:0x1, $msg) if($hash->{WEBSOCKET});
my $len = length($msg);
if($len < 126) {
$msg = chr(0x81) . chr($len) . $msg;
} else {
if ($len < 65536) {
$msg = chr(0x81) . chr(0x7E) . pack('n', $len) . $msg;
} else {
$msg = chr(0x81) . chr(0x7F) . chr(0x00) . chr(0x00) .
chr(0x00) . chr(0x00) . pack('N', $len) . $msg;
}
}
}
syswrite($hash->{TCPDev}, $msg); syswrite($hash->{TCPDev}, $msg);
} elsif($hash->{DIODev}) { } elsif($hash->{DIODev}) {