#include "sni_split.h" static bool read_u16(const uint8_t* d, size_t len, size_t pos, uint16_t& out) { if (pos + 2 > len) return false; out = (uint16_t(d[pos]) << 8) | d[pos + 1]; return true; } size_t find_sni_split_point(const uint8_t* data, size_t len) { if (len < 6 || data[0] != 0x16) return 0; size_t pos = 5; if (pos >= len || data[pos] != 0x01) return 0; pos += 4; if (pos + 2 + 32 > len) return 0; pos += 2 + 32; if (pos >= len) return 0; uint8_t session_id_len = data[pos]; pos += 1 + session_id_len; uint16_t cipher_len; if (!read_u16(data, len, pos, cipher_len)) return 0; pos += 2 + cipher_len; if (pos >= len) return 0; uint8_t comp_len = data[pos]; pos += 1 + comp_len; uint16_t ext_total_len; if (!read_u16(data, len, pos, ext_total_len)) return 0; pos += 2; size_t ext_end = pos + ext_total_len; if (ext_end > len) ext_end = len; while (pos + 4 <= ext_end) { uint16_t ext_type, ext_len; if (!read_u16(data, len, pos, ext_type)) break; if (!read_u16(data, len, pos + 2, ext_len)) break; size_t ext_data_start = pos + 4; if (ext_type == 0x0000) { size_t p = ext_data_start; uint16_t list_len; if (!read_u16(data, len, p, list_len)) return 0; p += 2; if (p + 3 > len) return 0; uint8_t name_type = data[p]; uint16_t name_len; if (name_type != 0 || !read_u16(data, len, p + 1, name_len)) return 0; size_t name_start = p + 3; size_t name_end = name_start + name_len; if (name_end > len || name_len == 0) return 0; return name_start + (name_len / 2); } pos = ext_data_start + ext_len; } return 0; }