LyoKICogVkdBIGhhcmR3YXJlIGVtdWxhdGlvbgogKiAKICogQ29weXJpZ2h0IDE5OTggT3ZlIEvldmVuICh3aXRoIHNvbWUgaGVscCBmcm9tIE1hcmN1cyBNZWlzc25lcikKICoKICovCgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlICJ3aW5iYXNlLmgiCiNpbmNsdWRlICJ3aW51c2VyLmgiCiNpbmNsdWRlICJ3aW5lL3dpbnVzZXIxNi5oIgojaW5jbHVkZSAibWlzY2VtdS5oIgojaW5jbHVkZSAidmdhLmgiCiNpbmNsdWRlICJkZHJhdy5oIgojaW5jbHVkZSAiZGVidWcuaCIKCkRFRkFVTFRfREVCVUdfQ0hBTk5FTChkZHJhdykKCnN0YXRpYyBJRGlyZWN0RHJhdyAqbHBkZHJhdyA9IE5VTEw7CnN0YXRpYyBJRGlyZWN0RHJhd1N1cmZhY2UgKmxwZGRzdXJmOwpzdGF0aWMgSURpcmVjdERyYXdQYWxldHRlICpscGRkcGFsOwpzdGF0aWMgRERTVVJGQUNFREVTQyBzZGVzYzsKc3RhdGljIFdPUkQgcG9sbF90aW1lcjsKc3RhdGljIENSSVRJQ0FMX1NFQ1RJT04gdmdhX2NyaXQ7CnN0YXRpYyBpbnQgdmdhX3BvbGxpbmcsdmdhX3JlZnJlc2g7CgppbnQgVkdBX1NldE1vZGUodW5zaWduZWQgWHJlcyx1bnNpZ25lZCBZcmVzLHVuc2lnbmVkIERlcHRoKQp7CiAgICBpZiAobHBkZHJhdykgVkdBX0V4aXQoKTsKICAgIGlmICghbHBkZHJhdykgewogICAgICAgIERpcmVjdERyYXdDcmVhdGUoTlVMTCwmbHBkZHJhdyxOVUxMKTsKICAgICAgICBpZiAoIWxwZGRyYXcpIHsKICAgICAgICAgICAgRVJSKGRkcmF3LCJEaXJlY3REcmF3IGlzIG5vdCBhdmFpbGFibGVcbiIpOwogICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9CiAgICAgICAgaWYgKElEaXJlY3REcmF3X1NldERpc3BsYXlNb2RlKGxwZGRyYXcsWHJlcyxZcmVzLERlcHRoKSkgewogICAgICAgICAgICBFUlIoZGRyYXcsIkRpcmVjdERyYXcgZG9lcyBub3Qgc3VwcG9ydCByZXF1ZXN0ZWQgZGlzcGxheSBtb2RlXG4iKTsKICAgICAgICAgICAgSURpcmVjdERyYXdfUmVsZWFzZShscGRkcmF3KTsKICAgICAgICAgICAgbHBkZHJhdz1OVUxMOwogICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9CiAgICAgICAgSURpcmVjdERyYXdfQ3JlYXRlUGFsZXR0ZShscGRkcmF3LEREUENBUFNfOEJJVCxOVUxMLCZscGRkcGFsLE5VTEwpOwogICAgICAgIG1lbXNldCgmc2Rlc2MsMCxzaXplb2Yoc2Rlc2MpKTsKICAgICAgICBzZGVzYy5kd1NpemU9c2l6ZW9mKHNkZXNjKTsKCXNkZXNjLmR3RmxhZ3MgPSBERFNEX0NBUFM7CglzZGVzYy5kZHNDYXBzLmR3Q2FwcyA9IEREU0NBUFNfUFJJTUFSWVNVUkZBQ0U7CiAgICAgICAgaWYgKElEaXJlY3REcmF3X0NyZWF0ZVN1cmZhY2UobHBkZHJhdywmc2Rlc2MsJmxwZGRzdXJmLE5VTEwpfHwoIWxwZGRzdXJmKSkgewogICAgICAgICAgICBFUlIoZGRyYXcsIkRpcmVjdERyYXcgc3VyZmFjZSBpcyBub3QgYXZhaWxhYmxlXG4iKTsKICAgICAgICAgICAgSURpcmVjdERyYXdfUmVsZWFzZShscGRkcmF3KTsKICAgICAgICAgICAgbHBkZHJhdz1OVUxMOwogICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9CiAgICAgICAgdmdhX3JlZnJlc2g9MDsKICAgICAgICBJbml0aWFsaXplQ3JpdGljYWxTZWN0aW9uKCZ2Z2FfY3JpdCk7CiAgICAgICAgTWFrZUNyaXRpY2FsU2VjdGlvbkdsb2JhbCgmdmdhX2NyaXQpOwogICAgICAgIC8qIHBvbGwgZXZlcnkgMjBtcyAoNTBmcHMgc2hvdWxkIHByb3ZpZGUgYWRlcXVhdGUgcmVzcG9uc2l2ZW5lc3MpICovCiAgICAgICAgcG9sbF90aW1lciA9IENyZWF0ZVN5c3RlbVRpbWVyKCAyMCwgVkdBX1BvbGwgKTsKICAgIH0KICAgIHJldHVybiAwOwp9CgppbnQgVkdBX0dldE1vZGUodW5zaWduZWQqSGVpZ2h0LHVuc2lnbmVkKldpZHRoLHVuc2lnbmVkKkRlcHRoKQp7CiAgICBpZiAoIWxwZGRyYXcpIHJldHVybiAxOwogICAgaWYgKCFscGRkc3VyZikgcmV0dXJuIDE7CiAgICBpZiAoSGVpZ2h0KSAqSGVpZ2h0PXNkZXNjLmR3SGVpZ2h0OwogICAgaWYgKFdpZHRoKSAqV2lkdGg9c2Rlc2MuZHdXaWR0aDsKICAgIGlmIChEZXB0aCkgKkRlcHRoPXNkZXNjLmRkcGZQaXhlbEZvcm1hdC54LmR3UkdCQml0Q291bnQ7CiAgICByZXR1cm4gMDsKfQoKdm9pZCBWR0FfRXhpdCh2b2lkKQp7CiAgICBpZiAobHBkZHJhdykgewogICAgICAgIFNZU1RFTV9LaWxsU3lzdGVtVGltZXIocG9sbF90aW1lcik7CiAgICAgICAgRGVsZXRlQ3JpdGljYWxTZWN0aW9uKCZ2Z2FfY3JpdCk7CiAgICAgICAgSURpcmVjdERyYXdTdXJmYWNlX1JlbGVhc2UobHBkZHN1cmYpOwogICAgICAgIGxwZGRzdXJmPU5VTEw7CiAgICAgICAgSURpcmVjdERyYXdfUmVsZWFzZShscGRkcmF3KTsKICAgICAgICBscGRkcmF3PU5VTEw7CiAgICB9Cn0KCnZvaWQgVkdBX1NldFBhbGV0dGUoUEFMRVRURUVOVFJZKnBhbCxpbnQgc3RhcnQsaW50IGxlbikKewogICAgaWYgKCFscGRkcmF3KSByZXR1cm47CiAgICBJRGlyZWN0RHJhd1BhbGV0dGVfU2V0RW50cmllcyhscGRkcGFsLDAsc3RhcnQsbGVuLHBhbCk7CiAgICBJRGlyZWN0RHJhd1N1cmZhY2VfU2V0UGFsZXR0ZShscGRkc3VyZixscGRkcGFsKTsKfQoKdm9pZCBWR0FfU2V0UXVhZFBhbGV0dGUoUkdCUVVBRCpjb2xvcixpbnQgc3RhcnQsaW50IGxlbikKewogICAgUEFMRVRURUVOVFJZIHBhbFsyNTZdOwogICAgaW50IGM7CgogICAgaWYgKCFscGRkcmF3KSByZXR1cm47CiAgICBmb3IgKGM9MDsgYzxsZW47IGMrKykgewogICAgICAgIHBhbFtjXS5wZVJlZCAgPWNvbG9yW2NdLnJnYlJlZDsKICAgICAgICBwYWxbY10ucGVHcmVlbj1jb2xvcltjXS5yZ2JHcmVlbjsKICAgICAgICBwYWxbY10ucGVCbHVlID1jb2xvcltjXS5yZ2JCbHVlOwogICAgICAgIHBhbFtjXS5wZUZsYWdzPTA7CiAgICB9CiAgICBJRGlyZWN0RHJhd1BhbGV0dGVfU2V0RW50cmllcyhscGRkcGFsLDAsc3RhcnQsbGVuLHBhbCk7CiAgICBJRGlyZWN0RHJhd1N1cmZhY2VfU2V0UGFsZXR0ZShscGRkc3VyZixscGRkcGFsKTsKfQoKTFBTVFIgVkdBX0xvY2sodW5zaWduZWQqUGl0Y2gsdW5zaWduZWQqSGVpZ2h0LHVuc2lnbmVkKldpZHRoLHVuc2lnbmVkKkRlcHRoKQp7CiAgICBpZiAoIWxwZGRyYXcpIHJldHVybiBOVUxMOwogICAgaWYgKCFscGRkc3VyZikgcmV0dXJuIE5VTEw7CiAgICBpZiAoSURpcmVjdERyYXdTdXJmYWNlX0xvY2sobHBkZHN1cmYsTlVMTCwmc2Rlc2MsMCwwKSkgewogICAgICAgIEVSUihkZHJhdywiY291bGQgbm90IGxvY2sgc3VyZmFjZSFcbiIpOwogICAgICAgIHJldHVybiBOVUxMOwogICAgfQogICAgaWYgKFBpdGNoKSAqUGl0Y2g9c2Rlc2MubFBpdGNoOwogICAgaWYgKEhlaWdodCkgKkhlaWdodD1zZGVzYy5kd0hlaWdodDsKICAgIGlmIChXaWR0aCkgKldpZHRoPXNkZXNjLmR3V2lkdGg7CiAgICBpZiAoRGVwdGgpICpEZXB0aD1zZGVzYy5kZHBmUGl4ZWxGb3JtYXQueC5kd1JHQkJpdENvdW50OwogICAgcmV0dXJuIHNkZXNjLnkubHBTdXJmYWNlOwp9Cgp2b2lkIFZHQV9VbmxvY2sodm9pZCkKewogICAgSURpcmVjdERyYXdTdXJmYWNlX1VubG9jayhscGRkc3VyZixzZGVzYy55LmxwU3VyZmFjZSk7Cn0KCi8qIFdlIGFyZSBjYWxsZWQgZnJvbSBTSUdBTFJNLCBhcmVuJ3Qgd2U/IFdlIHNob3VsZCBfTk9UXyBkbyBzeW5jaHJvbml6YXRpb24KICogc3R1ZmYhCiAqLwp2b2lkIFZHQV9Qb2xsKCBXT1JEIHRpbWVyICkKewogICAgY2hhciAqZGF0OwogICAgdW5zaWduZWQgUGl0Y2gsSGVpZ2h0LFdpZHRoOwogICAgY2hhciAqc3VyZjsKICAgIGludCBZOwogICAgLyogaW50IFg7ICovCgogICAgRW50ZXJDcml0aWNhbFNlY3Rpb24oJnZnYV9jcml0KTsKICAgIGlmICghdmdhX3BvbGxpbmcpIHsKICAgICAgICB2Z2FfcG9sbGluZysrOwogICAgICAgIExlYXZlQ3JpdGljYWxTZWN0aW9uKCZ2Z2FfY3JpdCk7CiAgICAgICAgLyogRklYTUU6IG9wdGltaXplIGJ5IGRvaW5nIHRoaXMgb25seSBpZiB0aGUgZGF0YSBoYXMgYWN0dWFsbHkgY2hhbmdlZAogICAgICAgICAqICAgICAgICAoaW4gYSB3YXkgc2ltaWxhciB0byBESUJTZWN0aW9uLCBwZXJoYXBzKSAqLwogICAgICAgIHN1cmYgPSBWR0FfTG9jaygmUGl0Y2gsJkhlaWdodCwmV2lkdGgsTlVMTCk7CiAgICAgICAgaWYgKCFzdXJmKSByZXR1cm47CiAgICAgICAgZGF0ID0gRE9TTUVNX01hcERvc1RvTGluZWFyKDB4YTAwMDApOwogICAgICAgIC8qIGNvcHkgZnJvbSB2aXJ0dWFsIFZHQSBmcmFtZSBidWZmZXIgdG8gRGlyZWN0RHJhdyBzdXJmYWNlICovCiAgICAgICAgZm9yIChZPTA7IFk8SGVpZ2h0OyBZKyssc3VyZis9UGl0Y2gsZGF0Kz1XaWR0aCkgewogICAgICAgICAgICBtZW1jcHkoc3VyZixkYXQsV2lkdGgpOwogICAgICAgICAgICAvKmZvciAoWD0wOyBYPFdpZHRoOyBYKyspIGlmIChkYXRbWF0pIFRSQUNFKGRkcmF3LCJkYXRhKCVkKSBhdCAoJWQsJWQpXG4iLGRhdFtYXSxYLFkpOyovCiAgICAgICAgfQogICAgICAgIFZHQV9VbmxvY2soKTsKICAgICAgICB2Z2FfcmVmcmVzaD0xOwogICAgICAgIEVudGVyQ3JpdGljYWxTZWN0aW9uKCZ2Z2FfY3JpdCk7CiAgICAgICAgdmdhX3BvbGxpbmctLTsKICAgIH0KICAgIExlYXZlQ3JpdGljYWxTZWN0aW9uKCZ2Z2FfY3JpdCk7Cn0KCnN0YXRpYyBCWVRFIHBhbHJlZyxwYWxjbnQ7CnN0YXRpYyBQQUxFVFRFRU5UUlkgcGFsZGF0OwoKdm9pZCBWR0FfaW9wb3J0X291dCggV09SRCBwb3J0LCBCWVRFIHZhbCApCnsKICAgIHN3aXRjaCAocG9ydCkgewogICAgICAgIGNhc2UgMHgzYzg6CiAgICAgICAgICAgIHBhbHJlZz12YWw7IHBhbGNudD0wOyBicmVhazsKICAgICAgICBjYXNlIDB4M2M5OgogICAgICAgICAgICAoKEJZVEUqKSZwYWxkYXQpW3BhbGNudCsrXT12YWwgPDwgMjsKICAgICAgICAgICAgaWYgKHBhbGNudD09MykgewogICAgICAgICAgICAgICAgVkdBX1NldFBhbGV0dGUoJnBhbGRhdCxwYWxyZWcrKywxKTsKICAgICAgICAgICAgICAgIHBhbGNudD0wOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgfQp9CgpCWVRFIFZHQV9pb3BvcnRfaW4oIFdPUkQgcG9ydCApCnsKICAgIEJZVEUgcmV0OwoKICAgIHN3aXRjaCAocG9ydCkgewogICAgICAgIGNhc2UgMHgzZGE6CiAgICAgICAgICAgIC8qIHNpbmNlIHdlIGRvbid0ICh5ZXQ/KSBzZXJ2ZSBET1MgVk0gcmVxdWVzdHMgd2hpbGUgVkdBX1BvbGwgaXMgcnVubmluZywKICAgICAgICAgICAgICAgd2UgbmVlZCB0byBmYWtlIHRoZSBvY2N1cnJlbmNlIG9mIHRoZSB2ZXJ0aWNhbCByZWZyZXNoICovCiAgICAgICAgICAgIGlmIChscGRkcmF3KSB7CiAgICAgICAgICAgICAgICByZXQ9dmdhX3JlZnJlc2g/MHgwMDoweDA4OwogICAgICAgICAgICAgICAgdmdhX3JlZnJlc2g9MDsKICAgICAgICAgICAgfSBlbHNlIHJldD0weDA4OwogICAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICByZXQ9MHhmZjsKICAgIH0KICAgIHJldHVybiByZXQ7Cn0K