LyoKICogVkdBIGhhcmR3YXJlIGVtdWxhdGlvbgogKiAKICogQ29weXJpZ2h0IDE5OTggT3ZlIEvldmVuICh3aXRoIHNvbWUgaGVscCBmcm9tIE1hcmN1cyBNZWlzc25lcikKICoKICovCgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlICJ3aW5iYXNlLmgiCiNpbmNsdWRlICJ3aW5jb24uaCIKI2luY2x1ZGUgIm1pc2NlbXUuaCIKI2luY2x1ZGUgInZnYS5oIgojaW5jbHVkZSAiZGRyYXcuaCIKI2luY2x1ZGUgInNlcnZpY2VzLmgiCiNpbmNsdWRlICJkZWJ1Z3Rvb2xzLmgiCgpERUZBVUxUX0RFQlVHX0NIQU5ORUwoZGRyYXcpOwoKc3RhdGljIElEaXJlY3REcmF3ICpscGRkcmF3ID0gTlVMTDsKc3RhdGljIElEaXJlY3REcmF3U3VyZmFjZSAqbHBkZHN1cmY7CnN0YXRpYyBJRGlyZWN0RHJhd1BhbGV0dGUgKmxwZGRwYWw7CnN0YXRpYyBERFNVUkZBQ0VERVNDIHNkZXNjOwpzdGF0aWMgTE9ORyB2Z2FfcG9sbGluZyx2Z2FfcmVmcmVzaDsKc3RhdGljIEhBTkRMRSBwb2xsX3RpbWVyOwoKc3RhdGljIEhSRVNVTFQgV0lOQVBJICgqcERpcmVjdERyYXdDcmVhdGUpKExQR1VJRCxMUERJUkVDVERSQVcgKixMUFVOS05PV04pOwoKc3RhdGljIHZvaWQgVkdBX0RlaW5zdGFsbFRpbWVyKHZvaWQpCnsKICAgIGlmIChwb2xsX3RpbWVyKSB7CiAgICAgICAgU0VSVklDRV9EZWxldGUoIHBvbGxfdGltZXIgKTsKICAgICAgICBwb2xsX3RpbWVyID0gMDsKICAgIH0KfQoKc3RhdGljIHZvaWQgVkdBX0luc3RhbGxUaW1lcih1bnNpZ25lZCBSYXRlKQp7CiAgICBWR0FfRGVpbnN0YWxsVGltZXIoKTsKICAgIGlmICghcG9sbF90aW1lcikKICAgICAgICBwb2xsX3RpbWVyID0gU0VSVklDRV9BZGRUaW1lciggUmF0ZSwgVkdBX1BvbGwsIDAgKTsKfQoKSEFORExFIFZHQV9BbHBoYUNvbnNvbGUodm9pZCkKewogICAgLyogdGhpcyBhc3N1bWVzIHRoYXQgbm8gV2luMzIgcmVkaXJlY3Rpb24gaGFzIHRha2VuIHBsYWNlLCBidXQgdGhlbiBhZ2FpbiwKICAgICAqIG9ubHkgMTYtYml0IGFwcHMgYXJlIGxpa2VseSB0byB1c2UgdGhpcyBwYXJ0IG9mIFdpbmUuLi4gKi8KICAgIHJldHVybiBHZXRTdGRIYW5kbGUoU1REX09VVFBVVF9IQU5ETEUpOwp9CgpjaGFyKlZHQV9BbHBoYUJ1ZmZlcih2b2lkKQp7CiAgICByZXR1cm4gRE9TTUVNX01hcERvc1RvTGluZWFyKDB4YjgwMDApOwp9CgovKioqIEdSQVBISUNTIE1PREUgKioqLwoKaW50IFZHQV9TZXRNb2RlKHVuc2lnbmVkIFhyZXMsdW5zaWduZWQgWXJlcyx1bnNpZ25lZCBEZXB0aCkKewogICAgaWYgKGxwZGRyYXcpIFZHQV9FeGl0KCk7CiAgICBpZiAoIWxwZGRyYXcpIHsKICAgICAgICBpZiAoIXBEaXJlY3REcmF3Q3JlYXRlKQogICAgICAgIHsKICAgICAgICAgICAgSE1PRFVMRSBobW9kID0gTG9hZExpYnJhcnlBKCAiZGRyYXcuZGxsIiApOwogICAgICAgICAgICBpZiAoaG1vZCkgcERpcmVjdERyYXdDcmVhdGUgPSBHZXRQcm9jQWRkcmVzcyggaG1vZCwgIkRpcmVjdERyYXdDcmVhdGUiICk7CiAgICAgICAgfQogICAgICAgIGlmIChwRGlyZWN0RHJhd0NyZWF0ZSkgcERpcmVjdERyYXdDcmVhdGUoTlVMTCwmbHBkZHJhdyxOVUxMKTsKICAgICAgICBpZiAoIWxwZGRyYXcpIHsKICAgICAgICAgICAgRVJSKCJEaXJlY3REcmF3IGlzIG5vdCBhdmFpbGFibGVcbiIpOwogICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9CiAgICAgICAgaWYgKElEaXJlY3REcmF3X1NldERpc3BsYXlNb2RlKGxwZGRyYXcsWHJlcyxZcmVzLERlcHRoKSkgewogICAgICAgICAgICBFUlIoIkRpcmVjdERyYXcgZG9lcyBub3Qgc3VwcG9ydCByZXF1ZXN0ZWQgZGlzcGxheSBtb2RlXG4iKTsKICAgICAgICAgICAgSURpcmVjdERyYXdfUmVsZWFzZShscGRkcmF3KTsKICAgICAgICAgICAgbHBkZHJhdz1OVUxMOwogICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9CiAgICAgICAgSURpcmVjdERyYXdfQ3JlYXRlUGFsZXR0ZShscGRkcmF3LEREUENBUFNfOEJJVCxOVUxMLCZscGRkcGFsLE5VTEwpOwogICAgICAgIG1lbXNldCgmc2Rlc2MsMCxzaXplb2Yoc2Rlc2MpKTsKICAgICAgICBzZGVzYy5kd1NpemU9c2l6ZW9mKHNkZXNjKTsKCXNkZXNjLmR3RmxhZ3MgPSBERFNEX0NBUFM7CglzZGVzYy5kZHNDYXBzLmR3Q2FwcyA9IEREU0NBUFNfUFJJTUFSWVNVUkZBQ0U7CiAgICAgICAgaWYgKElEaXJlY3REcmF3X0NyZWF0ZVN1cmZhY2UobHBkZHJhdywmc2Rlc2MsJmxwZGRzdXJmLE5VTEwpfHwoIWxwZGRzdXJmKSkgewogICAgICAgICAgICBFUlIoIkRpcmVjdERyYXcgc3VyZmFjZSBpcyBub3QgYXZhaWxhYmxlXG4iKTsKICAgICAgICAgICAgSURpcmVjdERyYXdfUmVsZWFzZShscGRkcmF3KTsKICAgICAgICAgICAgbHBkZHJhdz1OVUxMOwogICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9CiAgICAgICAgRklYTUUoIm5vIGRlZmF1bHQgcGFsZXR0ZSBlbnRyaWVzXG4iKTsKICAgICAgICBJRGlyZWN0RHJhd1N1cmZhY2VfU2V0UGFsZXR0ZShscGRkc3VyZixscGRkcGFsKTsKICAgICAgICB2Z2FfcmVmcmVzaD0wOwogICAgICAgIC8qIHBvbGwgZXZlcnkgMjBtcyAoNTBmcHMgc2hvdWxkIHByb3ZpZGUgYWRlcXVhdGUgcmVzcG9uc2l2ZW5lc3MpICovCiAgICAgICAgVkdBX0luc3RhbGxUaW1lcigyMCk7CiAgICB9CiAgICByZXR1cm4gMDsKfQoKaW50IFZHQV9HZXRNb2RlKHVuc2lnbmVkKkhlaWdodCx1bnNpZ25lZCpXaWR0aCx1bnNpZ25lZCpEZXB0aCkKewogICAgaWYgKCFscGRkcmF3KSByZXR1cm4gMTsKICAgIGlmICghbHBkZHN1cmYpIHJldHVybiAxOwogICAgaWYgKEhlaWdodCkgKkhlaWdodD1zZGVzYy5kd0hlaWdodDsKICAgIGlmIChXaWR0aCkgKldpZHRoPXNkZXNjLmR3V2lkdGg7CiAgICBpZiAoRGVwdGgpICpEZXB0aD1zZGVzYy5kZHBmUGl4ZWxGb3JtYXQudS5kd1JHQkJpdENvdW50OwogICAgcmV0dXJuIDA7Cn0KCnZvaWQgVkdBX0V4aXQodm9pZCkKewogICAgaWYgKGxwZGRyYXcpIHsKICAgICAgICBWR0FfRGVpbnN0YWxsVGltZXIoKTsKICAgICAgICBJRGlyZWN0RHJhd1N1cmZhY2VfU2V0UGFsZXR0ZShscGRkc3VyZixOVUxMKTsKICAgICAgICBJRGlyZWN0RHJhd1N1cmZhY2VfUmVsZWFzZShscGRkc3VyZik7CiAgICAgICAgbHBkZHN1cmY9TlVMTDsKICAgICAgICBJRGlyZWN0RHJhd1BhbGV0dGVfUmVsZWFzZShscGRkcGFsKTsKICAgICAgICBscGRkcGFsPU5VTEw7CiAgICAgICAgSURpcmVjdERyYXdfUmVsZWFzZShscGRkcmF3KTsKICAgICAgICBscGRkcmF3PU5VTEw7CiAgICB9Cn0KCnZvaWQgVkdBX1NldFBhbGV0dGUoUEFMRVRURUVOVFJZKnBhbCxpbnQgc3RhcnQsaW50IGxlbikKewogICAgaWYgKCFscGRkcmF3KSByZXR1cm47CiAgICBJRGlyZWN0RHJhd1BhbGV0dGVfU2V0RW50cmllcyhscGRkcGFsLDAsc3RhcnQsbGVuLHBhbCk7Cn0KCnZvaWQgVkdBX1NldFF1YWRQYWxldHRlKFJHQlFVQUQqY29sb3IsaW50IHN0YXJ0LGludCBsZW4pCnsKICAgIFBBTEVUVEVFTlRSWSBwYWxbMjU2XTsKICAgIGludCBjOwoKICAgIGlmICghbHBkZHJhdykgcmV0dXJuOwogICAgZm9yIChjPTA7IGM8bGVuOyBjKyspIHsKICAgICAgICBwYWxbY10ucGVSZWQgID1jb2xvcltjXS5yZ2JSZWQ7CiAgICAgICAgcGFsW2NdLnBlR3JlZW49Y29sb3JbY10ucmdiR3JlZW47CiAgICAgICAgcGFsW2NdLnBlQmx1ZSA9Y29sb3JbY10ucmdiQmx1ZTsKICAgICAgICBwYWxbY10ucGVGbGFncz0wOwogICAgfQogICAgSURpcmVjdERyYXdQYWxldHRlX1NldEVudHJpZXMobHBkZHBhbCwwLHN0YXJ0LGxlbixwYWwpOwp9CgpMUFNUUiBWR0FfTG9jayh1bnNpZ25lZCpQaXRjaCx1bnNpZ25lZCpIZWlnaHQsdW5zaWduZWQqV2lkdGgsdW5zaWduZWQqRGVwdGgpCnsKICAgIGlmICghbHBkZHJhdykgcmV0dXJuIE5VTEw7CiAgICBpZiAoIWxwZGRzdXJmKSByZXR1cm4gTlVMTDsKICAgIGlmIChJRGlyZWN0RHJhd1N1cmZhY2VfTG9jayhscGRkc3VyZixOVUxMLCZzZGVzYywwLDApKSB7CiAgICAgICAgRVJSKCJjb3VsZCBub3QgbG9jayBzdXJmYWNlIVxuIik7CiAgICAgICAgcmV0dXJuIE5VTEw7CiAgICB9CiAgICBpZiAoUGl0Y2gpICpQaXRjaD1zZGVzYy5sUGl0Y2g7CiAgICBpZiAoSGVpZ2h0KSAqSGVpZ2h0PXNkZXNjLmR3SGVpZ2h0OwogICAgaWYgKFdpZHRoKSAqV2lkdGg9c2Rlc2MuZHdXaWR0aDsKICAgIGlmIChEZXB0aCkgKkRlcHRoPXNkZXNjLmRkcGZQaXhlbEZvcm1hdC51LmR3UkdCQml0Q291bnQ7CiAgICByZXR1cm4gc2Rlc2MudTEubHBTdXJmYWNlOwp9Cgp2b2lkIFZHQV9VbmxvY2sodm9pZCkKewogICAgSURpcmVjdERyYXdTdXJmYWNlX1VubG9jayhscGRkc3VyZixzZGVzYy51MS5scFN1cmZhY2UpOwp9CgovKioqIFRFWFQgTU9ERSAqKiovCgppbnQgVkdBX1NldEFscGhhTW9kZSh1bnNpZ25lZCBYcmVzLHVuc2lnbmVkIFlyZXMpCnsKICAgIENPT1JEIHNpejsKCiAgICBpZiAobHBkZHJhdykgVkdBX0V4aXQoKTsKCiAgICAvKiB0aGUgeHRlcm0gaXMgc2xvdywgc28gcmVmcmVzaCBvbmx5IGV2ZXJ5IDIwMG1zICg1ZnBzKSAqLwogICAgVkdBX0luc3RhbGxUaW1lcigyMDApOwoKICAgIHNpei5YID0gWHJlczsKICAgIHNpei5ZID0gWXJlczsKICAgIFNldENvbnNvbGVTY3JlZW5CdWZmZXJTaXplKFZHQV9BbHBoYUNvbnNvbGUoKSxzaXopOwogICAgcmV0dXJuIDA7Cn0KCnZvaWQgVkdBX0dldEFscGhhTW9kZSh1bnNpZ25lZCpYcmVzLHVuc2lnbmVkKllyZXMpCnsKICAgIENPTlNPTEVfU0NSRUVOX0JVRkZFUl9JTkZPIGluZm87CiAgICBHZXRDb25zb2xlU2NyZWVuQnVmZmVySW5mbyhWR0FfQWxwaGFDb25zb2xlKCksJmluZm8pOwogICAgaWYgKFhyZXMpICpYcmVzPWluZm8uZHdTaXplLlg7CiAgICBpZiAoWXJlcykgKllyZXM9aW5mby5kd1NpemUuWTsKfQoKdm9pZCBWR0FfU2V0Q3Vyc29yUG9zKHVuc2lnbmVkIFgsdW5zaWduZWQgWSkKewogICAgQ09PUkQgcG9zOwogICAgCiAgICBwb3MuWCA9IFg7CiAgICBwb3MuWSA9IFk7CiAgICBTZXRDb25zb2xlQ3Vyc29yUG9zaXRpb24oVkdBX0FscGhhQ29uc29sZSgpLHBvcyk7Cn0KCnZvaWQgVkdBX0dldEN1cnNvclBvcyh1bnNpZ25lZCpYLHVuc2lnbmVkKlkpCnsKICAgIENPTlNPTEVfU0NSRUVOX0JVRkZFUl9JTkZPIGluZm87CiAgICBHZXRDb25zb2xlU2NyZWVuQnVmZmVySW5mbyhWR0FfQWxwaGFDb25zb2xlKCksJmluZm8pOwogICAgaWYgKFgpICpYPWluZm8uZHdDdXJzb3JQb3NpdGlvbi5YOwogICAgaWYgKFkpICpZPWluZm8uZHdDdXJzb3JQb3NpdGlvbi5ZOwp9Cgp2b2lkIFZHQV9Xcml0ZUNoYXJzKHVuc2lnbmVkIFgsdW5zaWduZWQgWSx1bnNpZ25lZCBjaCxpbnQgYXR0cixpbnQgY291bnQpCnsKICAgIHVuc2lnbmVkIFhSLCBZUjsKICAgIGNoYXIqZGF0OwoKICAgIFZHQV9HZXRBbHBoYU1vZGUoJlhSLCAmWVIpOwogICAgZGF0ID0gVkdBX0FscGhhQnVmZmVyKCkgKyAoKFhSKlkgKyBYKSAqIDIpOwogICAgLyogRklYTUU6IGFsc28gY2FsbCBXcml0ZUNvbnNvbGVPdXRwdXRBLCBmb3IgYmV0dGVyIHJlc3BvbnNpdmVuZXNzICovCiAgICB3aGlsZSAoY291bnQtLSkgewogICAgICAgICpkYXQrKyA9IGNoOwogICAgICAgIGlmIChhdHRyPj0wKSAqZGF0ID0gYXR0cjsKICAgICAgICBkYXQrKzsKICAgIH0KfQoKLyoqKiBDT05UUk9MICoqKi8KCnZvaWQgQ0FMTEJBQ0sgVkdBX1BvbGwoIFVMT05HX1BUUiBhcmcgKQp7CiAgICBjaGFyICpkYXQ7CiAgICB1bnNpZ25lZCBpbnQgUGl0Y2gsSGVpZ2h0LFdpZHRoLFksWDsKICAgIGNoYXIgKnN1cmY7CgogICAgaWYgKCFJbnRlcmxvY2tlZEV4Y2hhbmdlQWRkKCZ2Z2FfcG9sbGluZywgMSkpIHsKICAgICAgICAvKiBGSVhNRTogb3B0aW1pemUgYnkgZG9pbmcgdGhpcyBvbmx5IGlmIHRoZSBkYXRhIGhhcyBhY3R1YWxseSBjaGFuZ2VkCiAgICAgICAgICogICAgICAgIChpbiBhIHdheSBzaW1pbGFyIHRvIERJQlNlY3Rpb24sIHBlcmhhcHMpICovCiAgICAgICAgaWYgKGxwZGRyYXcpIHsKICAgICAgICAgIC8qIGdyYXBoaWNzIG1vZGUgKi8KICAgICAgICAgIHN1cmYgPSBWR0FfTG9jaygmUGl0Y2gsJkhlaWdodCwmV2lkdGgsTlVMTCk7CiAgICAgICAgICBpZiAoIXN1cmYpIHJldHVybjsKICAgICAgICAgIGRhdCA9IERPU01FTV9NYXBEb3NUb0xpbmVhcigweGEwMDAwKTsKICAgICAgICAgIC8qIGNvcHkgZnJvbSB2aXJ0dWFsIFZHQSBmcmFtZSBidWZmZXIgdG8gRGlyZWN0RHJhdyBzdXJmYWNlICovCiAgICAgICAgICBmb3IgKFk9MDsgWTxIZWlnaHQ7IFkrKyxzdXJmKz1QaXRjaCxkYXQrPVdpZHRoKSB7CiAgICAgICAgICAgICAgbWVtY3B5KHN1cmYsZGF0LFdpZHRoKTsKICAgICAgICAgICAgICAvKmZvciAoWD0wOyBYPFdpZHRoOyBYKyspIGlmIChkYXRbWF0pIFRSQUNFKGRkcmF3LCJkYXRhKCVkKSBhdCAoJWQsJWQpXG4iLGRhdFtYXSxYLFkpOyovCiAgICAgICAgICB9CiAgICAgICAgICBWR0FfVW5sb2NrKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIC8qIHRleHQgbW9kZSAqLwogICAgICAgICAgQ0hBUl9JTkZPIGNoWzgwXTsKICAgICAgICAgIENPT1JEIHNpeiwgb2ZmOwogICAgICAgICAgU01BTExfUkVDVCBkZXN0OwogICAgICAgICAgSEFORExFIGNvbiA9IFZHQV9BbHBoYUNvbnNvbGUoKTsKCiAgICAgICAgICBWR0FfR2V0QWxwaGFNb2RlKCZXaWR0aCwmSGVpZ2h0KTsKICAgICAgICAgIGRhdCA9IFZHQV9BbHBoYUJ1ZmZlcigpOwogICAgICAgICAgc2l6LlggPSA4MDsgc2l6LlkgPSAxOwogICAgICAgICAgb2ZmLlggPSAwOyBvZmYuWSA9IDA7CiAgICAgICAgICAvKiBjb3B5IGZyb20gdmlydHVhbCBWR0EgZnJhbWUgYnVmZmVyIHRvIGNvbnNvbGUgKi8KICAgICAgICAgIGZvciAoWT0wOyBZPEhlaWdodDsgWSsrKSB7CiAgICAgICAgICAgICAgZGVzdC5Ub3A9WTsgZGVzdC5Cb3R0b209WTsKICAgICAgICAgICAgICBmb3IgKFg9MDsgWDxXaWR0aDsgWCsrKSB7CiAgICAgICAgICAgICAgICAgIGNoW1hdLkNoYXIuQXNjaWlDaGFyID0gKmRhdCsrOwoJCSAgLyogV3JpdGVDb25zb2xlT3V0cHV0QSBkb2Vzbid0IGxpa2UgImRlYWQiIGNoYXJzICovCgkJICBpZiAoY2hbWF0uQ2hhci5Bc2NpaUNoYXIgPT0gJ1wwJykKCQkgICAgICBjaFtYXS5DaGFyLkFzY2lpQ2hhciA9ICcgJzsKICAgICAgICAgICAgICAgICAgY2hbWF0uQXR0cmlidXRlcyA9ICpkYXQrKzsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgZGVzdC5MZWZ0PTA7IGRlc3QuUmlnaHQ9V2lkdGgrMTsKICAgICAgICAgICAgICBXcml0ZUNvbnNvbGVPdXRwdXRBKGNvbiwgY2gsIHNpeiwgb2ZmLCAmZGVzdCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHZnYV9yZWZyZXNoPTE7CiAgICB9CiAgICBJbnRlcmxvY2tlZERlY3JlbWVudCgmdmdhX3BvbGxpbmcpOwp9CgpzdGF0aWMgQllURSBwYWxyZWcscGFsY250OwpzdGF0aWMgUEFMRVRURUVOVFJZIHBhbGRhdDsKCnZvaWQgVkdBX2lvcG9ydF9vdXQoIFdPUkQgcG9ydCwgQllURSB2YWwgKQp7CiAgICBzd2l0Y2ggKHBvcnQpIHsKICAgICAgICBjYXNlIDB4M2M4OgogICAgICAgICAgICBwYWxyZWc9dmFsOyBwYWxjbnQ9MDsgYnJlYWs7CiAgICAgICAgY2FzZSAweDNjOToKICAgICAgICAgICAgKChCWVRFKikmcGFsZGF0KVtwYWxjbnQrK109dmFsIDw8IDI7CiAgICAgICAgICAgIGlmIChwYWxjbnQ9PTMpIHsKICAgICAgICAgICAgICAgIFZHQV9TZXRQYWxldHRlKCZwYWxkYXQscGFscmVnKyssMSk7CiAgICAgICAgICAgICAgICBwYWxjbnQ9MDsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgIH0KfQoKQllURSBWR0FfaW9wb3J0X2luKCBXT1JEIHBvcnQgKQp7CiAgICBCWVRFIHJldDsKCiAgICBzd2l0Y2ggKHBvcnQpIHsKICAgICAgICBjYXNlIDB4M2RhOgogICAgICAgICAgICAvKiBzaW5jZSB3ZSBkb24ndCAoeWV0Pykgc2VydmUgRE9TIFZNIHJlcXVlc3RzIHdoaWxlIFZHQV9Qb2xsIGlzIHJ1bm5pbmcsCiAgICAgICAgICAgICAgIHdlIG5lZWQgdG8gZmFrZSB0aGUgb2NjdXJyZW5jZSBvZiB0aGUgdmVydGljYWwgcmVmcmVzaCAqLwogICAgICAgICAgICByZXQ9dmdhX3JlZnJlc2g/MHgwMDoweDA4OwogICAgICAgICAgICB2Z2FfcmVmcmVzaD0wOwogICAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICByZXQ9MHhmZjsKICAgIH0KICAgIHJldHVybiByZXQ7Cn0KCnZvaWQgVkdBX0NsZWFuKHZvaWQpCnsKICAgIFZHQV9FeGl0KCk7CiAgICBWR0FfRGVpbnN0YWxsVGltZXIoKTsKfQo=