LyoKICogVkdBIGhhcmR3YXJlIGVtdWxhdGlvbgogKiAKICogQ29weXJpZ2h0IDE5OTggT3ZlIEvldmVuICh3aXRoIHNvbWUgaGVscCBmcm9tIE1hcmN1cyBNZWlzc25lcikKICoKICovCgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlICJ3aW5iYXNlLmgiCiNpbmNsdWRlICJ3aW5jb24uaCIKI2luY2x1ZGUgIm1pc2NlbXUuaCIKI2luY2x1ZGUgInZnYS5oIgojaW5jbHVkZSAiZGRyYXcuaCIKI2luY2x1ZGUgInNlcnZpY2VzLmgiCiNpbmNsdWRlICJkZWJ1Z3Rvb2xzLmgiCgpERUZBVUxUX0RFQlVHX0NIQU5ORUwoZGRyYXcpCgpzdGF0aWMgSURpcmVjdERyYXcgKmxwZGRyYXcgPSBOVUxMOwpzdGF0aWMgSURpcmVjdERyYXdTdXJmYWNlICpscGRkc3VyZjsKc3RhdGljIElEaXJlY3REcmF3UGFsZXR0ZSAqbHBkZHBhbDsKc3RhdGljIEREU1VSRkFDRURFU0Mgc2Rlc2M7CnN0YXRpYyBMT05HIHZnYV9wb2xsaW5nLHZnYV9yZWZyZXNoOwpzdGF0aWMgSEFORExFIHBvbGxfdGltZXI7CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgKCpwRGlyZWN0RHJhd0NyZWF0ZSkoTFBHVUlELExQRElSRUNURFJBVyAqLExQVU5LTk9XTik7CgpzdGF0aWMgdm9pZCBWR0FfRGVpbnN0YWxsVGltZXIodm9pZCkKewogICAgaWYgKHBvbGxfdGltZXIpIHsKICAgICAgICBTRVJWSUNFX0RlbGV0ZSggcG9sbF90aW1lciApOwogICAgICAgIHBvbGxfdGltZXIgPSAwOwogICAgfQp9CgpzdGF0aWMgdm9pZCBWR0FfSW5zdGFsbFRpbWVyKHVuc2lnbmVkIFJhdGUpCnsKICAgIFZHQV9EZWluc3RhbGxUaW1lcigpOwogICAgaWYgKCFwb2xsX3RpbWVyKQogICAgICAgIHBvbGxfdGltZXIgPSBTRVJWSUNFX0FkZFRpbWVyKCBSYXRlLCBWR0FfUG9sbCwgMCApOwp9CgpIQU5ETEUgVkdBX0FscGhhQ29uc29sZSh2b2lkKQp7CiAgICAvKiB0aGlzIGFzc3VtZXMgdGhhdCBubyBXaW4zMiByZWRpcmVjdGlvbiBoYXMgdGFrZW4gcGxhY2UsIGJ1dCB0aGVuIGFnYWluLAogICAgICogb25seSAxNi1iaXQgYXBwcyBhcmUgbGlrZWx5IHRvIHVzZSB0aGlzIHBhcnQgb2YgV2luZS4uLiAqLwogICAgcmV0dXJuIEdldFN0ZEhhbmRsZShTVERfT1VUUFVUX0hBTkRMRSk7Cn0KCi8qKiogR1JBUEhJQ1MgTU9ERSAqKiovCgppbnQgVkdBX1NldE1vZGUodW5zaWduZWQgWHJlcyx1bnNpZ25lZCBZcmVzLHVuc2lnbmVkIERlcHRoKQp7CiAgICBpZiAobHBkZHJhdykgVkdBX0V4aXQoKTsKICAgIGlmICghbHBkZHJhdykgewogICAgICAgIGlmICghcERpcmVjdERyYXdDcmVhdGUpCiAgICAgICAgewogICAgICAgICAgICBITU9EVUxFIGhtb2QgPSBMb2FkTGlicmFyeUEoICJkZHJhdy5kbGwiICk7CiAgICAgICAgICAgIGlmIChobW9kKSBwRGlyZWN0RHJhd0NyZWF0ZSA9IEdldFByb2NBZGRyZXNzKCBobW9kLCAiRGlyZWN0RHJhd0NyZWF0ZSIgKTsKICAgICAgICB9CiAgICAgICAgaWYgKHBEaXJlY3REcmF3Q3JlYXRlKSBwRGlyZWN0RHJhd0NyZWF0ZShOVUxMLCZscGRkcmF3LE5VTEwpOwogICAgICAgIGlmICghbHBkZHJhdykgewogICAgICAgICAgICBFUlIoIkRpcmVjdERyYXcgaXMgbm90IGF2YWlsYWJsZVxuIik7CiAgICAgICAgICAgIHJldHVybiAxOwogICAgICAgIH0KICAgICAgICBpZiAoSURpcmVjdERyYXdfU2V0RGlzcGxheU1vZGUobHBkZHJhdyxYcmVzLFlyZXMsRGVwdGgpKSB7CiAgICAgICAgICAgIEVSUigiRGlyZWN0RHJhdyBkb2VzIG5vdCBzdXBwb3J0IHJlcXVlc3RlZCBkaXNwbGF5IG1vZGVcbiIpOwogICAgICAgICAgICBJRGlyZWN0RHJhd19SZWxlYXNlKGxwZGRyYXcpOwogICAgICAgICAgICBscGRkcmF3PU5VTEw7CiAgICAgICAgICAgIHJldHVybiAxOwogICAgICAgIH0KICAgICAgICBJRGlyZWN0RHJhd19DcmVhdGVQYWxldHRlKGxwZGRyYXcsRERQQ0FQU184QklULE5VTEwsJmxwZGRwYWwsTlVMTCk7CiAgICAgICAgbWVtc2V0KCZzZGVzYywwLHNpemVvZihzZGVzYykpOwogICAgICAgIHNkZXNjLmR3U2l6ZT1zaXplb2Yoc2Rlc2MpOwoJc2Rlc2MuZHdGbGFncyA9IEREU0RfQ0FQUzsKCXNkZXNjLmRkc0NhcHMuZHdDYXBzID0gRERTQ0FQU19QUklNQVJZU1VSRkFDRTsKICAgICAgICBpZiAoSURpcmVjdERyYXdfQ3JlYXRlU3VyZmFjZShscGRkcmF3LCZzZGVzYywmbHBkZHN1cmYsTlVMTCl8fCghbHBkZHN1cmYpKSB7CiAgICAgICAgICAgIEVSUigiRGlyZWN0RHJhdyBzdXJmYWNlIGlzIG5vdCBhdmFpbGFibGVcbiIpOwogICAgICAgICAgICBJRGlyZWN0RHJhd19SZWxlYXNlKGxwZGRyYXcpOwogICAgICAgICAgICBscGRkcmF3PU5VTEw7CiAgICAgICAgICAgIHJldHVybiAxOwogICAgICAgIH0KICAgICAgICB2Z2FfcmVmcmVzaD0wOwogICAgICAgIC8qIHBvbGwgZXZlcnkgMjBtcyAoNTBmcHMgc2hvdWxkIHByb3ZpZGUgYWRlcXVhdGUgcmVzcG9uc2l2ZW5lc3MpICovCiAgICAgICAgVkdBX0luc3RhbGxUaW1lcigyMDAwMCk7CiAgICB9CiAgICByZXR1cm4gMDsKfQoKaW50IFZHQV9HZXRNb2RlKHVuc2lnbmVkKkhlaWdodCx1bnNpZ25lZCpXaWR0aCx1bnNpZ25lZCpEZXB0aCkKewogICAgaWYgKCFscGRkcmF3KSByZXR1cm4gMTsKICAgIGlmICghbHBkZHN1cmYpIHJldHVybiAxOwogICAgaWYgKEhlaWdodCkgKkhlaWdodD1zZGVzYy5kd0hlaWdodDsKICAgIGlmIChXaWR0aCkgKldpZHRoPXNkZXNjLmR3V2lkdGg7CiAgICBpZiAoRGVwdGgpICpEZXB0aD1zZGVzYy5kZHBmUGl4ZWxGb3JtYXQudS5kd1JHQkJpdENvdW50OwogICAgcmV0dXJuIDA7Cn0KCnZvaWQgVkdBX0V4aXQodm9pZCkKewogICAgaWYgKGxwZGRyYXcpIHsKICAgICAgICBWR0FfRGVpbnN0YWxsVGltZXIoKTsKICAgICAgICBJRGlyZWN0RHJhd1N1cmZhY2VfUmVsZWFzZShscGRkc3VyZik7CiAgICAgICAgbHBkZHN1cmY9TlVMTDsKICAgICAgICBJRGlyZWN0RHJhd19SZWxlYXNlKGxwZGRyYXcpOwogICAgICAgIGxwZGRyYXc9TlVMTDsKICAgIH0KfQoKdm9pZCBWR0FfU2V0UGFsZXR0ZShQQUxFVFRFRU5UUlkqcGFsLGludCBzdGFydCxpbnQgbGVuKQp7CiAgICBpZiAoIWxwZGRyYXcpIHJldHVybjsKICAgIElEaXJlY3REcmF3UGFsZXR0ZV9TZXRFbnRyaWVzKGxwZGRwYWwsMCxzdGFydCxsZW4scGFsKTsKICAgIElEaXJlY3REcmF3U3VyZmFjZV9TZXRQYWxldHRlKGxwZGRzdXJmLGxwZGRwYWwpOwp9Cgp2b2lkIFZHQV9TZXRRdWFkUGFsZXR0ZShSR0JRVUFEKmNvbG9yLGludCBzdGFydCxpbnQgbGVuKQp7CiAgICBQQUxFVFRFRU5UUlkgcGFsWzI1Nl07CiAgICBpbnQgYzsKCiAgICBpZiAoIWxwZGRyYXcpIHJldHVybjsKICAgIGZvciAoYz0wOyBjPGxlbjsgYysrKSB7CiAgICAgICAgcGFsW2NdLnBlUmVkICA9Y29sb3JbY10ucmdiUmVkOwogICAgICAgIHBhbFtjXS5wZUdyZWVuPWNvbG9yW2NdLnJnYkdyZWVuOwogICAgICAgIHBhbFtjXS5wZUJsdWUgPWNvbG9yW2NdLnJnYkJsdWU7CiAgICAgICAgcGFsW2NdLnBlRmxhZ3M9MDsKICAgIH0KICAgIElEaXJlY3REcmF3UGFsZXR0ZV9TZXRFbnRyaWVzKGxwZGRwYWwsMCxzdGFydCxsZW4scGFsKTsKICAgIElEaXJlY3REcmF3U3VyZmFjZV9TZXRQYWxldHRlKGxwZGRzdXJmLGxwZGRwYWwpOwp9CgpMUFNUUiBWR0FfTG9jayh1bnNpZ25lZCpQaXRjaCx1bnNpZ25lZCpIZWlnaHQsdW5zaWduZWQqV2lkdGgsdW5zaWduZWQqRGVwdGgpCnsKICAgIGlmICghbHBkZHJhdykgcmV0dXJuIE5VTEw7CiAgICBpZiAoIWxwZGRzdXJmKSByZXR1cm4gTlVMTDsKICAgIGlmIChJRGlyZWN0RHJhd1N1cmZhY2VfTG9jayhscGRkc3VyZixOVUxMLCZzZGVzYywwLDApKSB7CiAgICAgICAgRVJSKCJjb3VsZCBub3QgbG9jayBzdXJmYWNlIVxuIik7CiAgICAgICAgcmV0dXJuIE5VTEw7CiAgICB9CiAgICBpZiAoUGl0Y2gpICpQaXRjaD1zZGVzYy5sUGl0Y2g7CiAgICBpZiAoSGVpZ2h0KSAqSGVpZ2h0PXNkZXNjLmR3SGVpZ2h0OwogICAgaWYgKFdpZHRoKSAqV2lkdGg9c2Rlc2MuZHdXaWR0aDsKICAgIGlmIChEZXB0aCkgKkRlcHRoPXNkZXNjLmRkcGZQaXhlbEZvcm1hdC51LmR3UkdCQml0Q291bnQ7CiAgICByZXR1cm4gc2Rlc2MudTEubHBTdXJmYWNlOwp9Cgp2b2lkIFZHQV9VbmxvY2sodm9pZCkKewogICAgSURpcmVjdERyYXdTdXJmYWNlX1VubG9jayhscGRkc3VyZixzZGVzYy51MS5scFN1cmZhY2UpOwp9CgovKioqIFRFWFQgTU9ERSAqKiovCgppbnQgVkdBX1NldEFscGhhTW9kZSh1bnNpZ25lZCBYcmVzLHVuc2lnbmVkIFlyZXMpCnsKICAgIENPT1JEIHNpejsKCiAgICBpZiAobHBkZHJhdykgVkdBX0V4aXQoKTsKCiAgICAvKiB0aGUgeHRlcm0gaXMgc2xvdywgc28gcmVmcmVzaCBvbmx5IGV2ZXJ5IDIwMG1zICg1ZnBzKSAqLwogICAgVkdBX0luc3RhbGxUaW1lcigyMDAwMDApOwoKICAgIHNpei54ID0gWHJlczsKICAgIHNpei55ID0gWXJlczsKICAgIFNldENvbnNvbGVTY3JlZW5CdWZmZXJTaXplKFZHQV9BbHBoYUNvbnNvbGUoKSxzaXopOwogICAgcmV0dXJuIDA7Cn0KCnZvaWQgVkdBX0dldEFscGhhTW9kZSh1bnNpZ25lZCpYcmVzLHVuc2lnbmVkKllyZXMpCnsKICAgIENPTlNPTEVfU0NSRUVOX0JVRkZFUl9JTkZPIGluZm87CiAgICBHZXRDb25zb2xlU2NyZWVuQnVmZmVySW5mbyhWR0FfQWxwaGFDb25zb2xlKCksJmluZm8pOwogICAgaWYgKFhyZXMpICpYcmVzPWluZm8uZHdTaXplLng7CiAgICBpZiAoWXJlcykgKllyZXM9aW5mby5kd1NpemUueTsKfQoKdm9pZCBWR0FfU2V0Q3Vyc29yUG9zKHVuc2lnbmVkIFgsdW5zaWduZWQgWSkKewogICAgQ09PUkQgcG9zOwogICAgCiAgICBwb3MueCA9IFg7CiAgICBwb3MueSA9IFk7CiAgICBTZXRDb25zb2xlQ3Vyc29yUG9zaXRpb24oVkdBX0FscGhhQ29uc29sZSgpLHBvcyk7Cn0KCnZvaWQgVkdBX0dldEN1cnNvclBvcyh1bnNpZ25lZCpYLHVuc2lnbmVkKlkpCnsKICAgIENPTlNPTEVfU0NSRUVOX0JVRkZFUl9JTkZPIGluZm87CiAgICBHZXRDb25zb2xlU2NyZWVuQnVmZmVySW5mbyhWR0FfQWxwaGFDb25zb2xlKCksJmluZm8pOwogICAgaWYgKFgpICpYPWluZm8uZHdDdXJzb3JQb3NpdGlvbi54OwogICAgaWYgKFkpICpZPWluZm8uZHdDdXJzb3JQb3NpdGlvbi55Owp9CgovKioqIENPTlRST0wgKioqLwoKdm9pZCBDQUxMQkFDSyBWR0FfUG9sbCggVUxPTkdfUFRSIGFyZyApCnsKICAgIGNoYXIgKmRhdDsKICAgIHVuc2lnbmVkIFBpdGNoLEhlaWdodCxXaWR0aDsKICAgIGNoYXIgKnN1cmY7CiAgICBpbnQgWSxYOwoKICAgIGlmICghSW50ZXJsb2NrZWRFeGNoYW5nZUFkZCgmdmdhX3BvbGxpbmcsIDEpKSB7CiAgICAgICAgLyogRklYTUU6IG9wdGltaXplIGJ5IGRvaW5nIHRoaXMgb25seSBpZiB0aGUgZGF0YSBoYXMgYWN0dWFsbHkgY2hhbmdlZAogICAgICAgICAqICAgICAgICAoaW4gYSB3YXkgc2ltaWxhciB0byBESUJTZWN0aW9uLCBwZXJoYXBzKSAqLwogICAgICAgIGlmIChscGRkcmF3KSB7CiAgICAgICAgICAvKiBncmFwaGljcyBtb2RlICovCiAgICAgICAgICBzdXJmID0gVkdBX0xvY2soJlBpdGNoLCZIZWlnaHQsJldpZHRoLE5VTEwpOwogICAgICAgICAgaWYgKCFzdXJmKSByZXR1cm47CiAgICAgICAgICBkYXQgPSBET1NNRU1fTWFwRG9zVG9MaW5lYXIoMHhhMDAwMCk7CiAgICAgICAgICAvKiBjb3B5IGZyb20gdmlydHVhbCBWR0EgZnJhbWUgYnVmZmVyIHRvIERpcmVjdERyYXcgc3VyZmFjZSAqLwogICAgICAgICAgZm9yIChZPTA7IFk8SGVpZ2h0OyBZKyssc3VyZis9UGl0Y2gsZGF0Kz1XaWR0aCkgewogICAgICAgICAgICAgIG1lbWNweShzdXJmLGRhdCxXaWR0aCk7CiAgICAgICAgICAgICAgLypmb3IgKFg9MDsgWDxXaWR0aDsgWCsrKSBpZiAoZGF0W1hdKSBUUkFDRShkZHJhdywiZGF0YSglZCkgYXQgKCVkLCVkKVxuIixkYXRbWF0sWCxZKTsqLwogICAgICAgICAgfQogICAgICAgICAgVkdBX1VubG9jaygpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvKiB0ZXh0IG1vZGUgKi8KICAgICAgICAgIENIQVJfSU5GTyBjaFs4MF07CiAgICAgICAgICBDT09SRCBzaXosIG9mZjsKICAgICAgICAgIFNNQUxMX1JFQ1QgZGVzdDsKICAgICAgICAgIEhBTkRMRSBjb24gPSBWR0FfQWxwaGFDb25zb2xlKCk7CgogICAgICAgICAgVkdBX0dldEFscGhhTW9kZSgmV2lkdGgsJkhlaWdodCk7CiAgICAgICAgICBkYXQgPSBET1NNRU1fTWFwRG9zVG9MaW5lYXIoMHhiODAwMCk7CiAgICAgICAgICBzaXoueCA9IDgwOyBzaXoueSA9IDE7CiAgICAgICAgICBvZmYueCA9IDA7IG9mZi55ID0gMDsKICAgICAgICAgIC8qIGNvcHkgZnJvbSB2aXJ0dWFsIFZHQSBmcmFtZSBidWZmZXIgdG8gY29uc29sZSAqLwogICAgICAgICAgZm9yIChZPTA7IFk8SGVpZ2h0OyBZKyspIHsKICAgICAgICAgICAgICBkZXN0LlRvcD1ZOyBkZXN0LkJvdHRvbT1ZOwogICAgICAgICAgICAgIGZvciAoWD0wOyBYPFdpZHRoOyBYKyspIHsKICAgICAgICAgICAgICAgICAgY2hbWF0uQ2hhci5Bc2NpaUNoYXIgPSAqZGF0Kys7CiAgICAgICAgICAgICAgICAgIGNoW1hdLkF0dHJpYnV0ZXMgPSAqZGF0Kys7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGRlc3QuTGVmdD0wOyBkZXN0LlJpZ2h0PVdpZHRoKzE7CiAgICAgICAgICAgICAgV3JpdGVDb25zb2xlT3V0cHV0QShjb24sIGNoLCBzaXosIG9mZiwgJmRlc3QpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB2Z2FfcmVmcmVzaD0xOwogICAgfQogICAgSW50ZXJsb2NrZWREZWNyZW1lbnQoJnZnYV9wb2xsaW5nKTsKfQoKc3RhdGljIEJZVEUgcGFscmVnLHBhbGNudDsKc3RhdGljIFBBTEVUVEVFTlRSWSBwYWxkYXQ7Cgp2b2lkIFZHQV9pb3BvcnRfb3V0KCBXT1JEIHBvcnQsIEJZVEUgdmFsICkKewogICAgc3dpdGNoIChwb3J0KSB7CiAgICAgICAgY2FzZSAweDNjODoKICAgICAgICAgICAgcGFscmVnPXZhbDsgcGFsY250PTA7IGJyZWFrOwogICAgICAgIGNhc2UgMHgzYzk6CiAgICAgICAgICAgICgoQllURSopJnBhbGRhdClbcGFsY250KytdPXZhbCA8PCAyOwogICAgICAgICAgICBpZiAocGFsY250PT0zKSB7CiAgICAgICAgICAgICAgICBWR0FfU2V0UGFsZXR0ZSgmcGFsZGF0LHBhbHJlZysrLDEpOwogICAgICAgICAgICAgICAgcGFsY250PTA7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnJlYWs7CiAgICB9Cn0KCkJZVEUgVkdBX2lvcG9ydF9pbiggV09SRCBwb3J0ICkKewogICAgQllURSByZXQ7CgogICAgc3dpdGNoIChwb3J0KSB7CiAgICAgICAgY2FzZSAweDNkYToKICAgICAgICAgICAgLyogc2luY2Ugd2UgZG9uJ3QgKHlldD8pIHNlcnZlIERPUyBWTSByZXF1ZXN0cyB3aGlsZSBWR0FfUG9sbCBpcyBydW5uaW5nLAogICAgICAgICAgICAgICB3ZSBuZWVkIHRvIGZha2UgdGhlIG9jY3VycmVuY2Ugb2YgdGhlIHZlcnRpY2FsIHJlZnJlc2ggKi8KICAgICAgICAgICAgcmV0PXZnYV9yZWZyZXNoPzB4MDA6MHgwODsKICAgICAgICAgICAgdmdhX3JlZnJlc2g9MDsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgcmV0PTB4ZmY7CiAgICB9CiAgICByZXR1cm4gcmV0Owp9Cgp2b2lkIFZHQV9DbGVhbih2b2lkKQp7CiAgICBWR0FfRXhpdCgpOwogICAgVkdBX0RlaW5zdGFsbFRpbWVyKCk7Cn0K