LyoKICogVkdBIGhhcmR3YXJlIGVtdWxhdGlvbgogKiAKICogQ29weXJpZ2h0IDE5OTggT3ZlIEvldmVuICh3aXRoIHNvbWUgaGVscCBmcm9tIE1hcmN1cyBNZWlzc25lcikKICoKICovCgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlICJ3aW5kb3dzLmgiCiNpbmNsdWRlICJ3aW5iYXNlLmgiCiNpbmNsdWRlICJtaXNjZW11LmgiCiNpbmNsdWRlICJ2Z2EuaCIKI2luY2x1ZGUgImRkcmF3LmgiCiNpbmNsdWRlICJkZWJ1Zy5oIgoKc3RhdGljIElEaXJlY3REcmF3ICpscGRkcmF3ID0gTlVMTDsKc3RhdGljIElEaXJlY3REcmF3U3VyZmFjZSAqbHBkZHN1cmY7CnN0YXRpYyBJRGlyZWN0RHJhd1BhbGV0dGUgKmxwZGRwYWw7CnN0YXRpYyBERFNVUkZBQ0VERVNDIHNkZXNjOwpzdGF0aWMgV09SRCBwb2xsX3RpbWVyOwpzdGF0aWMgQ1JJVElDQUxfU0VDVElPTiB2Z2FfY3JpdDsKc3RhdGljIGludCB2Z2FfcG9sbGluZyx2Z2FfcmVmcmVzaDsKCmludCBWR0FfU2V0TW9kZSh1bnNpZ25lZCBYcmVzLHVuc2lnbmVkIFlyZXMsdW5zaWduZWQgRGVwdGgpCnsKICAgIGlmIChscGRkcmF3KSBWR0FfRXhpdCgpOwogICAgaWYgKCFscGRkcmF3KSB7CiAgICAgICAgRGlyZWN0RHJhd0NyZWF0ZShOVUxMLCZscGRkcmF3LE5VTEwpOwogICAgICAgIGlmICghbHBkZHJhdykgewogICAgICAgICAgICBFUlIoZGRyYXcsIkRpcmVjdERyYXcgaXMgbm90IGF2YWlsYWJsZVxuIik7CiAgICAgICAgICAgIHJldHVybiAxOwogICAgICAgIH0KICAgICAgICBpZiAobHBkZHJhdy0+bHB2dGJsLT5mblNldERpc3BsYXlNb2RlKGxwZGRyYXcsWHJlcyxZcmVzLERlcHRoKSkgewogICAgICAgICAgICBFUlIoZGRyYXcsIkRpcmVjdERyYXcgZG9lcyBub3Qgc3VwcG9ydCByZXF1ZXN0ZWQgZGlzcGxheSBtb2RlXG4iKTsKICAgICAgICAgICAgbHBkZHJhdy0+bHB2dGJsLT5mblJlbGVhc2UobHBkZHJhdyk7CiAgICAgICAgICAgIGxwZGRyYXc9TlVMTDsKICAgICAgICAgICAgcmV0dXJuIDE7CiAgICAgICAgfQogICAgICAgIGxwZGRyYXctPmxwdnRibC0+Zm5DcmVhdGVQYWxldHRlKGxwZGRyYXcsMCxOVUxMLCZscGRkcGFsLE5VTEwpOwogICAgICAgIG1lbXNldCgmc2Rlc2MsMCxzaXplb2Yoc2Rlc2MpKTsKICAgICAgICBzZGVzYy5kd1NpemU9c2l6ZW9mKHNkZXNjKTsKICAgICAgICBpZiAobHBkZHJhdy0+bHB2dGJsLT5mbkNyZWF0ZVN1cmZhY2UobHBkZHJhdywmc2Rlc2MsJmxwZGRzdXJmLE5VTEwpfHwoIWxwZGRzdXJmKSkgewogICAgICAgICAgICBFUlIoZGRyYXcsIkRpcmVjdERyYXcgc3VyZmFjZSBpcyBub3QgYXZhaWxhYmxlXG4iKTsKICAgICAgICAgICAgbHBkZHJhdy0+bHB2dGJsLT5mblJlbGVhc2UobHBkZHJhdyk7CiAgICAgICAgICAgIGxwZGRyYXc9TlVMTDsKICAgICAgICAgICAgcmV0dXJuIDE7CiAgICAgICAgfQogICAgICAgIHZnYV9yZWZyZXNoPTA7CiAgICAgICAgSW5pdGlhbGl6ZUNyaXRpY2FsU2VjdGlvbigmdmdhX2NyaXQpOwogICAgICAgIE1ha2VDcml0aWNhbFNlY3Rpb25HbG9iYWwoJnZnYV9jcml0KTsKICAgICAgICAvKiBwb2xsIGV2ZXJ5IDIwbXMgKDUwZnBzIHNob3VsZCBwcm92aWRlIGFkZXF1YXRlIHJlc3BvbnNpdmVuZXNzKSAqLwogICAgICAgIHBvbGxfdGltZXIgPSBDcmVhdGVTeXN0ZW1UaW1lciggMjAsIFZHQV9Qb2xsICk7CiAgICB9CiAgICByZXR1cm4gMDsKfQoKaW50IFZHQV9HZXRNb2RlKHVuc2lnbmVkKkhlaWdodCx1bnNpZ25lZCpXaWR0aCx1bnNpZ25lZCpEZXB0aCkKewogICAgaWYgKCFscGRkcmF3KSByZXR1cm4gMTsKICAgIGlmICghbHBkZHN1cmYpIHJldHVybiAxOwogICAgaWYgKEhlaWdodCkgKkhlaWdodD1zZGVzYy5kd0hlaWdodDsKICAgIGlmIChXaWR0aCkgKldpZHRoPXNkZXNjLmR3V2lkdGg7CiAgICBpZiAoRGVwdGgpICpEZXB0aD1zZGVzYy5kZHBmUGl4ZWxGb3JtYXQueC5kd1JHQkJpdENvdW50OwogICAgcmV0dXJuIDA7Cn0KCnZvaWQgVkdBX0V4aXQodm9pZCkKewogICAgaWYgKGxwZGRyYXcpIHsKICAgICAgICBTWVNURU1fS2lsbFN5c3RlbVRpbWVyKHBvbGxfdGltZXIpOwogICAgICAgIERlbGV0ZUNyaXRpY2FsU2VjdGlvbigmdmdhX2NyaXQpOwogICAgICAgIGxwZGRzdXJmLT5scHZ0YmwtPmZuUmVsZWFzZShscGRkc3VyZik7CiAgICAgICAgbHBkZHN1cmY9TlVMTDsKICAgICAgICBscGRkcmF3LT5scHZ0YmwtPmZuUmVsZWFzZShscGRkcmF3KTsKICAgICAgICBscGRkcmF3PU5VTEw7CiAgICB9Cn0KCnZvaWQgVkdBX1NldFBhbGV0dGUoUEFMRVRURUVOVFJZKnBhbCxpbnQgc3RhcnQsaW50IGxlbikKewogICAgaWYgKCFscGRkcmF3KSByZXR1cm47CiAgICBscGRkcGFsLT5scHZ0YmwtPmZuU2V0RW50cmllcyhscGRkcGFsLDAsc3RhcnQsbGVuLHBhbCk7CiAgICBscGRkc3VyZi0+bHB2dGJsLT5mblNldFBhbGV0dGUobHBkZHN1cmYsbHBkZHBhbCk7Cn0KCnZvaWQgVkdBX1NldFF1YWRQYWxldHRlKFJHQlFVQUQqY29sb3IsaW50IHN0YXJ0LGludCBsZW4pCnsKICAgIFBBTEVUVEVFTlRSWSBwYWxbMjU2XTsKICAgIGludCBjOwoKICAgIGlmICghbHBkZHJhdykgcmV0dXJuOwogICAgZm9yIChjPTA7IGM8bGVuOyBjKyspIHsKICAgICAgICBwYWxbY10ucGVSZWQgID1jb2xvcltjXS5yZ2JSZWQ7CiAgICAgICAgcGFsW2NdLnBlR3JlZW49Y29sb3JbY10ucmdiR3JlZW47CiAgICAgICAgcGFsW2NdLnBlQmx1ZSA9Y29sb3JbY10ucmdiQmx1ZTsKICAgICAgICBwYWxbY10ucGVGbGFncz0wOwogICAgfQogICAgbHBkZHBhbC0+bHB2dGJsLT5mblNldEVudHJpZXMobHBkZHBhbCwwLHN0YXJ0LGxlbixwYWwpOwogICAgbHBkZHN1cmYtPmxwdnRibC0+Zm5TZXRQYWxldHRlKGxwZGRzdXJmLGxwZGRwYWwpOwp9CgpMUFNUUiBWR0FfTG9jayh1bnNpZ25lZCpQaXRjaCx1bnNpZ25lZCpIZWlnaHQsdW5zaWduZWQqV2lkdGgsdW5zaWduZWQqRGVwdGgpCnsKICAgIGlmICghbHBkZHJhdykgcmV0dXJuIE5VTEw7CiAgICBpZiAoIWxwZGRzdXJmKSByZXR1cm4gTlVMTDsKICAgIGlmIChscGRkc3VyZi0+bHB2dGJsLT5mbkxvY2sobHBkZHN1cmYsTlVMTCwmc2Rlc2MsMCwwKSkgewogICAgICAgIEVSUihkZHJhdywiY291bGQgbm90IGxvY2sgc3VyZmFjZSFcbiIpOwogICAgICAgIHJldHVybiBOVUxMOwogICAgfQogICAgaWYgKFBpdGNoKSAqUGl0Y2g9c2Rlc2MubFBpdGNoOwogICAgaWYgKEhlaWdodCkgKkhlaWdodD1zZGVzYy5kd0hlaWdodDsKICAgIGlmIChXaWR0aCkgKldpZHRoPXNkZXNjLmR3V2lkdGg7CiAgICBpZiAoRGVwdGgpICpEZXB0aD1zZGVzYy5kZHBmUGl4ZWxGb3JtYXQueC5kd1JHQkJpdENvdW50OwogICAgcmV0dXJuIHNkZXNjLnkubHBTdXJmYWNlOwp9Cgp2b2lkIFZHQV9VbmxvY2sodm9pZCkKewogICAgbHBkZHN1cmYtPmxwdnRibC0+Zm5VbmxvY2sobHBkZHN1cmYsc2Rlc2MueS5scFN1cmZhY2UpOwp9Cgp2b2lkIFZHQV9Qb2xsKCBXT1JEIHRpbWVyICkKewogICAgY2hhciAqZGF0OwogICAgdW5zaWduZWQgUGl0Y2gsSGVpZ2h0LFdpZHRoOwogICAgY2hhciAqc3VyZjsKICAgIGludCBZLFg7CgogICAgRW50ZXJDcml0aWNhbFNlY3Rpb24oJnZnYV9jcml0KTsKICAgIGlmICghdmdhX3BvbGxpbmcpIHsKICAgICAgICB2Z2FfcG9sbGluZysrOwogICAgICAgIExlYXZlQ3JpdGljYWxTZWN0aW9uKCZ2Z2FfY3JpdCk7CiAgICAgICAgLyogRklYTUU6IG9wdGltaXplIGJ5IGRvaW5nIHRoaXMgb25seSBpZiB0aGUgZGF0YSBoYXMgYWN0dWFsbHkgY2hhbmdlZAogICAgICAgICAqICAgICAgICAoaW4gYSB3YXkgc2ltaWxhciB0byBESUJTZWN0aW9uLCBwZXJoYXBzKSAqLwogICAgICAgIHN1cmYgPSBWR0FfTG9jaygmUGl0Y2gsJkhlaWdodCwmV2lkdGgsTlVMTCk7CiAgICAgICAgaWYgKCFzdXJmKSByZXR1cm47CiAgICAgICAgZGF0ID0gRE9TTUVNX01hcERvc1RvTGluZWFyKDB4YTAwMDApOwogICAgICAgIC8qIGNvcHkgZnJvbSB2aXJ0dWFsIFZHQSBmcmFtZSBidWZmZXIgdG8gRGlyZWN0RHJhdyBzdXJmYWNlICovCiAgICAgICAgZm9yIChZPTA7IFk8SGVpZ2h0OyBZKyssc3VyZis9UGl0Y2gsZGF0Kz1XaWR0aCkgewogICAgICAgICAgICBtZW1jcHkoc3VyZixkYXQsV2lkdGgpOwogICAgICAgICAgICBmb3IgKFg9MDsgWDxXaWR0aDsgWCsrKSBpZiAoZGF0W1hdKSBUUkFDRShkZHJhdywiZGF0YSglZCkgYXQgKCVkLCVkKVxuIixkYXRbWF0sWCxZKTsKICAgICAgICB9CiAgICAgICAgVkdBX1VubG9jaygpOwogICAgICAgIHZnYV9yZWZyZXNoPTE7CiAgICAgICAgRW50ZXJDcml0aWNhbFNlY3Rpb24oJnZnYV9jcml0KTsKICAgICAgICB2Z2FfcG9sbGluZy0tOwogICAgfQogICAgTGVhdmVDcml0aWNhbFNlY3Rpb24oJnZnYV9jcml0KTsKfQoKc3RhdGljIEJZVEUgcGFscmVnLHBhbGNudDsKc3RhdGljIFBBTEVUVEVFTlRSWSBwYWxkYXQ7Cgp2b2lkIFZHQV9pb3BvcnRfb3V0KCBXT1JEIHBvcnQsIEJZVEUgdmFsICkKewogICAgc3dpdGNoIChwb3J0KSB7CiAgICAgICAgY2FzZSAweDNjODoKICAgICAgICAgICAgcGFscmVnPXZhbDsgcGFsY250PTA7IGJyZWFrOwogICAgICAgIGNhc2UgMHgzYzk6CiAgICAgICAgICAgICgoQllURSopJnBhbGRhdClbcGFsY250KytdPXZhbCA8PCAyOwogICAgICAgICAgICBpZiAocGFsY250PT0zKSB7CiAgICAgICAgICAgICAgICBWR0FfU2V0UGFsZXR0ZSgmcGFsZGF0LHBhbHJlZywxKTsKICAgICAgICAgICAgICAgIHBhbHJlZysrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgfQp9CgpCWVRFIFZHQV9pb3BvcnRfaW4oIFdPUkQgcG9ydCApCnsKICAgIEJZVEUgcmV0OwoKICAgIHN3aXRjaCAocG9ydCkgewogICAgICAgIGNhc2UgMHgzZGE6CiAgICAgICAgICAgIC8qIHNpbmNlIHdlIGRvbid0ICh5ZXQ/KSBzZXJ2ZSBET1MgVk0gcmVxdWVzdHMgd2hpbGUgVkdBX1BvbGwgaXMgcnVubmluZywKICAgICAgICAgICAgICAgd2UgbmVlZCB0byBmYWtlIHRoZSBvY2N1cnJlbmNlIG9mIHRoZSB2ZXJ0aWNhbCByZWZyZXNoICovCiAgICAgICAgICAgIGlmIChscGRkcmF3KSB7CiAgICAgICAgICAgICAgICByZXQ9dmdhX3JlZnJlc2g/MHgwMDoweDA4OwogICAgICAgICAgICAgICAgdmdhX3JlZnJlc2g9MDsKICAgICAgICAgICAgfSBlbHNlIHJldD0weDA4OwogICAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICByZXQ9MHhmZjsKICAgIH0KICAgIHJldHVybiByZXQ7Cn0K