NGAPPDU WarningMessageContents编码异常求助(Wireshark解码报错)
问题描述
我尝试将字符串“Severe Earthquake expected immediately”编码为字节流,封装到NGAP PDU的WarningMessageContents中。根据ETSI TS 138 413 V17.11.0 (2025-01)规范,WarningMessageContents定义为WarningMessageContents ::= OCTET STRING (SIZE(1..9600)),但目前遇到问题:Wireshark显示解码内容错误,且页码计算已确认正确。请帮忙排查以下代码可能存在的问题,编码方案的其他规范可参考ETSI TS 123 038 V17.0.0 (2022-04)第5节。
待排查代码
const ( MaxCBSPageSize = 82 // Bytes per page (after GSM 7-bit encoding) MaxPages = 15 // 3GPP TS 23.041 limit MaxMessageBytes = 9600 // Total CBS message size limit ) type WarningMessageContents struct { Value aper.OctetString `aper:"sizeLB:1,sizeUB:9600"` } type OctetString []byte // Function to encode CBS message according to ETSI TS 123 041 func EncodeCBSWarningMessage(message string) (*ngapType.WarningMessageContents, error) { // Calculate number of pages messageLen := len(message) numPages := (messageLen + MaxCBSPageSize - 1) / MaxCBSPageSize // Ceiling division // Strict validation for maximum pages if numPages > 15 { return nil, fmt.Errorf("too many CBS pages (must be <= 15), found: %d", numPages) } // Validate total size if messageLen < 1 || messageLen > 9600 { return nil, errors.New("warning message size out of range (must be between 1 and 9600 bytes)") } // Build CBS formatted message cbsMessage := make([]byte, 0, messageLen+numPages*5) // Pre-allocate with some extra space // First byte is Total Number of Pages cbsMessage = append(cbsMessage, byte(numPages)) // Split message into pages for i := 0; i < numPages; i++ { start := i * MaxCBSPageSize end := start + MaxCBSPageSize if end > messageLen { end = messageLen } // Precise page header according to CBS specifications pageHeader := []byte{ byte(i + 1), // Page Number (1-based) 0x01, // Data Coding Scheme (GSM 7-bit) 0x00, // Language Group (English) } // Append page header cbsMessage = append(cbsMessage, pageHeader...) // Append page content cbsMessage = append(cbsMessage, []byte(message[start:end])...) } // Create WarningMessageContents return &ngapType.WarningMessageContents{ Value: aper.OctetString(cbsMessage), }, nil }
代码问题分析
GSM 7-bit编码未实现
代码直接将原始字符串转为字节数组,但MaxCBSPageSize = 82是GSM 7-bit编码后的每页字节数。GSM 7-bit编码是把8个字符打包成7字节,因此每页能容纳的原始字符数约为82 * 8 /7 ≈93个,而非82个。当前分页逻辑用原始字符数除以82,混淆了原始字符数和编码后字节数,导致分页完全错误。必须先对字符串做GSM 7-bit编码,再按编码后的字节数分页。CBS消息结构不符合规范
根据ETSI TS 123 038第5节,多页CBS的每页头部应包含总页数+当前页号,而非仅在消息开头放一个总页数。正确的每页头部格式应为:[总页数(1字节)] + [当前页号(1字节)] + [DCS(1字节)] + [语言组(1字节)],当前结构会导致Wireshark无法识别分页信息。字符集与编码转换缺失
Go中[]byte(message)默认输出UTF-8编码,但GSM 7-bit编码依赖GSM 03.38字符集,若字符串包含该字符集外的字符,直接转换会导致解码失败。需要先将UTF-8字符串转换为GSM 03.38字符集的字节,再执行7-bit打包。DCS与编码的匹配问题
设置的DCS值0x01对应GSM 7-bit编码,但未处理7-bit编码的填充位(最后一个字节若不足7位需补0),这会导致Wireshark解码时出现字节对齐错误。长度验证逻辑错误
当前验证的是原始字符串长度是否在1-9600之间,但WarningMessageContents的大小限制是编码完成后的整个CBS消息(含所有头部和内容)的字节数,而非原始字符串长度。应在编码完成后检查最终cbsMessage的长度是否符合要求。
内容的提问来源于stack exchange,提问作者van

