LyoKICogVkdBIGhhcmR3YXJlIGVtdWxhdGlvbgogKiAKICogQ29weXJpZ2h0IDE5OTggT3ZlIEvldmVuICh3aXRoIHNvbWUgaGVscCBmcm9tIE1hcmN1cyBNZWlzc25lcikKICoKICovCgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlICJ3aW5iYXNlLmgiCiNpbmNsdWRlICJ3aW5jb24uaCIKI2luY2x1ZGUgIm1pc2NlbXUuaCIKI2luY2x1ZGUgInZnYS5oIgojaW5jbHVkZSAiZGRyYXcuaCIKI2luY2x1ZGUgInNlcnZpY2VzLmgiCiNpbmNsdWRlICJkZWJ1Z3Rvb2xzLmgiCgpERUZBVUxUX0RFQlVHX0NIQU5ORUwoZGRyYXcpCgpzdGF0aWMgSURpcmVjdERyYXcgKmxwZGRyYXcgPSBOVUxMOwpzdGF0aWMgSURpcmVjdERyYXdTdXJmYWNlICpscGRkc3VyZjsKc3RhdGljIElEaXJlY3REcmF3UGFsZXR0ZSAqbHBkZHBhbDsKc3RhdGljIEREU1VSRkFDRURFU0Mgc2Rlc2M7CnN0YXRpYyBMT05HIHZnYV9wb2xsaW5nLHZnYV9yZWZyZXNoOwpzdGF0aWMgSEFORExFIHBvbGxfdGltZXI7CgpzdGF0aWMgdm9pZCBWR0FfRGVpbnN0YWxsVGltZXIodm9pZCkKewogICAgaWYgKHBvbGxfdGltZXIpIHsKICAgICAgICBTRVJWSUNFX0RlbGV0ZSggcG9sbF90aW1lciApOwogICAgICAgIHBvbGxfdGltZXIgPSAwOwogICAgfQp9CgpzdGF0aWMgdm9pZCBWR0FfSW5zdGFsbFRpbWVyKHVuc2lnbmVkIFJhdGUpCnsKICAgIFZHQV9EZWluc3RhbGxUaW1lcigpOwogICAgaWYgKCFwb2xsX3RpbWVyKQogICAgICAgIHBvbGxfdGltZXIgPSBTRVJWSUNFX0FkZFRpbWVyKCBSYXRlLCBWR0FfUG9sbCwgMCApOwp9CgpIQU5ETEUgVkdBX0FscGhhQ29uc29sZSh2b2lkKQp7CiAgICAvKiB0aGlzIGFzc3VtZXMgdGhhdCBubyBXaW4zMiByZWRpcmVjdGlvbiBoYXMgdGFrZW4gcGxhY2UsIGJ1dCB0aGVuIGFnYWluLAogICAgICogb25seSAxNi1iaXQgYXBwcyBhcmUgbGlrZWx5IHRvIHVzZSB0aGlzIHBhcnQgb2YgV2luZS4uLiAqLwogICAgcmV0dXJuIEdldFN0ZEhhbmRsZShTVERfT1VUUFVUX0hBTkRMRSk7Cn0KCi8qKiogR1JBUEhJQ1MgTU9ERSAqKiovCgppbnQgVkdBX1NldE1vZGUodW5zaWduZWQgWHJlcyx1bnNpZ25lZCBZcmVzLHVuc2lnbmVkIERlcHRoKQp7CiAgICBpZiAobHBkZHJhdykgVkdBX0V4aXQoKTsKICAgIGlmICghbHBkZHJhdykgewogICAgICAgIERpcmVjdERyYXdDcmVhdGUoTlVMTCwmbHBkZHJhdyxOVUxMKTsKICAgICAgICBpZiAoIWxwZGRyYXcpIHsKICAgICAgICAgICAgRVJSKCJEaXJlY3REcmF3IGlzIG5vdCBhdmFpbGFibGVcbiIpOwogICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9CiAgICAgICAgaWYgKElEaXJlY3REcmF3X1NldERpc3BsYXlNb2RlKGxwZGRyYXcsWHJlcyxZcmVzLERlcHRoKSkgewogICAgICAgICAgICBFUlIoIkRpcmVjdERyYXcgZG9lcyBub3Qgc3VwcG9ydCByZXF1ZXN0ZWQgZGlzcGxheSBtb2RlXG4iKTsKICAgICAgICAgICAgSURpcmVjdERyYXdfUmVsZWFzZShscGRkcmF3KTsKICAgICAgICAgICAgbHBkZHJhdz1OVUxMOwogICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9CiAgICAgICAgSURpcmVjdERyYXdfQ3JlYXRlUGFsZXR0ZShscGRkcmF3LEREUENBUFNfOEJJVCxOVUxMLCZscGRkcGFsLE5VTEwpOwogICAgICAgIG1lbXNldCgmc2Rlc2MsMCxzaXplb2Yoc2Rlc2MpKTsKICAgICAgICBzZGVzYy5kd1NpemU9c2l6ZW9mKHNkZXNjKTsKCXNkZXNjLmR3RmxhZ3MgPSBERFNEX0NBUFM7CglzZGVzYy5kZHNDYXBzLmR3Q2FwcyA9IEREU0NBUFNfUFJJTUFSWVNVUkZBQ0U7CiAgICAgICAgaWYgKElEaXJlY3REcmF3X0NyZWF0ZVN1cmZhY2UobHBkZHJhdywmc2Rlc2MsJmxwZGRzdXJmLE5VTEwpfHwoIWxwZGRzdXJmKSkgewogICAgICAgICAgICBFUlIoIkRpcmVjdERyYXcgc3VyZmFjZSBpcyBub3QgYXZhaWxhYmxlXG4iKTsKICAgICAgICAgICAgSURpcmVjdERyYXdfUmVsZWFzZShscGRkcmF3KTsKICAgICAgICAgICAgbHBkZHJhdz1OVUxMOwogICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9CiAgICAgICAgdmdhX3JlZnJlc2g9MDsKICAgICAgICAvKiBwb2xsIGV2ZXJ5IDIwbXMgKDUwZnBzIHNob3VsZCBwcm92aWRlIGFkZXF1YXRlIHJlc3BvbnNpdmVuZXNzKSAqLwogICAgICAgIFZHQV9JbnN0YWxsVGltZXIoMjAwMDApOwogICAgfQogICAgcmV0dXJuIDA7Cn0KCmludCBWR0FfR2V0TW9kZSh1bnNpZ25lZCpIZWlnaHQsdW5zaWduZWQqV2lkdGgsdW5zaWduZWQqRGVwdGgpCnsKICAgIGlmICghbHBkZHJhdykgcmV0dXJuIDE7CiAgICBpZiAoIWxwZGRzdXJmKSByZXR1cm4gMTsKICAgIGlmIChIZWlnaHQpICpIZWlnaHQ9c2Rlc2MuZHdIZWlnaHQ7CiAgICBpZiAoV2lkdGgpICpXaWR0aD1zZGVzYy5kd1dpZHRoOwogICAgaWYgKERlcHRoKSAqRGVwdGg9c2Rlc2MuZGRwZlBpeGVsRm9ybWF0LnUuZHdSR0JCaXRDb3VudDsKICAgIHJldHVybiAwOwp9Cgp2b2lkIFZHQV9FeGl0KHZvaWQpCnsKICAgIGlmIChscGRkcmF3KSB7CiAgICAgICAgVkdBX0RlaW5zdGFsbFRpbWVyKCk7CiAgICAgICAgSURpcmVjdERyYXdTdXJmYWNlX1JlbGVhc2UobHBkZHN1cmYpOwogICAgICAgIGxwZGRzdXJmPU5VTEw7CiAgICAgICAgSURpcmVjdERyYXdfUmVsZWFzZShscGRkcmF3KTsKICAgICAgICBscGRkcmF3PU5VTEw7CiAgICB9Cn0KCnZvaWQgVkdBX1NldFBhbGV0dGUoUEFMRVRURUVOVFJZKnBhbCxpbnQgc3RhcnQsaW50IGxlbikKewogICAgaWYgKCFscGRkcmF3KSByZXR1cm47CiAgICBJRGlyZWN0RHJhd1BhbGV0dGVfU2V0RW50cmllcyhscGRkcGFsLDAsc3RhcnQsbGVuLHBhbCk7CiAgICBJRGlyZWN0RHJhd1N1cmZhY2VfU2V0UGFsZXR0ZShscGRkc3VyZixscGRkcGFsKTsKfQoKdm9pZCBWR0FfU2V0UXVhZFBhbGV0dGUoUkdCUVVBRCpjb2xvcixpbnQgc3RhcnQsaW50IGxlbikKewogICAgUEFMRVRURUVOVFJZIHBhbFsyNTZdOwogICAgaW50IGM7CgogICAgaWYgKCFscGRkcmF3KSByZXR1cm47CiAgICBmb3IgKGM9MDsgYzxsZW47IGMrKykgewogICAgICAgIHBhbFtjXS5wZVJlZCAgPWNvbG9yW2NdLnJnYlJlZDsKICAgICAgICBwYWxbY10ucGVHcmVlbj1jb2xvcltjXS5yZ2JHcmVlbjsKICAgICAgICBwYWxbY10ucGVCbHVlID1jb2xvcltjXS5yZ2JCbHVlOwogICAgICAgIHBhbFtjXS5wZUZsYWdzPTA7CiAgICB9CiAgICBJRGlyZWN0RHJhd1BhbGV0dGVfU2V0RW50cmllcyhscGRkcGFsLDAsc3RhcnQsbGVuLHBhbCk7CiAgICBJRGlyZWN0RHJhd1N1cmZhY2VfU2V0UGFsZXR0ZShscGRkc3VyZixscGRkcGFsKTsKfQoKTFBTVFIgVkdBX0xvY2sodW5zaWduZWQqUGl0Y2gsdW5zaWduZWQqSGVpZ2h0LHVuc2lnbmVkKldpZHRoLHVuc2lnbmVkKkRlcHRoKQp7CiAgICBpZiAoIWxwZGRyYXcpIHJldHVybiBOVUxMOwogICAgaWYgKCFscGRkc3VyZikgcmV0dXJuIE5VTEw7CiAgICBpZiAoSURpcmVjdERyYXdTdXJmYWNlX0xvY2sobHBkZHN1cmYsTlVMTCwmc2Rlc2MsMCwwKSkgewogICAgICAgIEVSUigiY291bGQgbm90IGxvY2sgc3VyZmFjZSFcbiIpOwogICAgICAgIHJldHVybiBOVUxMOwogICAgfQogICAgaWYgKFBpdGNoKSAqUGl0Y2g9c2Rlc2MubFBpdGNoOwogICAgaWYgKEhlaWdodCkgKkhlaWdodD1zZGVzYy5kd0hlaWdodDsKICAgIGlmIChXaWR0aCkgKldpZHRoPXNkZXNjLmR3V2lkdGg7CiAgICBpZiAoRGVwdGgpICpEZXB0aD1zZGVzYy5kZHBmUGl4ZWxGb3JtYXQudS5kd1JHQkJpdENvdW50OwogICAgcmV0dXJuIHNkZXNjLnUxLmxwU3VyZmFjZTsKfQoKdm9pZCBWR0FfVW5sb2NrKHZvaWQpCnsKICAgIElEaXJlY3REcmF3U3VyZmFjZV9VbmxvY2sobHBkZHN1cmYsc2Rlc2MudTEubHBTdXJmYWNlKTsKfQoKLyoqKiBURVhUIE1PREUgKioqLwoKaW50IFZHQV9TZXRBbHBoYU1vZGUodW5zaWduZWQgWHJlcyx1bnNpZ25lZCBZcmVzKQp7CiAgICBDT09SRCBzaXo7CgogICAgaWYgKGxwZGRyYXcpIFZHQV9FeGl0KCk7CgogICAgLyogdGhlIHh0ZXJtIGlzIHNsb3csIHNvIHJlZnJlc2ggb25seSBldmVyeSAyMDBtcyAoNWZwcykgKi8KICAgIFZHQV9JbnN0YWxsVGltZXIoMjAwMDAwKTsKCiAgICBzaXoueCA9IFhyZXM7CiAgICBzaXoueSA9IFlyZXM7CiAgICBTZXRDb25zb2xlU2NyZWVuQnVmZmVyU2l6ZShWR0FfQWxwaGFDb25zb2xlKCksc2l6KTsKICAgIHJldHVybiAwOwp9Cgp2b2lkIFZHQV9HZXRBbHBoYU1vZGUodW5zaWduZWQqWHJlcyx1bnNpZ25lZCpZcmVzKQp7CiAgICBDT05TT0xFX1NDUkVFTl9CVUZGRVJfSU5GTyBpbmZvOwogICAgR2V0Q29uc29sZVNjcmVlbkJ1ZmZlckluZm8oVkdBX0FscGhhQ29uc29sZSgpLCZpbmZvKTsKICAgIGlmIChYcmVzKSAqWHJlcz1pbmZvLmR3U2l6ZS54OwogICAgaWYgKFlyZXMpICpZcmVzPWluZm8uZHdTaXplLnk7Cn0KCnZvaWQgVkdBX1NldEN1cnNvclBvcyh1bnNpZ25lZCBYLHVuc2lnbmVkIFkpCnsKICAgIENPT1JEIHBvczsKICAgIAogICAgcG9zLnggPSBYOwogICAgcG9zLnkgPSBZOwogICAgU2V0Q29uc29sZUN1cnNvclBvc2l0aW9uKFZHQV9BbHBoYUNvbnNvbGUoKSxwb3MpOwp9Cgp2b2lkIFZHQV9HZXRDdXJzb3JQb3ModW5zaWduZWQqWCx1bnNpZ25lZCpZKQp7CiAgICBDT05TT0xFX1NDUkVFTl9CVUZGRVJfSU5GTyBpbmZvOwogICAgR2V0Q29uc29sZVNjcmVlbkJ1ZmZlckluZm8oVkdBX0FscGhhQ29uc29sZSgpLCZpbmZvKTsKICAgIGlmIChYKSAqWD1pbmZvLmR3Q3Vyc29yUG9zaXRpb24ueDsKICAgIGlmIChZKSAqWT1pbmZvLmR3Q3Vyc29yUG9zaXRpb24ueTsKfQoKLyoqKiBDT05UUk9MICoqKi8KCnZvaWQgQ0FMTEJBQ0sgVkdBX1BvbGwoIFVMT05HX1BUUiBhcmcgKQp7CiAgICBjaGFyICpkYXQ7CiAgICB1bnNpZ25lZCBQaXRjaCxIZWlnaHQsV2lkdGg7CiAgICBjaGFyICpzdXJmOwogICAgaW50IFksWDsKCiAgICBpZiAoIUludGVybG9ja2VkRXhjaGFuZ2VBZGQoJnZnYV9wb2xsaW5nLCAxKSkgewogICAgICAgIC8qIEZJWE1FOiBvcHRpbWl6ZSBieSBkb2luZyB0aGlzIG9ubHkgaWYgdGhlIGRhdGEgaGFzIGFjdHVhbGx5IGNoYW5nZWQKICAgICAgICAgKiAgICAgICAgKGluIGEgd2F5IHNpbWlsYXIgdG8gRElCU2VjdGlvbiwgcGVyaGFwcykgKi8KICAgICAgICBpZiAobHBkZHJhdykgewogICAgICAgICAgLyogZ3JhcGhpY3MgbW9kZSAqLwogICAgICAgICAgc3VyZiA9IFZHQV9Mb2NrKCZQaXRjaCwmSGVpZ2h0LCZXaWR0aCxOVUxMKTsKICAgICAgICAgIGlmICghc3VyZikgcmV0dXJuOwogICAgICAgICAgZGF0ID0gRE9TTUVNX01hcERvc1RvTGluZWFyKDB4YTAwMDApOwogICAgICAgICAgLyogY29weSBmcm9tIHZpcnR1YWwgVkdBIGZyYW1lIGJ1ZmZlciB0byBEaXJlY3REcmF3IHN1cmZhY2UgKi8KICAgICAgICAgIGZvciAoWT0wOyBZPEhlaWdodDsgWSsrLHN1cmYrPVBpdGNoLGRhdCs9V2lkdGgpIHsKICAgICAgICAgICAgICBtZW1jcHkoc3VyZixkYXQsV2lkdGgpOwogICAgICAgICAgICAgIC8qZm9yIChYPTA7IFg8V2lkdGg7IFgrKykgaWYgKGRhdFtYXSkgVFJBQ0UoZGRyYXcsImRhdGEoJWQpIGF0ICglZCwlZClcbiIsZGF0W1hdLFgsWSk7Ki8KICAgICAgICAgIH0KICAgICAgICAgIFZHQV9VbmxvY2soKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgLyogdGV4dCBtb2RlICovCiAgICAgICAgICBDSEFSX0lORk8gY2hbODBdOwogICAgICAgICAgQ09PUkQgc2l6LCBvZmY7CiAgICAgICAgICBTTUFMTF9SRUNUIGRlc3Q7CiAgICAgICAgICBIQU5ETEUgY29uID0gVkdBX0FscGhhQ29uc29sZSgpOwoKICAgICAgICAgIFZHQV9HZXRBbHBoYU1vZGUoJldpZHRoLCZIZWlnaHQpOwogICAgICAgICAgZGF0ID0gRE9TTUVNX01hcERvc1RvTGluZWFyKDB4YjgwMDApOwogICAgICAgICAgc2l6LnggPSA4MDsgc2l6LnkgPSAxOwogICAgICAgICAgb2ZmLnggPSAwOyBvZmYueSA9IDA7CiAgICAgICAgICAvKiBjb3B5IGZyb20gdmlydHVhbCBWR0EgZnJhbWUgYnVmZmVyIHRvIGNvbnNvbGUgKi8KICAgICAgICAgIGZvciAoWT0wOyBZPEhlaWdodDsgWSsrKSB7CiAgICAgICAgICAgICAgZGVzdC5Ub3A9WTsgZGVzdC5Cb3R0b209WTsKICAgICAgICAgICAgICBmb3IgKFg9MDsgWDxXaWR0aDsgWCsrKSB7CiAgICAgICAgICAgICAgICAgIGNoW1hdLkNoYXIuQXNjaWlDaGFyID0gKmRhdCsrOwogICAgICAgICAgICAgICAgICBjaFtYXS5BdHRyaWJ1dGVzID0gKmRhdCsrOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBkZXN0LkxlZnQ9MDsgZGVzdC5SaWdodD1XaWR0aCsxOwogICAgICAgICAgICAgIFdyaXRlQ29uc29sZU91dHB1dEEoY29uLCBjaCwgc2l6LCBvZmYsICZkZXN0KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgdmdhX3JlZnJlc2g9MTsKICAgIH0KICAgIEludGVybG9ja2VkRGVjcmVtZW50KCZ2Z2FfcG9sbGluZyk7Cn0KCnN0YXRpYyBCWVRFIHBhbHJlZyxwYWxjbnQ7CnN0YXRpYyBQQUxFVFRFRU5UUlkgcGFsZGF0OwoKdm9pZCBWR0FfaW9wb3J0X291dCggV09SRCBwb3J0LCBCWVRFIHZhbCApCnsKICAgIHN3aXRjaCAocG9ydCkgewogICAgICAgIGNhc2UgMHgzYzg6CiAgICAgICAgICAgIHBhbHJlZz12YWw7IHBhbGNudD0wOyBicmVhazsKICAgICAgICBjYXNlIDB4M2M5OgogICAgICAgICAgICAoKEJZVEUqKSZwYWxkYXQpW3BhbGNudCsrXT12YWwgPDwgMjsKICAgICAgICAgICAgaWYgKHBhbGNudD09MykgewogICAgICAgICAgICAgICAgVkdBX1NldFBhbGV0dGUoJnBhbGRhdCxwYWxyZWcrKywxKTsKICAgICAgICAgICAgICAgIHBhbGNudD0wOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgfQp9CgpCWVRFIFZHQV9pb3BvcnRfaW4oIFdPUkQgcG9ydCApCnsKICAgIEJZVEUgcmV0OwoKICAgIHN3aXRjaCAocG9ydCkgewogICAgICAgIGNhc2UgMHgzZGE6CiAgICAgICAgICAgIC8qIHNpbmNlIHdlIGRvbid0ICh5ZXQ/KSBzZXJ2ZSBET1MgVk0gcmVxdWVzdHMgd2hpbGUgVkdBX1BvbGwgaXMgcnVubmluZywKICAgICAgICAgICAgICAgd2UgbmVlZCB0byBmYWtlIHRoZSBvY2N1cnJlbmNlIG9mIHRoZSB2ZXJ0aWNhbCByZWZyZXNoICovCiAgICAgICAgICAgIHJldD12Z2FfcmVmcmVzaD8weDAwOjB4MDg7CiAgICAgICAgICAgIHZnYV9yZWZyZXNoPTA7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHJldD0weGZmOwogICAgfQogICAgcmV0dXJuIHJldDsKfQoKdm9pZCBWR0FfQ2xlYW4odm9pZCkKewogICAgVkdBX0V4aXQoKTsKICAgIFZHQV9EZWluc3RhbGxUaW1lcigpOwp9Cg==