📄 receiver.cpp
字号:
fd_set fdRecv, fdError;
struct timeval tv = {0, RECV_INTERVAL};
RECV_BUF* pBuf;
*pszRedirect = NULL;
#ifdef _UNICODE
WideCharToMultiByte(CP_ACP, 0, pszURL, -1, szURL, MAX_URL, 0, 0);
WideCharToMultiByte(CP_ACP, 0, m_szProxy, -1, szProxy, MAX_URL, 0, 0);
WideCharToMultiByte(CP_ACP, 0, m_szUserAgent, -1, szUserAgent, MAX_URL, 0, 0);
#else
strcpy(szURL, pszURL);
strcpy(szProxy, m_szProxy);
strcpy(szUserAgent, m_szUserAgent);
#endif
if (!strlen(szURL))
return FALSE;
// URL傪夝愅偡傞
// Proxy僒乕僶乕偑愝掕偝傟偰偄傞偲偒偼僒乕僶乕傾僪儗僗傪夝愅
if (m_fUseProxy && strlen(szProxy)) {
if (strncmp(szProxy, "http://", strlen("http://"))) {
if (sscanf(szProxy, "%[^:/]:%d", szHostName, &nPort) < 2)
nPort = RECV_HTTP;
}
else {
if (sscanf(szProxy, "http://%[^:/]:%d", szHostName, &nPort) < 2)
nPort = RECV_HTTP;
}
psz = szURL;
}
else {
if (strncmp(szURL, "http://", strlen("http://"))) {
if (sscanf(szURL, "%[^:/]:%d", szHostName, &nPort) < 2)
nPort = RECV_HTTP;
psz = strchr(szURL, '/');
}
else {
if (sscanf(szURL, "http://%[^:/]:%d", szHostName, &nPort) < 2)
nPort = RECV_HTTP;
psz = strchr(szURL + 7, '/');
}
}
if (!strlen(szHostName))
return FALSE;
// socket偺嶌惉
m_hSock = socket(PF_INET, SOCK_STREAM, 0);
if (m_hSock == INVALID_SOCKET)
return FALSE;
// 傾僪儗僗偺庢摼
addr = inet_addr(szHostName);
if (addr == SOCKET_ERROR) {
pHost = gethostbyname(szHostName);
if (!pHost)
return FALSE;
addr = *((unsigned long*)(pHost->h_addr_list)[0]);
}
// 旕摨婜庴怣偵愗傝懼偊
if (ioctlsocket(m_hSock, FIONBIO, &val) == SOCKET_ERROR)
goto fail;
// 愙懕
memset(&sAddr, 0, sizeof(struct sockaddr_in));
sAddr.sin_family = AF_INET;
sAddr.sin_port = htons((u_short)nPort);
sAddr.sin_addr.s_addr = addr;
connect(m_hSock, (const sockaddr*)&sAddr, sizeof(sAddr));
// 僞僀儉傾僂僩偡傞傑偱懸偮
nTimeout = 0;
while (TRUE) {
if (m_fStop)
goto fail;
FD_ZERO(&fdRecv);
FD_SET(m_hSock, &fdRecv);
FD_ZERO(&fdError);
FD_SET(m_hSock, &fdError);
if (select(NULL, 0, &fdRecv, &fdError, &tv) != SOCKET_ERROR) {
if (FD_ISSET(m_hSock, &fdError))
goto fail;
else if (FD_ISSET(m_hSock, &fdRecv))
break;
}
nTimeout += RECV_INTERVAL;
if (nTimeout > RECV_CONNECT_TIMEOUT)
goto fail;
}
// Request(HTTP)偺憲怣
sprintf(szRequest, "GET %s HTTP/1.0\r\nHost: %s\r\nAccept: */*\r\nIcy-MetaData:1\r\nUser-Agent: %s\r\n\r\n",
psz ? psz : "/", szHostName, szUserAgent);
//x-audiocast-udpport: %d\r\n 傑偩枹懳墳
if (send(m_hSock, szRequest, strlen(szRequest), 0) == SOCKET_ERROR)
goto fail;
// ICY (HTTP)僿僢僟傪偡傋偰庴怣偡傞
psz = NULL;
while (!psz && RECV_BUFF_SIZE - nLen - 1 > 0) {
// 僞僀儉傾僂僩偡傞傑偱懸偮
nTimeout = 0;
while (TRUE) {
if (m_fStop)
goto fail;
FD_ZERO(&fdRecv);
FD_SET(m_hSock, &fdRecv);
if (select(NULL, &fdRecv, 0, 0, &tv) != SOCKET_ERROR && FD_ISSET(m_hSock, &fdRecv))
break;
nTimeout += RECV_INTERVAL;
if (nTimeout > RECV_RECEIVE_TIMEOUT)
goto fail;
}
int nRecv = recv(m_hSock, szRecv + nLen, RECV_BUFF_SIZE - nLen, 0);
if (!nRecv || nRecv == SOCKET_ERROR)
goto fail;
nLen += nRecv;
if (nRet == 0) {
// 僄儔乕僐乕僪傪僠僃僢僋
if (!sscanf(szRecv, " %*s %d", &nRet))
goto fail;
if (nRet != ICY_OK && nRet != ICY_REDIRECT)
goto fail;
}
szRecv[nLen] = NULL;
psz = strstr(szRecv, "\r\n\r\n");
}
if (!psz) // 僿僢僟偑廔傢偭偰偄側偄
goto fail;
// 僿僢僟傪夝愅偡傞
if (nRet == ICY_REDIRECT) {
// 儕僟僀儗僋僩
DisconnectServer();
psz = strstr(szRecv, "Location: ");
if (sscanf(psz, "Location: %256[^\r\n]", szURL) == 1) {
#ifdef _UNICODE
MultiByteToWideChar(CP_ACP, 0, szURL, -1, pszRedirect, MAX_URL);
#else
strncpy(pszRedirect, szURL, MAX_URL);
pszRedirect[MAX_URL - 1] = NULL;
#endif
return FALSE;
}
}
// name
psz = strstr(szRecv, "icy-name");
if (psz) {
m_fShoutcast = TRUE;
psz += strlen("icy-name:");
if (sscanf(psz, "%256[^\r\n]", szURL)) {
LPSTR p = szURL;
while (*p == ' ') p++;
#ifdef _UNICODE
MultiByteToWideChar(CP_ACP, 0, p, -1, m_szIcyName, MAX_URL);
#else
strcpy(m_szIcyName, p);
#endif
}
}
psz = strstr(szRecv, "ice-name");
if (psz) {
m_fShoutcast = TRUE;
psz += strlen("ice-name:");
if (sscanf(psz, "%256[^\r\n]", szURL)) {
LPSTR p = szURL;
while (*p == ' ') p++;
#ifdef _UNICODE
MultiByteToWideChar(CP_ACP, 0, p, -1, m_szIcyName, MAX_URL);
#else
strcpy(m_szIcyName, p);
#endif
}
}
// genre
psz = strstr(szRecv, "icy-genre");
if (psz) {
m_fShoutcast = TRUE;
psz += strlen("icy-genre:");
if (sscanf(psz, "%256[^\r\n]", szURL)) {
LPSTR p = szURL;
while (*p == ' ') p++;
#ifdef _UNICODE
MultiByteToWideChar(CP_ACP, 0, p, -1, m_szIcyGenre, MAX_URL);
#else
strcpy(m_szIcyGenre, p);
#endif
}
}
psz = strstr(szRecv, "ice-genre");
if (psz) {
m_fShoutcast = TRUE;
psz += strlen("ice-genre:");
if (sscanf(psz, "%256[^\r\n]", szURL)) {
LPSTR p = szURL;
while (*p == ' ') p++;
#ifdef _UNICODE
MultiByteToWideChar(CP_ACP, 0, p, -1, m_szIcyGenre, MAX_URL);
#else
strcpy(m_szIcyGenre, p);
#endif
}
}
// url
psz = strstr(szRecv, "icy-url");
if (psz) {
m_fShoutcast = TRUE;
psz += strlen("icy-url:");
if (sscanf(psz, "%256[^\r\n]", szURL)) {
LPSTR p = szURL;
while (*p == ' ') p++;
#ifdef _UNICODE
MultiByteToWideChar(CP_ACP, 0, p, -1, m_szIcyURL, MAX_URL);
#else
strcpy(m_szIcyURL, p);
#endif
}
}
psz = strstr(szRecv, "ice-url");
if (psz) {
m_fShoutcast = TRUE;
psz += strlen("ice-url:");
if (sscanf(psz, "%256[^\r\n]", szURL)) {
LPSTR p = szURL;
while (*p == ' ') p++;
#ifdef _UNICODE
MultiByteToWideChar(CP_ACP, 0, p, -1, m_szIcyURL, MAX_URL);
#else
strcpy(m_szIcyURL, p);
#endif
}
}
//psz = strstr(szRecv, "icy-pub");
//psz = strstr(szRecv, "x-audiocast-udpport:");
// MetaData
psz = strstr(szRecv, "icy-metaint");
if (psz) {
psz += strlen("icy-metaint:");
m_cbMetaData = atoi(psz);
}
else {
m_cbMetaData = 0;
}
m_cbMetaDataInterval = m_cbMetaData;
// 僿僢僟埲奜偺庴怣嵪傒僶僢僼傽傪僐僺乕偡傞
pBuf = (RECV_BUF*)m_listBufFree.GetAt(0);
psz = strstr(szRecv, "\r\n\r\n") + 4;
pBuf->cbRecv = nLen - (psz - szRecv);
memcpy(pBuf->pbBuf, psz, pBuf->cbRecv);
// MetaData偺僠僃僢僋
pBuf->cbRecv -= CheckMetaData(pBuf->pbBuf, pBuf->cbRecv);
return TRUE;
fail:
DisconnectServer();
return FALSE;
}
void CReceiver::DisconnectServer()
{
if (m_hSock != INVALID_SOCKET) {
shutdown(m_hSock, -2);
closesocket(m_hSock);
m_hSock = INVALID_SOCKET;
}
}
BOOL CReceiver::PrepareBuffer()
{
CAutoLock lock(&m_csecBuf);
for (int i = 0; i < (int)m_cBuf; i++) {
RECV_BUF* p = new RECV_BUF;
if (!p) goto fail;
m_listBufFree.Add((DWORD)p);
}
m_eventBufFree.Set();
m_eventBuf.Reset();
return TRUE;
fail:
UnprepareBuffer();
return FALSE;
}
void CReceiver::UnprepareBuffer()
{
CAutoLock lock(&m_csecBuf);
int i;
for (i = 0; i < m_listBufFree.GetCount(); i++) {
RECV_BUF* p = (RECV_BUF*)m_listBufFree.GetAt(i);
delete p;
}
m_listBufFree.RemoveAll();
for (i = 0; i < m_listBuf.GetCount(); i++) {
RECV_BUF* p = (RECV_BUF*)m_listBuf.GetAt(i);
delete p;
}
m_listBuf.RemoveAll();
m_eventBufFree.Set();
m_eventBuf.Set();
}
int CReceiver::CheckMetaData(LPBYTE pbBuf, int cbBuf)
{
if (!m_cbMetaData)
return 0;
static TCHAR sz[MAX_URL];
if (m_cbMetaDataInterval < 0) {
// 搑拞傑偱偼MetaData
if (cbBuf + m_cbMetaDataInterval <= 0) {
memcpy(m_bMetaDataBuf + m_cbMetaDataBuf, pbBuf, cbBuf);
m_cbMetaDataBuf += cbBuf;
m_cbMetaDataInterval += cbBuf; // 傑偨搑拞傑偱偟偐側偄...
return cbBuf;
}
int cbMetaData = -m_cbMetaDataInterval;
memcpy(m_bMetaDataBuf + m_cbMetaDataBuf, pbBuf, cbMetaData);
m_cbMetaDataBuf += cbMetaData;
memmove(pbBuf, pbBuf - m_cbMetaDataInterval, cbBuf - cbMetaData);
m_cbMetaDataInterval = m_cbMetaData - (cbBuf - cbMetaData);
if (m_cbMetaDataInterval < 0) { // 2005/01/16
m_cbMetaDataInterval = m_cbMetaData;
return CheckMetaData(pbBuf, cbBuf - cbMetaData) + cbMetaData;
}
// 僞僀僩儖偺捠抦傪峴偆
if (GetStreamTitle(sz)) {
NotifyMessage(MAP_MSG_STREAM_TITLE, (WPARAM)sz, 0);
}
return cbMetaData;
}
if (m_cbMetaDataInterval - cbBuf < 0) {
LPBYTE pMetaData = pbBuf + m_cbMetaDataInterval;
int nSize = *pMetaData * 16 + 1;
if (m_cbMetaDataInterval + nSize > cbBuf) {
// 搑拞傑偱偟偐側偄...
if (*pMetaData) {
m_cbMetaDataBuf = cbBuf - m_cbMetaDataInterval;
memcpy(m_bMetaDataBuf, pMetaData, m_cbMetaDataBuf);
}
m_cbMetaDataInterval = cbBuf - m_cbMetaDataInterval - nSize; // 儅僀僫僗抣偵側傞
return nSize + m_cbMetaDataInterval;
}
// MetaData偺撪梕傪庢傝弌偡
if (*pMetaData) {
m_cbMetaDataBuf = nSize;
memcpy(m_bMetaDataBuf, pMetaData, m_cbMetaDataBuf);
}
// 僶僢僼傽傪媗傔傞
cbBuf = cbBuf - m_cbMetaDataInterval - nSize;
memmove(pMetaData, pMetaData + nSize, cbBuf);
m_cbMetaDataInterval = m_cbMetaData - cbBuf;
if (m_cbMetaDataInterval < 0) { // 2005/01/16
m_cbMetaDataInterval = m_cbMetaData;
return CheckMetaData(pMetaData, cbBuf) + nSize;
}
// 僞僀僩儖偺捠抦傪峴偆
if (nSize > 1 && GetStreamTitle(sz)) {
NotifyMessage(MAP_MSG_STREAM_TITLE, (WPARAM)sz, 0);
}
return nSize;
}
m_cbMetaDataInterval -= cbBuf;
return 0;
}
void CReceiver::NotifyMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (m_hwndMessage) {
PostMessage(m_hwndMessage, uMsg, wParam, lParam);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -