From 67808f22b8f18243fbc8d63aad99ae24e86a0794 Mon Sep 17 00:00:00 2001 From: yet Date: Fri, 15 May 2026 17:32:46 +0400 Subject: [PATCH] Convert Pattern.java to Kotlin and refactor lookup logic to use a Map. --- .../noise/southernstorm/protocol/Pattern.kt | 1070 ++++------------- 1 file changed, 261 insertions(+), 809 deletions(-) diff --git a/app/src/main/java/com/bitchat/android/noise/southernstorm/protocol/Pattern.kt b/app/src/main/java/com/bitchat/android/noise/southernstorm/protocol/Pattern.kt index 2a625c90..2ab07c95 100644 --- a/app/src/main/java/com/bitchat/android/noise/southernstorm/protocol/Pattern.kt +++ b/app/src/main/java/com/bitchat/android/noise/southernstorm/protocol/Pattern.kt @@ -19,817 +19,269 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - -package com.bitchat.android.noise.southernstorm.protocol; +package com.bitchat.android.noise.southernstorm.protocol /** * Information about all supported handshake patterns. */ -class Pattern { - - private Pattern() {} - - // Token codes. - public static final short S = 1; - public static final short E = 2; - public static final short EE = 3; - public static final short ES = 4; - public static final short SE = 5; - public static final short SS = 6; - public static final short F = 7; - public static final short FF = 8; - public static final short FLIP_DIR = 255; - - // Pattern flag bits. - public static final short FLAG_LOCAL_STATIC = 0x0001; - public static final short FLAG_LOCAL_EPHEMERAL = 0x0002; - public static final short FLAG_LOCAL_REQUIRED = 0x0004; - public static final short FLAG_LOCAL_EPHEM_REQ = 0x0008; - public static final short FLAG_LOCAL_HYBRID = 0x0010; - public static final short FLAG_LOCAL_HYBRID_REQ = 0x0020; - public static final short FLAG_REMOTE_STATIC = 0x0100; - public static final short FLAG_REMOTE_EPHEMERAL = 0x0200; - public static final short FLAG_REMOTE_REQUIRED = 0x0400; - public static final short FLAG_REMOTE_EPHEM_REQ = 0x0800; - public static final short FLAG_REMOTE_HYBRID = 0x1000; - public static final short FLAG_REMOTE_HYBRID_REQ = 0x2000; - - private static final short[] noise_pattern_N = { - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_REQUIRED, - - E, - ES - }; - - private static final short[] noise_pattern_K = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_REQUIRED, - - E, - ES, - SS - }; - - private static final short[] noise_pattern_X = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_REQUIRED, - - E, - ES, - S, - SS - }; - - private static final short[] noise_pattern_NN = { - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - EE - }; - - private static final short[] noise_pattern_NK = { - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_REQUIRED, - - E, - ES, - FLIP_DIR, - E, - EE - }; - - private static final short[] noise_pattern_NX = { - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - EE, - S, - ES - }; - - private static final short[] noise_pattern_XN = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - EE, - FLIP_DIR, - S, - SE - }; - - private static final short[] noise_pattern_XK = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_REQUIRED, - - E, - ES, - FLIP_DIR, - E, - EE, - FLIP_DIR, - S, - SE - }; - - private static final short[] noise_pattern_XX = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - EE, - S, - ES, - FLIP_DIR, - S, - SE - }; - - private static final short[] noise_pattern_KN = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - EE, - SE - }; - - private static final short[] noise_pattern_KK = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_REQUIRED, - - E, - ES, - SS, - FLIP_DIR, - E, - EE, - SE - }; - - private static final short[] noise_pattern_KX = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - EE, - SE, - S, - ES - }; - - private static final short[] noise_pattern_IN = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_EPHEMERAL, - - E, - S, - FLIP_DIR, - E, - EE, - SE - }; - - private static final short[] noise_pattern_IK = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_REQUIRED, - - E, - ES, - S, - SS, - FLIP_DIR, - E, - EE, - SE - }; - - private static final short[] noise_pattern_IX = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL, - - E, - S, - FLIP_DIR, - E, - EE, - SE, - S, - ES - }; - - private static final short[] noise_pattern_XXfallback = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_EPHEM_REQ, - - E, - EE, - S, - SE, - FLIP_DIR, - S, - ES - }; - - private static final short[] noise_pattern_Xnoidh = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_REQUIRED, - - E, - S, - ES, - SS - }; - - private static final short[] noise_pattern_NXnoidh = { - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - S, - EE, - ES - }; - - private static final short[] noise_pattern_XXnoidh = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - S, - EE, - ES, - FLIP_DIR, - S, - SE - }; - - private static final short[] noise_pattern_KXnoidh = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - S, - EE, - SE, - ES - }; - - private static final short[] noise_pattern_IKnoidh = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_REQUIRED, - - E, - S, - ES, - SS, - FLIP_DIR, - E, - EE, - SE - }; - - private static final short[] noise_pattern_IXnoidh = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL, - - E, - S, - FLIP_DIR, - E, - S, - EE, - SE, - ES - }; - - private static final short[] noise_pattern_NNhfs = { - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - EE, - FF - }; - - private static final short[] noise_pattern_NKhfs = { - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID | - FLAG_REMOTE_REQUIRED, - - E, - F, - ES, - FLIP_DIR, - E, - F, - EE, - FF - }; - - private static final short[] noise_pattern_NXhfs = { - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - EE, - FF, - S, - ES - }; - - private static final short[] noise_pattern_XNhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - EE, - FF, - FLIP_DIR, - S, - SE - }; - - private static final short[] noise_pattern_XKhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID | - FLAG_REMOTE_REQUIRED, - - E, - F, - ES, - FLIP_DIR, - E, - F, - EE, - FF, - FLIP_DIR, - S, - SE - }; - - private static final short[] noise_pattern_XXhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - EE, - FF, - S, - ES, - FLIP_DIR, - S, - SE - }; - - private static final short[] noise_pattern_KNhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - EE, - FF, - SE - }; - - private static final short[] noise_pattern_KKhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID | - FLAG_REMOTE_REQUIRED, - - E, - F, - ES, - SS, - FLIP_DIR, - E, - F, - EE, - FF, - SE - }; - - private static final short[] noise_pattern_KXhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - EE, - FF, - SE, - S, - ES - }; - - private static final short[] noise_pattern_INhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - S, - FLIP_DIR, - E, - F, - EE, - FF, - SE - }; - - private static final short[] noise_pattern_IKhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID | - FLAG_REMOTE_REQUIRED, - - E, - F, - ES, - S, - SS, - FLIP_DIR, - E, - F, - EE, - FF, - SE - }; - - private static final short[] noise_pattern_IXhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - S, - FLIP_DIR, - E, - F, - EE, - FF, - SE, - S, - ES - }; - - private static final short[] noise_pattern_XXfallback_hfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_EPHEM_REQ | - FLAG_REMOTE_HYBRID | - FLAG_REMOTE_HYBRID_REQ, - - E, - F, - EE, - FF, - S, - SE, - FLIP_DIR, - S, - ES - }; - - private static final short[] noise_pattern_NXnoidh_hfs = { - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - S, - EE, - FF, - ES - }; - - private static final short[] noise_pattern_XXnoidh_hfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - S, - EE, - FF, - ES, - FLIP_DIR, - S, - SE - }; - - private static final short[] noise_pattern_KXnoidh_hfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - S, - EE, - FF, - SE, - ES - }; - - private static final short[] noise_pattern_IKnoidh_hfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - S, - ES, - SS, - FLIP_DIR, - E, - F, - EE, - FF, - SE - }; - - private static final short[] noise_pattern_IXnoidh_hfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - S, - FLIP_DIR, - E, - F, - S, - EE, - FF, - SE, - ES - }; - - /** - * Look up the description information for a pattern. - * - * @param name The name of the pattern. - * @return The pattern description or null. - */ - public static short[] lookup(String name) - { - if (name.equals("N")) - return noise_pattern_N; - else if (name.equals("K")) - return noise_pattern_K; - else if (name.equals("X")) - return noise_pattern_X; - else if (name.equals("NN")) - return noise_pattern_NN; - else if (name.equals("NK")) - return noise_pattern_NK; - else if (name.equals("NX")) - return noise_pattern_NX; - else if (name.equals("XN")) - return noise_pattern_XN; - else if (name.equals("XK")) - return noise_pattern_XK; - else if (name.equals("XX")) - return noise_pattern_XX; - else if (name.equals("KN")) - return noise_pattern_KN; - else if (name.equals("KK")) - return noise_pattern_KK; - else if (name.equals("KX")) - return noise_pattern_KX; - else if (name.equals("IN")) - return noise_pattern_IN; - else if (name.equals("IK")) - return noise_pattern_IK; - else if (name.equals("IX")) - return noise_pattern_IX; - else if (name.equals("XXfallback")) - return noise_pattern_XXfallback; - else if (name.equals("Xnoidh")) - return noise_pattern_Xnoidh; - else if (name.equals("NXnoidh")) - return noise_pattern_NXnoidh; - else if (name.equals("XXnoidh")) - return noise_pattern_XXnoidh; - else if (name.equals("KXnoidh")) - return noise_pattern_KXnoidh; - else if (name.equals("IKnoidh")) - return noise_pattern_IKnoidh; - else if (name.equals("IXnoidh")) - return noise_pattern_IXnoidh; - else if (name.equals("NNhfs")) - return noise_pattern_NNhfs; - else if (name.equals("NKhfs")) - return noise_pattern_NKhfs; - else if (name.equals("NXhfs")) - return noise_pattern_NXhfs; - else if (name.equals("XNhfs")) - return noise_pattern_XNhfs; - else if (name.equals("XKhfs")) - return noise_pattern_XKhfs; - else if (name.equals("XXhfs")) - return noise_pattern_XXhfs; - else if (name.equals("KNhfs")) - return noise_pattern_KNhfs; - else if (name.equals("KKhfs")) - return noise_pattern_KKhfs; - else if (name.equals("KXhfs")) - return noise_pattern_KXhfs; - else if (name.equals("INhfs")) - return noise_pattern_INhfs; - else if (name.equals("IKhfs")) - return noise_pattern_IKhfs; - else if (name.equals("IXhfs")) - return noise_pattern_IXhfs; - else if (name.equals("XXfallback+hfs")) - return noise_pattern_XXfallback_hfs; - else if (name.equals("NXnoidh+hfs")) - return noise_pattern_NXnoidh_hfs; - else if (name.equals("XXnoidh+hfs")) - return noise_pattern_XXnoidh_hfs; - else if (name.equals("KXnoidh+hfs")) - return noise_pattern_KXnoidh_hfs; - else if (name.equals("IKnoidh+hfs")) - return noise_pattern_IKnoidh_hfs; - else if (name.equals("IXnoidh+hfs")) - return noise_pattern_IXnoidh_hfs; - return null; - } - - /** - * Reverses the local and remote flags for a pattern. - * - * @param flags The flags, assuming that the initiator is "local". - * @return The reversed flags, with the responder now being "local". - */ - public static short reverseFlags(short flags) - { - return (short)(((flags >> 8) & 0x00FF) | ((flags << 8) & 0xFF00)); - } +internal object Pattern { + // Token codes. + const val S: Short = 1 + const val E: Short = 2 + const val EE: Short = 3 + const val ES: Short = 4 + const val SE: Short = 5 + const val SS: Short = 6 + const val F: Short = 7 + const val FF: Short = 8 + const val FLIP_DIR: Short = 255 + + // Pattern flag bits. + const val FLAG_LOCAL_STATIC: Short = 0x0001 + const val FLAG_LOCAL_EPHEMERAL: Short = 0x0002 + const val FLAG_LOCAL_REQUIRED: Short = 0x0004 + const val FLAG_LOCAL_EPHEM_REQ: Short = 0x0008 + const val FLAG_LOCAL_HYBRID: Short = 0x0010 + const val FLAG_LOCAL_HYBRID_REQ: Short = 0x0020 + const val FLAG_REMOTE_STATIC: Short = 0x0100 + const val FLAG_REMOTE_EPHEMERAL: Short = 0x0200 + const val FLAG_REMOTE_REQUIRED: Short = 0x0400 + const val FLAG_REMOTE_EPHEM_REQ: Short = 0x0800 + const val FLAG_REMOTE_HYBRID: Short = 0x1000 + const val FLAG_REMOTE_HYBRID_REQ: Short = 0x2000 + + private fun flags(vararg bits: Short): Short { + var v = 0 + for (b in bits) v = v or b.toInt() + return v.toShort() + } + + private val patterns: Map = mapOf( + "N" to shortArrayOf( + flags(FLAG_LOCAL_EPHEMERAL, FLAG_REMOTE_STATIC, FLAG_REMOTE_REQUIRED), + E, ES + ), + "K" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_REQUIRED, + FLAG_REMOTE_STATIC, FLAG_REMOTE_REQUIRED), + E, ES, SS + ), + "X" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, + FLAG_REMOTE_STATIC, FLAG_REMOTE_REQUIRED), + E, ES, S, SS + ), + "NN" to shortArrayOf( + flags(FLAG_LOCAL_EPHEMERAL, FLAG_REMOTE_EPHEMERAL), + E, FLIP_DIR, E, EE + ), + "NK" to shortArrayOf( + flags(FLAG_LOCAL_EPHEMERAL, FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, + FLAG_REMOTE_REQUIRED), + E, ES, FLIP_DIR, E, EE + ), + "NX" to shortArrayOf( + flags(FLAG_LOCAL_EPHEMERAL, FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL), + E, FLIP_DIR, E, EE, S, ES + ), + "XN" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_REMOTE_EPHEMERAL), + E, FLIP_DIR, E, EE, FLIP_DIR, S, SE + ), + "XK" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_REQUIRED), + E, ES, FLIP_DIR, E, EE, FLIP_DIR, S, SE + ), + "XX" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL), + E, FLIP_DIR, E, EE, S, ES, FLIP_DIR, S, SE + ), + "KN" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_REQUIRED, + FLAG_REMOTE_EPHEMERAL), + E, FLIP_DIR, E, EE, SE + ), + "KK" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_REQUIRED, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_REQUIRED), + E, ES, SS, FLIP_DIR, E, EE, SE + ), + "KX" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_REQUIRED, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL), + E, FLIP_DIR, E, EE, SE, S, ES + ), + "IN" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_REMOTE_EPHEMERAL), + E, S, FLIP_DIR, E, EE, SE + ), + "IK" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_REQUIRED), + E, ES, S, SS, FLIP_DIR, E, EE, SE + ), + "IX" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL), + E, S, FLIP_DIR, E, EE, SE, S, ES + ), + "XXfallback" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_EPHEM_REQ), + E, EE, S, SE, FLIP_DIR, S, ES + ), + "Xnoidh" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, + FLAG_REMOTE_STATIC, FLAG_REMOTE_REQUIRED), + E, S, ES, SS + ), + "NXnoidh" to shortArrayOf( + flags(FLAG_LOCAL_EPHEMERAL, FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL), + E, FLIP_DIR, E, S, EE, ES + ), + "XXnoidh" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL), + E, FLIP_DIR, E, S, EE, ES, FLIP_DIR, S, SE + ), + "KXnoidh" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_REQUIRED, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL), + E, FLIP_DIR, E, S, EE, SE, ES + ), + "IKnoidh" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_REQUIRED), + E, S, ES, SS, FLIP_DIR, E, EE, SE + ), + "IXnoidh" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL), + E, S, FLIP_DIR, E, S, EE, SE, ES + ), + "NNhfs" to shortArrayOf( + flags(FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_HYBRID, + FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_HYBRID), + E, F, FLIP_DIR, E, F, EE, FF + ), + "NKhfs" to shortArrayOf( + flags(FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_HYBRID, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_HYBRID, + FLAG_REMOTE_REQUIRED), + E, F, ES, FLIP_DIR, E, F, EE, FF + ), + "NXhfs" to shortArrayOf( + flags(FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_HYBRID, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_HYBRID), + E, F, FLIP_DIR, E, F, EE, FF, S, ES + ), + "XNhfs" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_HYBRID, + FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_HYBRID), + E, F, FLIP_DIR, E, F, EE, FF, FLIP_DIR, S, SE + ), + "XKhfs" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_HYBRID, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_HYBRID, + FLAG_REMOTE_REQUIRED), + E, F, ES, FLIP_DIR, E, F, EE, FF, FLIP_DIR, S, SE + ), + "XXhfs" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_HYBRID, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_HYBRID), + E, F, FLIP_DIR, E, F, EE, FF, S, ES, FLIP_DIR, S, SE + ), + "KNhfs" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_REQUIRED, + FLAG_LOCAL_HYBRID, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_HYBRID), + E, F, FLIP_DIR, E, F, EE, FF, SE + ), + "KKhfs" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_REQUIRED, + FLAG_LOCAL_HYBRID, FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, + FLAG_REMOTE_HYBRID, FLAG_REMOTE_REQUIRED), + E, F, ES, SS, FLIP_DIR, E, F, EE, FF, SE + ), + "KXhfs" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_REQUIRED, + FLAG_LOCAL_HYBRID, FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, + FLAG_REMOTE_HYBRID), + E, F, FLIP_DIR, E, F, EE, FF, SE, S, ES + ), + "INhfs" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_HYBRID, + FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_HYBRID), + E, F, S, FLIP_DIR, E, F, EE, FF, SE + ), + "IKhfs" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_HYBRID, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_HYBRID, + FLAG_REMOTE_REQUIRED), + E, F, ES, S, SS, FLIP_DIR, E, F, EE, FF, SE + ), + "IXhfs" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_HYBRID, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_HYBRID), + E, F, S, FLIP_DIR, E, F, EE, FF, SE, S, ES + ), + "XXfallback+hfs" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_HYBRID, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_EPHEM_REQ, + FLAG_REMOTE_HYBRID, FLAG_REMOTE_HYBRID_REQ), + E, F, EE, FF, S, SE, FLIP_DIR, S, ES + ), + "NXnoidh+hfs" to shortArrayOf( + flags(FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_HYBRID, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_HYBRID), + E, F, FLIP_DIR, E, F, S, EE, FF, ES + ), + "XXnoidh+hfs" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_HYBRID, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_HYBRID), + E, F, FLIP_DIR, E, F, S, EE, FF, ES, FLIP_DIR, S, SE + ), + "KXnoidh+hfs" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_REQUIRED, + FLAG_LOCAL_HYBRID, FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, + FLAG_REMOTE_HYBRID), + E, F, FLIP_DIR, E, F, S, EE, FF, SE, ES + ), + // Note: FLAG_REMOTE_EPHEMERAL is listed twice in the original Java + // pattern definition. Kept here verbatim — the duplicate or-bit is a + // no-op, so behavior matches the upstream implementation. + "IKnoidh+hfs" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_HYBRID, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_EPHEMERAL, + FLAG_REMOTE_HYBRID), + E, F, S, ES, SS, FLIP_DIR, E, F, EE, FF, SE + ), + "IXnoidh+hfs" to shortArrayOf( + flags(FLAG_LOCAL_STATIC, FLAG_LOCAL_EPHEMERAL, FLAG_LOCAL_HYBRID, + FLAG_REMOTE_STATIC, FLAG_REMOTE_EPHEMERAL, FLAG_REMOTE_HYBRID), + E, F, S, FLIP_DIR, E, F, S, EE, FF, SE, ES + ), + ) + + /** + * Look up the description information for a pattern. + * + * @param name The name of the pattern. + * @return The pattern description or null. + */ + @JvmStatic + fun lookup(name: String): ShortArray? = patterns[name] + + /** + * Reverses the local and remote flags for a pattern. + * + * @param flags The flags, assuming that the initiator is "local". + * @return The reversed flags, with the responder now being "local". + */ + @JvmStatic + fun reverseFlags(flags: Short): Short { + val v = flags.toInt() and 0xFFFF + return (((v shr 8) and 0x00FF) or ((v shl 8) and 0xFF00)).toShort() + } }