mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2025-08-18 09:25:49 +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;
|
char *protocol;
|
||||||
POPTION_ITEM options;
|
POPTION_ITEM options;
|
||||||
char *payload;
|
char *payload;
|
||||||
|
int payloadLength;
|
||||||
|
|
||||||
char* messageBuffer;
|
char* messageBuffer;
|
||||||
|
|
||||||
@ -54,10 +55,10 @@ typedef struct _RTSP_MESSAGE {
|
|||||||
} message;
|
} message;
|
||||||
} RTSP_MESSAGE, *PRTSP_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 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 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);
|
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);
|
char *getOptionContent(POPTION_ITEM optionsHead, char *option);
|
||||||
void insertOption(POPTION_ITEM *optionsHead, POPTION_ITEM opt);
|
void insertOption(POPTION_ITEM *optionsHead, POPTION_ITEM opt);
|
||||||
void freeOptionList(POPTION_ITEM optionsHead);
|
void freeOptionList(POPTION_ITEM optionsHead);
|
||||||
|
@ -4,14 +4,15 @@
|
|||||||
static SOCKET sock = INVALID_SOCKET;
|
static SOCKET sock = INVALID_SOCKET;
|
||||||
static IP_ADDRESS remoteAddr;
|
static IP_ADDRESS remoteAddr;
|
||||||
static int currentSeqNumber = 1;
|
static int currentSeqNumber = 1;
|
||||||
static char* rtspTargetUrl;
|
static char rtspTargetUrl[256];
|
||||||
static char sessionIdString[16];
|
static char sessionIdString[16];
|
||||||
|
static int hasSessionId = 0;
|
||||||
|
|
||||||
// GFE 2.1.1
|
// GFE 2.1.1
|
||||||
#define RTSP_CLIENT_VERSION 10
|
#define RTSP_CLIENT_VERSION 10
|
||||||
#define RTSP_CLIENT_VERSION_S "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)
|
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)
|
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",
|
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);
|
freeMessage(msg);
|
||||||
return 0;
|
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
|
// Successfully parsed response
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
@ -178,7 +184,7 @@ static int setupStream(PRTSP_MESSAGE response, char* target) {
|
|||||||
|
|
||||||
ret = initializeRtspRequest(&request, "SETUP", target);
|
ret = initializeRtspRequest(&request, "SETUP", target);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
if (sessionIdString[0] != 0) {
|
if (hasSessionId) {
|
||||||
if (!addOption(&request, "Session", sessionIdString)) {
|
if (!addOption(&request, "Session", sessionIdString)) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
goto FreeMessage;
|
goto FreeMessage;
|
||||||
@ -241,6 +247,7 @@ static int sendVideoAnnounce(PRTSP_MESSAGE response, PSTREAM_CONFIGURATION strea
|
|||||||
goto FreeMessage;
|
goto FreeMessage;
|
||||||
}
|
}
|
||||||
request.flags |= FLAG_ALLOCATED_PAYLOAD;
|
request.flags |= FLAG_ALLOCATED_PAYLOAD;
|
||||||
|
request.payloadLength = payloadLength;
|
||||||
|
|
||||||
sprintf(payloadLengthStr, "%d", payloadLength);
|
sprintf(payloadLengthStr, "%d", payloadLength);
|
||||||
if (!addOption(&request, "Content-length", payloadLengthStr)) {
|
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) {
|
int performRtspHandshake(IP_ADDRESS addr, PSTREAM_CONFIGURATION streamConfigPtr) {
|
||||||
|
struct in_addr inaddr;
|
||||||
|
|
||||||
|
// Initialize global state
|
||||||
remoteAddr = addr;
|
remoteAddr = addr;
|
||||||
|
inaddr.S_un.S_addr = addr;
|
||||||
|
sprintf(rtspTargetUrl, "rtsp://%s", inet_ntoa(inaddr));
|
||||||
|
|
||||||
{
|
{
|
||||||
RTSP_MESSAGE response;
|
RTSP_MESSAGE response;
|
||||||
@ -314,6 +326,9 @@ int performRtspHandshake(IP_ADDRESS addr, PSTREAM_CONFIGURATION streamConfigPtr)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strcpy(sessionIdString, sessionId);
|
||||||
|
hasSessionId = 1;
|
||||||
|
|
||||||
freeMessage(&response);
|
freeMessage(&response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,14 +48,13 @@ static int getMessageLength(PRTSP_MESSAGE msg){
|
|||||||
count += 2;
|
count += 2;
|
||||||
|
|
||||||
/* Add the length of the payload, if any */
|
/* Add the length of the payload, if any */
|
||||||
if (msg->payload != NULL)
|
count += msg->payloadLength;
|
||||||
count += strlen(msg->payload);
|
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given an RTSP message string rtspMessage, parse it into an RTSP_MESSAGE struct msg */
|
/* 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 *token, *protocol, *endCheck, *target, *statusStr, *command, *sequence, *content, flag;
|
||||||
char messageEnded = 0, *payload = NULL, *opt = NULL;
|
char messageEnded = 0, *payload = NULL, *opt = NULL;
|
||||||
int statusCode, sequenceNum, exitCode;
|
int statusCode, sequenceNum, exitCode;
|
||||||
@ -69,12 +68,15 @@ int parseRtspMessage(PRTSP_MESSAGE msg, char *rtspMessage) {
|
|||||||
char typeFlag = TOKEN_OPTION;
|
char typeFlag = TOKEN_OPTION;
|
||||||
|
|
||||||
/* Put the raw message into a string we can use */
|
/* 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) {
|
if (messageBuffer == NULL) {
|
||||||
exitCode = RTSP_ERROR_NO_MEMORY;
|
exitCode = RTSP_ERROR_NO_MEMORY;
|
||||||
goto ExitFailure;
|
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*/
|
/* Get the first token of the message*/
|
||||||
token = strtok(messageBuffer, delim);
|
token = strtok(messageBuffer, delim);
|
||||||
@ -135,7 +137,7 @@ int parseRtspMessage(PRTSP_MESSAGE msg, char *rtspMessage) {
|
|||||||
}
|
}
|
||||||
/* Parse remaining options */
|
/* Parse remaining options */
|
||||||
while (token != NULL){
|
while (token != NULL){
|
||||||
token = strtok(NULL, optDelim);
|
token = strtok(NULL, typeFlag == TOKEN_OPTION ? optDelim : end);
|
||||||
if (token != NULL){
|
if (token != NULL){
|
||||||
|
|
||||||
/* The token is an option */
|
/* The token is an option */
|
||||||
@ -194,10 +196,12 @@ int parseRtspMessage(PRTSP_MESSAGE msg, char *rtspMessage) {
|
|||||||
}
|
}
|
||||||
/* Package the new parsed message into the struct */
|
/* Package the new parsed message into the struct */
|
||||||
if (flag == TYPE_REQUEST){
|
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 {
|
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;
|
return RTSP_ERROR_SUCCESS;
|
||||||
|
|
||||||
@ -214,13 +218,14 @@ ExitFailure:
|
|||||||
|
|
||||||
/* Create new RTSP message struct with response data */
|
/* Create new RTSP message struct with response data */
|
||||||
void createRtspResponse(PRTSP_MESSAGE msg, char *message, int flags, char *protocol,
|
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->type = TYPE_RESPONSE;
|
||||||
msg->flags = flags;
|
msg->flags = flags;
|
||||||
msg->messageBuffer = message;
|
msg->messageBuffer = message;
|
||||||
msg->protocol = protocol;
|
msg->protocol = protocol;
|
||||||
msg->options = optionsHead;
|
msg->options = optionsHead;
|
||||||
msg->payload = payload;
|
msg->payload = payload;
|
||||||
|
msg->payloadLength = payloadLength;
|
||||||
msg->sequenceNumber = sequenceNumber;
|
msg->sequenceNumber = sequenceNumber;
|
||||||
msg->message.response.statusString = statusString;
|
msg->message.response.statusString = statusString;
|
||||||
msg->message.response.statusCode = statusCode;
|
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 */
|
/* Create new RTSP message struct with request data */
|
||||||
void createRtspRequest(PRTSP_MESSAGE msg, char *message, int flags,
|
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->type = TYPE_REQUEST;
|
||||||
msg->flags = flags;
|
msg->flags = flags;
|
||||||
msg->protocol = protocol;
|
msg->protocol = protocol;
|
||||||
msg->messageBuffer = message;
|
msg->messageBuffer = message;
|
||||||
msg->options = optionsHead;
|
msg->options = optionsHead;
|
||||||
msg->payload = payload;
|
msg->payload = payload;
|
||||||
|
msg->payloadLength = payloadLength;
|
||||||
msg->sequenceNumber = sequenceNumber;
|
msg->sequenceNumber = sequenceNumber;
|
||||||
msg->message.request.command = command;
|
msg->message.request.command = command;
|
||||||
msg->message.request.target = target;
|
msg->message.request.target = target;
|
||||||
@ -286,7 +292,7 @@ void freeOptionList(POPTION_ITEM optionsHead){
|
|||||||
while (current != NULL){
|
while (current != NULL){
|
||||||
temp = current;
|
temp = current;
|
||||||
current = current->next;
|
current = current->next;
|
||||||
if (optionsHead->flags & FLAG_ALLOCATED_OPTION_FIELDS){
|
if (temp->flags & FLAG_ALLOCATED_OPTION_FIELDS){
|
||||||
free(temp->option);
|
free(temp->option);
|
||||||
free(temp->content);
|
free(temp->content);
|
||||||
}
|
}
|
||||||
@ -299,7 +305,7 @@ char *serializeRtspMessage(PRTSP_MESSAGE msg, int *serializedLength){
|
|||||||
int size = getMessageLength(msg);
|
int size = getMessageLength(msg);
|
||||||
char *serializedMessage = malloc(size);
|
char *serializedMessage = malloc(size);
|
||||||
POPTION_ITEM current = msg->options;
|
POPTION_ITEM current = msg->options;
|
||||||
char *statusCodeStr = malloc(sizeof(int));
|
char *statusCodeStr = malloc(4); // 3 characeters + NUL
|
||||||
|
|
||||||
if (msg->type == TYPE_REQUEST){
|
if (msg->type == TYPE_REQUEST){
|
||||||
/* command [space] */
|
/* command [space] */
|
||||||
@ -336,9 +342,21 @@ char *serializeRtspMessage(PRTSP_MESSAGE msg, int *serializedLength){
|
|||||||
strcat(serializedMessage, "\r\n");
|
strcat(serializedMessage, "\r\n");
|
||||||
|
|
||||||
/* payload */
|
/* 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;
|
return serializedMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user