LyoKICogQ09NIHN0dWIgKENTdGRTdHViQnVmZmVyKSBpbXBsZW1lbnRhdGlvbgogKgogKiBDb3B5cmlnaHQgMjAwMSBPdmUgS+V2ZW4sIFRyYW5zR2FtaW5nIFRlY2hub2xvZ2llcwogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3ICBVU0EKICovCgojaW5jbHVkZSA8c3RkYXJnLmg+CgojZGVmaW5lIENPQkpNQUNST1MKCiNpbmNsdWRlICJ3aW5kZWYuaCIKI2luY2x1ZGUgIndpbmJhc2UuaCIKI2luY2x1ZGUgIndpbmVycm9yLmgiCgojaW5jbHVkZSAib2JqYmFzZS5oIgoKI2luY2x1ZGUgInJwY3Byb3h5LmgiCgojaW5jbHVkZSAid2luZS9kZWJ1Zy5oIgoKI2luY2x1ZGUgImNwc2YuaCIKCldJTkVfREVGQVVMVF9ERUJVR19DSEFOTkVMKG9sZSk7CgojZGVmaW5lIFNUVUJfSEVBREVSKFRoaXMpICgoKENJbnRlcmZhY2VTdHViSGVhZGVyKikoKFRoaXMpLT5scFZ0YmwpKVstMV0pCgpIUkVTVUxUIFdJTkFQSSBDU3RkU3R1YkJ1ZmZlcl9Db25zdHJ1Y3QoUkVGSUlEIHJpaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExQVU5LTk9XTiBwVW5rU2VydmVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQQ0ludGVyZmFjZU5hbWUgbmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0ludGVyZmFjZVN0dWJWdGJsICp2dGJsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMUFBTRkFDVE9SWUJVRkZFUiBwUFNGYWN0b3J5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMUFJQQ1NUVUJCVUZGRVIgKnBwU3R1YikKewogIENTdGRTdHViQnVmZmVyICpUaGlzOwoKICBUUkFDRSgiKCVwLCVwLCVwLCVwKSAlc1xuIiwgcFVua1NlcnZlciwgdnRibCwgcFBTRmFjdG9yeSwgcHBTdHViLCBuYW1lKTsKICBUUkFDRSgiaWlkPSVzXG4iLCBkZWJ1Z3N0cl9ndWlkKHZ0YmwtPmhlYWRlci5waWlkKSk7CiAgVFJBQ0UoInZ0Ymw9JXBcbiIsICZ2dGJsLT5WdGJsKTsKCiAgaWYgKCFJc0VxdWFsR1VJRCh2dGJsLT5oZWFkZXIucGlpZCwgcmlpZCkpIHsKICAgIEVSUigiSUlEIG1pc21hdGNoIGR1cmluZyBzdHViIGNyZWF0aW9uXG4iKTsKICAgIHJldHVybiBSUENfRV9VTkVYUEVDVEVEOwogIH0KCiAgVGhpcyA9IEhlYXBBbGxvYyhHZXRQcm9jZXNzSGVhcCgpLEhFQVBfWkVST19NRU1PUlksc2l6ZW9mKENTdGRTdHViQnVmZmVyKSk7CiAgaWYgKCFUaGlzKSByZXR1cm4gRV9PVVRPRk1FTU9SWTsKCiAgVGhpcy0+bHBWdGJsID0gJnZ0YmwtPlZ0Ymw7CiAgVGhpcy0+UmVmQ291bnQgPSAxOwogIFRoaXMtPnB2U2VydmVyT2JqZWN0ID0gcFVua1NlcnZlcjsKICBUaGlzLT5wUFNGYWN0b3J5ID0gcFBTRmFjdG9yeTsKICAqcHBTdHViID0gKExQUlBDU1RVQkJVRkZFUilUaGlzOwoKICBJVW5rbm93bl9BZGRSZWYoVGhpcy0+cHZTZXJ2ZXJPYmplY3QpOwogIElQU0ZhY3RvcnlCdWZmZXJfQWRkUmVmKHBQU0ZhY3RvcnkpOwogIHJldHVybiBTX09LOwp9CgpIUkVTVUxUIFdJTkFQSSBDU3RkU3R1YkJ1ZmZlcl9RdWVyeUludGVyZmFjZShMUFJQQ1NUVUJCVUZGRVIgaWZhY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVGSUlEIHJpaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTFBWT0lEICpvYmopCnsKICBDU3RkU3R1YkJ1ZmZlciAqVGhpcyA9IChDU3RkU3R1YkJ1ZmZlciAqKWlmYWNlOwogIFRSQUNFKCIoJXApLT5RdWVyeUludGVyZmFjZSglcywlcClcbiIsVGhpcyxkZWJ1Z3N0cl9ndWlkKHJpaWQpLG9iaik7CgogIGlmIChJc0VxdWFsR1VJRCgmSUlEX0lVbmtub3duLHJpaWQpIHx8CiAgICAgIElzRXF1YWxHVUlEKCZJSURfSVJwY1N0dWJCdWZmZXIscmlpZCkpIHsKICAgICpvYmogPSBUaGlzOwogICAgVGhpcy0+UmVmQ291bnQrKzsKICAgIHJldHVybiBTX09LOwogIH0KICByZXR1cm4gRV9OT0lOVEVSRkFDRTsKfQoKVUxPTkcgV0lOQVBJIENTdGRTdHViQnVmZmVyX0FkZFJlZihMUFJQQ1NUVUJCVUZGRVIgaWZhY2UpCnsKICBDU3RkU3R1YkJ1ZmZlciAqVGhpcyA9IChDU3RkU3R1YkJ1ZmZlciAqKWlmYWNlOwogIFRSQUNFKCIoJXApLT5BZGRSZWYoKVxuIixUaGlzKTsKICByZXR1cm4gKysoVGhpcy0+UmVmQ291bnQpOwp9CgpVTE9ORyBXSU5BUEkgTmRyQ1N0ZFN0dWJCdWZmZXJfUmVsZWFzZShMUFJQQ1NUVUJCVUZGRVIgaWZhY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTFBQU0ZBQ1RPUllCVUZGRVIgcFBTRikKewogIENTdGRTdHViQnVmZmVyICpUaGlzID0gKENTdGRTdHViQnVmZmVyICopaWZhY2U7CiAgVFJBQ0UoIiglcCktPlJlbGVhc2UoKVxuIixUaGlzKTsKCiAgaWYgKCEtLShUaGlzLT5SZWZDb3VudCkpIHsKICAgIGlmKFRoaXMtPnB2U2VydmVyT2JqZWN0KQogICAgICAgIElVbmtub3duX1JlbGVhc2UoVGhpcy0+cHZTZXJ2ZXJPYmplY3QpOwogICAgaWYoVGhpcy0+cFBTRmFjdG9yeSkKICAgICAgICBJUFNGYWN0b3J5QnVmZmVyX1JlbGVhc2UoVGhpcy0+cFBTRmFjdG9yeSk7CiAgICBIZWFwRnJlZShHZXRQcm9jZXNzSGVhcCgpLDAsVGhpcyk7CiAgICByZXR1cm4gMDsKICB9CiAgcmV0dXJuIFRoaXMtPlJlZkNvdW50Owp9CgpIUkVTVUxUIFdJTkFQSSBDU3RkU3R1YkJ1ZmZlcl9Db25uZWN0KExQUlBDU1RVQkJVRkZFUiBpZmFjZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExQVU5LTk9XTiBscFVua1NlcnZlcikKewogIENTdGRTdHViQnVmZmVyICpUaGlzID0gKENTdGRTdHViQnVmZmVyICopaWZhY2U7CiAgVFJBQ0UoIiglcCktPkNvbm5lY3QoJXApXG4iLFRoaXMsbHBVbmtTZXJ2ZXIpOwogIFRoaXMtPnB2U2VydmVyT2JqZWN0ID0gbHBVbmtTZXJ2ZXI7CiAgcmV0dXJuIFNfT0s7Cn0KCnZvaWQgV0lOQVBJIENTdGRTdHViQnVmZmVyX0Rpc2Nvbm5lY3QoTFBSUENTVFVCQlVGRkVSIGlmYWNlKQp7CiAgQ1N0ZFN0dWJCdWZmZXIgKlRoaXMgPSAoQ1N0ZFN0dWJCdWZmZXIgKilpZmFjZTsKICBUUkFDRSgiKCVwKS0+RGlzY29ubmVjdCgpXG4iLFRoaXMpOwogIFRoaXMtPnB2U2VydmVyT2JqZWN0ID0gTlVMTDsKfQoKSFJFU1VMVCBXSU5BUEkgQ1N0ZFN0dWJCdWZmZXJfSW52b2tlKExQUlBDU1RVQkJVRkZFUiBpZmFjZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUFJQQ09MRU1FU1NBR0UgcE1zZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTFBSUENDSEFOTkVMQlVGRkVSIHBDaGFubmVsKQp7CiAgQ1N0ZFN0dWJCdWZmZXIgKlRoaXMgPSAoQ1N0ZFN0dWJCdWZmZXIgKilpZmFjZTsKICBEV09SRCBkd1BoYXNlID0gU1RVQl9VTk1BUlNIQUw7CiAgVFJBQ0UoIiglcCktPkludm9rZSglcCwlcClcbiIsVGhpcyxwTXNnLHBDaGFubmVsKTsKCiAgU1RVQl9IRUFERVIoVGhpcykucERpc3BhdGNoVGFibGVbcE1zZy0+aU1ldGhvZF0oaWZhY2UsIHBDaGFubmVsLCAoUFJQQ19NRVNTQUdFKXBNc2csICZkd1BoYXNlKTsKICByZXR1cm4gU19PSzsKfQoKTFBSUENTVFVCQlVGRkVSIFdJTkFQSSBDU3RkU3R1YkJ1ZmZlcl9Jc0lJRFN1cHBvcnRlZChMUFJQQ1NUVUJCVUZGRVIgaWZhY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRUZJSUQgcmlpZCkKewogIENTdGRTdHViQnVmZmVyICpUaGlzID0gKENTdGRTdHViQnVmZmVyICopaWZhY2U7CiAgVFJBQ0UoIiglcCktPklzSUlEU3VwcG9ydGVkKCVzKVxuIixUaGlzLGRlYnVnc3RyX2d1aWQocmlpZCkpOwogIHJldHVybiBJc0VxdWFsR1VJRChTVFVCX0hFQURFUihUaGlzKS5waWlkLCByaWlkKSA/IGlmYWNlIDogTlVMTDsKfQoKVUxPTkcgV0lOQVBJIENTdGRTdHViQnVmZmVyX0NvdW50UmVmcyhMUFJQQ1NUVUJCVUZGRVIgaWZhY2UpCnsKICBDU3RkU3R1YkJ1ZmZlciAqVGhpcyA9IChDU3RkU3R1YkJ1ZmZlciAqKWlmYWNlOwogIFRSQUNFKCIoJXApLT5Db3VudFJlZnMoKVxuIixUaGlzKTsKICByZXR1cm4gVGhpcy0+UmVmQ291bnQ7Cn0KCkhSRVNVTFQgV0lOQVBJIENTdGRTdHViQnVmZmVyX0RlYnVnU2VydmVyUXVlcnlJbnRlcmZhY2UoTFBSUENTVFVCQlVGRkVSIGlmYWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTFBWT0lEICpwcHYpCnsKICBDU3RkU3R1YkJ1ZmZlciAqVGhpcyA9IChDU3RkU3R1YkJ1ZmZlciAqKWlmYWNlOwogIFRSQUNFKCIoJXApLT5EZWJ1Z1NlcnZlclF1ZXJ5SW50ZXJmYWNlKCVwKVxuIixUaGlzLHBwdik7CiAgcmV0dXJuIFNfT0s7Cn0KCnZvaWQgV0lOQVBJIENTdGRTdHViQnVmZmVyX0RlYnVnU2VydmVyUmVsZWFzZShMUFJQQ1NUVUJCVUZGRVIgaWZhY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExQVk9JRCBwdikKewogIENTdGRTdHViQnVmZmVyICpUaGlzID0gKENTdGRTdHViQnVmZmVyICopaWZhY2U7CiAgVFJBQ0UoIiglcCktPkRlYnVnU2VydmVyUmVsZWFzZSglcClcbiIsVGhpcyxwdik7Cn0K