⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 core_mmst.cpp

📁 ASFR+是在ASFRecorder的基础上的改进版本,它可以: ◇支持中文文件名. ◇多线程下载ASF文件. ◇断点续传,自动重试. ◇支持MMS(TCP)协议和HTTP协议(自动探测). ◇在下载
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* 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 + -