1 // ------------------------------------------------
6 // Servent handshaking, TODO: should be in its own class
8 // (c) 2002 peercast.org
9 // ------------------------------------------------
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 // ------------------------------------------------
31 #include "chkMemoryLeak.h"
32 #define DEBUG_NEW new(__FILE__, __LINE__)
36 // -----------------------------------
37 static void termArgs(char *str)
41 size_t slen = strlen(str);
42 for(size_t i=0; i<slen; i++)
43 if (str[i]=='&') str[i] = 0;
46 // -----------------------------------
47 char *nextCGIarg(char *cp, char *cmd, char *arg)
64 if (cnt >= (MAX_CGI_LEN-1))
80 if (cnt >= (MAX_CGI_LEN-1))
87 // -----------------------------------
88 bool getCGIargBOOL(char *a)
90 return (strcmp(a,"1")==0);
92 // -----------------------------------
93 int getCGIargINT(char *a)
98 // -----------------------------------
99 void Servent::handshakeHTTP(HTTP &http, bool isHTTP)
101 char *in = http.cmdLine;
103 if (http.isRequest("GET /"))
107 char *pt = strstr(fn,HTTP_PROTO1);
111 if (strncmp(fn,"/admin?",7)==0)
113 if (!isAllowed(ALLOW_HTML))
114 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
117 LOG_DEBUG("Admin client");
120 }else if (strncmp(fn,"/http/",6)==0)
122 String dirName = fn+6;
124 if (!isAllowed(ALLOW_HTML))
125 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
127 if (!handshakeAuth(http,fn,false))
128 throw HTTPException(HTTP_SC_UNAUTHORIZED,401);
131 handshakeRemoteFile(dirName);
134 }else if (strncmp(fn,"/html/",6)==0)
136 String dirName = fn+1;
138 if (!isAllowed(ALLOW_HTML))
139 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
141 if (handshakeAuth(http,fn,true))
142 handshakeLocalFile(dirName);
145 }else if (strncmp(fn,"/admin/?",8)==0)
147 if (!isAllowed(ALLOW_HTML))
148 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
150 LOG_DEBUG("Admin client");
153 }else if (strncmp(fn,"/admin.cgi",10)==0)
155 if (!isAllowed(ALLOW_BROADCAST))
156 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
158 char *pwdArg = getCGIarg(fn,"pass=");
159 char *songArg = getCGIarg(fn,"song=");
160 char *mountArg = getCGIarg(fn,"mount=");
161 char *urlArg = getCGIarg(fn,"url=");
163 if (pwdArg && songArg)
166 size_t slen = strlen(fn);
167 for(i=0; i<slen; i++)
168 if (fn[i]=='&') fn[i] = 0;
170 Channel *c=chanMgr->channel;
173 if ((c->status == Channel::S_BROADCASTING) &&
174 (c->info.contentType == ChanInfo::T_MP3) )
176 // if we have a mount point then check for it, otherwise update all channels.
180 match = strcmp(c->mount,mountArg)==0;
184 ChanInfo newInfo = c->info;
185 newInfo.track.title.set(songArg,String::T_ESC);
186 newInfo.track.title.convertTo(String::T_UNICODE);
190 newInfo.track.contact.set(urlArg,String::T_ESC);
191 LOG_CHANNEL("Channel Shoutcast update: %s",songArg);
192 c->updateInfo(newInfo);
199 }else if (strncmp(fn,"/pls/",5)==0)
202 if (!sock->host.isLocalhost())
203 if (!isAllowed(ALLOW_DIRECT) || !isFiltered(ServFilter::F_DIRECT))
204 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
208 if (servMgr->getChannel(fn+5,info,isPrivate()))
209 handshakePLS(info,false);
211 throw HTTPException(HTTP_SC_NOTFOUND,404);
213 }else if (strncmp(fn,"/stream/",8)==0)
216 if (!sock->host.isLocalhost())
217 if (!isAllowed(ALLOW_DIRECT) || !isFiltered(ServFilter::F_DIRECT))
218 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
220 triggerChannel(fn+8,ChanInfo::SP_HTTP,isPrivate());
223 }else if (strncmp(fn,"/channel/",9)==0)
226 if (!sock->host.isLocalhost())
227 if (!isAllowed(ALLOW_NETWORK) || !isFiltered(ServFilter::F_NETWORK))
228 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
230 triggerChannel(fn+9,ChanInfo::SP_PCP,false);
234 while (http.nextHeader());
235 http.writeLine(HTTP_SC_FOUND);
236 http.writeLineF("Location: /%s/index.html",servMgr->htmlPath);
240 else if (http.isRequest("POST /"))
244 char *pt = strstr(fn,HTTP_PROTO1);
248 if (strncmp(fn,"/pls/",5)==0)
251 if (!sock->host.isLocalhost())
252 if (!isAllowed(ALLOW_DIRECT) || !isFiltered(ServFilter::F_DIRECT))
253 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
257 if (servMgr->getChannel(fn+5,info,isPrivate()))
258 handshakePLS(info,false);
260 throw HTTPException(HTTP_SC_NOTFOUND,404);
262 }else if (strncmp(fn,"/stream/",8)==0)
265 if (!sock->host.isLocalhost())
266 if (!isAllowed(ALLOW_DIRECT) || !isFiltered(ServFilter::F_DIRECT))
267 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
269 triggerChannel(fn+8,ChanInfo::SP_HTTP,isPrivate());
271 }else if (strncmp(fn,"/admin",7)==0)
273 if (!isAllowed(ALLOW_HTML))
274 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
277 LOG_DEBUG("Admin client");
278 while(http.nextHeader()){
279 LOG_DEBUG("%s",http.cmdLine);
282 if (sock->readLine(buf, sizeof(buf)) != 0){
288 while (http.nextHeader());
289 http.writeLine(HTTP_SC_FOUND);
290 http.writeLineF("Location: /%s/index.html",servMgr->htmlPath);
293 }else if (http.isRequest("GIV"))
297 while (http.nextHeader()) ;
299 if (!isAllowed(ALLOW_NETWORK))
300 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
305 char *idstr = strstr(in,"/");
310 sock->host.toStr(ipstr);
314 // at the moment we don`t really care where the GIV came from, so just give to chan. no. if its waiting.
315 Channel *ch = chanMgr->findChannelByID(id);
318 throw HTTPException(HTTP_SC_NOTFOUND,404);
320 if (!ch->acceptGIV(sock))
321 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
324 LOG_DEBUG("Accepted GIV channel %s from: %s",idstr,ipstr);
326 sock=NULL; // release this servent but dont close socket.
330 if (!servMgr->acceptGIV(sock))
331 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
333 LOG_DEBUG("Accepted GIV PCP from: %s",ipstr);
334 sock=NULL; // release this servent but dont close socket.
337 }else if (http.isRequest(PCX_PCP_CONNECT))
340 if (!isAllowed(ALLOW_NETWORK) || !isFiltered(ServFilter::F_NETWORK))
341 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
343 processIncomingPCP(true);
345 }else if (http.isRequest("PEERCAST CONNECT"))
347 if (!isAllowed(ALLOW_NETWORK) || !isFiltered(ServFilter::F_NETWORK))
348 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
350 LOG_DEBUG("PEERCAST client");
353 }else if (http.isRequest("SOURCE"))
355 if (!isAllowed(ALLOW_BROADCAST))
356 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
361 if (ps=strstr(in,"ICE/1.0"))
365 LOG_DEBUG("ICE 1.0 client to %s",mount?mount:"unknown");
367 mount = in+strlen(in);
371 mount[-1] = 0; // password preceeds
374 loginPassword.set(in+7);
376 LOG_DEBUG("ICY client: %s %s",loginPassword.cstr(),mount?mount:"unknown");
380 loginMount.set(mount);
382 handshakeICY(Channel::SRC_ICECAST,isHTTP);
383 sock = NULL; // socket is taken over by channel, so don`t close it
385 } else if (http.isRequest("HEAD")) // for android client
389 if (str = stristr(str, "/stream/"))
394 while (*str && (('0' <= *str && *str <= '9') || ('A' <= *str && *str <= 'F') || ('a' <= *str && *str <= 'f')))
397 if (cnt == 32 && !strncmp(str, ".wmv", 4))
399 // interpret "HEAD /stream/[0-9a-fA-F]{32}.wmv" as GET
400 LOG_DEBUG("INFO: interpret as GET");
404 char *pt = strstr(fn,HTTP_PROTO1);
408 if (!sock->host.isLocalhost())
409 if (!isAllowed(ALLOW_DIRECT) || !isFiltered(ServFilter::F_DIRECT))
410 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
412 triggerChannel(fn+8,ChanInfo::SP_HTTP,isPrivate());
418 if (http.isRequest(servMgr->password))
420 if (!isAllowed(ALLOW_BROADCAST))
421 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
423 loginPassword.set(servMgr->password); // pwd already checked
425 sock->writeLine("OK2");
426 sock->writeLine("icy-caps:11");
428 LOG_DEBUG("ShoutCast client");
430 handshakeICY(Channel::SRC_SHOUTCAST,isHTTP);
431 sock = NULL; // socket is taken over by channel, so don`t close it
435 throw HTTPException(HTTP_SC_BADREQUEST,400);
437 } else if (http.isRequest(servMgr->password))
439 if (!isAllowed(ALLOW_BROADCAST))
440 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
442 loginPassword.set(servMgr->password); // pwd already checked
444 sock->writeLine("OK2");
445 sock->writeLine("icy-caps:11");
447 LOG_DEBUG("ShoutCast client");
449 handshakeICY(Channel::SRC_SHOUTCAST,isHTTP);
450 sock = NULL; // socket is taken over by channel, so don`t close it
454 throw HTTPException(HTTP_SC_BADREQUEST,400);
458 // -----------------------------------
459 bool Servent::canStream(Channel *ch)
464 if (servMgr->isDisabled)
469 if (!ch->isPlaying() || ch->isFull() || ((type == T_DIRECT) && servMgr->directFull()))
472 if (!isIndexTxt(ch) && (type == T_RELAY) && (servMgr->relaysFull()))
475 Channel *c = chanMgr->channel;
477 unsigned int needRate = 0;
478 unsigned int allRate = 0;
481 int nlr = c->localRelays();
482 allRate += c->info.bitrate * nlr;
483 if ((c != ch) && (nlr == 0)){
484 if(!isIndexTxt(c)) // for PCRaw (relay)
486 needRate+=c->info.bitrate;
491 unsigned int numRelay = servMgr->numStreams(Servent::T_RELAY,false);
492 int diff = servMgr->maxRelays - numRelay;
493 if (ch->localRelays()){
502 LOG_DEBUG("Relay check: Max=%d Now=%d Need=%d ch=%d",
503 servMgr->maxBitrateOut, allRate, needRate, ch->info.bitrate);
504 // if ( !ch->isPlaying()
506 // || (allRate + needRate + ch->info.bitrate > servMgr->maxBitrateOut)
507 // || ((type == T_RELAY) && servMgr->relaysFull() && force_off) // for PCRaw (relay) (force_off)
508 // || ((type == T_RELAY) && (((servMgr->numStreams(Servent::T_RELAY,false) + noRelay) >= servMgr->maxRelays)) && force_off) // for PCRaw (relay) (force_off)
509 // || ((type == T_DIRECT) && servMgr->directFull())
512 if (allRate + needRate + ch->info.bitrate > servMgr->maxBitrateOut)
514 LOG_DEBUG("Relay check: NG");
518 if (!isIndexTxt(ch) && (type == T_RELAY) && (numRelay + noRelay >= servMgr->maxRelays))
520 LOG_DEBUG("Relay check: NG");
525 LOG_DEBUG("Relay check: OK");
528 // -----------------------------------
529 void Servent::handshakeIncoming()
532 setStatus(S_HANDSHAKE);
535 sock->readLine(buf,sizeof(buf));
538 sock->host.toStr(sb);
541 if (stristr(buf,RTSP_PROTO1))
543 LOG_DEBUG("RTSP from %s '%.100s'",sb,buf);
545 rtsp.initRequest(buf);
547 }else if (stristr(buf,HTTP_PROTO1))
549 LOG_DEBUG("HTTP from %s '%.100s'",sb,buf);
551 http.initRequest(buf);
552 handshakeHTTP(http,true);
555 LOG_DEBUG("Connect from %s '%.100s'",sb,buf);
557 http.initRequest(buf);
558 handshakeHTTP(http,false);
562 // -----------------------------------
563 void Servent::triggerChannel(char *str, ChanInfo::PROTOCOL proto,bool relay)
567 // WLockBlock lb(&(chanMgr->channellock));
569 // LOG_DEBUG("----------triggerChannel LOCK ON");
571 servMgr->getChannel(str,info,relay);
572 // LOG_DEBUG("==========triggerChannel LOCK OFF");
575 if (proto == ChanInfo::SP_PCP)
580 outputProtocol = proto;
582 processStream(false,info);
585 // -----------------------------------
586 void writePLSHeader(Stream &s, PlayList::TYPE type)
588 s.writeLine(HTTP_SC_OK);
589 s.writeLineF("%s %s",HTTP_HS_SERVER,PCX_AGENT);
594 case PlayList::T_PLS:
597 case PlayList::T_ASX:
600 case PlayList::T_RAM:
607 s.writeLineF("%s %s",HTTP_HS_CONTENT,content);
608 s.writeLine("Content-Disposition: inline");
609 s.writeLine("Cache-Control: private" );
610 s.writeLineF("%s %s",HTTP_HS_CONNECTION,"close");
615 // -----------------------------------
616 void Servent::handshakePLS(ChanInfo &info, bool doneHandshake)
623 while (sock->readLine(in,128));
626 if (getLocalTypeURL(url,info.contentType))
631 if ((info.contentType == ChanInfo::T_WMA) || (info.contentType == ChanInfo::T_WMV))
632 type = PlayList::T_ASX;
633 else if (info.contentType == ChanInfo::T_OGM)
634 type = PlayList::T_RAM;
636 type = PlayList::T_PLS;
638 writePLSHeader(*sock,type);
642 pls = new PlayList(type,1);
644 pls->addChannel(url,info);
651 // -----------------------------------
652 void Servent::handshakePLS(ChanHitList **cl, int num, bool doneHandshake)
658 while (sock->readLine(in,128));
660 if (getLocalURL(url))
662 writePLSHeader(*sock,PlayList::T_SCPLS);
666 pls = new PlayList(PlayList::T_SCPLS,num);
668 for(int i=0; i<num; i++)
669 pls->addChannel(url,cl[i]->info);
676 // -----------------------------------
677 bool Servent::getLocalURL(char *str)
680 throw StreamException("Not connected");
687 if (sock->host.localIP())
688 h = sock->getLocalHost();
690 h = servMgr->serverHost;
692 h.port = servMgr->serverHost.port;
696 sprintf(str,"http://%s",ipStr);
700 // -----------------------------------
701 bool Servent::getLocalTypeURL(char *str, ChanInfo::TYPE type)
704 throw StreamException("Not connected");
711 if (sock->host.localIP())
712 h = sock->getLocalHost();
714 h = servMgr->serverHost;
716 h.port = servMgr->serverHost.port;
720 case ChanInfo::T_WMA:
721 case ChanInfo::T_WMV:
722 sprintf(str,"mms://%s",ipStr);
725 sprintf(str,"http://%s",ipStr);
729 // -----------------------------------
730 // Warning: testing RTSP/RTP stuff below.
731 // .. moved over to seperate app now.
732 // -----------------------------------
733 void Servent::handshakePOST()
736 while (sock->readLine(tmp,sizeof(tmp)))
737 LOG_DEBUG("POST: %s",tmp);
739 throw HTTPException(HTTP_SC_BADREQUEST,400);
743 // -----------------------------------
744 void Servent::handshakeRTSP(RTSP &rtsp)
746 throw HTTPException(HTTP_SC_BADREQUEST,400);
748 // -----------------------------------
749 bool Servent::handshakeAuth(HTTP &http,const char *args,bool local)
751 char user[1024],pass[1024];
752 user[0] = pass[0] = 0;
754 char *pwd = getCGIarg(args, "pass=");
756 if ((pwd) && strlen(servMgr->password))
759 char *as = strstr(tmp.cstr(),"&");
761 if (strcmp(tmp,servMgr->password)==0)
763 while (http.nextHeader());
771 while (http.nextHeader())
773 char *arg = http.getArgStr();
777 switch (servMgr->authType)
779 case ServMgr::AUTH_HTTPBASIC:
780 if (http.isHeader("Authorization"))
781 http.getAuthUserPass(user, pass, sizeof(user), sizeof(pass));
783 case ServMgr::AUTH_COOKIE:
784 if (http.isHeader("Cookie"))
786 LOG_DEBUG("Got cookie: %s",arg);
788 while ((idp = strstr(idp,"id=")))
791 gotCookie.set(idp,sock->host.ip);
792 if (servMgr->cookieList.contains(gotCookie))
794 LOG_DEBUG("Cookie found");
805 if (sock->host.isLocalhost())
809 switch (servMgr->authType)
811 case ServMgr::AUTH_HTTPBASIC:
813 if ((strcmp(pass,servMgr->password)==0) && strlen(servMgr->password))
816 case ServMgr::AUTH_COOKIE:
817 if (servMgr->cookieList.contains(cookie))
824 if (servMgr->authType == ServMgr::AUTH_HTTPBASIC)
826 http.writeLine(HTTP_SC_UNAUTHORIZED);
827 http.writeLine("WWW-Authenticate: Basic realm=\"PeerCast Admin\"");
828 }else if (servMgr->authType == ServMgr::AUTH_COOKIE)
830 String file = servMgr->htmlPath;
831 file.append("/login.html");
833 handshakeLocalFile(file);
835 handshakeRemoteFile(file);
842 // -----------------------------------
843 void Servent::handshakeCMD(char *cmd)
845 char result[MAX_CGI_LEN];
846 char arg[MAX_CGI_LEN];
847 char curr[MAX_CGI_LEN];
858 if (!handshakeAuth(http,cmd,true))
863 if (cmpCGIarg(cmd,"cmd=","redirect"))
865 char *j = getCGIarg(cmd,"url=");
870 url.set(j,String::T_ESC);
871 url.convertTo(String::T_ASCII);
873 if (!url.contains("http://"))
874 url.prepend("http://");
876 html.setRefreshURL(url.cstr());
880 html.startTagEnd("h3","Please wait...");
887 if (cmpCGIarg(cmd,"cmd=","viewxml"))
892 }else if (cmpCGIarg(cmd,"cmd=","clearlog"))
894 sys->logBuf->clear();
895 sprintf(jumpStr,"/%s/viewlog.html",servMgr->htmlPath);
898 }else if (cmpCGIarg(cmd,"cmd=","save"))
901 peercastInst->saveSettings();
903 sprintf(jumpStr,"/%s/settings.html",servMgr->htmlPath);
905 }else if (cmpCGIarg(cmd,"cmd=","reg"))
908 chanMgr->broadcastID.toStr(idstr);
909 sprintf(jumpStr,"http://www.peercast.org/register/?id=%s",idstr);
911 }else if (cmpCGIarg(cmd,"cmd=","edit_bcid"))
916 while (cp=nextCGIarg(cp,curr,arg))
918 if (strcmp(curr,"id")==0)
920 else if (strcmp(curr,"del")==0)
921 servMgr->removeValidBCID(id);
922 else if (strcmp(curr,"valid")==0)
924 bcid = servMgr->findValidBCID(id);
926 bcid->valid = getCGIargBOOL(arg);
929 peercastInst->saveSettings();
930 sprintf(jumpStr,"/%s/bcid.html",servMgr->htmlPath);
933 }else if (cmpCGIarg(cmd,"cmd=","add_bcid"))
935 BCID *bcid = new BCID();
939 while (cp=nextCGIarg(cp,curr,arg))
941 if (strcmp(curr,"id")==0)
942 bcid->id.fromStr(arg);
943 else if (strcmp(curr,"name")==0)
945 else if (strcmp(curr,"email")==0)
946 bcid->email.set(arg);
947 else if (strcmp(curr,"url")==0)
949 else if (strcmp(curr,"valid")==0)
950 bcid->valid = getCGIargBOOL(arg);
951 else if (strcmp(curr,"result")==0)
956 LOG_DEBUG("Adding BCID : %s",bcid->name.cstr());
957 servMgr->addValidBCID(bcid);
958 peercastInst->saveSettings();
961 http.writeLine(HTTP_SC_OK);
963 http.writeString("OK");
966 sprintf(jumpStr,"/%s/bcid.html",servMgr->htmlPath);
971 }else if (cmpCGIarg(cmd,"cmd=","apply"))
973 //servMgr->numFilters = 0;
974 ServFilter *currFilter=servMgr->filters;
975 bool beginfilt = false;
982 int newPort=servMgr->serverHost.port;
983 int enableGetName = 0;
984 int allowConnectPCST = 0;
985 int disableAutoBumpIfDirect = 0; //JP-MOD
986 int asxDetailedMode = 0; //JP-MOD
989 while (cp=nextCGIarg(cp,curr,arg))
991 LOG_DEBUG("ARG: %s = %s", curr, arg);
994 if (strcmp(curr,"serveractive")==0)
995 servMgr->autoServe = getCGIargBOOL(arg);
996 else if (strcmp(curr,"port")==0)
997 newPort = getCGIargINT(arg);
998 else if (strcmp(curr,"icymeta")==0)
1000 int iv = getCGIargINT(arg);
1002 else if (iv > 16384) iv = 16384;
1004 chanMgr->icyMetaInterval = iv;
1006 }else if (strcmp(curr,"passnew")==0)
1007 strcpy(servMgr->password,arg);
1008 else if (strcmp(curr,"root")==0)
1009 servMgr->isRoot = getCGIargBOOL(arg);
1010 else if (strcmp(curr,"brroot")==0)
1011 brRoot = getCGIargBOOL(arg);
1012 else if (strcmp(curr,"getupd")==0)
1013 getUpd = getCGIargBOOL(arg);
1014 else if (strcmp(curr,"huint")==0)
1015 chanMgr->setUpdateInterval(getCGIargINT(arg));
1016 else if (strcmp(curr,"forceip")==0)
1017 servMgr->forceIP = arg;
1018 else if (strcmp(curr,"htmlPath")==0)
1020 strcpy(servMgr->htmlPath,"html/");
1021 strcat(servMgr->htmlPath,arg);
1022 }else if (strcmp(curr,"djmsg")==0)
1025 msg.set(arg,String::T_ESC);
1026 msg.convertTo(String::T_UNICODE);
1027 chanMgr->setBroadcastMsg(msg);
1029 else if (strcmp(curr,"pcmsg")==0)
1031 servMgr->rootMsg.set(arg,String::T_ESC);
1032 servMgr->rootMsg.convertTo(String::T_UNICODE);
1033 }else if (strcmp(curr,"minpgnu")==0)
1034 servMgr->minGnuIncoming = atoi(arg);
1035 else if (strcmp(curr,"maxpgnu")==0)
1036 servMgr->maxGnuIncoming = atoi(arg);
1041 else if (strcmp(curr,"maxcin")==0)
1042 servMgr->maxControl = getCGIargINT(arg);
1044 else if (strcmp(curr,"maxup")==0)
1045 servMgr->maxBitrateOut = getCGIargINT(arg);
1046 else if (strcmp(curr,"maxrelays")==0)
1047 servMgr->setMaxRelays(getCGIargINT(arg));
1048 else if (strcmp(curr,"maxdirect")==0)
1049 servMgr->maxDirect = getCGIargINT(arg);
1050 else if (strcmp(curr,"maxrelaypc")==0)
1051 chanMgr->maxRelaysPerChannel = getCGIargINT(arg);
1052 else if (strncmp(curr,"filt_",5)==0)
1055 servMgr->numFilters = 0;
1060 if (strncmp(fs,"ip",2)==0) // ip must be first
1062 currFilter = &servMgr->filters[servMgr->numFilters];
1064 currFilter->host.fromStrIP(arg,DEFAULT_PORT);
1065 if ((currFilter->host.ip) && (servMgr->numFilters < (ServMgr::MAX_FILTERS-1)))
1067 servMgr->numFilters++;
1068 servMgr->filters[servMgr->numFilters].init(); // clear new entry
1069 LOG_DEBUG("numFilters = %d", servMgr->numFilters);
1072 }else if (strncmp(fs,"bn",2)==0)
1073 currFilter->flags |= ServFilter::F_BAN;
1074 else if (strncmp(fs,"pr",2)==0)
1075 currFilter->flags |= ServFilter::F_PRIVATE;
1076 else if (strncmp(fs,"nw",2)==0)
1077 currFilter->flags |= ServFilter::F_NETWORK;
1078 else if (strncmp(fs,"di",2)==0)
1079 currFilter->flags |= ServFilter::F_DIRECT;
1084 else if (strcmp(curr,"clientactive")==0)
1085 servMgr->autoConnect = getCGIargBOOL(arg);
1086 else if (strcmp(curr,"yp")==0)
1090 String str(arg,String::T_ESC);
1091 str.convertTo(String::T_ASCII);
1092 servMgr->rootHost = str;
1095 else if (strcmp(curr,"yp2")==0)
1099 String str(arg,String::T_ESC);
1100 str.convertTo(String::T_ASCII);
1101 servMgr->rootHost2 = str;
1104 else if (strcmp(curr,"deadhitage")==0)
1105 chanMgr->deadHitAge = getCGIargINT(arg);
1106 else if (strcmp(curr,"refresh")==0)
1107 servMgr->refreshHTML = getCGIargINT(arg);
1108 else if (strcmp(curr,"auth")==0)
1110 if (strcmp(arg,"cookie")==0)
1111 servMgr->authType = ServMgr::AUTH_COOKIE;
1112 else if (strcmp(arg,"http")==0)
1113 servMgr->authType = ServMgr::AUTH_HTTPBASIC;
1115 }else if (strcmp(curr,"expire")==0)
1117 if (strcmp(arg,"session")==0)
1118 servMgr->cookieList.neverExpire = false;
1119 else if (strcmp(arg,"never")==0)
1120 servMgr->cookieList.neverExpire = true;
1123 else if (strcmp(curr,"logDebug")==0)
1124 showLog |= atoi(arg)?(1<<LogBuffer::T_DEBUG):0;
1125 else if (strcmp(curr,"logErrors")==0)
1126 showLog |= atoi(arg)?(1<<LogBuffer::T_ERROR):0;
1127 else if (strcmp(curr,"logNetwork")==0)
1128 showLog |= atoi(arg)?(1<<LogBuffer::T_NETWORK):0;
1129 else if (strcmp(curr,"logChannel")==0)
1130 showLog |= atoi(arg)?(1<<LogBuffer::T_CHANNEL):0;
1132 else if (strcmp(curr,"allowHTML1")==0)
1133 allowServer1 |= atoi(arg)?(ALLOW_HTML):0;
1134 else if (strcmp(curr,"allowNetwork1")==0)
1135 allowServer1 |= atoi(arg)?(ALLOW_NETWORK):0;
1136 else if (strcmp(curr,"allowBroadcast1")==0)
1137 allowServer1 |= atoi(arg)?(ALLOW_BROADCAST):0;
1138 else if (strcmp(curr,"allowDirect1")==0)
1139 allowServer1 |= atoi(arg)?(ALLOW_DIRECT):0;
1141 else if (strcmp(curr,"allowHTML2")==0)
1142 allowServer2 |= atoi(arg)?(ALLOW_HTML):0;
1143 else if (strcmp(curr,"allowBroadcast2")==0)
1144 allowServer2 |= atoi(arg)?(ALLOW_BROADCAST):0;
1147 else if (strcmp(curr, "autoRelayKeep") ==0)
1148 servMgr->autoRelayKeep = getCGIargINT(arg);
1149 else if (strcmp(curr, "autoMaxRelaySetting") ==0)
1150 servMgr->autoMaxRelaySetting = getCGIargINT(arg);
1151 else if (strcmp(curr, "autoBumpSkipCount") ==0)
1152 servMgr->autoBumpSkipCount = getCGIargINT(arg);
1153 else if (strcmp(curr, "kickPushStartRelays") ==0)
1154 servMgr->kickPushStartRelays = getCGIargINT(arg);
1155 else if (strcmp(curr, "kickPushInterval") ==0)
1156 servMgr->kickPushInterval = getCGIargINT(arg);
1157 else if (strcmp(curr, "allowConnectPCST") ==0)
1158 allowConnectPCST = atoi(arg) ? 1 : 0;
1159 else if (strcmp(curr, "enableGetName") ==0)
1160 enableGetName = atoi(arg)? 1 : 0;
1161 else if (strcmp(curr, "autoPort0Kick") ==0)
1162 servMgr->autoPort0Kick = getCGIargBOOL(arg);
1163 else if (strcmp(curr, "allowOnlyVP") ==0)
1164 servMgr->allowOnlyVP = getCGIargBOOL(arg);
1165 else if (strcmp(curr, "kickKeepTime") ==0)
1166 servMgr->kickKeepTime = getCGIargINT(arg);
1168 else if (strcmp(curr, "maxRelaysIndexTxt") ==0) // for PCRaw (relay)
1169 servMgr->maxRelaysIndexTxt = getCGIargINT(arg);
1170 else if (strcmp(curr, "disableAutoBumpIfDirect") ==0) //JP-MOD
1171 disableAutoBumpIfDirect = atoi(arg) ? 1 : 0;
1172 else if (strcmp(curr, "asxDetailedMode") ==0) //JP-MOD
1173 asxDetailedMode = getCGIargINT(arg);
1178 servMgr->showLog = showLog;
1179 servMgr->allowServer1 = allowServer1;
1180 servMgr->allowServer2 = allowServer2;
1181 servMgr->enableGetName = enableGetName;
1182 servMgr->allowConnectPCST = allowConnectPCST;
1183 servMgr->disableAutoBumpIfDirect = disableAutoBumpIfDirect; //JP-MOD
1184 servMgr->asxDetailedMode = asxDetailedMode; //JP-MOD
1185 if (!(servMgr->allowServer1 & ALLOW_HTML) && !(servMgr->allowServer2 & ALLOW_HTML))
1186 servMgr->allowServer1 |= ALLOW_HTML;
1188 if (servMgr->serverHost.port != newPort)
1190 Host lh(ClientSocket::getIP(NULL),newPort);
1193 sprintf(jumpStr,"http://%s/%s/settings.html",ipstr,servMgr->htmlPath);
1195 servMgr->serverHost.port = newPort;
1196 servMgr->restartServer=true;
1197 //html.setRefresh(3);
1198 //html.setRefreshURL(jumpStr);
1201 // html.startBody();
1202 // html.startTagEnd("h1","Please wait...");
1209 //servMgr->serverHost.toStr(ipstr);
1210 //sprintf(jumpStr,"/%s/settings.html",ipstr,servMgr->htmlPath);
1215 sprintf(jumpStr,"/%s/settings.html",servMgr->htmlPath);
1219 peercastInst->saveSettings();
1221 peercastApp->updateSettings();
1223 if ((servMgr->isRoot) && (brRoot))
1224 servMgr->broadcastRootSettings(getUpd);
1230 }else if (cmpCGIarg(cmd,"cmd=","fetch"))
1237 while (cp=nextCGIarg(cp,curr,arg))
1239 if (strcmp(curr,"url")==0)
1241 curl.set(arg,String::T_ESC);
1242 curl.convertTo(String::T_UNICODE);
1243 }else if (strcmp(curr,"name")==0)
1245 info.name.set(arg,String::T_ESC);
1246 info.name.convertTo(String::T_UNICODE);
1247 }else if (strcmp(curr,"desc")==0)
1249 info.desc.set(arg,String::T_ESC);
1250 info.desc.convertTo(String::T_UNICODE);
1251 }else if (strcmp(curr,"genre")==0)
1253 info.genre.set(arg,String::T_ESC);
1254 info.genre.convertTo(String::T_UNICODE);
1255 }else if (strcmp(curr,"contact")==0)
1257 info.url.set(arg,String::T_ESC);
1258 info.url.convertTo(String::T_UNICODE);
1259 }else if (strcmp(curr,"bitrate")==0)
1261 info.bitrate = atoi(arg);
1262 }else if (strcmp(curr,"type")==0)
1264 info.contentType = ChanInfo::getTypeFromStr(arg);
1265 }else if (strcmp(curr,"bcstClap")==0) //JP-MOD
1267 info.ppFlags |= ServMgr::bcstClap;
1272 info.bcID = chanMgr->broadcastID;
1274 Channel *c = chanMgr->createChannel(info,NULL);
1276 c->startURL(curl.cstr());
1279 sprintf(jumpStr,"/%s/relays.html",servMgr->htmlPath);
1282 }else if (cmpCGIarg(cmd,"cmd=","stopserv"))
1286 while (cp=nextCGIarg(cp,curr,arg))
1288 if (strcmp(curr,"index")==0)
1290 Servent *s = servMgr->findServentByIndex(atoi(arg));
1295 sprintf(jumpStr,"/%s/connections.html",servMgr->htmlPath);
1299 }else if (cmpCGIarg(cmd,"cmd=","hitlist"))
1302 bool stayConnected=hasCGIarg(cmd,"relay");
1305 ChanHitList *chl = chanMgr->hitlist;
1311 sprintf(tmp,"c%d=",index);
1312 if (cmpCGIarg(cmd,tmp,"1"))
1315 if (!(c=chanMgr->findChannelByID(chl->info.id)))
1317 c = chanMgr->createChannel(chl->info,NULL);
1319 throw StreamException("out of channels");
1320 c->stayConnected = stayConnected;
1329 char *findArg = getCGIarg(cmd,"keywords=");
1331 if (hasCGIarg(cmd,"relay"))
1334 sprintf(jumpStr,"/%s/relays.html",servMgr->htmlPath);
1337 }else if (cmpCGIarg(cmd,"cmd=","clear"))
1340 while (cp=nextCGIarg(cp,curr,arg))
1342 if (strcmp(curr,"hostcache")==0)
1343 servMgr->clearHostCache(ServHost::T_SERVENT);
1344 else if (strcmp(curr,"hitlists")==0)
1345 chanMgr->clearHitLists();
1346 else if (strcmp(curr,"packets")==0)
1348 stats.clearRange(Stats::PACKETSSTART,Stats::PACKETSEND);
1349 servMgr->numVersions = 0;
1353 sprintf(jumpStr,"/%s/index.html",servMgr->htmlPath);
1356 }else if (cmpCGIarg(cmd,"cmd=","upgrade"))
1358 if (servMgr->downloadURL[0])
1360 sprintf(jumpStr,"/admin?cmd=redirect&url=%s",servMgr->downloadURL);
1367 }else if (cmpCGIarg(cmd,"cmd=","connect"))
1371 Servent *s = servMgr->servents;
1374 sprintf(tmp,"c%d=",s->serventIndex);
1375 if (cmpCGIarg(cmd,tmp,"1"))
1377 if (hasCGIarg(cmd,"stop"))
1378 s->thread.active = false;
1382 sprintf(jumpStr,"/%s/connections.html",servMgr->htmlPath);
1385 }else if (cmpCGIarg(cmd,"cmd=","shutdown"))
1387 servMgr->shutdownTimer = 1;
1389 }else if (cmpCGIarg(cmd,"cmd=","stop"))
1393 while (cp=nextCGIarg(cp,curr,arg))
1395 if (strcmp(curr,"id")==0)
1399 Channel *c = chanMgr->findChannelByID(id);
1401 c->thread.active = false;
1402 c->thread.finish = true;
1406 sprintf(jumpStr,"/%s/relays.html",servMgr->htmlPath);
1409 }else if (cmpCGIarg(cmd,"cmd=","bump"))
1413 while (cp=nextCGIarg(cp,curr,arg))
1415 if (strcmp(curr,"id")==0)
1419 Channel *c = chanMgr->findChannelByID(id);
1423 sprintf(jumpStr,"/%s/relays.html",servMgr->htmlPath);
1426 }else if (cmpCGIarg(cmd,"cmd=","keep"))
1430 while (cp=nextCGIarg(cp,curr,arg))
1432 if (strcmp(curr,"id")==0)
1436 Channel *c = chanMgr->findChannelByID(id);
1439 //c->stayConnected = true;
1440 if (!c->stayConnected)
1442 //if (servMgr->getFirewall() == ServMgr::FW_OFF)
1443 c->stayConnected = true;
1446 c->stayConnected = false;
1449 sprintf(jumpStr,"/%s/relays.html",servMgr->htmlPath);
1452 }else if (cmpCGIarg(cmd,"cmd=","relay"))
1456 while (cp=nextCGIarg(cp,curr,arg))
1458 if (strcmp(curr,"id")==0)
1459 info.id.fromStr(arg);
1463 if (!chanMgr->findChannelByID(info.id))
1466 ChanHitList *chl = chanMgr->findHitList(info);
1468 throw StreamException("channel not found");
1471 Channel *c = chanMgr->createChannel(chl->info,NULL);
1473 throw StreamException("out of channels");
1475 c->stayConnected = true;
1479 sprintf(jumpStr,"/%s/relays.html",servMgr->htmlPath);
1483 }else if (cmpCGIarg(cmd,"net=","add"))
1488 while (cmd=nextCGIarg(cmd,curr,arg))
1490 if (strcmp(curr,"ip")==0)
1493 h.fromStrIP(arg,DEFAULT_PORT);
1494 if (servMgr->addOutgoing(h,id,true))
1495 LOG_NETWORK("Added connection: %s",arg);
1497 }else if (strcmp(curr,"id")==0)
1504 }else if (cmpCGIarg(cmd,"cmd=","logout"))
1507 servMgr->cookieList.remove(cookie);
1509 }else if (cmpCGIarg(cmd,"cmd=","login"))
1516 cookie.set(idstr,sock->host.ip);
1517 servMgr->cookieList.add(cookie);
1519 http.writeLine(HTTP_SC_FOUND);
1520 if (servMgr->cookieList.neverExpire)
1521 http.writeLineF("%s id=%s; path=/; expires=\"Mon, 01-Jan-3000 00:00:00 GMT\";",HTTP_HS_SETCOOKIE,idstr);
1523 http.writeLineF("%s id=%s; path=/;",HTTP_HS_SETCOOKIE,idstr);
1524 http.writeLineF("Location: /%s/index.html",servMgr->htmlPath);
1527 }else if (cmpCGIarg(cmd,"cmd=","setmeta"))
1530 while (cp=nextCGIarg(cp,curr,arg))
1532 if (strcmp(curr,"name")==0)
1535 chname.set(arg,String::T_ESC);
1536 chname.convertTo(String::T_ASCII);
1537 for(int i=0; i<ChanMgr::MAX_CHANNELS; i++)
1539 Channel *c = &chanMgr->channels[i];
1540 if ((c->isActive()) && (c->status == Channel::S_BROADCASTING) && (strcmp(c->info.name.cstr(),chname.cstr())==0))
1542 ChanInfo newInfo = c->info;
1544 while (cmd=nextCGIarg(cmd,curr,arg))
1547 chmeta.set(arg,String::T_ESC);
1548 chmeta.convertTo(String::T_ASCII);
1549 if (strcmp(curr,"desc")==0)
1550 newInfo.desc = chmeta.cstr();
1551 else if (strcmp(curr,"url")==0)
1552 newInfo.url = chmeta.cstr();
1553 else if (strcmp(curr,"genre")==0)
1554 newInfo.genre = chmeta.cstr();
1555 else if (strcmp(curr,"comment")==0)
1556 newInfo.comment = chmeta.cstr();
1557 else if (strcmp(curr,"t_contact")==0)
1558 newInfo.track.contact = chmeta.cstr();
1559 else if (strcmp(curr,"t_title")==0)
1560 newInfo.track.title = chmeta.cstr();
1561 else if (strcmp(curr,"t_artist")==0)
1562 newInfo.track.artist = chmeta.cstr();
1563 else if (strcmp(curr,"t_album")==0)
1564 newInfo.track.album = chmeta.cstr();
1565 else if (strcmp(curr,"t_genre")==0)
1566 newInfo.track.genre = chmeta.cstr();
1568 c->updateInfo(newInfo);
1570 newInfo.id.toStr(idstr);
1571 sprintf(jumpStr,"/%s/relayinfo.html?id=%s",servMgr->htmlPath,idstr);
1577 chname.set(arg,String::T_ESC);
1578 chname.convertTo(String::T_ASCII);
1580 Channel *c = chanMgr->findChannelByName(chname.cstr());
1581 if (c && (c->isActive()) && (c->status == Channel::S_BROADCASTING)){
1582 ChanInfo newInfo = c->info;
1583 newInfo.ppFlags = ServMgr::bcstNone; //JP-MOD
1584 while (cmd=nextCGIarg(cmd,curr,arg))
1587 chmeta.set(arg,String::T_ESC);
1588 chmeta.convertTo(String::T_ASCII);
1589 if (strcmp(curr,"desc")==0)
1590 newInfo.desc = chmeta.cstr();
1591 else if (strcmp(curr,"url")==0)
1592 newInfo.url = chmeta.cstr();
1593 else if (strcmp(curr,"genre")==0)
1594 newInfo.genre = chmeta.cstr();
1595 else if (strcmp(curr,"comment")==0)
1596 newInfo.comment = chmeta.cstr();
1597 else if (strcmp(curr,"bcstClap")==0) //JP-MOD
1598 newInfo.ppFlags |= ServMgr::bcstClap;
1599 else if (strcmp(curr,"t_contact")==0)
1600 newInfo.track.contact = chmeta.cstr();
1601 else if (strcmp(curr,"t_title")==0)
1602 newInfo.track.title = chmeta.cstr();
1603 else if (strcmp(curr,"t_artist")==0)
1604 newInfo.track.artist = chmeta.cstr();
1605 else if (strcmp(curr,"t_album")==0)
1606 newInfo.track.album = chmeta.cstr();
1607 else if (strcmp(curr,"t_genre")==0)
1608 newInfo.track.genre = chmeta.cstr();
1610 c->updateInfo(newInfo);
1612 newInfo.id.toStr(idstr);
1613 sprintf(jumpStr,"/%s/relayinfo.html?id=%s",servMgr->htmlPath,idstr);
1625 sprintf(jumpStr,"/%s/index.html",servMgr->htmlPath);
1630 }catch(StreamException &e)
1632 html.startTagEnd("h1","ERROR - %s",e.msg);
1633 LOG_ERROR("html: %s",e.msg);
1641 String jmp(jumpArg,String::T_HTML);
1642 jmp.convertTo(String::T_ASCII);
1643 html.locateTo(jmp.cstr());
1649 // -----------------------------------
1650 static XML::Node *createChannelXML(Channel *c)
1652 XML::Node *n = c->info.createChannelXML();
1653 n->add(c->createRelayXML(true));
1654 n->add(c->info.createTrackXML());
1655 // n->add(c->info.createServentXML());
1658 // -----------------------------------
1659 static XML::Node *createChannelXML(ChanHitList *chl)
1661 XML::Node *n = chl->info.createChannelXML();
1662 n->add(chl->createXML());
1663 n->add(chl->info.createTrackXML());
1664 // n->add(chl->info.createServentXML());
1667 // -----------------------------------
1668 void Servent::handshakeXML()
1676 XML::Node *rn = new XML::Node("peercast");
1680 rn->add(new XML::Node("servent uptime=\"%d\"",servMgr->getUptime()));
1682 rn->add(new XML::Node("bandwidth out=\"%d\" in=\"%d\"",
1683 stats.getPerSecond(Stats::BYTESOUT)-stats.getPerSecond(Stats::LOCALBYTESOUT),
1684 stats.getPerSecond(Stats::BYTESIN)-stats.getPerSecond(Stats::LOCALBYTESIN)
1687 rn->add(new XML::Node("connections total=\"%d\" relays=\"%d\" direct=\"%d\"",servMgr->totalConnected(),servMgr->numStreams(Servent::T_RELAY,true),servMgr->numStreams(Servent::T_DIRECT,true)));
1689 XML::Node *an = new XML::Node("channels_relayed total=\"%d\"",chanMgr->numChannels());
1692 Channel *c = chanMgr->channel;
1696 an->add(createChannelXML(c));
1701 // add public channels
1703 XML::Node *fn = new XML::Node("channels_found total=\"%d\"",chanMgr->numHitLists());
1706 ChanHitList *chl = chanMgr->hitlist;
1710 fn->add(createChannelXML(chl));
1717 if (servMgr->isRoot)
1719 // add private channels
1721 XML::Node *pn = new XML::Node("priv_channels");
1724 ChanHitList *chl = chanMgr->hitlist;
1728 if (chl->info.isPrivate())
1729 pn->add(createChannelXML(chl));
1736 XML::Node *hc = new XML::Node("host_cache");
1737 for(i=0; i<ServMgr::MAX_HOSTCACHE; i++)
1739 ServHost *sh = &servMgr->hostCache[i];
1740 if (sh->type != ServHost::T_NONE)
1743 sh->host.toStr(ipstr);
1745 hc->add(new XML::Node("host ip=\"%s\" type=\"%s\" time=\"%d\"",ipstr,ServHost::getTypeStr(sh->type),sh->time));
1752 // calculate content-length
1756 // set line-feed code to CRLF (for HTTP header)
1757 bool bWriteCRLF = sock->writeCRLF;
1758 sock->writeCRLF = true;
1760 // write HTTP response header
1761 sock->writeLine(HTTP_SC_OK);
1762 sock->writeLineF("%s %s",HTTP_HS_SERVER,PCX_AGENT);
1763 sock->writeLineF("%s %s",HTTP_HS_CONTENT,MIME_XML);
1764 sock->writeLineF("%s %d", HTTP_HS_LENGTH, ds.getLength());
1765 sock->writeLine("Connection: close");
1766 sock->writeLine("");
1769 sock->writeCRLF = bWriteCRLF;
1775 // -----------------------------------
1776 void Servent::readICYHeader(HTTP &http, ChanInfo &info, char *pwd, size_t szPwd)
1778 char *arg = http.getArgStr();
1781 if (http.isHeader("x-audiocast-name") || http.isHeader("icy-name") || http.isHeader("ice-name"))
1783 info.name.set(arg,String::T_ASCII);
1784 info.name.convertTo(String::T_UNICODE);
1786 }else if (http.isHeader("x-audiocast-url") || http.isHeader("icy-url") || http.isHeader("ice-url"))
1787 info.url.set(arg,String::T_ASCII);
1788 else if (http.isHeader("x-audiocast-bitrate") || (http.isHeader("icy-br")) || http.isHeader("ice-bitrate") || http.isHeader("icy-bitrate"))
1789 info.bitrate = atoi(arg);
1790 else if (http.isHeader("x-audiocast-genre") || http.isHeader("ice-genre") || http.isHeader("icy-genre"))
1792 info.genre.set(arg,String::T_ASCII);
1793 info.genre.convertTo(String::T_UNICODE);
1795 }else if (http.isHeader("x-audiocast-description") || http.isHeader("ice-description"))
1797 info.desc.set(arg,String::T_ASCII);
1798 info.desc.convertTo(String::T_UNICODE);
1800 }else if (http.isHeader("Authorization"))
1801 http.getAuthUserPass(NULL, pwd, 0, sizeof(pwd));
1802 else if (http.isHeader(PCX_HS_CHANNELID))
1803 info.id.fromStr(arg);
1804 else if (http.isHeader("ice-password"))
1807 if (strlen(arg) < 64)
1809 }else if (http.isHeader("content-type"))
1811 if (stristr(arg,MIME_OGG))
1812 info.contentType = ChanInfo::T_OGG;
1813 else if (stristr(arg,MIME_XOGG))
1814 info.contentType = ChanInfo::T_OGG;
1816 else if (stristr(arg,MIME_MP3))
1817 info.contentType = ChanInfo::T_MP3;
1818 else if (stristr(arg,MIME_XMP3))
1819 info.contentType = ChanInfo::T_MP3;
1821 else if (stristr(arg,MIME_WMA))
1822 info.contentType = ChanInfo::T_WMA;
1823 else if (stristr(arg,MIME_WMV))
1824 info.contentType = ChanInfo::T_WMV;
1825 else if (stristr(arg,MIME_ASX))
1826 info.contentType = ChanInfo::T_ASX;
1828 else if (stristr(arg,MIME_NSV))
1829 info.contentType = ChanInfo::T_NSV;
1830 else if (stristr(arg,MIME_RAW))
1831 info.contentType = ChanInfo::T_RAW;
1833 else if (stristr(arg,MIME_MMS))
1834 info.srcProtocol = ChanInfo::SP_MMS;
1835 else if (stristr(arg,MIME_XPCP))
1836 info.srcProtocol = ChanInfo::SP_PCP;
1837 else if (stristr(arg,MIME_XPEERCAST))
1838 info.srcProtocol = ChanInfo::SP_PEERCAST;
1840 else if (stristr(arg,MIME_XSCPLS))
1841 info.contentType = ChanInfo::T_PLS;
1842 else if (stristr(arg,MIME_PLS))
1843 info.contentType = ChanInfo::T_PLS;
1844 else if (stristr(arg,MIME_XPLS))
1845 info.contentType = ChanInfo::T_PLS;
1846 else if (stristr(arg,MIME_M3U))
1847 info.contentType = ChanInfo::T_PLS;
1848 else if (stristr(arg,MIME_MPEGURL))
1849 info.contentType = ChanInfo::T_PLS;
1850 else if (stristr(arg,MIME_TEXT))
1851 info.contentType = ChanInfo::T_PLS;
1858 // -----------------------------------
1859 void Servent::handshakeICY(Channel::SRC_TYPE type, bool isHTTP)
1865 // default to mp3 for shoutcast DSP (doesn`t send content-type)
1866 if (type == Channel::SRC_SHOUTCAST)
1867 info.contentType = ChanInfo::T_MP3;
1869 while (http.nextHeader())
1871 LOG_DEBUG("ICY %.100s",http.cmdLine);
1872 readICYHeader(http, info, loginPassword.cstr(), loginPassword.MAX_LEN);
1877 // check password before anything else, if needed
1878 if (!loginPassword.isSame(servMgr->password))
1880 if (!sock->host.isLocalhost() || !loginPassword.isEmpty())
1881 throw HTTPException(HTTP_SC_UNAUTHORIZED,401);
1885 // we need a valid IP address before we start
1886 servMgr->checkFirewall();
1889 // attach channel ID to name, channel ID is also encoded with IP address
1890 // to help prevent channel hijacking.
1893 info.id = chanMgr->broadcastID;
1894 info.id.encode(NULL,info.name.cstr(),loginMount.cstr(),info.bitrate);
1896 LOG_DEBUG("Incoming source: %s : %s",info.name.cstr(),info.getTypeStr());
1900 sock->writeStringF("%s\n\n",HTTP_SC_OK);
1902 sock->writeLine("OK");
1904 Channel *c = chanMgr->findChannelByID(info.id);
1907 LOG_CHANNEL("ICY channel already active, closing old one");
1908 c->thread.shutdown();
1912 info.comment = chanMgr->broadcastMsg;
1913 info.bcID = chanMgr->broadcastID;
1915 c = chanMgr->createChannel(info,loginMount.cstr());
1917 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
1919 c->startICY(sock,type);
1923 // -----------------------------------
1924 void Servent::handshakeLocalFile(const char *fn)
1929 if (servMgr->getModulePath) //JP-EX
1931 peercastApp->getDirectory();
1932 fileName = servMgr->modulePath;
1934 fileName = peercastApp->getPath();
1936 fileName.append(fn);
1938 LOG_DEBUG("Writing HTML file: %s",fileName.cstr());
1940 HTML html("",*sock);
1942 char *args = strstr(fileName.cstr(),"?");
1946 if (fileName.contains(".htm"))
1948 html.writeOK(MIME_HTML);
1949 html.writeTemplate(fileName.cstr(),args);
1951 }else if (fileName.contains(".css"))
1953 html.writeOK(MIME_CSS);
1954 html.writeRawFile(fileName.cstr());
1955 }else if (fileName.contains(".jpg"))
1957 html.writeOK(MIME_JPEG);
1958 html.writeRawFile(fileName.cstr());
1959 }else if (fileName.contains(".gif"))
1961 html.writeOK(MIME_GIF);
1962 html.writeRawFile(fileName.cstr());
1963 }else if (fileName.contains(".png"))
1965 html.writeOK(MIME_PNG);
1966 html.writeRawFile(fileName.cstr());
1970 // -----------------------------------
1971 void Servent::handshakeRemoteFile(const char *dirName)
1973 ClientSocket *rsock = sys->createSocket();
1975 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
1978 const char *hostName = "www.peercast.org"; // hardwired for "security"
1981 host.fromStrName(hostName,80);
1989 rhttp.writeLineF("GET /%s HTTP/1.0",dirName);
1990 rhttp.writeLineF("%s %s",HTTP_HS_HOST,hostName);
1991 rhttp.writeLineF("%s %s",HTTP_HS_CONNECTION,"close");
1992 rhttp.writeLineF("%s %s",HTTP_HS_ACCEPT,"*/*");
1993 rhttp.writeLine("");
1996 bool isTemplate = false;
1997 while (rhttp.nextHeader())
1999 char *arg = rhttp.getArgStr();
2002 if (rhttp.isHeader("content-type"))
2007 MemoryStream mem(100*1024);
2008 while (!rsock->eof())
2012 len = rsock->readUpto(buf,sizeof(buf));
2021 int fileLen = mem.getPosition();
2026 if (contentType.contains(MIME_HTML))
2029 sock->writeLine(HTTP_SC_OK);
2030 sock->writeLineF("%s %s",HTTP_HS_SERVER,PCX_AGENT);
2031 sock->writeLineF("%s %s",HTTP_HS_CACHE,"no-cache");
2032 sock->writeLineF("%s %s",HTTP_HS_CONNECTION,"close");
2033 sock->writeLineF("%s %s",HTTP_HS_CONTENT,contentType.cstr());
2035 sock->writeLine("");
2039 HTML html("",*sock);
2040 html.readTemplate(mem,sock,0);
2042 sock->write(mem.buf,fileLen);