📄 core_mmsh.cpp
字号:
/*
ModuleL: core_mmsh.cxx
ASF donwload and extraction
*/
/* The core routine for ASF download/extraction. */
#include "core_mmsh.h"
#include "../../asfr.h"
#include "../asf_commonh.h"
#include "../asf_helper.h"
#include "../asf_redirection.h"
#include "../asf_net.h"
void core_mmsh(struct JOB_PARM *My_Job)
{
int MyID = My_Job->ThreadID;
struct THREAD_INFO *My_ti = My_Job->ti[MyID];
struct HEADER_INFO *My_hi = My_Job->hi;
struct CUSTOM_INFO_ASF *My_ci = (struct CUSTOM_INFO_ASF*)My_Job->ci;
unsigned int i;
unsigned char Buffer[MAX_CHUNK_SIZE];
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
switch(My_ti->RequestType)
{
case REQUEST_INIT:
My_Job->ciSize = sizeof(struct CUSTOM_INFO_ASF);
break;
case REQUEST_RESET:
memset(My_ci, 0, sizeof(struct CUSTOM_INFO_ASF));
My_ci->ASFContentType = unknown_content;
My_ci->PortNum = MMSH_DEFAULT_PORT;
randomize_guid(My_ci->RandomizedGUID);
break;
case REQUEST_INFORMATION:
{
char *URLPtr;
char *DashPtr;
char *ColonPtr;
char EscapedURL[512];
My_ti->Reply = REPLY_FAIL;
/* Firset treat this as a on-disk redirection file */
parse_redirection(My_Job, NULL, 0);
gui_showstatus(STATUS_INFORMATION, "Parsing URL: '%s'\n", My_Job->URL);
/* replace unescaped characters (e.g. spaces) by escape sequences */
escape_url_string(EscapedURL, My_Job->URL);
URLPtr = EscapedURL;
if (!strnicmp("http://", URLPtr, 7)) URLPtr += 7;
if (!strnicmp("mms://", URLPtr, 6)) URLPtr += 6;
DashPtr = strchr(URLPtr, '/');
if (DashPtr == NULL)
{
DashPtr = URLPtr+strlen(URLPtr);
gui_showstatus(STATUS_CRITICALERROR, "Invalid URL format!\n");
break;
}
else
{
strncpy(My_ci->ServerName, URLPtr, DashPtr-URLPtr);
My_ci->ServerName[DashPtr-URLPtr] = 0;
strcpy(My_ci->File, DashPtr);
ColonPtr = strchr(My_ci->ServerName, ':');
if (ColonPtr != NULL)
{
My_ci->PortNum = (unsigned short)atol(ColonPtr+1);
*ColonPtr = '\0';
if (My_ci->PortNum == 0)
{
gui_showstatus(STATUS_CRITICALERROR, "Invalid URL format!\n");
strcpy(My_ci->ServerName, "");
strcpy(My_ci->File, "");
break;
}
}
} /* url parse finished */
/* parse proxy URL */
if ( strcmp( My_Job->Proxy, "") )
{
char FullPath[512];
if (My_ci->PortNum == MMSH_DEFAULT_PORT)
sprintf(FullPath, "http://%s%s", My_ci->ServerName, My_ci->File);
else
sprintf(FullPath, "http://%s:%d%s", My_ci->ServerName, My_ci->PortNum, My_ci->File);
strcpy(My_ci->File, FullPath);
escape_url_string(EscapedURL, My_Job->Proxy);
URLPtr = EscapedURL;
if (!strnicmp("http://", URLPtr, 7)) URLPtr+=7;
DashPtr = strchr(URLPtr, '/'); /* There should be no '/' in proxy string */
if (DashPtr != NULL)
gui_showstatus(STATUS_CRITICALERROR, "Invalid proxy URL format!\n");
else
{
ColonPtr = strchr(URLPtr, ':');
if (ColonPtr != NULL)
{
unsigned short ProxyPortNum;
ProxyPortNum = (unsigned short)atol(ColonPtr+1);
if (ProxyPortNum == 0)
{
gui_showstatus(STATUS_CRITICALERROR, "Invalid proxy URL format!\n");
strcpy(My_ci->ServerName, "");
strcpy(My_ci->File, "");
}
else
My_ci->PortNum = ProxyPortNum;
}
else
ColonPtr = URLPtr+strlen(URLPtr);
strncpy(My_ci->ServerName, URLPtr, ColonPtr-URLPtr);
My_ci->ServerName[ColonPtr-URLPtr] = 0;
}
} /* proxy parse finished */
if ( strcmp(My_Job->Username, "") || strcmp(My_Job->Password, "") )
{
char PasswordCombo[128];
sprintf(PasswordCombo, "%s:%s", My_Job->Username, My_Job->Password);
base64enc(PasswordCombo,My_ci->Base64Buf);
}
if(Debug) gui_showstatus(STATUS_INFORMATION, "ServerName: '%s'\nPortNum: %d\nFile: '%s'\n",
My_ci->ServerName, My_ci->PortNum, My_ci->File);
/* Attempt to detect if we should call gethostbyname() or gethostbyaddr() */
if(Debug) gui_showstatus(STATUS_INFORMATION, "Resolving host: '%s'\n", My_ci->ServerName);
unsigned int Addr = 0;
struct hostent *hp = NULL;
if (isalpha(My_ci->ServerName[0]))
{
/* Server address is a host name */
hp = gethostbyname(My_ci->ServerName);
if (hp == NULL)
{
gui_showstatus(STATUS_CRITICALERROR, "Unable to resolve host '%s'!\n", My_ci->ServerName);
break;
}
}
else
{
/* Server is a ip address. convert nnn.nnn address to a usable one */
Addr = inet_addr(My_ci->ServerName);
if ((hp = gethostbyaddr((char *)&Addr,4,AF_INET))!=NULL)
strcpy(My_ci->ServerName, hp->h_name);
} /* Gethost finished */
/* Copy the resolved information into the sockaddr_in structure */
if (hp != NULL)
{
memcpy(&(My_ci->Server.sin_addr),hp->h_addr,hp->h_length);
My_ci->Server.sin_family = hp->h_addrtype;
strcpy(My_ci->ServerName, hp->h_name);
}
else
{
memcpy(&(My_ci->Server.sin_addr), &Addr, 4);
My_ci->Server.sin_family = AF_INET;
}
My_ci->Server.sin_port = htons(My_ci->PortNum);
} /* Fall through */
case REQUEST_GETDATA:
{
My_ti->Message = 0;
My_ti->Reply = REPLY_FAIL;
/* Open a socket */
SOCKET ConnSocket;
if ((ConnSocket=my_socket(AF_INET, SOCK_STREAM, 0)) <= 0)
{
gui_showstatus(STATUS_CRITICALERROR, "Socket() failed: %d\n", errno);
break;
}
gui_showstatus(STATUS_INFORMATION, "Connecting to: %s:%d\n", My_ci->ServerName, My_ci->PortNum);
if( my_connect(ConnSocket, (struct sockaddr*)&(My_ci->Server), sizeof(My_ci->Server)) == SOCKET_ERROR )
{
if(My_ci->PortNum == MMSH_DEFAULT_PORT) /* maybe this is a dedicated mmst server, mmsh port(80) is not opened */
My_ti->Reply = REPLY_MMST; /* Try mmst next time */
gui_showstatus(STATUS_CRITICALERROR, "connect() failed: %d\n", errno);
break;
}
/* Prepare a stream to read incoming datas */
struct STREAM_PARM Stream_Parm;
Stream_Parm.RequestType = REQUEST_INIT;
Stream_Parm.conn_socket = ConnSocket;
if( (Stream_Parm.si = (char*)malloc( readfromstream(&Stream_Parm, 0, 0))) == NULL) break;
Stream_Parm.RequestType = REQUEST_RESET;
readfromstream(&Stream_Parm, 0, 0);
Stream_Parm.RequestType = REQUEST_GETDATA;
/* Generate a HTTP request */
unsigned long OffsetHi = 0;
unsigned long OffsetLo = My_ti->SourOffset;
char *BufPtr = (char*)Buffer;
if(OffsetLo == 0) OffsetHi=0xffffffff,OffsetLo=0xffffffff;
if (My_ti->RequestType == REQUEST_GETDATA)
{ /* Generate information for server */
BufPtr+=sprintf(BufPtr,"GET %s HTTP/1.0\r\n", My_ci->File);
if ( ustrcmp(My_ci->Base64Buf, "") ) BufPtr += sprintf(BufPtr,"Authorization: Basic %s\r\n", My_ci->Base64Buf);
BufPtr+=sprintf(BufPtr,"Accept: */*\r\n");
BufPtr+=sprintf(BufPtr,"User-Agent: NSPlayer/4.1.0.3856\r\n");
if ( strcmp(My_Job->Proxy, "") ) BufPtr+=sprintf(BufPtr,"Host: %s\r\n", My_ci->ServerName);
if (My_ci->ASFContentType == prerecorded_content)
BufPtr+=sprintf(BufPtr,"Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=%u:%u,request-context=2,max-duration=0\r\n",(unsigned)OffsetHi,(unsigned)OffsetLo);
if (My_ci->ASFContentType == live_content)
BufPtr+=sprintf(BufPtr,"Pragma: no-cache,rate=1.000000,request-context=2\r\n");
BufPtr+=sprintf(BufPtr,"Pragma: xPlayStrm=1\r\n");
BufPtr+=sprintf(BufPtr,"Pragma: xClientGUID=%s\r\n", My_ci->RandomizedGUID);
BufPtr+=sprintf(BufPtr,"Pragma: stream-switch-count=1\r\n");
BufPtr+=sprintf(BufPtr,"Pragma: stream-switch-entry=ffff:1:0\r\n");
BufPtr+=sprintf(BufPtr,"Connection: Close\r\n\r\n");
}
if (My_ti->RequestType == REQUEST_INFORMATION)
{
BufPtr+=sprintf(BufPtr,"GET %s HTTP/1.0\r\n", My_ci->File);
if ( ustrcmp(My_ci->Base64Buf, "") ) BufPtr += sprintf(BufPtr,"Authorization: Basic %s\r\n", My_ci->Base64Buf);
BufPtr+=sprintf(BufPtr,"Accept: */*\r\n");
BufPtr+=sprintf(BufPtr,"User-Agent: NSPlayer/4.1.0.3856\r\n");
if ( strcmp(My_Job->Proxy, "") ) BufPtr+=sprintf(BufPtr,"Host: %s\r\n", My_ci->ServerName);
BufPtr+=sprintf(BufPtr,"Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=0:0,request-context=1,max-duration=0\r\n");
BufPtr+=sprintf(BufPtr,"Pragma: xClientGUID=%s\r\n", My_ci->RandomizedGUID);
BufPtr+=sprintf(BufPtr,"Connection: Close\r\n\r\n");
}
if (DUMP_HEADERS) /* Dump the outgoing HTTP request */
gui_showstatus(STATUS_INFORMATION, "\nHTTP-Request to send:\n%s", Buffer);
gui_showstatus(STATUS_INFORMATION, "sending request [%d bytes]\n",(int)BufPtr-(int)Buffer);
if ((my_send(ConnSocket,Buffer,((int)BufPtr-(int)Buffer),0)) == SOCKET_ERROR)
{
gui_showstatus(STATUS_CRITICALERROR, "send() failed: %d\n", errno);
my_closesocket(ConnSocket);
free(Stream_Parm.si);
break;
}
gui_showstatus(STATUS_INFORMATION, "Waiting for reply...\n");
char HTTPLine[512];
char HTTPMessage[128] = "<none>";
char Features[256] = "";
char ContentType[256] = "";
char ServerType[256] = "";
char *HDRPtr;
unsigned int ErrorCode = 0;
unsigned int EOL = 0;
unsigned int HDRPos = 0;
unsigned int LinePos = 0;
unsigned int LineNum = 0;
unsigned char ToBreak = 0;
for (;;)
{
unsigned char c;
if (readfromstream(&Stream_Parm, &c, 1) == 1)
{
/* Server is OK, so retry if connect reset */
My_ti->Reply = REPLY_RETRY;
if ((c != '\r') && (c != '\n'))
{
EOL = 0;
HTTPLine[LinePos++] = c;
}
else
HTTPLine[LinePos++] = 0;
if (c == '\n') /* finish of a line */
{
if (EOL == 0) /* if this is first '/n'? 2 '/n' will make this FALSE ,which mean end of HTTP header */
{
LinePos = 0;
EOL = 1;
LineNum++;
HDRPtr = HTTPLine;
if (LineNum == 1) /* Parse first line of HTTP reply */
{
if ((!strnicmp(HDRPtr, "HTTP/1.0 ", 9)) || (!strnicmp(HDRPtr, "HTTP/1.1 ", 9)))
{
HDRPtr += 9;
sscanf(HDRPtr, "%d", &ErrorCode);
HDRPtr += 4;
strcpy(HTTPMessage, HDRPtr);
}
else
gui_showstatus(STATUS_CRITICALERROR, "Illegal server reply! Expected HTTP/1.0 or HTTP/1.1\n");
}
else
{
/* Parse all other lines of HTTP reply , find "Content-Type:" */
if (!strnicmp(HDRPtr, "Content-Type: ", 14))
{
HDRPtr += 14;
strncpy(ContentType, HDRPtr, sizeof(ContentType));
}
if (!strnicmp(HDRPtr, "Pragma: ", 8))
{
HDRPtr += 8;
if (!strnicmp(HDRPtr, "features=", 9))
{
HDRPtr += 9;
strncpy(Features, HDRPtr, sizeof(Features));
}
}
if (!strnicmp(HDRPtr, "Server: ", 8))
{
HDRPtr += 8;
strncpy(ServerType, HDRPtr, sizeof(ServerType));
}
}
}
else
{
Buffer[HDRPos++] = 0;
break;
}
}
Buffer[HDRPos++] = c;
}
else
{
if( !HDRPos ) /* Nothing Received, this is probably a mmst stream */
My_ti->Reply = REPLY_MMST;
gui_showstatus(STATUS_CRITICALERROR, "readfromstream() returned other than 1!\n");
ToBreak = 1;
break;
}
}
if(ToBreak) break;
ToBreak = 0;
gui_showstatus(STATUS_INFORMATION, "reply: %d - %s\n", ErrorCode, HTTPMessage);
/* Dump the incoming HTTP reply */
if (DUMP_HEADERS)
gui_showstatus(STATUS_INFORMATION, "\nHTTP-Reply:\n%s\n", Buffer);
/* Detect reply's content, apply only once */
if(My_ti->RequestType == REQUEST_INFORMATION)
{
if ( !stricmp(ContentType, "application/octet-stream") )
{
if (strstr(Features, "broadcast"))
{
My_ci->ASFContentType = live_content;
My_hi->Resumeable = FALSE;
}
else
{
My_ci->ASFContentType = prerecorded_content;
My_hi->Resumeable = TRUE;
}
}
else /* Then what's it */
{
if (!eos(&Stream_Parm)) /* try to read as much data as fits into the buffer */
{
unsigned char c = 0x00;
unsigned int RedirSize = 0;
unsigned int PrintableCount = 0;
RedirSize = readfromstream(&Stream_Parm, Buffer, MAX_CHUNK_SIZE);
for(i=0 ; i<RedirSize ; c=Buffer[i++]) /* Count all printable chars */
{
if( (c == ' ') || (c == '\t') || (c == '\r') || (c == '\n')) continue;
if(isprint(c)) PrintableCount++;
}
if(PrintableCount >= RedirSize*3/4) /* If printable chars > 3/4, assume it as redirector */
{
gui_showstatus(0, "\n%s", Buffer);
parse_redirection(My_Job, Buffer, RedirSize);
My_ti->Reply = REPLY_RETRY;
}
else
{
gui_showstatus(STATUS_CRITICALERROR, "This is a HTTP content\n");
My_ti->Reply = REPLY_HTTP;
}
}
else
{
gui_showstatus(STATUS_CRITICALERROR, "Unknown content-type: %s\n", ContentType);
}
}
switch(ErrorCode)
{
case 200: /* ok */
break;
case 401:
My_hi->RequirePassword = TRUE;
ToBreak = 1;
break;
case 400: /* Bad Request */
case 404: /* The famous 404 error */
My_ti->Reply = REPLY_MMST;
ToBreak = 1;
break;
case 453: /* "Not enough bandwidth" */
My_ti->Reply = REPLY_RETRY;
ToBreak = 1;
break;
default: /* We dont know what it is */
My_ci->ASFContentType = server_error;
ToBreak = 1;
break;
}
}
if(ToBreak)
{
my_closesocket(ConnSocket);
free(Stream_Parm.si);
break;
}
/* Return if contenttype unknown */
if ( eos(&Stream_Parm) || ((My_ci->ASFContentType != live_content) && (My_ci->ASFContentType != prerecorded_content)) )
{
my_closesocket(ConnSocket);
free(Stream_Parm.si);
break;
}
/* Handle live or prerecorded content */
unsigned long MyFilePointer = 0;
unsigned char TimeCodeString[64]={""};
//unsigned int StartTimeHi = 0xffffffff;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -