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

📄 httpinput.cpp

📁 FreeAMP(MP3播放)程序源代码-用来研究MP3解码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
                                "has no value ?!");

      sSourceAddr.sin_family = AF_INET;
      sSourceAddr.sin_port = 0;
      sSourceAddr.sin_addr.s_addr = inet_addr(szSourceAddr);
      iRet = bind(m_hHandle, (struct sockaddr *) &sSourceAddr,

                  sizeof(struct sockaddr_in));
      if (iRet < 0)
      {
         close(m_hHandle);
         m_hHandle = -1;
         ReportError
            ("Cannot bind the socket. Please make sure that your TCP/IP networking is correctly configured.");
         return kError_CannotBind;
      }
   }

#if defined(WIN32)
   unsigned long lMicrosoftSucksBalls = 1;

   ioctlsocket(m_hHandle, FIONBIO, &lMicrosoftSucksBalls);
#elif defined(__BEOS__)
//  int on = 1;
//  setsockopt( m_hHandle, SOL_SOCKET, SO_NONBLOCK, &on, sizeof( on ) );
#else
   fcntl(m_hHandle, F_SETFL, fcntl(m_hHandle, F_GETFL) | O_NONBLOCK);
#endif

   iConnect = connect(m_hHandle, (const sockaddr *) &sAddr, sizeof(sAddr));

   if (iConnect == -1)
   {

#ifndef WIN32
      int       error = errno;

      if (error != EINPROGRESS)
#else
      int       error = WSAGetLastError();

      if (error != WSAEINPROGRESS && error != WSAEWOULDBLOCK)
#endif
      {
         ReportError("Cannot connect to host: %s", szHostName);
         closesocket(m_hHandle);
         return (Error) httpError_CannotConnect;
      }

      int       conattempt = 0;

      for (; iConnect && !m_bExit;)
      {
         if (conattempt > 50)
         {
            cout << "timed out\n";
            ReportError("Host not answering: %s", szHostName);
            closesocket(m_hHandle);
            return (Error) httpError_CannotConnect;
         }

         conattempt++;
         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;

   szQuery = new char[iMaxUrlLen];

   if (file.length() > 0)
   {
      sprintf(szQuery, "GET %s HTTP/1.0\r\n"
              "Host: %s\r\n"
              "Accept: */*\r\n"
              "Icy-MetaData:1\r\n"
              "User-Agent: FreeAmp/%s\r\n",
              file.c_str(), szHostName, FREEAMP_VERSION);
   }
   else
   {
      sprintf(szQuery, "GET / HTTP/1.0\r\n"
              "Host: %s\r\n"
              "Accept: */*\r\n"
              "Icy-MetaData:1\r\n"
              "User-Agent: FreeAmp/%s\r\n", szHostName, 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\r\n",
                 iPort);
      }
      else
      {
         delete    m_pTitleStream;

         m_pTitleStream = NULL;
      }
   }

   strcat(szQuery, "\r\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_REDIRECT)
      {
         char *redir;

         redir = strstr(pInitialBuffer, "Location: ");
         if (redir)
         {
             int port, ret;
             char url[MAX_PATH];

             ret = sscanf(redir, "Location: %255[0-9.]:%d", url, &port);
             if (ret == 0)
                 ret = sscanf(redir, "Location: http://%255[0-9.]:%d", url, &port);
             if (ret)
             {
                 if (ret == 2)
                    sprintf(m_path, "http://%s:%d", url, port);
                 else
                    sprintf(m_path, "http://%s", url);

                 sprintf(url, "Redirected to: %s", m_path);
                 ReportStatus(url);

                 delete    pInitialBuffer;
                 closesocket(m_hHandle);
                 return Open(); 
             }
         } 
      }
      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);
      }

      pPtr = strstr(pHeaderData, "icy-metaint");
      if (pPtr)
      {
         pPtr += strlen("icy-metaint:");
         m_iMetaDataInterval = atoi(pPtr);
      }

      // 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))
      {
         PlaylistItemsUpdatedEvent *e;
         PlaylistItem *pItem;

         pItem = m_pContext->plm->GetCurrentItem();
         if (pItem && szStreamName)
         {
            MetaData  oData;

            oData = pItem->GetMetaData();
            oData.SetTitle(szStreamName);
            pItem->SetMetaData(&oData);

            vector < PlaylistItem * >pl_items;
            pl_items.push_back(pItem);

            e = new PlaylistItemsUpdatedEvent(&pl_items, m_pContext->plm);
            m_pTarget->AcceptEvent(e);
         }
         delete    szStreamUrl;
      }

      pPtr = strstr(pHeaderData, "x-audiocast-udpport:");
      if (pPtr)
      {
         // Debug_v("x-audiocast-udpport: %s", atoi(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);
         m_uBytesReceived = 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 && iRead > 0)
      {
         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? (1)");
            return kError_WriteFile;
         }
      }
   }
   delete    pHeaderData;
   delete    szStreamName;

   return kError_NoErr;
}

void
HttpInput::StartWorkerThread(void *pVoidBuffer)
{
   ((HttpInput *) pVoidBuffer)->WorkerThread();
}

void
HttpInput::WorkerThread(void)
{
   int       iRead, iRet, iReadSize = 1024, iMaxReadBytes;
   void     *pBuffer;
   Error     eError;
   fd_set    sSet;
   struct timeval sTv;
   char      cNumBlocks;
   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)
      {
         if (m_iMetaDataInterval > 0)
         {
            iMaxReadBytes =
               min(iReadSize, m_iMetaDataInterval - m_uBytesReceived);
            if (iMaxReadBytes == 0)
            {
               iRead = recv(m_hHandle, &cNumBlocks, 1, 0);
               if (cNumBlocks > 0)
               {
                  char     *pMeta, *pPtr, *pNull;

                  pMeta = new char[cNumBlocks * 16 + 1];

                  recv(m_hHandle, pMeta, cNumBlocks * 16, 0);
                  pMeta[cNumBlocks * 16] = 0;

                  pPtr = strstr(pMeta, "StreamTitle=");
                  if (pPtr)
                  {
                     pPtr += strlen("StreamTitle='");
                     pNull = strchr(pPtr, '\'');
                     if (pNull)
                     {
                        *pNull = 0;
                        m_pTarget->AcceptEvent(new StreamInfoEvent(pPtr, NULL));
                     }

                  }
                  delete    pMeta;
               }

               iMaxReadBytes = iReadSize;
               m_uBytesReceived = 0;
            }
         }
         else
            iMaxReadBytes = iReadSize;

         iRead = recv(m_hHandle, (char *) pBuffer, iMaxReadBytes, 0);
         if (iRead == 0)
         {
            m_pOutputBuffer->SetEndOfStream(true);
            m_pOutputBuffer->EndWrite(0);
         }
         if (iRead < 0)
         {
#ifdef WIN32
            if (WSAGetLastError() == WSAEWOULDBLOCK)
#else
            if (errno == EAGAIN)
#endif
            {
               iRead = 0;
            }
         }
         if (iRead < 0)
         {
            m_pOutputBuffer->SetEndOfStream(true);
            m_pOutputBuffer->EndWrite(0);
            break;
         }
         iSize += iRead;
         m_uBytesReceived += iRead;

         if (m_fpSave)
         {
            iRet = fwrite(pBuffer, sizeof(char), iRead, m_fpSave);

            if (iRet != iRead)
            {
               ReportError("Cannot save http stream to disk. Disk full? (2)");
               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;
}

vector < string > *HttpInput::GetProtocols(void)
{
   vector < string > *protoList = new vector < string >;

   protoList->push_back("http");

   return protoList;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -