3
3
import io .netty .buffer .ByteBuf ;
4
4
import io .netty .buffer .ByteBufAllocator ;
5
5
import io .netty .buffer .ByteBufUtil ;
6
+ import io .netty .buffer .Unpooled ;
7
+ import io .netty .util .CharsetUtil ;
6
8
import io .rsocket .buffer .TupleByteBuf ;
7
9
import io .rsocket .util .CharByteBufUtil ;
8
10
@@ -14,6 +16,8 @@ public class AuthMetadataFlyweight {
14
16
static final int USERNAME_BYTES_LENGTH = 1 ;
15
17
static final int AUTH_TYPE_ID_LENGTH = 1 ;
16
18
19
+ static final char [] EMPTY_CHARS_ARRAY = new char [0 ];
20
+
17
21
private AuthMetadataFlyweight () {}
18
22
19
23
/**
@@ -80,7 +84,7 @@ public static ByteBuf encodeMetadata(
80
84
/**
81
85
* Encode a Authentication CompositeMetadata payload using Simple Authentication format
82
86
*
83
- * @throws IllegalArgumentException if username length is greater than 128
87
+ * @throws IllegalArgumentException if username length is greater than 256
84
88
* @param allocator the {@link ByteBufAllocator} to use to create intermediate buffers as needed.
85
89
* @param username the char sequence which represents user name.
86
90
* @param password the char sequence which represents user password.
@@ -89,9 +93,9 @@ public static ByteBuf encodeSimpleMetadata(
89
93
ByteBufAllocator allocator , char [] username , char [] password ) {
90
94
91
95
int usernameLength = CharByteBufUtil .utf8Bytes (username );
92
- if (usernameLength > 128 ) {
96
+ if (usernameLength > 256 ) {
93
97
throw new IllegalArgumentException (
94
- "Username should be shorter than or equal to 128 bytes length in UTF-8 encoding" );
98
+ "Username should be shorter than or equal to 256 bytes length in UTF-8 encoding" );
95
99
}
96
100
97
101
int passwordLength = CharByteBufUtil .utf8Bytes (password );
@@ -152,4 +156,183 @@ public static ByteBuf encodeMetadataWithCompression(
152
156
return AuthMetadataFlyweight .encodeMetadata (allocator , wkn , metadata );
153
157
}
154
158
}
159
+
160
+ /**
161
+ * Get the first {@code byte} from a {@link ByteBuf} and check whether it is length or {@link
162
+ * WellKnownAuthType}. Assuming said buffer properly contains such a {@code byte}
163
+ *
164
+ * @param metadata byteBuf used to get information from
165
+ */
166
+ public static boolean isWellKnownAuthType (ByteBuf metadata ) {
167
+ byte lengthOrId = metadata .getByte (0 );
168
+ return (lengthOrId & STREAM_METADATA_LENGTH_MASK ) != lengthOrId ;
169
+ }
170
+
171
+ /**
172
+ * Read first byte from the given {@code metadata} and tries to convert it's value to {@link
173
+ * WellKnownAuthType}.
174
+ *
175
+ * @param metadata given metadata buffer to read from
176
+ * @return Return on of the know Auth types or {@link WellKnownAuthType#UNPARSEABLE_AUTH_TYPE} if
177
+ * field's value is length or unknown auth type
178
+ * @throws IllegalStateException if not enough readable bytes in the given ByteBuf
179
+ */
180
+ public static WellKnownAuthType decodeWellKnownAuthType (ByteBuf metadata ) {
181
+ if (metadata .readableBytes () < 1 ) {
182
+ throw new IllegalStateException (
183
+ "Unable to decode Well Know Auth type. Not enough readable bytes" );
184
+ }
185
+ byte lengthOrId = metadata .readByte ();
186
+ int normalizedId = (byte ) (lengthOrId & STREAM_METADATA_LENGTH_MASK );
187
+
188
+ if (normalizedId != lengthOrId ) {
189
+ return WellKnownAuthType .fromIdentifier (normalizedId );
190
+ }
191
+
192
+ return WellKnownAuthType .UNPARSEABLE_AUTH_TYPE ;
193
+ }
194
+
195
+ /**
196
+ * Read up to 129 bytes from the given metadata in order to get the custom Auth Type
197
+ *
198
+ * @param metadata
199
+ * @return
200
+ */
201
+ public static CharSequence decodeCustomAuthType (ByteBuf metadata ) {
202
+ if (metadata .readableBytes () < 2 ) {
203
+ throw new IllegalStateException (
204
+ "Unable to decode custom Auth type. Not enough readable bytes" );
205
+ }
206
+
207
+ byte encodedLength = metadata .readByte ();
208
+ if (encodedLength < 0 ) {
209
+ throw new IllegalStateException (
210
+ "Unable to decode custom Auth type. Incorrect auth type length" );
211
+ }
212
+
213
+ // encoded length is realLength - 1 in order to avoid intersection with 0x00 authtype
214
+ int realLength = encodedLength + 1 ;
215
+ if (metadata .readableBytes () < realLength ) {
216
+ throw new IllegalArgumentException (
217
+ "Unable to decode custom Auth type. Malformed length or auth type string" );
218
+ }
219
+
220
+ return metadata .readCharSequence (realLength , CharsetUtil .US_ASCII );
221
+ }
222
+
223
+ /**
224
+ * Read all remaining {@code bytes} from the given {@link ByteBuf} and return sliced
225
+ * representation of a payload
226
+ *
227
+ * @param metadata metadata to get payload from. Please note, the {@code metadata#readIndex}
228
+ * should be set to the beginning of the payload bytes
229
+ * @return sliced {@link ByteBuf} or {@link Unpooled#EMPTY_BUFFER} if no bytes readable in the
230
+ * given one
231
+ */
232
+ public static ByteBuf decodePayload (ByteBuf metadata ) {
233
+ if (metadata .readableBytes () == 0 ) {
234
+ return Unpooled .EMPTY_BUFFER ;
235
+ }
236
+
237
+ return metadata .readSlice (metadata .readableBytes ());
238
+ }
239
+
240
+ /**
241
+ * Read up to 257 {@code bytes} from the given {@link ByteBuf} where the first byte is username
242
+ * length and the subsequent number of bytes equal to decoded length
243
+ *
244
+ * @param simpleAuthMetadata the given metadata to read username from. Please note, the {@code
245
+ * simpleAuthMetadata#readIndex} should be set to the username length byte
246
+ * @return sliced {@link ByteBuf} or {@link Unpooled#EMPTY_BUFFER} if username length is zero
247
+ */
248
+ public static ByteBuf decodeUsername (ByteBuf simpleAuthMetadata ) {
249
+ short usernameLength = decodeUsernameLength (simpleAuthMetadata );
250
+
251
+ if (usernameLength == 0 ) {
252
+ return Unpooled .EMPTY_BUFFER ;
253
+ }
254
+
255
+ return simpleAuthMetadata .readSlice (usernameLength );
256
+ }
257
+
258
+ /**
259
+ * Read all the remaining {@code byte}s from the given {@link ByteBuf} which represents user's
260
+ * password
261
+ *
262
+ * @param simpleAuthMetadata the given metadata to read password from. Please note, the {@code
263
+ * simpleAuthMetadata#readIndex} should be set to the beginning of the password bytes
264
+ * @return sliced {@link ByteBuf} or {@link Unpooled#EMPTY_BUFFER} if password length is zero
265
+ */
266
+ public static ByteBuf decodePassword (ByteBuf simpleAuthMetadata ) {
267
+ if (simpleAuthMetadata .readableBytes () == 0 ) {
268
+ return Unpooled .EMPTY_BUFFER ;
269
+ }
270
+
271
+ return simpleAuthMetadata .readSlice (simpleAuthMetadata .readableBytes ());
272
+ }
273
+ /**
274
+ * Read up to 257 {@code bytes} from the given {@link ByteBuf} where the first byte is username
275
+ * length and the subsequent number of bytes equal to decoded length
276
+ *
277
+ * @param simpleAuthMetadata the given metadata to read username from. Please note, the {@code
278
+ * simpleAuthMetadata#readIndex} should be set to the username length byte
279
+ * @return {@code char[]} which represents UTF-8 username
280
+ */
281
+ public static char [] decodeUsernameAsCharArray (ByteBuf simpleAuthMetadata ) {
282
+ short usernameLength = decodeUsernameLength (simpleAuthMetadata );
283
+
284
+ if (usernameLength == 0 ) {
285
+ return EMPTY_CHARS_ARRAY ;
286
+ }
287
+
288
+ return CharByteBufUtil .readUtf8 (simpleAuthMetadata , usernameLength );
289
+ }
290
+
291
+ /**
292
+ * Read all the remaining {@code byte}s from the given {@link ByteBuf} which represents user's
293
+ * password
294
+ *
295
+ * @param simpleAuthMetadata the given metadata to read username from. Please note, the {@code
296
+ * simpleAuthMetadata#readIndex} should be set to the beginning of the password bytes
297
+ * @return {@code char[]} which represents UTF-8 password
298
+ */
299
+ public static char [] decodePasswordAsCharArray (ByteBuf simpleAuthMetadata ) {
300
+ if (simpleAuthMetadata .readableBytes () == 0 ) {
301
+ return EMPTY_CHARS_ARRAY ;
302
+ }
303
+
304
+ return CharByteBufUtil .readUtf8 (simpleAuthMetadata , simpleAuthMetadata .readableBytes ());
305
+ }
306
+
307
+ /**
308
+ * Read all the remaining {@code bytes} from the given {@link ByteBuf} where the first byte is
309
+ * username length and the subsequent number of bytes equal to decoded length
310
+ *
311
+ * @param bearerAuthMetadata the given metadata to read username from. Please note, the {@code
312
+ * simpleAuthMetadata#readIndex} should be set to the beginning of the password bytes
313
+ * @return {@code char[]} which represents UTF-8 password
314
+ */
315
+ public static char [] decodeBearerTokenAsCharArray (ByteBuf bearerAuthMetadata ) {
316
+ if (bearerAuthMetadata .readableBytes () == 0 ) {
317
+ return EMPTY_CHARS_ARRAY ;
318
+ }
319
+
320
+ return CharByteBufUtil .readUtf8 (bearerAuthMetadata , bearerAuthMetadata .readableBytes ());
321
+ }
322
+
323
+ private static short decodeUsernameLength (ByteBuf simpleAuthMetadata ) {
324
+ if (simpleAuthMetadata .readableBytes () < 1 ) {
325
+ throw new IllegalStateException (
326
+ "Unable to decode custom username. Not enough readable bytes" );
327
+ }
328
+
329
+ short usernameLength = simpleAuthMetadata .readUnsignedByte ();
330
+
331
+ if (simpleAuthMetadata .readableBytes () < usernameLength ) {
332
+ throw new IllegalArgumentException (
333
+ "Unable to decode username. Malformed username length or content" );
334
+ }
335
+
336
+ return usernameLength ;
337
+ }
155
338
}
0 commit comments