url.cpp
上传用户:chn_coc
上传日期:2007-12-20
资源大小:563k
文件大小:8k
源码类别:

P2P编程

开发平台:

Windows_Unix

  1. // ------------------------------------------------ // File : url.h // Date: 20-feb-2004 // Author: giles // // (c) 2002-4 peercast.org // ------------------------------------------------ // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the // GNU General Public License for more details. // ------------------------------------------------ #include "url.h" #include "socket.h" #include "http.h" #include "servent.h" #include "servmgr.h" #include "peercast.h"
  2. #include "version2.h"
  3. // ------------------------------------------------ void URLSource::stream(Channel *ch) { String url; while (ch->thread.active && !peercastInst->isQuitting) { if (url.isEmpty()) url = baseurl; url = streamURL(ch,url.cstr()); }
  4. } // ------------------------------------------------
  5. int URLSource::getSourceRate()
  6. {
  7. if (inputStream)
  8. return inputStream->bytesInPerSec;
  9. else
  10. return 0;
  11. } // ------------------------------------------------ ::String URLSource::streamURL(Channel *ch, const char *url) { String nextURL;
  12. if (peercastInst->isQuitting || !ch->thread.active)
  13. return nextURL;
  14. String urlTmp; urlTmp.set(url); char *fileName = urlTmp.cstr(); PlayList *pls=NULL; ChannelStream *source=NULL;
  15. LOG_CHANNEL("Fetch URL=%s",fileName); try {
  16. // get the source protocol if (strnicmp(fileName,"http://",7)==0)  { ch->info.srcProtocol = ChanInfo::SP_HTTP; fileName += 7; } else if (strnicmp(fileName,"mms://",6)==0)  { ch->info.srcProtocol = ChanInfo::SP_MMS; fileName += 6; } else if (strnicmp(fileName,"pcp://",6)==0) 
  17. {
  18. ch->info.srcProtocol = ChanInfo::SP_PCP;
  19. fileName += 6;
  20. }
  21. else if (strnicmp(fileName,"file://",7)==0)  { ch->info.srcProtocol = ChanInfo::SP_FILE; fileName += 7; } else  { ch->info.srcProtocol = ChanInfo::SP_FILE; }
  22. // default to mp3 for shoutcast servers
  23. if (ch->info.contentType == ChanInfo::T_PLS)
  24. ch->info.contentType = ChanInfo::T_MP3;
  25. ch->setStatus(Channel::S_CONNECTING); if ((ch->info.srcProtocol == ChanInfo::SP_HTTP) || (ch->info.srcProtocol == ChanInfo::SP_PCP) || (ch->info.srcProtocol == ChanInfo::SP_MMS)) { if ((ch->info.contentType == ChanInfo::T_WMA) || (ch->info.contentType == ChanInfo::T_WMV)) ch->info.srcProtocol = ChanInfo::SP_MMS; LOG_CHANNEL("Channel source is HTTP"); ClientSocket *inputSocket = sys->createSocket(); if (!inputSocket) throw StreamException("Channel cannot create socket");
  26. inputStream = inputSocket;
  27. char *dir = strstr(fileName,"/"); if (dir) *dir++=0; LOG_CHANNEL("Fetch Host=%s",fileName); if (dir) LOG_CHANNEL("Fetch Dir=%s",dir); Host host; host.fromStrName(fileName,80); inputSocket->open(host); inputSocket->connect(); HTTP http(*inputSocket); http.writeLineF("GET /%s HTTP/1.0",dir?dir:""); http.writeLineF("%s %s",HTTP_HS_HOST,fileName); http.writeLineF("%s %s",HTTP_HS_CONNECTION,"close"); http.writeLineF("%s %s",HTTP_HS_ACCEPT,"*/*"); if (ch->info.srcProtocol == ChanInfo::SP_MMS) {
  28. http.writeLineF("%s %s",HTTP_HS_AGENT,"NSPlayer/4.1.0.3856");
  29. http.writeLine("Pragma: no-cache,rate=1.000000,request-context=1");
  30. //http.writeLine("Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=4294967295:4294967295,request-context=22605256,max-duration=0");
  31. http.writeLine("Pragma: xPlayStrm=1");
  32. http.writeLine("Pragma: xClientGUID={c77e7400-738a-11d2-9add-0020af0a3278}");
  33. http.writeLine("Pragma: stream-switch-count=2"); http.writeLine("Pragma: stream-switch-entry=ffff:1:0 ffff:2:0"); }else { http.writeLineF("%s %s",HTTP_HS_AGENT,PCX_AGENT);   http.writeLineF("%s %d",PCX_HS_PCP,1);  
  34. http.writeLine("Icy-MetaData:1"); // fix by ravon  }
  35. http.writeLine(""); int res = http.readResponse(); String name = ch->info.name;
  36. while (http.nextHeader()) { LOG_CHANNEL("Fetch HTTP: %s",http.cmdLine); ChanInfo tmpInfo = ch->info; Servent::readICYHeader(http,ch->info,NULL); if (!tmpInfo.name.isEmpty()) ch->info.name = tmpInfo.name; if (!tmpInfo.genre.isEmpty()) ch->info.genre = tmpInfo.genre; if (!tmpInfo.url.isEmpty()) ch->info.url = tmpInfo.url; if (http.isHeader("icy-metaint")) ch->icyMetaInterval = http.getArgInt(); else if (http.isHeader("Location:")) nextURL.set(http.getArgStr());
  37. char *arg = http.getArgStr(); if (arg) { if (http.isHeader("content-type")) { if (stristr(arg,MIME_XSCPLS)) pls = new PlayList(PlayList::T_SCPLS, 1000); else if (stristr(arg,MIME_PLS)) pls = new PlayList(PlayList::T_PLS, 1000); else if (stristr(arg,MIME_XPLS)) pls = new PlayList(PlayList::T_PLS, 1000); else if (stristr(arg,MIME_M3U)) pls = new PlayList(PlayList::T_PLS, 1000); else if (stristr(arg,MIME_TEXT)) pls = new PlayList(PlayList::T_PLS, 1000); else if (stristr(arg,MIME_ASX))
  38. pls = new PlayList(PlayList::T_ASX, 1000);
  39. else if (stristr(arg,MIME_MMS)) ch->info.srcProtocol = ChanInfo::SP_MMS; } } }
  40. if ((!nextURL.isEmpty()) && (res==302)) { LOG_CHANNEL("Channel redirect: %s",nextURL.cstr()); inputSocket->close(); delete inputSocket; inputSocket = NULL; return nextURL; }
  41. if (res!=200)
  42. {
  43. LOG_ERROR("HTTP response: %d",res);
  44. throw StreamException("Bad HTTP connect");
  45. }
  46. }else if (ch->info.srcProtocol == ChanInfo::SP_FILE) { LOG_CHANNEL("Channel source is FILE"); FileStream *fs = new FileStream(); fs->openReadOnly(fileName); inputStream = fs; ChanInfo::TYPE fileType = ChanInfo::T_UNKNOWN; // if filetype is unknown, try and figure it out from file extension. //if ((info.srcType == ChanInfo::T_UNKNOWN) || (info.srcType == ChanInfo::T_PLAYLIST)) { const char *ext = fileName+strlen(fileName); while (*--ext) if (*ext=='.') { ext++; break; } fileType = ChanInfo::getTypeFromStr(ext); } if (ch->info.bitrate) ch->readDelay = true; if (fileType == ChanInfo::T_PLS)  pls = new PlayList(PlayList::T_PLS, 1000); else if (fileType == ChanInfo::T_ASX)  pls = new PlayList(PlayList::T_ASX, 1000); else ch->info.contentType = fileType; }else { throw StreamException("Unsupported URL"); } if (pls) { LOG_CHANNEL("Channel is Playlist"); pls->read(*inputStream); inputStream->close(); delete inputStream; inputStream = NULL; int urlNum=0; String url; LOG_CHANNEL("Playlist: %d URLs",pls->numURLs); while ((ch->thread.active) && (pls->numURLs) && (!peercastInst->isQuitting)) { if (url.isEmpty()) { url = pls->urls[urlNum%pls->numURLs]; urlNum++; } try { url = streamURL(ch,url.cstr()); }catch(StreamException &) {} } delete pls; }else { // if we didn`t get a channel id from the source, then create our own (its an original broadcast) if (!ch->info.id.isSet()) { ch->info.id = chanMgr->broadcastID; ch->info.id.encode(NULL,ch->info.name.cstr(),ch->info.genre,ch->info.bitrate); }
  47. if (ch->info.contentType == ChanInfo::T_ASX)
  48. ch->info.contentType = ChanInfo::T_WMV; ch->setStatus(Channel::S_BROADCASTING);
  49. inputStream->setReadTimeout(60); // use longer read timeout
  50. source = ch->createSource();
  51. ch->readStream(*inputStream,source);
  52. inputStream->close(); } }catch(StreamException &e) { ch->setStatus(Channel::S_ERROR); LOG_ERROR("Channel error: %s",e.msg); sys->sleep(1000); }
  53. ch->setStatus(Channel::S_CLOSING); if (inputStream) { delete inputStream;
  54. inputStream = NULL; } if (source)
  55. delete source;
  56. return nextURL; }