mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2025-08-17 17:05:50 +00:00
Fix RTSP parser and connection bugs
This commit is contained in:
parent
5a97188197
commit
6571708eb5
@ -37,6 +37,7 @@ typedef struct _RTSP_MESSAGE {
|
||||
char *protocol;
|
||||
POPTION_ITEM options;
|
||||
char *payload;
|
||||
int payloadLength;
|
||||
|
||||
char* messageBuffer;
|
||||
|
||||
@ -54,10 +55,10 @@ typedef struct _RTSP_MESSAGE {
|
||||
} message;
|
||||
} RTSP_MESSAGE, *PRTSP_MESSAGE;
|
||||
|
||||
int parseRtspMessage(PRTSP_MESSAGE msg, char *rtspMessage);
|
||||
int parseRtspMessage(PRTSP_MESSAGE msg, char *rtspMessage, int length);
|
||||
void freeMessage(PRTSP_MESSAGE msg);
|
||||
void createRtspResponse(PRTSP_MESSAGE msg, char* messageBuffer, int flags, char *protocol, int statusCode, char *statusString, int sequenceNumber, POPTION_ITEM optionsHead, char *payload);
|
||||
void createRtspRequest(PRTSP_MESSAGE msg, char* messageBuffer, int flags, char *command, char *target, char *protocol, int sequenceNumber, POPTION_ITEM optionsHead, char *payload);
|
||||
void createRtspResponse(PRTSP_MESSAGE msg, char* messageBuffer, int flags, char *protocol, int statusCode, char *statusString, int sequenceNumber, POPTION_ITEM optionsHead, char *payload, int payloadLength);
|
||||
void createRtspRequest(PRTSP_MESSAGE msg, char* messageBuffer, int flags, char *command, char *target, char *protocol, int sequenceNumber, POPTION_ITEM optionsHead, char *payload, int payloadLength);
|
||||
char *getOptionContent(POPTION_ITEM optionsHead, char *option);
|
||||
void insertOption(POPTION_ITEM *optionsHead, POPTION_ITEM opt);
|
||||
void freeOptionList(POPTION_ITEM optionsHead);
|
||||
|
@ -4,14 +4,15 @@
|
||||
static SOCKET sock = INVALID_SOCKET;
|
||||
static IP_ADDRESS remoteAddr;
|
||||
static int currentSeqNumber = 1;
|
||||
static char* rtspTargetUrl;
|
||||
static char rtspTargetUrl[256];
|
||||
static char sessionIdString[16];
|
||||
static int hasSessionId = 0;
|
||||
|
||||
// GFE 2.1.1
|
||||
#define RTSP_CLIENT_VERSION 10
|
||||
#define RTSP_CLIENT_VERSION_S "10"
|
||||
|
||||
#define RTSP_MAX_RESP_SIZE 1024
|
||||
#define RTSP_MAX_RESP_SIZE 16384
|
||||
|
||||
static POPTION_ITEM createOptionItem(char* option, char* content)
|
||||
{
|
||||
@ -58,10 +59,15 @@ static int addOption(PRTSP_MESSAGE msg, char* option, char* content)
|
||||
|
||||
static int initializeRtspRequest(PRTSP_MESSAGE msg, char* command, char* target)
|
||||
{
|
||||
char sequenceNumberStr[16];
|
||||
|
||||
// FIXME: Hacked CSeq attribute due to RTSP parser bug
|
||||
createRtspRequest(msg, NULL, 0, command, target, "RTSP/1.0",
|
||||
currentSeqNumber++, NULL, NULL);
|
||||
0, NULL, NULL, 0);
|
||||
|
||||
if (!addOption(msg, "X-GS-ClientVersion", RTSP_CLIENT_VERSION_S)) {
|
||||
sprintf(sequenceNumberStr, "%d", currentSeqNumber++);
|
||||
if (!addOption(msg, "CSeq", sequenceNumberStr) ||
|
||||
!addOption(msg, "X-GS-ClientVersion", RTSP_CLIENT_VERSION_S)) {
|
||||
freeMessage(msg);
|
||||
return 0;
|
||||
}
|
||||
@ -113,7 +119,7 @@ static int transactRtspMessage(PRTSP_MESSAGE request, PRTSP_MESSAGE response) {
|
||||
}
|
||||
}
|
||||
|
||||
if (parseRtspMessage(response, responseBuffer) == RTSP_ERROR_SUCCESS) {
|
||||
if (parseRtspMessage(response, responseBuffer, offset) == RTSP_ERROR_SUCCESS) {
|
||||
// Successfully parsed response
|
||||
ret = 1;
|
||||
}
|
||||
@ -178,7 +184,7 @@ static int setupStream(PRTSP_MESSAGE response, char* target) {
|
||||
|
||||
ret = initializeRtspRequest(&request, "SETUP", target);
|
||||
if (ret != 0) {
|
||||
if (sessionIdString[0] != 0) {
|
||||
if (hasSessionId) {
|
||||
if (!addOption(&request, "Session", sessionIdString)) {
|
||||
ret = 0;
|
||||
goto FreeMessage;
|
||||
@ -241,6 +247,7 @@ static int sendVideoAnnounce(PRTSP_MESSAGE response, PSTREAM_CONFIGURATION strea
|
||||
goto FreeMessage;
|
||||
}
|
||||
request.flags |= FLAG_ALLOCATED_PAYLOAD;
|
||||
request.payloadLength = payloadLength;
|
||||
|
||||
sprintf(payloadLengthStr, "%d", payloadLength);
|
||||
if (!addOption(&request, "Content-length", payloadLengthStr)) {
|
||||
@ -257,7 +264,12 @@ static int sendVideoAnnounce(PRTSP_MESSAGE response, PSTREAM_CONFIGURATION strea
|
||||
}
|
||||
|
||||
int performRtspHandshake(IP_ADDRESS addr, PSTREAM_CONFIGURATION streamConfigPtr) {
|
||||
struct in_addr inaddr;
|
||||
|
||||
// Initialize global state
|
||||
remoteAddr = addr;
|
||||
inaddr.S_un.S_addr = addr;
|
||||
sprintf(rtspTargetUrl, "rtsp://%s", inet_ntoa(inaddr));
|
||||
|
||||
{
|
||||
RTSP_MESSAGE response;
|
||||
@ -314,6 +326,9 @@ int performRtspHandshake(IP_ADDRESS addr, PSTREAM_CONFIGURATION streamConfigPtr)
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(sessionIdString, sessionId);
|
||||
hasSessionId = 1;
|
||||
|
||||
freeMessage(&response);
|
||||
}
|
||||
|
||||
|
@ -48,14 +48,13 @@ static int getMessageLength(PRTSP_MESSAGE msg){
|
||||
count += 2;
|
||||
|
||||
/* Add the length of the payload, if any */
|
||||
if (msg->payload != NULL)
|
||||
count += strlen(msg->payload);
|
||||
count += msg->payloadLength;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Given an RTSP message string rtspMessage, parse it into an RTSP_MESSAGE struct msg */
|
||||
int parseRtspMessage(PRTSP_MESSAGE msg, char *rtspMessage) {
|
||||
int parseRtspMessage(PRTSP_MESSAGE msg, char *rtspMessage, int length) {
|
||||
char *token, *protocol, *endCheck, *target, *statusStr, *command, *sequence, *content, flag;
|
||||
char messageEnded = 0, *payload = NULL, *opt = NULL;
|
||||
int statusCode, sequenceNum, exitCode;
|
||||
@ -69,12 +68,15 @@ int parseRtspMessage(PRTSP_MESSAGE msg, char *rtspMessage) {
|
||||
char typeFlag = TOKEN_OPTION;
|
||||
|
||||
/* Put the raw message into a string we can use */
|
||||
char *messageBuffer = malloc((strlen(rtspMessage) + 1) * sizeof(*rtspMessage));
|
||||
char *messageBuffer = malloc(length + 1);
|
||||
if (messageBuffer == NULL) {
|
||||
exitCode = RTSP_ERROR_NO_MEMORY;
|
||||
goto ExitFailure;
|
||||
}
|
||||
strcpy(messageBuffer, rtspMessage);
|
||||
memcpy(messageBuffer, rtspMessage, length);
|
||||
|
||||
// The payload logic depends on a null-terminator at the end
|
||||
messageBuffer[length] = 0;
|
||||
|
||||
/* Get the first token of the message*/
|
||||
token = strtok(messageBuffer, delim);
|
||||
@ -135,7 +137,7 @@ int parseRtspMessage(PRTSP_MESSAGE msg, char *rtspMessage) {
|
||||
}
|
||||
/* Parse remaining options */
|
||||
while (token != NULL){
|
||||
token = strtok(NULL, optDelim);
|
||||
token = strtok(NULL, typeFlag == TOKEN_OPTION ? optDelim : end);
|
||||
if (token != NULL){
|
||||
|
||||
/* The token is an option */
|
||||
@ -194,10 +196,12 @@ int parseRtspMessage(PRTSP_MESSAGE msg, char *rtspMessage) {
|
||||
}
|
||||
/* Package the new parsed message into the struct */
|
||||
if (flag == TYPE_REQUEST){
|
||||
createRtspRequest(msg, messageBuffer, FLAG_ALLOCATED_MESSAGE_BUFFER | FLAG_ALLOCATED_OPTION_ITEMS, command, target, protocol, sequenceNum, options, payload);
|
||||
createRtspRequest(msg, messageBuffer, FLAG_ALLOCATED_MESSAGE_BUFFER | FLAG_ALLOCATED_OPTION_ITEMS, command, target,
|
||||
protocol, sequenceNum, options, payload, payload ? length - (messageBuffer - payload) : 0);
|
||||
}
|
||||
else {
|
||||
createRtspResponse(msg, messageBuffer, FLAG_ALLOCATED_MESSAGE_BUFFER | FLAG_ALLOCATED_OPTION_ITEMS, protocol, statusCode, statusStr, sequenceNum, options, payload);
|
||||
createRtspResponse(msg, messageBuffer, FLAG_ALLOCATED_MESSAGE_BUFFER | FLAG_ALLOCATED_OPTION_ITEMS, protocol, statusCode,
|
||||
statusStr, sequenceNum, options, payload, payload ? length - (messageBuffer - payload) : 0);
|
||||
}
|
||||
return RTSP_ERROR_SUCCESS;
|
||||
|
||||
@ -214,13 +218,14 @@ ExitFailure:
|
||||
|
||||
/* Create new RTSP message struct with response data */
|
||||
void createRtspResponse(PRTSP_MESSAGE msg, char *message, int flags, char *protocol,
|
||||
int statusCode, char *statusString, int sequenceNumber, POPTION_ITEM optionsHead, char *payload) {
|
||||
int statusCode, char *statusString, int sequenceNumber, POPTION_ITEM optionsHead, char *payload, int payloadLength) {
|
||||
msg->type = TYPE_RESPONSE;
|
||||
msg->flags = flags;
|
||||
msg->messageBuffer = message;
|
||||
msg->protocol = protocol;
|
||||
msg->options = optionsHead;
|
||||
msg->payload = payload;
|
||||
msg->payloadLength = payloadLength;
|
||||
msg->sequenceNumber = sequenceNumber;
|
||||
msg->message.response.statusString = statusString;
|
||||
msg->message.response.statusCode = statusCode;
|
||||
@ -228,13 +233,14 @@ void createRtspResponse(PRTSP_MESSAGE msg, char *message, int flags, char *proto
|
||||
|
||||
/* Create new RTSP message struct with request data */
|
||||
void createRtspRequest(PRTSP_MESSAGE msg, char *message, int flags,
|
||||
char *command, char *target, char *protocol, int sequenceNumber, POPTION_ITEM optionsHead, char *payload) {
|
||||
char *command, char *target, char *protocol, int sequenceNumber, POPTION_ITEM optionsHead, char *payload, int payloadLength) {
|
||||
msg->type = TYPE_REQUEST;
|
||||
msg->flags = flags;
|
||||
msg->protocol = protocol;
|
||||
msg->messageBuffer = message;
|
||||
msg->options = optionsHead;
|
||||
msg->payload = payload;
|
||||
msg->payloadLength = payloadLength;
|
||||
msg->sequenceNumber = sequenceNumber;
|
||||
msg->message.request.command = command;
|
||||
msg->message.request.target = target;
|
||||
@ -286,7 +292,7 @@ void freeOptionList(POPTION_ITEM optionsHead){
|
||||
while (current != NULL){
|
||||
temp = current;
|
||||
current = current->next;
|
||||
if (optionsHead->flags & FLAG_ALLOCATED_OPTION_FIELDS){
|
||||
if (temp->flags & FLAG_ALLOCATED_OPTION_FIELDS){
|
||||
free(temp->option);
|
||||
free(temp->content);
|
||||
}
|
||||
@ -299,7 +305,7 @@ char *serializeRtspMessage(PRTSP_MESSAGE msg, int *serializedLength){
|
||||
int size = getMessageLength(msg);
|
||||
char *serializedMessage = malloc(size);
|
||||
POPTION_ITEM current = msg->options;
|
||||
char *statusCodeStr = malloc(sizeof(int));
|
||||
char *statusCodeStr = malloc(4); // 3 characeters + NUL
|
||||
|
||||
if (msg->type == TYPE_REQUEST){
|
||||
/* command [space] */
|
||||
@ -336,9 +342,21 @@ char *serializeRtspMessage(PRTSP_MESSAGE msg, int *serializedLength){
|
||||
strcat(serializedMessage, "\r\n");
|
||||
|
||||
/* payload */
|
||||
strcat(serializedMessage, msg->payload);
|
||||
if (msg->payload != NULL) {
|
||||
int offset;
|
||||
|
||||
// Find end of the RTSP message header
|
||||
for (offset = 0; serializedMessage[offset] != 0; offset++);
|
||||
|
||||
// Add the payload after
|
||||
memcpy(&serializedMessage[offset], msg->payload, msg->payloadLength);
|
||||
|
||||
*serializedLength = offset + msg->payloadLength;
|
||||
}
|
||||
else {
|
||||
*serializedLength = strlen(serializedMessage);
|
||||
}
|
||||
|
||||
*serializedLength = strlen(serializedMessage) + 1;
|
||||
return serializedMessage;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user