array (0x0005, 0x0012, 0x001E), 0x0002 => array (0x0003, 0x0004, 0x0009, 0x000F), 0x0003 => array (0x0003), 0x0006 => array (0x0002), 0x0007 => array (0x0002, 0x0004, 0x0008, 0x0009), 0x0008 => array (0x0002), 0x0009 => array (0x0003), 0x000A => array (0x0003), 0x000B => array (0x0003), 0x000D => array (0x0009), 0x0013 => array (0x0003), 0x0015 => array (0x0002, 0x0003), 0x0017 => array (0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007), ); $Printables = utf8_decode ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 ,;.:-_#'+*~·@ł€¶ŧ←↓→øþ¨æßðđŋħjĸł˝^`«»¢“”nµ²³¼½¬{[]}\¸'`!\"§\$%&/()=?"); function dumpData ($Data, $Prefix = "", $Return = false) { global $Printables; $buf = ""; $line = ""; for ($i = 0; $i < strlen ($Data); $i++) { $m = $i % 16; if ($m == 0) $buf .= $Prefix; $n = ord ($Data [$i]); $c = dechex ($n); $line .= $Data [$i]; $buf .= ($n < 16 ? "0" : "") . $c . " "; if ($m == 15) { $buf .= " "; for ($p = 0; $p < strlen ($line); $p++) { $c = $line [$p]; if (strpos ($Printables, $c) === false) $buf .= "."; else $buf .= utf8_encode ($c); } $buf .= "\n"; $line = ""; } } if ($i % 16 != 15) $buf .= "\n"; if ($Return) return $buf; print $buf; } function flapDebug ($Flap, $Socket = null, $Read = true, $DebugInfo = "") { global $TLV_SNACs; // Retrive information about our socket $IP = ""; $Port = 0; if (is_resource ($Socket)) socket_getpeername ($Socket, $IP, $Port); // Output FLAP Header if ($DebugInfo != "") $DebugInfo .= " "; print $DebugInfo; if ($Read) print "Reading FLAP" . ($IP != "" ? " from $IP:$Port" : ""); else print "Writing FLAP" . ($IP != "" ? " to $IP:$Port" : ""); print "\n" . $DebugInfo . "Channel " . $Flap ["Channel"] . " / Sequence " . $Flap ["Sequence"] . " / Length " . $Flap ["Length"] . " (" . strlen ($Flap ["Payload"]) . ")\n" . $DebugInfo . "\n"; // Handle SNACs on Channel 2 if ($Flap ["Channel"] == 2) { $SNAC = flapReadSNAC ($Flap); print $DebugInfo . "SNAC Family 0x" . dechex ($SNAC ["Family"]) . " / Subtype 0x" . dechex ($SNAC ["Subtype"]) . " / " . "Flags 0x" . dechex ($SNAC ["Flags"]) . " / Sequence 0x" . dechex ($SNAC ["Sequence"]) . "\n" . $DebugInfo . "\n"; // Check for TLVs in SNAC if (isset ($TLV_SNACs [$SNAC ["Family"]]) && in_array ($SNAC ["Subtype"], $TLV_SNACs [$SNAC ["Family"]])) $hasTLV = true; else $hasTLV = false; # TODO: Try to autodetect TLV-SNACs here if ($hasTLV) { $Flap ["Length"] = 0; $Items = flapTreatTLV ($SNAC); foreach ($Items as $Item) { print $DebugInfo . "TLV Type 0x" . dechex ($Item ["Type"]) . " / Length " . $Item ["Length"] . "\n"; dumpData ($Item ["Payload"], $DebugInfo); print $DebugInfo . "\n"; } // Dirty hack :D } else { $Flap = $SNAC; $Flap ["Length"] = strlen ($SNAC ["Payload"]); } } // Output payload if ($Flap ["Length"] > 0) dumpData ($Flap ["Payload"], $DebugInfo); print "\n"; } function flapRead ($Socket, $Debug = false, $DebugInfo = "") { // Read magic packet from stream $C = chr (0x2A); while (($c = socket_read ($Socket, 1, PHP_BINARY_READ)) && ($c != $C)) { if ($c == "") break; usleep (1); } // Check if read was successfull if ($c != $C) { unsetSocketContext ($Socket); return false; } // Read FLAP-Header from stream $Header = socket_read ($Socket, 5, PHP_BINARY_READ); // Parse the header $Info = array ( "Channel" => ord ($Header [0]), "Sequence" => (ord ($Header [1]) << 8) + ord ($Header [2]), "Length" => (ord ($Header [3]) << 8) + ord ($Header [4]), "Payload" => "", ); // Read payload if ($Info ["Length"] > 0) { while (strlen ($Info ["Payload"]) < $Info ["Length"]) $Info ["Payload"] .= socket_read ($Socket, $Info ["Length"] - strlen ($Info ["Payload"]), PHP_BINARY_READ); if (($l = strlen ($Info ["Payload"])) != $Info ["Length"]) print "WARNING: Read " . $l . " bytes instead of " . $Info ["Length"] . "\n\n"; } // Debug this packet if ($Debug) flapDebug ($Info, $Socket, true, $DebugInfo); return $Info; } function writeFlap ($Socket, $Data, $Debug = false, $DebugInfo = "") { // Prepare FLAP Payload if ($Data ["Length"] > 0) { $Payload = substr ($Data ["Payload"], 0, $Data ["Length"]); if (($l = strlen ($Payload)) < $Data ["Length"]) $Payload .= str_repeat (chr (0), $Data ["Length"] - $l); } else $Payload = ""; if ($Debug) flapDebug ($Data, $Socket, false, $DebugInfo); // Write everything to stream return @socket_write ( $Socket, chr (0x2A) . chr ($Data ["Channel"]) . chr (($Data ["Sequence"] & 0xFF00) >> 8) . chr ($Data ["Sequence"] & 0xFF) . chr (($Data ["Length"] & 0xFF00) >> 8) . chr ($Data ["Length"] & 0xFF) . $Payload ); } function flapTreatTLV ($Flap) { $Payload = $Flap ["Payload"]; $Items = array (); while (strlen ($Payload) > 0) { $Type = (ord ($Payload [0]) << 8) + ord ($Payload [1]); $Length = (ord ($Payload [2]) << 8) + ord ($Payload [3]); if ($Length > 0) $Data = substr ($Payload, 4, $Length); else $Data = ""; $Items [] = array ( "Type" => $Type, "Length" => $Length, "Payload" => $Data, ); $Payload = substr ($Payload, $Length + 4); } return $Items; } function flapReadSNAC ($Flap) { if ($Flap ["Channel"] != 2) return false; $Payload = $Flap ["Payload"]; $Family = (ord ($Payload [0]) << 8) + ord ($Payload [1]); $Subtype = (ord ($Payload [2]) << 8) + ord ($Payload [3]); $Flags = (ord ($Payload [4]) << 8) + ord ($Payload [5]); $Request = (ord ($Payload [6]) << 24) + (ord ($Payload [7]) << 16) + (ord ($Payload [8]) << 8) + ord ($Payload [9]); $Payload = substr ($Payload, 10); return array ( "Family" => $Family, "Subtype" => $Subtype, "Flags" => $Flags, "Request" => $Request, "Payload" => $Payload, ); } function flapRewriteSNAC ($FLAP, $SNAC) { $FLAP ["Payload"] = chr (($SNAC ["Family"] & 0xFF00) >> 8) . chr ($SNAC ["Family"] & 0xFF) . chr (($SNAC ["Subtype"] & 0xFF00) >> 8) . chr ($SNAC ["Subtype"] & 0xFF) . chr (($SNAC ["Flags"] & 0xFF00) >> 8) . chr ($SNAC ["Flags"] & 0xFF) . chr (($SNAC ["Request"] & 0xFF000000) >> 24) . chr (($SNAC ["Request"] & 0x00FF0000) >> 16) . chr (($SNAC ["Request"] & 0x0000FF00) >> 8) . chr ($SNAC ["Request"] & 0x000000FF) . $SNAC ["Payload"]; $FLAP ["Length"] = strlen ($FLAP ["Payload"]); return $FLAP; } function flapRewriteTLV ($FLAP, $Items) { $FLAP ["Payload"] = ""; foreach ($Items as $Item) { if ($Item ["Length"] > 0) { $Payload = $Item ["Payload"]; if (($l = strlen ($Payload)) < $Item ["Length"]) $Payload .= str_repeat (chr (0), $Item ["Length"] - $l); } else $Payload = ""; $FLAP ["Payload"] .= chr (($Item ["Type"] & 0xFF00) >> 8) . chr ($Item ["Type"] & 0xFF) . chr (($Item ["Length"] & 0xFF00) >> 8) . chr ($Item ["Length"] & 0xFF) . $Payload; } $FLAP ["Length"] = strlen ($FLAP ["Payload"]); return $FLAP; } ?>