Dynamically allocate the RTSP response buffer

This commit is contained in:
Cameron Gutman
2020-04-29 19:58:50 -07:00
parent 247b1fe0e3
commit 7d0458a16b
3 changed files with 47 additions and 24 deletions
+1
View File
@@ -55,6 +55,7 @@ extern int AudioPacketDuration;
int serviceEnetHost(ENetHost* client, ENetEvent* event, enet_uint32 timeoutMs); int serviceEnetHost(ENetHost* client, ENetEvent* event, enet_uint32 timeoutMs);
int extractVersionQuadFromString(const char* string, int* quad); int extractVersionQuadFromString(const char* string, int* quad);
int isReferenceFrameInvalidationEnabled(void); int isReferenceFrameInvalidationEnabled(void);
void* extendBuffer(void* ptr, size_t newSize);
void fixupMissingCallbacks(PDECODER_RENDERER_CALLBACKS* drCallbacks, PAUDIO_RENDERER_CALLBACKS* arCallbacks, void fixupMissingCallbacks(PDECODER_RENDERER_CALLBACKS* drCallbacks, PAUDIO_RENDERER_CALLBACKS* arCallbacks,
PCONNECTION_LISTENER_CALLBACKS* clCallbacks); PCONNECTION_LISTENER_CALLBACKS* clCallbacks);
+8
View File
@@ -63,6 +63,14 @@ int extractVersionQuadFromString(const char* string, int* quad) {
return 0; return 0;
} }
void* extendBuffer(void* ptr, size_t newSize) {
void* newBuf = realloc(ptr, newSize);
if (newBuf == NULL && ptr != NULL) {
free(ptr);
}
return newBuf;
}
int isReferenceFrameInvalidationEnabled(void) { int isReferenceFrameInvalidationEnabled(void) {
LC_ASSERT(NegotiatedVideoFormat != 0); LC_ASSERT(NegotiatedVideoFormat != 0);
return ((NegotiatedVideoFormat & VIDEO_FORMAT_MASK_H264) && (VideoCallbacks.capabilities & CAPABILITY_REFERENCE_FRAME_INVALIDATION_AVC)) || return ((NegotiatedVideoFormat & VIDEO_FORMAT_MASK_H264) && (VideoCallbacks.capabilities & CAPABILITY_REFERENCE_FRAME_INVALIDATION_AVC)) ||
+38 -24
View File
@@ -3,14 +3,12 @@
#include <enet/enet.h> #include <enet/enet.h>
#define RTSP_MAX_RESP_SIZE 49152
#define RTSP_TIMEOUT_SEC 10 #define RTSP_TIMEOUT_SEC 10
static int currentSeqNumber; static int currentSeqNumber;
static char rtspTargetUrl[256]; static char rtspTargetUrl[256];
static char sessionIdString[16]; static char sessionIdString[16];
static int hasSessionId; static int hasSessionId;
static char responseBuffer[RTSP_MAX_RESP_SIZE];
static int rtspClientVersion; static int rtspClientVersion;
static char urlAddr[URLSAFESTRING_LEN]; static char urlAddr[URLSAFESTRING_LEN];
static int useEnet; static int useEnet;
@@ -106,6 +104,11 @@ static int transactRtspMessageEnet(PRTSP_MESSAGE request, PRTSP_MESSAGE response
char* payload; char* payload;
int payloadLength; int payloadLength;
int ret; int ret;
char* responseBuffer;
*error = -1;
ret = 0;
responseBuffer = NULL;
// We're going to handle the payload separately, so temporarily set the payload to NULL // We're going to handle the payload separately, so temporarily set the payload to NULL
payload = request->payload; payload = request->payload;
@@ -116,21 +119,18 @@ static int transactRtspMessageEnet(PRTSP_MESSAGE request, PRTSP_MESSAGE response
// Serialize the RTSP message into a message buffer // Serialize the RTSP message into a message buffer
serializedMessage = serializeRtspMessage(request, &messageLen); serializedMessage = serializeRtspMessage(request, &messageLen);
if (serializedMessage == NULL) { if (serializedMessage == NULL) {
ret = 0;
goto Exit; goto Exit;
} }
// Create the reliable packet that describes our outgoing message // Create the reliable packet that describes our outgoing message
packet = enet_packet_create(serializedMessage, messageLen, ENET_PACKET_FLAG_RELIABLE); packet = enet_packet_create(serializedMessage, messageLen, ENET_PACKET_FLAG_RELIABLE);
if (packet == NULL) { if (packet == NULL) {
ret = 0;
goto Exit; goto Exit;
} }
// Send the message // Send the message
if (enet_peer_send(peer, 0, packet) < 0) { if (enet_peer_send(peer, 0, packet) < 0) {
enet_packet_destroy(packet); enet_packet_destroy(packet);
ret = 0;
goto Exit; goto Exit;
} }
enet_host_flush(client); enet_host_flush(client);
@@ -139,14 +139,12 @@ static int transactRtspMessageEnet(PRTSP_MESSAGE request, PRTSP_MESSAGE response
if (payload != NULL) { if (payload != NULL) {
packet = enet_packet_create(payload, payloadLength, ENET_PACKET_FLAG_RELIABLE); packet = enet_packet_create(payload, payloadLength, ENET_PACKET_FLAG_RELIABLE);
if (packet == NULL) { if (packet == NULL) {
ret = 0;
goto Exit; goto Exit;
} }
// Send the payload // Send the payload
if (enet_peer_send(peer, 0, packet) < 0) { if (enet_peer_send(peer, 0, packet) < 0) {
enet_packet_destroy(packet); enet_packet_destroy(packet);
ret = 0;
goto Exit; goto Exit;
} }
@@ -157,13 +155,13 @@ static int transactRtspMessageEnet(PRTSP_MESSAGE request, PRTSP_MESSAGE response
if (serviceEnetHost(client, &event, RTSP_TIMEOUT_SEC * 1000) <= 0 || if (serviceEnetHost(client, &event, RTSP_TIMEOUT_SEC * 1000) <= 0 ||
event.type != ENET_EVENT_TYPE_RECEIVE) { event.type != ENET_EVENT_TYPE_RECEIVE) {
Limelog("Failed to receive RTSP reply\n"); Limelog("Failed to receive RTSP reply\n");
ret = 0;
goto Exit; goto Exit;
} }
if (event.packet->dataLength > RTSP_MAX_RESP_SIZE) { responseBuffer = malloc(event.packet->dataLength);
Limelog("RTSP message too long\n"); if (responseBuffer == NULL) {
ret = 0; Limelog("Failed to allocate RTSP response buffer\n");
enet_packet_destroy(event.packet);
goto Exit; goto Exit;
} }
@@ -178,13 +176,13 @@ static int transactRtspMessageEnet(PRTSP_MESSAGE request, PRTSP_MESSAGE response
if (serviceEnetHost(client, &event, RTSP_TIMEOUT_SEC * 1000) <= 0 || if (serviceEnetHost(client, &event, RTSP_TIMEOUT_SEC * 1000) <= 0 ||
event.type != ENET_EVENT_TYPE_RECEIVE) { event.type != ENET_EVENT_TYPE_RECEIVE) {
Limelog("Failed to receive RTSP reply payload\n"); Limelog("Failed to receive RTSP reply payload\n");
ret = 0;
goto Exit; goto Exit;
} }
if (event.packet->dataLength + offset > RTSP_MAX_RESP_SIZE) { responseBuffer = extendBuffer(responseBuffer, event.packet->dataLength + offset);
Limelog("RTSP message payload too long\n"); if (responseBuffer == NULL) {
ret = 0; Limelog("Failed to extend RTSP response buffer\n");
enet_packet_destroy(event.packet);
goto Exit; goto Exit;
} }
@@ -200,7 +198,6 @@ static int transactRtspMessageEnet(PRTSP_MESSAGE request, PRTSP_MESSAGE response
} }
else { else {
Limelog("Failed to parse RTSP response\n"); Limelog("Failed to parse RTSP response\n");
ret = 0;
} }
Exit: Exit:
@@ -213,18 +210,27 @@ Exit:
free(serializedMessage); free(serializedMessage);
} }
// Free the response buffer
if (responseBuffer != NULL) {
free(responseBuffer);
}
return ret; return ret;
} }
// Send RTSP message and get response over TCP // Send RTSP message and get response over TCP
static int transactRtspMessageTcp(PRTSP_MESSAGE request, PRTSP_MESSAGE response, int expectingPayload, int* error) { static int transactRtspMessageTcp(PRTSP_MESSAGE request, PRTSP_MESSAGE response, int expectingPayload, int* error) {
SOCK_RET err; SOCK_RET err;
int ret = 0; int ret;
int offset; int offset;
char* serializedMessage = NULL; char* serializedMessage = NULL;
int messageLen; int messageLen;
char* responseBuffer;
int responseBufferSize;
*error = -1; *error = -1;
ret = 0;
responseBuffer = NULL;
sock = connectTcpSocket(&RemoteAddr, RemoteAddrLen, 48010, RTSP_TIMEOUT_SEC); sock = connectTcpSocket(&RemoteAddr, RemoteAddrLen, 48010, RTSP_TIMEOUT_SEC);
if (sock == INVALID_SOCKET) { if (sock == INVALID_SOCKET) {
@@ -252,8 +258,18 @@ static int transactRtspMessageTcp(PRTSP_MESSAGE request, PRTSP_MESSAGE response,
// Read the response until the server closes the connection // Read the response until the server closes the connection
offset = 0; offset = 0;
responseBufferSize = 0;
for (;;) { for (;;) {
err = recv(sock, &responseBuffer[offset], RTSP_MAX_RESP_SIZE - offset, 0); if (offset >= responseBufferSize) {
responseBufferSize = offset + 16384;
responseBuffer = extendBuffer(responseBuffer, responseBufferSize);
if (responseBuffer == NULL) {
Limelog("Failed to allocate RTSP response buffer\n");
goto Exit;
}
}
err = recv(sock, &responseBuffer[offset], responseBufferSize - offset, 0);
if (err < 0) { if (err < 0) {
// Error reading // Error reading
*error = LastSocketError(); *error = LastSocketError();
@@ -267,12 +283,6 @@ static int transactRtspMessageTcp(PRTSP_MESSAGE request, PRTSP_MESSAGE response,
else { else {
offset += err; offset += err;
} }
// Warn if the RTSP message is too big
if (offset == RTSP_MAX_RESP_SIZE) {
Limelog("RTSP message too long\n");
goto Exit;
}
} }
if (parseRtspMessage(response, responseBuffer, offset) == RTSP_ERROR_SUCCESS) { if (parseRtspMessage(response, responseBuffer, offset) == RTSP_ERROR_SUCCESS) {
@@ -288,6 +298,10 @@ Exit:
free(serializedMessage); free(serializedMessage);
} }
if (responseBuffer != NULL) {
free(responseBuffer);
}
closeSocket(sock); closeSocket(sock);
sock = INVALID_SOCKET; sock = INVALID_SOCKET;
return ret; return ret;