📄 core_mmst.cpp
字号:
/* The core routine for ASF download/extraction. */
#include "core_mmst.h"
#include "../../asfr.h"
#include "../asf_commonh.h"
#include "../asf_helper.h"
#include "../asf_redirection.h"
#include "../asf_net.h"
void core_mmst(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 = MMST_DEFAULT_PORT;
randomize_guid(My_ci->RandomizedGUID);
break;
case REQUEST_INFORMATION:
{
My_ti->Reply = REPLY_FAIL;
char *URLPtr;
char *DashPtr;
char *ColonPtr;
char EscapedURL[512];
/* 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);
strcpy(EscapedURL, My_Job->URL); /* No need to escape, MMST use UNICODE path */
URLPtr = EscapedURL;
if (!strnicmp("mms://", URLPtr, 6)) URLPtr += 6;
if (!strnicmp("mmst://", URLPtr, 7)) URLPtr += 7;
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+1);
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 */
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 )
{
gui_showstatus(STATUS_CRITICALERROR, "connect() failed: %d\n", errno);
break;
}
/* Initialize a stream */
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;
unsigned char *BufPtr;
unsigned int MMSCSize;
unsigned int MMSCSeq = 0;
BufPtr = Buffer; /* Send Initial Request */
BufPtr += my_sprintf(BufPtr, MMSC_HEADER, sizeof(MMSC_HEADER));
BufPtr += my_sprintf(BufPtr, MMSC_REQUEST_INIT, sizeof(MMSC_REQUEST_INIT));
BufPtr += my_swprintf(BufPtr, "NSPlayer/4.0.0.3845; ", 0);
BufPtr += my_swprintf(BufPtr, (const char*)My_ci->RandomizedGUID, 0);
BufPtr += my_swprintf(BufPtr, "\0", 1);
MMSCSize=(int)BufPtr-(int)Buffer; if(MMSCSize%8) MMSCSize+=8-MMSCSize%8; put_long(Buffer+MMSC_POS_SIZE, MMSCSize-0x10);
put_long(Buffer+MMSC_POS_SEQ, MMSCSeq++);
if ((my_send(ConnSocket, Buffer, MMSCSize, 0)) == SOCKET_ERROR)
{
gui_showstatus(STATUS_CRITICALERROR, "send() failed: %d\n", errno);
my_closesocket(ConnSocket);
free(Stream_Parm.si);
break;
}
/* The main loop for chunk extraction/ASF generation */
unsigned long MyFilePointer = 0;
unsigned char TimeCodeString[64];
//unused unsigned int StartTimeHi = 0xffffffff;
unsigned int StartTime = 0xffffffff;
unsigned int StartSeqNO = 0xffffffff;
for (;;)
{
unsigned char Type, SubType;
unsigned short Length;
unsigned int BodyLength;
unsigned long SeqNO;
unsigned long TimeCode;
unsigned int Progress; /* scaled from 0 to 10000 */
unsigned int Got;
if (eos(&Stream_Parm))
{
gui_showstatus(STATUS_CRITICALERROR, "Connection reset\n");
break;
}
if( readfromstream(&Stream_Parm, Buffer, 0x08) != 0x08) break;
Buffer[3] = 0x00; /* Mask out server version(maybe?) */
if( !memcmp(MMSC_HEADER, Buffer, 0x08) ) /* Process MMSC if found */
{
unsigned char ToBreak = 0;
unsigned long DataSize;
if( readfromstream(&Stream_Parm, Buffer+0x08, 0x08) != 0x08) break;
get_long(Buffer+MMSC_POS_SIZE, &DataSize);
if( (unsigned)readfromstream(&Stream_Parm, Buffer+0x10, DataSize) != DataSize) break;
unsigned char MMSCFlag = Buffer[MMSC_POS_FLAG];
//unused unsigned char MMSCSubFlag = Buffer[MMSC_POS_SUBFLAG];
BufPtr = Buffer; /* Prepare Send Request */
BufPtr += my_sprintf(BufPtr, MMSC_HEADER, sizeof(MMSC_HEADER));
switch(MMSCFlag)
{
case 0x01: /* Server Info Received */
{ /* Send local address & port */
SOCKADDR_IN Client;
#ifdef __MINGW32__
int ClientLen = sizeof(Client);
#else
size_t ClientLen = sizeof(Client);
#endif /* __MINGW32__ */
unsigned char PortNumString[8];
getsockname(ConnSocket, (struct sockaddr*)&Client, &ClientLen);
sprintf((char *)PortNumString, "%d", ntohs(Client.sin_port));
BufPtr += my_sprintf(BufPtr, MMSC_REQUEST_CONNPORT, sizeof(MMSC_REQUEST_CONNPORT));
BufPtr += my_swprintf(BufPtr, "\\\\", 0);
BufPtr += my_swprintf(BufPtr, inet_ntoa(Client.sin_addr), 0);
BufPtr += my_swprintf(BufPtr, "\\TCP\\", 0);
BufPtr += my_swprintf(BufPtr, (char*)PortNumString, 0);
BufPtr += my_swprintf(BufPtr, "\0", 1);
My_ti->Reply = REPLY_RETRY; /* Server is OK, so Retry if connect reset */
}break;
case 0x02: /* 'Funnel Of The' Received, whats meaning? */
{ /* Send file request */
BufPtr += my_sprintf(BufPtr, MMSC_REQUEST_FILE, sizeof(MMSC_REQUEST_FILE));
BufPtr += my_swprintf(BufPtr, My_ci->File, 0);
BufPtr += my_swprintf(BufPtr, "\0", 1);
}break;
case 0x05: /* ASF Body Received */
break; /* Nothing to do :) */
case 0x06: /* File Info Received */
{ /* Send request for ASF Header */
get_long(Buffer+MMSC_POS_CHUNKLENGTH, &My_ci->ChunkLength2);
if(My_ci->ChunkLength2) /* detect file existance here */
{
BufPtr += my_sprintf(BufPtr, MMSC_REQUEST_RECVHEADER, sizeof(MMSC_REQUEST_RECVHEADER));
My_hi->Resumeable = TRUE;
}
else
{
gui_showstatus(STATUS_CRITICALERROR, "File '%s/%s' not found!\n", My_ci->ServerName, My_ci->File);
My_ti->Reply = REPLY_FAIL;
ToBreak = 1;
}
}break;
case 0x11: /* ASF Header Received */
{ /* Send request for ASF Body if needed */
usleep(1000);
if (My_ti->RequestType == REQUEST_GETDATA)
{
BufPtr += my_sprintf(BufPtr, MMSC_REQUEST_RECVBODY, sizeof(MMSC_REQUEST_RECVBODY));
unsigned long ReqSeqNO = max((signed)(My_ti->SourOffset - My_ci->EndOfHeaderOffs - DATSEG_HDR_SIZE), 0) / My_ci->ChunkLength;
put_long(Buffer+MMSC_POS_REQCHUNKSEQ, ReqSeqNO);
}
}break;
case 0x1A: /* File is password protected */
{
gui_showstatus(STATUS_CRITICALERROR, "File is password protected!\n");
My_ti->Reply = REPLY_FAIL;
ToBreak = 1;
} break;
case 0x1B: /* Received every minute */
{ /* Send a reply */
BufPtr += my_sprintf(BufPtr, MMSC_REPLY, sizeof(MMSC_REPLY));
} break;
case 0x1E: /* Transfer finished */
{
gui_showstatus(STATUS_FINISH, "Transfer complete.\n");
My_ti->Reply = REPLY_FINISH;
ToBreak = 1;
} break;
default: /* What this? */
{
gui_showstatus(STATUS_INFORMATION, "Unknown MMSCFlag:%X\n", MMSCFlag);
if(Debug) { /* Dump all contents */
for ( i=0 ; i<DataSize+0x10 ; ++i ) {
if( 0 == (i % 0x10) ) printf("\n");
printf("%02X ", Buffer[i]);
}
printf("\n\n");
}
return;
} break;
}
if( (MMSCSize=(int)BufPtr-(int)Buffer) > sizeof(MMSC_HEADER) ) /* have something to send */
{
if(MMSCSize % 8) MMSCSize += 8-MMSCSize%8; put_long(Buffer+MMSC_POS_SIZE, MMSCSize-0x10);
put_long(Buffer+MMSC_POS_SEQ, MMSCSeq++);
if ((my_send(ConnSocket, Buffer, MMSCSize, 0)) == SOCKET_ERROR)
{
gui_showstatus(STATUS_CRITICALERROR, "send() failed: %d\n", errno);
my_closesocket(ConnSocket);
free(Stream_Parm.si);
break;
}
}
if(ToBreak) break;
continue;
}
else
{
get_long(Buffer, &SeqNO);
Type = Buffer[MMSD_POS_TYPE];
SubType = Buffer[MMSD_POS_SUBTYPE];
get_short(Buffer+MMSD_POS_SIZE, &Length);
}
if (eos(&Stream_Parm))
{
gui_showstatus(STATUS_CRITICALERROR, "Connection reset\n");
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -