in native/src/sslcontext.c [1443:1522]
static int initProtocols(JNIEnv *e, const tcn_ssl_ctxt_t *c, unsigned char **proto_data,
unsigned int *proto_len, jobjectArray protos) {
int i;
unsigned char *p_data;
/*
* We start with allocate 128 bytes which should be good enough for most use-cases while still be pretty low.
* We will call realloc to increate this if needed.
*/
size_t p_data_size = 128;
size_t p_data_len = 0;
jstring proto_string;
const char *proto_chars;
size_t proto_chars_len;
int cnt;
if (protos == NULL) {
// Guard against NULL protos.
return -1;
}
cnt = (*e)->GetArrayLength(e, protos);
if (cnt == 0) {
// if cnt is 0 we not need to continue and can just fail fast.
return -1;
}
p_data = (unsigned char *) malloc(p_data_size);
if (p_data == NULL) {
// Not enough memory?
return -1;
}
for (i = 0; i < cnt; ++i) {
proto_string = (jstring) (*e)->GetObjectArrayElement(e, protos, i);
proto_chars = (*e)->GetStringUTFChars(e, proto_string, 0);
proto_chars_len = strlen(proto_chars);
if (proto_chars_len > 0 && proto_chars_len <= MAX_ALPN_PROTO_SIZE) {
// We need to add +1 as each protocol is prefixed by it's length (unsigned char).
// For all except of the last one we already have the extra space as everything is
// delimited by ','.
p_data_len += 1 + proto_chars_len;
if (p_data_len > p_data_size) {
// double size
p_data_size <<= 1;
p_data = realloc(p_data, p_data_size);
if (p_data == NULL) {
// Not enough memory?
(*e)->ReleaseStringUTFChars(e, proto_string, proto_chars);
break;
}
}
// Write the length of the protocol and then increment before memcpy the protocol itself.
*p_data = proto_chars_len;
++p_data;
memcpy(p_data, proto_chars, proto_chars_len);
p_data += proto_chars_len;
}
// Release the string to prevent memory leaks
(*e)->ReleaseStringUTFChars(e, proto_string, proto_chars);
}
if (p_data == NULL) {
// Something went wrong so update the proto_len and return -1
*proto_len = 0;
return -1;
} else {
if (*proto_data != NULL) {
// Free old data
free(*proto_data);
}
// Decrement pointer again as we incremented it while creating the protocols in wire format.
p_data -= p_data_len;
*proto_data = p_data;
*proto_len = p_data_len;
return 0;
}
}