httpinput.cpp
字号:
iConnect = connect(m_hHandle,(const sockaddr *)&sAddr,sizeof(sAddr));
for(; iConnect && !m_bExit;)
{
sTv.tv_sec = 0; sTv.tv_usec = 0;
FD_ZERO(&sSet); FD_SET(m_hHandle, &sSet);
iRet = select(m_hHandle + 1, NULL, &sSet, NULL, &sTv);
if (!iRet)
{
usleep(100000);
continue;
}
if (iRet < 0)
{
ReportError("Cannot connect to host: %s", szHostName);
closesocket(m_hHandle);
return (Error)httpError_CannotConnect;
}
break;
}
if (m_bExit)
return (Error)kError_Interrupt;
gethostname(szLocalName, iMaxHostNameLen);
szQuery = new char[iMaxUrlLen];
if (szFile)
sprintf(szQuery, "GET %s HTTP/1.0\n"
"Host: %s\n"
"Accept: */*\n"
"User-Agent: FreeAmp/%s\n",
szFile, szLocalName, FREEAMP_VERSION);
else
sprintf(szQuery, "GET / HTTP/1.0\n"
"Host: %s\n"
"Accept: */*\n"
"User-Agent: FreeAmp/%s\n",
szLocalName, FREEAMP_VERSION);
m_pContext->prefs->GetPrefBoolean(kUseTitleStreamingPref, &bUseTitleStreaming);
if (bUseTitleStreaming)
{
int iPort;
Error eRet;
m_pTitleStream = new TitleStreamServer(m_pContext, m_pTarget);
eRet = m_pTitleStream->Init(iPort);
if (IsntError(eRet))
{
sprintf(szQuery + strlen(szQuery), "x-audiocast-udpport: %d\n",
iPort);
}
else
{
delete m_pTitleStream;
m_pTitleStream = NULL;
}
}
strcat(szQuery, "\n");
ReportStatus("Requesting stream...");
iRet = send(m_hHandle, szQuery, strlen(szQuery), 0);
if (iRet != (int)strlen(szQuery))
{
delete szQuery;
ReportError("Cannot send data to host: %s", szHostName);
closesocket(m_hHandle);
return (Error)httpError_SocketWrite;
}
delete szQuery;
pInitialBuffer = new char[iInitialBufferSize + 1];
for(;!m_bExit;)
{
sTv.tv_sec = 0; sTv.tv_usec = 0;
FD_ZERO(&sSet); FD_SET(m_hHandle, &sSet);
iRet = select(m_hHandle + 1, &sSet, NULL, NULL, &sTv);
if (!iRet)
{
usleep(10000);
continue;
}
iRead = recv(m_hHandle, pInitialBuffer, iInitialBufferSize, 0);
if (iRead < 0)
{
ReportError("Cannot receive data from host: %s", szHostName);
closesocket(m_hHandle);
return (Error)httpError_SocketRead;
}
break;
}
if (m_bExit)
return (Error)kError_Interrupt;
if (sscanf(pInitialBuffer, " %*s %d %255[^\n\r]", &iRet, m_szError))
{
void *pData;
if (iRet != iICY_OK)
{
ReportStatus("");
ReportError("This stream is not available: %s\n", m_szError);
delete pInitialBuffer;
closesocket(m_hHandle);
return (Error)httpError_CustomError;
}
//for(int i = 0; i < 25; i++)
// Debug_v("%c - %d", pInitialBuffer[i], pInitialBuffer[i]);
pHeaderData = new char[iHeaderSize];
for(;;)
{
if (iHeaderBytes + iRead > iCurHeaderSize)
{
char *pNew;
iCurHeaderSize += iHeaderSize;
pNew = new char[iCurHeaderSize + 1];
memset(pNew, 0, iCurHeaderSize + 1);
memcpy(pNew, pHeaderData, iHeaderBytes);
delete pHeaderData;
pHeaderData = pNew;
}
memcpy(pHeaderData + iHeaderBytes, pInitialBuffer, iRead);
iHeaderBytes += iRead;
pEnd = strstr(pHeaderData, "\r\n\r\n");
if (pEnd)
{
*(pEnd + 3) = 0;
break;
}
pEnd = strstr(pHeaderData, "\n\n");
if (pEnd)
{
*(pEnd + 1) = 0;
break;
}
for(;!m_bExit;)
{
sTv.tv_sec = 0; sTv.tv_usec = 0;
FD_ZERO(&sSet); FD_SET(m_hHandle, &sSet);
iRet = select(m_hHandle + 1, &sSet, NULL, NULL, &sTv);
if (!iRet)
{
usleep(10000);
continue;
}
iRead = recv(m_hHandle, pInitialBuffer, iInitialBufferSize, 0);
if (iRead < 0)
{
ReportError("Cannot receive data from host: %s", szHostName);
closesocket(m_hHandle);
return (Error)httpError_SocketRead;
}
break;
}
if (m_bExit)
return (Error)kError_Interrupt;
}
pPtr = strstr(pHeaderData, "icy-name");
if (pPtr)
{
pPtr += strlen("icy-name:");
szStreamName = new char[strlen(pPtr) + 1];
sscanf(pPtr, " %[^\r\n]", szStreamName);
}
pPtr = strstr(pHeaderData, "icy-url");
if (pPtr)
{
pPtr += strlen("icy-url:");
szStreamUrl = new char[strlen(pPtr) + 1];
sscanf(pPtr, " %[^\r\n]", szStreamUrl);
}
// If this is a stream from a web server and not a shout/ice
// server we don't want to use buffer reduction when the
// input buffers fill up
if (strstr(pHeaderData, "Server:") &&
strstr(pHeaderData, "Date:"))
m_bUseBufferReduction = false;
if (szStreamName && strlen(szStreamName))
{
StreamInfoEvent *e;
e = new StreamInfoEvent(szStreamName ? szStreamName : (char *)"",
szStreamUrl ? szStreamUrl : (char *)"");
m_pTarget->AcceptEvent(e);
delete szStreamUrl;
}
pPtr = strstr(pHeaderData, "x-audiocast-udpport:");
if (pPtr)
{
if (m_pTitleStream)
m_pTitleStream->Run(sAddr.sin_addr, atoi(pPtr + 20));
}
// Let's save the bytes we've read into the pullbuffer.
iRead = iHeaderBytes - strlen(pHeaderData) - 1;
if (iRead > 0)
{
m_pOutputBuffer->BeginWrite(pData, iRead);
memcpy(pData, (char *)pHeaderData + strlen(pHeaderData) + 1, iRead);
m_pOutputBuffer->EndWrite(iRead);
}
}
delete pInitialBuffer;
bool bSave;
uint32 size = 255;
m_pContext->prefs->GetPrefBoolean(kSaveStreamsPref, &bSave);
if (bSave || (m_pContext->argFlags & FAC_ARGFLAGS_SAVE_STREAMS))
{
char szPath[255], szFile[255];
unsigned i;
if (szStreamName == NULL)
{
szStreamName = new char[255];
sprintf(szStreamName, "%s:%d", szHostName, iPort);
}
for(i = 0; i < strlen(szStreamName); i++)
if (strchr("\\/?*{}[]()*|:<>\"'", szStreamName[i]))
szStreamName[i] = '-';
if (m_pContext->prefs->GetPrefString(kSaveStreamsDirPref, szPath, &size) ==
kError_NoPrefValue)
strcpy(szPath, ".");
if (szPath[strlen(szPath) - 1] == cDirSepChar)
szPath[strlen(szPath) - 1] = 0;
for(i = 0;; i++)
{
if (!i)
sprintf(szFile, "%s%c%s.mp3", szPath, cDirSepChar, szStreamName);
else
sprintf(szFile, "%s%c%s-%d.mp3", szPath, cDirSepChar, szStreamName, i);
if (access(szFile, F_OK))
break;
}
m_fpSave = fopen(szFile, "wb");
if (m_fpSave == NULL)
ReportError("Cannot open file to save HTTP stream. Check "
"the save streams locally setting in the "
"options dialog.");
if (pHeaderData && m_fpSave)
{
iRet = fwrite((char *)pHeaderData + strlen(pHeaderData) + 1,
sizeof(char), iRead, m_fpSave);
if (iRet != iRead)
{
delete pHeaderData;
ReportError("Cannot save http stream to disk. Disk full?");
return kError_WriteFile;
}
}
}
delete pHeaderData;
delete szStreamName;
ReportStatus("");
return kError_NoErr;
}
void HttpInput::StartWorkerThread(void *pVoidBuffer)
{
((HttpInput*)pVoidBuffer)->WorkerThread();
}
void HttpInput::WorkerThread(void)
{
int iRead, iRet, iReadSize = 1024;
void *pBuffer;
Error eError;
fd_set sSet;
struct timeval sTv;
static int iSize = 0;
eError = Open();
if (IsError(eError) || m_bExit)
{
return;
}
m_pSleepSem->Wait();
for(; !m_bExit;)
{
if (m_pOutputBuffer->IsEndOfStream())
{
m_pSleepSem->Wait();
continue;
}
sTv.tv_sec = 0; sTv.tv_usec = 0;
FD_ZERO(&sSet); FD_SET(m_hHandle, &sSet);
iRet = select(m_hHandle + 1, &sSet, NULL, NULL, &sTv);
if (!iRet)
{
usleep(10000);
continue;
}
eError = m_pOutputBuffer->BeginWrite(pBuffer, iReadSize);
if (eError == kError_NoErr)
{
iRead = recv(m_hHandle, (char *)pBuffer, iReadSize, 0);
if (iRead <= 0)
{
m_pOutputBuffer->SetEndOfStream(true);
m_pOutputBuffer->EndWrite(0);
break;
}
iSize += iRead;
if (m_fpSave)
{
iRet = fwrite(pBuffer, sizeof(char), iRead, m_fpSave);
if (iRet != iRead)
{
ReportError("Cannot save http stream to disk. Disk full?");
break;
}
}
eError = m_pOutputBuffer->EndWrite(iRead);
if (IsError(eError))
{
m_pContext->log->Error("http: EndWrite returned: %d\n", eError);
break;
}
}
if (eError == kError_BufferTooSmall)
{
if (m_bLoop)
{
m_pOutputBuffer->DiscardBytes();
m_bDiscarded = true;
}
else
{
iSize = 0;
m_pSleepSem->Wait();
}
continue;
}
}
shutdown(m_hHandle, 2);
closesocket(m_hHandle);
m_hHandle = -1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -