LyoKICogUlBDIGVuZHBvaW50IG1hcHBlciBzZXJ2ZXIKICoKICogQ29weXJpZ2h0IChDKSAyMDAxIE92ZSBL5XZlbiwgVHJhbnNHYW1pbmcgVGVjaG5vbG9naWVzIEluYywKICogQ29weXJpZ2h0IChDKSAyMDAyIEdyZWcgVHVybmVyCiAqCiAqIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IKICogbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIKICogdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uCiAqCiAqIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAogKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgogKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVQogKiBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgogKgogKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKICogRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3QsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BIDAyMTEwLTEzMDEsIFVTQQogKi8KCiNpbmNsdWRlIDxhc3NlcnQuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgoKI2luY2x1ZGUgInJwY3NzLmgiCiNpbmNsdWRlICJycGMuaCIKI2luY2x1ZGUgIndpbmUvZGVidWcuaCIKCldJTkVfREVGQVVMVF9ERUJVR19DSEFOTkVMKG9sZSk7CgpzdHJ1Y3QgZXBtYXBfZW50cnkKewogICAgc3RydWN0IGVwbWFwX2VudHJ5ICpuZXh0OwogICAgUlBDX1NZTlRBWF9JREVOVElGSUVSIGlmYWNlOwogICAgVVVJRCBvYmplY3Q7CiAgICBjaGFyICpwcm90c2VxOwogICAgY2hhciAqZW5kcG9pbnQ7Cn07CgpzdGF0aWMgc3RydWN0IGVwbWFwX2VudHJ5ICplcG1hcDsKCnN0YXRpYyBjb25zdCBVVUlEIG5pbF9vYmplY3Q7CgpzdGF0aWMgY2hhciAqbXlzdHJkdXAoY29uc3QgY2hhciAqc3RyKSB7CiAgICBjaGFyICpydmFsOwogICAgcnZhbCA9IExvY2FsQWxsb2MoTFBUUiwgc3RybGVuKHN0cikrMSk7CiAgICBDb3B5TWVtb3J5KHJ2YWwsIHN0ciwgc3RybGVuKHN0cikrMSk7CiAgICByZXR1cm4gcnZhbDsKfQoKc3RhdGljIHN0cnVjdCBlcG1hcF9lbnRyeSAqZmluZF9lbmRwb2ludChjb25zdCBSUENfU1lOVEFYX0lERU5USUZJRVIgKmlmYWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNoYXIgKnByb3RzZXEsIGNvbnN0IFVVSUQgKm9iamVjdCkKewogICAgc3RydWN0IGVwbWFwX2VudHJ5ICptYXA7CiAgICBmb3IgKG1hcD1lcG1hcDsgbWFwOyBtYXA9bWFwLT5uZXh0KSB7CiAgICAgICAgaWYgKG1lbWNtcCgmbWFwLT5pZmFjZSwgaWZhY2UsIHNpemVvZihSUENfU1lOVEFYX0lERU5USUZJRVIpKSkgY29udGludWU7CiAgICAgICAgaWYgKG1lbWNtcCgmbWFwLT5vYmplY3QsIG9iamVjdCwgc2l6ZW9mKFVVSUQpKSkgY29udGludWU7CiAgICAgICAgaWYgKHN0cmNtcChtYXAtPnByb3RzZXEsIHByb3RzZXEpKSBjb250aW51ZTsKCVdJTkVfVFJBQ0UoImZvdW5kLlxuIik7CiAgICAgICAgcmV0dXJuIG1hcDsKICAgIH0KICAgIFdJTkVfVFJBQ0UoIm5vdCBmb3VuZC5cbiIpOwogICAgcmV0dXJuIE5VTEw7Cn0KCnN0YXRpYyB2b2lkIHJlZ2lzdGVyX2VuZHBvaW50KGNvbnN0IFJQQ19TWU5UQVhfSURFTlRJRklFUiAqaWZhY2UsIGNvbnN0IGNoYXIgKnByb3RzZXEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNoYXIgKmVuZHBvaW50LCBjb25zdCBVVUlEICpvYmplY3RzLCBpbnQgb2JqY291bnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludCBub19yZXBsYWNlKQp7CiAgICBpbnQgYzsKCiAgICBXSU5FX1RSQUNFKCIocHJvdHNlcSA9PSAlcywgZW5kcG9pbnQgPT0gJXMsIG9iamNvdW50ID09ICVpLCBub19yZXBsYWNlID09ICVpKVxuIiwKICAgICAgd2luZV9kYmdzdHJfYShwcm90c2VxKSwgd2luZV9kYmdzdHJfYShlbmRwb2ludCksIG9iamNvdW50LCBub19yZXBsYWNlKTsKCiAgICBpZiAoIW9iamNvdW50KSB7CiAgICAgICAgb2JqZWN0cyA9ICZuaWxfb2JqZWN0OwogICAgICAgIG9iamNvdW50ID0gMTsKICAgIH0KCiAgICBmb3IgKGM9MDsgYzxvYmpjb3VudDsgYysrKSB7CiAgICAgICAgc3RydWN0IGVwbWFwX2VudHJ5ICptYXAgPSBOVUxMOwogICAgICAgIGlmICghbm9fcmVwbGFjZSkKICAgICAgICAgICAgbWFwID0gZmluZF9lbmRwb2ludChpZmFjZSwgcHJvdHNlcSwgJm9iamVjdHNbY10pOwogICAgICAgIGlmIChtYXApIHsKICAgICAgICAgICAgTG9jYWxGcmVlKG1hcC0+ZW5kcG9pbnQpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgbWFwID0gTG9jYWxBbGxvYyhMUFRSLCBzaXplb2Yoc3RydWN0IGVwbWFwX2VudHJ5KSk7CiAgICAgICAgICAgIG1lbWNweSgmbWFwLT5pZmFjZSwgaWZhY2UsIHNpemVvZihSUENfU1lOVEFYX0lERU5USUZJRVIpKTsKICAgICAgICAgICAgbWVtY3B5KCZtYXAtPm9iamVjdCwgJm9iamVjdHNbY10sIHNpemVvZihVVUlEKSk7CiAgICAgICAgICAgIG1hcC0+cHJvdHNlcSA9IG15c3RyZHVwKHByb3RzZXEpOwogICAgICAgICAgICBtYXAtPm5leHQgPSBlcG1hcDsKICAgICAgICAgICAgZXBtYXAgPSBtYXA7CiAgICAgICAgfQogICAgICAgIFdJTkVfVFJBQ0UoIiAgbWFwcGluZyBlbmRwb2ludCAocHJvdHNlcSA9PSAlcywgZW5kcG9pbnQgPT0gJXMsIHV1aWQgPT0gJXMpXG4iLAoJICB3aW5lX2RiZ3N0cl9hKHByb3RzZXEpLCB3aW5lX2RiZ3N0cl9hKGVuZHBvaW50KSwgd2luZV9kYmdzdHJfZ3VpZCgmb2JqZWN0c1tjXSkpOwogICAgICAgIG1hcC0+ZW5kcG9pbnQgPSBteXN0cmR1cChlbmRwb2ludCk7CiAgICB9Cn0KCnN0YXRpYyB2b2lkIHVucmVnaXN0ZXJfZW5kcG9pbnQoY29uc3QgUlBDX1NZTlRBWF9JREVOVElGSUVSICppZmFjZSwgY29uc3QgY2hhciAqcHJvdHNlcSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGFyICplbmRwb2ludCwgY29uc3QgVVVJRCAqb2JqZWN0cywgaW50IG9iamNvdW50KQp7CiAgICBzdHJ1Y3QgZXBtYXBfZW50cnkgKm1hcCwgKnByZXYsICpucHJldiwgKm5leHQ7CiAgICBpbnQgYzsKICAgIAogICAgV0lORV9UUkFDRSgiKHByb3RzZXEgPT0gJXMsIGVuZHBvaW50ID09ICVzLCBvYmpjb3VudCA9PSAlaSlcbiIsIAogICAgICB3aW5lX2RiZ3N0cl9hKHByb3RzZXEpLCB3aW5lX2RiZ3N0cl9hKGVuZHBvaW50KSwgb2JqY291bnQpOwogICAgCiAgICBpZiAoIW9iamNvdW50KSB7CiAgICAgICAgb2JqZWN0cyA9ICZuaWxfb2JqZWN0OwogICAgICAgIG9iamNvdW50ID0gMTsKICAgIH0KICAgIHByZXY9TlVMTDsKICAgIG5wcmV2PU5VTEw7CiAgICBtYXA9ZXBtYXA7CiAgICB3aGlsZShtYXApIHsKICAgICAgICBuZXh0ID0gbWFwLT5uZXh0OwogICAgICAgIG5wcmV2ID0gbWFwOwogICAgICAgIGlmIChtZW1jbXAoJm1hcC0+aWZhY2UsIGlmYWNlLCBzaXplb2YoUlBDX1NZTlRBWF9JREVOVElGSUVSKSkpIGdvdG8gY29udDsKICAgICAgICBmb3IgKGM9MDsgYzxvYmpjb3VudDsgYysrKQogICAgICAgICAgICBpZiAoIW1lbWNtcCgmbWFwLT5vYmplY3QsICZvYmplY3RzW2NdLCBzaXplb2YoVVVJRCkpKSBicmVhazsKICAgICAgICBpZiAoYz09b2JqY291bnQpIGdvdG8gY29udDsKICAgICAgICBpZiAoc3RyY21wKG1hcC0+cHJvdHNlcSwgcHJvdHNlcSkpIGdvdG8gY29udDsKICAgICAgICAKICAgICAgICBXSU5FX1RSQUNFKCIgIHVubWFwcGluZzogKHByb3RzZXEgPT0gJXMsIGVuZHBvaW50ID09ICVzLCB1dWlkID09ICVzKVxuIiwKCSAgd2luZV9kYmdzdHJfYShtYXAtPnByb3RzZXEpLCB3aW5lX2RiZ3N0cl9hKG1hcC0+ZW5kcG9pbnQpLAoJICB3aW5lX2RiZ3N0cl9ndWlkKCZtYXAtPm9iamVjdCkpOwogICAgICAgIAogICAgICAgIGlmIChwcmV2KSBwcmV2LT5uZXh0ID0gbWFwLT5uZXh0OwogICAgICAgIGVsc2UgZXBtYXAgPSBtYXAtPm5leHQ7CiAgICAgICAgbnByZXYgPSBwcmV2OwoKICAgICAgICBMb2NhbEZyZWUobWFwLT5wcm90c2VxKTsKICAgICAgICBMb2NhbEZyZWUobWFwLT5lbmRwb2ludCk7CiAgICAgICAgTG9jYWxGcmVlKG1hcCk7CgogICAgICAgIGNvbnQ6CgoJcHJldiA9IG5wcmV2OwoJbWFwID0gbmV4dDsKICAgIH0KfQoKc3RhdGljIHZvaWQgcmVzb2x2ZV9lbmRwb2ludChjb25zdCBSUENfU1lOVEFYX0lERU5USUZJRVIgKmlmYWNlLCBjb25zdCBjaGFyICpwcm90c2VxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFVVSUQgKm9iamVjdCwgY2hhciAqcnNsdF9lcCkKewogICAgc2l6ZV90IGxlbjsKICAgIHN0cnVjdCBlcG1hcF9lbnRyeSAqbWFwOwoKICAgIGlmICghKG1hcCA9IGZpbmRfZW5kcG9pbnQoaWZhY2UsIHByb3RzZXEsIG9iamVjdCkpKSByZXR1cm47CgogICAgbGVuID0gbWluKCBNQVhfUlBDU1NfTlBfUkVQTFlfU1RSSU5HX0xFTiwgc3RybGVuKG1hcC0+ZW5kcG9pbnQpKzEgKTsKICAgIGlmIChsZW4pIG1lbWNweShyc2x0X2VwLCBtYXAtPmVuZHBvaW50LCBsZW4pOwp9CgpzdGF0aWMgY29uc3QgY2hhciAqZ2V0X3N0cmluZyhjb25zdCBjaGFyKipwdHIsIGNvbnN0IGNoYXIqZW5kKQp7CiAgICBjb25zdCBjaGFyICpzdHIgPSAqcHRyLCAqbnB0ciA9IHN0cjsKCiAgICB3aGlsZSAobnB0ciA8IGVuZCAmJiAqbnB0cikgbnB0cisrOwogICAgaWYgKG5wdHIgPT0gZW5kKQogICAgICAgIHJldHVybiBOVUxMOwogICAgKnB0ciA9IG5wdHIgKyAxOwogICAgcmV0dXJuIHN0cjsKfQoKQk9PTCBSUENTU19FcG1hcEVtcHR5KHZvaWQpCnsKICByZXR1cm4gKCFlcG1hcCk7Cn0KCnZvaWQgUlBDU1NfUmVnaXN0ZXJScGNFbmRwb2ludHMoUlBDX1NZTlRBWF9JREVOVElGSUVSIGlmYWNlLCBpbnQgb2JqZWN0X2NvdW50LCAKICBpbnQgYmluZGluZ19jb3VudCwgaW50IG5vX3JlcGxhY2UsIGNoYXIgKnZhcmRhdGEsIGxvbmcgdmFyZGF0YV9zaXplKQp7CiAgICBjb25zdCBjaGFyICpkYXRhID0gdmFyZGF0YTsKICAgIGNvbnN0IGNoYXIgKmVuZCA9IGRhdGEgKyB2YXJkYXRhX3NpemU7CiAgICBjb25zdCBVVUlEICpvYmplY3RzID0gKGNvbnN0IFVVSUQgKilkYXRhOwogICAgaW50IGM7CgogICAgZGF0YSArPSBvYmplY3RfY291bnQgKiBzaXplb2YoVVVJRCk7CiAgICBmb3IgKGM9MDsgYyA8IGJpbmRpbmdfY291bnQ7IGMrKykgewogICAgICAgIGNvbnN0IGNoYXIgKnByb3RzZXEgPSBnZXRfc3RyaW5nKCZkYXRhLCBlbmQpOwogICAgICAgIGNvbnN0IGNoYXIgKmVuZHBvaW50ID0gZ2V0X3N0cmluZygmZGF0YSwgZW5kKTsKICAgICAgICBpZiAocHJvdHNlcSAmJiBlbmRwb2ludCkKICAgICAgICAgICAgcmVnaXN0ZXJfZW5kcG9pbnQoJmlmYWNlLCBwcm90c2VxLCBlbmRwb2ludCwgb2JqZWN0cywgb2JqZWN0X2NvdW50LCBub19yZXBsYWNlKTsKICAgIH0KfQoKdm9pZCBSUENTU19VbnJlZ2lzdGVyUnBjRW5kcG9pbnRzKFJQQ19TWU5UQVhfSURFTlRJRklFUiBpZmFjZSwgaW50IG9iamVjdF9jb3VudCwKICBpbnQgYmluZGluZ19jb3VudCwgY2hhciAqdmFyZGF0YSwgbG9uZyB2YXJkYXRhX3NpemUpCnsKICAgIGNvbnN0IGNoYXIgKmRhdGEgPSB2YXJkYXRhOwogICAgY29uc3QgY2hhciAqZW5kID0gZGF0YSArIHZhcmRhdGFfc2l6ZTsKICAgIGNvbnN0IFVVSUQgKm9iamVjdHMgPSAoY29uc3QgVVVJRCAqKWRhdGE7CiAgICBpbnQgYzsKCiAgICBkYXRhICs9IG9iamVjdF9jb3VudCAqIHNpemVvZihVVUlEKTsKICAgIGZvciAoYz0wOyBjIDwgYmluZGluZ19jb3VudDsgYysrKSB7CiAgICAgICAgY29uc3QgY2hhciAqcHJvdHNlcSA9IGdldF9zdHJpbmcoJmRhdGEsIGVuZCk7CiAgICAgICAgY29uc3QgY2hhciAqZW5kcG9pbnQgPSBnZXRfc3RyaW5nKCZkYXRhLCBlbmQpOwogICAgICAgIGlmIChwcm90c2VxICYmIGVuZHBvaW50KQogICAgICAgICAgICB1bnJlZ2lzdGVyX2VuZHBvaW50KCZpZmFjZSwgcHJvdHNlcSwgZW5kcG9pbnQsIG9iamVjdHMsIG9iamVjdF9jb3VudCk7CiAgICB9Cn0KCnZvaWQgUlBDU1NfUmVzb2x2ZVJwY0VuZHBvaW50cyhSUENfU1lOVEFYX0lERU5USUZJRVIgaWZhY2UsIFVVSUQgb2JqZWN0LCBjaGFyICpwcm90c2VxLCBjaGFyICpyc2x0X2VwKQp7CiAgICByZXNvbHZlX2VuZHBvaW50KCZpZmFjZSwgcHJvdHNlcSwgJm9iamVjdCwgcnNsdF9lcCk7Cn0K