BulkDecodeTemplate sets up a context for decoding by taking the template and a binary buffer to be decoded
(ctx context.Context, templateBodyJSON []byte, compressedPayload []byte)
| 110 | |
| 111 | // BulkDecodeTemplate sets up a context for decoding by taking the template and a binary buffer to be decoded |
| 112 | func BulkDecodeTemplate(ctx context.Context, templateBodyJSON []byte, compressedPayload []byte) (tmplContext BulkTemplateContext, err error) { |
| 113 | body := BulkBody{} |
| 114 | err = note.JSONUnmarshal(templateBodyJSON, &body) |
| 115 | if err != nil { |
| 116 | err = fmt.Errorf("couldn't unmarshal bulk template: %w", err) |
| 117 | return |
| 118 | } |
| 119 | if body.NoteFormat != BulkNoteFormatOriginal && body.NoteFormat != BulkNoteFormatFlex && body.NoteFormat != BulkNoteFormatFlexNano { |
| 120 | err = fmt.Errorf("bulk template: unrecognized format: %d", body.NoteFormat) |
| 121 | return |
| 122 | } |
| 123 | |
| 124 | // Set up the context |
| 125 | tmplContext.NoteFormat = body.NoteFormat |
| 126 | tmplContext.Template = body.NoteTemplate |
| 127 | tmplContext.ORIGTemplatePayloadLen = body.NoteTemplatePayloadLen |
| 128 | |
| 129 | // Parse the template if this is the original format, because in that format entries were not self-describing |
| 130 | if body.NoteFormat == BulkNoteFormatOriginal { |
| 131 | err = parseORIGTemplate(ctx, &tmplContext) |
| 132 | if err != nil { |
| 133 | return |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | // 2024-04-11 NF-305 Deal with the odd situation where flexnano format is intentionally snappy-compressed |
| 138 | // because it's being sent over cellular. In this case, we had nowhere to store a flag saying "this is |
| 139 | // compressed" and so we use an in-band method. |
| 140 | isSnappyCompressed := false |
| 141 | snappySig := []byte("snappy$") |
| 142 | snappySigLen := len(snappySig) |
| 143 | if len(compressedPayload) >= snappySigLen && bytes.Equal(snappySig, compressedPayload[:snappySigLen]) { |
| 144 | isSnappyCompressed = true |
| 145 | compressedPayload = compressedPayload[snappySigLen:] |
| 146 | } |
| 147 | |
| 148 | // Decompress the payload if not flex nano, which is sent uncompressed |
| 149 | if body.NoteFormat == BulkNoteFormatFlexNano && !isSnappyCompressed { |
| 150 | tmplContext.Bin = compressedPayload |
| 151 | tmplContext.BinLen = len(tmplContext.Bin) |
| 152 | } else if len(compressedPayload) > 0 { |
| 153 | tmplContext.Bin, err = snappy.Decode(nil, compressedPayload) |
| 154 | tmplContext.BinLen = len(tmplContext.Bin) |
| 155 | if err != nil { |
| 156 | err = fmt.Errorf("bulk decode error '%s': template:%s payload:%v", err, string(templateBodyJSON), compressedPayload) |
| 157 | return |
| 158 | } |
| 159 | if debugDecoding { |
| 160 | logDebug(ctx, "$$$ BULK DATA $$$: decompressed payload from %d to %d", len(compressedPayload), len(tmplContext.Bin)) |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | if debugDecoding { |
| 165 | logDebug(ctx, "Bulk decode: binlen:%d format:%d template: %s\n", tmplContext.BinLen, tmplContext.NoteFormat, tmplContext.Template) |
| 166 | if debugDecodingDetails { |
| 167 | logDebug(ctx, "Bulk decode: bin: %X", tmplContext.Bin) |
| 168 | } |
| 169 | } |